public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, d] Committed merge with upstream dmd
@ 2018-12-02 11:48 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2018-12-02 11:48 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 716 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream 5220ad51e.

Backports Ddoc fix that is present in upstream, but did not make its
way into the C++ port of the D front-end implementation.

The old special types for C long, unsigned long, and long double have
also been removed as neither the compiler nor druntime bindings
support handling it anymore.

Commits merged from dmd.

        Backport Issue 14633: Fixed false DDoc warnings
        https://github.com/dlang/dmd/pull/9027

        Remove old support code for struct __c_long/ulong/long_double
        https://github.com/dlang/dmd/pull/9028


Bootstrapped and tested on x86_64-linux-gnu.

Committed to trunk as r266719.

-- 
Iain

---

[-- Attachment #2: dmd5220ad51e.patch --]
[-- Type: text/x-patch, Size: 9137 bytes --]

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 7727205bed4..223ffbdc358 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-6243fa6d2ceab4615a9fe21c5bc9484e52bb2d1e
+5220ad51eebe06754e6881d9bd5aab89dba2b065
 
 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/cppmangle.c b/gcc/d/dmd/cppmangle.c
index d2d357667cb..ad88242d820 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -952,15 +952,6 @@ public:
         if (t->isImmutable() || t->isShared())
             return error(t);
 
-        /* __c_long and __c_ulong get special mangling
-         */
-        Identifier *id = t->sym->ident;
-        //printf("struct id = '%s'\n", id->toChars());
-        if (id == Id::__c_long)
-            return writeBasicType(t, 0, 'l');
-        else if (id == Id::__c_ulong)
-            return writeBasicType(t, 0, 'm');
-
         //printf("TypeStruct %s\n", t->toChars());
         doSymbol(t);
     }
diff --git a/gcc/d/dmd/doc.c b/gcc/d/dmd/doc.c
index d35ca7b2522..797991ee2c4 100644
--- a/gcc/d/dmd/doc.c
+++ b/gcc/d/dmd/doc.c
@@ -133,6 +133,25 @@ bool isCVariadicParameter(Dsymbols *a, const utf8_t *p, size_t len)
     return false;
 }
 
+/****************************************************
+ */
+static Parameter *isFunctionParameter(Dsymbol *s, const utf8_t *p, size_t len)
+{
+    TypeFunction *tf = isTypeFunction(s);
+    if (tf && tf->parameters)
+    {
+        for (size_t k = 0; k < tf->parameters->dim; k++)
+        {
+            Parameter *fparam = (*tf->parameters)[k];
+            if (fparam->ident && cmp(fparam->ident->toChars(), p, len) == 0)
+            {
+                return fparam;
+            }
+        }
+    }
+    return NULL;
+}
+
 static Dsymbol *getEponymousMember(TemplateDeclaration *td)
 {
     if (!td->onemember)
@@ -150,6 +169,54 @@ static Dsymbol *getEponymousMember(TemplateDeclaration *td)
     return NULL;
 }
 
