From: Iain Buclaw Date: Mon, 21 Jan 2019 21:16:06 +0000 (+0000) Subject: Merge dmd upstream 180465274 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=255b2d916ec794078cfd0c351d3e921f8701142a;p=gcc.git Merge dmd upstream 180465274 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 * d-frontend.cc (Compiler::paintAsType): Update for new signature. From-SVN: r268124 --- diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 32160db1d36..7014b215f5a 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,7 @@ +2019-01-21 Iain Buclaw + + * d-frontend.cc (Compiler::paintAsType): Update for new signature. + 2019-01-20 Iain Buclaw * d-builtins.cc (d_init_versions): Check value of 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; } diff --git a/gcc/testsuite/gdc.test/compilable/cppmangle.d b/gcc/testsuite/gdc.test/compilable/cppmangle.d index 0fd197d17c4..7fcd41ab214 100644 --- a/gcc/testsuite/gdc.test/compilable/cppmangle.d +++ b/gcc/testsuite/gdc.test/compilable/cppmangle.d @@ -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"); +} +