-ed71446aaa2bd0e548c3bf2154a638826dfe3db0
+d517c0e6a10b548f44d82b71b3c079663cb94f8e
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
bool definitelyValueParameter(Expression *e);
Expression *semantic(Expression *e, Scope *sc);
+StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
/********************************* AttribDeclaration ****************************/
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;
}
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");
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;
}
}
#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,
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
unsigned Module::dprogress;
const char *lookForSourceFile(const char **path, const char *filename);
+StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
void Module::_init()
{
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.
*/
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)
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.
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.
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);
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
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)
if (f.read())
{
e->error("cannot read file %s", f.toChars());
- goto Lerror;
+ return setError();
}
else
{
}
}
result = semantic(se, sc);
- return;
-
- Lerror:
- return setError();
}
void visit(AssertExp *exp)
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)
{
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;
}
--- /dev/null
+deprecated([]) module imports.test19609a;
--- /dev/null
+deprecated(['h','e','l','l','o']) module imports.test19609b;
--- /dev/null
+deprecated(null) module imports.test19609c;
--- /dev/null
+// REQUIRED_ARGS: -o-
+/*
+TEST_OUTPUT:
+---
+---
+*/
+deprecated("a" ~ "b") module fail12567;
--- /dev/null
+// 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;
+++ /dev/null
-// REQUIRED_ARGS: -o-
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail12567.d(8): Error: string expected, not '"a" ~ "b"'
----
-*/
-deprecated("a" ~ "b") module fail12567;
--- /dev/null
+// 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;
--- /dev/null
+deprecated([""]) module imports.fail19609a;
--- /dev/null
+deprecated([1]) module imports.fail19609b;
--- /dev/null
+deprecated(123.4f) module imports.fail19609c;