+/****************************************************
+ */
+static Parameter *isEponymousFunctionParameter(Dsymbols *a, const utf8_t *p, size_t len)
+{
+    for (size_t i = 0; i < a->dim; i++)
+    {
+        TemplateDeclaration *td = (*a)[i]->isTemplateDeclaration();
+        if (td && td->onemember)
+        {
+            /* Case 1: we refer to a template declaration inside the template
+
+               /// ...ddoc...
+               template case1(T) {
+                 void case1(R)() {}
+               }
+             */
+            td = td->onemember->isTemplateDeclaration();
+        }
+        if (!td)
+        {
+            /* Case 2: we're an alias to a template declaration
+
+               /// ...ddoc...
+               alias case2 = case1!int;
+             */
+            AliasDeclaration *ad = (*a)[i]->isAliasDeclaration();
+            if (ad && ad->aliassym)
+            {
+                td = ad->aliassym->isTemplateDeclaration();
+            }
+        }
+        while (td)
+        {
+            Dsymbol *sym = getEponymousMember(td);
+            if (sym)
+            {
+                Parameter *fparam = isFunctionParameter(sym, p, len);
+                if (fparam)
+                {
+                    return fparam;
+                }
+            }
+            td = td->overnext;
+        }
+    }
+    return NULL;
+}
+
 static TemplateDeclaration *getEponymousParent(Dsymbol *s)
 {
     if (!s->parent)
@@ -1590,6 +1657,12 @@ void ParamSection::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffe
                 {
                     size_t o = buf->offset;
                     Parameter *fparam = isFunctionParameter(a, namestart, namelen);
+                    if (!fparam)
+                    {
+                        // Comments on a template might refer to function parameters within.
+                        // Search the parameters of nested eponymous functions (with the same name.)
+                        fparam = isEponymousFunctionParameter(a, namestart, namelen);
+                    }
                     bool isCVariadic = isCVariadicParameter(a, namestart, namelen);
                     if (isCVariadic)
                     {
@@ -2085,17 +2158,10 @@ Parameter *isFunctionParameter(Dsymbols *a, const utf8_t *p, size_t len)
 {
     for (size_t i = 0; i < a->dim; i++)
     {
-        TypeFunction *tf = isTypeFunction((*a)[i]);
-        if (tf && tf->parameters)
+        Parameter *fparam = isFunctionParameter((*a)[i], p, len);
+        if (fparam)
         {
-            for (size_t k = 0; k < tf->parameters->dim; k++)
-            {
-                Parameter *fparam = (*tf->parameters)[k];
-                if (fparam->ident && cmp(fparam->ident->toChars(), p, len) == 0)
-                {
-                    return fparam;
-                }
-            }
+            return fparam;
         }
     }
     return NULL;
@@ -2108,7 +2174,10 @@ TemplateParameter *isTemplateParameter(Dsymbols *a, const utf8_t *p, size_t len)
 {
     for (size_t i = 0; i < a->dim; i++)
     {
-        TemplateDeclaration *td = getEponymousParent((*a)[i]);
+        TemplateDeclaration *td = (*a)[i]->isTemplateDeclaration();
+        // Check for the parent, if the current symbol is not a template declaration.
+        if (!td)
+            td = getEponymousParent((*a)[i]);
         if (td && td->origParameters)
         {
             for (size_t k = 0; k < td->origParameters->dim; k++)
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc10236.d b/gcc/testsuite/gdc.test/compilable/ddoc10236.d
index 25738ec34e3..1c547613c44 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc10236.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc10236.d
@@ -1,5 +1,5 @@
 // PERMUTE_ARGS:
-// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -w -o-
+// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o-
 
 /*
 TEST_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc10236b.d b/gcc/testsuite/gdc.test/compilable/ddoc10236b.d
index d814d375c06..065ced0936c 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc10236b.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc10236b.d
@@ -1,5 +1,5 @@
 // PERMUTE_ARGS:
-// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -w -o-
+// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o-
 
 /*
 TEST_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc13502.d b/gcc/testsuite/gdc.test/compilable/ddoc13502.d
index 6ab2ca0614d..93f383fea9f 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc13502.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc13502.d
@@ -1,5 +1,5 @@
 // PERMUTE_ARGS:
-// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -w -o-
+// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o-
 /*
 TEST_OUTPUT:
 ---
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc4899.d b/gcc/testsuite/gdc.test/compilable/ddoc4899.d
index 1fbd6a9cbe8..b5cfa86367c 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc4899.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc4899.d
@@ -1,5 +1,5 @@
 // PERMUTE_ARGS:
-// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -w -o-
+// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o-
 
 /*
 TEST_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/runnable/cppa.d b/gcc/testsuite/gdc.test/runnable/cppa.d
index 3b283427951..82b93adf1f6 100644
--- a/gcc/testsuite/gdc.test/runnable/cppa.d
+++ b/gcc/testsuite/gdc.test/runnable/cppa.d
@@ -612,13 +612,7 @@ extern(C++)
 
 version (CRuntime_Microsoft)
 {
-    struct __c_long_double
-    {
-        this(double d) { ld = d; }
-        double ld;
-        alias ld this;
-    }
-
+    enum __c_long_double : double;
     alias __c_long_double myld;
 }
 else
@@ -655,20 +649,8 @@ else
   }
 }
 
-struct __c_long
-{
-    this(x_long d) { ld = d; }
-    x_long ld;
-    alias ld this;
-}
-
-struct __c_ulong
-{
-    this(x_ulong d) { ld = d; }
-    x_ulong ld;
-    alias ld this;
-}
-
+enum __c_long : x_long;
+enum __c_ulong : x_ulong;
 alias __c_long mylong;
 alias __c_ulong myulong;
 
@@ -688,6 +670,43 @@ void test16()
     ld = testul(ld);
     assert(ld == 5 + myulong.sizeof);
   }
+
+  static if (__c_long.sizeof == long.sizeof)
+  {
+    static assert(__c_long.max == long.max);
+    static assert(__c_long.min == long.min);
+    static assert(__c_long.init == long.init);
+    static assert(__c_ulong.max == ulong.max);
+    static assert(__c_ulong.min == ulong.min);
+    static assert(__c_ulong.init == ulong.init);
+    __c_long cl = 0;
+    cl = cl + 1;
+    long l = cl;
+    cl = l;
+    __c_ulong cul = 0;
+    cul = cul + 1;
+    ulong ul = cul;
+    cul = ul;
+  }
+  else static if (__c_long.sizeof == int.sizeof)
+  {
+    static assert(__c_long.max == int.max);
+    static assert(__c_long.min == int.min);
+    static assert(__c_long.init == int.init);
+    static assert(__c_ulong.max == uint.max);
+    static assert(__c_ulong.min == uint.min);
+    static assert(__c_ulong.init == uint.init);
+    __c_long cl = 0;
+    cl = cl + 1;
+    int i = cl;
+    cl = i;
+    __c_ulong cul = 0;
+    cul = cul + 1;
+    uint u = cul;
+    cul = u;
+  }
+  else
+    static assert(0);
 }
 
 /****************************************/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH d]: Committed merge with upstream dmd
@ 2020-03-16  9:54 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2020-03-16  9:54 UTC (permalink / raw)
  To: gcc-patches

Hi,

This patch merges the D front-end implementation with upstream dmd 
b061bd744.

Fixes an ICE in the parser, and deprecates a previously allowed style of
syntax that deviated from GNU-style extended asm.

Bootstrapped and tested on x86_64-linux-gnu, and committed to trunk.

Regards
Iain.

---
gcc/testsuite/ChangeLog:

2020-03-16  Iain Buclaw  <ibuclaw@gdcproject.org>

	* gdc.dg/asm1.d: Add new test for ICE in asm parser.
	* gdc.dg/asm5.d: New test.

---
 gcc/d/dmd/MERGE             |  2 +-
 gcc/d/dmd/iasmgcc.c         | 30 +++++++++++++++++++++++++++---
 gcc/testsuite/ChangeLog     |  5 +++++
 gcc/testsuite/gdc.dg/asm1.d |  9 +++++++++
 gcc/testsuite/gdc.dg/asm5.d | 12 ++++++++++++
 5 files changed, 54 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/asm5.d

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index b017c037d74..6cbc4e37819 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-e9420cfbf5cd0cf9e6e398603e009ccc8e14d324
+b061bd744cb4eb94a7118581387d988d4ec25e97
 
 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/iasmgcc.c b/gcc/d/dmd/iasmgcc.c
index cecbdefe41a..548453321db 100644
--- a/gcc/d/dmd/iasmgcc.c
+++ b/gcc/d/dmd/iasmgcc.c
@@ -13,6 +13,7 @@
 
 #include "scope.h"
 #include "declaration.h"
+#include "errors.h"
 #include "parse.h"
 #include "statement.h"
 
@@ -23,8 +24,8 @@ Statement *semantic(Statement *s, Scope *sc);
  * Parse list of extended asm input or output operands.
  * Grammar:
  *      | Operands:
- *      |     SymbolicName(opt) StringLiteral AssignExpression
- *      |     SymbolicName(opt) StringLiteral AssignExpression , Operands
+ *      |     SymbolicName(opt) StringLiteral ( AssignExpression )
+ *      |     SymbolicName(opt) StringLiteral ( AssignExpression ), Operands
  *      |
  *      | SymbolicName:
  *      |     [ Identifier ]
@@ -54,7 +55,9 @@ static int parseExtAsmOperands(Parser *p, GccAsmStatement *s)
             case TOKlbracket:
                 if (p->peekNext() == TOKidentifier)
                 {
+                    // Skip over openings `[`
                     p->nextToken();
+                    // Store the symbolic name
                     name = p->token.ident;
                     p->nextToken();
                 }
@@ -63,12 +66,32 @@ static int parseExtAsmOperands(Parser *p, GccAsmStatement *s)
                     p->error(s->loc, "expected identifier after `[`");
                     goto Lerror;
                 }
+                // Look for closing `]`
                 p->check(TOKrbracket);
+                // Look for the string literal and fall through
+                if (p->token.value != TOKstring)
+                    goto Ldefault;
                 // fall through
 
             case TOKstring:
                 constraint = p->parsePrimaryExp();
-                arg = p->parseAssignExp();
+                // @@@DEPRECATED@@@
+                // Old parser allowed omitting parentheses around the expression.
+                // Deprecated in 2.091. Can be made permanent error after 2.100
+                if (p->token.value != TOKlparen)
+                {
+                    arg = p->parseAssignExp();
+                    deprecation(arg->loc, "`%s` must be surrounded by parentheses", arg->toChars());
+                }
+                else
+                {
+                    // Look for the opening `(`
+                    p->check(TOKlparen);
+                    // Parse the assign expression
+                    arg = p->parseAssignExp();
+                    // Look for the closing `)`
+                    p->check(TOKrparen);
+                }
 
                 if (!s->args)
                 {
@@ -86,6 +109,7 @@ static int parseExtAsmOperands(Parser *p, GccAsmStatement *s)
                 break;
 
             default:
+            Ldefault:
                 p->error("expected constant string constraint for operand, not `%s`",
                         p->token.toChars());
                 goto Lerror;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ab0406656d2..32a51b96a0e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-03-16  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+	* gdc.dg/asm1.d: Add new test for ICE in asm parser.
+	* gdc.dg/asm5.d: New test.
+
 2020-03-16  Bin Cheng  <bin.cheng@linux.alibaba.com>
 
 	PR tree-optimization/94125
diff --git a/gcc/testsuite/gdc.dg/asm1.d b/gcc/testsuite/gdc.dg/asm1.d
index 7b00e4d54ec..3fcfd6a58c1 100644
--- a/gcc/testsuite/gdc.dg/asm1.d
+++ b/gcc/testsuite/gdc.dg/asm1.d
@@ -29,6 +29,15 @@ void parse3()
     // { dg-error "found 'EOF' when expecting ';'" "" { target *-*-* } .-4 }
 }
 
+void parse4()
+{
+    int expr;
+    asm
+    {
+        "%name" : [name] string (expr); // { dg-error "expected constant string constraint for operand, not 'string'" }
+    }
+}
+
 void semantic1()
 {
     {
diff --git a/gcc/testsuite/gdc.dg/asm5.d b/gcc/testsuite/gdc.dg/asm5.d
new file mode 100644
index 00000000000..b525a2131ce
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/asm5.d
@@ -0,0 +1,12 @@
+// https://issues.dlang.org/show_bug.cgi?id=20593
+// { dg-do compile }
+// { dg-options "-Wall -Wdeprecated -Werror" }
+module asm5;
+
+void test(int a)
+{
+    asm
+    {
+        "cpuid" : : "a" a;  // { dg-error "'a' must be surrounded by parentheses" }
+    }
+}
-- 
2.20.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-04-12  6:30 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-04-12  6:30 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 360 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream c185f9df1.

Adds new virtual isVersionCondition, this is so that in the code
generation pass, a ConditionDeclaration's condition can be identified
without requiring a Visitor function.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r270300.

-- 
Iain
---

[-- Attachment #2: dmdc185f9df1.patch --]
[-- Type: text/x-patch, Size: 1066 bytes --]

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 800be95e4e6..be0c5a50da2 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-d7ed327edb0b01ad56e7e73e77b3401cd565675e
+c185f9df1789456c7d88d047f2df23dd784f1182
 
 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/cond.h b/gcc/d/dmd/cond.h
index 891969be48d..8e33b16a9da 100644
--- a/gcc/d/dmd/cond.h
+++ b/gcc/d/dmd/cond.h
@@ -39,6 +39,7 @@ public:
     virtual Condition *syntaxCopy() = 0;
     virtual int include(Scope *sc, ScopeDsymbol *sds) = 0;
     virtual DebugCondition *isDebugCondition() { return NULL; }
+    virtual VersionCondition *isVersionCondition() { return NULL; }
     virtual void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -91,6 +92,7 @@ public:
     VersionCondition(Module *mod, unsigned level, Identifier *ident);
 
     int include(Scope *sc, ScopeDsymbol *sds);
+    VersionCondition *isVersionCondition() { return this; }
     void accept(Visitor *v) { v->visit(this); }
 };
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-04-11 21:23 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-04-11 21:23 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 262 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream d7ed327ed.

Backports fix for an ICE that occurred when accessing empty array in CTFE.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r270294.

-- 
Iain
---

[-- Attachment #2: dmdd7ed327ed.patch --]
[-- Type: text/x-patch, Size: 1667 bytes --]

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 31ea106965b..800be95e4e6 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-5dd3eccc3b0758346f77bee3cdc3f6bd15de339b
+d7ed327edb0b01ad56e7e73e77b3401cd565675e
 
 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/dinterpret.c b/gcc/d/dmd/dinterpret.c
index 777f89cf186..40f3e77cbc5 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -6272,11 +6272,14 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
 /* Returns: true if e is void,
  * or is an array literal or struct literal of void elements.
  */
-static bool isVoid(Expression *e)
+static bool isVoid(Expression *e, bool checkArray = false)
 {
     if (e->op == TOKvoid)
         return true;
 
+    if (checkArray && e->type->ty != Tsarray)
+        return false;
+
     if (e->op == TOKarrayliteral)
         return isEntirelyVoid(((ArrayLiteralExp *)e)->elements);
 
@@ -6314,7 +6317,7 @@ Expression *scrubArray(Loc loc, Expressions *elems, bool structlit)
 
         // A struct .init may contain void members.
         // Static array members are a weird special case (bug 10994).
-        if (structlit && isVoid(e))
+        if (structlit && isVoid(e, true))
         {
             e = NULL;
         }
diff --git a/gcc/testsuite/gdc.test/compilable/test19778.d b/gcc/testsuite/gdc.test/compilable/test19778.d
new file mode 100644
index 00000000000..87905fae6a0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19778.d
@@ -0,0 +1,6 @@
+struct S
+{
+    int[] data;
+}
+immutable X = S([]);
+enum len = X.data.length;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-03-31  4:40 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-03-31  4:40 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 633 bytes --]

Hi,

The patch merges the D front-end implementation with dmd upstream 5dd3eccc3.

Aligns the test flags between gcc and upstream, after adding support
to gdc-test.exp to handle extra source and file settings being passed
multiple times.

Regression tested on x86_64-linux-gnu.

Committed to trunk as r270038.

-- 
Iain
---
gcc/testsuite/ChangeLog:

2019-03-30  Iain Buclaw  <ibuclaw@gdcproject.org>

        * gdc.test/gdc-test.exp (gdc-copy-extra): Append copied files to
        cleanup_extra_files.
        (dmd2dg): Copy additional files after test is translated.
        (gdc-do-test): Remove all copied files after test.

---

[-- Attachment #2: dmd5dd3eccc3.patch --]
[-- Type: text/x-patch, Size: 16689 bytes --]

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index ffad6cb524d..31ea106965b 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-ab702e73e56aefb3b77b8f8f42da94bc22143eeb
+5dd3eccc3b0758346f77bee3cdc3f6bd15de339b
 
 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/testsuite/gdc.test/compilable/test6395.d b/gcc/testsuite/gdc.test/compilable/test6395.d
index 95f1a7eae6e..a1bac8e48f1 100644
--- a/gcc/testsuite/gdc.test/compilable/test6395.d
+++ b/gcc/testsuite/gdc.test/compilable/test6395.d
@@ -1,5 +1,6 @@
-// REQUIRED_ARGS: -c -Icompilable/extra-files
+// REQUIRED_ARGS: -Icompilable/extra-files
 // EXTRA_SOURCES: b6395.d
+// EXTRA_FILES: extra-files/c6395.d
 
 // 6395
 
diff --git a/gcc/testsuite/gdc.test/compilable/test7190.d b/gcc/testsuite/gdc.test/compilable/test7190.d
index 5143f55e772..45344f13b8f 100644
--- a/gcc/testsuite/gdc.test/compilable/test7190.d
+++ b/gcc/testsuite/gdc.test/compilable/test7190.d
@@ -1,6 +1,9 @@
 // PERMUTE_ARGS:
 // REQUIRED_ARGS: -Icompilable/extra-files
-// EXTRA_FILES: extra-files/example7190/controllers/HomeController.d extra-files/example7190/models/HomeModel.d extra-files/serenity7190/core/Controller.d  extra-files/serenity7190/core/Model.d
+// EXTRA_FILES: extra-files/example7190/controllers/HomeController.d
+// EXTRA_FILES: extra-files/example7190/models/HomeModel.d
+// EXTRA_FILES: extra-files/serenity7190/core/Controller.d
+// EXTRA_FILES: extra-files/serenity7190/core/Model.d
 
 import example7190.controllers.HomeController;
 import example7190.models.HomeModel;
diff --git a/gcc/testsuite/gdc.test/compilable/test9436.d b/gcc/testsuite/gdc.test/compilable/test9436.d
index c80bdc59e82..2baee7c216b 100644
--- a/gcc/testsuite/gdc.test/compilable/test9436.d
+++ b/gcc/testsuite/gdc.test/compilable/test9436.d
@@ -1,4 +1,3 @@
-// REQUIRED_ARGS: -c
 // EXTRA_SOURCES: imports/test9436interp.d
 
 // this is a dummy module for test 9436.
diff --git a/gcc/testsuite/gdc.test/compilable/testDIP37.d b/gcc/testsuite/gdc.test/compilable/testDIP37.d
index a612365eaf4..7188758414c 100644
--- a/gcc/testsuite/gdc.test/compilable/testDIP37.d
+++ b/gcc/testsuite/gdc.test/compilable/testDIP37.d
@@ -1,6 +1,9 @@
 // PERMUTE_ARGS:
 // REQUIRED_ARGS: -Icompilable/extra-files
-// EXTRA_FILES: extra-files/pkgDIP37/datetime/package.d extra-files/pkgDIP37/datetime/common.d extra-files/pkgDIP37/test17629/package.di extra-files/pkgDIP37/test17629/common.di
+// EXTRA_FILES: extra-files/pkgDIP37/datetime/package.d
+// EXTRA_FILES: extra-files/pkgDIP37/datetime/common.d
+// EXTRA_FILES: extra-files/pkgDIP37/test17629/package.di
+// EXTRA_FILES: extra-files/pkgDIP37/test17629/common.di
 
 void test1()
 {
diff --git a/gcc/testsuite/gdc.test/compilable/testDIP37_10302.d b/gcc/testsuite/gdc.test/compilable/testDIP37_10302.d
index 7e76595f06f..3c4a409b709 100644
--- a/gcc/testsuite/gdc.test/compilable/testDIP37_10302.d
+++ b/gcc/testsuite/gdc.test/compilable/testDIP37_10302.d
@@ -1,6 +1,7 @@
 // PERMUTE_ARGS:
-// REQUIRED_ARGS: -c -Icompilable/extra-files
-// EXTRA_SOURCES: extra-files/pkgDIP37_10302/liba.d extra-files/pkgDIP37_10302/libb.d
+// REQUIRED_ARGS: -Icompilable/extra-files
+// COMPILED_IMPORTS: extra-files/pkgDIP37_10302/liba.d
+// COMPILED_IMPORTS: extra-files/pkgDIP37_10302/libb.d
 // EXTRA_FILES: extra-files/pkgDIP37_10302/package.d
 
 module test;
diff --git a/gcc/testsuite/gdc.test/compilable/testDIP37_10354.d b/gcc/testsuite/gdc.test/compilable/testDIP37_10354.d
index 2993fa94d39..f9adf86307c 100644
--- a/gcc/testsuite/gdc.test/compilable/testDIP37_10354.d
+++ b/gcc/testsuite/gdc.test/compilable/testDIP37_10354.d
@@ -1,6 +1,8 @@
 // PERMUTE_ARGS:
 // REQUIRED_ARGS: -o- -Icompilable/extra-files
-// EXTRA_FILES: extra-files/pkgDIP37_10354/mbar.d extra-files/pkgDIP37_10354/mfoo.d extra-files/pkgDIP37_10354/package.d
+// EXTRA_FILES: extra-files/pkgDIP37_10354/mbar.d
+// EXTRA_FILES: extra-files/pkgDIP37_10354/mfoo.d
+// EXTRA_FILES: extra-files/pkgDIP37_10354/package.d
 
 module testDIP37_10354;
 import pkgDIP37_10354.mfoo;
diff --git a/gcc/testsuite/gdc.test/compilable/testDIP37_10421.d b/gcc/testsuite/gdc.test/compilable/testDIP37_10421.d
index 859347331b1..7da5bcf2d08 100644
--- a/gcc/testsuite/gdc.test/compilable/testDIP37_10421.d
+++ b/gcc/testsuite/gdc.test/compilable/testDIP37_10421.d
@@ -1,6 +1,8 @@
 // PERMUTE_ARGS:
 // REQUIRED_ARGS: -Icompilable/extra-files
-// COMPILED_IMPORTS: extra-files/pkgDIP37_10421/algo/package.d extra-files/pkgDIP37_10421/algo/mod.d extra-files/pkgDIP37_10421/except.d
+// COMPILED_IMPORTS: extra-files/pkgDIP37_10421/algo/package.d
+// COMPILED_IMPORTS: extra-files/pkgDIP37_10421/algo/mod.d
+// COMPILED_IMPORTS: extra-files/pkgDIP37_10421/except.d
 
 module testDIP37_10421;
 import pkgDIP37_10421.algo;
diff --git a/gcc/testsuite/gdc.test/gdc-test.exp b/gcc/testsuite/gdc.test/gdc-test.exp
index 59abf74dc89..ab8a4a3cfbd 100644
--- a/gcc/testsuite/gdc.test/gdc-test.exp
+++ b/gcc/testsuite/gdc.test/gdc-test.exp
@@ -153,6 +153,10 @@ proc gdc-copy-extra { base extra } {
     close $fdin
     close $fdout
 
+    # Remove file once test is finished.
+    upvar 2 cleanup_extra_files cleanups
+    lappend cleanups $extra
+
     return $extra
 }
 
@@ -184,6 +188,9 @@ proc dmd2dg { base test } {
     set PERMUTE_ARGS $DEFAULT_DFLAGS
     set GDC_EXECUTE_ARGS ""
 
+    set extra_sources ""
+    set extra_files ""
+
     # Split base, folder/file.
     set type [file dirname $test]
     set name [file tail $test]
@@ -230,46 +237,57 @@ proc dmd2dg { base test } {
 	    regsub -- {REQUIRED_ARGS.*$} $copy_line $new_option out_line
 
 	} elseif [regexp -- {EXTRA_SOURCES\s*:\s*(.*)} $copy_line match sources] {
-	    # Copy all sources to the testsuite build directory.
-	    foreach import $sources {
-		# print "Import: $base $type/$import"
-		gdc-copy-extra $base "$type/$import"
+	    # EXTRA_SOURCES are appended to extra_sources list
+	    foreach srcfile $sources {
+		lappend extra_sources $srcfile
 	    }
-	    set new_option "{ dg-additional-sources \"$sources\" }"
-	    regsub -- {EXTRA_SOURCES.*$} $copy_line $new_option out_line
+	    regsub -- {EXTRA_SOURCES.*$} $copy_line "" out_line
 
 	} elseif [regexp -- {EXTRA_CPP_SOURCES\s*:\s*(.*)} $copy_line match sources] {
-	    # Copy all sources to the testsuite build directory.
-	    foreach import $sources {
-		# print "Import: $base $type/$import"
-		gdc-copy-extra $base "$type/$import"
+	    # EXTRA_CPP_SOURCES are appended to extra_sources list
+	    foreach srcfile $sources {
+		# C++ sources are found in the extra-files directory.
+		lappend extra_sources "extra-files/$srcfile"
 	    }
-	    set new_option "{ dg-additional-sources \"$sources\" }"
-	    regsub -- {EXTRA_CPP_SOURCES.*$} $copy_line $new_option out_line
+	    regsub -- {EXTRA_CPP_SOURCES.*$} $copy_line "" out_line
 
 	} elseif [regexp -- {EXTRA_FILES\s*:\s*(.*)} $copy_line match files] {
-	    # Copy all files to the testsuite build directory.
-	    foreach import $files {
-		# print "Import: $base $type/$import"
-		gdc-copy-extra $base "$type/$import"
+	    # EXTRA_FILES are appended to extra_files list
+	    foreach file $files {
+		lappend extra_files $file
 	    }
-	    set new_option "{ dg-additional-files \"$files\" }"
-	    regsub -- {EXTRA_FILES.*$} $copy_line $new_option out_line
+	    regsub -- {EXTRA_FILES.*$} $copy_line "" out_line
 
 	} elseif [regexp -- {COMPILED_IMPORTS\s*:\s*(.*)} $copy_line match sources] {
-	    # Copy all sources to the testsuite build directory.
+	    # COMPILED_IMPORTS are appended to extra_sources list
 	    foreach import $sources {
-		# print "Import: $base $type/$import"
-		gdc-copy-extra $base "$type/$import"
+		lappend extra_sources $import
 	    }
-	    set new_option "{ dg-additional-sources \"$sources\" }"
-	    regsub -- {COMPILED_IMPORTS.*$} $copy_line $new_option out_line
+	    regsub -- {COMPILED_IMPORTS.*$} $copy_line "" out_line
 
 	}
 
 	puts $fdout $out_line
     }
 
+    # Now that all extra sources and files have been collected, copy them all
+    # to the testsuite build directory.
+    if { [llength $extra_sources] > 0 } {
+	foreach srcfile $extra_sources {
+	    gdc-copy-extra $base "$type/$srcfile"
+	}
+	set out_line "// { dg-additional-sources \"$extra_sources\" }"
+	puts $fdout $out_line
+    }
+
+    if { [llength $extra_files] > 0 } {
+	foreach file $extra_files {
+	    gdc-copy-extra $base "$type/$file"
+	}
+	set out_line "// { dg-additional-files \"$extra_files\" }"
+	puts $fdout $out_line
+    }
+
     # Add specific options for test type
 
     # DMD's testsuite is extremely verbose, compiler messages from constructs
@@ -387,6 +405,7 @@ proc gdc-do-test { } {
 
 	# Convert to DG test.
 	set imports [format "-I%s/%s" $base $dir]
+	set cleanup_extra_files ""
 	# Include $subdir prefix so test names follow DejaGnu conventions.
 	set filename "$subdir/[dmd2dg $base $dir/$name.$ext]"
 
@@ -430,7 +449,10 @@ proc gdc-do-test { } {
 	    }
 	}
 
-	# Cleanup
+	# Cleanup test directory.
+	foreach srcfile $cleanup_extra_files {
+	    file delete $subdir/$srcfile
+	}
 	file delete $filename
     }
 
diff --git a/gcc/testsuite/gdc.test/runnable/cabi1.d b/gcc/testsuite/gdc.test/runnable/cabi1.d
index b58e25ca5dc..3a914cd0e57 100644
--- a/gcc/testsuite/gdc.test/runnable/cabi1.d
+++ b/gcc/testsuite/gdc.test/runnable/cabi1.d
@@ -1,5 +1,5 @@
 
-// EXTRA_CPP_SOURCES: extra-files/cabi2.cpp
+// EXTRA_CPP_SOURCES: cabi2.cpp
 
 import core.stdc.stdio;
 import core.stdc.config;
diff --git a/gcc/testsuite/gdc.test/runnable/cpp_abi_tests.d b/gcc/testsuite/gdc.test/runnable/cpp_abi_tests.d
index f0c0c097904..83e1cff10d9 100644
--- a/gcc/testsuite/gdc.test/runnable/cpp_abi_tests.d
+++ b/gcc/testsuite/gdc.test/runnable/cpp_abi_tests.d
@@ -1,4 +1,4 @@
-// EXTRA_CPP_SOURCES: extra-files/cpp_abi_tests.cpp
+// EXTRA_CPP_SOURCES: cpp_abi_tests.cpp
 
 extern(C++) {
 
diff --git a/gcc/testsuite/gdc.test/runnable/cppa.d b/gcc/testsuite/gdc.test/runnable/cppa.d
index 6b2bafbe7bc..b9b4832991e 100644
--- a/gcc/testsuite/gdc.test/runnable/cppa.d
+++ b/gcc/testsuite/gdc.test/runnable/cppa.d
@@ -1,5 +1,5 @@
 // PERMUTE_ARGS: -g
-// EXTRA_CPP_SOURCES: extra-files/cppb.cpp
+// EXTRA_CPP_SOURCES: cppb.cpp
 
 import core.stdc.stdio;
 import core.stdc.stdarg;
diff --git a/gcc/testsuite/gdc.test/runnable/externmangle.d b/gcc/testsuite/gdc.test/runnable/externmangle.d
index bf80adafe02..9099f94f2d0 100644
--- a/gcc/testsuite/gdc.test/runnable/externmangle.d
+++ b/gcc/testsuite/gdc.test/runnable/externmangle.d
@@ -1,4 +1,4 @@
-// EXTRA_CPP_SOURCES: extra-files/externmangle.cpp
+// EXTRA_CPP_SOURCES: externmangle.cpp
 
 extern(C++):
 
diff --git a/gcc/testsuite/gdc.test/runnable/externmangle2.d b/gcc/testsuite/gdc.test/runnable/externmangle2.d
index 7d87fbd67f3..74beb2581f0 100644
--- a/gcc/testsuite/gdc.test/runnable/externmangle2.d
+++ b/gcc/testsuite/gdc.test/runnable/externmangle2.d
@@ -1,4 +1,4 @@
-// EXTRA_CPP_SOURCES: extra-files/externmangle2.cpp
+// EXTRA_CPP_SOURCES: externmangle2.cpp
 
 version(Windows)
 {
diff --git a/gcc/testsuite/gdc.test/runnable/ice10086a.d b/gcc/testsuite/gdc.test/runnable/ice10086a.d
index c2f5ae6f729..31a5b568b50 100644
--- a/gcc/testsuite/gdc.test/runnable/ice10086a.d
+++ b/gcc/testsuite/gdc.test/runnable/ice10086a.d
@@ -1,4 +1,5 @@
-// EXTRA_SOURCES: imports/ice10086x.d imports/ice10086y.d
+// EXTRA_SOURCES: imports/ice10086x.d
+// EXTRA_SOURCES: imports/ice10086y.d
 
 import imports.ice10086x;
 import imports.ice10086y;
diff --git a/gcc/testsuite/gdc.test/runnable/ice10086b.d b/gcc/testsuite/gdc.test/runnable/ice10086b.d
index 0dc64f84c16..abb6f78a4ac 100644
--- a/gcc/testsuite/gdc.test/runnable/ice10086b.d
+++ b/gcc/testsuite/gdc.test/runnable/ice10086b.d
@@ -1,4 +1,5 @@
-// EXTRA_SOURCES: imports/ice10086y.d imports/ice10086x.d
+// EXTRA_SOURCES: imports/ice10086y.d
+// EXTRA_SOURCES: imports/ice10086x.d
 
 import imports.ice10086y;
 import imports.ice10086x;
diff --git a/gcc/testsuite/gdc.test/runnable/ice4481.d b/gcc/testsuite/gdc.test/runnable/ice4481.d
index 638d1518f60..e1467963ee7 100644
--- a/gcc/testsuite/gdc.test/runnable/ice4481.d
+++ b/gcc/testsuite/gdc.test/runnable/ice4481.d
@@ -1,4 +1,5 @@
-// EXTRA_SOURCES: imports/ice4481a.d imports/ice4481b.d
+// EXTRA_SOURCES: imports/ice4481a.d
+// EXTRA_SOURCES: imports/ice4481b.d
 
 import imports.ice4481a;
 import imports.ice4481b;
diff --git a/gcc/testsuite/gdc.test/runnable/imports/std12010container.d b/gcc/testsuite/gdc.test/runnable/imports/std12010container.d
index a2288059927..1fe8aff14a9 100644
--- a/gcc/testsuite/gdc.test/runnable/imports/std12010container.d
+++ b/gcc/testsuite/gdc.test/runnable/imports/std12010container.d
@@ -1,4 +1,3 @@
-module imports.std12010container;
 struct Array(T)
 {
     private struct Payload
diff --git a/gcc/testsuite/gdc.test/runnable/link11069b.d b/gcc/testsuite/gdc.test/runnable/link11069b.d
index a6253504f98..658f46eb51b 100644
--- a/gcc/testsuite/gdc.test/runnable/link11069b.d
+++ b/gcc/testsuite/gdc.test/runnable/link11069b.d
@@ -1,5 +1,7 @@
 // COMPILE_SEPARATELY
-// EXTRA_SOURCES: imports/link11069x.d imports/link11069y.d imports/link11069z.d
+// EXTRA_SOURCES: imports/link11069x.d
+// EXTRA_SOURCES: imports/link11069y.d
+// EXTRA_SOURCES: imports/link11069z.d
 
 import imports.link11069y;
 import imports.link11069z;
diff --git a/gcc/testsuite/gdc.test/runnable/link12010.d b/gcc/testsuite/gdc.test/runnable/link12010.d
index 41fa719f799..49c4eb184b1 100644
--- a/gcc/testsuite/gdc.test/runnable/link12010.d
+++ b/gcc/testsuite/gdc.test/runnable/link12010.d
@@ -1,5 +1,6 @@
 // COMPILE_SEPARATELY
-// EXTRA_SOURCES: imports/a12010.d imports/std12010container.d
+// EXTRA_SOURCES: imports/a12010.d
+// EXTRA_FILES: imports/std12010container.d
 // REQUIRED_ARGS: -release
 // -release is necessary to avoid __assert.
 
diff --git a/gcc/testsuite/gdc.test/runnable/link2644.d b/gcc/testsuite/gdc.test/runnable/link2644.d
index bf656f7ef81..f38b8cab8c2 100644
--- a/gcc/testsuite/gdc.test/runnable/link2644.d
+++ b/gcc/testsuite/gdc.test/runnable/link2644.d
@@ -1,5 +1,7 @@
 // PERMUTE_ARGS: -version=X -inline -release -g -O
-// EXTRA_SOURCES: imports/link2644a.d imports/link2644b.d imports/link2644c.d
+// EXTRA_SOURCES: imports/link2644a.d
+// EXTRA_SOURCES: imports/link2644b.d
+// EXTRA_SOURCES: imports/link2644c.d
 // COMPILE_SEPARATELY:
 
 module link2644;
diff --git a/gcc/testsuite/gdc.test/runnable/overload.d b/gcc/testsuite/gdc.test/runnable/overload.d
index 73354281df4..f8fa7d5cdda 100644
--- a/gcc/testsuite/gdc.test/runnable/overload.d
+++ b/gcc/testsuite/gdc.test/runnable/overload.d
@@ -1,4 +1,5 @@
-// EXTRA_SOURCES: imports/ovs1528a.d imports/ovs1528b.d imports/template_ovs1.d imports/template_ovs2.d imports/template_ovs3.d
+// EXTRA_SOURCES: imports/ovs1528a.d imports/ovs1528b.d
+// EXTRA_SOURCES: imports/template_ovs1.d imports/template_ovs2.d imports/template_ovs3.d
 
 import imports.template_ovs1;
 import imports.template_ovs2;
diff --git a/gcc/testsuite/gdc.test/runnable/test10736.d b/gcc/testsuite/gdc.test/runnable/test10736.d
index 373b536129b..55b6f539887 100644
--- a/gcc/testsuite/gdc.test/runnable/test10736.d
+++ b/gcc/testsuite/gdc.test/runnable/test10736.d
@@ -1,4 +1,5 @@
-// EXTRA_SOURCES: imports/test10736a.d imports/test10736b.d
+// EXTRA_SOURCES: imports/test10736a.d
+// EXTRA_SOURCES: imports/test10736b.d
 
 import imports.test10736a;
 import imports.test10736b;
diff --git a/gcc/testsuite/gdc.test/runnable/test11863.d b/gcc/testsuite/gdc.test/runnable/test11863.d
index f42ac45d348..c1285b3bef7 100644
--- a/gcc/testsuite/gdc.test/runnable/test11863.d
+++ b/gcc/testsuite/gdc.test/runnable/test11863.d
@@ -1,5 +1,6 @@
 // COMPILE_SEPARATELY
-// EXTRA_SOURCES: imports/std11863conv.d imports/std11863format.d
+// EXTRA_SOURCES: imports/std11863conv.d
+// EXTRA_FILES: imports/std11863format.d
 
 import imports.std11863conv;
 
diff --git a/gcc/testsuite/gdc.test/runnable/test42.d b/gcc/testsuite/gdc.test/runnable/test42.d
index b9619c992ff..87ee7a8e73a 100644
--- a/gcc/testsuite/gdc.test/runnable/test42.d
+++ b/gcc/testsuite/gdc.test/runnable/test42.d
@@ -5676,7 +5676,11 @@ void testreal_to_ulong()
     real adjust = 1.0L/real.epsilon;
     u = r2ulong(adjust);
     //writefln("%s %s", adjust, u);
-    static if(real.mant_dig == 64)
+    static if(real.mant_dig == 113)
+        assert(u == 18446744073709551615UL);
+    else static if(real.mant_dig == 106)
+        assert(u == 18446744073709551615UL);
+    else static if(real.mant_dig == 64)
         assert(u == 9223372036854775808UL);
     else static if(real.mant_dig == 53)
         assert(u == 4503599627370496UL);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-03-26 14:45 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-03-26 14:45 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 302 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream ab702e73e.

Backports memory leak fix in the mangler, and introduces recognition
and rejection of more C types and directives.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r269945.

-- 
Iain
---

[-- Attachment #2: dmdab702e73e.patch --]
[-- Type: text/x-patch, Size: 6263 bytes --]

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 3017f0d34af..ffad6cb524d 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-74ac873be1862090b7ec0e4a876fd1b758520359
+ab702e73e56aefb3b77b8f8f42da94bc22143eeb
 
 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/dmangle.c b/gcc/d/dmd/dmangle.c
index 7f13947ae2b..44f4f826b41 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -306,8 +306,9 @@ public:
         buf2.reserve(32);
         Mangler v(&buf2);
         v.paramsToDecoBuffer(t->arguments);
+        const char *s = buf2.peekString();
         int len = (int)buf2.offset;
-        buf->printf("%d%.*s", len, len, buf2.extractData());
+        buf->printf("%d%.*s", len, len, s);
     }
 
     void visit(TypeNull *t)
diff --git a/gcc/d/dmd/dscope.c b/gcc/d/dmd/dscope.c
index 27c3fd58947..def448a2408 100644
--- a/gcc/d/dmd/dscope.c
+++ b/gcc/d/dmd/dscope.c
@@ -685,14 +685,16 @@ Dsymbol *Scope::search_correct(Identifier *ident)
 const char *Scope::search_correct_C(Identifier *ident)
 {
     TOK tok;
-    if (ident == Id::_NULL)
+    if (ident == Id::C_NULL)
         tok = TOKnull;
-    else if (ident == Id::_TRUE)
+    else if (ident == Id::C_TRUE)
         tok = TOKtrue;
-    else if (ident == Id::_FALSE)
+    else if (ident == Id::C_FALSE)
         tok = TOKfalse;
-    else if (ident == Id::_unsigned)
+    else if (ident == Id::C_unsigned)
         tok = TOKuns32;
+    else if (ident == Id::C_wchar_t)
+        tok = global.params.isWindows ? TOKwchar : TOKdchar;
     else
         return NULL;
     return Token::toChars(tok);
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index ec26b2c7008..e75004893aa 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -374,10 +374,11 @@ Msgtable msgtable[] =
     { "udaSelector", "selector" },
 
     // C names, for undefined identifier error messages
-    { "_NULL", "NULL" },
-    { "_TRUE", "TRUE" },
-    { "_FALSE", "FALSE" },
-    { "_unsigned", "unsigned" },
+    { "C_NULL", "NULL" },
+    { "C_TRUE", "TRUE" },
+    { "C_FALSE", "FALSE" },
+    { "C_unsigned", "unsigned" },
+    { "C_wchar_t", "wchar_t" },
 };
 
 
diff --git a/gcc/d/dmd/lexer.c b/gcc/d/dmd/lexer.c
index b466f17e4be..8a2c90f1dfd 100644
--- a/gcc/d/dmd/lexer.c
+++ b/gcc/d/dmd/lexer.c
@@ -901,16 +901,25 @@ void Lexer::scan(Token *t)
                 p++;
                 Token n;
                 scan(&n);
-                if (n.value == TOKidentifier && n.ident == Id::line)
+                if (n.value == TOKidentifier)
                 {
-                    poundLine();
-                    continue;
+                   if (n.ident == Id::line)
+                   {
+                       poundLine();
+                       continue;
+                   }
+                   else
+                   {
+                       const Loc locx = loc();
+                       warning(locx, "C preprocessor directive `#%s` is not supported", n.ident->toChars());
+                   }
                 }
-                else
+                else if (n.value == TOKif)
                 {
-                    t->value = TOKpound;
-                    return;
+                    error("C preprocessor directive `#if` is not supported, use `version` or `static if`");
                 }
+                t->value = TOKpound;
+                return;
             }
 
             default:
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index e0ee299eb6d..3afdbc257f8 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -3076,7 +3076,23 @@ Type *Parser::parseBasicType(bool dontLookDotIdents)
         case TOKuns16:   t = Type::tuns16; goto LabelX;
         case TOKint32:   t = Type::tint32; goto LabelX;
         case TOKuns32:   t = Type::tuns32; goto LabelX;
-        case TOKint64:   t = Type::tint64; goto LabelX;
+        case TOKint64:
+            t = Type::tint64;
+            nextToken();
+            if (token.value == TOKint64)    // if `long long`
+            {
+                error("use `long` for a 64 bit integer instead of `long long`");
+                nextToken();
+            }
+            else if (token.value == TOKfloat64) // if `long double`
+            {
+                error("use `real` instead of `long double`");
+                t = Type::tfloat80;
+                nextToken();
+
+            }
+            break;
+
         case TOKuns64:   t = Type::tuns64; goto LabelX;
         case TOKint128:  t = Type::tint128; goto LabelX;
         case TOKuns128:  t = Type::tuns128; goto LabelX;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/cerrors.d b/gcc/testsuite/gdc.test/fail_compilation/cerrors.d
new file mode 100644
index 00000000000..3d69d415e2b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/cerrors.d
@@ -0,0 +1,15 @@
+/* REQUIRED_ARGS: -wi
+TEST_OUTPUT:
+---
+fail_compilation/cerrors.d(11): Error: C preprocessor directive `#if` is not supported, use `version` or `static if`
+fail_compilation/cerrors.d(11): Error: declaration expected, not `#`
+fail_compilation/cerrors.d(15): Warning: C preprocessor directive `#endif` is not supported
+fail_compilation/cerrors.d(15): Error: declaration expected, not `#`
+---
+*/
+
+#if 1
+
+void test(wchar_t u);
+
+#endif
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ctypes.d b/gcc/testsuite/gdc.test/fail_compilation/ctypes.d
new file mode 100644
index 00000000000..9f5ff18f751
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ctypes.d
@@ -0,0 +1,13 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ctypes.d(11): Error: use `real` instead of `long double`
+fail_compilation/ctypes.d(12): Error: use `long` for a 64 bit integer instead of `long long`
+---
+*/
+
+void test()
+{
+    long double r;
+    long long ll;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/widechars.d b/gcc/testsuite/gdc.test/fail_compilation/widechars.d
new file mode 100644
index 00000000000..ccfc47aa817
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/widechars.d
@@ -0,0 +1,10 @@
+
+/*
+DISABLED: win32 win64
+TEST_OUTPUT:
+---
+fail_compilation/widechars.d(10): Error: undefined identifier `wchar_t`, did you mean `dchar`?
+---
+*/
+
+wchar_t x;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-03-12 14:17 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-03-12 14:17 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 673 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream 7423993c9.

Backports a fix for extern(C++) mangling for substituted basic types
that are target-specific.  Introduces a new method that currently does
nothing, but could in future make use of flag_abi_version as
extern(C++) integration improves in latter versions of the D
front-end.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r269611.

-- 
Iain
---
gcc/d/ChangeLog:

2019-03-12  Iain Buclaw  <ibuclaw@gdcproject.org>

        * d-lang.cc (d_init_options): Set global.params.cplusplus to C++14.
        * d-target.cc (Target::cppFundamentalType): New method.
---

[-- Attachment #2: dmd7423993c9.patch --]
[-- Type: text/x-patch, Size: 7032 bytes --]

diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index b53e56e65a2..d97525a590e 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -282,6 +282,9 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
   global.params.betterC = false;
   global.params.allInst = false;
 
+  /* Default extern(C++) mangling to C++14.  */
+  global.params.cplusplus = CppStdRevisionCpp14;
+
   global.params.linkswitches = new Strings ();
   global.params.libfiles = new Strings ();
   global.params.objfiles = new Strings ();
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index de57d9256db..e0cfbafe0b9 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -385,6 +385,15 @@ Target::cppParameterType (Parameter *arg)
   return t;
 }
 
+/* Checks whether TYPE is a vendor-specific fundamental type.  Stores the result
+   in IS_FUNDAMENTAL and returns true if the parameter was set.  */
+
+bool
+Target::cppFundamentalType (const Type *, bool &)
+{
+  return false;
+}
+
 /* Return the default system linkage for the target.  */
 
 LINK
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index cf5a22f070f..f58b620d844 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-fcc235e8e25f7758266f7874edd5abefb9943e0b
+7423993c996ed9f73d6ba6d58f625ad3c778ca1d
 
 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/cppmangle.c b/gcc/d/dmd/cppmangle.c
index b991417c35e..9b24fd2c2e4 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -120,6 +120,40 @@ class CppMangleVisitor : public Visitor
                 !getQualifier(s));      // at global level
     }
 
+    /************************
+     * Determine if type is a C++ fundamental type.
+     * Params:
+     *  t = type to check
+     * Returns:
+     *  true if it is a fundamental type
+     */
+    static bool isFundamentalType(Type *t)
+    {
+        // First check the target whether some specific ABI is being followed.
+        bool isFundamental;
+        if (Target::cppFundamentalType(t, isFundamental))
+            return isFundamental;
+        if (t->ty == Tenum)
+        {
+            // Peel off enum type from special types.
+            TypeEnum *te = (TypeEnum *)t;
+            if (te->sym->isSpecial())
+                t = te->sym->getMemtype(Loc());
+        }
+
+        // Fundamental arithmetic types:
+        // 1. integral types: bool, char, int, ...
+        // 2. floating point types: float, double, real
+        // 3. void
+        // 4. null pointer: std::nullptr_t (since C++11)
+        if (t->ty == Tvoid || t->ty == Tbool)
+            return true;
+        else if (t->ty == Tnull && global.params.cplusplus >= CppStdRevisionCpp11)
+            return true;
+        else
+            return t->isTypeBasic() && (t->isintegral() || t->isreal());
+    }
+
     /******************************
      * Write the mangled representation of the template arguments.
      * Params:
@@ -741,7 +775,8 @@ public:
      */
     void writeBasicType(Type *t, char p, char c)
     {
-        if (p || t->isConst())
+        // Only do substitutions for non-fundamental types.
+        if (!isFundamentalType(t) || t->isConst())
         {
             if (substitute(t))
                 return;
@@ -767,6 +802,22 @@ public:
         if (t->isImmutable() || t->isShared())
             return error(t);
 
+        // Handle any target-specific basic types.
+        if (const char *tm = Target::cppTypeMangle(t))
+        {
+            // Only do substitutions for non-fundamental types.
+            if (!isFundamentalType(t) || t->isConst())
+            {
+                if (substitute(t))
+                    return;
+                else
+                    append(t);
+            }
+            CV_qualifiers(t);
+            buf->writestring(tm);
+            return;
+        }
+
         /* <builtin-type>:
          * v        void
          * w        wchar_t
@@ -832,17 +883,6 @@ public:
             case Tcomplex80:    p = 'C'; c = 'e';       break;
 
             default:
-                // Handle any target-specific basic types.
-                if (const char *tm = Target::cppTypeMangle(t))
-                {
-                    if (substitute(t))
-                        return;
-                    else
-                        append(t);
-                    CV_qualifiers(t);
-                    buf->writestring(tm);
-                    return;
-                }
                 return error(t);
         }
         writeBasicType(t, p, c);
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 6c37cca3236..e2d42c7b67b 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -55,6 +55,14 @@ enum CPU
     native              // the machine the compiler is being run on
 };
 
+enum CppStdRevision
+{
+    CppStdRevisionCpp98 = 199711,
+    CppStdRevisionCpp11 = 201103,
+    CppStdRevisionCpp14 = 201402,
+    CppStdRevisionCpp17 = 201703
+};
+
 // Put command line switches in here
 struct Param
 {
@@ -114,6 +122,7 @@ struct Param
     bool check10378;    // check for issues transitioning to 10738
     bool bug10378;      // use pre-bugzilla 10378 search strategy
     bool vsafe;         // use enhanced @safe checking
+    unsigned cplusplus;     // version of C++ name mangling to support
     bool showGaggedErrors;  // print gagged errors anyway
 
     CPU cpu;                // CPU instruction set to target
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index 66be2014432..1729bc33ffa 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -71,5 +71,6 @@ struct Target
     static const char *cppTypeInfoMangle(ClassDeclaration *cd);
     static const char *cppTypeMangle(Type *t);
     static Type *cppParameterType(Parameter *p);
+    static bool cppFundamentalType(const Type *t, bool& isFundamental);
     static LINK systemLinkage();
 };
diff --git a/gcc/testsuite/gdc.test/runnable/cppa.d b/gcc/testsuite/gdc.test/runnable/cppa.d
index 82b93adf1f6..6b2bafbe7bc 100644
--- a/gcc/testsuite/gdc.test/runnable/cppa.d
+++ b/gcc/testsuite/gdc.test/runnable/cppa.d
@@ -619,6 +619,7 @@ else
     alias c_long_double myld;
 
 extern (C++) myld testld(myld);
+extern (C++) myld testldld(myld, myld);
 
 
 void test15()
@@ -626,6 +627,10 @@ void test15()
     myld ld = 5.0;
     ld = testld(ld);
     assert(ld == 6.0);
+
+    myld ld2 = 5.0;
+    ld2 = testldld(ld2, ld2);
+    assert(ld2 == 6.0);
 }
 
 /****************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/extra-files/cppb.cpp b/gcc/testsuite/gdc.test/runnable/extra-files/cppb.cpp
index 7574c5fba72..587145c61c3 100644
--- a/gcc/testsuite/gdc.test/runnable/extra-files/cppb.cpp
+++ b/gcc/testsuite/gdc.test/runnable/extra-files/cppb.cpp
@@ -439,6 +439,12 @@ long double testld(long double ld)
     return ld + 1;
 }
 
+long double testldld(long double ld1, long double ld2)
+{
+    assert(ld1 == 5);
+    return ld2 + 1;
+}
+
 long testl(long lng)
 {
     assert(lng == 5);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-03-01 10:22 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-03-01 10:22 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 630 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream ed71446aa.

Backports support for extern(C++, "namespace"), which makes the
core.stdcpp package compilable.

Added predefined condition for CppRuntime_Gcc unconditionally, as it
is unlikely that D code will be linking to anything other than
libstdc++ when extern(C++) is used.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r269304.

-- 
Iain
---

gcc/d/ChangeLog:

2019-03-01  Iain Buclaw  <ibuclaw@gdcproject.org>

        * d-builtins.cc (d_init_versions): Add CppRuntime_Gcc as predefined
        version condition.

---

[-- Attachment #2: dmded71446aa.patch --]
[-- Type: text/x-patch, Size: 21733 bytes --]

diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index b0a315a3ed9..f263aafbd59 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -452,6 +452,8 @@ d_init_versions (void)
   /* Emit all target-specific version identifiers.  */
   targetdm.d_cpu_versions ();
   targetdm.d_os_versions ();
+
+  VersionCondition::addPredefinedGlobalIdent ("CppRuntime_Gcc");
 }
 
 /* A helper for d_build_builtins_module.  Return a new ALIAS for TYPE.
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 8b377015129..97aa40d1ace 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-39edbe17e7b5c761d780c9d1d4376a06df7bf3d8
+ed71446aaa2bd0e548c3bf2154a638826dfe3db0
 
 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/cond.c b/gcc/d/dmd/cond.c
index 8df226fa9b6..9d7df5fd240 100644
--- a/gcc/d/dmd/cond.c
+++ b/gcc/d/dmd/cond.c
@@ -171,6 +171,8 @@ static bool isReserved(const char *ident)
         "SysV4",
         "Hurd",
         "Android",
+        "PlayStation",
+        "PlayStation4",
         "Cygwin",
         "MinGW",
         "FreeStanding",
@@ -197,8 +199,11 @@ static bool isReserved(const char *ident)
         "MIPS_EABI",
         "MIPS_SoftFloat",
         "MIPS_HardFloat",
+        "MSP430",
         "NVPTX",
         "NVPTX64",
+        "RISCV32",
+        "RISCV64",
         "SPARC",
         "SPARC_V8Plus",
         "SPARC_SoftFloat",
@@ -219,6 +224,13 @@ static bool isReserved(const char *ident)
         "CRuntime_Digitalmars",
         "CRuntime_Glibc",
         "CRuntime_Microsoft",
+        "CRuntime_Musl",
+        "CRuntime_UClibc",
+        "CppRuntime_Clang",
+        "CppRuntime_DigitalMars",
+        "CppRuntime_Gcc",
+        "CppRuntime_Microsoft",
+        "CppRuntime_Sun",
         "D_Coverage",
         "D_Ddoc",
         "D_InlineAsm_X86",
diff --git a/gcc/d/dmd/cppmangle.c b/gcc/d/dmd/cppmangle.c
index e26f7647d3c..b991417c35e 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -196,8 +196,8 @@ class CppMangleVisitor : public Visitor
                 Expression *e = isExpression(o);
                 if (d && d->isFuncDeclaration())
                 {
-                    bool is_nested = d->toParent() &&
-                        !d->toParent()->isModule() &&
+                    bool is_nested = d->toParent3() &&
+                        !d->toParent3()->isModule() &&
                         ((TypeFunction*)d->isFuncDeclaration()->type)->linkage == LINKcpp;
                     if (is_nested)
                         buf->writeByte('X');
@@ -271,7 +271,7 @@ class CppMangleVisitor : public Visitor
      */
     Dsymbol *getInstance(Dsymbol *s)
     {
-        Dsymbol *p = s->toParent();
+        Dsymbol *p = s->toParent3();
         if (p)
         {
             if (TemplateInstance *ti = p->isTemplateInstance())
@@ -292,7 +292,7 @@ class CppMangleVisitor : public Visitor
      */
     static Dsymbol *getQualifier(Dsymbol *s)
     {
-        Dsymbol *p = s->toParent();
+        Dsymbol *p = s->toParent3();
         return (p && !p->isModule()) ? p : NULL;
     }
 
@@ -324,7 +324,7 @@ class CppMangleVisitor : public Visitor
         Dsymbol *s = ((TypeStruct*)t)->toDsymbol(NULL);
         if (s->ident != ident)
             return false;
-        Dsymbol *p = s->toParent();
+        Dsymbol *p = s->toParent3();
         if (!p)
             return false;
         TemplateInstance *ti = p->isTemplateInstance();
@@ -427,7 +427,7 @@ class CppMangleVisitor : public Visitor
     void cpp_mangle_name(Dsymbol *s, bool qualified)
     {
         //printf("cpp_mangle_name(%s, %d)\n", s->toChars(), qualified);
-        Dsymbol *p = s->toParent();
+        Dsymbol *p = s->toParent3();
         Dsymbol *se = s;
         bool write_prefix = true;
         if (p && p->isTemplateInstance())
@@ -435,7 +435,7 @@ class CppMangleVisitor : public Visitor
             se = p;
             if (find(p->isTemplateInstance()->tempdecl) >= 0)
                 write_prefix = false;
-            p = p->toParent();
+            p = p->toParent3();
         }
 
         if (p && !p->isModule())
@@ -521,7 +521,7 @@ class CppMangleVisitor : public Visitor
             fatal();
         }
 
-        Dsymbol *p = d->toParent();
+        Dsymbol *p = d->toParent3();
         if (p && !p->isModule()) //for example: char Namespace1::beta[6] should be mangled as "_ZN10Namespace14betaE"
         {
             buf->writestring("_ZN");
@@ -561,7 +561,7 @@ class CppMangleVisitor : public Visitor
              */
             TemplateInstance *ti = d->parent->isTemplateInstance();
             assert(ti);
-            Dsymbol *p = ti->toParent();
+            Dsymbol *p = ti->toParent3();
             if (p && !p->isModule() && tf->linkage == LINKcpp)
             {
                 buf->writeByte('N');
@@ -581,7 +581,7 @@ class CppMangleVisitor : public Visitor
         }
         else
         {
-            Dsymbol *p = d->toParent();
+            Dsymbol *p = d->toParent3();
             if (p && !p->isModule() && tf->linkage == LINKcpp)
             {
                 /* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
@@ -997,7 +997,7 @@ public:
         else
         {
             Dsymbol *s = t->toDsymbol(NULL);
-            Dsymbol *p = s->toParent();
+            Dsymbol *p = s->toParent3();
             if (p && p->isTemplateInstance())
             {
                 /* https://issues.dlang.org/show_bug.cgi?id=17947
@@ -1044,7 +1044,7 @@ public:
 
         {
             Dsymbol *s = t->toDsymbol(NULL);
-            Dsymbol *p = s->toParent();
+            Dsymbol *p = s->toParent3();
             if (p && p->isTemplateInstance())
             {
                  /* https://issues.dlang.org/show_bug.cgi?id=17947
diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c
index 4d82d7217e1..9aec87a04f5 100644
--- a/gcc/d/dmd/dsymbol.c
+++ b/gcc/d/dmd/dsymbol.c
@@ -30,6 +30,7 @@
 #include "attrib.h"
 #include "enum.h"
 #include "lexer.h"
+#include "nspace.h"
 
 bool symbolIsVisible(Dsymbol *origin, Dsymbol *s);
 typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
@@ -310,6 +311,14 @@ Dsymbol *Dsymbol::toAlias2()
     return toAlias();
 }
 
+/**
+ * `pastMixin` returns the enclosing symbol if this is a template mixin.
+ *
+ * `pastMixinAndNspace` does likewise, additionally skipping over Nspaces that
+ * are mangleOnly.
+ *
+ * See also `parent`, `toParent`, `toParent2` and `toParent3`.
+ */
 Dsymbol *Dsymbol::pastMixin()
 {
     Dsymbol *s = this;
@@ -320,16 +329,31 @@ Dsymbol *Dsymbol::pastMixin()
     return s;
 }
 
+/// ditto
+Dsymbol *Dsymbol::pastMixinAndNspace()
+{
+    //printf("Dsymbol::pastMixinAndNspace() %s\n", toChars());
+    Nspace *ns = isNspace();
+    if (!(ns && ns->mangleOnly) && !isTemplateMixin() && !isForwardingAttribDeclaration())
+        return this;
+    if (!parent)
+        return NULL;
+    return parent->pastMixinAndNspace();
+}
+
 /**********************************
  * `parent` field returns a lexically enclosing scope symbol this is a member of.
  *
  * `toParent()` returns a logically enclosing scope symbol this is a member of.
- * It skips over TemplateMixin's.
+ * It skips over TemplateMixin's and Nspaces that are mangleOnly.
  *
  * `toParent2()` returns an enclosing scope symbol this is living at runtime.
  * It skips over both TemplateInstance's and TemplateMixin's.
  * It's used when looking for the 'this' pointer of the enclosing function/class.
  *
+ * `toParent3()` returns a logically enclosing scope symbol this is a member of.
+ * It skips over TemplateMixin's.
+ *
  * Examples:
  *  module mod;
  *  template Foo(alias a) { mixin Bar!(); }
@@ -352,7 +376,7 @@ Dsymbol *Dsymbol::pastMixin()
  */
 Dsymbol *Dsymbol::toParent()
 {
-    return parent ? parent->pastMixin() : NULL;
+    return parent ? parent->pastMixinAndNspace() : NULL;
 }
 
 /// ditto
@@ -364,6 +388,12 @@ Dsymbol *Dsymbol::toParent2()
     return s;
 }
 
+/// ditto
+Dsymbol *Dsymbol::toParent3()
+{
+    return parent ? parent->pastMixin() : NULL;
+}
+
 TemplateInstance *Dsymbol::isInstantiated()
 {
     for (Dsymbol *s = parent; s; s = s->parent)
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index bfed31d3f22..a840261c0bf 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -180,8 +180,10 @@ public:
     Module *getModule();
     Module *getAccessModule();
     Dsymbol *pastMixin();
+    Dsymbol *pastMixinAndNspace();
     Dsymbol *toParent();
     Dsymbol *toParent2();
+    Dsymbol *toParent3();
     TemplateInstance *isInstantiated();
     TemplateInstance *isSpeculative();
     Ungag ungagSpeculative();
diff --git a/gcc/d/dmd/nspace.c b/gcc/d/dmd/nspace.c
index 3068bfc225d..dc785418db8 100644
--- a/gcc/d/dmd/nspace.c
+++ b/gcc/d/dmd/nspace.c
@@ -17,23 +17,29 @@
 /* This implements namespaces.
  */
 
-Nspace::Nspace(Loc loc, Identifier *ident, Dsymbols *members)
+Nspace::Nspace(Loc loc, Identifier *ident, Dsymbols *members, bool mangleOnly)
     : ScopeDsymbol(ident)
 {
     //printf("Nspace::Nspace(ident = %s)\n", ident->toChars());
     this->loc = loc;
     this->members = members;
+    // Determines whether the symbol for this namespace should be included in
+    // the symbol table.
+    this->mangleOnly = mangleOnly;
 }
 
 Dsymbol *Nspace::syntaxCopy(Dsymbol *)
 {
-    Nspace *ns = new Nspace(loc, ident, NULL);
+    Nspace *ns = new Nspace(loc, ident, NULL, mangleOnly);
     return ScopeDsymbol::syntaxCopy(ns);
 }
 
 void Nspace::addMember(Scope *sc, ScopeDsymbol *sds)
 {
-    ScopeDsymbol::addMember(sc, sds);
+    if (mangleOnly)
+        parent = sds;
+    else
+        ScopeDsymbol::addMember(sc, sds);
     if (members)
     {
         if (!symtab)
diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h
index c045b9657f6..851f800707d 100644
--- a/gcc/d/dmd/nspace.h
+++ b/gcc/d/dmd/nspace.h
@@ -19,7 +19,8 @@
 class Nspace : public ScopeDsymbol
 {
   public:
-    Nspace(Loc loc, Identifier *ident, Dsymbols *members);
+    bool mangleOnly;
+    Nspace(Loc loc, Identifier *ident, Dsymbols *members, bool mangleOnly);
 
     Dsymbol *syntaxCopy(Dsymbol *s);
     void addMember(Scope *sc, ScopeDsymbol *sds);
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index 171ed14f132..701c3141031 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -676,7 +676,8 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
                 Loc linkLoc = token.loc;
                 Identifiers *idents = NULL;
                 CPPMANGLE cppmangle = CPPMANGLEdefault;
-                LINK link = parseLinkage(&idents, &cppmangle);
+                bool cppMangleOnly = false;
+                LINK link = parseLinkage(&idents, &cppmangle, &cppMangleOnly);
                 if (pAttrs->link != LINKdefault)
                 {
                     if (pAttrs->link != link)
@@ -709,7 +710,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
                             a = new Dsymbols();
                             a->push(s);
                         }
-                        s = new Nspace(linkLoc, id, a);
+                        s = new Nspace(linkLoc, id, a, cppMangleOnly);
                     }
                     delete idents;
                     pAttrs->link = LINKdefault;
@@ -1271,13 +1272,15 @@ Type *Parser::parseVector()
  * Parse:
  *      extern (linkage)
  *      extern (C++, namespaces)
+ *      extern (C++, "namespace", "namespaces", ...)
  * The parser is on the 'extern' token.
  */
 
-LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle)
+LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle, bool *pcppMangleOnly)
 {
     Identifiers *idents = NULL;
     CPPMANGLE cppmangle = CPPMANGLEdefault;
+    bool cppMangleOnly = false;
     LINK link = LINKdefault;
     nextToken();
     assert(token.value == TOKlparen);
@@ -1307,6 +1310,42 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle)
                         cppmangle = token.value == TOKclass ? CPPMANGLEclass : CPPMANGLEstruct;
                         nextToken();
                     }
+                    else if (token.value == TOKstring)  // extern(C++, "namespace", "namespaces")
+                    {
+                        cppMangleOnly = true;
+                        idents = new Identifiers();
+
+                        while (1)
+                        {
+                            StringExp *stringExp = (StringExp *)parsePrimaryExp();
+                            const char *name = stringExp->toPtr();
+                            if (stringExp->len == 0)
+                            {
+                                error("invalid zero length C++ namespace");
+                                idents = NULL;
+                                break;
+                            }
+                            else if (!Identifier::isValidIdentifier(name))
+                            {
+                                error("expected valid identifer for C++ namespace but got `%s`", name);
+                                idents = NULL;
+                                break;
+                            }
+                            idents->push(Identifier::idPool(name));
+                            if (token.value == TOKcomma)
+                            {
+                                nextToken();
+                                if (token.value != TOKstring)
+                                {
+                                    error("string expected following `,` for C++ namespace, not `%s`", token.toChars());
+                                    idents = NULL;
+                                    break;
+                                }
+                            }
+                            else
+                                break;
+                        }
+                    }
                     else
                     {
                         idents = new Identifiers();
@@ -1368,6 +1407,7 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle)
     check(TOKrparen);
     *pidents = idents;
     *pcppmangle = cppmangle;
+    *pcppMangleOnly = cppMangleOnly;
     return link;
 }
 
@@ -3604,7 +3644,8 @@ void Parser::parseStorageClasses(StorageClass &storage_class, LINK &link,
                 sawLinkage = true;
                 Identifiers *idents = NULL;
                 CPPMANGLE cppmangle = CPPMANGLEdefault;
-                link = parseLinkage(&idents, &cppmangle);
+                bool cppMangleOnly = false;
+                link = parseLinkage(&idents, &cppmangle, &cppMangleOnly);
                 if (idents)
                 {
                     error("C++ name spaces not allowed here");
diff --git a/gcc/d/dmd/parse.h b/gcc/d/dmd/parse.h
index a77d5e5e436..97630dc3c4d 100644
--- a/gcc/d/dmd/parse.h
+++ b/gcc/d/dmd/parse.h
@@ -88,7 +88,7 @@ public:
     StaticAssert *parseStaticAssert();
     TypeQualified *parseTypeof();
     Type *parseVector();
-    LINK parseLinkage(Identifiers **, CPPMANGLE *);
+    LINK parseLinkage(Identifiers **, CPPMANGLE *, bool *);
     Identifiers *parseQualifiedIdentifier(const char *entity);
     Condition *parseDebugCondition();
     Condition *parseVersionCondition();
diff --git a/gcc/testsuite/gdc.test/compilable/cppmangle3.d b/gcc/testsuite/gdc.test/compilable/cppmangle3.d
new file mode 100644
index 00000000000..4c48012a3d6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/cppmangle3.d
@@ -0,0 +1,37 @@
+module cppmangle3;
+
+
+extern(C++, "true")
+{
+}
+
+extern(C++, "__traits")
+{
+}
+
+extern(C++, "foo")
+{
+}
+
+int foo; // no name clashing with above namespace
+
+extern(C++, "std", "chrono")
+{
+    void func();
+}
+
+version(Windows) static assert(func.mangleof == "?func@chrono@std@@YAXXZ");
+else             static assert(func.mangleof == "_ZNSt6chrono4funcEv");
+
+struct Foo
+{
+    extern(C++, "namespace")
+    {
+        static void bar();
+    }
+}
+
+alias Alias(alias a) = a;
+alias Alias(T) = T;
+
+static assert(is(Alias!(__traits(parent, bar)) == Foo));
diff --git a/gcc/testsuite/gdc.test/compilable/test19574.d b/gcc/testsuite/gdc.test/compilable/test19574.d
new file mode 100644
index 00000000000..907bb3b8edf
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19574.d
@@ -0,0 +1,18 @@
+
+static assert( Foo(10).bar.value == 10 );
+
+extern(C++, "ns") {
+    struct Foo {
+        Bar!Foo bar;
+
+        this( int v ) {
+            bar.value = v;
+        }
+    }
+}
+
+extern(C++, "ns") {
+    struct Bar(T) {
+        int value;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
new file mode 100644
index 00000000000..b8b2f03f019
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
@@ -0,0 +1,20 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/cppmangle.d(10): Error: invalid zero length C++ namespace
+fail_compilation/cppmangle.d(14): Error: expected valid identifer for C++ namespace but got `0num`
+fail_compilation/cppmangle.d(18): Error: string expected following `,` for C++ namespace, not `)`
+---
+*/
+
+extern(C++, "")
+{
+}
+
+extern(C++, "0num")
+{
+}
+
+extern(C++, "std", )
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
index de23c461e4a..1fe47282959 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
@@ -97,11 +97,17 @@ fail_compilation/reserved_version.d(196): Error: version identifier `D_Version2`
 fail_compilation/reserved_version.d(197): Error: version identifier `D_NoBoundsChecks` is reserved and cannot be set
 fail_compilation/reserved_version.d(200): Error: version identifier `all` is reserved and cannot be set
 fail_compilation/reserved_version.d(201): Error: version identifier `none` is reserved and cannot be set
+fail_compilation/reserved_version.d(202): Error: version identifier `CppRuntime_Clang` is reserved and cannot be set
+fail_compilation/reserved_version.d(203): Error: version identifier `CppRuntime_DigitalMars` is reserved and cannot be set
+fail_compilation/reserved_version.d(204): Error: version identifier `CppRuntime_Gcc` is reserved and cannot be set
+fail_compilation/reserved_version.d(205): Error: version identifier `CppRuntime_Microsoft` is reserved and cannot be set
+fail_compilation/reserved_version.d(206): Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
 ---
 */
 
 // Some extra empty lines to help fixup the manual line numbering after adding new version identifiers
 
+#line 105
 version = MSP430;
 version = D_P16;
 version = DigitalMars;
@@ -199,6 +205,11 @@ version = D_NoBoundsChecks;
 //version = assert;
 version = all;
 version = none;
+version = CppRuntime_Clang;
+version = CppRuntime_DigitalMars;
+version = CppRuntime_Gcc;
+version = CppRuntime_Microsoft;
+version = CppRuntime_Sun;
 
 // This should work though
 debug = DigitalMars;
@@ -278,6 +289,11 @@ debug = CRuntime_Glibc;
 debug = CRuntime_Microsoft;
 debug = CRuntime_Musl;
 debug = CRuntime_UClibc;
+debug = CppRuntime_Clang;
+debug = CppRuntime_DigitalMars;
+debug = CppRuntime_Gcc;
+debug = CppRuntime_Microsoft;
+debug = CppRuntime_Sun;
 debug = D_Coverage;
 debug = D_Ddoc;
 debug = D_InlineAsm_X86;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
index eb794d2ac42..0259273f89e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
@@ -77,6 +77,11 @@
 // REQUIRED_ARGS: -version=CRuntime_Microsoft
 // REQUIRED_ARGS: -version=CRuntime_Musl
 // REQUIRED_ARGS: -version=CRuntime_UClibc
+// REQUIRED_ARGS: -version=CppRuntime_Clang
+// REQUIRED_ARGS: -version=CppRuntime_DigitalMars
+// REQUIRED_ARGS: -version=CppRuntime_Gcc
+// REQUIRED_ARGS: -version=CppRuntime_Microsoft
+// REQUIRED_ARGS: -version=CppRuntime_Sun
 // REQUIRED_ARGS: -version=D_Coverage
 // REQUIRED_ARGS: -version=D_Ddoc
 // REQUIRED_ARGS: -version=D_InlineAsm_X86
@@ -168,6 +173,11 @@
 // REQUIRED_ARGS: -debug=CRuntime_Microsoft
 // REQUIRED_ARGS: -debug=CRuntime_Musl
 // REQUIRED_ARGS: -debug=CRuntime_UClibc
+// REQUIRED_ARGS: -debug=CppRuntime_Clang
+// REQUIRED_ARGS: -debug=CppRuntime_DigitalMars
+// REQUIRED_ARGS: -debug=CppRuntime_Gcc
+// REQUIRED_ARGS: -debug=CppRuntime_Microsoft
+// REQUIRED_ARGS: -debug=CppRuntime_Sun
 // REQUIRED_ARGS: -debug=D_Coverage
 // REQUIRED_ARGS: -debug=D_Ddoc
 // REQUIRED_ARGS: -debug=D_InlineAsm_X86
@@ -264,6 +274,11 @@ Error: version identifier `CRuntime_Glibc` is reserved and cannot be set
 Error: version identifier `CRuntime_Microsoft` is reserved and cannot be set
 Error: version identifier `CRuntime_Musl` is reserved and cannot be set
 Error: version identifier `CRuntime_UClibc` is reserved and cannot be set
+Error: version identifier `CppRuntime_Clang` is reserved and cannot be set
+Error: version identifier `CppRuntime_DigitalMars` is reserved and cannot be set
+Error: version identifier `CppRuntime_Gcc` is reserved and cannot be set
+Error: version identifier `CppRuntime_Microsoft` is reserved and cannot be set
+Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
 Error: version identifier `D_Coverage` is reserved and cannot be set
 Error: version identifier `D_Ddoc` is reserved and cannot be set
 Error: version identifier `D_InlineAsm_X86` is reserved and cannot be set

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH, d] Committed merge with upstream dmd
  2019-01-22 10:08 ` Andreas Schwab
@ 2019-01-22 21:31   ` Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-01-22 21:31 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: gcc-patches

On Tue, 22 Jan 2019 at 11:08, Andreas Schwab <schwab@suse.de> wrote:
>
> In file included from ../../gcc/d/d-system.h:23,
>                  from ../../gcc/d/dmd/root/dsystem.h:24,
>                  from ../../gcc/d/dmd/mtype.c:11:
> ../../gcc/d/dmd/mtype.c: In member function 'Identifier* Type::getTypeInfoIdent()':
> ../../gcc/d/dmd/mtype.c:2329:33: error: comparison of integer expressions of different signedness: 'int' and 'size_t' {aka 'long unsigned int'} [-Werror=sign-compare]
>  2329 |     assert(0 < length && length < namelen);     // don't overflow the buffer
>       |                          ~~~~~~~^~~~~~~~~
> ../../gcc/system.h:742:14: note: in definition of macro 'gcc_assert'
>   742 |    ((void)(!(EXPR) ? fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0 : 0))
>       |              ^~~~
> ../../gcc/d/dmd/mtype.c:2329:5: note: in expansion of macro 'assert'
>  2329 |     assert(0 < length && length < namelen);     // don't overflow the buffer
>       |     ^~~~~~
>

Sorry that slipped through.  Fix has gone in upstream and I'll commit it now.

-- 
Iain
---

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index e8ab8df4f7b..c1c6cc145c4 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-180465274b72a2ff218449f6793af0fbaabbcaa3
+e21c07e84bd9668e1c0fc1f45e514c5fd76988e7

 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/mtype.c b/gcc/d/dmd/mtype.c
index 09161a313ee..2a23cab74fd 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -2326,7 +2326,7 @@ Identifier *Type::getTypeInfoIdent()

     int length = sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned
long long) 9 + len, buf.data);
     //printf("%p, deco = %s, name = %s\n", this, deco, name);
-    assert(0 < length && length < namelen);     // don't overflow the buffer
+    assert(0 < length && (size_t)length < namelen);     // don't
overflow the buffer

     Identifier *id = Identifier::idPool(name, length);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH, d] Committed merge with upstream dmd
  2019-01-21 21:17 Iain Buclaw
@ 2019-01-22 10:08 ` Andreas Schwab
  2019-01-22 21:31   ` Iain Buclaw
  0 siblings, 1 reply; 14+ messages in thread
From: Andreas Schwab @ 2019-01-22 10:08 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: gcc-patches

In file included from ../../gcc/d/d-system.h:23,
                 from ../../gcc/d/dmd/root/dsystem.h:24,
                 from ../../gcc/d/dmd/mtype.c:11:
../../gcc/d/dmd/mtype.c: In member function 'Identifier* Type::getTypeInfoIdent()':
../../gcc/d/dmd/mtype.c:2329:33: error: comparison of integer expressions of different signedness: 'int' and 'size_t' {aka 'long unsigned int'} [-Werror=sign-compare]
 2329 |     assert(0 < length && length < namelen);     // don't overflow the buffer
      |                          ~~~~~~~^~~~~~~~~
../../gcc/system.h:742:14: note: in definition of macro 'gcc_assert'
  742 |    ((void)(!(EXPR) ? fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0 : 0))
      |              ^~~~
../../gcc/d/dmd/mtype.c:2329:5: note: in expansion of macro 'assert'
 2329 |     assert(0 < length && length < namelen);     // don't overflow the buffer
      |     ^~~~~~

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-01-21 21:17 Iain Buclaw
  2019-01-22 10:08 ` Andreas Schwab
  0 siblings, 1 reply; 14+ messages in thread
From: Iain Buclaw @ 2019-01-21 21:17 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 458 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream 180465274.

Main bulk of it reduces the memory footprint of the CTFE interpreter
by replacing new with emplacement new in many places.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r268124.

-- 
Iain
---
gcc/d/ChangeLog:

2019-01-21  Iain Buclaw  <ibuclaw@gdcproject.org>

        * d-frontend.cc (Compiler::paintAsType): Update for new signature.
---

[-- Attachment #2: dmd180465274.patch --]
[-- Type: text/x-patch, Size: 78855 bytes --]

diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index a1c0d53d1ca..d1d3c78ec86 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -446,7 +446,7 @@ Compiler::genCmain (Scope *sc)
    so we just lower the value to GCC and return the converted CST.  */
 
 Expression *
-Compiler::paintAsType (Expression *expr, Type *type)
+Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
 {
   /* We support up to 512-bit values.  */
   unsigned char buffer[64];
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index a3b2db74af4..e8ab8df4f7b 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-cd2034cd7b157dd8f3e94c684061bb1aa630b2b6
+180465274b72a2ff218449f6793af0fbaabbcaa3
 
 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/compiler.h b/gcc/d/dmd/compiler.h
index e8ab9925c5a..a8520788f98 100644
--- a/gcc/d/dmd/compiler.h
+++ b/gcc/d/dmd/compiler.h
@@ -19,6 +19,7 @@ class Expression;
 class Module;
 class Type;
 struct Scope;
+struct UnionExp;
 
 // DMD-generated module `__entrypoint` where the C main resides
 extern Module *entrypoint;
@@ -28,7 +29,7 @@ extern Module *rootHasMain;
 struct Compiler
 {
     // CTFE support for cross-compilation.
-    static Expression *paintAsType(Expression *, Type *);
+    static Expression *paintAsType(UnionExp *, Expression *, Type *);
     // Backend
     static void loadModule(Module *);
     static void genCmain(Scope *);
diff --git a/gcc/d/dmd/constfold.c b/gcc/d/dmd/constfold.c
index 83f0f3ef14f..ddd356bb966 100644
--- a/gcc/d/dmd/constfold.c
+++ b/gcc/d/dmd/constfold.c
@@ -1457,8 +1457,7 @@ UnionExp Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
             memcpy(elements->tdata(),
                    es1->elements->tdata() + ilwr,
                    (size_t)(iupr - ilwr) * sizeof((*es1->elements)[0]));
-            new(&ue) ArrayLiteralExp(e1->loc, elements);
-            ue.exp()->type = type;
+            new(&ue) ArrayLiteralExp(e1->loc, type, elements);
         }
     }
     else
@@ -1606,6 +1605,7 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
 
             new(&ue) StringExp(loc, s, len);
             StringExp *es = (StringExp *)ue.exp();
+            es->type = type;
             es->sz = sz;
             es->committed = 1;
         }
@@ -1614,9 +1614,8 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
             // Create an ArrayLiteralExp
             Expressions *elements = new Expressions();
             elements->push(e);
-            new(&ue) ArrayLiteralExp(e->loc, elements);
+            new(&ue) ArrayLiteralExp(e->loc, type, elements);
         }
-        ue.exp()->type = type;
         assert(ue.exp()->type);
         return ue;
     }
@@ -1627,8 +1626,7 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
             // Handle null ~= null
             if (t1->ty == Tarray && t2 == t1->nextOf())
             {
-                new(&ue) ArrayLiteralExp(e1->loc, e2);
-                ue.exp()->type = type;
+                new(&ue) ArrayLiteralExp(e1->loc, type, e2);
                 assert(ue.exp()->type);
                 return ue;
             }
@@ -1695,9 +1693,8 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
         {
             (*elems)[i] = ea->getElement(i);
         }
-        new(&ue) ArrayLiteralExp(e1->loc, elems);
+        new(&ue) ArrayLiteralExp(e1->loc, type, elems);
         ArrayLiteralExp *dest = (ArrayLiteralExp *)ue.exp();
-        dest->type = type;
         sliceAssignArrayLiteralFromString(dest, es, ea->elements->dim);
         assert(ue.exp()->type);
         return ue;
@@ -1715,9 +1712,8 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
         {
             (*elems)[es->len + i] = ea->getElement(i);
         }
-        new(&ue) ArrayLiteralExp(e1->loc, elems);
+        new(&ue) ArrayLiteralExp(e1->loc, type, elems);
         ArrayLiteralExp *dest = (ArrayLiteralExp *)ue.exp();
-        dest->type = type;
         sliceAssignArrayLiteralFromString(dest, es, 0);
         assert(ue.exp()->type);
         return ue;
@@ -1783,7 +1779,7 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
         // Concatenate the arrays
         Expressions *elems = ArrayLiteralExp::copyElements(e1, e2);
 
-        new(&ue) ArrayLiteralExp(e1->loc, elems);
+        new(&ue) ArrayLiteralExp(e1->loc, NULL, elems);
 
         e = ue.exp();
         if (type->toBasetype()->ty == Tsarray)
@@ -1809,7 +1805,7 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
         // Concatenate the array with null
         Expressions *elems = ArrayLiteralExp::copyElements(e);
 
-        new(&ue) ArrayLiteralExp(e->loc, elems);
+        new(&ue) ArrayLiteralExp(e->loc, NULL, elems);
 
         e = ue.exp();
         if (type->toBasetype()->ty == Tsarray)
@@ -1829,7 +1825,7 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
             ? ArrayLiteralExp::copyElements(e1) : new Expressions();
         elems->push(e2);
 
-        new(&ue) ArrayLiteralExp(e1->loc, elems);
+        new(&ue) ArrayLiteralExp(e1->loc, NULL, elems);
 
         e = ue.exp();
         if (type->toBasetype()->ty == Tsarray)
@@ -1846,7 +1842,7 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
     {
         Expressions *elems = ArrayLiteralExp::copyElements(e1, e2);
 
-        new(&ue) ArrayLiteralExp(e2->loc, elems);
+        new(&ue) ArrayLiteralExp(e2->loc, NULL, elems);
 
         e = ue.exp();
         if (type->toBasetype()->ty == Tsarray)
@@ -1874,9 +1870,8 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2)
         {
             Expressions *expressions = new Expressions();
             expressions->push(e);
-            new(&ue) ArrayLiteralExp(loc, expressions);
+            new(&ue) ArrayLiteralExp(loc, t, expressions);
             e = ue.exp();
-            e->type = t;
         }
         else
         {
diff --git a/gcc/d/dmd/ctfe.h b/gcc/d/dmd/ctfe.h
index 2c6a47440a8..0e49432e1b6 100644
--- a/gcc/d/dmd/ctfe.h
+++ b/gcc/d/dmd/ctfe.h
@@ -134,6 +134,7 @@ UnionExp copyLiteral(Expression *e);
 
 /// Set this literal to the given type, copying it if necessary
 Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
+Expression *paintTypeOntoLiteral(UnionExp *pue, Type *type, Expression *lit);
 UnionExp paintTypeOntoLiteralCopy(Type *type, Expression *lit);
 
 /// Convert from a CTFE-internal slice, into a normal Expression
@@ -143,11 +144,11 @@ Expression *resolveSlice(Expression *e, UnionExp *pue = NULL);
 uinteger_t resolveArrayLength(Expression *e);
 
 /// Create an array literal consisting of 'elem' duplicated 'dim' times.
-ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
+ArrayLiteralExp *createBlockDuplicatedArrayLiteral(UnionExp *pue, Loc loc, Type *type,
         Expression *elem, size_t dim);
 
 /// Create a string literal consisting of 'value' duplicated 'dim' times.
-StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
+StringExp *createBlockDuplicatedStringLiteral(UnionExp *pue, Loc loc, Type *type,
         unsigned value, size_t dim, unsigned char sz);
 
 
@@ -209,7 +210,7 @@ UnionExp pointerArithmetic(Loc loc, TOK op, Type *type,
 bool isFloatIntPaint(Type *to, Type *from);
 
 // Reinterpret float/int value 'fromVal' as a float/integer of type 'to'.
-Expression *paintFloatInt(Expression *fromVal, Type *to);
+Expression *paintFloatInt(UnionExp *pue, Expression *fromVal, Type *to);
 
 /// Return true if t is an AA
 bool isAssocArray(Type *t);
@@ -264,4 +265,4 @@ UnionExp ctfeCat(Loc loc, Type *type, Expression *e1, Expression *e2);
 Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx);
 
 /// Cast 'e' of type 'type' to type 'to'.
-Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e);
+Expression *ctfeCast(UnionExp *pue, Loc loc, Type *type, Type *to, Expression *e);
diff --git a/gcc/d/dmd/ctfeexpr.c b/gcc/d/dmd/ctfeexpr.c
index 713e0f9ff7d..1050e93699e 100644
--- a/gcc/d/dmd/ctfeexpr.c
+++ b/gcc/d/dmd/ctfeexpr.c
@@ -264,10 +264,9 @@ UnionExp copyLiteral(Expression *e)
         ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
         Expressions *elements = copyLiteralArray(ale->elements, ale->basis);
 
-        new(&ue) ArrayLiteralExp(e->loc, elements);
+        new(&ue) ArrayLiteralExp(e->loc, e->type, elements);
 
         ArrayLiteralExp *r = (ArrayLiteralExp *)ue.exp();
-        r->type = e->type;
         r->ownedByCtfe = OWNEDctfe;
         return ue;
     }
@@ -314,7 +313,10 @@ UnionExp copyLiteral(Expression *e)
                 {
                     TypeSArray *tsa = (TypeSArray *)v->type;
                     size_t len = (size_t)tsa->dim->toInteger();
-                    m = createBlockDuplicatedArrayLiteral(e->loc, v->type, m, len);
+                    UnionExp uex;
+                    m = createBlockDuplicatedArrayLiteral(&uex, e->loc, v->type, m, len);
+                    if (m == uex.exp())
+                        m = uex.copy();
                 }
             }
             (*newelems)[i] = m;
@@ -414,6 +416,14 @@ Expression *paintTypeOntoLiteral(Type *type, Expression *lit)
     return paintTypeOntoLiteralCopy(type, lit).copy();
 }
 
+Expression *paintTypeOntoLiteral(UnionExp *pue, Type *type, Expression *lit)
+{
+    if (lit->type->equals(type))
+        return lit;
+    *pue = paintTypeOntoLiteralCopy(type, lit);
+    return pue->exp();
+}
+
 UnionExp paintTypeOntoLiteralCopy(Type *type, Expression *lit)
 {
     UnionExp ue;
@@ -539,6 +549,7 @@ uinteger_t resolveArrayLength(Expression *e)
  * Helper for NewExp
  * Create an array literal consisting of 'elem' duplicated 'dim' times.
  * Params:
+ *      pue = where to store result
  *      loc = source location where the interpretation occurs
  *      type = target type of the result
  *      elem = the source of array element, it will be owned by the result
@@ -546,7 +557,7 @@ uinteger_t resolveArrayLength(Expression *e)
  * Returns:
  *      Constructed ArrayLiteralExp
  */
-ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
+ArrayLiteralExp *createBlockDuplicatedArrayLiteral(UnionExp *pue, Loc loc, Type *type,
         Expression *elem, size_t dim)
 {
     if (type->ty == Tsarray && type->nextOf()->ty == Tsarray && elem->type->ty != Tsarray)
@@ -554,7 +565,10 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
         // If it is a multidimensional array literal, do it recursively
         TypeSArray *tsa = (TypeSArray *)type->nextOf();
         size_t len = (size_t)tsa->dim->toInteger();
-        elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem, len);
+        UnionExp ue;
+        elem = createBlockDuplicatedArrayLiteral(&ue, loc, type->nextOf(), elem, len);
+        if (elem == ue.exp())
+            elem = ue.copy();
     }
 
     // Buzilla 15681
@@ -567,8 +581,8 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
     {
         (*elements)[i] = mustCopy ? copyLiteral(elem).copy() : elem;
     }
-    ArrayLiteralExp *ale = new ArrayLiteralExp(loc, elements);
-    ale->type = type;
+    new(pue) ArrayLiteralExp(loc, type, elements);
+    ArrayLiteralExp *ale = (ArrayLiteralExp *)pue->exp();
     ale->ownedByCtfe = OWNEDctfe;
     return ale;
 }
@@ -577,7 +591,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
  * Helper for NewExp
  * Create a string literal consisting of 'value' duplicated 'dim' times.
  */
-StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
+StringExp *createBlockDuplicatedStringLiteral(UnionExp *pue, Loc loc, Type *type,
         unsigned value, size_t dim, unsigned char sz)
 {
     utf8_t *s = (utf8_t *)mem.xcalloc(dim + 1, sz);
@@ -591,7 +605,8 @@ StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
             default:    assert(0);
         }
     }
-    StringExp *se = new StringExp(loc, s, dim);
+    new(pue) StringExp(loc, s, dim);
+    StringExp *se = (StringExp *)pue->exp();
     se->type = type;
     se->sz = sz;
     se->committed = true;
@@ -984,13 +999,13 @@ bool isFloatIntPaint(Type *to, Type *from)
 }
 
 // Reinterpret float/int value 'fromVal' as a float/integer of type 'to'.
-Expression *paintFloatInt(Expression *fromVal, Type *to)
+Expression *paintFloatInt(UnionExp *pue, Expression *fromVal, Type *to)
 {
     if (exceptionOrCantInterpret(fromVal))
         return fromVal;
 
     assert(to->size() == 4 || to->size() == 8);
-    return Compiler::paintAsType(fromVal, to);
+    return Compiler::paintAsType(pue, fromVal, to);
 }
 
 /******** Constant folding, with support for CTFE ***************************/
@@ -1512,10 +1527,9 @@ UnionExp ctfeCat(Loc loc, Type *type, Expression *e1, Expression *e2)
         ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
         ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
 
-        new(&ue) ArrayLiteralExp(es1->loc, copyLiteralArray(es1->elements));
+        new(&ue) ArrayLiteralExp(es1->loc, type, copyLiteralArray(es1->elements));
         es1 = (ArrayLiteralExp *)ue.exp();
         es1->elements->insert(es1->elements->dim, copyLiteralArray(es2->elements));
-        es1->type = type;
         return ue;
     }
     if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
@@ -1587,29 +1601,33 @@ Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx)
     }
 }
 
-Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e)
+Expression *ctfeCast(UnionExp *pue, Loc loc, Type *type, Type *to, Expression *e)
 {
     if (e->op == TOKnull)
-        return paintTypeOntoLiteral(to, e);
+        return paintTypeOntoLiteral(pue, to, e);
+
     if (e->op == TOKclassreference)
     {
         // Disallow reinterpreting class casts. Do this by ensuring that
         // the original class can implicitly convert to the target class
         ClassDeclaration *originalClass = ((ClassReferenceExp *)e)->originalClass();
         if (originalClass->type->implicitConvTo(to->mutableOf()))
-            return paintTypeOntoLiteral(to, e);
+            return paintTypeOntoLiteral(pue, to, e);
         else
-            return new NullExp(loc, to);
+        {
+            new(pue) NullExp(loc, to);
+            return pue->exp();
+        }
     }
+
     // Allow TypeInfo type painting
     if (isTypeInfo_Class(e->type) && e->type->implicitConvTo(to))
-        return paintTypeOntoLiteral(to, e);
+        return paintTypeOntoLiteral(pue, to, e);
+
     // Allow casting away const for struct literals
     if (e->op == TOKstructliteral &&
         e->type->toBasetype()->castMod(0) == to->toBasetype()->castMod(0))
-    {
-        return paintTypeOntoLiteral(to, e);
-    }
+        return paintTypeOntoLiteral(pue, to, e);
 
     Expression *r;
     if (e->type->equals(type) && type->equals(to))
@@ -1617,22 +1635,28 @@ Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e)
         // necessary not to change e's address for pointer comparisons
         r = e;
     }
-    else if (to->toBasetype()->ty == Tarray &&     type->toBasetype()->ty == Tarray &&
+    else if (to->toBasetype()->ty == Tarray &&
+             type->toBasetype()->ty == Tarray &&
              to->toBasetype()->nextOf()->size() == type->toBasetype()->nextOf()->size())
     {
         // Bugzilla 12495: Array reinterpret casts: eg. string to immutable(ubyte)[]
-        return paintTypeOntoLiteral(to, e);
+        return paintTypeOntoLiteral(pue, to, e);
     }
     else
     {
-        r = Cast(loc, type, to, e).copy();
+        *pue = Cast(loc, type, to, e);
+        r = pue->exp();
     }
+
     if (CTFEExp::isCantExp(r))
         error(loc, "cannot cast %s to %s at compile time", e->toChars(), to->toChars());
+
     if (e->op == TOKarrayliteral)
         ((ArrayLiteralExp *)e)->ownedByCtfe = OWNEDctfe;
+
     if (e->op == TOKstring)
         ((StringExp *)e)->ownedByCtfe = OWNEDctfe;
+
     return r;
 }
 
@@ -1816,9 +1840,8 @@ UnionExp changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
             for (size_t i = copylen; i < newlen; i++)
                 (*elements)[i] = defaultElem;
         }
-        new(&ue) ArrayLiteralExp(loc, elements);
+        new(&ue) ArrayLiteralExp(loc, arrayType, elements);
         ArrayLiteralExp *aae = (ArrayLiteralExp *)ue.exp();
-        aae->type = arrayType;
         aae->ownedByCtfe = OWNEDctfe;
     }
     return ue;
@@ -2078,9 +2101,8 @@ UnionExp voidInitLiteral(Type *t, VarDeclaration *var)
                 elem  = copyLiteral(elem).copy();
             (*elements)[i] = elem;
         }
-        new(&ue) ArrayLiteralExp(var->loc, elements);
+        new(&ue) ArrayLiteralExp(var->loc, tsa, elements);
         ArrayLiteralExp *ae = (ArrayLiteralExp *)ue.exp();
-        ae->type = tsa;
         ae->ownedByCtfe = OWNEDctfe;
     }
     else if (t->ty == Tstruct)
diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c
index 7c497d8958a..140abfdd7e9 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -264,14 +264,18 @@ void printCtfePerformanceStats()
 #endif
 }
 
-VarDeclaration *findParentVar(Expression *e);
-Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
+static Expression *evaluateIfBuiltin(UnionExp *pue, InterState *istate, Loc loc,
     FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
-Expression *evaluatePostblit(InterState *istate, Expression *e);
-Expression *evaluateDtor(InterState *istate, Expression *e);
-Expression *scrubReturnValue(Loc loc, Expression *e);
+static Expression *evaluatePostblit(InterState *istate, Expression *e);
+static Expression *evaluateDtor(InterState *istate, Expression *e);
 
-Expression *scrubCacheValue(Loc loc, Expression *e);
+static bool isEntirelyVoid(Expressions* elems);
+static Expression *scrubArray(Loc loc, Expressions *elems, bool structlit = false);
+static Expression *scrubStructLiteral(Loc loc, StructLiteralExp *sle);
+static Expression *scrubReturnValue(Loc loc, Expression *e);
+static Expression *scrubArrayCache(Expressions *elems);
+static Expression *scrubStructLiteralCache(StructLiteralExp *sle);
+static Expression *scrubCacheValue(Expression *e);
 
 
 /*************************************
@@ -635,8 +639,24 @@ void ctfeCompile(FuncDeclaration *fd)
  */
 Expression *ctfeInterpret(Expression *e)
 {
-    if (e->op == TOKerror)
+    switch (e->op)
+    {
+    case TOKint64:
+    case TOKfloat64:
+    case TOKcomplex80:
+    case TOKnull:
+    case TOKstring:
+        if (e->type->ty == Terror)
+            return new ErrorExp();
+        /* fall through */
+
+    case TOKerror:
         return e;
+
+    default:
+        break;
+    }
+
     assert(e->type);                    // Bugzilla 14642
     //assert(e->type->ty != Terror);    // FIXME
     if (e->type->ty == Terror)
@@ -710,6 +730,8 @@ Expression *ctfeInterpretForPragmaMsg(Expression *e)
 /*************************************
  * Attempt to interpret a function given the arguments.
  * Input:
+ *      pue        storage for result
+ *      fd         function being called
  *      istate     state for calling function (NULL if none)
  *      arguments  function arguments
  *      thisarg    'this', if a needThis() function, NULL if not.
@@ -718,8 +740,9 @@ Expression *ctfeInterpretForPragmaMsg(Expression *e)
  * or CTFEExp if function returned void.
  */
 
-static Expression *interpretFunction(FuncDeclaration *fd, InterState *istate, Expressions *arguments, Expression *thisarg)
+static Expression *interpretFunction(UnionExp *pue, FuncDeclaration *fd, InterState *istate, Expressions *arguments, Expression *thisarg)
 {
+    assert(pue);
     if (fd->semanticRun == PASSsemantic3)
     {
         fd->error("circular dependency. Functions cannot be interpreted while being compiled");
@@ -898,7 +921,7 @@ static Expression *interpretFunction(FuncDeclaration *fd, InterState *istate, Ex
             e = CTFEExp::cantexp;
             break;
         }
-        e = interpret(fd->fbody, &istatex);
+        e = interpret(pue, fd->fbody, &istatex);
 
         if (istatex.start)
         {
@@ -938,6 +961,8 @@ static Expression *interpretFunction(FuncDeclaration *fd, InterState *istate, Ex
     // If it generated an uncaught exception, report error.
     if (!istate && e->op == TOKthrownexception)
     {
+        if (e == pue->exp())
+            e = pue->copy();
         ((ThrownExceptionExp *)e)->generateUncaughtError();
         e = CTFEExp::cantexp;
     }
@@ -2004,7 +2029,8 @@ public:
         {
             // Normally this is already done by optimize()
             // Do it here in case optimize(WANTvalue) wasn't run before CTFE
-            result = new SymOffExp(e->loc, ((VarExp *)e->e1)->var, 0);
+            new(pue) SymOffExp(e->loc, ((VarExp *)e->e1)->var, 0);
+            result = pue->exp();
             result->type = e->type;
             return;
         }
@@ -2032,7 +2058,7 @@ public:
             return;
         }
 
-        Expression *er = interpret(e->e1, istate);
+        Expression *er = interpret(pue, e->e1, istate);
         if (exceptionOrCant(er))
             return;
         if (er == e->e1)
@@ -2042,6 +2068,7 @@ public:
         }
         else
         {
+            er = (er == pue->exp()) ? pue->copy() : er;
             new(pue) DelegateExp(e->loc, er, e->func, false);
             result = pue->exp();
             result->type = e->type;
@@ -2100,7 +2127,7 @@ public:
                     /* Bugzilla 14304: e is a value that is not yet owned by CTFE.
                      * Mark as "cached", and use it directly during interpretation.
                      */
-                    e = scrubCacheValue(v->loc, e);
+                    e = scrubCacheValue(e);
                     ctfeStack.saveGlobalConstant(v, e);
                 }
                 else
@@ -2236,7 +2263,7 @@ public:
              *  foo(s); // VarExp('s') will have const(S)
              */
             // A VarExp may include an implicit cast. It must be done explicitly.
-            result = paintTypeOntoLiteral(e->type, result);
+            result = paintTypeOntoLiteral(pue, e->type, result);
         }
     }
 
@@ -2363,7 +2390,7 @@ public:
         }
         if (Expression *ex = isExpression(e->obj))
         {
-            result = interpret(ex, istate);
+            result = interpret(pue, ex, istate);
             if (exceptionOrCant(ex))
                 return;
 
@@ -2493,9 +2520,8 @@ public:
                 result = CTFEExp::cantexp;
                 return;
             }
-            new(pue) ArrayLiteralExp(e->loc, basis, expsx);
+            new(pue) ArrayLiteralExp(e->loc, e->type, basis, expsx);
             ArrayLiteralExp *ale = (ArrayLiteralExp *)pue->exp();
-            ale->type = e->type;
             ale->ownedByCtfe = OWNEDctfe;
             result = ale;
         }
@@ -2505,7 +2531,10 @@ public:
             result = e;
         }
         else
-            result = copyLiteral(e).copy();
+        {
+            *pue = copyLiteral(e);
+            result = pue->exp();
+        }
     }
 
     void visit(AssocArrayLiteralExp *e)
@@ -2585,7 +2614,10 @@ public:
             result = ae;
         }
         else
-            result = copyLiteral(e).copy();
+        {
+            *pue = copyLiteral(e);
+            result = pue->exp();
+        }
     }
 
     void visit(StructLiteralExp *e)
@@ -2635,7 +2667,10 @@ public:
                     // Block assignment from inside struct literals
                     TypeSArray *tsa = (TypeSArray *)v->type;
                     size_t len = (size_t)tsa->dim->toInteger();
-                    ex = createBlockDuplicatedArrayLiteral(ex->loc, v->type, ex, len);
+                    UnionExp ue;
+                    ex = createBlockDuplicatedArrayLiteral(&ue, ex->loc, v->type, ex, len);
+                    if (ex == ue.exp())
+                        ex = ue.copy();
                 }
             }
 
@@ -2665,22 +2700,25 @@ public:
             result = sle;
         }
         else
-            result = copyLiteral(e).copy();
+        {
+            *pue = copyLiteral(e);
+            result = pue->exp();
+        }
     }
 
     // Create an array literal of type 'newtype' with dimensions given by
     // 'arguments'[argnum..$]
-    static Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *istate,
+    static Expression *recursivelyCreateArrayLiteral(UnionExp *pue, Loc loc, Type *newtype, InterState *istate,
         Expressions *arguments, int argnum)
     {
-        Expression *lenExpr = interpret((*arguments)[argnum], istate);
+        Expression *lenExpr = interpret(pue, (*arguments)[argnum], istate);
         if (exceptionOrCantInterpret(lenExpr))
             return lenExpr;
         size_t len = (size_t)(lenExpr->toInteger());
         Type *elemType = ((TypeArray *)newtype)->next;
         if (elemType->ty == Tarray && argnum < (int)arguments->dim - 1)
         {
-            Expression *elem = recursivelyCreateArrayLiteral(loc, elemType, istate,
+            Expression *elem = recursivelyCreateArrayLiteral(pue, loc, elemType, istate,
                 arguments, argnum + 1);
             if (exceptionOrCantInterpret(elem))
                 return elem;
@@ -2689,8 +2727,8 @@ public:
             elements->setDim(len);
             for (size_t i = 0; i < len; i++)
                  (*elements)[i] = copyLiteral(elem).copy();
-            ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements);
-            ae->type = newtype;
+            new(pue) ArrayLiteralExp(loc, newtype, elements);
+            ArrayLiteralExp *ae = (ArrayLiteralExp *)pue->exp();
             ae->ownedByCtfe = OWNEDctfe;
             return ae;
         }
@@ -2699,12 +2737,12 @@ public:
         {
             const unsigned ch = (unsigned)elemType->defaultInitLiteral(loc)->toInteger();
             const unsigned char sz = (unsigned char)elemType->size();
-            return createBlockDuplicatedStringLiteral(loc, newtype, ch, len, sz);
+            return createBlockDuplicatedStringLiteral(pue, loc, newtype, ch, len, sz);
         }
         else
         {
             Expression *el = interpret(elemType->defaultInitLiteral(loc), istate);
-            return createBlockDuplicatedArrayLiteral(loc, newtype, el, len);
+            return createBlockDuplicatedArrayLiteral(pue, loc, newtype, el, len);
         }
     }
 
@@ -2717,13 +2755,13 @@ public:
             return;
         }
 
-        result = interpret(e->argprefix, istate, ctfeNeedNothing);
-        if (exceptionOrCant(result))
+        Expression *epre = interpret(pue, e->argprefix, istate, ctfeNeedNothing);
+        if (exceptionOrCant(epre))
             return;
 
         if (e->newtype->ty == Tarray && e->arguments)
         {
-            result = recursivelyCreateArrayLiteral(e->loc, e->newtype, istate, e->arguments, 0);
+            result = recursivelyCreateArrayLiteral(pue, e->loc, e->newtype, istate, e->arguments, 0);
             return;
         }
         if (e->newtype->toBasetype()->ty == Tstruct)
@@ -2734,7 +2772,7 @@ public:
                 se = interpret(se, istate);
                 if (exceptionOrCant(se))
                     return;
-                result = interpretFunction(e->member, istate, e->arguments, se);
+                result = interpretFunction(pue, e->member, istate, e->arguments, se);
 
                 // Repaint as same as CallExp::interpret() does.
                 result->loc = e->loc;
@@ -2761,11 +2799,12 @@ public:
                 StructLiteralExp *se = new StructLiteralExp(e->loc, sd, exps, e->newtype);
                 se->type = e->newtype;
                 se->ownedByCtfe = OWNEDctfe;
-                result = interpret(se, istate);
+                result = interpret(pue, se, istate);
             }
             if (exceptionOrCant(result))
                 return;
-            new(pue) AddrExp(e->loc, result, e->type);
+            Expression *ev = (result == pue->exp()) ? pue->copy() : result;
+            new(pue) AddrExp(e->loc, ev, e->type);
             result = pue->exp();
             return;
         }
@@ -2809,13 +2848,14 @@ public:
             // We probably won't get away with this.
             StructLiteralExp *se = new StructLiteralExp(e->loc, (StructDeclaration *)cd, elems, e->newtype);
             se->ownedByCtfe = OWNEDctfe;
-            Expression *eref = new ClassReferenceExp(e->loc, se, e->type);
+            new(pue) ClassReferenceExp(e->loc, se, e->type);
+            Expression *eref = pue->exp();
             if (e->member)
             {
                 // Call constructor
                 if (!e->member->fbody)
                 {
-                    Expression *ctorfail = evaluateIfBuiltin(istate, e->loc, e->member, e->arguments, eref);
+                    Expression *ctorfail = evaluateIfBuiltin(pue, istate, e->loc, e->member, e->arguments, eref);
                     if (ctorfail)
                     {
                         if (exceptionOrCant(ctorfail))
@@ -2827,7 +2867,8 @@ public:
                     result = CTFEExp::cantexp;
                     return;
                 }
-                Expression *ctorfail = interpretFunction(e->member, istate, e->arguments, eref);
+                UnionExp ue;
+                Expression *ctorfail = interpretFunction(&ue, e->member, istate, e->arguments, eref);
                 if (exceptionOrCant(ctorfail))
                     return;
 
@@ -2855,8 +2896,7 @@ public:
             Expressions *elements = new Expressions();
             elements->setDim(1);
             (*elements)[0] = newval;
-            ArrayLiteralExp *ae = new ArrayLiteralExp(e->loc, elements);
-            ae->type = e->newtype->arrayOf();
+            ArrayLiteralExp *ae = new ArrayLiteralExp(e->loc, e->newtype->arrayOf(), elements);
             ae->ownedByCtfe = OWNEDctfe;
 
             IndexExp *ei = new IndexExp(e->loc, ae, new IntegerExp(Loc(), 0, Type::tsize_t));
@@ -3462,7 +3502,7 @@ public:
             assignAssocArrayElement(e->loc, existingAA, lastIndex, newval);
 
             // Determine the return value
-            result = ctfeCast(e->loc, e->type, e->type, fp && post ? oldval : newval);
+            result = ctfeCast(pue, e->loc, e->type, e->type, fp && post ? oldval : newval);
             return;
         }
         if (e1->op == TOKarraylength)
@@ -3474,10 +3514,13 @@ public:
              */
 
             // Determine the return value
-            result = ctfeCast(e->loc, e->type, e->type, fp && post ? oldval : newval);
+            result = ctfeCast(pue, e->loc, e->type, e->type, fp && post ? oldval : newval);
             if (exceptionOrCant(result))
                 return;
 
+            if (result == pue->exp())
+                result = pue->copy();
+
             size_t oldlen = (size_t)oldval->toInteger();
             size_t newlen = (size_t)newval->toInteger();
             if (oldlen == newlen) // no change required -- we're done!
@@ -3511,15 +3554,21 @@ public:
 
         if (!isBlockAssignment)
         {
-            newval = ctfeCast(e->loc, e->type, e->type, newval);
+            newval = ctfeCast(pue, e->loc, e->type, e->type, newval);
             if (exceptionOrCant(newval))
                 return;
+            if (newval == pue->exp())
+                newval = pue->copy();
 
             // Determine the return value
             if (goal == ctfeNeedLvalue)     // Bugzilla 14371
                 result = e1;
             else
-                result = ctfeCast(e->loc, e->type, e->type, fp && post ? oldval : newval);
+            {
+                result = ctfeCast(pue, e->loc, e->type, e->type, fp && post ? oldval : newval);
+                if (result == pue->exp())
+                    result = pue->copy();
+            }
             if (exceptionOrCant(result))
                 return;
         }
@@ -3536,7 +3585,7 @@ public:
         {
             // Note that slice assignments don't support things like ++, so
             // we don't need to remember 'returnValue'.
-            result = interpretAssignToSlice(e, e1, newval, isBlockAssignment);
+            result = interpretAssignToSlice(pue, e, e1, newval, isBlockAssignment);
             if (exceptionOrCant(result))
                 return;
             if (e->e1->op == TOKslice)
@@ -3781,7 +3830,7 @@ public:
      * it returns aggregate[low..upp], except that as an optimisation,
      * if goal == ctfeNeedNothing, it will return NULL
      */
-    Expression *interpretAssignToSlice(BinExp *e,
+    Expression *interpretAssignToSlice(UnionExp *pue, BinExp *e,
         Expression *e1, Expression *newval, bool isBlockAssignment)
     {
         dinteger_t lowerbound;
@@ -3962,7 +4011,7 @@ public:
                 new IntegerExp(e->loc, firstIndex, Type::tsize_t),
                 new IntegerExp(e->loc, firstIndex + upperbound - lowerbound, Type::tsize_t));
             retslice->type = e->type;
-            return interpret(retslice, istate);
+            return interpret(pue, retslice, istate);
         }
         if (aggregate->op == TOKarrayliteral)
         {
@@ -4178,7 +4227,7 @@ public:
                 new IntegerExp(e->loc, firstIndex, Type::tsize_t),
                 new IntegerExp(e->loc, firstIndex + upperbound - lowerbound, Type::tsize_t));
             retslice->type = e->type;
-            return interpret(retslice, istate);
+            return interpret(pue, retslice, istate);
         }
 
         e->error("slice operation %s = %s cannot be evaluated at compile time",
@@ -4285,7 +4334,7 @@ public:
      *  relational sub-expressions can be negated, eg
      *  (!(q1 < p1) && p2 <= q2) is valid.
      */
-    void interpretFourPointerRelation(BinExp *e)
+    void interpretFourPointerRelation(UnionExp *pue, BinExp *e)
     {
         assert(e->op == TOKandand || e->op == TOKoror);
 
@@ -4311,12 +4360,16 @@ public:
         }
 
         //printf("FourPointerRelation %s\n", toChars());
+        UnionExp ue1;
+        UnionExp ue2;
+        UnionExp ue3;
+        UnionExp ue4;
 
         // Evaluate the first two pointers
-        p1 = interpret(p1, istate);
+        p1 = interpret(&ue1, p1, istate);
         if (exceptionOrCant(p1))
             return;
-        p2 = interpret(p2, istate);
+        p2 = interpret(&ue2, p2, istate);
         if (exceptionOrCant(p2))
             return;
         dinteger_t ofs1, ofs2;
@@ -4329,7 +4382,7 @@ public:
         {
             // Here it is either CANT_INTERPRET,
             // or an IsInside comparison returning false.
-            p3 = interpret(p3, istate);
+            p3 = interpret(&ue3, p3, istate);
             if (CTFEExp::isCantExp(p3))
                 return;
             // Note that it is NOT legal for it to throw an exception!
@@ -4338,7 +4391,7 @@ public:
                 except = p3;
             else
             {
-                p4 = interpret(p4, istate);
+                p4 = interpret(&ue4, p4, istate);
                 if (CTFEExp::isCantExp(p4))
                 {
                     result = p4;
@@ -4367,7 +4420,8 @@ public:
                 (dir1 != dir2 && pointToSameMemoryBlock(agg1, agg3) && pointToSameMemoryBlock(agg2, agg4)))
             {
                 // it's a legal two-sided comparison
-                result = new IntegerExp(e->loc, (e->op == TOKandand) ?  0 : 1, e->type);
+                new(pue) IntegerExp(e->loc, (e->op == TOKandand) ?  0 : 1, e->type);
+                result = pue->exp();
                 return;
             }
             // It's an invalid four-pointer comparison. Either the second
@@ -4393,25 +4447,24 @@ public:
             nott = !nott;
             ex = ((NotExp *)ex)->e1;
         }
-        TOK cmpop = ex->op;
-        if (nott)
-            cmpop = reverseRelation(cmpop);
-        int cmp = comparePointers(cmpop, agg1, ofs1, agg2, ofs2);
+        const TOK cmpop = nott ? reverseRelation(ex->op) : ex->op;
+        const int cmp = comparePointers(cmpop, agg1, ofs1, agg2, ofs2);
         // We already know this is a valid comparison.
         assert(cmp >= 0);
         if ((e->op == TOKandand && cmp == 1) ||
             (e->op == TOKoror   && cmp == 0))
         {
-            result = interpret(e->e2, istate);
+            result = interpret(pue, e->e2, istate);
             return;
         }
-        result = new IntegerExp(e->loc, (e->op == TOKandand) ? 0 : 1, e->type);
+        new(pue) IntegerExp(e->loc, (e->op == TOKandand) ? 0 : 1, e->type);
+        result = pue->exp();
     }
 
     void visit(AndAndExp *e)
     {
         // Check for an insidePointer expression, evaluate it if so
-        interpretFourPointerRelation(e);
+        interpretFourPointerRelation(pue, e);
         if (result)
             return;
 
@@ -4461,7 +4514,7 @@ public:
     void visit(OrOrExp *e)
     {
         // Check for an insidePointer expression, evaluate it if so
-        interpretFourPointerRelation(e);
+        interpretFourPointerRelation(pue, e);
         if (result)
             return;
 
@@ -4695,7 +4748,7 @@ public:
         }
 
         // Check for built-in functions
-        result = evaluateIfBuiltin(istate, e->loc, fd, e->arguments, pthis);
+        result = evaluateIfBuiltin(pue, istate, e->loc, fd, e->arguments, pthis);
         if (result)
             return;
 
@@ -4707,13 +4760,17 @@ public:
             return;
         }
 
-        result = interpretFunction(fd, istate, e->arguments, pthis);
+        result = interpretFunction(pue, fd, istate, e->arguments, pthis);
         if (result->op == TOKvoidexp)
             return;
         if (!exceptionOrCantInterpret(result))
         {
-            if (goal != ctfeNeedLvalue) // Peel off CTFE reference if it's unnesessary
-                result = interpret(result, istate);
+            if (goal != ctfeNeedLvalue) // Peel off CTFE reference if it's unnecessary
+            {
+                if (result == pue->exp())
+                    result = pue->copy();
+                result = interpret(pue, result, istate);
+            }
         }
         if (!exceptionOrCantInterpret(result))
         {
@@ -5306,17 +5363,37 @@ public:
 
     void visit(CatExp *e)
     {
-        Expression *e1 = interpret(e->e1, istate);
+        UnionExp ue1;
+        Expression *e1 = interpret(&ue1, e->e1, istate);
         if (exceptionOrCant(e1))
             return;
-        Expression *e2 = interpret(e->e2, istate);
+
+        UnionExp ue2;
+        Expression *e2 = interpret(&ue2, e->e2, istate);
         if (exceptionOrCant(e2))
             return;
+
         UnionExp e1tmp;
         e1 = resolveSlice(e1, &e1tmp);
+
         UnionExp e2tmp;
         e2 = resolveSlice(e2, &e2tmp);
-        result = ctfeCat(e->loc, e->type, e1, e2).copy();
+
+        /* e1 and e2 can't go on the stack because of x~[y] and [x]~y will
+         * result in [x,y] and then x or y is on the stack.
+         * But if they are both strings, we can, because it isn't the x~[y] case.
+         */
+        if (!(e1->op == TOKstring && e2->op == TOKstring))
+        {
+            if (e1 == ue1.exp())
+                e1 = ue1.copy();
+            if (e2 == ue2.exp())
+                e2 = ue2.copy();
+        }
+
+        *pue = ctfeCat(e->loc, e->type, e1, e2);
+        result = pue->exp();
+
         if (CTFEExp::isCantExp(result))
         {
             e->error("%s cannot be interpreted at compile time", e->toChars());
@@ -5375,7 +5452,7 @@ public:
 
             if (cd->dtor)
             {
-                result = interpretFunction(cd->dtor, istate, NULL, cre);
+                result = interpretFunction(pue, cd->dtor, istate, NULL, cre);
                 if (exceptionOrCant(result))
                     return;
             }
@@ -5406,7 +5483,7 @@ public:
 
                 if (sd->dtor)
                 {
-                    result = interpretFunction(sd->dtor, istate, NULL, sle);
+                    result = interpretFunction(pue, sd->dtor, istate, NULL, sle);
                     if (exceptionOrCant(result))
                         return;
                 }
@@ -5440,7 +5517,7 @@ public:
                     for (size_t i = 0; i < ale->elements->dim; i++)
                     {
                         Expression *el = (*ale->elements)[i];
-                        result = interpretFunction(sd->dtor, istate, NULL, el);
+                        result = interpretFunction(pue, sd->dtor, istate, NULL, el);
                         if (exceptionOrCant(result))
                             return;
                     }
@@ -5473,7 +5550,7 @@ public:
             if (e1->op == TOKint64)
             {
                 // Happens with Windows HANDLEs, for example.
-                result = paintTypeOntoLiteral(e->to, e1);
+                result = paintTypeOntoLiteral(pue, e->to, e1);
                 return;
             }
             bool castToSarrayPointer = false;
@@ -5516,13 +5593,14 @@ public:
 
             if (e1->op == TOKslice)
             {
-                if (((SliceExp *)e1)->e1->op == TOKnull)
+                SliceExp *se = (SliceExp *)e1;
+                if (se->e1->op == TOKnull)
                 {
-                    result = paintTypeOntoLiteral(e->type, ((SliceExp *)e1)->e1);
+                    result = paintTypeOntoLiteral(pue, e->type, se->e1);
                     return;
                 }
                 // Create a CTFE pointer &aggregate[1..2]
-                IndexExp *ei = new IndexExp(e->loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr);
+                IndexExp *ei = new IndexExp(e->loc, se->e1, se->lwr);
                 ei->type = e->type->nextOf();
                 new(pue) AddrExp(e->loc, ei, e->type);
                 result = pue->exp();
@@ -5541,7 +5619,6 @@ public:
             {
                 // type painting operation
                 IndexExp *ie = (IndexExp *)e1;
-                result = new IndexExp(e1->loc, ie->e1, ie->e2);
                 if (castBackFromVoid)
                 {
                     // get the original type. For strings, it's just the type...
@@ -5550,7 +5627,7 @@ public:
                     if (ie->e1->op == TOKarrayliteral && ie->e2->op == TOKint64)
                     {
                         ArrayLiteralExp *ale = (ArrayLiteralExp *)ie->e1;
-                        size_t indx = (size_t)ie->e2->toInteger();
+                        const size_t indx = (size_t)ie->e2->toInteger();
                         if (indx < ale->elements->dim)
                         {
                             Expression *xx = (*ale->elements)[indx];
@@ -5572,23 +5649,26 @@ public:
                         return;
                     }
                 }
+                new(pue) IndexExp(e1->loc, ie->e1, ie->e2);
+                result = pue->exp();
                 result->type = e->type;
                 return;
             }
             if (e1->op == TOKaddress)
             {
-                Type *origType = ((AddrExp *)e1)->e1->type;
+                AddrExp *ae = (AddrExp *)e1;
+                Type *origType = ae->e1->type;
                 if (isSafePointerCast(origType, pointee))
                 {
-                    new(pue) AddrExp(e->loc, ((AddrExp *)e1)->e1, e->type);
+                    new(pue) AddrExp(e->loc, ae->e1, e->type);
                     result = pue->exp();
                     return;
                 }
-                if (castToSarrayPointer && pointee->toBasetype()->ty == Tsarray && ((AddrExp *)e1)->e1->op == TOKindex)
+                if (castToSarrayPointer && pointee->toBasetype()->ty == Tsarray && ae->e1->op == TOKindex)
                 {
                     // &val[idx]
                     dinteger_t dim = ((TypeSArray *)pointee->toBasetype())->dim->toInteger();
-                    IndexExp *ie = (IndexExp *)((AddrExp *)e1)->e1;
+                    IndexExp *ie = (IndexExp *)ae->e1;
                     Expression *lwr = ie->e2;
                     Expression *upr = new IntegerExp(ie->e2->loc, ie->e2->toInteger() + dim, Type::tsize_t);
 
@@ -5669,7 +5749,7 @@ public:
             result = pue->exp();
             return;
         }
-        result = ctfeCast(e->loc, e->type, e->to, e1);
+        result = ctfeCast(pue, e->loc, e->type, e->to, e1);
     }
 
     void visit(AssertExp *e)
@@ -5708,20 +5788,30 @@ public:
     void visit(PtrExp *e)
     {
         // Check for int<->float and long<->double casts.
-        if (e->e1->op == TOKsymoff && ((SymOffExp *)e->e1)->offset == 0 && ((SymOffExp *)e->e1)->var->isVarDeclaration() && isFloatIntPaint(e->type, ((SymOffExp *)e->e1)->var->type))
+        if (e->e1->op == TOKsymoff)
         {
-            // *(cast(int*)&v), where v is a float variable
-            result = paintFloatInt(getVarExp(e->loc, istate, ((SymOffExp *)e->e1)->var, ctfeNeedRvalue), e->type);
-            return;
+            SymOffExp *soe = (SymOffExp *)e->e1;
+            if (soe->offset == 0 && soe->var->isVarDeclaration() && isFloatIntPaint(e->type, soe->var->type))
+            {
+                // *(cast(int*)&v), where v is a float variable
+                result = paintFloatInt(pue, getVarExp(e->loc, istate, soe->var, ctfeNeedRvalue), e->type);
+                return;
+            }
         }
-        if (e->e1->op == TOKcast && ((CastExp *)e->e1)->e1->op == TOKaddress)
+
+        if (e->e1->op == TOKcast)
         {
-            // *(cast(int*)&x), where x is a float expression
-            Expression *x = ((AddrExp *)(((CastExp *)e->e1)->e1))->e1;
-            if (isFloatIntPaint(e->type, x->type))
+            CastExp *ce1 = (CastExp *)e->e1;
+            if (ce1->e1->op == TOKaddress)
             {
-                result = paintFloatInt(interpret(x, istate), e->type);
-                return;
+                AddrExp *ae11 = (AddrExp *)ce1->e1;
+                // *(cast(int*)&x), where x is a float expression
+                Expression *x = ae11->e1;
+                if (isFloatIntPaint(e->type, x->type))
+                {
+                    result = paintFloatInt(pue, interpret(x, istate), e->type);
+                    return;
+                }
             }
         }
 
@@ -5785,7 +5875,7 @@ public:
              */
             return;
         }
-        result = interpret(result, istate, goal);
+        result = interpret(pue, result, istate, goal);
         if (exceptionOrCant(result))
             return;
     }
@@ -5898,7 +5988,10 @@ public:
             // Block assignment from inside struct literals
             TypeSArray *tsa = (TypeSArray *)v->type;
             size_t len = (size_t)tsa->dim->toInteger();
-            result = createBlockDuplicatedArrayLiteral(ex->loc, v->type, ex, len);
+            UnionExp ue;
+            result = createBlockDuplicatedArrayLiteral(&ue, ex->loc, v->type, ex, len);
+            if (result == ue.exp())
+                result = ue.copy();
             (*se->elements)[i] = result;
         }
     }
@@ -6022,57 +6115,47 @@ Expression *interpret(Statement *s, InterState *istate)
     return result;
 }
 
-Expression *scrubArray(Loc loc, Expressions *elems, bool structlit = false);
-
-/* All results destined for use outside of CTFE need to have their CTFE-specific
+/**
+ * All results destined for use outside of CTFE need to have their CTFE-specific
  * features removed.
- * In particular, all slices must be resolved.
+ * In particular,
+ * 1. all slices must be resolved.
+ * 2. all .ownedByCtfe set to OWNEDcode
  */
 Expression *scrubReturnValue(Loc loc, Expression *e)
 {
     if (e->op == TOKclassreference)
     {
-        StructLiteralExp *se = ((ClassReferenceExp*)e)->value;
-        se->ownedByCtfe = OWNEDcode;
-        if (!(se->stageflags & stageScrub))
-        {
-            int old = se->stageflags;
-            se->stageflags |= stageScrub;
-            if (Expression *ex = scrubArray(loc, se->elements, true))
-                return ex;
-            se->stageflags = old;
-        }
+        StructLiteralExp *sle = ((ClassReferenceExp*)e)->value;
+        if (Expression *ex = scrubStructLiteral(loc, sle))
+            return ex;
     }
-    if (e->op == TOKvoid)
+    else if (e->op == TOKvoid)
     {
         error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars());
         return new ErrorExp();
     }
+
     e = resolveSlice(e);
+
     if (e->op == TOKstructliteral)
     {
-        StructLiteralExp *se = (StructLiteralExp *)e;
-        se->ownedByCtfe = OWNEDcode;
-        if (!(se->stageflags & stageScrub))
-        {
-            int old = se->stageflags;
-            se->stageflags |= stageScrub;
-            if (Expression *ex = scrubArray(loc, se->elements, true))
-                return ex;
-            se->stageflags = old;
-        }
+        StructLiteralExp *sle = (StructLiteralExp *)e;
+        if (Expression *ex = scrubStructLiteral(loc, sle))
+            return ex;
     }
-    if (e->op == TOKstring)
+    else if (e->op == TOKstring)
     {
         ((StringExp *)e)->ownedByCtfe = OWNEDcode;
     }
-    if (e->op == TOKarrayliteral)
+    else if (e->op == TOKarrayliteral)
     {
-        ((ArrayLiteralExp *)e)->ownedByCtfe = OWNEDcode;
-        if (Expression *ex = scrubArray(loc, ((ArrayLiteralExp *)e)->elements))
+        ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
+        ale->ownedByCtfe = OWNEDcode;
+        if (Expression *ex = scrubArray(loc, ale->elements))
             return ex;
     }
-    if (e->op == TOKassocarrayliteral)
+    else if (e->op == TOKassocarrayliteral)
     {
         AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
         aae->ownedByCtfe = OWNEDcode;
@@ -6085,24 +6168,34 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
     return e;
 }
 
+/* Returns: true if e is void,
+ * or is an array literal or struct literal of void elements.
+ */
+static bool isVoid(Expression *e)
+{
+    if (e->op == TOKvoid)
+        return true;
+
+    if (e->op == TOKarrayliteral)
+        return isEntirelyVoid(((ArrayLiteralExp *)e)->elements);
+
+    if (e->op == TOKstructliteral)
+        return isEntirelyVoid(((StructLiteralExp *)e)->elements);
+
+    return false;
+}
+
 // Return true if every element is either void,
 // or is an array literal or struct literal of void elements.
 bool isEntirelyVoid(Expressions *elems)
 {
     for (size_t i = 0; i < elems->dim; i++)
     {
-        Expression *m = (*elems)[i];
+        Expression *e = (*elems)[i];
         // It can be NULL for performance reasons,
         // see StructLiteralExp::interpret().
-        if (!m)
-            continue;
-
-        if (!(m->op == TOKvoid) &&
-            !(m->op == TOKarrayliteral && isEntirelyVoid(((ArrayLiteralExp *)m)->elements)) &&
-            !(m->op == TOKstructliteral && isEntirelyVoid(((StructLiteralExp *)m)->elements)))
-        {
+        if (e && !isVoid(e))
             return false;
-        }
     }
     return true;
 }
@@ -6112,102 +6205,116 @@ Expression *scrubArray(Loc loc, Expressions *elems, bool structlit)
 {
     for (size_t i = 0; i < elems->dim; i++)
     {
-        Expression *m = (*elems)[i];
+        Expression *e = (*elems)[i];
         // It can be NULL for performance reasons,
         // see StructLiteralExp::interpret().
-        if (!m)
+        if (!e)
             continue;
 
         // A struct .init may contain void members.
         // Static array members are a weird special case (bug 10994).
-        if (structlit &&
-            ((m->op == TOKvoid) ||
-             (m->op == TOKarrayliteral && m->type->ty == Tsarray && isEntirelyVoid(((ArrayLiteralExp *)m)->elements)) ||
-             (m->op == TOKstructliteral && isEntirelyVoid(((StructLiteralExp *)m)->elements))))
+        if (structlit && isVoid(e))
         {
-                m = NULL;
+            e = NULL;
         }
         else
         {
-            m = scrubReturnValue(loc, m);
-            if (CTFEExp::isCantExp(m) || m->op == TOKerror)
-                return m;
+            e = scrubReturnValue(loc, e);
+            if (CTFEExp::isCantExp(e) || e->op == TOKerror)
+                return e;
         }
-        (*elems)[i] = m;
+        (*elems)[i] = e;
     }
     return NULL;
 }
 
-Expression *scrubArrayCache(Loc loc, Expressions *elems);
+Expression *scrubStructLiteral(Loc loc, StructLiteralExp *sle)
+{
+    sle->ownedByCtfe = OWNEDcode;
+    if (!(sle->stageflags & stageScrub))
+    {
+        const int old = sle->stageflags;
+        sle->stageflags |= stageScrub;       // prevent infinite recursion
+        if (Expression *ex = scrubArray(loc, sle->elements, true))
+            return ex;
+        sle->stageflags = old;
+    }
+    return NULL;
+}
 
-Expression *scrubCacheValue(Loc loc, Expression *e)
+/**************************************
+ * Transitively set all .ownedByCtfe to OWNEDcache
+ */
+Expression *scrubCacheValue(Expression *e)
 {
+    if (!e)
+        return e;
+
     if (e->op == TOKclassreference)
     {
         StructLiteralExp *sle = ((ClassReferenceExp*)e)->value;
-        sle->ownedByCtfe = OWNEDcache;
-        if (!(sle->stageflags & stageScrub))
-        {
-            int old = sle->stageflags;
-            sle->stageflags |= stageScrub;
-            if (Expression *ex = scrubArrayCache(loc, sle->elements))
-                return ex;
-            sle->stageflags = old;
-        }
+        if (Expression *ex = scrubStructLiteralCache(sle))
+            return ex;
     }
-    if (e->op == TOKstructliteral)
+    else if (e->op == TOKstructliteral)
     {
         StructLiteralExp *sle = (StructLiteralExp *)e;
-        sle->ownedByCtfe = OWNEDcache;
-        if (!(sle->stageflags & stageScrub))
-        {
-            int old = sle->stageflags;
-            sle->stageflags |= stageScrub;
-            if (Expression *ex = scrubArrayCache(loc, sle->elements))
-                return ex;
-            sle->stageflags = old;
-        }
+        if (Expression *ex = scrubStructLiteralCache(sle))
+            return ex;
     }
-    if (e->op == TOKstring)
+    else if (e->op == TOKstring)
     {
         ((StringExp *)e)->ownedByCtfe = OWNEDcache;
     }
-    if (e->op == TOKarrayliteral)
+    else if (e->op == TOKarrayliteral)
     {
-        ((ArrayLiteralExp *)e)->ownedByCtfe = OWNEDcache;
-        if (Expression *ex = scrubArrayCache(loc, ((ArrayLiteralExp *)e)->elements))
+        ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
+        ale->ownedByCtfe = OWNEDcache;
+        if (Expression *ex = scrubArrayCache(ale->elements))
             return ex;
     }
-    if (e->op == TOKassocarrayliteral)
+    else if (e->op == TOKassocarrayliteral)
     {
         AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
         aae->ownedByCtfe = OWNEDcache;
-        if (Expression *ex = scrubArrayCache(loc, aae->keys))
+        if (Expression *ex = scrubArrayCache(aae->keys))
             return ex;
-        if (Expression *ex = scrubArrayCache(loc, aae->values))
+        if (Expression *ex = scrubArrayCache(aae->values))
             return ex;
     }
     return e;
 }
 
-Expression *scrubArrayCache(Loc loc, Expressions *elems)
+Expression *scrubArrayCache(Expressions *elems)
 {
     for (size_t i = 0; i < elems->dim; i++)
     {
-        Expression *m = (*elems)[i];
-        if (!m)
-            continue;
-        (*elems)[i] = scrubCacheValue(loc, m);
+        Expression *e = (*elems)[i];
+        (*elems)[i] = scrubCacheValue(e);
+    }
+    return NULL;
+}
+
+Expression *scrubStructLiteralCache(StructLiteralExp *sle)
+{
+    sle->ownedByCtfe = OWNEDcache;
+    if (!(sle->stageflags & stageScrub))
+    {
+        const int old = sle->stageflags;
+        sle->stageflags |= stageScrub;       // prevent infinite recursion
+        if (Expression *ex = scrubArrayCache(sle->elements))
+            return ex;
+        sle->stageflags = old;
     }
     return NULL;
 }
 
 /******************************* Special Functions ***************************/
 
-Expression *interpret_length(InterState *istate, Expression *earg)
+static Expression *interpret_length(UnionExp *pue, InterState *istate, Expression *earg)
 {
     //printf("interpret_length()\n");
-    earg = interpret(earg, istate);
+    earg = interpret(pue, earg, istate);
     if (exceptionOrCantInterpret(earg))
         return earg;
     dinteger_t len = 0;
@@ -6215,52 +6322,61 @@ Expression *interpret_length(InterState *istate, Expression *earg)
         len = ((AssocArrayLiteralExp *)earg)->keys->dim;
     else
         assert(earg->op == TOKnull);
-    Expression *e = new IntegerExp(earg->loc, len, Type::tsize_t);
-    return e;
+    new(pue) IntegerExp(earg->loc, len, Type::tsize_t);
+    return pue->exp();
 }
 
-Expression *interpret_keys(InterState *istate, Expression *earg, Type *returnType)
+static Expression *interpret_keys(UnionExp *pue, InterState *istate, Expression *earg, Type *returnType)
 {
-    earg = interpret(earg, istate);
+    earg = interpret(pue, earg, istate);
     if (exceptionOrCantInterpret(earg))
         return earg;
     if (earg->op == TOKnull)
-        return new NullExp(earg->loc, returnType);
+    {
+        new(pue) NullExp(earg->loc, earg->type);
+        return pue->exp();
+    }
     if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray)
         return NULL;
     assert(earg->op == TOKassocarrayliteral);
     AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
-    ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, aae->keys);
+    ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, returnType, aae->keys);
     ae->ownedByCtfe = aae->ownedByCtfe;
-    ae->type = returnType;
-    return copyLiteral(ae).copy();
+    *pue = copyLiteral(ae);
+    return pue->exp();
 }
 
-Expression *interpret_values(InterState *istate, Expression *earg, Type *returnType)
+static Expression *interpret_values(UnionExp *pue, InterState *istate, Expression *earg, Type *returnType)
 {
-    earg = interpret(earg, istate);
+    earg = interpret(pue, earg, istate);
     if (exceptionOrCantInterpret(earg))
         return earg;
     if (earg->op == TOKnull)
-        return new NullExp(earg->loc, returnType);
+    {
+        new(pue) NullExp(earg->loc, earg->type);
+        return pue->exp();
+    }
     if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray)
         return NULL;
     assert(earg->op == TOKassocarrayliteral);
     AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
-    ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, aae->values);
+    ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, returnType, aae->values);
     ae->ownedByCtfe = aae->ownedByCtfe;
-    ae->type = returnType;
     //printf("result is %s\n", e->toChars());
-    return copyLiteral(ae).copy();
+    *pue = copyLiteral(ae);
+    return pue->exp();
 }
 
-Expression *interpret_dup(InterState *istate, Expression *earg)
+Expression *interpret_dup(UnionExp *pue, InterState *istate, Expression *earg)
 {
-    earg = interpret(earg, istate);
+    earg = interpret(pue, earg, istate);
     if (exceptionOrCantInterpret(earg))
         return earg;
     if (earg->op == TOKnull)
-        return new NullExp(earg->loc, earg->type);
+    {
+        new(pue) NullExp(earg->loc, earg->type);
+        return pue->exp();
+    }
     if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray)
         return NULL;
     assert(earg->op == TOKassocarrayliteral);
@@ -6278,13 +6394,16 @@ Expression *interpret_dup(InterState *istate, Expression *earg)
 }
 
 // signature is int delegate(ref Value) OR int delegate(ref Key, ref Value)
-Expression *interpret_aaApply(InterState *istate, Expression *aa, Expression *deleg)
+Expression *interpret_aaApply(UnionExp *pue, InterState *istate, Expression *aa, Expression *deleg)
 {
     aa = interpret(aa, istate);
     if (exceptionOrCantInterpret(aa))
         return aa;
     if (aa->op != TOKassocarrayliteral)
-        return new IntegerExp(deleg->loc, 0, Type::tsize_t);
+    {
+        new(pue) IntegerExp(deleg->loc, 0, Type::tsize_t);
+        return pue->exp();
+    }
 
     FuncDeclaration *fd = NULL;
     Expression *pthis = NULL;
@@ -6323,9 +6442,13 @@ Expression *interpret_aaApply(InterState *istate, Expression *aa, Expression *de
             evalue->type = t;
         }
         args[numParams - 1] = evalue;
-        if (numParams == 2) args[0] = ekey;
+        if (numParams == 2)
+            args[0] = ekey;
 
-        eresult = interpretFunction(fd, istate, &args, pthis);
+        UnionExp ue;
+        eresult = interpretFunction(&ue, fd, istate, &args, pthis);
+        if (eresult == ue.exp())
+            eresult = ue.copy();
         if (exceptionOrCantInterpret(eresult))
             return eresult;
 
@@ -6336,19 +6459,10 @@ Expression *interpret_aaApply(InterState *istate, Expression *aa, Expression *de
     return eresult;
 }
 
-// Helper function: given a function of type A[] f(...),
-// return A[].
-Type *returnedArrayType(FuncDeclaration *fd)
-{
-    assert(fd->type->ty == Tfunction);
-    assert(fd->type->nextOf()->ty == Tarray);
-    return ((TypeFunction *)fd->type)->nextOf();
-}
-
 /* Decoding UTF strings for foreach loops. Duplicates the functionality of
  * the twelve _aApplyXXn functions in aApply.d in the runtime.
  */
-Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *deleg, bool rvs)
+static Expression *foreachApplyUtf(UnionExp *pue, InterState *istate, Expression *str, Expression *deleg, bool rvs)
 {
     FuncDeclaration *fd = NULL;
     Expression *pthis = NULL;
@@ -6369,7 +6483,10 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
                                      : Type::tsize_t;
     size_t len = (size_t)resolveArrayLength(str);
     if (len == 0)
-        return new IntegerExp(deleg->loc, 0, indexType);
+    {
+        new(pue) IntegerExp(deleg->loc, 0, indexType);
+        return pue->exp();
+    }
 
     str = resolveSlice(str);
 
@@ -6584,7 +6701,10 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
 
             args[numParams - 1] = val;
 
-            eresult = interpretFunction(fd, istate, &args, pthis);
+            UnionExp ue;
+            eresult = interpretFunction(&ue, fd, istate, &args, pthis);
+            if (eresult == ue.exp())
+                eresult = ue.copy();
             if (exceptionOrCantInterpret(eresult))
                 return eresult;
             assert(eresult->op == TOKint64);
@@ -6598,7 +6718,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
 /* If this is a built-in function, return the interpreted result,
  * Otherwise, return NULL.
  */
-Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
+Expression *evaluateIfBuiltin(UnionExp *pue, InterState *istate, Loc loc,
     FuncDeclaration *fd, Expressions *arguments, Expression *pthis)
 {
     Expression *e = NULL;
@@ -6631,21 +6751,31 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
         if (firstarg && firstarg->type->toBasetype()->ty == Taarray)
         {
             TypeAArray *firstAAtype = (TypeAArray *)firstarg->type;
-            const char *id = fd->ident->toChars();
-            if (nargs == 1 && fd->ident == Id::aaLen)
-                return interpret_length(istate, firstarg);
-            if (nargs == 3 && !strcmp(id, "_aaApply"))
-                return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2]));
-            if (nargs == 3 && !strcmp(id, "_aaApply2"))
-                return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2]));
-            if (nargs == 1 && !strcmp(id, "keys") && !strcmp(fd->toParent2()->ident->toChars(), "object"))
-                return interpret_keys(istate, firstarg, firstAAtype->index->arrayOf());
-            if (nargs == 1 && !strcmp(id, "values") && !strcmp(fd->toParent2()->ident->toChars(), "object"))
-                return interpret_values(istate, firstarg, firstAAtype->nextOf()->arrayOf());
-            if (nargs == 1 && !strcmp(id, "rehash") && !strcmp(fd->toParent2()->ident->toChars(), "object"))
-                return interpret(firstarg, istate);
-            if (nargs == 1 && !strcmp(id, "dup") && !strcmp(fd->toParent2()->ident->toChars(), "object"))
-                return interpret_dup(istate, firstarg);
+            const Identifier *id = fd->ident;
+            if (nargs == 1)
+            {
+                if (fd->ident == Id::aaLen)
+                    return interpret_length(pue, istate, firstarg);
+
+                if (fd->toParent2()->ident == Id::object)
+                {
+                    if (id == Id::keys)
+                        return interpret_keys(pue, istate, firstarg, firstAAtype->index->arrayOf());
+                    if (id == Id::values)
+                        return interpret_values(pue, istate, firstarg, firstAAtype->nextOf()->arrayOf());
+                    if (id == Id::rehash)
+                        return interpret(pue, firstarg, istate);
+                    if (id == Id::dup)
+                        return interpret_dup(pue, istate, firstarg);
+                }
+            }
+            else // (nargs == 3)
+            {
+                if (id == Id::_aaApply)
+                    return interpret_aaApply(pue, istate, firstarg, (Expression *)(arguments->data[2]));
+                if (id == Id::_aaApply2)
+                    return interpret_aaApply(pue, istate, firstarg, (Expression *)(arguments->data[2]));
+            }
         }
     }
     if (pthis && !fd->fbody && fd->isCtorDeclaration() && fd->parent && fd->parent->parent && fd->parent->parent->ident == Id::object)
@@ -6693,7 +6823,7 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
                 str = interpret(str, istate);
                 if (exceptionOrCantInterpret(str))
                     return str;
-                return foreachApplyUtf(istate, str, (*arguments)[1], rvs);
+                return foreachApplyUtf(pue, istate, str, (*arguments)[1], rvs);
             }
         }
     }
@@ -6723,7 +6853,10 @@ Expression *evaluatePostblit(InterState *istate, Expression *e)
     if (e->op == TOKstructliteral)
     {
         // e.__postblit()
-        e = interpretFunction(sd->postblit, istate, NULL, e);
+        UnionExp ue;
+        e = interpretFunction(&ue, sd->postblit, istate, NULL, e);
+        if (e == ue.exp())
+            e = ue.copy();
         if (exceptionOrCantInterpret(e))
             return e;
         return NULL;
@@ -6741,6 +6874,7 @@ Expression *evaluateDtor(InterState *istate, Expression *e)
     if (!sd->dtor)
         return NULL;
 
+    UnionExp ue;
     if (e->op == TOKarrayliteral)
     {
         ArrayLiteralExp *alex = (ArrayLiteralExp *)e;
@@ -6750,12 +6884,16 @@ Expression *evaluateDtor(InterState *istate, Expression *e)
     else if (e->op == TOKstructliteral)
     {
         // e.__dtor()
-        e = interpretFunction(sd->dtor, istate, NULL, e);
+        e = interpretFunction(&ue, sd->dtor, istate, NULL, e);
     }
     else
         assert(0);
     if (exceptionOrCantInterpret(e))
+    {
+        if (e == ue.exp())
+            e = ue.copy();
         return e;
+    }
     return NULL;
 }
 
diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c
index b7fcf43f6c1..4d82d7217e1 100644
--- a/gcc/d/dmd/dsymbol.c
+++ b/gcc/d/dmd/dsymbol.c
@@ -1189,23 +1189,26 @@ void ScopeDsymbol::importScope(Dsymbol *s, Prot protection)
     }
 }
 
+#define BITS_PER_INDEX (sizeof(size_t) * CHAR_BIT)
+
 static void bitArraySet(BitArray *array, size_t idx)
 {
-    array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] |= 1ULL << (idx & (sizeof(size_t) * CHAR_BIT - 1));
+    array->ptr[idx / BITS_PER_INDEX] |= 1ULL << (idx % BITS_PER_INDEX);
 }
 
 static bool bitArrayGet(BitArray *array, size_t idx)
 {
-    return (array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] & (1ULL << (idx & (sizeof(size_t) * CHAR_BIT - 1)))) != 0;
+    const size_t boffset = idx % BITS_PER_INDEX;
+    return (array->ptr[idx / BITS_PER_INDEX] & (1ULL << boffset)) >> boffset;
 }
 
 static void bitArrayLength(BitArray *array, size_t len)
 {
-    size_t obytes = (array->len + CHAR_BIT - 1) / CHAR_BIT;
-    size_t nbytes = (len + CHAR_BIT - 1) / CHAR_BIT;
-
-    if (obytes < nbytes)
+    if (array->len < len)
     {
+        const size_t obytes = (array->len + BITS_PER_INDEX - 1) / BITS_PER_INDEX;
+        const size_t nbytes = (len + BITS_PER_INDEX - 1) / BITS_PER_INDEX;
+
         if (!array->ptr)
             array->ptr = (size_t *)mem.xmalloc(nbytes * sizeof(size_t));
         else
@@ -1213,8 +1216,9 @@ static void bitArrayLength(BitArray *array, size_t len)
 
         for (size_t i = obytes; i < nbytes; i++)
             array->ptr[i] = 0;
+
+        array->len = nbytes * BITS_PER_INDEX;
     }
-    array->len = len;
 }
 
 void ScopeDsymbol::addAccessiblePackage(Package *p, Prot protection)
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index a1186c9fb53..cbc38195cca 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -1493,7 +1493,6 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
                          * is now optimized. See Bugzilla 2356.
                          */
                         Type *tbn = ((TypeArray *)tb)->next;
-                        Type *tsa = tbn->sarrayOf(nargs - i);
 
                         Expressions *elements = new Expressions();
                         elements->setDim(nargs - i);
@@ -1511,8 +1510,7 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
                             (*elements)[u] = a;
                         }
                         // Bugzilla 14395: Convert to a static array literal, or its slice.
-                        arg = new ArrayLiteralExp(loc, elements);
-                        arg->type = tsa;
+                        arg = new ArrayLiteralExp(loc, tbn->sarrayOf(nargs - i), elements);
                         if (tb->ty == Tarray)
                         {
                             arg = new SliceExp(loc, arg, NULL, NULL);
@@ -3741,34 +3739,37 @@ unsigned StringExp::charAt(uinteger_t i) const
 
 // [ e1, e2, e3, ... ]
 
-ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
+ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expressions *elements)
     : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
 {
     this->basis = NULL;
+    this->type = type;
     this->elements = elements;
     this->ownedByCtfe = OWNEDcode;
 }
 
-ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
+ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expression *e)
     : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
 {
     this->basis = NULL;
+    this->type = type;
     elements = new Expressions;
     elements->push(e);
     this->ownedByCtfe = OWNEDcode;
 }
 
-ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *basis, Expressions *elements)
+ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expression *basis, Expressions *elements)
     : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
 {
     this->basis = basis;
+    this->type = type;
     this->elements = elements;
     this->ownedByCtfe = OWNEDcode;
 }
 
 ArrayLiteralExp *ArrayLiteralExp::create(Loc loc, Expressions *elements)
 {
-    return new ArrayLiteralExp(loc, elements);
+    return new ArrayLiteralExp(loc, NULL, elements);
 }
 
 bool ArrayLiteralExp::equals(RootObject *o)
@@ -3806,6 +3807,7 @@ bool ArrayLiteralExp::equals(RootObject *o)
 Expression *ArrayLiteralExp::syntaxCopy()
 {
     return new ArrayLiteralExp(loc,
+        NULL,
         basis ? basis->syntaxCopy() : NULL,
         arraySyntaxCopy(elements));
 }
@@ -4082,8 +4084,7 @@ Expression *StructLiteralExp::getField(Type *type, unsigned offset)
                 z->setDim(length);
                 for (size_t q = 0; q < length; ++q)
                     (*z)[q] = e->copy();
-                e = new ArrayLiteralExp(loc, z);
-                e->type = type;
+                e = new ArrayLiteralExp(loc, type, z);
             }
             else
             {
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 51490828b1c..2dd0b249458 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -410,9 +410,9 @@ public:
     Expressions *elements;
     OwnedBy ownedByCtfe;
 
-    ArrayLiteralExp(Loc loc, Expressions *elements);
-    ArrayLiteralExp(Loc loc, Expression *e);
-    ArrayLiteralExp(Loc loc, Expression *basis, Expressions *elements);
+    ArrayLiteralExp(Loc loc, Type *type, Expressions *elements);
+    ArrayLiteralExp(Loc loc, Type *type, Expression *e);
+    ArrayLiteralExp(Loc loc, Type *type, Expression *basis, Expressions *elements);
     static ArrayLiteralExp *create(Loc loc, Expressions *elements);
     Expression *syntaxCopy();
     bool equals(RootObject *o);
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index b3274e4cfe4..d5319e55a6e 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -6632,8 +6632,7 @@ public:
                 if (tb2->ty == Tarray || tb2->ty == Tsarray)
                 {
                     // Make e2 into [e2]
-                    exp->e2 = new ArrayLiteralExp(exp->e2->loc, exp->e2);
-                    exp->e2->type = exp->type;
+                    exp->e2 = new ArrayLiteralExp(exp->e2->loc, exp->type, exp->e2);
                 }
                 result = exp->optimize(WANTvalue);
                 return;
@@ -6669,8 +6668,7 @@ public:
                 if (tb1->ty == Tarray || tb1->ty == Tsarray)
                 {
                     // Make e1 into [e1]
-                    exp->e1 = new ArrayLiteralExp(exp->e1->loc, exp->e1);
-                    exp->e1->type = exp->type;
+                    exp->e1 = new ArrayLiteralExp(exp->e1->loc, exp->type, exp->e1);
                 }
                 result = exp->optimize(WANTvalue);
                 return;
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index d413ded33b4..ec26b2c7008 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -267,6 +267,9 @@ Msgtable msgtable[] =
     { "_ArrayEq", NULL },
     { "_ArrayPostblit", NULL },
     { "_ArrayDtor", NULL },
+    { "dup", NULL },
+    { "_aaApply", NULL },
+    { "_aaApply2", NULL },
 
     // For pragma's
     { "Pinline", "inline" },
diff --git a/gcc/d/dmd/initsem.c b/gcc/d/dmd/initsem.c
index 74929389177..52e26bccd85 100644
--- a/gcc/d/dmd/initsem.c
+++ b/gcc/d/dmd/initsem.c
@@ -612,7 +612,7 @@ public:
                 assert((*elements)[i]->op != TOKerror);
             }
 
-            Expression *e = new ArrayLiteralExp(init->loc, elements);
+            Expression *e = new ArrayLiteralExp(init->loc, NULL, elements);
             ExpInitializer *ei = new ExpInitializer(init->loc, e);
             result = inferType(ei, sc);
             return;
@@ -857,8 +857,7 @@ public:
                             elements2->setDim(dim);
                             for (size_t j = 0; j < dim; j++)
                                 (*elements2)[j] = e;
-                            e = new ArrayLiteralExp(e->loc, elements2);
-                            e->type = tn;
+                            e = new ArrayLiteralExp(e->loc, tn, elements2);
                             (*elements)[i] = e;
                         }
                     }
@@ -877,8 +876,7 @@ public:
                 }
             }
 
-            Expression *e = new ArrayLiteralExp(init->loc, elements);
-            e->type = init->type;
+            Expression *e = new ArrayLiteralExp(init->loc, init->type, elements);
             result = e;
             return;
         }
@@ -902,8 +900,7 @@ public:
                 elements->setDim(d);
                 for (size_t i = 0; i < d; i++)
                     (*elements)[i] = e;
-                ArrayLiteralExp *ae = new ArrayLiteralExp(e->loc, elements);
-                ae->type = itype;
+                ArrayLiteralExp *ae = new ArrayLiteralExp(e->loc, itype, elements);
                 result = ae;
                 return;
             }
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index 50a33e5c4c5..09161a313ee 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -2324,16 +2324,11 @@ Identifier *Type::getTypeInfoIdent()
     size_t namelen = 19 + sizeof(len) * 3 + len + 1;
     char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)mem.xmalloc(namelen);
 
-    sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len, buf.data);
+    int length = sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len, buf.data);
     //printf("%p, deco = %s, name = %s\n", this, deco, name);
-    assert(strlen(name) < namelen);     // don't overflow the buffer
+    assert(0 < length && length < namelen);     // don't overflow the buffer
 
-    size_t off = 0;
-#ifndef IN_GCC
-    if (global.params.isOSX || (global.params.isWindows && !global.params.is64bit))
-        ++off;                 // C mangling will add '_' back in
-#endif
-    Identifier *id = Identifier::idPool(name + off);
+    Identifier *id = Identifier::idPool(name, length);
 
     if (name != namebuf)
         free(name);
@@ -4340,8 +4335,7 @@ Expression *TypeSArray::defaultInitLiteral(Loc loc)
     elements->setDim(d);
     for (size_t i = 0; i < d; i++)
         (*elements)[i] = NULL;
-    ArrayLiteralExp *ae = new ArrayLiteralExp(Loc(), elementinit, elements);
-    ae->type = this;
+    ArrayLiteralExp *ae = new ArrayLiteralExp(Loc(), this, elementinit, elements);
     return ae;
 }
 
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index c081e806785..171ed14f132 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -7020,7 +7020,7 @@ Expression *Parser::parsePrimaryExp()
             if (keys)
                 e = new AssocArrayLiteralExp(loc, keys, values);
             else
-                e = new ArrayLiteralExp(loc, values);
+                e = new ArrayLiteralExp(loc, NULL, values);
             break;
         }
 
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index a2d5c9b7a9c..1d5f3fc1064 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -479,8 +479,7 @@ Expression *pointerBitmap(TraitsExp *e)
     for (d_uns64 i = 0; i < cntdata; i++)
         exps->push(new IntegerExp(e->loc, data[(size_t)i], Type::tsize_t));
 
-    ArrayLiteralExp* ale = new ArrayLiteralExp(e->loc, exps);
-    ale->type = Type::tsize_t->sarrayOf(cntdata + 1);
+    ArrayLiteralExp* ale = new ArrayLiteralExp(e->loc, Type::tsize_t->sarrayOf(cntdata + 1), exps);
     return ale;
 }
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2019-01-14 10:39 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2019-01-14 10:39 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 663 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream cd2034cd7.

One fix in the asm statement parser to stop parsing if the end of the
statement has been reached, and moves all inline asm tests to gdc.dg.
These being adjusted where necessary to test the GCC style instead.

Bootstrapped and tested on x86_64-linux-gnu.

Committed to trunk as r267913.
-- 
Iain
---
gcc/testsuite/ChangeLog:

2019-01-14  Iain Buclaw  <ibuclaw@gdcproject.org>

    * gdc.dg/asm1.d: New test.
    * gdc.dg/asm2.d: New test.
    * gdc.dg/asm3.d: New test.
    * gdc.dg/asm4.d: New test.
    * lib/gdc.exp (gdc_init): Set gcc_error_prefix and gcc_warning_prefix.
---

[-- Attachment #2: dmdcd2034cd7.patch --]
[-- Type: text/x-patch, Size: 34882 bytes --]

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index feb65923273..a3b2db74af4 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-6d5b853d30908638d49210ebe600917296b8ab9b
+cd2034cd7b157dd8f3e94c684061bb1aa630b2b6
 
 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/iasmgcc.c b/gcc/d/dmd/iasmgcc.c
index 3c0494d5717..cecbdefe41a 100644
--- a/gcc/d/dmd/iasmgcc.c
+++ b/gcc/d/dmd/iasmgcc.c
@@ -224,7 +224,7 @@ Lerror:
 static GccAsmStatement *parseGccAsm(Parser *p, GccAsmStatement *s)
 {
     s->insn = p->parseExpression();
-    if (p->token.value == TOKsemicolon)
+    if (p->token.value == TOKsemicolon || p->token.value == TOKeof)
         goto Ldone;
 
     // No semicolon followed after instruction template, treat as extended asm.
@@ -254,7 +254,7 @@ static GccAsmStatement *parseGccAsm(Parser *p, GccAsmStatement *s)
                 assert(0);
         }
 
-        if (p->token.value == TOKsemicolon)
+        if (p->token.value == TOKsemicolon || p->token.value == TOKeof)
             goto Ldone;
     }
 Ldone:
@@ -288,6 +288,7 @@ Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc)
         *ptoklist = NULL;
     }
     p.token = *toklist;
+    p.scanloc = s->loc;
 
     // Parse the gcc asm statement.
     s = parseGccAsm(&p, s);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d0611e3bc37..373f39d2a8b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2019-01-14  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+	* gdc.dg/asm1.d: New test.
+	* gdc.dg/asm2.d: New test.
+	* gdc.dg/asm3.d: New test.
+	* gdc.dg/asm4.d: New test.
+	* lib/gdc.exp (gdc_init): Set gcc_error_prefix and gcc_warning_prefix.
+
 2019-01-13  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	PR libfortran/88776
diff --git a/gcc/testsuite/gdc.dg/asm1.d b/gcc/testsuite/gdc.dg/asm1.d
new file mode 100644
index 00000000000..7b00e4d54ec
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/asm1.d
@@ -0,0 +1,82 @@
+// { dg-do compile }
+module asm1;
+
+void parse1()
+{
+    asm
+    {
+        ""h;    // { dg-error "found 'h' when expecting ':'" }
+    }
+}
+
+void parse2()
+{
+    asm 
+    {
+        "" : : "g" 1 ? 2 : 3;
+        "" : : "g" 1 ? 2 : : 3;
+        // { dg-error "expression expected, not ':'" "" { target *-*-* } .-1 }
+        // { dg-error "expected constant string constraint for operand" "" { target *-*-* } .-2 }
+    }
+}
+
+void parse3()
+{
+    asm { "" [; }
+    // { dg-error "expression expected, not ';'" "" { target *-*-* } .-1 }
+    // { dg-error "found 'EOF' when expecting ','" "" { target *-*-* } .-2 }
+    // { dg-error "found 'EOF' when expecting ']'" "" { target *-*-* } .-3 }
+    // { dg-error "found 'EOF' when expecting ';'" "" { target *-*-* } .-4 }
+}
+
+void semantic1()
+{
+    {
+        int one;
+    L1:
+        ;
+    }
+    asm { "" : : : : L1, L2; }
+    // { dg-error "goto skips declaration of variable asm1.semantic1.one" "" { target *-*-* } .-1 }
+    // { dg-error "goto skips declaration of variable asm1.semantic1.two" "" { target *-*-* } .-2 }
+    {
+        int two;
+    L2:
+        ;
+    }
+}
+
+void semantic2a(X...)(X expr)
+{
+    alias X[0] var1;
+    asm { "%0" : "=m" var1; }   // { dg-error "double 'double' is a type, not an lvalue" }
+}
+
+void semantic2()
+{
+   semantic2a(3.6);     // { dg-error "template instance asm1.semantic2a!double error instantiating" }
+}
+
+void semantic3()
+{
+    asm 
+    {
+        unknown;        // { dg-error "undefined identifier" }
+    }
+}
+
+struct S4
+{
+    template opDispatch(string Name, P...)
+    {
+        static void opDispatch(P) {}
+    }
+}
+
+void semantic4()
+{
+    asm
+    {
+        "%0" : : "m" S4.foo;    // { dg-error "template instance opDispatch!\"foo\" has no value" }
+    }
+}
diff --git a/gcc/testsuite/gdc.dg/asm2.d b/gcc/testsuite/gdc.dg/asm2.d
new file mode 100644
index 00000000000..bce0e41a60f
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/asm2.d
@@ -0,0 +1,8 @@
+// { dg-do compile }
+module asm2;
+
+void test()
+{
+    asm const shared { }    // { dg-error "const/immutable/shared/inout attributes are not allowed on asm blocks" }
+}
+
diff --git a/gcc/testsuite/gdc.dg/asm3.d b/gcc/testsuite/gdc.dg/asm3.d
new file mode 100644
index 00000000000..333d83ec99b
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/asm3.d
@@ -0,0 +1,24 @@
+// { dg-do compile }
+// { dg-options "-Wall -Wdeprecated -Werror" }
+module asm3;
+
+void test1() nothrow    // { dg-error "nothrow function 'asm3.test1' may throw" }
+{
+    asm { }             // { dg-error "asm statement is assumed to throw - mark it with 'nothrow' if it does not" }
+}
+
+void test2() pure
+{
+    asm { }             // { dg-error "asm statement is assumed to be impure - mark it with 'pure' if it is not" }
+}
+
+void test3() @nogc
+{
+    asm { }             // { dg-error "asm statement is assumed to use the GC - mark it with '@nogc' if it does not" }
+}
+
+void test4() @safe
+{
+    asm { }             // { dg-error "asm statement is assumed to be @system - mark it with '@trusted' if it is not" }
+}
+
diff --git a/gcc/testsuite/gdc.dg/asm4.d b/gcc/testsuite/gdc.dg/asm4.d
new file mode 100644
index 00000000000..e243c0820ac
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/asm4.d
@@ -0,0 +1,40 @@
+// https://issues.dlang.org/show_bug.cgi?id=12979
+// { dg-do compile }
+// { dg-options "-Wall -Wdeprecated -Werror" }
+module asm4;
+
+void test1()
+{
+    asm pure nothrow @nogc @trusted {}
+    asm @safe {}
+}
+
+void test2() pure nothrow @nogc @safe
+{
+    asm pure nothrow @nogc @trusted {}
+}
+
+void test3()()
+{
+    asm pure nothrow @nogc @trusted {}
+}
+
+static assert(__traits(compiles, () pure nothrow @nogc @safe => test3()));
+
+void test4()()
+{
+    asm {}
+}
+
+// wait for deprecation of asm pure inference
+// static assert(!__traits(compiles, () pure => test4()));
+static assert(!__traits(compiles, () nothrow => test4()));
+// wait for deprecation of asm @nogc inference
+// static assert(!__traits(compiles, () @nogc => test4()));
+static assert(!__traits(compiles, () @safe => test4()));
+
+@safe
+void test5()
+{
+    static assert(!__traits(compiles, { asm { ""; } }() ));
+}
diff --git a/gcc/testsuite/gdc.test/compilable/deprecate12979a.d b/gcc/testsuite/gdc.test/compilable/deprecate12979a.d
deleted file mode 100644
index afe919af13d..00000000000
--- a/gcc/testsuite/gdc.test/compilable/deprecate12979a.d
+++ /dev/null
@@ -1,27 +0,0 @@
-// REQUIRED_ARGS: -dw
-// PERMUTE_ARGS:
-
-/*
-TEST_OUTPUT:
----
-compilable/deprecate12979a.d(13): Deprecation: asm statement is assumed to throw - mark it with `nothrow` if it does not
----
-*/
-
-void foo() nothrow
-{
-    version(GNU)
-    {
-        asm
-        {
-            "";
-        }
-    }
-    else
-    {
-        asm
-        {
-            ret;
-        }
-    }
-}
diff --git a/gcc/testsuite/gdc.test/compilable/iasm_labeloperand.d b/gcc/testsuite/gdc.test/compilable/iasm_labeloperand.d
deleted file mode 100644
index f88fd16511a..00000000000
--- a/gcc/testsuite/gdc.test/compilable/iasm_labeloperand.d
+++ /dev/null
@@ -1,48 +0,0 @@
-
-version (D_InlineAsm_X86)
-    version = TestInlineAsm;
-else version (D_InlineAsm_X86_64)
-    version = TestInlineAsm;
-else version (GNU)
-    version = TestInlineAsm;
-else
-    pragma(msg, "Inline asm not supported, not testing.");
-
-version (TestInlineAsm)
-{
-    void testInlineAsm()
-    {
-        version (GNU)
-        {
-        L1:
-            asm { ""; }
-            asm { "" : : : : L1, L2; }
-        L2:
-            asm { ""; }
-        }
-        else
-        {
-            asm
-            {
-		L1:
-			nop;
-			nop;
-			nop;
-			nop;
-			
-			mov EAX, dword ptr L1; // Check back references
-			mov EAX, dword ptr L2; // Check forward references
-			mov EAX, dword ptr DS:L1; // Not really useful in standard use, but who knows.
-			mov EAX, dword ptr FS:L2; // Once again, not really useful, but it is valid.
-			mov EAX, dword ptr CS:L1; // This is what the first test case should implicitly be.
-			
-		L2:
-			nop;
-			nop;
-			nop;
-			nop;
-			
-            }
-        }
-    }
-}
diff --git a/gcc/testsuite/gdc.test/compilable/test11471.d b/gcc/testsuite/gdc.test/compilable/test11471.d
deleted file mode 100644
index 1df7e80f20a..00000000000
--- a/gcc/testsuite/gdc.test/compilable/test11471.d
+++ /dev/null
@@ -1,10 +0,0 @@
-// REQUIRED_ARGS: -profile
-
-void main() nothrow
-{
-    // Error: asm statements are assumed to throw
-    version(GNU)
-        asm { ""; }
-    else
-        asm { nop; }
-}
diff --git a/gcc/testsuite/gdc.test/compilable/test12979a.d b/gcc/testsuite/gdc.test/compilable/test12979a.d
deleted file mode 100644
index 14ca6efc0ee..00000000000
--- a/gcc/testsuite/gdc.test/compilable/test12979a.d
+++ /dev/null
@@ -1,5 +0,0 @@
-void parse()
-{
-    asm pure nothrow @nogc @trusted {}
-    asm @safe {}
-}
diff --git a/gcc/testsuite/gdc.test/compilable/test12979b.d b/gcc/testsuite/gdc.test/compilable/test12979b.d
deleted file mode 100644
index 41c76a251e8..00000000000
--- a/gcc/testsuite/gdc.test/compilable/test12979b.d
+++ /dev/null
@@ -1,64 +0,0 @@
-// REQUIRED_ARGS: -w -de
-
-void foo() pure nothrow @nogc @safe
-{
-    version(GNU)
-    {
-        asm pure nothrow @nogc @trusted
-        {
-            "";
-        }
-    }
-    else
-    {
-        asm pure nothrow @nogc @trusted
-        {
-            ret;
-        }
-    }
-}
-
-void bar()()
-{
-    version(GNU)
-    {
-        asm pure nothrow @nogc @trusted
-        {
-            "";
-        }
-    }
-    else
-    {
-        asm pure nothrow @nogc @trusted
-        {
-            ret;
-        }
-    }
-}
-
-static assert(__traits(compiles, () pure nothrow @nogc @safe => bar()));
-
-void baz()()
-{
-    version(GNU)
-    {
-        asm
-        {
-            "";
-        }
-    }
-    else
-    {
-        asm
-        {
-            ret;
-        }
-    }
-}
-
-// wait for deprecation of asm pure inference
-// static assert(!__traits(compiles, () pure => baz()));
-static assert(!__traits(compiles, () nothrow => baz()));
-// wait for deprecation of asm @nogc inference
-// static assert(!__traits(compiles, () @nogc => baz()));
-static assert(!__traits(compiles, () @safe => baz()));
diff --git a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979a.d b/gcc/testsuite/gdc.test/fail_compilation/deprecate12979a.d
deleted file mode 100644
index 5b2cd56c9f9..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979a.d
+++ /dev/null
@@ -1,18 +0,0 @@
-// REQUIRED_ARGS: -de
-// PERMUTE_ARGS:
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/deprecate12979a.d(14): Deprecation: asm statement is assumed to throw - mark it with `nothrow` if it does not
-fail_compilation/deprecate12979a.d(12): Error: nothrow function `deprecate12979a.foo` may throw
----
-*/
-
-void foo() nothrow
-{
-    asm
-    {
-        ret;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979b.d b/gcc/testsuite/gdc.test/fail_compilation/deprecate12979b.d
deleted file mode 100644
index 0d675cb558f..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979b.d
+++ /dev/null
@@ -1,17 +0,0 @@
-// REQUIRED_ARGS: -de
-// PERMUTE_ARGS:
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/deprecate12979b.d(13): Deprecation: asm statement is assumed to be impure - mark it with 'pure' if it is not
----
-*/
-
-void foo() pure
-{
-    asm
-    {
-        ret;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979c.d b/gcc/testsuite/gdc.test/fail_compilation/deprecate12979c.d
deleted file mode 100644
index 782700469cd..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979c.d
+++ /dev/null
@@ -1,17 +0,0 @@
-// REQUIRED_ARGS: -de
-// PERMUTE_ARGS:
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/deprecate12979c.d(13): Deprecation: asm statement is assumed to use the GC - mark it with '@nogc' if it does not
----
-*/
-
-void foo() @nogc
-{
-    asm
-    {
-        ret;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979d.d b/gcc/testsuite/gdc.test/fail_compilation/deprecate12979d.d
deleted file mode 100644
index afff5671027..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/deprecate12979d.d
+++ /dev/null
@@ -1,16 +0,0 @@
-// PERMUTE_ARGS:
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/deprecate12979d.d(12): Error: asm statement is assumed to be @system - mark it with '@trusted' if it is not
----
-*/
-
-void foo() @safe
-{
-    asm
-    {
-        ret;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag6717.d b/gcc/testsuite/gdc.test/fail_compilation/diag6717.d
deleted file mode 100644
index fe30f898293..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/diag6717.d
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/diag6717.d(12): Error: end of instruction expected, not 'h'
----
-*/
-
-void main()
-{
-    asm
-    {
-        mov AX, 12h ;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12635.d b/gcc/testsuite/gdc.test/fail_compilation/fail12635.d
deleted file mode 100644
index b00cc47b300..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail12635.d
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail12635.d(19): Error: Cannot generate a segment prefix for a branching instruction
----
-*/
-
-void foo()
-{
-    enum NOP = 0x9090_9090_9090_9090;
-
-    asm
-    {
-    L1:
-        dq NOP,NOP,NOP,NOP;    //  32
-        dq NOP,NOP,NOP,NOP;    //  64
-        dq NOP,NOP,NOP,NOP;    //  96
-        dq NOP,NOP,NOP,NOP;    // 128
-        jmp DS:L1;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13938.d b/gcc/testsuite/gdc.test/fail_compilation/fail13938.d
deleted file mode 100644
index bd18ef2808f..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail13938.d
+++ /dev/null
@@ -1,16 +0,0 @@
-// REQUIRED_ARGS: -o-
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail13938.d(14): Error: cannot directly load TLS variable 'val'
----
-*/
-
-void test1()
-{
-    static int val;
-    asm
-    {
-        mov EAX, val;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13939.d b/gcc/testsuite/gdc.test/fail_compilation/fail13939.d
deleted file mode 100644
index 074c22c89aa..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail13939.d
+++ /dev/null
@@ -1,17 +0,0 @@
-// REQUIRED_ARGS: -o- -fPIC
-// DISABLED: win32 win64
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail13939.d(15): Error: cannot directly load global variable 'val' with PIC code
----
-*/
-version(Windows) static assert(0);
-void test1()
-{
-    __gshared int val;
-    asm
-    {
-        mov EAX, val;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14009.d b/gcc/testsuite/gdc.test/fail_compilation/fail14009.d
deleted file mode 100644
index 84f72c27f39..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail14009.d
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail14009.d(12): Error: expression expected not :
----
-*/
-
-void main()
-{
-    asm {
-      mov EAX, FS: 1 ? 2 : 3;     // accepted
-      mov EAX, FS: 1 ? 2 : : 3;   // rejected
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail152.d b/gcc/testsuite/gdc.test/fail_compilation/fail152.d
deleted file mode 100644
index 60cf4ce2782..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail152.d
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail152.d(15): Error: cannot use type double as an operand
----
-*/
-
-// 1028 Segfault using tuple inside asm code.
-
-void a(X...)(X expr)
-{
-    alias X[0] var1;
-    version(GNU)
-    {
-        version(X86) asm {"fstpd %0;" : "=m" (var1) : : ;}
-        else version(X86_64) asm {"fstpd %0;" : "=m" (var1) : : ;}
-        else static assert(false, "ASM code not implemented for this architecture");
-    }
-    else asm {
-        //fld double ptr X[0];   // (1) segfaults
-        fstp double ptr var1;    // (2) ICE
-    }
-}
-
-void main()
-{
-   a(3.6);
-}
-
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail2350.d b/gcc/testsuite/gdc.test/fail_compilation/fail2350.d
deleted file mode 100644
index deb0ceb6a32..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail2350.d
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail2350.d(8): Error: function fail2350.test2350 naked assembly functions with contracts are not supported
----
-*/
-
-void test2350()
-in
-{
-}
-body
-{
-	asm { naked; }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail274.d b/gcc/testsuite/gdc.test/fail_compilation/fail274.d
deleted file mode 100644
index 5fa55962d18..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail274.d
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail274.d(10): Error: expression expected not ;
----
-*/
-
-void main()
-{
-    asm { inc [; }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail327.d b/gcc/testsuite/gdc.test/fail_compilation/fail327.d
deleted file mode 100644
index ab872357bac..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail327.d
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail327.d(10): Error: asm statement is assumed to be @system - mark it with '@trusted' if it is not
----
-*/
-
-@safe void foo()
-{
-    version(GNU)
-    {
-        version(X86) asm {"xor %%EAX,%%EAX" : : : ;}
-        else version(X86_64) asm {"xor %%EAX,%%EAX" : : : ;}
-        else static assert(false, "ASM code not implemented for this architecture");
-    }
-    else asm { xor EAX,EAX; }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail3354.d b/gcc/testsuite/gdc.test/fail_compilation/fail3354.d
deleted file mode 100644
index bcf6368c421..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail3354.d
+++ /dev/null
@@ -1,12 +0,0 @@
-
-void main()
-{
-    version(D_InlineAsm_X86) {}
-    else version(D_InlineAsm_X64) {}
-    else static assert(0);
-
-    asm {
-        fldz ST(0), ST(1), ST(2), ST(3);
-        fld ST(0), ST(1), ST(2), ST(3);
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail353.d b/gcc/testsuite/gdc.test/fail_compilation/fail353.d
deleted file mode 100644
index 56cda779d9f..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail353.d
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-TEST_OUTPUT:
----
-block displacement of -130 exceeds the maximum offset of -128 to 127.
----
-*/
-
-void foo()
-{
-    enum NOP = 0x9090_9090_9090_9090;
-
-    version(GNU)
-    {
-        version(X86) asm {
-            "L1:"
-            "dq %0,%0,%0,%0;"
-            "dq %0,%0,%0,%0;"
-            "dq %0,%0,%0,%0;"
-            "dq %0,%0,%0,%0;"
-            "loop L1;" : "n" (NOP) : : ;
-        }
-        else version(X86_64) asm {
-            "L1:"
-            "dq %0,%0,%0,%0;"
-            "dq %0,%0,%0,%0;"
-            "dq %0,%0,%0,%0;"
-            "dq %0,%0,%0,%0;"
-            "loop L1;" : "n" (NOP) : : ;
-        }
-        else static assert(false, "ASM code not implemented for this architecture");
-    }
-    else asm
-    {
-    L1:
-        dq NOP,NOP,NOP,NOP;    //  32
-        dq NOP,NOP,NOP,NOP;    //  64
-        dq NOP,NOP,NOP,NOP;    //  96
-        dq NOP,NOP,NOP,NOP;    // 128
-        // unnoticed signed underflow of rel8 with DMD2.056
-        loop L1;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail8168.d b/gcc/testsuite/gdc.test/fail_compilation/fail8168.d
deleted file mode 100644
index ed1c307d4bc..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail8168.d
+++ /dev/null
@@ -1,6 +0,0 @@
-void main() {
-    asm {
-        unknown; // wrong opcode
-    }
-}
-
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice15239.d b/gcc/testsuite/gdc.test/fail_compilation/ice15239.d
deleted file mode 100644
index 6512d858c17..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/ice15239.d
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/ice15239.d(21): Error: cannot interpret opDispatch!"foo" at compile time
-fail_compilation/ice15239.d(21): Error: bad type/size of operands '__error'
----
-*/
-
-struct T
-{
-    template opDispatch(string Name, P...)
-    {
-        static void opDispatch(P) {}
-    }
-}
-
-void main()
-{
-    asm
-    {
-        call T.foo;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test12979.d b/gcc/testsuite/gdc.test/fail_compilation/test12979.d
deleted file mode 100644
index 95cd3aae1e1..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/test12979.d
+++ /dev/null
@@ -1,16 +0,0 @@
-// PERMUTE_ARGS:
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/test12979.d(13): Error: const/immutable/shared/inout attributes are not allowed on `asm` blocks
----
-*/
-
-void foo()
-{
-    asm const shared
-    {
-        ret;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/runnable/argufilem.d b/gcc/testsuite/gdc.test/runnable/argufilem.d
deleted file mode 100644
index 44d627005cc..00000000000
--- a/gcc/testsuite/gdc.test/runnable/argufilem.d
+++ /dev/null
@@ -1,22 +0,0 @@
-// EXTRA_SOURCES: imports/argufile.d
-
-// NOTE: The bug only works when main.d and argufile.d are put in
-//                      separate files and compiled like 'dmd main.d argufile.d'
-//                      Also, I'm sure writefln is causing the crash cause when I
-//                      use printf(), it doesn't crash.
-
-// main.d -------------------------------------------------------
-
-import argufile;
-
-int main(string[] args)
-{
-        string message = arguments("bob is ", 7, " years old");
-
-        writefln(message);
-
-        argufile.useargs(); // will crash here
-
-        return 0;
-}
-
diff --git a/gcc/testsuite/gdc.test/runnable/ctorpowtests.d b/gcc/testsuite/gdc.test/runnable/ctorpowtests.d
index 2fb458e44f1..b193d3b1e02 100644
--- a/gcc/testsuite/gdc.test/runnable/ctorpowtests.d
+++ b/gcc/testsuite/gdc.test/runnable/ctorpowtests.d
@@ -5,18 +5,8 @@ int magicVariable()
   if (__ctfe)
    return 3;
 
-  version(GNU)
-  {
-    version(X86)
-      asm { "nop"; }
-    else version(X86_64)
-      asm { "nop"; }
-    else
-      static assert("");
-  }
-  else
-      asm { nop; }
-  return 2;
+  shared int var = 2;
+  return var;
 }
 
 static assert(magicVariable()==3);
@@ -122,20 +112,14 @@ struct StructWithCtor
     float x;
 }
 
-int containsAsm() {
-       version(GNU)
-       {
-         version(X86)
-           asm { "nop"; }
-         else version(X86_64)
-           asm { "nop"; }
-         else
-           static assert("");
-       }
-       else
-          asm { nop; }
-       return 0;
-    }
+int containsAsm()
+{
+    version (D_InlineAsm_X86)
+        asm { nop; }
+    else version (D_InlineAsm_X86_64)
+        asm { nop; }
+    return 0;
+}
 
 enum A = StructWithCtor(1);
 enum B = StructWithCtor(7, 2.3);
diff --git a/gcc/testsuite/gdc.test/runnable/imports/argufile.d b/gcc/testsuite/gdc.test/runnable/imports/argufile.d
deleted file mode 100644
index 2a85547d8ab..00000000000
--- a/gcc/testsuite/gdc.test/runnable/imports/argufile.d
+++ /dev/null
@@ -1,146 +0,0 @@
-// argufile.d ----------------------------------------------------
-
-public:
-
-import core.vararg;
-import std.stdio;
-import std.utf;
-
-dstring formatstring(TypeInfo[] arguments, va_list argptr)
-{
-
-	dstring message = null;
-
-	void putc(dchar c)
-	{
-		message ~= c;
-	}
-
-
-	doFormat(&putc, arguments, argptr);
-
-
-	return message;
-}
-
-string arguments(...) // turns a bunch of arguments into a formatted char[] string
-{
-	return std.utf.toUTF8(formatstring(_arguments, _argptr));
-}
-
-void useargs(...)
-{
-	string crashage = arguments("why is 8 scared of 7? because", 7,8,9);
-
-	//printf("%.*s\n", crashage);
-	writefln(crashage);
-}
-
-
-// dustmited version of the deprecated doFormat.
-// See the full file at:
-// https://github.com/dlang/undeaD/blob/master/src/undead/doformat.d
-void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list ap)
-{
-    import core.stdc.stdlib : alloca, malloc;
-    import std.format ;
-
-    size_t bufLength = 1024;
-    void* argBuffer = malloc(bufLength);
-    size_t bufUsed ;
-    foreach (ti; arguments)
-    {
-        auto pos = bufUsed;
-        // Align to next word boundary
-        bufUsed += ti.tsize + size_t.sizeof - 1;
-        bufUsed -= bufUsed& size_t.sizeof - 1;
-        // Copy argument into buffer
-        va_arg(ap, ti, argBuffer + pos);
-    }
-
-    auto argptr = argBuffer;
-    void* skipArg(TypeInfo ti)
-    {
-        auto p = argptr;
-        // Align to next word boundary
-        argptr += ti.tsize + size_t.sizeof - 1;
-        argptr -= cast(size_t)argptr & size_t.sizeof - 1;
-        return p;
-    }
-    auto getArg(T)()
-    {
-        return *cast(T*)skipArg(typeid(T));
-    }
-
-    TypeInfo ti;
-    Mangle m;
-    void formatArg()
-    {
-        ulong vnumber;
-        char vchar;
-        Mangle m2;
-        int signed ;
-        string s;
-
-        void putstr(const char[] s)
-        {
-            foreach (c; s)
-                putc(c);
-
-        }
-
-        //printf("formatArg(fc = '%c', m = '%c')\n", fc, m);
-        int mi;
-        switch (m)
-        {
-            L2:
-                putstr((&vchar)[0 .. 1]);
-                return;
-
-            case Mangle.Tint:
-                signed = 1;
-                vnumber = getArg!int;
-                goto Lnumber;
-
-            case Mangle.Tarray:
-                mi = 10;
-while (1)
-                {
-                    m2 = cast(Mangle)typeid(ti).name[mi];
-                    switch (m2)
-                    {
-                        case Mangle.Tchar:
-                            s = getArg!string;
-                            putstr(s);
-                            break;
-
-                        case Mangle.Timmutable:
-                            mi++;
-                            continue;
-
-                        default:
-                            {}
-                    }
-                    return;
-                }
-            default:
-                {}
-        }
-
-    Lnumber:
-;
-vchar = cast(char)('0' + vnumber);
-                goto L2;
-    }
-
-    for (int j ; j < arguments.length; )
-    {
-        ti = arguments[j++];
-        int mi = 9;
-        do
-            m = cast(Mangle)typeid(ti).name[mi++];
-while (m == Mangle.Tconst );
-
-            formatArg;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/runnable/test23.d b/gcc/testsuite/gdc.test/runnable/test23.d
index 3a7beaf187e..ee17be0b00f 100644
--- a/gcc/testsuite/gdc.test/runnable/test23.d
+++ b/gcc/testsuite/gdc.test/runnable/test23.d
@@ -357,36 +357,22 @@ void test16()
 
 void test17()
 {
+    version(D_InlineAsm_X86_64)
+        enum AsmX86 = true;
+    else version(D_InlineAsm_X86)
+        enum AsmX86 = true;
+    else
+        enum AsmX86 = false;
+
     version (OSX)
     {
     }
     else
     {
-        /*const*/ float f = 1.2f;
+        const f = 1.2f;
         float g = void;
 
-
-        version(D_SoftFloat)
-        {
-            g = f;
-        }
-        else version(GNU)
-        {
-            version(X86) asm
-            {
-                "flds %1; fstps %0;" : "=m" (g) : "m" (f) : ;
-            }
-            else version(X86_64) asm
-            {
-                "flds %1; fstps %0;" : "=m" (g) : "m" (f) : ;
-            }
-            else version(ARM) asm
-            {
-                "vldr d0, %1; vstr d0, %0;" : "=m" (g) : "m" (f), : "d0";
-            }
-            else static assert(false, "ASM code not implemented for this architecture");
-        }
-        else
+        static if (AsmX86)
         {
             asm
             {
@@ -394,6 +380,10 @@ void test17()
                 fstp g;
             }
         }
+        else
+        {
+            g = f;
+        }
         assert(g == 1.2f);
     }
 }
diff --git a/gcc/testsuite/gdc.test/runnable/test34.d b/gcc/testsuite/gdc.test/runnable/test34.d
index 003024db977..5c28d0f8252 100644
--- a/gcc/testsuite/gdc.test/runnable/test34.d
+++ b/gcc/testsuite/gdc.test/runnable/test34.d
@@ -707,24 +707,7 @@ void foo35()
         c = 3;
 
         xxx = cast(typeof(xxx))(a + b);
-        version(GNU)
-        {
-            version(X86) asm
-            {
-                "int $3;" : : : ;
-            }
-            else version(X86_64) asm
-            {
-                "int $3;" : : : ;
-            }
-            else
-            {
-                import gcc.builtins;
-                __builtin_trap();
-            }
-        }
-        else
-            asm { int 3; }
+        throw new Exception("xxx");
         xxx( 4, 5, 6 );
 }
 
diff --git a/gcc/testsuite/gdc.test/runnable/test36.d b/gcc/testsuite/gdc.test/runnable/test36.d
deleted file mode 100644
index 9f5b140127d..00000000000
--- a/gcc/testsuite/gdc.test/runnable/test36.d
+++ /dev/null
@@ -1,109 +0,0 @@
-// PERMUTE_ARGS:
-
-import std.stdio;
-interface IUnknown{
-        extern(Windows):
-        void func();
-}
-class ComObject :IUnknown
-{
-extern (Windows):
-        void func()
-        {writefln(`comobject`);
-        }
-}
-interface IDataObject: IUnknown
-{
-        extern(Windows):
-        void method();
-}
-package class invarianttest:ComObject, IDataObject
-{
-        invariant()
-        {
-                writefln(`hello invariant`);
-        }
-
-extern (Windows):
-        override void func()
-        {
-        int esp;
-        version(GNU)
-        {
-            version(X86) asm
-            {
-                "mov %%ESP,%0" : "=r" esp : : ;
-            }
-            else version(X86_64) asm
-            {
-                "mov %%ESP,%0" : "=r" esp : : ;
-            }
-            else version(ARM) asm
-            {
-                "str sp,%0" : "=m" esp : : ;
-            }
-            else static assert(false, "ASM code not implemented for this architecture");
-        }
-        else asm
-        {
-                mov esp,ESP;
-        }
-        printf("\n%d",esp);
-        printf(`func`);
-        }
-        void method()
-        {
-                writefln(`method`);
-        }
-}
-int main()
-{
-        auto inst= new invarianttest;
-        int esp;
-        version(GNU)
-        {
-            version(X86) asm
-            {
-                "mov %%ESP,%0" : "=r" esp : : ;
-            }
-            else version(X86_64) asm
-            {
-                "mov %%ESP,%0" : "=r" esp : : ;
-            }
-            else version(ARM) asm
-            {
-                "str sp,%0" : "=m" esp : : ;
-            }
-            else static assert(false, "ASM code not implemented for this architecture");
-        }
-        else asm
-        {
-                mov esp,ESP;
-        }
-        inst.func();
-        inst.method();
-        writefln("\n%d",esp);
-        version(GNU)
-        {
-            version(X86) asm
-            {
-                "mov %%ESP,%0" : "=r" esp : : ;
-            }
-            else version(X86_64) asm
-            {
-                "mov %%ESP,%0" : "=r" esp : : ;
-            }
-            else version(ARM) asm
-            {
-                "str sp,%0" : "=m" esp : : ;
-            }
-            else static assert(false, "ASM code not implemented for this architecture");
-        }
-        else asm
-        {
-                mov esp,ESP;
-        }
-        writefln("\n%d",esp);
-        return 0;
-}
-
diff --git a/gcc/testsuite/gdc.test/runnable/test42.d b/gcc/testsuite/gdc.test/runnable/test42.d
index e75eb70da97..b9619c992ff 100644
--- a/gcc/testsuite/gdc.test/runnable/test42.d
+++ b/gcc/testsuite/gdc.test/runnable/test42.d
@@ -2469,40 +2469,21 @@ bool foo150()
 void crash(int x)
 {
     if (x==200) return;
-
-    version(GNU)
-    {
-        version(X86) asm
-        {
-            "int $3;" : :  :;
-        }
-        else version(X86_64) asm
-        {
-            "int $3;" : : :;
-        }
-        else
-        {
-            import gcc.builtins;
-            __builtin_trap();
-        }
-    }
-    else
-    {
-        asm { int 3; }
-    }
+    assert(0);
 }
 
 void test151()
 {
-   int x;
-   bug3521(&x);
+    int x;
+    bug3521(&x);
 }
 
-void bug3521(int *a){
+void bug3521(int *a)
+{
     int c = 0;
     *a = 0;
     if ( *a || (*a != (c = 200)) )
-       crash(c);
+        crash(c);
 }
 
 /***************************************************/
@@ -4236,28 +4217,22 @@ void oddity4001()
 }
 
 /***************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=3809
 
 int bug3809()
 {
-    version(GNU)
-    {
-        version(X86)
-            asm { "nop"; }
-        else version(X86_64)
-            asm { "nop"; }
-        else version(ARM)
-            asm { "nop"; }
-        else
-            static assert(false, "ASM code not implemented for this architecture");
-    }
-    else
-    {
-        asm { nop; }
-    }
-    return 0;
+    static int a = 0;
+    return a;
 }
-struct BUG3809 { int xx; }
-void bug3809b() {
+
+struct BUG3809
+{
+    int xx;
+}
+
+void bug3809b()
+{
+    BUG3809 b = { bug3809() };
 }
 
 /***************************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/testsafe.d b/gcc/testsuite/gdc.test/runnable/testsafe.d
index 543fef589ab..cec4c0f7fa4 100644
--- a/gcc/testsuite/gdc.test/runnable/testsafe.d
+++ b/gcc/testsuite/gdc.test/runnable/testsafe.d
@@ -207,18 +207,9 @@ void safeexception()
 @safe
 void inlineasm()
 {
-    version(GNU)
-    {
-        version(X86)
-            static assert(!__traits(compiles, { asm { "nop"; } }() ));
-        else version(X86_64)
-            static assert(!__traits(compiles, { asm { "nop"; } }() ));
-        else version(ARM)
-            static assert(!__traits(compiles, { asm { "nop"; } }() ));
-        else
-            static assert(false, "ASM code not implemented for this architecture");
-    }
-    else
+    version (D_InlineAsm_X86)
+        static assert(!__traits(compiles, { asm { int 3; } }() ));
+    else version (D_InlineAsm_X86_64)
         static assert(!__traits(compiles, { asm { int 3; } }() ));
 }
 
diff --git a/gcc/testsuite/lib/gdc.exp b/gcc/testsuite/lib/gdc.exp
index e64b7708520..c749c4c055d 100644
--- a/gcc/testsuite/lib/gdc.exp
+++ b/gcc/testsuite/lib/gdc.exp
@@ -192,6 +192,8 @@ proc gdc_init { args } {
     global GDC_UNDER_TEST
     global TESTING_IN_BUILD_TREE
     global TEST_ALWAYS_FLAGS
+    global gcc_warning_prefix
+    global gcc_error_prefix
 
     # We set LC_ALL and LANG to C so that we get the same error messages as expected.
     setenv LC_ALL C
@@ -250,6 +252,9 @@ proc gdc_init { args } {
 
     verbose -log "ALWAYS_DFLAGS set to $ALWAYS_DFLAGS"
 
+    set gcc_warning_prefix "warning:"
+    set gcc_error_prefix "(fatal )?error:"
+
     verbose "gdc is initialized" 3
 }
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2018-12-17 18:33 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2018-12-17 18:33 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 404 bytes --]

Hi,

This patch merges the D front-end implementation with dmd upstream 237ca3fbe.

Backports a fix where a bad cast to TypeFunction resulted in memory
corruption.  The logic in the function semantic has been fixed, and
casts have been replaced with a function call to always check the
front-end AST node value.

Bootstrapped and tested on x86_64-linux-gnu.

Committed to trunk as r267207.

-- 
Iain
---

[-- Attachment #2: dmd237ca3fbe.patch --]
[-- Type: text/x-patch, Size: 16607 bytes --]

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index a1a1fa0efd1..bc35d4adc1f 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-e2fe2687b817a201528abaa3aa882333e04db01b
+237ca3fbe8f9ac4b64e26ce912c20439ee4fc63a
 
 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/dclass.c b/gcc/d/dmd/dclass.c
index 6fe17b36576..ce9849fc7dd 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -805,7 +805,7 @@ Lancestorsdone:
         if (fd && !fd->errors)
         {
             //printf("Creating default this(){} for class %s\n", toChars());
-            TypeFunction *btf = (TypeFunction *)fd->type;
+            TypeFunction *btf = fd->type->toTypeFunction();
             TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class);
             tf->mod = btf->mod;
             tf->purity = btf->purity;
@@ -1152,7 +1152,7 @@ int isf(void *param, Dsymbol *s)
 
 bool ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
 {
-    //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
+    //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toPrettyChars());
     Dsymbol *s = search(Loc(), fd->ident, IgnoreAmbiguous | IgnoreErrors);
     if (!s)
     {
@@ -1749,6 +1749,7 @@ bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
         //printf("\tX base %s\n", b->sym->toChars());
         if (this == b->sym)
         {
+            //printf("\tfound at offset %d\n", b->offset);
             if (poffset)
             {
                 // don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980
@@ -1882,8 +1883,7 @@ bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newin
 
         assert(ifd);
         // Find corresponding function in this class
-        tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
-        assert(tf);  // should always be non-null
+        tf = ifd->type->toTypeFunction();
         fd = cd->findFunc(ifd->ident, tf);
         if (fd && !fd->isAbstract())
         {
diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c
index f9f15ba9092..77d6174241d 100644
--- a/gcc/d/dmd/dstruct.c
+++ b/gcc/d/dmd/dstruct.c
@@ -46,7 +46,7 @@ FuncDeclaration *search_toString(StructDeclaration *sd)
         if (!tftostring)
         {
             tftostring = new TypeFunction(NULL, Type::tstring, 0, LINKd);
-            tftostring = (TypeFunction *)tftostring->merge();
+            tftostring = tftostring->merge()->toTypeFunction();
         }
 
         fd = fd->overloadExactMatch(tftostring);
@@ -92,6 +92,7 @@ void semanticTypeInfo(Scope *sc, Type *t)
         }
         void visit(TypeStruct *t)
         {
+            //printf("semanticTypeInfo::visit(TypeStruct = %s)\n", t->toChars());
             StructDeclaration *sd = t->sym;
 
             /* Step 1: create TypeInfoDeclaration
diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c
index c8f9c5c350a..4e1b3e2d2d3 100644
--- a/gcc/d/dmd/func.c
+++ b/gcc/d/dmd/func.c
@@ -411,8 +411,8 @@ static bool canInferAttributes(FuncDeclaration *fd, Scope *sc)
  */
 static void initInferAttributes(FuncDeclaration *fd)
 {
-    assert(fd->type->ty == Tfunction);
-    TypeFunction *tf = (TypeFunction *)fd->type;
+    //printf("initInferAttributes() for %s\n", toPrettyChars());
+    TypeFunction *tf = fd->type->toTypeFunction();
     if (tf->purity == PUREimpure) // purity not specified
         fd->flags |= FUNCFLAGpurityInprocess;
 
@@ -495,7 +495,7 @@ void FuncDeclaration::semantic(Scope *sc)
             fld->tok = TOKfunction;
         else
             assert(0);
-        linkage = ((TypeFunction *)treq->nextOf())->linkage;
+        linkage = treq->nextOf()->toTypeFunction()->linkage;
     }
     else
         linkage = sc->linkage;
@@ -505,11 +505,21 @@ void FuncDeclaration::semantic(Scope *sc)
 
     if (!originalType)
         originalType = type->syntaxCopy();
+    if (type->ty != Tfunction)
+    {
+        if (type->ty != Terror)
+        {
+            error("%s must be a function instead of %s", toChars(), type->toChars());
+            type = Type::terror;
+        }
+        errors = true;
+        return;
+    }
     if (!type->deco)
     {
         sc = sc->push();
         sc->stc |= storage_class & (STCdisable | STCdeprecated);  // forward to function type
-        TypeFunction *tf = (TypeFunction *)type;
+        TypeFunction *tf = type->toTypeFunction();
 
         if (sc->func)
         {
@@ -678,8 +688,8 @@ void FuncDeclaration::semantic(Scope *sc)
     {
         // Merge back function attributes into 'originalType'.
         // It's used for mangling, ddoc, and json output.
-        TypeFunction *tfo = (TypeFunction *)originalType;
-        TypeFunction *tfx = (TypeFunction *)type;
+        TypeFunction *tfo = originalType->toTypeFunction();
+        TypeFunction *tfx = type->toTypeFunction();
         tfo->mod        = tfx->mod;
         tfo->isscope    = tfx->isscope;
         tfo->isscopeinferred = tfx->isscopeinferred;
@@ -1132,8 +1142,7 @@ void FuncDeclaration::semantic(Scope *sc)
         error("override only applies to class member functions");
 
     // Reflect this->type to f because it could be changed by findVtblIndex
-    assert(type->ty == Tfunction);
-    f = (TypeFunction *)type;
+    f = type->toTypeFunction();
 
     /* Do not allow template instances to add virtual functions
      * to a class.
@@ -2560,8 +2569,7 @@ void FuncDeclaration::buildResultVar(Scope *sc, Type *tret)
 
     if (sc && vresult->semanticRun == PASSinit)
     {
-        assert(type->ty == Tfunction);
-        TypeFunction *tf = (TypeFunction *)type;
+        TypeFunction *tf = type->toTypeFunction();
         if (tf->isref)
             vresult->storage_class |= STCref;
         vresult->type = tret;
@@ -3135,7 +3143,7 @@ FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &h
             return 0;
 
         m->anyf = f;
-        TypeFunction *tf = (TypeFunction *)f->type;
+        TypeFunction *tf = f->type->toTypeFunction();
         //printf("tf = %s\n", tf->toChars());
 
         MATCH match;
@@ -3205,7 +3213,7 @@ FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &h
     else                    // no match
     {
         hasOverloads = true;
-        TypeFunction *tf = (TypeFunction *)this->type;
+        TypeFunction *tf = this->type->toTypeFunction();
         assert(tthis);
         assert(!MODimplicitConv(tthis->mod, tf->mod));  // modifier mismatch
         {
@@ -3270,8 +3278,8 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
      * as g() is.
      */
 
-    TypeFunction *tf = (TypeFunction *)type;
-    TypeFunction *tg = (TypeFunction *)g->type;
+    TypeFunction *tf = type->toTypeFunction();
+    TypeFunction *tg = g->type->toTypeFunction();
     size_t nfparams = Parameter::dim(tf->parameters);
 
     /* If both functions have a 'this' pointer, and the mods are not
@@ -3524,7 +3532,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
             assert(fd);
 
             bool hasOverloads = fd->overnext != NULL;
-            TypeFunction *tf = (TypeFunction *)fd->type;
+            TypeFunction *tf = fd->type->toTypeFunction();
             if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch
             {
                 OutBuffer thisBuf, funcBuf;
@@ -3562,8 +3570,8 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
     }
     else if (m.nextf)
     {
-        TypeFunction *tf1 = (TypeFunction *)m.lastf->type;
-        TypeFunction *tf2 = (TypeFunction *)m.nextf->type;
+        TypeFunction *tf1 = m.lastf->type->toTypeFunction();
+        TypeFunction *tf2 = m.nextf->type->toTypeFunction();
         const char *lastprms = parametersTypeToChars(tf1->parameters, tf1->varargs);
         const char *nextprms = parametersTypeToChars(tf2->parameters, tf2->varargs);
         ::error(loc, "%s.%s called with argument types %s matches both:\n"
@@ -3679,7 +3687,7 @@ const char *FuncDeclaration::toPrettyChars(bool QualifyTypes)
 const char *FuncDeclaration::toFullSignature()
 {
     OutBuffer buf;
-    functionToBufferWithIdent((TypeFunction *)type, &buf, toChars());
+    functionToBufferWithIdent(type->toTypeFunction(), &buf, toChars());
     return buf.extractString();
 }
 
@@ -3776,8 +3784,7 @@ bool FuncDeclaration::isOverloadable()
 PURE FuncDeclaration::isPure()
 {
     //printf("FuncDeclaration::isPure() '%s'\n", toChars());
-    assert(type->ty == Tfunction);
-    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tf = type->toTypeFunction();
     if (flags & FUNCFLAGpurityInprocess)
         setImpure();
     if (tf->purity == PUREfwdref)
@@ -3829,10 +3836,9 @@ bool FuncDeclaration::setImpure()
 
 bool FuncDeclaration::isSafe()
 {
-    assert(type->ty == Tfunction);
     if (flags & FUNCFLAGsafetyInprocess)
         setUnsafe();
-    return ((TypeFunction *)type)->trust == TRUSTsafe;
+    return type->toTypeFunction()->trust == TRUSTsafe;
 }
 
 bool FuncDeclaration::isSafeBypassingInference()
@@ -3842,10 +3848,9 @@ bool FuncDeclaration::isSafeBypassingInference()
 
 bool FuncDeclaration::isTrusted()
 {
-    assert(type->ty == Tfunction);
     if (flags & FUNCFLAGsafetyInprocess)
         setUnsafe();
-    return ((TypeFunction *)type)->trust == TRUSTtrusted;
+    return type->toTypeFunction()->trust == TRUSTtrusted;
 }
 
 /**************************************
@@ -3858,7 +3863,7 @@ bool FuncDeclaration::setUnsafe()
     if (flags & FUNCFLAGsafetyInprocess)
     {
         flags &= ~FUNCFLAGsafetyInprocess;
-        ((TypeFunction *)type)->trust = TRUSTsystem;
+        type->toTypeFunction()->trust = TRUSTsystem;
         if (fes)
             fes->func->setUnsafe();
     }
@@ -3869,10 +3874,9 @@ bool FuncDeclaration::setUnsafe()
 
 bool FuncDeclaration::isNogc()
 {
-    assert(type->ty == Tfunction);
     if (flags & FUNCFLAGnogcInprocess)
         setGC();
-    return ((TypeFunction *)type)->isnogc;
+    return type->toTypeFunction()->isnogc;
 }
 
 bool FuncDeclaration::isNogcBypassingInference()
@@ -3891,7 +3895,7 @@ bool FuncDeclaration::setGC()
     if (flags & FUNCFLAGnogcInprocess)
     {
         flags &= ~FUNCFLAGnogcInprocess;
-        ((TypeFunction *)type)->isnogc = false;
+        type->toTypeFunction()->isnogc = false;
         if (fes)
             fes->func->setGC();
     }
@@ -4000,8 +4004,7 @@ bool traverseIndirections(Type *ta, Type *tb, void *p = NULL, bool reversePass =
 
 bool FuncDeclaration::isolateReturn()
 {
-    assert(type->ty == Tfunction);
-    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tf = type->toTypeFunction();
     assert(tf->next);
 
     Type *treti = tf->next;
@@ -4022,8 +4025,7 @@ bool FuncDeclaration::parametersIntersect(Type *t)
     if (!isPureBypassingInference() || isNested())
         return false;
 
-    assert(type->ty == Tfunction);
-    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tf = type->toTypeFunction();
 
     //printf("parametersIntersect(%s) t = %s\n", tf->toChars(), t->toChars());
 
@@ -4229,7 +4231,7 @@ FuncDeclaration *FuncDeclaration::genCfunc(Parameters *fparams, Type *treturn, I
  */
 void FuncDeclaration::checkDmain()
 {
-    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tf = type->toTypeFunction();
     const size_t nparams = Parameter::dim(tf->parameters);
     bool argerr = false;
     if (nparams == 1)
@@ -4608,8 +4610,7 @@ Parameters *FuncDeclaration::getParameters(int *pvarargs)
 
     if (type)
     {
-        assert(type->ty == Tfunction);
-        TypeFunction *fdtype = (TypeFunction *)type;
+        TypeFunction *fdtype = type->toTypeFunction();
         fparameters = fdtype->parameters;
         fvarargs = fdtype->varargs;
     }
@@ -4752,7 +4753,7 @@ void FuncLiteralDeclaration::modifyReturns(Scope *sc, Type *tret)
     // This is required so the code generator does not try to cast the
     // modified returns back to the original type.
     if (inferRetType && type->nextOf() != tret)
-        ((TypeFunction *)type)->next = tret;
+        type->toTypeFunction()->next = tret;
 }
 
 const char *FuncLiteralDeclaration::kind() const
@@ -4820,8 +4821,7 @@ void CtorDeclaration::semantic(Scope *sc)
     if (errors)
         return;
 
-    TypeFunction *tf = (TypeFunction *)type;
-    assert(tf && tf->ty == Tfunction);
+    TypeFunction *tf = type->toTypeFunction();
 
     /* See if it's the default constructor
      * But, template constructor should not become a default constructor.
@@ -5502,10 +5502,9 @@ void NewDeclaration::semantic(Scope *sc)
         type = new TypeFunction(parameters, tret, varargs, LINKd, storage_class);
 
     type = type->semantic(loc, sc);
-    assert(type->ty == Tfunction);
 
     // Check that there is at least one argument of type size_t
-    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tf = type->toTypeFunction();
     if (Parameter::dim(tf->parameters) < 1)
     {
         error("at least one argument of type size_t expected");
@@ -5581,10 +5580,9 @@ void DeleteDeclaration::semantic(Scope *sc)
         type = new TypeFunction(parameters, Type::tvoid, 0, LINKd, storage_class);
 
     type = type->semantic(loc, sc);
-    assert(type->ty == Tfunction);
 
     // Check that there is only one argument of type void*
-    TypeFunction *tf = (TypeFunction *)type;
+    TypeFunction *tf = type->toTypeFunction();
     if (Parameter::dim(tf->parameters) != 1)
     {
         error("one argument of type void* expected");
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index b35b7af3201..52598033832 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -2345,6 +2345,12 @@ TypeBasic *Type::isTypeBasic()
     return NULL;
 }
 
+TypeFunction *Type::toTypeFunction()
+{
+    if (ty != Tfunction)
+        assert(0);
+    return (TypeFunction *)this;
+}
 
 /***************************************
  * Resolve 'this' type to either type, symbol, or expression.
@@ -4808,14 +4814,14 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int
             Parameters *fparams = new Parameters();
             fparams->push(new Parameter(STCin, this, NULL, NULL));
             fd_aaLen = FuncDeclaration::genCfunc(fparams, Type::tsize_t, Id::aaLen);
-            TypeFunction *tf = (TypeFunction *)fd_aaLen->type;
+            TypeFunction *tf = fd_aaLen->type->toTypeFunction();
             tf->purity = PUREconst;
             tf->isnothrow = true;
             tf->isnogc = false;
         }
         Expression *ev = new VarExp(e->loc, fd_aaLen, false);
         e = new CallExp(e->loc, ev, e);
-        e->type = ((TypeFunction *)fd_aaLen->type)->next;
+        e->type = fd_aaLen->type->toTypeFunction()->next;
     }
     else
         e = Type::dotExp(sc, e, ident, flag);
@@ -5425,7 +5431,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
      * This can produce redundant copies if inferring return type,
      * as semantic() will get called again on this.
      */
-    TypeFunction *tf = (TypeFunction *)copy();
+    TypeFunction *tf = copy()->toTypeFunction();
     if (parameters)
     {
         tf->parameters = parameters->copy();
@@ -6283,7 +6289,7 @@ Expression *TypeFunction::defaultInit(Loc loc)
 Type *TypeFunction::addStorageClass(StorageClass stc)
 {
     //printf("addStorageClass(%llx) %d\n", stc, (stc & STCscope) != 0);
-    TypeFunction *t = (TypeFunction *)Type::addStorageClass(stc);
+    TypeFunction *t = Type::addStorageClass(stc)->toTypeFunction();
     if ((stc & STCpure && !t->purity) ||
         (stc & STCnothrow && !t->isnothrow) ||
         (stc & STCnogc && !t->isnogc) ||
@@ -9181,7 +9187,7 @@ Type *Parameter::isLazyArray()
         if (tel->ty == Tdelegate)
         {
             TypeDelegate *td = (TypeDelegate *)tel;
-            TypeFunction *tf = (TypeFunction *)td->next;
+            TypeFunction *tf = td->next->toTypeFunction();
 
             if (!tf->varargs && Parameter::dim(tf->parameters) == 0)
             {
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index c3b8a979bbe..b459fdf869f 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -335,6 +335,7 @@ public:
     virtual bool needsDestruction();
     virtual bool needsNested();
     void checkComplexTransition(Loc loc);
+    TypeFunction *toTypeFunction();
 
     static void error(Loc loc, const char *format, ...);
     static void warning(Loc loc, const char *format, ...);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, d] Committed merge with upstream dmd
@ 2018-11-04 23:34 Iain Buclaw
  0 siblings, 0 replies; 14+ messages in thread
From: Iain Buclaw @ 2018-11-04 23:34 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1500 bytes --]

Hi,

I've merged into the D front-end patches sent to upstream dmd, most
address problems found when building the compiler on OSX and Solaris.

This introduces a new header that pulls in system includes for use
only in the DMD front-end part of the compiler, fixing up uses of
problematic functions that are prevalent throughout the code.

Commits merged from dmd.

    Fix build of the D frontend on the Hurd and KFreeBSD.
    Initial patch from Matthias Klose.
    https://github.com/dlang/dmd/pull/8893

    Don't care about D/C++ compatibility in C++ port.
    Fixes build error in https://gcc.gnu.org/PR87788
    https://github.com/dlang/dmd/pull/8895

    Allow compiling front-end headers with strict warnings.
    https://github.com/dlang/dmd/pull/8909

    Add root/system.h header for wrapping system includes.
    Fixes https://gcc.gnu.org/PR87865
    https://github.com/dlang/dmd/pull/8910

    Move checkedint to dmd/root.
    https://github.com/dlang/dmd/pull/8912

    Use rmem instead of libc for malloc() and strdup().
    https://github.com/dlang/dmd/pull/8913

    Use align(8) for alignment of UnionExp, fixing several BUS errors
    due to alignment issues on SPARC.
    https://github.com/dlang/dmd/pull/8914

    Don't pass NULL pointer as format parameter to errorSupplemental.
    https://github.com/dlang/dmd/pull/8916

-- 
Iain

---
    gcc/d/ChangeLog:

    2018-11-05  Iain Buclaw  <ibuclaw@gdcproject.org>

            PR d/87865
            * d-system.h: New file.
---

[-- Attachment #2: dmd-6243fa6d2.patch --]
[-- Type: text/x-patch, Size: 69135 bytes --]

diff --git a/gcc/d/d-system.h b/gcc/d/d-system.h
new file mode 100644
index 00000000000..25a83b675b5
--- /dev/null
+++ b/gcc/d/d-system.h
@@ -0,0 +1,53 @@
+/* d-system.h -- DMD frontend inclusion of gcc header files.
+ * Copyright (C) 2018 Free Software Foundation, Inc.
+ *
+ * GCC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GCC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GCC; see the file COPYING3.  If not see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCC_D_SYSTEM_H
+#define GCC_D_SYSTEM_H
+
+#include "config.h"
+#include "system.h"
+
+/* Used by the dmd front-end to determine if we have POSIX-style IO.  */
+#define POSIX (__linux__ || __GLIBC__ || __gnu_hurd__ || __APPLE__ \
+	       || __FreeBSD__ || __OpenBSD__ || __DragonFly__ || __sun)
+
+/* Forward assert invariants to gcc_assert.  */
+#undef assert
+#define assert(EXPR) gcc_assert(EXPR)
+
+/* Forward ctype.h macros used by the dmd front-end to safe-ctype.h.  */
+#undef isalpha
+#define isalpha(c) ISALPHA(c)
+#undef isalnum
+#define isalnum(c) ISALNUM(c)
+#undef isdigit
+#define isdigit(c) ISDIGIT(c)
+#undef islower
+#define islower(c) ISLOWER(c)
+#undef isprint
+#define isprint(c) ISPRINT(c)
+#undef isspace
+#define isspace(c) ISSPACE(c)
+#undef isupper
+#define isupper(c) ISUPPER(c)
+#undef isxdigit
+#define isxdigit(c) ISXDIGIT(c)
+#undef tolower
+#define tolower(c) TOLOWER(c)
+
+#endif  /* GCC_D_SYSTEM_H  */
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
new file mode 100644
index 00000000000..7727205bed4
--- /dev/null
+++ b/gcc/d/dmd/MERGE
@@ -0,0 +1,4 @@
+6243fa6d2ceab4615a9fe21c5bc9484e52bb2d1e
+
+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/access.c b/gcc/d/dmd/access.c
index 37e9c8681d3..cd60cedc2a5 100644
--- a/gcc/d/dmd/access.c
+++ b/gcc/d/dmd/access.c
@@ -7,10 +7,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/access.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
 #include "root/rmem.h"
 
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index d7db82b0f0e..cac0b8efd9f 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -191,7 +191,7 @@ public:
     void semantic(Scope *sc);
     void semanticTypeInfoMembers();
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
-    const char *kind();
+    const char *kind() const;
     void finalizeSize();
     bool fit(Loc loc, Scope *sc, Expressions *elements, Type *stype);
     bool isPOD();
@@ -205,7 +205,7 @@ class UnionDeclaration : public StructDeclaration
 public:
     UnionDeclaration(Loc loc, Identifier *id);
     Dsymbol *syntaxCopy(Dsymbol *s);
-    const char *kind();
+    const char *kind() const;
 
     UnionDeclaration *isUnionDeclaration() { return this; }
     void accept(Visitor *v) { v->visit(this); }
@@ -306,7 +306,7 @@ public:
     virtual bool isCPPinterface() const;
     bool isAbstract();
     virtual int vtblOffset() const;
-    const char *kind();
+    const char *kind() const;
 
     void addLocalClass(ClassDeclarations *);
 
@@ -326,7 +326,7 @@ public:
     void semantic(Scope *sc);
     bool isBaseOf(ClassDeclaration *cd, int *poffset);
     bool isBaseOf(BaseClass *bc, int *poffset);
-    const char *kind();
+    const char *kind() const;
     int vtblOffset() const;
     bool isCPPinterface() const;
     bool isCOMinterface() const;
diff --git a/gcc/d/dmd/aliasthis.c b/gcc/d/dmd/aliasthis.c
index 50921ecb300..f4d627ff42d 100644
--- a/gcc/d/dmd/aliasthis.c
+++ b/gcc/d/dmd/aliasthis.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/aliasthis.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "identifier.h"
@@ -163,7 +162,7 @@ void AliasThis::semantic(Scope *sc)
     semanticRun = PASSsemanticdone;
 }
 
-const char *AliasThis::kind()
+const char *AliasThis::kind() const
 {
     return "alias this";
 }
diff --git a/gcc/d/dmd/aliasthis.h b/gcc/d/dmd/aliasthis.h
index e5b0280d9e1..290ccd63088 100644
--- a/gcc/d/dmd/aliasthis.h
+++ b/gcc/d/dmd/aliasthis.h
@@ -24,7 +24,7 @@ public:
 
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     AliasThis *isAliasThis() { return this; }
     void accept(Visitor *v) { v->visit(this); }
 };
diff --git a/gcc/d/dmd/apply.c b/gcc/d/dmd/apply.c
index f20e411228f..bec32a892e2 100644
--- a/gcc/d/dmd/apply.c
+++ b/gcc/d/dmd/apply.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/apply.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "expression.h"
diff --git a/gcc/d/dmd/argtypes.c b/gcc/d/dmd/argtypes.c
index cad8d4ec92f..c37d48a3691 100644
--- a/gcc/d/dmd/argtypes.c
+++ b/gcc/d/dmd/argtypes.c
@@ -8,10 +8,8 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/argtypes.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-
-#include "checkedint.h"
+#include "root/dsystem.h"
+#include "root/checkedint.h"
 
 #include "mars.h"
 #include "dsymbol.h"
diff --git a/gcc/d/dmd/arrayop.c b/gcc/d/dmd/arrayop.c
index 0ea0d329399..91c1b76e4ab 100644
--- a/gcc/d/dmd/arrayop.c
+++ b/gcc/d/dmd/arrayop.c
@@ -8,10 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/arrayop.c
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 #include "root/aav.h"
 
diff --git a/gcc/d/dmd/attrib.c b/gcc/d/dmd/attrib.c
index c4270ea63e6..05728518ff1 100644
--- a/gcc/d/dmd/attrib.c
+++ b/gcc/d/dmd/attrib.c
@@ -8,11 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/attrib.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>                     // memcpy()
-
+#include "root/dsystem.h"               // memcmp()
 #include "root/rmem.h"
 
 #include "mars.h"
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index 83486a95431..a491605fc13 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -212,10 +212,10 @@ public:
     Dsymbols *cache;
 
     Dsymbol *syntaxCopy(Dsymbol *s);
-    bool oneMember(Dsymbol *ps, Identifier *ident);
+    bool oneMember(Dsymbol **ps, Identifier *ident);
     Dsymbols *include(Scope *sc, ScopeDsymbol *sds);
     void addMember(Scope *sc, ScopeDsymbol *sds);
-    void addComment(const char *comment);
+    void addComment(const utf8_t *comment);
     void setScope(Scope *sc);
     void importAll(Scope *sc);
     void semantic(Scope *sc);
diff --git a/gcc/d/dmd/canthrow.c b/gcc/d/dmd/canthrow.c
index a00741b7d72..ec15153eb4e 100644
--- a/gcc/d/dmd/canthrow.c
+++ b/gcc/d/dmd/canthrow.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/canthrow.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "init.h"
diff --git a/gcc/d/dmd/clone.c b/gcc/d/dmd/clone.c
index 9105d114eaa..4384dc8064f 100644
--- a/gcc/d/dmd/clone.c
+++ b/gcc/d/dmd/clone.c
@@ -8,11 +8,9 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/clone.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-#include <new>
-
+#include "root/dsystem.h"
 #include "root/root.h"
+
 #include "aggregate.h"
 #include "scope.h"
 #include "mtype.h"
diff --git a/gcc/d/dmd/compiler.h b/gcc/d/dmd/compiler.h
index cfcc317ff9c..6c5cf7bd474 100644
--- a/gcc/d/dmd/compiler.h
+++ b/gcc/d/dmd/compiler.h
@@ -10,6 +10,8 @@
 
 #pragma once
 
+#include "root/array.h"
+
 // This file contains a data structure that describes a back-end compiler
 // and implements compiler-specific actions.
 
@@ -18,6 +20,11 @@ class Module;
 class Type;
 struct Scope;
 
+// DMD-generated module `__entrypoint` where the C main resides
+extern Module *entrypoint;
+// Module in which the D main is
+extern Module *rootHasMain;
+
 struct Compiler
 {
     // CTFE support for cross-compilation.
diff --git a/gcc/d/dmd/cond.c b/gcc/d/dmd/cond.c
index 047eca261d8..0538929f310 100644
--- a/gcc/d/dmd/cond.c
+++ b/gcc/d/dmd/cond.c
@@ -8,9 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/cond.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>                     // strcmp()
+#include "root/dsystem.h"               // strcmp()
 
 #include "mars.h"
 #include "id.h"
diff --git a/gcc/d/dmd/constfold.c b/gcc/d/dmd/constfold.c
index 43e831f1dfe..4b5dceba62e 100644
--- a/gcc/d/dmd/constfold.c
+++ b/gcc/d/dmd/constfold.c
@@ -8,12 +8,11 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/constfold.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>                     // mem{cpy|set|cmp}()
+#include "root/dsystem.h"               // mem{cpy|set|cmp}()
+
+#ifndef IN_GCC
 #include <math.h>
-#include <new>
+#endif
 
 #include "root/rmem.h"
 #include "root/root.h"
@@ -481,13 +480,21 @@ UnionExp Mod(Loc loc, Type *type, Expression *e1, Expression *e2)
         {
             real_t r2 = e2->toReal();
 
+#ifdef IN_GCC
             c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
+#else
+            c = complex_t(::fmodl(e1->toReal(), r2), ::fmodl(e1->toImaginary(), r2));
+#endif
         }
         else if (e2->type->isimaginary())
         {
             real_t i2 = e2->toImaginary();
 
+#ifdef IN_GCC
             c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
+#else
+            c = complex_t(::fmodl(e1->toReal(), i2), ::fmodl(e1->toImaginary(), i2));
+#endif
         }
         else
             assert(0);
diff --git a/gcc/d/dmd/cppmangle.c b/gcc/d/dmd/cppmangle.c
index bb919a5f2bb..d2d357667cb 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -21,9 +21,7 @@
  *  enter `C++, mangling` as the keywords.
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "dsymbol.h"
@@ -47,9 +45,9 @@ class CppMangleVisitor : public Visitor
 {
     Objects components;         // array of components available for substitution
     OutBuffer *buf;             // append the mangling to buf[]
+  public:
     Loc loc;                    // location for use in error messages
 
-    public:
     // Write <seq-id> to buf
     void write_seq_id(size_t i)
     {
diff --git a/gcc/d/dmd/ctfeexpr.c b/gcc/d/dmd/ctfeexpr.c
index ad5b827dcd3..430342dae54 100644
--- a/gcc/d/dmd/ctfeexpr.c
+++ b/gcc/d/dmd/ctfeexpr.c
@@ -8,12 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/ctfeexpr.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>                     // mem{cpy|set}()
-#include <new>
-
+#include "root/dsystem.h"               // mem{cpy|set}()
 #include "root/rmem.h"
 
 #include "mars.h"
diff --git a/gcc/d/dmd/dcast.c b/gcc/d/dmd/dcast.c
index ee3bfd9d888..39471665e4a 100644
--- a/gcc/d/dmd/dcast.c
+++ b/gcc/d/dmd/dcast.c
@@ -8,10 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/cast.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>                     // mem{set|cpy}()
-
+#include "root/dsystem.h"               // mem{set|cpy}()
 #include "root/rmem.h"
 
 #include "mars.h"
diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c
index 414332ccd34..6fe17b36576 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -8,11 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/class.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>                     // mem{cpy|set}()
-
+#include "root/dsystem.h"               // mem{cpy|set}()
 #include "root/root.h"
 #include "root/rmem.h"
 
@@ -1389,7 +1385,7 @@ int ClassDeclaration::vtblOffset() const
 /****************************************
  */
 
-const char *ClassDeclaration::kind()
+const char *ClassDeclaration::kind() const
 {
     return "class";
 }
@@ -1827,7 +1823,7 @@ bool InterfaceDeclaration::isCPPinterface() const
 /*******************************************
  */
 
-const char *InterfaceDeclaration::kind()
+const char *InterfaceDeclaration::kind() const
 {
     return "interface";
 }
diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c
index 76132b9458e..9f43b88dd0f 100644
--- a/gcc/d/dmd/declaration.c
+++ b/gcc/d/dmd/declaration.c
@@ -8,10 +8,8 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/declaration.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-
-#include "checkedint.h"
+#include "root/dsystem.h"
+#include "root/checkedint.h"
 
 #include "errors.h"
 #include "init.h"
@@ -87,7 +85,7 @@ void Declaration::semantic(Scope *)
 {
 }
 
-const char *Declaration::kind()
+const char *Declaration::kind() const
 {
     return "declaration";
 }
@@ -188,7 +186,7 @@ Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *)
     return NULL;
 }
 
-const char *TupleDeclaration::kind()
+const char *TupleDeclaration::kind() const
 {
     return "tuple";
 }
@@ -575,7 +573,7 @@ bool AliasDeclaration::overloadInsert(Dsymbol *s)
     return true;
 }
 
-const char *AliasDeclaration::kind()
+const char *AliasDeclaration::kind() const
 {
     return "alias";
 }
@@ -705,7 +703,7 @@ OverDeclaration::OverDeclaration(Identifier *ident, Dsymbol *s, bool hasOverload
     }
 }
 
-const char *OverDeclaration::kind()
+const char *OverDeclaration::kind() const
 {
     return "overload alias";    // todo
 }
@@ -1770,7 +1768,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
     //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad->toChars(), offset, memsize);
 }
 
-const char *VarDeclaration::kind()
+const char *VarDeclaration::kind() const
 {
     return "variable";
 }
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 071ce2ca206..6952bffb38a 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -127,7 +127,7 @@ public:
 
     Declaration(Identifier *id);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     d_uns64 size(Loc loc);
     int checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag);
 
@@ -177,7 +177,7 @@ public:
 
     TupleDeclaration(Loc loc, Identifier *ident, Objects *objects);
     Dsymbol *syntaxCopy(Dsymbol *);
-    const char *kind();
+    const char *kind() const;
     Type *getType();
     Dsymbol *toAlias2();
     bool needThis();
@@ -202,7 +202,7 @@ public:
     void semantic(Scope *sc);
     void aliasSemantic(Scope *sc);
     bool overloadInsert(Dsymbol *s);
-    const char *kind();
+    const char *kind() const;
     Type *getType();
     Dsymbol *toAlias();
     Dsymbol *toAlias2();
@@ -222,7 +222,7 @@ public:
     bool hasOverloads;
 
     OverDeclaration(Identifier *ident, Dsymbol *s, bool hasOverloads = true);
-    const char *kind();
+    const char *kind() const;
     void semantic(Scope *sc);
     bool equals(RootObject *o);
     bool overloadInsert(Dsymbol *s);
@@ -269,7 +269,7 @@ public:
     void semantic(Scope *sc);
     void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
     void semantic2(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     AggregateDeclaration *isThis();
     bool needThis();
     bool isExport() const;
@@ -654,7 +654,7 @@ public:
     virtual bool isFinalFunc();
     virtual bool addPreInvariant();
     virtual bool addPostInvariant();
-    const char *kind();
+    const char *kind() const;
     FuncDeclaration *isUnique();
     bool checkNestedReference(Scope *sc, Loc loc);
     bool needsClosure();
@@ -690,7 +690,7 @@ public:
     FuncAliasDeclaration(Identifier *ident, FuncDeclaration *funcalias, bool hasOverloads = true);
 
     FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
-    const char *kind();
+    const char *kind() const;
 
     FuncDeclaration *toAliasFunc();
     void accept(Visitor *v) { v->visit(this); }
@@ -717,7 +717,7 @@ public:
     void modifyReturns(Scope *sc, Type *tret);
 
     FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
-    const char *kind();
+    const char *kind() const;
     const char *toPrettyChars(bool QualifyTypes = false);
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -728,7 +728,7 @@ public:
     CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     const char *toChars();
     bool isVirtual();
     bool addPreInvariant();
@@ -760,7 +760,7 @@ public:
     DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     const char *toChars();
     bool isVirtual();
     bool addPreInvariant();
@@ -870,7 +870,7 @@ public:
     NewDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *arguments, int varargs);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     bool isVirtual();
     bool addPreInvariant();
     bool addPostInvariant();
@@ -888,7 +888,7 @@ public:
     DeleteDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *arguments);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     bool isDelete();
     bool isVirtual();
     bool addPreInvariant();
diff --git a/gcc/d/dmd/delegatize.c b/gcc/d/dmd/delegatize.c
index 99fe93828a6..8745026252e 100644
--- a/gcc/d/dmd/delegatize.c
+++ b/gcc/d/dmd/delegatize.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/delegatize.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "expression.h"
diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c
index 4107f11738e..56652f219c9 100644
--- a/gcc/d/dmd/denum.c
+++ b/gcc/d/dmd/denum.c
@@ -8,10 +8,9 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/enum.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
+
 #include "errors.h"
 #include "enum.h"
 #include "mtype.h"
@@ -457,7 +456,7 @@ Type *EnumDeclaration::getType()
     return type;
 }
 
-const char *EnumDeclaration::kind()
+const char *EnumDeclaration::kind() const
 {
     return "enum";
 }
@@ -515,7 +514,7 @@ Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
         origType ? origType->syntaxCopy() : NULL);
 }
 
-const char *EnumMember::kind()
+const char *EnumMember::kind() const
 {
     return "enum member";
 }
diff --git a/gcc/d/dmd/dimport.c b/gcc/d/dmd/dimport.c
index 03b3d1f2c57..922e18a3fe9 100644
--- a/gcc/d/dmd/dimport.c
+++ b/gcc/d/dmd/dimport.c
@@ -8,10 +8,9 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/import.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
+
 #include "mars.h"
 #include "dsymbol.h"
 #include "import.h"
@@ -70,7 +69,7 @@ void Import::addAlias(Identifier *name, Identifier *alias)
     aliases.push(alias);
 }
 
-const char *Import::kind()
+const char *Import::kind() const
 {
     return isstatic ? "static import" : "import";
 }
diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c
index 54bf00d5a41..2bb1aace2ca 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -8,12 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/interpret.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>                     // mem{cpy|set}()
-#include <new>
-
+#include "root/dsystem.h"               // mem{cpy|set}()
 #include "root/rmem.h"
 
 #include "mars.h"
diff --git a/gcc/d/dmd/dmacro.c b/gcc/d/dmd/dmacro.c
index a5d8da10c36..c6171229fd9 100644
--- a/gcc/d/dmd/dmacro.c
+++ b/gcc/d/dmd/dmacro.c
@@ -11,11 +11,7 @@
 /* Simple macro text processor.
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "errors.h"
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index 9734624b288..7686c69c9fe 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -8,11 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/mangle.c
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
 
 #include "mangle.h"
diff --git a/gcc/d/dmd/dmodule.c b/gcc/d/dmd/dmodule.c
index a374aac73a7..55b54b1cee6 100644
--- a/gcc/d/dmd/dmodule.c
+++ b/gcc/d/dmd/dmodule.c
@@ -8,9 +8,8 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/module.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
+#include "root/dsystem.h"
+#include "root/rmem.h"
 
 #include "mars.h"
 #include "module.h"
@@ -24,14 +23,6 @@
 #include "lexer.h"
 #include "attrib.h"
 
-// For getcwd()
-#if _WIN32
-#include <direct.h>
-#endif
-#if POSIX
-#include <unistd.h>
-#endif
-
 AggregateDeclaration *Module::moduleinfo;
 
 Module *Module::rootModule;
@@ -193,7 +184,7 @@ void Module::deleteObjFile()
         docfile->remove();
 }
 
-const char *Module::kind()
+const char *Module::kind() const
 {
     return "module";
 }
@@ -310,7 +301,8 @@ bool Module::read(Loc loc)
         {
             ::error(loc, "cannot find source code for runtime library file 'object.d'");
             errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
-            errorSupplemental(loc, "config file: %s", FileName::canonicalName(global.inifilename));
+            const char *dmdConfFile = FileName::canonicalName(global.inifilename);
+            errorSupplemental(loc, "config file: %s", dmdConfFile ? dmdConfFile : "not found");
         }
         else
         {
@@ -1043,8 +1035,7 @@ void Module::runDeferredSemantic()
         }
         else
         {
-            todo = (Dsymbol **)malloc(len * sizeof(Dsymbol *));
-            assert(todo);
+            todo = (Dsymbol **)mem.xmalloc(len * sizeof(Dsymbol *));
             todoalloc = todo;
         }
         memcpy(todo, deferred.tdata(), len * sizeof(Dsymbol *));
@@ -1219,7 +1210,7 @@ Package::Package(Identifier *ident)
 }
 
 
-const char *Package::kind()
+const char *Package::kind() const
 {
     return "package";
 }
diff --git a/gcc/d/dmd/doc.c b/gcc/d/dmd/doc.c
index 92ce33cd546..d35ca7b2522 100644
--- a/gcc/d/dmd/doc.c
+++ b/gcc/d/dmd/doc.c
@@ -10,12 +10,7 @@
 
 // This implements the Ddoc capability.
 
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 #include "root/root.h"
 #include "root/port.h"
diff --git a/gcc/d/dmd/doc.h b/gcc/d/dmd/doc.h
index 7f3ef5127de..d1428fb8a69 100644
--- a/gcc/d/dmd/doc.h
+++ b/gcc/d/dmd/doc.h
@@ -10,5 +10,10 @@
 
 #pragma once
 
+#include "root/dsystem.h"
+
+class Module;
+struct OutBuffer;
+
 void escapeDdocString(OutBuffer *buf, size_t start);
 void gendocfile(Module *m);
diff --git a/gcc/d/dmd/dscope.c b/gcc/d/dmd/dscope.c
index 924a3764c00..27412b53d13 100644
--- a/gcc/d/dmd/dscope.c
+++ b/gcc/d/dmd/dscope.c
@@ -8,10 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/scope.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>                     // strlen()
-
+#include "root/dsystem.h"               // strlen()
 #include "root/root.h"
 #include "root/rmem.h"
 #include "root/speller.h"
diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c
index c99abcea9aa..f9f15ba9092 100644
--- a/gcc/d/dmd/dstruct.c
+++ b/gcc/d/dmd/dstruct.c
@@ -8,10 +8,9 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/struct.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
+
 #include "errors.h"
 #include "aggregate.h"
 #include "scope.h"
@@ -1438,7 +1437,7 @@ bool StructDeclaration::isPOD()
     return (ispod == ISPODyes);
 }
 
-const char *StructDeclaration::kind()
+const char *StructDeclaration::kind() const
 {
     return "struct";
 }
@@ -1457,7 +1456,7 @@ Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
     return StructDeclaration::syntaxCopy(ud);
 }
 
-const char *UnionDeclaration::kind()
+const char *UnionDeclaration::kind() const
 {
     return "union";
 }
diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c
index 0f0a0dc6904..b511b79c7e0 100644
--- a/gcc/d/dmd/dsymbol.c
+++ b/gcc/d/dmd/dsymbol.c
@@ -8,11 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/dsymbol.c
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <limits.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 #include "root/speller.h"
 #include "root/aav.h"
@@ -241,9 +237,7 @@ const char *Dsymbol::toPrettyChars(bool QualifyTypes)
         ++complength;
 
     // Allocate temporary array comp[]
-    const char **comp = (const char **)malloc(complength * sizeof(char**));
-    if (!comp)
-        Mem::error();
+    const char **comp = (const char **)mem.xmalloc(complength * sizeof(char**));
 
     // Fill in comp[] and compute length of final result
     size_t length = 0;
@@ -293,7 +287,7 @@ const char *Dsymbol::locToChars()
     return getLoc().toChars();
 }
 
-const char *Dsymbol::kind()
+const char *Dsymbol::kind() const
 {
     return "symbol";
 }
@@ -921,7 +915,7 @@ void OverloadSet::push(Dsymbol *s)
     a.push(s);
 }
 
-const char *OverloadSet::kind()
+const char *OverloadSet::kind() const
 {
     return "overloadset";
 }
@@ -1273,7 +1267,7 @@ void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
     }
 }
 
-const char *ScopeDsymbol::kind()
+const char *ScopeDsymbol::kind() const
 {
     return "ScopeDsymbol";
 }
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 0f2f03de4f1..421a043c8a2 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -193,7 +193,7 @@ public:
 
     virtual Identifier *getIdent();
     virtual const char *toPrettyChars(bool QualifyTypes = false);
-    virtual const char *kind();
+    virtual const char *kind() const;
     virtual Dsymbol *toAlias();                 // resolve real symbol
     virtual Dsymbol *toAlias2();
     virtual int apply(Dsymbol_apply_ft_t fp, void *param);
@@ -309,7 +309,7 @@ public:
     virtual bool isPackageAccessible(Package *p, Prot protection, int flags = 0);
     bool isforwardRef();
     static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
-    const char *kind();
+    const char *kind() const;
     FuncDeclaration *findGetMembers();
     virtual Dsymbol *symtabInsert(Dsymbol *s);
     virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id);
@@ -366,7 +366,7 @@ public:
     OverloadSet(Identifier *ident, OverloadSet *os = NULL);
     void push(Dsymbol *s);
     OverloadSet *isOverloadSet() { return this; }
-    const char *kind();
+    const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -380,7 +380,7 @@ class ForwardingScopeDsymbol : public ScopeDsymbol
     Dsymbol *symtabLookup(Dsymbol *s, Identifier *id);
     void importScope(Dsymbol *s, Prot protection);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
 
     ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return this; }
 };
diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c
index f2b3b2f7b21..9455e976074 100644
--- a/gcc/d/dmd/dtemplate.c
+++ b/gcc/d/dmd/dtemplate.c
@@ -10,9 +10,7 @@
 
 // Handle template implementation
 
-#include <stdio.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
 #include "root/aav.h"
 #include "root/rmem.h"
@@ -689,7 +687,7 @@ void TemplateDeclaration::semantic(Scope *sc)
      */
 }
 
-const char *TemplateDeclaration::kind()
+const char *TemplateDeclaration::kind() const
 {
     return (onemember && onemember->isAggregateDeclaration())
                 ? onemember->kind()
@@ -7844,7 +7842,7 @@ Dsymbol *TemplateInstance::toAlias()
     return inst;
 }
 
-const char *TemplateInstance::kind()
+const char *TemplateInstance::kind() const
 {
     return "template instance";
 }
@@ -8530,7 +8528,7 @@ void TemplateMixin::semantic3(Scope *sc)
     }
 }
 
-const char *TemplateMixin::kind()
+const char *TemplateMixin::kind() const
 {
     return "mixin";
 }
diff --git a/gcc/d/dmd/dversion.c b/gcc/d/dmd/dversion.c
index 47374868674..849afaaa6a8 100644
--- a/gcc/d/dmd/dversion.c
+++ b/gcc/d/dmd/dversion.c
@@ -8,9 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/version.c
  */
 
-#include <stdio.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
 
 #include "identifier.h"
@@ -106,7 +104,7 @@ void DebugSymbol::semantic(Scope *)
         semanticRun = PASSsemanticdone;
 }
 
-const char *DebugSymbol::kind()
+const char *DebugSymbol::kind() const
 {
     return "debug";
 }
@@ -196,7 +194,7 @@ void VersionSymbol::semantic(Scope *)
         semanticRun = PASSsemanticdone;
 }
 
-const char *VersionSymbol::kind()
+const char *VersionSymbol::kind() const
 {
     return "version";
 }
diff --git a/gcc/d/dmd/entity.c b/gcc/d/dmd/entity.c
index 38fd2d8713e..78abc8fad97 100644
--- a/gcc/d/dmd/entity.c
+++ b/gcc/d/dmd/entity.c
@@ -8,9 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/entity.c
  */
 
-#include <string.h>
-#include <ctype.h>
-
+#include "root/dsystem.h"
 #include "root/port.h"
 
 /*********************************************
diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h
index 072eacf583e..ce500579e17 100644
--- a/gcc/d/dmd/enum.h
+++ b/gcc/d/dmd/enum.h
@@ -50,7 +50,7 @@ public:
     void semantic(Scope *sc);
     bool oneMember(Dsymbol **ps, Identifier *ident);
     Type *getType();
-    const char *kind();
+    const char *kind() const;
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
     bool isDeprecated();                // is Dsymbol deprecated?
     Prot prot();
@@ -86,7 +86,7 @@ public:
 
     EnumMember(Loc loc, Identifier *id, Expression *value, Type *origType);
     Dsymbol *syntaxCopy(Dsymbol *s);
-    const char *kind();
+    const char *kind() const;
     void semantic(Scope *sc);
     Expression *getVarExp(Loc loc, Scope *sc);
 
diff --git a/gcc/d/dmd/errors.h b/gcc/d/dmd/errors.h
index 7b3ebc0deeb..42cc1d70eea 100644
--- a/gcc/d/dmd/errors.h
+++ b/gcc/d/dmd/errors.h
@@ -10,6 +10,7 @@
 
 #pragma once
 
+#include "root/dsystem.h"
 #include "globals.h"
 
 bool isConsoleColorSupported();
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index dc0d8e7c017..359e4cc91fd 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -8,12 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/expression.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <math.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 #include "root/root.h"
 
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 57c516c1d23..27a153eaaf1 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -1490,6 +1490,14 @@ struct UnionExp
     Expression *copy();
 
 private:
+    // Ensure that the union is suitably aligned.
+#if defined(__GNUC__) || defined(__clang__)
+    __attribute__((aligned(8)))
+#elif defined(_MSC_VER)
+    __declspec(align(8))
+#elif defined(__DMC__)
+    #pragma pack(8)
+#endif
     union
     {
         char exp       [sizeof(Expression)];
@@ -1507,10 +1515,10 @@ private:
         char addrexp   [sizeof(AddrExp)];
         char indexexp  [sizeof(IndexExp)];
         char sliceexp  [sizeof(SliceExp)];
-
-        // Ensure that the union is suitably aligned.
-        real_t for_alignment_only;
     } u;
+#if defined(__DMC__)
+    #pragma pack()
+#endif
 };
 
 /****************************************************************/
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index 247d1433f4b..96ae7efd7e3 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -7,12 +7,7 @@
  * http://www.boost.org/LICENSE_1_0.txt
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <math.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 #include "root/root.h"
 
diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c
index 2feea9126cd..c8f9c5c350a 100644
--- a/gcc/d/dmd/func.c
+++ b/gcc/d/dmd/func.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/func.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "init.h"
@@ -4254,7 +4253,7 @@ void FuncDeclaration::checkDmain()
         error("parameters must be main() or main(string[] args)");
 }
 
-const char *FuncDeclaration::kind()
+const char *FuncDeclaration::kind() const
 {
     return generated ? "generated function" : "function";
 }
@@ -4645,7 +4644,7 @@ FuncAliasDeclaration::FuncAliasDeclaration(Identifier *ident, FuncDeclaration *f
     userAttribDecl = funcalias->userAttribDecl;
 }
 
-const char *FuncAliasDeclaration::kind()
+const char *FuncAliasDeclaration::kind() const
 {
     return "function alias";
 }
@@ -4756,7 +4755,7 @@ void FuncLiteralDeclaration::modifyReturns(Scope *sc, Type *tret)
         ((TypeFunction *)type)->next = tret;
 }
 
-const char *FuncLiteralDeclaration::kind()
+const char *FuncLiteralDeclaration::kind() const
 {
     return (tok != TOKfunction) ? "delegate" : "function";
 }
@@ -4869,7 +4868,7 @@ void CtorDeclaration::semantic(Scope *sc)
     }
 }
 
-const char *CtorDeclaration::kind()
+const char *CtorDeclaration::kind() const
 {
     return "constructor";
 }
@@ -5039,7 +5038,7 @@ bool DtorDeclaration::addPostInvariant()
     return false;
 }
 
-const char *DtorDeclaration::kind()
+const char *DtorDeclaration::kind() const
 {
     return "destructor";
 }
@@ -5521,7 +5520,7 @@ void NewDeclaration::semantic(Scope *sc)
     FuncDeclaration::semantic(sc);
 }
 
-const char *NewDeclaration::kind()
+const char *NewDeclaration::kind() const
 {
     return "allocator";
 }
@@ -5600,7 +5599,7 @@ void DeleteDeclaration::semantic(Scope *sc)
     FuncDeclaration::semantic(sc);
 }
 
-const char *DeleteDeclaration::kind()
+const char *DeleteDeclaration::kind() const
 {
     return "deallocator";
 }
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 63caeb7b6b1..e5fefe911ea 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -234,22 +234,13 @@ struct Global
 
 extern Global global;
 
-// Because int64_t and friends may be any integral type of the
-// correct size, we have to explicitly ask for the correct
-// integer type to get the correct mangling with ddmd
-#if __LP64__
 // Be careful not to care about sign when using dinteger_t
 // use this instead of integer_t to
 // avoid conflicts with system #include's
-typedef unsigned long dinteger_t;
+typedef uint64_t dinteger_t;
 // Signed and unsigned variants
-typedef long sinteger_t;
-typedef unsigned long uinteger_t;
-#else
-typedef unsigned long long dinteger_t;
-typedef long long sinteger_t;
-typedef unsigned long long uinteger_t;
-#endif
+typedef int64_t sinteger_t;
+typedef uint64_t uinteger_t;
 
 typedef int8_t                  d_int8;
 typedef uint8_t                 d_uns8;
diff --git a/gcc/d/dmd/hdrgen.c b/gcc/d/dmd/hdrgen.c
index 2c734b31822..a1f3c12ba72 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -10,11 +10,7 @@
 
 // Routines to emit header files
 
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 
 #include "mars.h"
@@ -2336,7 +2332,8 @@ public:
         (ie, 8 chars more than mantissa). Plus one for trailing \0.
         Plus one for rounding. */
         const size_t BUFFER_LEN = sizeof(value) * 3 + 8 + 1 + 1;
-        char buffer[BUFFER_LEN] = {};
+        char buffer[BUFFER_LEN];
+        memset(buffer, 0, BUFFER_LEN);
         CTFloat::sprint(buffer, 'g', value);
         assert(strlen(buffer) < BUFFER_LEN);
 
diff --git a/gcc/d/dmd/hdrgen.h b/gcc/d/dmd/hdrgen.h
index c4bafca6d36..f9178beda8d 100644
--- a/gcc/d/dmd/hdrgen.h
+++ b/gcc/d/dmd/hdrgen.h
@@ -10,8 +10,7 @@
 
 #pragma once
 
-#include <string.h>                     // memset()
-
+#include "root/dsystem.h"               // memset()
 #include "dsymbol.h"
 
 void genhdrfile(Module *m);
diff --git a/gcc/d/dmd/identifier.c b/gcc/d/dmd/identifier.c
index 5e40746da7d..f535e5b62a1 100644
--- a/gcc/d/dmd/identifier.c
+++ b/gcc/d/dmd/identifier.c
@@ -8,11 +8,9 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/identifier.c
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
+
 #include "identifier.h"
 #include "mars.h"
 #include "id.h"
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index d360ec850d8..d07725b0253 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -14,10 +14,7 @@
 //      id.h
 //      id.c
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 struct Msgtable
 {
diff --git a/gcc/d/dmd/impcnvgen.c b/gcc/d/dmd/impcnvgen.c
index 5b88e8e682e..15239fdc283 100644
--- a/gcc/d/dmd/impcnvgen.c
+++ b/gcc/d/dmd/impcnvgen.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/impcnvgen.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
+#include "root/dsystem.h"
 
 #include "mtype.h"
 
diff --git a/gcc/d/dmd/imphint.c b/gcc/d/dmd/imphint.c
index 6d75603d80c..9b29490d361 100644
--- a/gcc/d/dmd/imphint.c
+++ b/gcc/d/dmd/imphint.c
@@ -9,11 +9,7 @@
  */
 
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 
diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h
index e0fa14d5888..dcaec5c7acb 100644
--- a/gcc/d/dmd/import.h
+++ b/gcc/d/dmd/import.h
@@ -42,7 +42,7 @@ public:
     Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
         int isstatic);
     void addAlias(Identifier *name, Identifier *alias);
-    const char *kind();
+    const char *kind() const;
     Prot prot();
     Dsymbol *syntaxCopy(Dsymbol *s);    // copy only syntax trees
     void load(Scope *sc);
diff --git a/gcc/d/dmd/init.c b/gcc/d/dmd/init.c
index e619cb4850a..6603f66bfe6 100644
--- a/gcc/d/dmd/init.c
+++ b/gcc/d/dmd/init.c
@@ -8,10 +8,9 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/init.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
+#include "root/checkedint.h"
 
-#include "checkedint.h"
 #include "mars.h"
 #include "init.h"
 #include "expression.h"
diff --git a/gcc/d/dmd/initsem.c b/gcc/d/dmd/initsem.c
index bdaf2534a0c..bcb620d8209 100644
--- a/gcc/d/dmd/initsem.c
+++ b/gcc/d/dmd/initsem.c
@@ -7,7 +7,7 @@
  * http://www.boost.org/LICENSE_1_0.txt
  */
 
-#include "checkedint.h"
+#include "root/checkedint.h"
 #include "mars.h"
 #include "init.h"
 #include "expression.h"
diff --git a/gcc/d/dmd/intrange.c b/gcc/d/dmd/intrange.c
index b4d54dbfeea..966b9a2986e 100644
--- a/gcc/d/dmd/intrange.c
+++ b/gcc/d/dmd/intrange.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/intrange.c
  */
 
-#include <stddef.h>
-#include <stdint.h>
+#include "root/dsystem.h"
 
 #include "intrange.h"
 #include "mars.h"
diff --git a/gcc/d/dmd/json.c b/gcc/d/dmd/json.c
index 4c49023b542..5ee957103c6 100644
--- a/gcc/d/dmd/json.c
+++ b/gcc/d/dmd/json.c
@@ -10,10 +10,7 @@
 
 // This implements the JSON capability.
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 
 #include "mars.h"
diff --git a/gcc/d/dmd/lexer.c b/gcc/d/dmd/lexer.c
index 1fefe2b08de..0b1824538fd 100644
--- a/gcc/d/dmd/lexer.c
+++ b/gcc/d/dmd/lexer.c
@@ -10,16 +10,7 @@
 
 /* Lexical Analyzer */
 
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <wchar.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <time.h>       // for time() and ctime()
-
+#include "root/dsystem.h" // for time() and ctime()
 #include "root/rmem.h"
 
 #include "mars.h"
diff --git a/gcc/d/dmd/macro.h b/gcc/d/dmd/macro.h
index 006f11842c4..f44108b1517 100644
--- a/gcc/d/dmd/macro.h
+++ b/gcc/d/dmd/macro.h
@@ -10,11 +10,7 @@
 
 #pragma once
 
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-
+#include "root/dsystem.h"
 #include "root/root.h"
 
 
diff --git a/gcc/d/dmd/mars.h b/gcc/d/dmd/mars.h
index 9cc5bb86fee..5aec7e6b458 100644
--- a/gcc/d/dmd/mars.h
+++ b/gcc/d/dmd/mars.h
@@ -54,9 +54,7 @@ the target object file format:
  */
 
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdarg.h>
+#include "root/dsystem.h"
 
 #ifdef __DMC__
 #ifdef DEBUG
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 399b0085635..d8fb020175e 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -35,7 +35,7 @@ public:
     Module *mod;        // != NULL if isPkgMod == PKGmodule
 
     Package(Identifier *ident);
-    const char *kind();
+    const char *kind() const;
 
     static DsymbolTable *resolve(Identifiers *packages, Dsymbol **pparent, Package **ppkg);
 
@@ -117,7 +117,7 @@ public:
 
     static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
 
-    const char *kind();
+    const char *kind() const;
     File *setOutfile(const char *name, const char *dir, const char *arg, const char *ext);
     void setDocfile();
     bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index a4c38e8a1ee..dedaf7dc83e 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -8,22 +8,8 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/mtype.c
  */
 
-#define __C99FEATURES__ 1       // Needed on Solaris for NaN and more
-#define __USE_ISOC99 1          // so signbit() gets defined
-
-#include <math.h>
-#include <stdio.h>
-#include <assert.h>
-#include <float.h>
-
-#if _MSC_VER
-#include <malloc.h>
-#include <limits>
-#elif __MINGW32__
-#include <malloc.h>
-#endif
-
-#include "checkedint.h"
+#include "root/dsystem.h"
+#include "root/checkedint.h"
 #include "root/rmem.h"
 
 #include "mars.h"
@@ -2336,8 +2322,7 @@ Identifier *Type::getTypeInfoIdent()
     // Allocate buffer on stack, fail over to using malloc()
     char namebuf[128];
     size_t namelen = 19 + sizeof(len) * 3 + len + 1;
-    char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)malloc(namelen);
-    assert(name);
+    char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)mem.xmalloc(namelen);
 
     sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len, buf.data);
     //printf("%p, deco = %s, name = %s\n", this, deco, name);
@@ -9343,20 +9328,23 @@ bool Parameter::isCovariantScope(bool returnByRef, StorageClass from, StorageCla
         static unsigned buildSR(bool returnByRef, StorageClass stc)
         {
             unsigned result;
-            switch (stc & (STCref | STCscope | STCreturn))
-            {
-                case 0:                    result = SRNone;        break;
-                case STCref:               result = SRRef;         break;
-                case STCscope:             result = SRScope;       break;
-                case STCreturn | STCref:   result = SRReturnRef;   break;
-                case STCreturn | STCscope: result = SRReturnScope; break;
-                case STCref    | STCscope: result = SRRefScope;    break;
-                case STCreturn | STCref | STCscope:
-                    result = returnByRef ? SRReturnRef_Scope : SRRef_ReturnScope;
-                    break;
-                default:
-                    assert(0);
-            }
+            StorageClass stc2 = stc & (STCref | STCscope | STCreturn);
+            if (stc2 == 0)
+                result = SRNone;
+            else if (stc2 == STCref)
+                result = SRRef;
+            else if (stc2 == STCscope)
+                result = SRScope;
+            else if (stc2 == (STCscope | STCreturn))
+                result = SRReturnScope;
+            else if (stc2 == (STCref | STCreturn))
+                result = SRReturnRef;
+            else if (stc2 == (STCscope | STCref))
+                result = SRRefScope;
+            else if (stc2 == (STCscope | STCref | STCreturn))
+                result = returnByRef ? SRReturnRef_Scope : SRRef_ReturnScope;
+            else
+                assert(0);
             return result;
         }
 
diff --git a/gcc/d/dmd/nspace.c b/gcc/d/dmd/nspace.c
index 2bd6b969813..49c41f37677 100644
--- a/gcc/d/dmd/nspace.c
+++ b/gcc/d/dmd/nspace.c
@@ -6,9 +6,7 @@
 // Source: https://github.com/D-Programming-Language/dmd/blob/master/src/nspace.c
 
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "dsymbol.h"
@@ -156,7 +154,7 @@ void Nspace::semantic3(Scope *sc)
     }
 }
 
-const char *Nspace::kind()
+const char *Nspace::kind() const
 {
     return "namespace";
 }
diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h
index 8ca01ae8485..f6c4a3d8288 100644
--- a/gcc/d/dmd/nspace.h
+++ b/gcc/d/dmd/nspace.h
@@ -32,7 +32,7 @@ class Nspace : public ScopeDsymbol
     int apply(Dsymbol_apply_ft_t fp, void *param);
     bool hasPointers();
     void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
-    const char *kind();
+    const char *kind() const;
     Nspace *isNspace() { return this; }
     void accept(Visitor *v) { v->visit(this); }
 };
diff --git a/gcc/d/dmd/opover.c b/gcc/d/dmd/opover.c
index be6fd78886a..0bcccb63afd 100644
--- a/gcc/d/dmd/opover.c
+++ b/gcc/d/dmd/opover.c
@@ -8,12 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/opover.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>                     // memset()
-
+#include "root/dsystem.h"               // memset()
 #include "root/rmem.h"
 
 #include "mars.h"
diff --git a/gcc/d/dmd/optimize.c b/gcc/d/dmd/optimize.c
index 12224fa5188..89a584bea77 100644
--- a/gcc/d/dmd/optimize.c
+++ b/gcc/d/dmd/optimize.c
@@ -8,12 +8,9 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/optimize.c
  */
 
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
-#include <math.h>
+#include "root/dsystem.h"
 
-#include "checkedint.h"
+#include "root/checkedint.h"
 #include "lexer.h"
 #include "mtype.h"
 #include "expression.h"
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index 9ee2f0837b1..119876065b1 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -10,11 +10,9 @@
 
 // This is the D parser
 
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>                     // strlen(),memcpy()
-
+#include "root/dsystem.h"               // strlen(),memcpy()
 #include "root/rmem.h"
+
 #include "mars.h"
 #include "lexer.h"
 #include "parse.h"
diff --git a/gcc/d/dmd/parse.h b/gcc/d/dmd/parse.h
index 50381067917..92c09dec073 100644
--- a/gcc/d/dmd/parse.h
+++ b/gcc/d/dmd/parse.h
@@ -52,7 +52,7 @@ enum ParseStatementFlags
     PSscope = 2,        // start a new scope
     PScurly = 4,        // { } statement is required
     PScurlyscope = 8,   // { } starts a new scope
-    PSsemi_ok = 0x10,   // empty ';' are really ok
+    PSsemi_ok = 0x10    // empty ';' are really ok
 };
 
 
@@ -180,7 +180,7 @@ enum PREC
     PREC_mul,
     PREC_pow,
     PREC_unary,
-    PREC_primary,
+    PREC_primary
 };
 
 extern PREC precedence[TOKMAX];
diff --git a/gcc/d/dmd/root/aav.c b/gcc/d/dmd/root/aav.c
index 4c015bf0700..931a395a701 100644
--- a/gcc/d/dmd/root/aav.c
+++ b/gcc/d/dmd/root/aav.c
@@ -11,11 +11,7 @@
  *
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
+#include "dsystem.h"
 #include "aav.h"
 #include "rmem.h"
 
diff --git a/gcc/d/dmd/root/aav.h b/gcc/d/dmd/root/aav.h
index 24c281a1503..ad57cb4ce4b 100644
--- a/gcc/d/dmd/root/aav.h
+++ b/gcc/d/dmd/root/aav.h
@@ -8,6 +8,8 @@
 
 #pragma once
 
+#include "dsystem.h"
+
 typedef void* Value;
 typedef void* Key;
 
diff --git a/gcc/d/dmd/root/array.h b/gcc/d/dmd/root/array.h
index ed128b93dd7..dd289982290 100644
--- a/gcc/d/dmd/root/array.h
+++ b/gcc/d/dmd/root/array.h
@@ -7,11 +7,7 @@
 
 #pragma once
 
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
+#include "dsystem.h"
 #include "object.h"
 #include "rmem.h"
 
diff --git a/gcc/d/dmd/checkedint.c b/gcc/d/dmd/root/checkedint.c
similarity index 99%
rename from gcc/d/dmd/checkedint.c
rename to gcc/d/dmd/root/checkedint.c
index b9ccb5b2397..392904acf8a 100644
--- a/gcc/d/dmd/checkedint.c
+++ b/gcc/d/dmd/root/checkedint.c
@@ -24,13 +24,13 @@
  * Copyright: Copyright (C) 2014-2018 by The D Language Foundation, All Rights Reserved
  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Authors:   Walter Bright
- * Source:    https://github.com/D-Programming-Language/dmd/blob/master/src/root/port.c
+ * Source:    https://github.com/D-Programming-Language/dmd/blob/master/src/root/checkedint.c
  */
 
-#include <assert.h>
-
+#include "dsystem.h"
 #include "checkedint.h"
 
+
 /*******************************
  * Add two signed integers, checking for overflow.
  *
diff --git a/gcc/d/dmd/checkedint.h b/gcc/d/dmd/root/checkedint.h
similarity index 90%
rename from gcc/d/dmd/checkedint.h
rename to gcc/d/dmd/root/checkedint.h
index 1f6545b6c62..1362ff51be9 100644
--- a/gcc/d/dmd/checkedint.h
+++ b/gcc/d/dmd/root/checkedint.h
@@ -5,15 +5,10 @@
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/checkedint.h
+ * https://github.com/D-Programming-Language/dmd/blob/master/src/root/checkedint.h
  */
 
-#pragma once
-
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-#include <stdint.h>
+#include "dsystem.h"
 
 
 int adds(int x, int y, bool& overflow);
diff --git a/gcc/d/dmd/root/dcompat.h b/gcc/d/dmd/root/dcompat.h
index 3fc169c034e..f92f0abaabb 100644
--- a/gcc/d/dmd/root/dcompat.h
+++ b/gcc/d/dmd/root/dcompat.h
@@ -9,6 +9,8 @@
 
 #pragma once
 
+#include "dsystem.h"
+
 /// Represents a D [ ] array
 template<typename T>
 struct DArray
diff --git a/gcc/d/dmd/root/dsystem.h b/gcc/d/dmd/root/dsystem.h
new file mode 100644
index 00000000000..940ff500062
--- /dev/null
+++ b/gcc/d/dmd/root/dsystem.h
@@ -0,0 +1,24 @@
+/* dsystem.h -- Get common system includes from the host.
+ * Copyright (C) 2018 Free Software Foundation, Inc.
+ *
+ * GCC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GCC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GCC; see the file COPYING3.  If not see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+/* This header is used in place of dmd upstream so that we can wrap
+   around gcc's system.h.  */
+
+#pragma once
+
+#include "d-system.h"
diff --git a/gcc/d/dmd/root/file.c b/gcc/d/dmd/root/file.c
index f4fd51a0012..454d4cb0760 100644
--- a/gcc/d/dmd/root/file.c
+++ b/gcc/d/dmd/root/file.c
@@ -6,29 +6,14 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/file.c
  */
 
+#include "dsystem.h"
 #include "file.h"
 
-#if defined (__sun)
-#include <alloca.h>
-#endif
-
-#if _MSC_VER ||__MINGW32__
-#include <malloc.h>
-#include <string>
-#endif
-
 #if _WIN32
 #include <windows.h>
-#include <direct.h>
-#include <errno.h>
 #endif
 
 #if POSIX
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
 #include <utime.h>
 #endif
 
@@ -104,7 +89,11 @@ bool File::read()
         goto err2;
     }
     size = (size_t)buf.st_size;
+#ifdef IN_GCC
+    buffer = (unsigned char *) ::xmalloc(size + 2);
+#else
     buffer = (unsigned char *) ::malloc(size + 2);
+#endif
     if (!buffer)
     {
         printf("\tmalloc error, errno = %d\n",errno);
@@ -155,7 +144,11 @@ err1:
     ref = 0;
 
     size = GetFileSize(h,NULL);
+#ifdef IN_GCC
+    buffer = (unsigned char *) ::xmalloc(size + 2);
+#else
     buffer = (unsigned char *) ::malloc(size + 2);
+#endif
     if (!buffer)
         goto err2;
 
diff --git a/gcc/d/dmd/root/file.h b/gcc/d/dmd/root/file.h
index f6953ab34db..f4d2937bfd3 100644
--- a/gcc/d/dmd/root/file.h
+++ b/gcc/d/dmd/root/file.h
@@ -8,8 +8,7 @@
 
 #pragma once
 
-#include <stddef.h>
-
+#include "dsystem.h"
 #include "array.h"
 
 typedef Array<struct File *> Files;
diff --git a/gcc/d/dmd/root/filename.c b/gcc/d/dmd/root/filename.c
index 307e94f6584..b0bd1a5a4fd 100644
--- a/gcc/d/dmd/root/filename.c
+++ b/gcc/d/dmd/root/filename.c
@@ -6,37 +6,19 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/filename.c
  */
 
+#include "dsystem.h"
 #include "filename.h"
 
-#include <stdint.h>
-#include <ctype.h>
-
 #include "outbuffer.h"
 #include "array.h"
 #include "file.h"
 #include "rmem.h"
 
-#if defined (__sun)
-#include <alloca.h>
-#endif
-
-#if _MSC_VER ||__MINGW32__
-#include <malloc.h>
-#include <string>
-#endif
-
 #if _WIN32
 #include <windows.h>
-#include <direct.h>
-#include <errno.h>
 #endif
 
 #if POSIX
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
 #include <utime.h>
 #endif
 
diff --git a/gcc/d/dmd/root/hash.h b/gcc/d/dmd/root/hash.h
index 1b05672ff9f..f1bc6cc5cca 100644
--- a/gcc/d/dmd/root/hash.h
+++ b/gcc/d/dmd/root/hash.h
@@ -10,8 +10,7 @@
 
 #pragma once
 
-#include <stdint.h>                     // uint{8|16|32}_t
-#include <stdlib.h>
+#include "dsystem.h"                    // uint{8|16|32}_t
 
 // MurmurHash2 was written by Austin Appleby, and is placed in the public
 // domain. The author hereby disclaims copyright to this source code.
diff --git a/gcc/d/dmd/root/object.h b/gcc/d/dmd/root/object.h
index e9d770d5d3d..d465e363522 100644
--- a/gcc/d/dmd/root/object.h
+++ b/gcc/d/dmd/root/object.h
@@ -6,11 +6,9 @@
  * https://github.com/dlang/dmd/blob/master/src/root/object.h
  */
 
-#define POSIX (__linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun)
-
 #pragma once
 
-#include <stddef.h>
+#include "dsystem.h"
 
 typedef size_t hash_t;
 
@@ -25,7 +23,7 @@ enum DYNCAST
     DYNCAST_IDENTIFIER,
     DYNCAST_TUPLE,
     DYNCAST_PARAMETER,
-    DYNCAST_STATEMENT,
+    DYNCAST_STATEMENT
 };
 
 /*
diff --git a/gcc/d/dmd/root/outbuffer.c b/gcc/d/dmd/root/outbuffer.c
index 7b6782defb1..4791bb177c9 100644
--- a/gcc/d/dmd/root/outbuffer.c
+++ b/gcc/d/dmd/root/outbuffer.c
@@ -6,16 +6,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/outbuffer.c
  */
 
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if __sun
-#include <alloca.h>
-#endif
-
+#include "dsystem.h"
 #include "outbuffer.h"
 #include "object.h"
 
diff --git a/gcc/d/dmd/root/outbuffer.h b/gcc/d/dmd/root/outbuffer.h
index 6d3be107129..6e6b35d8d93 100644
--- a/gcc/d/dmd/root/outbuffer.h
+++ b/gcc/d/dmd/root/outbuffer.h
@@ -8,10 +8,7 @@
 
 #pragma once
 
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <assert.h>
+#include "dsystem.h"
 #include "port.h"
 #include "rmem.h"
 
diff --git a/gcc/d/dmd/root/port.h b/gcc/d/dmd/root/port.h
index 3f3c46d9168..0dbb3197ad5 100644
--- a/gcc/d/dmd/root/port.h
+++ b/gcc/d/dmd/root/port.h
@@ -11,11 +11,9 @@
 // Portable wrapper around compiler/system specific things.
 // The idea is to minimize #ifdef's in the app code.
 
-#include <stdlib.h> // for alloca
-#include <stdint.h>
+#include "dsystem.h" // for alloca
 
 #if _MSC_VER
-#include <alloca.h>
 typedef __int64 longlong;
 typedef unsigned __int64 ulonglong;
 #else
diff --git a/gcc/d/dmd/root/rmem.c b/gcc/d/dmd/root/rmem.c
index 92e79ca95ae..d24e0126b37 100644
--- a/gcc/d/dmd/root/rmem.c
+++ b/gcc/d/dmd/root/rmem.c
@@ -6,10 +6,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/rmem.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
+#include "dsystem.h"
 #include "rmem.h"
 
 /* This implementation of the storage allocator uses the standard C allocation package.
@@ -23,7 +20,11 @@ char *Mem::xstrdup(const char *s)
 
     if (s)
     {
+#ifdef IN_GCC
+        p = ::xstrdup(s);
+#else
         p = strdup(s);
+#endif
         if (p)
             return p;
         error();
@@ -38,7 +39,11 @@ void *Mem::xmalloc(size_t size)
         p = NULL;
     else
     {
+#ifdef IN_GCC
+        p = ::xmalloc(size);
+#else
         p = malloc(size);
+#endif
         if (!p)
             error();
     }
@@ -52,7 +57,11 @@ void *Mem::xcalloc(size_t size, size_t n)
         p = NULL;
     else
     {
+#ifdef IN_GCC
+        p = ::xcalloc(size, n);
+#else
         p = calloc(size, n);
+#endif
         if (!p)
             error();
     }
@@ -70,14 +79,22 @@ void *Mem::xrealloc(void *p, size_t size)
     }
     else if (!p)
     {
+#ifdef IN_GCC
+        p = ::xmalloc(size);
+#else
         p = malloc(size);
+#endif
         if (!p)
             error();
     }
     else
     {
         void *psave = p;
+#ifdef IN_GCC
+        p = ::xrealloc(psave, size);
+#else
         p = realloc(psave, size);
+#endif
         if (!p)
         {   xfree(psave);
             error();
@@ -99,7 +116,11 @@ void *Mem::xmallocdup(void *o, size_t size)
         p = NULL;
     else
     {
+#ifdef IN_GCC
+        p = ::xmalloc(size);
+#else
         p = malloc(size);
+#endif
         if (!p)
             error();
         else
@@ -143,7 +164,11 @@ extern "C" void *allocmemory(size_t m_size)
 
     if (m_size > CHUNK_SIZE)
     {
+#ifdef IN_GCC
+        void *p = xmalloc(m_size);
+#else
         void *p = malloc(m_size);
+#endif
         if (p)
             return p;
         printf("Error: out of memory\n");
@@ -152,7 +177,11 @@ extern "C" void *allocmemory(size_t m_size)
     }
 
     heapleft = CHUNK_SIZE;
+#ifdef IN_GCC
+    heapp = xmalloc(CHUNK_SIZE);
+#else
     heapp = malloc(CHUNK_SIZE);
+#endif
     if (!heapp)
     {
         printf("Error: out of memory\n");
diff --git a/gcc/d/dmd/root/rmem.h b/gcc/d/dmd/root/rmem.h
index 87d465f1da3..0123402bfae 100644
--- a/gcc/d/dmd/root/rmem.h
+++ b/gcc/d/dmd/root/rmem.h
@@ -8,7 +8,7 @@
 
 #pragma once
 
-#include <stddef.h>     // for size_t
+#include "dsystem.h"    // for size_t
 
 #if __APPLE__ && __i386__
     /* size_t is 'unsigned long', which makes it mangle differently
diff --git a/gcc/d/dmd/root/rootobject.c b/gcc/d/dmd/root/rootobject.c
index cd239d6c3ca..b45e795e14e 100644
--- a/gcc/d/dmd/root/rootobject.c
+++ b/gcc/d/dmd/root/rootobject.c
@@ -5,8 +5,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/object.c
  */
 
-#include <stdio.h>
-
+#include "dsystem.h"
 #include "object.h"
 #include "outbuffer.h"
 
diff --git a/gcc/d/dmd/root/speller.c b/gcc/d/dmd/root/speller.c
index 52b4e4767f8..a5c16bab12d 100644
--- a/gcc/d/dmd/root/speller.c
+++ b/gcc/d/dmd/root/speller.c
@@ -6,16 +6,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/speller.c
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <limits.h>
-
-#if __sun || _MSC_VER
-#include <alloca.h>
-#endif
-
+#include "dsystem.h"
 #include "speller.h"
 
 const char idchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
diff --git a/gcc/d/dmd/root/stringtable.c b/gcc/d/dmd/root/stringtable.c
index 158e2af6e23..473df7cbe50 100644
--- a/gcc/d/dmd/root/stringtable.c
+++ b/gcc/d/dmd/root/stringtable.c
@@ -6,11 +6,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/stringtable.c
  */
 
-#include <stdio.h>
-#include <stdint.h>                     // uint{8|16|32}_t
-#include <string.h>                     // memcpy()
-#include <stdlib.h>
-
+#include "dsystem.h"                    // uint{8|16|32}_t, memcpy()
 #include "root.h"
 #include "rmem.h"                       // mem
 #include "stringtable.h"
diff --git a/gcc/d/dmd/sapply.c b/gcc/d/dmd/sapply.c
index 89209770234..18689c1f2da 100644
--- a/gcc/d/dmd/sapply.c
+++ b/gcc/d/dmd/sapply.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/sapply.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "statement.h"
diff --git a/gcc/d/dmd/sideeffect.c b/gcc/d/dmd/sideeffect.c
index 83e79738041..56d7d078027 100644
--- a/gcc/d/dmd/sideeffect.c
+++ b/gcc/d/dmd/sideeffect.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/sideeffect.c
  */
 
-#include <stdio.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "init.h"
diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c
index 6e679074e0a..561791478ba 100644
--- a/gcc/d/dmd/statement.c
+++ b/gcc/d/dmd/statement.c
@@ -8,9 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "statement.h"
 #include "errors.h"
diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c
index 7ee541c9d50..9be934fb4ef 100644
--- a/gcc/d/dmd/statementsem.c
+++ b/gcc/d/dmd/statementsem.c
@@ -7,12 +7,9 @@
  * http://www.boost.org/LICENSE_1_0.txt
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
-#include "checkedint.h"
+#include "root/checkedint.h"
 
 #include "errors.h"
 #include "statement.h"
diff --git a/gcc/d/dmd/staticassert.c b/gcc/d/dmd/staticassert.c
index 476668f900b..5da1f7d9b77 100644
--- a/gcc/d/dmd/staticassert.c
+++ b/gcc/d/dmd/staticassert.c
@@ -8,9 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/staticassert.c
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
+#include "root/dsystem.h"
 
 #include "mars.h"
 #include "dsymbol.h"
@@ -98,7 +96,7 @@ bool StaticAssert::oneMember(Dsymbol **ps, Identifier *)
     return true;
 }
 
-const char *StaticAssert::kind()
+const char *StaticAssert::kind() const
 {
     return "static assert";
 }
diff --git a/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h
index 0112f027024..4a601ab7afa 100644
--- a/gcc/d/dmd/staticassert.h
+++ b/gcc/d/dmd/staticassert.h
@@ -27,6 +27,6 @@ public:
     void semantic(Scope *sc);
     void semantic2(Scope *sc);
     bool oneMember(Dsymbol **ps, Identifier *ident);
-    const char *kind();
+    const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index 937900896b2..63dfcf261a4 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -19,6 +19,7 @@
 class ClassDeclaration;
 class Dsymbol;
 class Expression;
+class Parameter;
 class Type;
 struct OutBuffer;
 
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index f5991030f39..c913b2a5bfa 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -83,7 +83,7 @@ public:
     void semantic(Scope *sc);
     bool overloadInsert(Dsymbol *s);
     bool hasStaticCtorOrDtor();
-    const char *kind();
+    const char *kind() const;
     const char *toChars();
 
     Prot prot();
@@ -331,7 +331,7 @@ public:
     void semantic2(Scope *sc);
     void semantic3(Scope *sc);
     Dsymbol *toAlias();                 // resolve real symbol
-    const char *kind();
+    const char *kind() const;
     bool oneMember(Dsymbol **ps, Identifier *ident);
     const char *toChars();
     const char* toPrettyCharsHelper();
@@ -371,7 +371,7 @@ public:
     void semantic(Scope *sc);
     void semantic2(Scope *sc);
     void semantic3(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     bool oneMember(Dsymbol **ps, Identifier *ident);
     int apply(Dsymbol_apply_ft_t fp, void *param);
     bool hasPointers();
diff --git a/gcc/d/dmd/tokens.c b/gcc/d/dmd/tokens.c
index 6f68e478dee..7251c261cdb 100644
--- a/gcc/d/dmd/tokens.c
+++ b/gcc/d/dmd/tokens.c
@@ -8,8 +8,7 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/lexer.c
  */
 
-#include <stdio.h>
-#include <ctype.h>
+#include "root/dsystem.h"
 
 #include "tokens.h"
 #include "root/rmem.h"
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index b869893d4f1..e4ebea68389 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -8,16 +8,11 @@
  * https://github.com/D-Programming-Language/dmd/blob/master/src/traits.c
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
-#include <math.h>
-
+#include "root/dsystem.h"
 #include "root/rmem.h"
 #include "root/aav.h"
+#include "root/checkedint.h"
 
-#include "checkedint.h"
 #include "errors.h"
 #include "mtype.h"
 #include "init.h"
diff --git a/gcc/d/dmd/unittests.c b/gcc/d/dmd/unittests.c
deleted file mode 100644
index 482782255d7..00000000000
--- a/gcc/d/dmd/unittests.c
+++ /dev/null
@@ -1,26 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/unittests.c
- */
-
-#include <stdio.h>
-
-#include "mars.h"
-
-void unittest_speller();
-void unittest_importHint();
-void unittest_aa();
-
-void unittests()
-{
-#if UNITTEST
-    unittest_speller();
-    unittest_importHint();
-    unittest_aa();
-#endif
-}
diff --git a/gcc/d/dmd/utf.c b/gcc/d/dmd/utf.c
index f07340e95e0..6eb46993acf 100644
--- a/gcc/d/dmd/utf.c
+++ b/gcc/d/dmd/utf.c
@@ -17,8 +17,6 @@
 /// [3] http://unicode.org/faq/utf_bom.html
 /// [4] http://www.unicode.org/versions/Unicode6.1.0/ch03.pdf
 
-#include <assert.h>
-
 #include "utf.h"
 
 /* The following encodings are valid, except for the 5 and 6 byte
diff --git a/gcc/d/dmd/utf.h b/gcc/d/dmd/utf.h
index 154d39ad474..831128e7fa7 100644
--- a/gcc/d/dmd/utf.h
+++ b/gcc/d/dmd/utf.h
@@ -10,7 +10,7 @@
 
 #pragma once
 
-#include <stdlib.h>
+#include "root/dsystem.h"
 
 /// A UTF-8 code unit
 typedef unsigned char   utf8_t;
diff --git a/gcc/d/dmd/utils.c b/gcc/d/dmd/utils.c
index e3ea8c19e50..177f3cfa7a6 100644
--- a/gcc/d/dmd/utils.c
+++ b/gcc/d/dmd/utils.c
@@ -7,12 +7,13 @@
  * http://www.boost.org/LICENSE_1_0.txt
  */
 
-#include <string.h>
+#include "root/dsystem.h"
 #include "mars.h"
 #include "globals.h"
 #include "root/file.h"
 #include "root/filename.h"
 #include "root/outbuffer.h"
+#include "root/rmem.h"
 
 /**
  * Normalize path by turning forward slashes into backslashes
@@ -28,7 +29,7 @@ const char * toWinPath(const char *src)
     if (src == NULL)
         return NULL;
 
-    char *result = strdup(src);
+    char *result = mem.xstrdup(src);
     char *p = result;
     while (*p != '\0')
     {
diff --git a/gcc/d/dmd/version.h b/gcc/d/dmd/version.h
index 6268822df19..cdff1a873fc 100644
--- a/gcc/d/dmd/version.h
+++ b/gcc/d/dmd/version.h
@@ -24,7 +24,7 @@ public:
     const char *toChars();
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -40,6 +40,6 @@ public:
     const char *toChars();
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void semantic(Scope *sc);
-    const char *kind();
+    const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index ee0db983181..b86f4f675b2 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/dmd/visitor.h
@@ -9,7 +9,7 @@
 
 #pragma once
 
-#include <assert.h>
+#include "root/dsystem.h"
 
 class Statement;
 class ErrorStatement;

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2020-03-16  9:54 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-02 11:48 [PATCH, d] Committed merge with upstream dmd Iain Buclaw
  -- strict thread matches above, loose matches on Subject: below --
2020-03-16  9:54 [PATCH d]: " Iain Buclaw
2019-04-12  6:30 [PATCH, d] " Iain Buclaw
2019-04-11 21:23 Iain Buclaw
2019-03-31  4:40 Iain Buclaw
2019-03-26 14:45 Iain Buclaw
2019-03-12 14:17 Iain Buclaw
2019-03-01 10:22 Iain Buclaw
2019-01-21 21:17 Iain Buclaw
2019-01-22 10:08 ` Andreas Schwab
2019-01-22 21:31   ` Iain Buclaw
2019-01-14 10:39 Iain Buclaw
2018-12-17 18:33 Iain Buclaw
2018-11-04 23:34 Iain Buclaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).