Commit 8f5439be by Iain Buclaw

d/dmd: Merge upstream dmd d517c0e6a

Fixes https://gcc.gnu.org/PR89016

Reviewed-on: https://github.com/dlang/dmd/pull/9427

From-SVN: r269465
parent 59d9a0aa
ed71446aaa2bd0e548c3bf2154a638826dfe3db0 d517c0e6a10b548f44d82b71b3c079663cb94f8e
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository. merge done from the dlang/dmd repository.
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
bool definitelyValueParameter(Expression *e); bool definitelyValueParameter(Expression *e);
Expression *semantic(Expression *e, Scope *sc); Expression *semantic(Expression *e, Scope *sc);
StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
/********************************* AttribDeclaration ****************************/ /********************************* AttribDeclaration ****************************/
...@@ -977,41 +978,29 @@ void PragmaDeclaration::semantic(Scope *sc) ...@@ -977,41 +978,29 @@ void PragmaDeclaration::semantic(Scope *sc)
error("string expected for library name"); error("string expected for library name");
else else
{ {
Expression *e = (*args)[0]; StringExp *se = semanticString(sc, (*args)[0], "library name");
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();
if (!se) if (!se)
error("string expected for library name, not '%s'", e->toChars()); goto Lnodecl;
else (*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); OutBuffer *ob = global.params.moduleDeps;
memcpy(name, se->string, se->len); Module *imod = sc->instantiatingModule();
name[se->len] = 0; ob->writestring("depsLib ");
if (global.params.verbose) ob->writestring(imod->toPrettyChars());
message("library %s", name); ob->writestring(" (");
if (global.params.moduleDeps && !global.params.moduleDepsFile) escapePath(ob, imod->srcfile->toChars());
{ ob->writestring(") : ");
OutBuffer *ob = global.params.moduleDeps; ob->writestring((char *) name);
Module *imod = sc->instantiatingModule(); ob->writenl();
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);
} }
mem.xfree(name);
} }
goto Lnodecl; goto Lnodecl;
} }
...@@ -1053,19 +1042,11 @@ void PragmaDeclaration::semantic(Scope *sc) ...@@ -1053,19 +1042,11 @@ void PragmaDeclaration::semantic(Scope *sc)
goto Ldecl; goto Ldecl;
} }
Expression *e = (*args)[0]; StringExp *se = semanticString(sc, (*args)[0], "mangled name");
e = ::semantic(e, sc);
e = e->ctfeInterpret();
(*args)[0] = e;
if (e->op == TOKerror)
goto Ldecl;
StringExp *se = e->toStringExp();
if (!se) if (!se)
{
error("string expected for mangled name, not '%s'", e->toChars());
goto Ldecl; goto Ldecl;
} (*args)[0] = se; // Will be used for later
if (!se->len) if (!se->len)
{ {
error("zero-length string not allowed for mangled name"); error("zero-length string not allowed for mangled name");
...@@ -1418,35 +1399,22 @@ void CompileDeclaration::setScope(Scope *sc) ...@@ -1418,35 +1399,22 @@ void CompileDeclaration::setScope(Scope *sc)
void CompileDeclaration::compileIt(Scope *sc) void CompileDeclaration::compileIt(Scope *sc)
{ {
//printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars()); //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
sc = sc->startCTFE(); StringExp *se = semanticString(sc, exp, "argument to mixin");
exp = ::semantic(exp, sc); if (!se)
exp = resolveProperties(sc, exp); return;
sc = sc->endCTFE(); 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(); assert(global.errors != errors);
if (e->op == TOKerror) // Bugzilla 15974 decl = NULL;
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;
}
}
} }
} }
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "attrib.h" #include "attrib.h"
#include "hdrgen.h" #include "hdrgen.h"
StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
/********************************* Import ****************************/ /********************************* Import ****************************/
Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId, Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
...@@ -176,6 +178,8 @@ void Import::importAll(Scope *sc) ...@@ -176,6 +178,8 @@ void Import::importAll(Scope *sc)
if (mod->md && mod->md->isdeprecated) if (mod->md && mod->md->isdeprecated)
{ {
Expression *msg = mod->md->msg; Expression *msg = mod->md->msg;
if (msg)
msg = semanticString(sc, msg, "deprecation message");
if (StringExp *se = msg ? msg->toStringExp() : NULL) if (StringExp *se = msg ? msg->toStringExp() : NULL)
mod->deprecation(loc, "is deprecated - %s", se->string); mod->deprecation(loc, "is deprecated - %s", se->string);
else else
......
...@@ -35,6 +35,7 @@ Dsymbols Module::deferred3; // deferred Dsymbol's needing semantic3() run on the ...@@ -35,6 +35,7 @@ Dsymbols Module::deferred3; // deferred Dsymbol's needing semantic3() run on the
unsigned Module::dprogress; unsigned Module::dprogress;
const char *lookForSourceFile(const char **path, const char *filename); const char *lookForSourceFile(const char **path, const char *filename);
StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
void Module::_init() void Module::_init()
{ {
...@@ -727,14 +728,6 @@ void Module::importAll(Scope *) ...@@ -727,14 +728,6 @@ void Module::importAll(Scope *)
return; 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. /* Note that modules get their own scope, from scratch.
* This is so regardless of where in the syntax a module * This is so regardless of where in the syntax a module
* gets imported, it is unaffected by context. * gets imported, it is unaffected by context.
...@@ -742,6 +735,9 @@ void Module::importAll(Scope *) ...@@ -742,6 +735,9 @@ void Module::importAll(Scope *)
*/ */
Scope *sc = Scope::createGlobal(this); // create root 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. // Add import of "object", even for the "object" module.
// If it isn't there, some compiler rewrites, like // If it isn't there, some compiler rewrites, like
// classinst == classinst -> .object.opEquals(classinst, classinst) // classinst == classinst -> .object.opEquals(classinst, classinst)
......
...@@ -6850,6 +6850,43 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0) ...@@ -6850,6 +6850,43 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
return ae; 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 * Runs semantic on se->lwr and se->upr. Declares a temporary variable
* if '$' was used. * if '$' was used.
......
...@@ -74,6 +74,7 @@ Expression *binSemanticProp(BinExp *e, Scope *sc); ...@@ -74,6 +74,7 @@ Expression *binSemanticProp(BinExp *e, Scope *sc);
Expression *semantic(Expression *e, Scope *sc); Expression *semantic(Expression *e, Scope *sc);
Expression *semanticY(DotIdExp *exp, Scope *sc, int flag); Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
Expression *semanticY(DotTemplateInstanceExp *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. * Preprocess arguments to function.
...@@ -2259,27 +2260,9 @@ public: ...@@ -2259,27 +2260,9 @@ public:
void visit(CompileExp *exp) void visit(CompileExp *exp)
{ {
sc = sc->startCTFE(); StringExp *se = semanticString(sc, exp->e1, "argument to mixin");
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();
if (!se) if (!se)
{
exp->error("argument to mixin must be a string, not (%s)", exp->e1->toChars());
return setError(); return setError();
}
se = se->toUTF8(sc); se = se->toUTF8(sc);
unsigned errors = global.errors; unsigned errors = global.errors;
Parser p(exp->loc, sc->_module, (utf8_t *)se->string, se->len, 0); Parser p(exp->loc, sc->_module, (utf8_t *)se->string, se->len, 0);
...@@ -2301,27 +2284,16 @@ public: ...@@ -2301,27 +2284,16 @@ public:
void visit(ImportExp *e) void visit(ImportExp *e)
{ {
const char *name; StringExp *se = semanticString(sc, e->e1, "file name argument");
StringExp *se; if (!se)
return setError();
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;
se = se->toUTF8(sc); se = se->toUTF8(sc);
name = (char *)se->string;
const char *name = (char *)se->string;
if (!global.params.fileImppath) if (!global.params.fileImppath)
{ {
e->error("need -Jpath switch to import text file %s", name); 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 /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
...@@ -2333,7 +2305,7 @@ public: ...@@ -2333,7 +2305,7 @@ public:
if (!name) if (!name)
{ {
e->error("file %s cannot be found or not in a path specified with -J", se->toChars()); 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) if (global.params.verbose)
...@@ -2363,7 +2335,7 @@ public: ...@@ -2363,7 +2335,7 @@ public:
if (f.read()) if (f.read())
{ {
e->error("cannot read file %s", f.toChars()); e->error("cannot read file %s", f.toChars());
goto Lerror; return setError();
} }
else else
{ {
...@@ -2372,10 +2344,6 @@ public: ...@@ -2372,10 +2344,6 @@ public:
} }
} }
result = semantic(se, sc); result = semantic(se, sc);
return;
Lerror:
return setError();
} }
void visit(AssertExp *exp) void visit(AssertExp *exp)
......
...@@ -31,6 +31,7 @@ StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f); ...@@ -31,6 +31,7 @@ StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
bool checkEscapeRef(Scope *sc, Expression *e, bool gag); bool checkEscapeRef(Scope *sc, Expression *e, bool gag);
VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e); VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
Expression *semantic(Expression *e, Scope *sc); Expression *semantic(Expression *e, Scope *sc);
StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
Identifier *fixupLabelName(Scope *sc, Identifier *ident) Identifier *fixupLabelName(Scope *sc, Identifier *ident)
{ {
...@@ -487,45 +488,36 @@ Statement *CompileStatement::syntaxCopy() ...@@ -487,45 +488,36 @@ Statement *CompileStatement::syntaxCopy()
return new CompileStatement(loc, exp->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) Statements *CompileStatement::flatten(Scope *sc)
{ {
//printf("CompileStatement::flatten() %s\n", exp->toChars()); //printf("CompileStatement::flatten() %s\n", exp->toChars());
sc = sc->startCTFE(); StringExp *se = semanticString(sc, exp, "argument to mixin");
exp = semantic(exp, sc); if (!se)
exp = resolveProperties(sc, exp); return errorStatements();
sc = sc->endCTFE(); 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(); Statements *a = new Statements();
if (exp->op != TOKerror) while (p.token.value != TOKeof)
{ {
Expression *e = exp->ctfeInterpret(); Statement *s = p.parseStatement(PSsemi | PScurlyscope);
if (e->op == TOKerror) // Bugzilla 15974 if (!s || p.errors)
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
{ {
se = se->toUTF8(sc); assert(!p.errors || global.errors != errors); // make sure we caught all the cases
unsigned errors = global.errors; return errorStatements();
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;
} }
a->push(s);
} }
Lerror:
a->push(new ErrorStatement());
return a; return a;
} }
......
deprecated([]) module imports.test19609a;
deprecated(['h','e','l','l','o']) module imports.test19609b;
deprecated(null) module imports.test19609c;
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail12567.d(8): Error: string expected, not '"a" ~ "b"'
--- ---
*/ */
deprecated("a" ~ "b") module fail12567; deprecated("a" ~ "b") module fail12567;
// 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;
// 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;
deprecated([""]) module imports.fail19609a;
deprecated([1]) module imports.fail19609b;
deprecated(123.4f) module imports.fail19609c;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment