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;
