Merge dmd upstream 180465274
authorIain Buclaw <ibuclaw@gdcproject.org>
Mon, 21 Jan 2019 21:16:06 +0000 (21:16 +0000)
committerIain Buclaw <ibuclaw@gcc.gnu.org>
Mon, 21 Jan 2019 21:16:06 +0000 (21:16 +0000)
Reduces the memory footprint of the CTFE interpreter by replacing new
with emplacement new in many places.

gcc/d/ChangeLog:

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

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

From-SVN: r268124

18 files changed:
gcc/d/ChangeLog
gcc/d/d-frontend.cc
gcc/d/dmd/MERGE
gcc/d/dmd/compiler.h
gcc/d/dmd/constfold.c
gcc/d/dmd/ctfe.h
gcc/d/dmd/ctfeexpr.c
gcc/d/dmd/dinterpret.c
gcc/d/dmd/dsymbol.c
gcc/d/dmd/expression.c
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.c
gcc/d/dmd/idgen.c
gcc/d/dmd/initsem.c
gcc/d/dmd/mtype.c
gcc/d/dmd/parse.c
gcc/d/dmd/traits.c
gcc/testsuite/gdc.test/compilable/cppmangle.d

index 32160db1d3656e29fd126b0939754f0a64208cf7..7014b215f5a6415adab857b8b6dae5cb5077e566 100644 (file)
@@ -1,3 +1,7 @@
+2019-01-21  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * d-frontend.cc (Compiler::paintAsType): Update for new signature.
+
 2019-01-20  Iain Buclaw  <ibuclaw@gdcproject.org>
 
        * d-builtins.cc (d_init_versions): Check value of
index a1c0d53d1ca383776d9e59d9dcd498ef53e17a5a..d1d3c78ec8653072124b1b19de2fcffda2b3f4a7 100644 (file)
@@ -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];
index a3b2db74af4c2b47437769fdcd4f376ba8a2739e..e8ab8df4f7bfe43028d83b4dce756bc917ea18d2 100644 (file)
@@ -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.
index e8ab9925c5adacb7311ccaab7cfbcd1957bfb1cb..a8520788f989397e7ad5ae0d028c58a91dc53fc4 100644 (file)
@@ -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 *);
index 83f0f3ef14fbf0fc5ea1ccdb19878f4923082e86..ddd356bb966a7196581dd2054f98e26e18550844 100644 (file)
@@ -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
         {
index 2c6a47440a8f6648cda990df78e99467a458b907..0e49432e1b635fbab6914abd68a7adc6e530b6dd 100644 (file)
@@ -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);
index 713e0f9ff7d9ae45f586969c99d872f41b111cb9..1050e93699ea70ec2a9c6d544a3210af5177d2b9 100644 (file)
@@ -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)
index 7c497d8958a7ac8b2df7136652c17dd7512b14b5..140abfdd7e97fd2be1e546702ce238f312389360 100644 (file)
@@ -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;
 }
 
index b7fcf43f6c14eba99af7d6300d8df3d08be498eb..4d82d7217e177c13fdf2b9a54509579098d8360d 100644 (file)
@@ -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)
index a1186c9fb5337469b477a571ddba67460fea8264..cbc38195ccad7c3c49a2cd75ebb270c742ff8dcc 100644 (file)
@@ -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
             {
index 51490828b1cb68b18f8cdefd1a495cc6be30b2f1..2dd0b249458e8d373f0b407da4916a951d03ba17 100644 (file)
@@ -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);
index b3274e4cfe43542a82ab06929599a6a1241698d9..d5319e55a6e60edac21003627f22d0e06de899d3 100644 (file)
@@ -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;
index d413ded33b4e266669166d6950b06a9de00af8eb..ec26b2c70088a7a415b18175ac9a8f27f042e5e7 100644 (file)
@@ -267,6 +267,9 @@ Msgtable msgtable[] =
     { "_ArrayEq", NULL },
     { "_ArrayPostblit", NULL },
     { "_ArrayDtor", NULL },
+    { "dup", NULL },
+    { "_aaApply", NULL },
+    { "_aaApply2", NULL },
 
     // For pragma's
     { "Pinline", "inline" },
index 74929389177a38d721099680565a41288f42c55f..52e26bccd858881cabd7b98590845c8ef093dabf 100644 (file)
@@ -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;
             }
index 50a33e5c4c56032f2782f015ba99a54baa0d253e..09161a313eefed778b7d7d8ce74db5a8ec079f94 100644 (file)
@@ -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;
 }
 
index c081e806785dad2c8ae882d850d01f42ab51ff77..171ed14f132268213732755fbbbb24437a0f809f 100644 (file)
@@ -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;
         }
 
index a2d5c9b7a9c7e11d338e85ca9e70fae368f8de38..1d5f3fc1064e63a1219e6c842202e635bba3dd35 100644 (file)
@@ -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;
 }
 
index 0fd197d17c4dace3dfd7894a46f11ad98ded6dac..7fcd41ab214fcbfda60e7069b083ecf553bf26fd 100644 (file)
@@ -351,3 +351,24 @@ void test15789()
 {
     test15789a(0);
 }
+
+/**************************************/
+// 7030
+
+extern(C++)
+{
+    struct T
+    {
+        void foo(int) const;
+        void bar(int);
+        static __gshared int boo;
+    }
+}
+
+version (Posix)
+{
+    static assert(T.foo.mangleof == "_ZNK1T3fooEi");
+    static assert(T.bar.mangleof == "_ZN1T3barEi");
+    static assert(T.boo.mangleof == "_ZN1T3booE");
+}
+