From patchwork Thu Mar 7 16:57:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1053069 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-497511-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gdcproject.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="KxrTA8Qn"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44FcJh67Pjz9sDn for ; Fri, 8 Mar 2019 03:58:07 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=JkKviPLAYOB9bUvnMdpdyPops70neK10uHjlEt+zlM9SGZ odcEmpvuTSDNxFEi1nqaaoXn+CttjXaTJdkMOB21Y9Hf8L3eKiJistEThSJC0syA uX9CprT1PtFUitKOjRltXKKEPvRu4olD6Cfe97J+KHVCPBZDqcw4FSDH7gc40= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=ihN+YM7Qr2LflnSEjCfXfZU1Ra4=; b=KxrTA8QnD3fKu5ikSdts xuvSv6WnawUL+s7NnxbJMeggskZmcI+sxK/gFh9r7gvUH9TgehFZwAfS8F5Sg5kY dfctjvTv9R0BkMrQBb/GD3QSMF4BBzdlxDpw3PDZwn2YeAchzxYrVjSwLoSO4cJ7 OrxS3GaV3AV2FoLK+pMmRWM= Received: (qmail 36578 invoked by alias); 7 Mar 2019 16:57:59 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 36570 invoked by uid 89); 7 Mar 2019 16:57:58 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-14.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=msg, improper, Iain, se X-HELO: mail-qk1-f175.google.com Received: from mail-qk1-f175.google.com (HELO mail-qk1-f175.google.com) (209.85.222.175) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 07 Mar 2019 16:57:55 +0000 Received: by mail-qk1-f175.google.com with SMTP id x9so9453603qkf.0 for ; Thu, 07 Mar 2019 08:57:55 -0800 (PST) MIME-Version: 1.0 From: Iain Buclaw Date: Thu, 7 Mar 2019 17:57:42 +0100 Message-ID: Subject: [PATCH, PR d/89016] Committed fix for ICE at d/dmd/expression.c:3873 To: gcc-patches X-IsSubscribed: yes Hi, This patch merges the D front-end implementation with dmd upstream d517c0e6a, fixing the ICE reported in PR d/89016. Bootstrapped and regression tested on x86_64-linux-gnu. Committed to trunk as r269465. diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 97aa40d1ace..3f416dbfb7b 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -ed71446aaa2bd0e548c3bf2154a638826dfe3db0 +d517c0e6a10b548f44d82b71b3c079663cb94f8e The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/attrib.c b/gcc/d/dmd/attrib.c index e4ad5739e73..a6686381485 100644 --- a/gcc/d/dmd/attrib.c +++ b/gcc/d/dmd/attrib.c @@ -30,6 +30,7 @@ bool definitelyValueParameter(Expression *e); Expression *semantic(Expression *e, Scope *sc); +StringExp *semanticString(Scope *sc, Expression *exp, const char *s); /********************************* AttribDeclaration ****************************/ @@ -977,41 +978,29 @@ void PragmaDeclaration::semantic(Scope *sc) error("string expected for library name"); else { - Expression *e = (*args)[0]; - - sc = sc->startCTFE(); - e = ::semantic(e, sc); - e = resolveProperties(sc, e); - sc = sc->endCTFE(); - - e = e->ctfeInterpret(); - (*args)[0] = e; - if (e->op == TOKerror) - goto Lnodecl; - StringExp *se = e->toStringExp(); + StringExp *se = semanticString(sc, (*args)[0], "library name"); if (!se) - error("string expected for library name, not '%s'", e->toChars()); - else + goto Lnodecl; + (*args)[0] = se; + + char *name = (char *)mem.xmalloc(se->len + 1); + memcpy(name, se->string, se->len); + name[se->len] = 0; + if (global.params.verbose) + message("library %s", name); + if (global.params.moduleDeps && !global.params.moduleDepsFile) { - char *name = (char *)mem.xmalloc(se->len + 1); - memcpy(name, se->string, se->len); - name[se->len] = 0; - if (global.params.verbose) - message("library %s", name); - if (global.params.moduleDeps && !global.params.moduleDepsFile) - { - OutBuffer *ob = global.params.moduleDeps; - Module *imod = sc->instantiatingModule(); - ob->writestring("depsLib "); - ob->writestring(imod->toPrettyChars()); - ob->writestring(" ("); - escapePath(ob, imod->srcfile->toChars()); - ob->writestring(") : "); - ob->writestring((char *) name); - ob->writenl(); - } - mem.xfree(name); + OutBuffer *ob = global.params.moduleDeps; + Module *imod = sc->instantiatingModule(); + ob->writestring("depsLib "); + ob->writestring(imod->toPrettyChars()); + ob->writestring(" ("); + escapePath(ob, imod->srcfile->toChars()); + ob->writestring(") : "); + ob->writestring((char *) name); + ob->writenl(); } + mem.xfree(name); } goto Lnodecl; } @@ -1053,19 +1042,11 @@ void PragmaDeclaration::semantic(Scope *sc) goto Ldecl; } - Expression *e = (*args)[0]; - e = ::semantic(e, sc); - e = e->ctfeInterpret(); - (*args)[0] = e; - if (e->op == TOKerror) - goto Ldecl; - - StringExp *se = e->toStringExp(); + StringExp *se = semanticString(sc, (*args)[0], "mangled name"); if (!se) - { - error("string expected for mangled name, not '%s'", e->toChars()); goto Ldecl; - } + (*args)[0] = se; // Will be used for later + if (!se->len) { error("zero-length string not allowed for mangled name"); @@ -1418,35 +1399,22 @@ void CompileDeclaration::setScope(Scope *sc) void CompileDeclaration::compileIt(Scope *sc) { //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars()); - sc = sc->startCTFE(); - exp = ::semantic(exp, sc); - exp = resolveProperties(sc, exp); - sc = sc->endCTFE(); + StringExp *se = semanticString(sc, exp, "argument to mixin"); + if (!se) + return; + se = se->toUTF8(sc); + + unsigned errors = global.errors; + Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0); + p.nextToken(); - if (exp->op != TOKerror) + decl = p.parseDeclDefs(0); + if (p.token.value != TOKeof) + exp->error("incomplete mixin declaration (%s)", se->toChars()); + if (p.errors) { - Expression *e = exp->ctfeInterpret(); - if (e->op == TOKerror) // Bugzilla 15974 - return; - StringExp *se = e->toStringExp(); - if (!se) - exp->error("argument to mixin must be a string, not (%s) of type %s", exp->toChars(), exp->type->toChars()); - else - { - se = se->toUTF8(sc); - unsigned errors = global.errors; - Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0); - p.nextToken(); - - decl = p.parseDeclDefs(0); - if (p.token.value != TOKeof) - exp->error("incomplete mixin declaration (%s)", se->toChars()); - if (p.errors) - { - assert(global.errors != errors); - decl = NULL; - } - } + assert(global.errors != errors); + decl = NULL; } } diff --git a/gcc/d/dmd/dimport.c b/gcc/d/dmd/dimport.c index ad1e2d0463c..cd2c5b22a74 100644 --- a/gcc/d/dmd/dimport.c +++ b/gcc/d/dmd/dimport.c @@ -23,6 +23,8 @@ #include "attrib.h" #include "hdrgen.h" +StringExp *semanticString(Scope *sc, Expression *exp, const char *s); + /********************************* Import ****************************/ Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId, @@ -176,6 +178,8 @@ void Import::importAll(Scope *sc) if (mod->md && mod->md->isdeprecated) { Expression *msg = mod->md->msg; + if (msg) + msg = semanticString(sc, msg, "deprecation message"); if (StringExp *se = msg ? msg->toStringExp() : NULL) mod->deprecation(loc, "is deprecated - %s", se->string); else diff --git a/gcc/d/dmd/dmodule.c b/gcc/d/dmd/dmodule.c index 3b74446c9f5..20dbb69a91c 100644 --- a/gcc/d/dmd/dmodule.c +++ b/gcc/d/dmd/dmodule.c @@ -35,6 +35,7 @@ Dsymbols Module::deferred3; // deferred Dsymbol's needing semantic3() run on the unsigned Module::dprogress; const char *lookForSourceFile(const char **path, const char *filename); +StringExp *semanticString(Scope *sc, Expression *exp, const char *s); void Module::_init() { @@ -727,14 +728,6 @@ void Module::importAll(Scope *) return; } - if (md && md->msg) - { - if (StringExp *se = md->msg->toStringExp()) - md->msg = se; - else - md->msg->error("string expected, not '%s'", md->msg->toChars()); - } - /* Note that modules get their own scope, from scratch. * This is so regardless of where in the syntax a module * gets imported, it is unaffected by context. @@ -742,6 +735,9 @@ void Module::importAll(Scope *) */ Scope *sc = Scope::createGlobal(this); // create root scope + if (md && md->msg) + md->msg = semanticString(sc, md->msg, "deprecation message"); + // Add import of "object", even for the "object" module. // If it isn't there, some compiler rewrites, like // classinst == classinst -> .object.opEquals(classinst, classinst) diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c index cbc38195cca..df373925e09 100644 --- a/gcc/d/dmd/expression.c +++ b/gcc/d/dmd/expression.c @@ -6850,6 +6850,43 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0) return ae; } +/*********************************************************** + * Resolve `exp` as a compile-time known string. + * Params: + * sc = scope + * exp = Expression which expected as a string + * s = What the string is expected for, will be used in error diagnostic. + * Returns: + * String literal, or `null` if error happens. + */ +StringExp *semanticString(Scope *sc, Expression *exp, const char *s) +{ + sc = sc->startCTFE(); + exp = semantic(exp, sc); + exp = resolveProperties(sc, exp); + sc = sc->endCTFE(); + + if (exp->op == TOKerror) + return NULL; + + Expression *e = exp; + if (exp->type->isString()) + { + e = e->ctfeInterpret(); + if (e->op == TOKerror) + return NULL; + } + + StringExp *se = e->toStringExp(); + if (!se) + { + exp->error("string expected for %s, not (%s) of type %s", + s, exp->toChars(), exp->type->toChars()); + return NULL; + } + return se; +} + /************************************** * Runs semantic on se->lwr and se->upr. Declares a temporary variable * if '$' was used. diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c index d5319e55a6e..3fd5c1fa33f 100644 --- a/gcc/d/dmd/expressionsem.c +++ b/gcc/d/dmd/expressionsem.c @@ -74,6 +74,7 @@ Expression *binSemanticProp(BinExp *e, Scope *sc); Expression *semantic(Expression *e, Scope *sc); Expression *semanticY(DotIdExp *exp, Scope *sc, int flag); Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag); +StringExp *semanticString(Scope *sc, Expression *exp, const char *s); /**************************************** * Preprocess arguments to function. @@ -2259,27 +2260,9 @@ public: void visit(CompileExp *exp) { - sc = sc->startCTFE(); - exp->e1 = semantic(exp->e1, sc); - exp->e1 = resolveProperties(sc, exp->e1); - sc = sc->endCTFE(); - if (exp->e1->op == TOKerror) - { - result = exp->e1; - return; - } - if (!exp->e1->type->isString()) - { - exp->error("argument to mixin must be a string type, not %s", exp->e1->type->toChars()); - return setError(); - } - exp->e1 = exp->e1->ctfeInterpret(); - StringExp *se = exp->e1->toStringExp(); + StringExp *se = semanticString(sc, exp->e1, "argument to mixin"); if (!se) - { - exp->error("argument to mixin must be a string, not (%s)", exp->e1->toChars()); return setError(); - } se = se->toUTF8(sc); unsigned errors = global.errors; Parser p(exp->loc, sc->_module, (utf8_t *)se->string, se->len, 0); @@ -2301,27 +2284,16 @@ public: void visit(ImportExp *e) { - const char *name; - StringExp *se; - - sc = sc->startCTFE(); - e->e1 = semantic(e->e1, sc); - e->e1 = resolveProperties(sc, e->e1); - sc = sc->endCTFE(); - e->e1 = e->e1->ctfeInterpret(); - if (e->e1->op != TOKstring) - { - e->error("file name argument must be a string, not (%s)", e->e1->toChars()); - goto Lerror; - } - se = (StringExp *)e->e1; + StringExp *se = semanticString(sc, e->e1, "file name argument"); + if (!se) + return setError(); se = se->toUTF8(sc); - name = (char *)se->string; + const char *name = (char *)se->string; if (!global.params.fileImppath) { e->error("need -Jpath switch to import text file %s", name); - goto Lerror; + return setError(); } /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory @@ -2333,7 +2305,7 @@ public: if (!name) { e->error("file %s cannot be found or not in a path specified with -J", se->toChars()); - goto Lerror; + return setError(); } if (global.params.verbose) @@ -2363,7 +2335,7 @@ public: if (f.read()) { e->error("cannot read file %s", f.toChars()); - goto Lerror; + return setError(); } else { @@ -2372,10 +2344,6 @@ public: } } result = semantic(se, sc); - return; - - Lerror: - return setError(); } void visit(AssertExp *exp) diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c index 95bb77268a5..2d3a11237cb 100644 --- a/gcc/d/dmd/statement.c +++ b/gcc/d/dmd/statement.c @@ -31,6 +31,7 @@ StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f); bool checkEscapeRef(Scope *sc, Expression *e, bool gag); VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e); Expression *semantic(Expression *e, Scope *sc); +StringExp *semanticString(Scope *sc, Expression *exp, const char *s); Identifier *fixupLabelName(Scope *sc, Identifier *ident) { @@ -487,45 +488,36 @@ Statement *CompileStatement::syntaxCopy() return new CompileStatement(loc, exp->syntaxCopy()); } +static Statements *errorStatements() +{ + Statements *a = new Statements(); + a->push(new ErrorStatement()); + return a; +} + Statements *CompileStatement::flatten(Scope *sc) { //printf("CompileStatement::flatten() %s\n", exp->toChars()); - sc = sc->startCTFE(); - exp = semantic(exp, sc); - exp = resolveProperties(sc, exp); - sc = sc->endCTFE(); + StringExp *se = semanticString(sc, exp, "argument to mixin"); + if (!se) + return errorStatements(); + se = se->toUTF8(sc); + + unsigned errors = global.errors; + Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0); + p.nextToken(); Statements *a = new Statements(); - if (exp->op != TOKerror) + while (p.token.value != TOKeof) { - Expression *e = exp->ctfeInterpret(); - if (e->op == TOKerror) // Bugzilla 15974 - goto Lerror; - StringExp *se = e->toStringExp(); - if (!se) - error("argument to mixin must be a string, not (%s) of type %s", exp->toChars(), exp->type->toChars()); - else + Statement *s = p.parseStatement(PSsemi | PScurlyscope); + if (!s || p.errors) { - se = se->toUTF8(sc); - unsigned errors = global.errors; - Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0); - p.nextToken(); - - while (p.token.value != TOKeof) - { - Statement *s = p.parseStatement(PSsemi | PScurlyscope); - if (!s || p.errors) - { - assert(!p.errors || global.errors != errors); // make sure we caught all the cases - goto Lerror; - } - a->push(s); - } - return a; + assert(!p.errors || global.errors != errors); // make sure we caught all the cases + return errorStatements(); } + a->push(s); } -Lerror: - a->push(new ErrorStatement()); return a; } diff --git a/gcc/testsuite/gdc.test/compilable/imports/test19609a.d b/gcc/testsuite/gdc.test/compilable/imports/test19609a.d new file mode 100644 index 00000000000..53d4f887027 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/test19609a.d @@ -0,0 +1 @@ +deprecated([]) module imports.test19609a; diff --git a/gcc/testsuite/gdc.test/compilable/imports/test19609b.d b/gcc/testsuite/gdc.test/compilable/imports/test19609b.d new file mode 100644 index 00000000000..91e26e2862b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/test19609b.d @@ -0,0 +1 @@ +deprecated(['h','e','l','l','o']) module imports.test19609b; diff --git a/gcc/testsuite/gdc.test/compilable/imports/test19609c.d b/gcc/testsuite/gdc.test/compilable/imports/test19609c.d new file mode 100644 index 00000000000..789585d6c88 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/test19609c.d @@ -0,0 +1 @@ +deprecated(null) module imports.test19609c; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12567.d b/gcc/testsuite/gdc.test/compilable/test12567e.d similarity index 54% rename from gcc/testsuite/gdc.test/fail_compilation/fail12567.d rename to gcc/testsuite/gdc.test/compilable/test12567e.d index e1ecd19fee1..14c72bc5afb 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail12567.d +++ b/gcc/testsuite/gdc.test/compilable/test12567e.d @@ -2,7 +2,6 @@ /* TEST_OUTPUT: --- -fail_compilation/fail12567.d(8): Error: string expected, not '"a" ~ "b"' --- */ deprecated("a" ~ "b") module fail12567; diff --git a/gcc/testsuite/gdc.test/compilable/test19609.d b/gcc/testsuite/gdc.test/compilable/test19609.d new file mode 100644 index 00000000000..a3d69233249 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test19609.d @@ -0,0 +1,12 @@ +// https://issues.dlang.org/show_bug.cgi?id=19609 +/* +TEST_OUTPUT +--- +compilable/test19609.d(10): Deprecation: module `imports.test19609a` is deprecated - +compilable/test19609.d(11): Deprecation: module `imports.test19609b` is deprecated - hello +compilable/test19609.d(12): Deprecation: module `imports.test19609c` is deprecated - +--- +*/ +import imports.test19609a; +import imports.test19609b; +import imports.test19609c; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19609.d b/gcc/testsuite/gdc.test/fail_compilation/fail19609.d new file mode 100644 index 00000000000..64d080ac5d0 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19609.d @@ -0,0 +1,18 @@ +// https://issues.dlang.org/show_bug.cgi?id=19609 +/* +TEST_OUTPUT +--- +fail_compilation/imports/fail19609a.d(1): Error: `string` expected for deprecation message, not `([""])` of type `string[]` +fail_compilation/fail19609.d(16): Deprecation: module `imports.fail19609a` is deprecated +fail_compilation/imports/fail19609a.d(1): Error: `string` expected for deprecation message, not `([""])` of type `string[]` +fail_compilation/imports/fail19609b.d(1): Error: `string` expected for deprecation message, not `([1])` of type `int[]` +fail_compilation/fail19609.d(17): Deprecation: module `imports.fail19609b` is deprecated +fail_compilation/imports/fail19609b.d(1): Error: `string` expected for deprecation message, not `([1])` of type `int[]` +fail_compilation/imports/fail19609c.d(1): Error: `string` expected for deprecation message, not `(123.4F)` of type `float` +fail_compilation/fail19609.d(18): Deprecation: module `imports.fail19609c` is deprecated +fail_compilation/imports/fail19609c.d(1): Error: `string` expected for deprecation message, not `(123.4F)` of type `float` +--- +*/ +import imports.fail19609a; +import imports.fail19609b; +import imports.fail19609c; diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609a.d b/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609a.d new file mode 100644 index 00000000000..6cf5d61c063 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609a.d @@ -0,0 +1 @@ +deprecated([""]) module imports.fail19609a; diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609b.d b/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609b.d new file mode 100644 index 00000000000..2ba62fe7e6f --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609b.d @@ -0,0 +1 @@ +deprecated([1]) module imports.fail19609b; diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609c.d b/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609c.d new file mode 100644 index 00000000000..4aadb600fa8 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/fail19609c.d @@ -0,0 +1 @@ +deprecated(123.4f) module imports.fail19609c;