diff --git a/VERSION b/VERSION index ffa7596baecd..324d5d690965 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.087.0 +v2.087.1-beta.1 diff --git a/src/dmd/access.d b/src/dmd/access.d index b556072eaa3f..a50edbf1ed89 100644 --- a/src/dmd/access.d +++ b/src/dmd/access.d @@ -41,7 +41,8 @@ bool checkAccess(AggregateDeclaration ad, Loc loc, Scope* sc, Dsymbol smember) printf("AggregateDeclaration::checkAccess() for %s.%s in function %s() in scope %s\n", ad.toChars(), smember.toChars(), f ? f.toChars() : null, cdscope ? cdscope.toChars() : null); } - if (smember.toParent().isTemplateInstance()) + const p = smember.toParent(); + if (p && p.isTemplateInstance()) { return false; // for backward compatibility } diff --git a/src/dmd/aggregate.d b/src/dmd/aggregate.d index a2adfc566db6..fb4e71b4c0b4 100644 --- a/src/dmd/aggregate.d +++ b/src/dmd/aggregate.d @@ -217,17 +217,20 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol return 0; } - for (size_t i = 0; i < members.dim; i++) + if (members) { - auto s = (*members)[i]; - if (s.apply(&func, cast(void*)this)) + for (size_t i = 0; i < members.dim; i++) { - if (sizeok != Sizeok.none) + auto s = (*members)[i]; + if (s.apply(&func, cast(void*)this)) { - // recursive determineFields already finished - return true; + if (sizeok != Sizeok.none) + { + // recursive determineFields already finished + return true; + } + return false; } - return false; } } diff --git a/src/dmd/astbase.d b/src/dmd/astbase.d index 7e99115d7b42..1737d20cbfd9 100644 --- a/src/dmd/astbase.d +++ b/src/dmd/astbase.d @@ -4202,7 +4202,6 @@ struct ASTBase { TraitsExp exp; Loc loc; - bool inAliasDeclaration; extern (D) this(const ref Loc loc, TraitsExp exp) { diff --git a/src/dmd/backend/cgcod.d b/src/dmd/backend/cgcod.d index 28d2fa172e79..1cc41f37f746 100644 --- a/src/dmd/backend/cgcod.d +++ b/src/dmd/backend/cgcod.d @@ -290,32 +290,6 @@ tryagain: regcon.params &= ~noparams; } - // See if we need to enforce a particular stack alignment - foreach (i; 0 .. globsym.top) - { - Symbol *s = globsym.tab[i]; - - switch (s.Sclass) - { - case SCregister: - case SCauto: - case SCfastpar: - if (s.Sfl == FLreg) - break; - - const sz = type_alignsize(s.Stype); - if (sz > STACKALIGN && (I64 || config.exe == EX_OSX)) - { - STACKALIGN = sz; - enforcealign = true; - } - break; - - default: - break; - } - } - if (config.flags4 & CFG4optimized) { if (nretblocks == 0 && // if no return blocks in function @@ -375,6 +349,35 @@ tryagain: cgcod_eh(); } + // See if we need to enforce a particular stack alignment + foreach (i; 0 .. globsym.top) + { + Symbol *s = globsym.tab[i]; + + if (Symbol_Sisdead(s, anyiasm)) + continue; + + switch (s.Sclass) + { + case SCregister: + case SCauto: + case SCfastpar: + if (s.Sfl == FLreg) + break; + + const sz = type_alignsize(s.Stype); + if (sz > STACKALIGN && (I64 || config.exe == EX_OSX)) + { + STACKALIGN = sz; + enforcealign = true; + } + break; + + default: + break; + } + } + stackoffsets(1); // compute addresses of stack variables cod5_prol_epi(); // see where to place prolog/epilog CSE.finish(); // compute addresses and sizes of CSE saves @@ -995,7 +998,14 @@ else } /* Determine if we need BP set up */ - if (config.flags & CFGalwaysframe) + if (enforcealign) + { + // we need BP to reset the stack before return + // otherwise the return address is lost + needframe = 1; + + } + else if (config.flags & CFGalwaysframe) needframe = 1; else { diff --git a/src/dmd/backend/cgobj.d b/src/dmd/backend/cgobj.d index 5a601c474ed4..b75a768953b1 100644 --- a/src/dmd/backend/cgobj.d +++ b/src/dmd/backend/cgobj.d @@ -460,24 +460,12 @@ version (X86ASM) { int insidx(char *p,uint index) { - // https://issues.dlang.org/show_bug.cgi?id=19974 - static if (__VERSION__ >= 2086) - asm - { - naked ; - mov EAX,index - [ESP] ; - mov ECX,p - [ESP] ; - } - else - asm nothrow - { - naked ; - mov EAX,index - [ESP+4] ; - mov ECX,p - [ESP+4] ; - } - - asm nothrow + asm { + naked ; + mov EAX,[ESP+8] ; // index + mov ECX,[ESP+4] ; // p + cmp EAX,0x7F ; jae L1 ; mov [ECX],AL ; diff --git a/src/dmd/backend/cod3.d b/src/dmd/backend/cod3.d index bf2f08e1a0ca..070685c639fc 100644 --- a/src/dmd/backend/cod3.d +++ b/src/dmd/backend/cod3.d @@ -4187,7 +4187,7 @@ void epilog(block *b) { L4: assert(hasframe); - if (xlocalsize) + if (xlocalsize || enforcealign) { if (config.flags2 & CFG2stomp) { /* MOV ECX,0xBEAF diff --git a/src/dmd/backend/dcgcv.d b/src/dmd/backend/dcgcv.d index 6b2f9d1a04e2..8d8781fefcd3 100644 --- a/src/dmd/backend/dcgcv.d +++ b/src/dmd/backend/dcgcv.d @@ -244,17 +244,16 @@ debtyp_t * debtyp_alloc(uint length) length += pad; } + length < 0x10000 || assert(0); + const len = debtyp_t.sizeof - (d.data).sizeof + length; debug { - const len = debtyp_t.sizeof - (d.data).sizeof + length; - assert(len < 4 * 4096 - 100); d = cast(debtyp_t *) mem_malloc(len /*+ 1*/); memset(d, 0xAA, len); // (cast(char*)d)[len] = 0x2E; } else { - assert(length < 0x10000); d = cast(debtyp_t *) malloc(debtyp_t.sizeof - (d.data).sizeof + length); } d.length = cast(ushort)length; @@ -277,8 +276,8 @@ private void debtyp_free(debtyp_t *d) //fflush(stdout); debug { + assert(d.length < 0x10000); uint len = debtyp_t.sizeof - (d.data).sizeof + d.length; - assert(len < 4 * 4096 - 100); // assert((cast(char*)d)[len] == 0x2E); memset(d, 0x55, len); mem_free(d); diff --git a/src/dmd/ctfeexpr.d b/src/dmd/ctfeexpr.d index 45b0bbcc45ee..c553a8797657 100644 --- a/src/dmd/ctfeexpr.d +++ b/src/dmd/ctfeexpr.d @@ -1835,6 +1835,8 @@ bool isCtfeValueValid(Expression newval) return true; //((StructLiteralExp *)newval)->ownedByCtfe; if (newval.op == TOK.classReference) return true; + if (newval.op == TOK.type) + return true; if (newval.op == TOK.vector) return true; // vector literal if (newval.op == TOK.function_) diff --git a/src/dmd/delegatize.d b/src/dmd/delegatize.d index 06029cbcd7ad..53a022147a72 100644 --- a/src/dmd/delegatize.d +++ b/src/dmd/delegatize.d @@ -86,6 +86,25 @@ private void lambdaSetParent(Expression e, FuncDeclaration fd) alias visit = typeof(super).visit; FuncDeclaration fd; + private void setParent(Dsymbol s) + { + VarDeclaration vd = s.isVarDeclaration(); + FuncDeclaration pfd = s.parent ? s.parent.isFuncDeclaration() : null; + s.parent = fd; + if (!vd || !pfd) + return; + // move to fd's closure when applicable + foreach (i; 0 .. pfd.closureVars.dim) + { + if (vd == pfd.closureVars[i]) + { + pfd.closureVars.remove(i); + fd.closureVars.push(vd); + break; + } + } + } + public: extern (D) this(FuncDeclaration fd) { @@ -98,7 +117,7 @@ private void lambdaSetParent(Expression e, FuncDeclaration fd) override void visit(DeclarationExp e) { - e.declaration.parent = fd; + setParent(e.declaration); e.declaration.accept(this); } @@ -107,7 +126,7 @@ private void lambdaSetParent(Expression e, FuncDeclaration fd) if (e.lengthVar) { //printf("lengthVar\n"); - e.lengthVar.parent = fd; + setParent(e.lengthVar); e.lengthVar.accept(this); } } @@ -117,7 +136,7 @@ private void lambdaSetParent(Expression e, FuncDeclaration fd) if (e.lengthVar) { //printf("lengthVar\n"); - e.lengthVar.parent = fd; + setParent(e.lengthVar); e.lengthVar.accept(this); } } diff --git a/src/dmd/dinterpret.d b/src/dmd/dinterpret.d index 6c31c21bff3b..c45195e307f3 100644 --- a/src/dmd/dinterpret.d +++ b/src/dmd/dinterpret.d @@ -2029,12 +2029,21 @@ public: { printf("%s Expression::interpret() '%s' %s\n", e.loc.toChars(), Token.toChars(e.op), e.toChars()); printf("type = %s\n", e.type.toChars()); - e.print(); + showCtfeExpr(e); } e.error("cannot interpret `%s` at compile time", e.toChars()); result = CTFEExp.cantexp; } + override void visit(TypeExp e) + { + debug (LOG) + { + printf("%s TypeExp.interpret() %s\n", e.loc.toChars(), e.toChars()); + } + result = e; + } + override void visit(ThisExp e) { debug (LOG) @@ -2076,7 +2085,7 @@ public: } return; } - assert(result.op == TOK.structLiteral || result.op == TOK.classReference); + assert(result.op == TOK.structLiteral || result.op == TOK.classReference || result.op == TOK.type); return; } e.error("value of `this` is not known at compile time"); @@ -4262,6 +4271,13 @@ public: lowerbound = 0; upperbound = 0; } + else if (VectorExp ve = e1.isVectorExp()) + { + // ve is not handled but a proper error message is returned + // this is to prevent https://issues.dlang.org/show_bug.cgi?id=20042 + lowerbound = 0; + upperbound = ve.dim; + } else assert(0); @@ -5077,7 +5093,8 @@ public: result = CTFEExp.cantexp; return; } - assert(pthis.op == TOK.structLiteral || pthis.op == TOK.classReference); + + assert(pthis.op == TOK.structLiteral || pthis.op == TOK.classReference || pthis.op == TOK.type); if (fd.isVirtual() && !e.directcall) { diff --git a/src/dmd/dscope.d b/src/dmd/dscope.d index a0b2dc6cb14f..040f8c6f7684 100644 --- a/src/dmd/dscope.d +++ b/src/dmd/dscope.d @@ -60,6 +60,7 @@ enum SCOPE free = 0x8000, /// is on free list fullinst = 0x10000, /// fully instantiate templates + alias_ = 0x20000, /// inside alias declaration. } // Flags that are carried along with a scope push() diff --git a/src/dmd/dsymbol.d b/src/dmd/dsymbol.d index 265cd17d62b7..501185453f70 100644 --- a/src/dmd/dsymbol.d +++ b/src/dmd/dsymbol.d @@ -441,7 +441,7 @@ extern (C++) class Dsymbol : ASTNode final inout(Dsymbol) pastMixin() inout { //printf("Dsymbol::pastMixin() %s\n", toChars()); - if (!isTemplateMixin() && !isForwardingAttribDeclaration()) + if (!isTemplateMixin() && !isForwardingAttribDeclaration() && !isForwardingScopeDsymbol()) return this; if (!parent) return null; @@ -494,7 +494,7 @@ extern (C++) class Dsymbol : ASTNode /// ditto final inout(Dsymbol) toParent2() inout { - if (!parent || !parent.isTemplateInstance && !parent.isForwardingAttribDeclaration()) + if (!parent || !parent.isTemplateInstance && !parent.isForwardingAttribDeclaration() && !parent.isForwardingScopeDsymbol()) return parent; return parent.toParent2; } diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index f9a8bb3a9c85..2c9358d8a2fb 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -2281,6 +2281,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (sc.stc & STC.deprecated_) ed.isdeprecated = true; ed.userAttribDecl = sc.userAttribDecl; + ed.namespace = sc.namespace; ed.semanticRun = PASS.semantic; @@ -2956,6 +2957,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor Scope* scy = sc.push(tm); scy.parent = tm; + /* https://issues.dlang.org/show_bug.cgi?id=930 + * + * If the template that is to be mixed in is in the scope of a template + * instance, we have to also declare the type aliases in the new mixin scope. + */ + auto parentInstance = tempdecl.parent ? tempdecl.parent.isTemplateInstance() : null; + if (parentInstance) + parentInstance.declareParameters(scy); + tm.argsym = new ScopeDsymbol(); tm.argsym.parent = scy.parent; Scope* argscope = scy.push(tm.argsym); @@ -3600,8 +3610,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor debug foreach (const i, s; cd.vtbl) { + // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl), + // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception. if (auto fd = s.isFuncDeclaration()) - assert(fd.vtblIndex == i); + assert(fd.vtblIndex == i || (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration)); } } else @@ -6309,18 +6321,12 @@ Laftersemantic: void aliasSemantic(AliasDeclaration ds, Scope* sc) { //printf("AliasDeclaration::semantic() %s\n", ds.toChars()); - if (ds.type && ds.type.ty == Ttraits) - { - // TypeTraits is not a valid type, it's semantic is called manually to - // have either a symbol or a valid type to alias. - TypeTraits tt = cast(TypeTraits) ds.type; - tt.inAliasDeclaration = true; - if (Type t = typeSemantic(tt, tt.loc, sc)) - ds.type = t; - else if (tt.sym) - ds.aliassym = tt.sym; - tt.inAliasDeclaration = false; - } + + // TypeTraits needs to know if it's located in an AliasDeclaration + sc.flags |= SCOPE.alias_; + scope(exit) + sc.flags &= ~SCOPE.alias_; + if (ds.aliassym) { auto fd = ds.aliassym.isFuncLiteralDeclaration(); @@ -6451,7 +6457,7 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc) } if (global.gag && errors != global.errors) { - ds.type = oldtype; + ds.type = Type.terror; ds.aliassym = null; } ds.inuse = 0; diff --git a/src/dmd/dtemplate.d b/src/dmd/dtemplate.d index 9c091a070817..7cf13da2b9c0 100644 --- a/src/dmd/dtemplate.d +++ b/src/dmd/dtemplate.d @@ -266,15 +266,15 @@ private bool match(RootObject o1, RootObject o2) static if (log) { - printf("\te1 = %s '%s' %s\n", e1.type.toChars(), Token.toChars(e1.op), e1.toChars()); - printf("\te2 = %s '%s' %s\n", e2.type.toChars(), Token.toChars(e2.op), e2.toChars()); + printf("\te1 = %s '%s' %s\n", e1.type ? e1.type.toChars() : "null", Token.toChars(e1.op), e1.toChars()); + printf("\te2 = %s '%s' %s\n", e2.type ? e2.type.toChars() : "null", Token.toChars(e2.op), e2.toChars()); } // two expressions can be equal although they do not have the same // type; that happens when they have the same value. So check type // as well as expression equality to ensure templates are properly // matched. - if (!e1.type.equals(e2.type) || !e1.equals(e2)) + if (!(e1.type && e2.type && e1.type.equals(e2.type)) || !e1.equals(e2)) goto Lnomatch; goto Lmatch; @@ -758,8 +758,11 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars()); /* It must be a subscope of p.sc, other scope chains are not recursive * instantiations. + * the chain of enclosing scopes is broken by paramscope (its enclosing + * scope is _scope, but paramscope.callsc is the instantiating scope). So + * it's good enough to check the chain of callsc */ - for (Scope* scx = sc; scx; scx = scx.enclosing) + for (Scope* scx = paramscope.callsc; scx; scx = scx.callsc) { if (scx == p.sc) return false; @@ -771,7 +774,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol TemplatePrevious pr; pr.prev = previous; - pr.sc = paramscope; + pr.sc = paramscope.callsc; pr.dedargs = dedargs; previous = ≺ // add this to threaded list @@ -1128,12 +1131,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol tf.fargs = fargs; uint olderrors = global.startGagging(); fd.type = tf.typeSemantic(loc, paramscope); - if (global.endGagging(olderrors)) - { - assert(fd.type.ty != Tfunction); + global.endGagging(olderrors); + if (fd.type.ty != Tfunction) goto Lnomatch; - } - assert(fd.type.ty == Tfunction); fd.originalType = fd.type; // for mangling } diff --git a/src/dmd/e2ir.d b/src/dmd/e2ir.d index 9d4aad1b2dfe..974e471e87ed 100644 --- a/src/dmd/e2ir.d +++ b/src/dmd/e2ir.d @@ -2647,7 +2647,7 @@ elem *toElem(Expression e, IRState *irs) elem *ea = toElem(re.e1, irs); elem *ekey = toElem(re.e2, irs); - ekey = addressElem(ekey, re.e1.type); + ekey = addressElem(ekey, re.e2.type); Symbol *s = aaGetSymbol(taa, "DelX", 0); elem *keyti = getTypeInfo(re.loc, taa.index, irs); elem *ep = el_params(ekey, keyti, ea, null); diff --git a/src/dmd/expression.d b/src/dmd/expression.d index 5341d6b9a9b4..5743a0479833 100644 --- a/src/dmd/expression.d +++ b/src/dmd/expression.d @@ -5114,19 +5114,6 @@ extern (C++) final class CastExp : UnaExp return to ? new CastExp(loc, e1.syntaxCopy(), to.syntaxCopy()) : new CastExp(loc, e1.syntaxCopy(), mod); } - override bool isLvalue() - { - //printf("e1.type = %s, to.type = %s\n", e1.type.toChars(), to.toChars()); - return e1.isLvalue() && e1.type.mutableOf().unSharedOf().equals(to.mutableOf().unSharedOf()); - } - - override Expression toLvalue(Scope* sc, Expression e) - { - if (isLvalue()) - return this; - return Expression.toLvalue(sc, e); - } - override Expression addDtorHook(Scope* sc) { if (to.toBasetype().ty == Tvoid) // look past the cast(void) diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d index 664ec213878d..3dc8d2336360 100644 --- a/src/dmd/expressionsem.d +++ b/src/dmd/expressionsem.d @@ -1706,6 +1706,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, } Parameter p = tf.parameterList[i]; + const bool isRef = (p.storageClass & (STC.ref_ | STC.out_)) != 0; if (!arg) { @@ -1731,6 +1732,13 @@ private bool functionParameters(const ref Loc loc, Scope* sc, } } + + if (isRef && !p.type.isConst && !p.type.isImmutable + && (p.storageClass & STC.const_) != STC.const_ + && (p.storageClass & STC.immutable_) != STC.immutable_ + && checkIfIsStructLiteralDotExpr(arg)) + break; + if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic { //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars()); @@ -1818,7 +1826,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, L1: if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid)) { - bool isRef = (p.storageClass & (STC.ref_ | STC.out_)) != 0; + if (ubyte wm = arg.type.deduceWild(p.type, isRef)) { wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm; @@ -1921,7 +1929,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc, : p.type; const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor; - if (!(hasCopyCtor || tprm.equals(arg.type))) + const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf()); + if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type))) { //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars()); arg = arg.implicitCastTo(sc, tprm); @@ -5515,6 +5524,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + if (checkIfIsStructLiteralDotExpr(exp.e1)) + return setError(); if (exp.e1.op == TOK.arrayLength) { // arr.length op= e2; @@ -6099,6 +6110,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration(); if (f.needThis()) e.e1 = getRightThis(e.loc, sc, ad, e.e1, f); + if (e.e1.op == TOK.error) + return setError(); /* A delegate takes the address of e.e1 in order to set the .ptr field * https://issues.dlang.org/show_bug.cgi?id=18575 @@ -8806,13 +8819,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Try to do a decent error message with the expression // before it got constant folded - // https://issues.dlang.org/show_bug.cgi?id=19754 - // first see if the unoptimized expression is modifiable + if (e1x.op != TOK.variable) + e1x = e1x.optimize(WANTvalue); + if (exp.op == TOK.assign) e1x = e1x.modifiableLvalue(sc, e1old); - if (e1x.op != TOK.variable) - e1x = e1x.optimize(WANTvalue); + if (checkIfIsStructLiteralDotExpr(e1x)) + return setError(); if (e1x.op == TOK.error) { @@ -9156,6 +9170,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } } + if (checkIfIsStructLiteralDotExpr(exp.e1)) + return setError(); + exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); if (exp.e1.op == TOK.error) { @@ -11971,3 +11988,40 @@ bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string desc error(loc, "`%s.%s` not found. The current runtime does not support %.*s, or the runtime is corrupt.", module_.toChars(), id.toChars(), cast(int)description.length, description.ptr); return false; } + +/** + * Check if an expression is an access to a struct member with the struct + * defined from a literal. + * + * This happens with manifest constants since the initializer is reused as is, + * each time the declaration is part of an expression, which means that the + * literal used as initializer can become a Lvalue. This Lvalue must not be modifiable. + * + * Params: + * exp = An expression that's attempted to be written. + * Must be the LHS of an `AssignExp`, `BinAssignExp`, `CatAssignExp`, + * or the expression passed to a modifiable function parameter. + * Returns: + * `true` if `expr` is a dot var or a dot identifier touching to a struct literal, + * in which case an error message is issued, and `false` otherwise. + */ +private bool checkIfIsStructLiteralDotExpr(Expression exp) +{ + // e1.var = ... + // e1.ident = ... + Expression e1; + if (exp.op == TOK.dotVariable) + e1 = exp.isDotVarExp().e1; + else if (exp.op == TOK.dotIdentifier) + e1 = exp.isDotIdExp().e1; + else + return false; + + // enum SomeStruct ss = { ... } + // also true for access from a .init: SomeStruct.init.member = ... + if (e1.op != TOK.structLiteral) + return false; + + error(exp.loc, "cannot modify constant expression `%s`", exp.toChars()); + return true; +} diff --git a/src/dmd/func.d b/src/dmd/func.d index 6e9aa4c539cd..37de1e9039ab 100644 --- a/src/dmd/func.d +++ b/src/dmd/func.d @@ -1396,7 +1396,7 @@ extern (C++) class FuncDeclaration : Declaration } /************************************** - * The function is doing something unsave, + * The function is doing something unsafe, * so mark it as unsafe. * If there's a safe error, return true. */ diff --git a/src/dmd/hdrgen.d b/src/dmd/hdrgen.d index c2d0bd4503aa..9054ca71abb9 100644 --- a/src/dmd/hdrgen.d +++ b/src/dmd/hdrgen.d @@ -1772,7 +1772,7 @@ public: if (hgs.fullDump) { auto sym = te.sym; - if (hgs.inEnumDecl != sym) foreach(i;0 .. sym.members.dim) + if (hgs.inEnumDecl && sym && hgs.inEnumDecl != sym) foreach(i;0 .. sym.members.dim) { EnumMember em = cast(EnumMember) (*sym.members)[i]; if (em.value.toInteger == v) diff --git a/src/dmd/mtype.d b/src/dmd/mtype.d index 113fa7f0f5d2..c4ba560c3928 100644 --- a/src/dmd/mtype.d +++ b/src/dmd/mtype.d @@ -5109,8 +5109,6 @@ extern (C++) final class TypeTraits : Type TraitsExp exp; /// After `typeSemantic` the symbol when `exp` doesn't represent a type. Dsymbol sym; - /// Indicates wether we are in an alias or not. - bool inAliasDeclaration; final extern (D) this(const ref Loc loc, TraitsExp exp) { diff --git a/src/dmd/mtype.h b/src/dmd/mtype.h index ed3f7f26f30e..bf8a9e0b27f7 100644 --- a/src/dmd/mtype.h +++ b/src/dmd/mtype.h @@ -647,8 +647,6 @@ class TypeTraits : public Type TraitsExp *exp; /// The symbol when exp doesn't represent a type. Dsymbol *sym; - /// Indicates wether we are in an alias or not. - bool inAliasDeclaration; Type *syntaxCopy(); d_uns64 size(const Loc &loc); diff --git a/src/dmd/semantic3.d b/src/dmd/semantic3.d index 9cb673bbfdb0..466cb726ec84 100644 --- a/src/dmd/semantic3.d +++ b/src/dmd/semantic3.d @@ -889,13 +889,7 @@ private extern(C++) final class Semantic3Visitor : Visitor const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor; // if a copy constructor is present, the return type conversion will be handled by it if (!hasCopyCtor) - { - if (f.isref && !MODimplicitConv(exp.type.mod, tret.mod) && !tret.isTypeSArray()) - error(exp.loc, "expression `%s` of type `%s` is not implicitly convertible to return type `ref %s`", - exp.toChars(), exp.type.toChars(), tret.toChars()); - else - exp = exp.implicitCastTo(sc2, tret); - } + exp = exp.implicitCastTo(sc2, tret); if (f.isref) { diff --git a/src/dmd/statementsem.d b/src/dmd/statementsem.d index 8397dd4a31a6..c7409a2827fd 100644 --- a/src/dmd/statementsem.d +++ b/src/dmd/statementsem.d @@ -1528,7 +1528,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor if (auto f = resolveFuncCall(loc, sc, td, null, tab, &a, FuncResolveFlag.quiet)) tfront = f.type; } - else if (auto d = sfront.isDeclaration()) + else if (auto d = sfront.toAlias().isDeclaration()) { tfront = d.type; } diff --git a/src/dmd/typesem.d b/src/dmd/typesem.d index cb98727ea09d..204a9e4abda9 100644 --- a/src/dmd/typesem.d +++ b/src/dmd/typesem.d @@ -1398,13 +1398,6 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) e = new AddrExp(e.loc, e); e = e.expressionSemantic(argsc); } - if (isRefOrOut && (!isAuto || e.isLvalue()) - && !MODimplicitConv(e.type.mod, fparam.type.mod)) - { - const(char)* errTxt = fparam.storageClass & STC.ref_ ? "ref" : "out"; - .error(e.loc, "expression `%s` of type `%s` is not implicitly convertible to type `%s %s` of parameter `%s`", - e.toChars(), e.type.toChars(), errTxt, fparam.type.toChars(), fparam.toChars()); - } e = e.implicitCastTo(argsc, fparam.type); // default arg must be an lvalue @@ -1666,6 +1659,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) if (mtype.ty == Terror) return mtype; + const inAlias = (sc.flags & SCOPE.alias_) != 0; if (mtype.exp.ident != Id.allMembers && mtype.exp.ident != Id.derivedMembers && mtype.exp.ident != Id.getMember && @@ -1679,7 +1673,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) { static immutable (const(char)*)[2] ctxt = ["as type", "in alias"]; .error(mtype.loc, "trait `%s` is either invalid or not supported %s", - mtype.exp.ident.toChars, ctxt[mtype.inAliasDeclaration]); + mtype.exp.ident.toChars, ctxt[inAlias]); mtype.ty = Terror; return mtype; } @@ -1714,8 +1708,31 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) mtype.sym = (cast(ScopeExp)e).sds; break; case TOK.tuple: - mtype.sym = new TupleDeclaration(e.loc, - Identifier.generateId("__aliastup"), cast(Objects*) e.toTupleExp.exps); + TupleExp te = e.toTupleExp(); + Objects* elems = new Objects(te.exps.dim); + foreach (i; 0 .. elems.dim) + { + auto src = (*te.exps)[i]; + switch (src.op) + { + case TOK.type: + (*elems)[i] = (cast(TypeExp)src).type; + break; + case TOK.dotType: + (*elems)[i] = (cast(DotTypeExp)src).sym.isType(); + break; + case TOK.overloadSet: + (*elems)[i] = (cast(OverExp)src).type; + break; + default: + if (auto sym = isDsymbol(src)) + (*elems)[i] = sym; + else + (*elems)[i] = src; + } + } + TupleDeclaration td = new TupleDeclaration(e.loc, Identifier.generateId("__aliastup"), elems); + mtype.sym = td; break; case TOK.dotType: result = (cast(DotTypeExp)e).sym.isType(); @@ -1733,7 +1750,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) if (result) result = result.addMod(mtype.mod); - if (!mtype.inAliasDeclaration && !result) + if (!inAlias && !result) { if (!global.errors) .error(mtype.loc, "`%s` does not give a valid type", mtype.toChars); @@ -1977,6 +1994,12 @@ Type merge(Type type) case Tmixin: return type; + case Tsarray: + // prevents generating the mangle if the array dim is not yet known + if (!(cast(TypeSArray) type).dim.isIntegerExp()) + return type; + goto default; + case Tenum: break; @@ -3003,6 +3026,16 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, Expression* pe, Type* pt, Ds returnError(); } + void visitTraits(TypeTraits tt) + { + if (Type t = typeSemantic(tt, loc, sc)) + returnType(t); + else if (tt.sym) + returnSymbol(tt.sym); + else + return returnError(); + } + switch (mt.ty) { default: visitType (mt); break; @@ -3015,6 +3048,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, Expression* pe, Type* pt, Ds case Treturn: visitReturn (cast(TypeReturn)mt); break; case Tslice: visitSlice (cast(TypeSlice)mt); break; case Tmixin: visitMixin (cast(TypeMixin)mt); break; + case Ttraits: visitTraits (cast(TypeTraits)mt); break; } } diff --git a/test/compilable/b20011.d b/test/compilable/b20011.d new file mode 100644 index 000000000000..f752032044db --- /dev/null +++ b/test/compilable/b20011.d @@ -0,0 +1,13 @@ +void main() +{ + struct Foo {int i;} + // allow because const, although param (member of literal, not of instance) + // is not modifiable + void test1(ref const(int)){} + void test2(const ref int){} + void test3(const ref const(int)){} + enum Foo f = {i : 42}; + test1(f.i); + test2(f.i); + test3(f.i); +} diff --git a/test/compilable/b20045.d b/test/compilable/b20045.d new file mode 100644 index 000000000000..988bbca5d96f --- /dev/null +++ b/test/compilable/b20045.d @@ -0,0 +1,2 @@ +alias U = const ubyte[uint.sizeof]*; +static assert (is(U == const(ubyte[4]*))); diff --git a/test/compilable/b20067.d b/test/compilable/b20067.d new file mode 100644 index 000000000000..af79cabfed0d --- /dev/null +++ b/test/compilable/b20067.d @@ -0,0 +1,23 @@ +struct S1 +{ + int i; + @property int ii(){return 0;} + @property bool b(){return true;} + alias empty = b; + alias front = ii; + void popFront(){} +} +struct S2 +{ + int i; + bool b; + alias empty = b; + alias front = i; + void popFront(){} +} + +void main() +{ + foreach(n; S1()) { } // 2.086: Error: cannot infer argument types + foreach(n; S2()) { } // 2.086: Error: cannot infer argument types +} diff --git a/test/compilable/cppmangle.d b/test/compilable/cppmangle.d index 06c088472766..827de97b2acc 100644 --- a/test/compilable/cppmangle.d +++ b/test/compilable/cppmangle.d @@ -1130,3 +1130,28 @@ version (Posix) static assert(PR10021_Struct2.func.mangleof == `_ZN1a1b15PR10021_Struct24funcEv`); static assert(PR10021_Struct2.func2.mangleof == `_ZN1a1b15PR10021_Struct25func2EPS1_`); } + +/// https://issues.dlang.org/show_bug.cgi?id=20022 +version (Posix) +{ + extern(C++, `ns20022`) enum Enum20022_1 { A = 1, } + extern(C++) void fun20022_1(Enum20022_1); + extern(C++, `ns20022`) void fun20022_2(Enum20022_1); + + extern(C++, ns20022) + { + enum Enum20022_2 { A = 1, } + void fun20022_5(Enum20022_1); + void fun20022_6(Enum20022_2); + } + extern(C++) void fun20022_3(Enum20022_2); + extern(C++, `ns20022`) void fun20022_4(Enum20022_2); + + static assert(fun20022_1.mangleof == `_Z10fun20022_1N7ns2002211Enum20022_1E`); + static assert(fun20022_2.mangleof == `_ZN7ns2002210fun20022_2ENS_11Enum20022_1E`); + + static assert(fun20022_3.mangleof == `_Z10fun20022_3N7ns2002211Enum20022_2E`); + static assert(fun20022_4.mangleof == `_ZN7ns2002210fun20022_4ENS_11Enum20022_2E`); + static assert(fun20022_5.mangleof == `_ZN7ns2002210fun20022_5ENS_11Enum20022_1E`); + static assert(fun20022_6.mangleof == `_ZN7ns2002210fun20022_6ENS_11Enum20022_2E`); +} diff --git a/test/compilable/ice20044.d b/test/compilable/ice20044.d new file mode 100644 index 000000000000..f85342c71fb0 --- /dev/null +++ b/test/compilable/ice20044.d @@ -0,0 +1,10 @@ +struct Algebraic(T...) +{ + T t; +} + +struct This; + +struct While(T) { T[] body; } + +alias Stmt = Algebraic!(While!(This)); diff --git a/test/compilable/staticforeach.d b/test/compilable/staticforeach.d index 67dbb078baf3..46988bc32104 100644 --- a/test/compilable/staticforeach.d +++ b/test/compilable/staticforeach.d @@ -711,3 +711,10 @@ static foreach(m; __traits(allMembers, staticforeach)) { pragma(msg, m); } + +//https://issues.dlang.org/show_bug.cgi?id=20072 +struct T2{ + static foreach(i;0..1) + struct S{} +} +static assert(is(__traits(parent,T2.S)==T2)); diff --git a/test/compilable/test19754.d b/test/compilable/test19754.d deleted file mode 100644 index 3661406bed8d..000000000000 --- a/test/compilable/test19754.d +++ /dev/null @@ -1,11 +0,0 @@ -void main() -{ - shared int x; - (cast() x) = 5; - - const int x1; - (cast() x1) = 5; - - immutable int x2; - (cast() x2) = 5; -} diff --git a/test/compilable/test20039.d b/test/compilable/test20039.d new file mode 100644 index 000000000000..d912139d8036 --- /dev/null +++ b/test/compilable/test20039.d @@ -0,0 +1,13 @@ +void foo()() { } +class bar { } + +alias bug = foo; +alias bug = bar; + +template Identity(T...) { } + +void main() +{ + alias member1 = Identity!(__traits(getMember, mixin(__MODULE__), "bug")); + alias member2 = Identity!(__traits(getMember, mixin(__MODULE__), "bug")); +} diff --git a/test/compilable/test20051.d b/test/compilable/test20051.d new file mode 100644 index 000000000000..fc4fdb44e83e --- /dev/null +++ b/test/compilable/test20051.d @@ -0,0 +1,25 @@ +// https://issues.dlang.org/show_bug.cgi?id=20051 + +/* +TEST_OUTPUT: +--- +--- +*/ + +struct Templ2(Args...) +{ +} + +struct WillAlsoWork(alias T : Templ!Args, Args...) +{ + alias A = Args[0]; +} + +void main() +{ + alias C2 = Templ2!int; + static assert(!__traits(compiles, { + alias B2 = WillAlsoWork!C2; + B2.A a2; + })); +} diff --git a/test/compilable/test20063.d b/test/compilable/test20063.d new file mode 100644 index 000000000000..9fa1db401216 --- /dev/null +++ b/test/compilable/test20063.d @@ -0,0 +1,14 @@ + +struct S +{ + void f(alias fun)() {} +} + +auto handleLazily(T)(lazy T expr) {} + +void main() +{ + class C {} + + S().f!(() => new C()).handleLazily; +} diff --git a/test/compilable/test20065.d b/test/compilable/test20065.d new file mode 100644 index 000000000000..c1be44dda8e9 --- /dev/null +++ b/test/compilable/test20065.d @@ -0,0 +1,12 @@ +alias AliasSeq(T...) = T; + +void main() +{ + enum string[] array1 = [AliasSeq!("foo")]; + + static assert(array1 == ["foo"]); + + enum string[] array2 = [AliasSeq!()]; + + static assert(array2 == []); +} diff --git a/test/compilable/test930.d b/test/compilable/test930.d new file mode 100644 index 000000000000..5daf7460751d --- /dev/null +++ b/test/compilable/test930.d @@ -0,0 +1,28 @@ +// https://issues.dlang.org/show_bug.cgi?id=930 + +/* +TEST_OUTPUT: +--- +--- +*/ +template ATemplate(T) +{ + template ATemplate() + { + auto foo() + { + T x = 2; // this line causes an error + } + } +} + +class TheClass(alias MixIt) +{ + mixin MixIt!(); +} + +void main() +{ + auto val = new TheClass!(ATemplate!(int)); + val.foo(); +} diff --git a/test/compilable/vcg-ast.d b/test/compilable/vcg-ast.d index d68a212cb9e5..bfcaf83d5720 100644 --- a/test/compilable/vcg-ast.d +++ b/test/compilable/vcg-ast.d @@ -42,3 +42,19 @@ class C return 2; } } + +enum __c_wchar_t : dchar; +alias wchar_t = __c_wchar_t; + +T[] values(T)() +{ + T[] values; + values ~= T(); + return values; +} + +void main() +{ + values!wchar_t; +} + diff --git a/test/fail_compilation/b20011.d b/test/fail_compilation/b20011.d new file mode 100644 index 000000000000..fc9d4e3033a7 --- /dev/null +++ b/test/fail_compilation/b20011.d @@ -0,0 +1,36 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/b20011.d(22): Error: cannot modify constant `S1(cast(ubyte)0u).member` +fail_compilation/b20011.d(24): Error: `S2(null).member` is not an lvalue and cannot be modified +fail_compilation/b20011.d(26): Error: cannot modify constant expression `S2(null).member` +fail_compilation/b20011.d(27): Error: cannot modify constant expression `S2(null).member` +fail_compilation/b20011.d(30): Error: cannot modify constant expression `U1(cast(ubyte)0u, ).m2` +fail_compilation/b20011.d(34): Error: cannot modify constant expression `S1(cast(ubyte)0u).member` +fail_compilation/b20011.d(35): Error: cannot modify constant expression `S1(cast(ubyte)0u).member` +--- +*/ +module b20011; + +struct S1 { ubyte member; } +struct S2 { ubyte[] member; } +union U1 { ubyte m1; int m2; } + +void main() +{ + enum S1 s1 = {}; + s1.member = 42; + + enum S2 s2 = {}; + s2.member = []; + s2.member ~= []; + s2.member += []; + + enum U1 u1 = {m1 : 0}; + u1.m2 = 42; + + void assignableByRef(ref ubyte p){ p = 42; } + void assignableByOut(out ubyte p){ p = 42; } + assignableByRef(s1.member); + assignableByOut(s1.member); +} diff --git a/test/fail_compilation/diag4596.d b/test/fail_compilation/diag4596.d index c9e4771cb721..0d9350f3c86d 100644 --- a/test/fail_compilation/diag4596.d +++ b/test/fail_compilation/diag4596.d @@ -1,12 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/diag4596.d(17): Error: `this` is not an lvalue and cannot be modified -fail_compilation/diag4596.d(18): Error: `this` is not an lvalue and cannot be modified -fail_compilation/diag4596.d(18): Error: `this` is not an lvalue and cannot be modified -fail_compilation/diag4596.d(20): Error: `super` is not an lvalue and cannot be modified -fail_compilation/diag4596.d(21): Error: `super` is not an lvalue and cannot be modified -fail_compilation/diag4596.d(21): Error: `super` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(15): Error: `this` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(16): Error: `1 ? this : this` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(18): Error: `super` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(19): Error: `1 ? super : super` is not an lvalue and cannot be modified --- */ diff --git a/test/fail_compilation/fail106.d b/test/fail_compilation/fail106.d index ba9f7dd69cde..602423ef53f2 100644 --- a/test/fail_compilation/fail106.d +++ b/test/fail_compilation/fail106.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail106.d(12): Error: cannot modify `immutable` expression `"ABC"[2]` +fail_compilation/fail106.d(12): Error: cannot modify `immutable` expression `'C'` --- */ diff --git a/test/fail_compilation/fail17491.d b/test/fail_compilation/fail17491.d index 91e21b86717b..3a103058825f 100644 --- a/test/fail_compilation/fail17491.d +++ b/test/fail_compilation/fail17491.d @@ -1,14 +1,16 @@ /* TEST_OUTPUT: --- -fail_compilation/fail17491.d(20): Error: `(S17491).init` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(21): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(29): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(30): Error: `S17491(0)` is not an lvalue and cannot be modified +fail_compilation/fail17491.d(22): Error: `(S17491).init` is not an lvalue and cannot be modified +fail_compilation/fail17491.d(23): Error: `S17491(0)` is not an lvalue and cannot be modified +fail_compilation/fail17491.d(25): Error: cannot modify constant `S17491(0).field` +fail_compilation/fail17491.d(26): Error: cannot modify constant `*&S17491(0).field` +fail_compilation/fail17491.d(31): Error: `S17491(0)` is not an lvalue and cannot be modified +fail_compilation/fail17491.d(32): Error: `S17491(0)` is not an lvalue and cannot be modified +fail_compilation/fail17491.d(34): Error: cannot modify constant `S17491(0).field` +fail_compilation/fail17491.d(35): Error: cannot modify constant `*&S17491(0).field` --- */ - // https://issues.dlang.org/show_bug.cgi?id=17491 - struct S17491 { int field; diff --git a/test/fail_compilation/fail351.d b/test/fail_compilation/fail351.d index b11d15f0380a..770f20659f94 100644 --- a/test/fail_compilation/fail351.d +++ b/test/fail_compilation/fail351.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail351.d(14): Error: expression `this.num[index]` of type `immutable(uint)` is not implicitly convertible to return type `ref uint` +fail_compilation/fail351.d(14): Error: `cast(uint)this.num[index]` is not an lvalue and cannot be modified --- */ diff --git a/test/fail_compilation/fail4206.d b/test/fail_compilation/fail4206.d index 86d4a1ddd0a0..b9c1671d7810 100644 --- a/test/fail_compilation/fail4206.d +++ b/test/fail_compilation/fail4206.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail4206.d(9): Error: cannot interpret `s` at compile time +fail_compilation/fail4206.d(9): Error: initializer must be an expression, not `s` --- */ diff --git a/test/fail_compilation/fail8262.d b/test/fail_compilation/fail8262.d index 74e1e85eedc2..2df1bca4fe35 100644 --- a/test/fail_compilation/fail8262.d +++ b/test/fail_compilation/fail8262.d @@ -1,6 +1,6 @@ /* TEST_OUTPUT: --- -fail_compilation/fail8262.d(32): Error: cannot interpret `Tuple8262!1` at compile time +fail_compilation/fail8262.d(32): Error: initializer must be an expression, not `Tuple8262!1` fail_compilation/fail8262.d(27): Error: template instance `fail8262.T8262!(Tuple8262!1)` error instantiating fail_compilation/fail8262.d(19): Error: cannot implicitly convert expression `S(0)` of type `S` to `int` --- diff --git a/test/fail_compilation/fail9891.d b/test/fail_compilation/fail9891.d index 791e734349f4..d9fc487e1151 100644 --- a/test/fail_compilation/fail9891.d +++ b/test/fail_compilation/fail9891.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail9891.d(13): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `ref int` of parameter `n` -fail_compilation/fail9891.d(18): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `out int` of parameter `n` +fail_compilation/fail9891.d(13): Error: `cast(int)i` is not an lvalue and cannot be modified +fail_compilation/fail9891.d(18): Error: `cast(int)i` is not an lvalue and cannot be modified fail_compilation/fail9891.d(23): Error: `prop()` is not an lvalue and cannot be modified --- */ diff --git a/test/fail_compilation/ice11856_0.d b/test/fail_compilation/ice11856_0.d new file mode 100644 index 000000000000..76ddb8c8dfa6 --- /dev/null +++ b/test/fail_compilation/ice11856_0.d @@ -0,0 +1,16 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ice11856_0.d(16): Error: template `ice11856_0.f` cannot deduce function from argument types `!()(int)`, candidates are: +fail_compilation/ice11856_0.d(10): `ice11856_0.f(T)(T t) if (!__traits(compiles, .f!T))` +fail_compilation/ice11856_0.d(13): `ice11856_0.f(T)(T t) if (!__traits(compiles, .f!T))` +--- +*/ + +int f(T)(T t) if(!__traits(compiles,.f!T)) { + return 0; +} +int f(T)(T t) if(!__traits(compiles,.f!T)) { + return 1; +} +enum x=f(2); diff --git a/test/fail_compilation/ice11856_1.d b/test/fail_compilation/ice11856_1.d new file mode 100644 index 000000000000..7f008f3e0680 --- /dev/null +++ b/test/fail_compilation/ice11856_1.d @@ -0,0 +1,13 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ice11856_1.d(13): Error: template `ice11856_1.g` cannot deduce function from argument types `!()(A)`, candidates are: +fail_compilation/ice11856_1.d(11): `ice11856_1.g(T)(T x) if (is(typeof(x.f())))` +--- +*/ +struct A {} + +void f(T)(T x) if (is(typeof(x.g()))) {} +void g(T)(T x) if (is(typeof(x.f()))) {} + +void main() { A().g(); } diff --git a/test/fail_compilation/ice11919.d b/test/fail_compilation/ice11919.d index 52258e3566aa..4e6171eaab37 100644 --- a/test/fail_compilation/ice11919.d +++ b/test/fail_compilation/ice11919.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice11919.d(17): Error: cannot interpret `foo` at compile time +fail_compilation/ice11919.d(17): Error: initializer must be an expression, not `foo` fail_compilation/imports/a11919.d(4): Error: template instance `a11919.doBar!(Foo).doBar.zoo!(t)` error instantiating fail_compilation/imports/a11919.d(11): instantiated from here: `doBar!(Foo)` fail_compilation/ice11919.d(25): instantiated from here: `doBar!(Bar)` diff --git a/test/fail_compilation/ice12362.d b/test/fail_compilation/ice12362.d index 787dec686c89..d0853b9b20d4 100644 --- a/test/fail_compilation/ice12362.d +++ b/test/fail_compilation/ice12362.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice12362.d(12): Error: cannot interpret `foo` at compile time +fail_compilation/ice12362.d(12): Error: initializer must be an expression, not `foo` --- */ diff --git a/test/compilable/test14929.d b/test/fail_compilation/ice14929.d similarity index 68% rename from test/compilable/test14929.d rename to test/fail_compilation/ice14929.d index 1b794a66248e..349e328095e8 100644 --- a/test/compilable/test14929.d +++ b/test/fail_compilation/ice14929.d @@ -1,3 +1,14 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ice14929.d(45): Error: `cast(Node)(*this.current).items[this.index]` is not an lvalue and cannot be modified +fail_compilation/ice14929.d(88): Error: template instance `ice14929.HashMap!(ulong, int).HashMap.opBinaryRight!"in"` error instantiating +fail_compilation/ice14929.d(92): instantiated from here: `HashmapComponentStorage!int` +fail_compilation/ice14929.d(92): Error: template instance `ice14929.isComponentStorage!(HashmapComponentStorage!int, int)` error instantiating +fail_compilation/ice14929.d(92): while evaluating: `static assert(isComponentStorage!(HashmapComponentStorage!int, int))` +--- +*/ + struct HashMap(K, V) { V* opBinaryRight(string op)(K key) const if (op == "in") diff --git a/test/fail_compilation/ice19295.d b/test/fail_compilation/ice19295.d new file mode 100644 index 000000000000..a92f5f8384c5 --- /dev/null +++ b/test/fail_compilation/ice19295.d @@ -0,0 +1,18 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ice19295.d(11): Error: `this` for `gun` needs to be type `S2` not type `S1!(gun)` +fail_compilation/ice19295.d(11): while evaluating `pragma(msg, &gun)` +fail_compilation/ice19295.d(17): Error: template instance `ice19295.S1!(gun)` error instantiating +--- +*/ +struct S1(T...) { + auto fun() { + pragma(msg, &T[0]); + } +} + +struct S2 { + void gun() {} + S1!gun overloaded; +} diff --git a/test/fail_compilation/ice19950.d b/test/fail_compilation/ice19950.d new file mode 100644 index 000000000000..8fa61daf6b94 --- /dev/null +++ b/test/fail_compilation/ice19950.d @@ -0,0 +1,13 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ice19950.d(8): Error: undefined identifier `NotHere` +fail_compilation/ice19950.d(9): Error: template instance `ice19950.baz!()` does not match template declaration `baz()(Foo) if (true)` +--- +*/ +alias Foo = NotHere; +alias Bar = baz!(); + +void baz()(Foo) + if (true) +{} diff --git a/test/fail_compilation/ice20042.d b/test/fail_compilation/ice20042.d new file mode 100644 index 000000000000..7ba9309c0772 --- /dev/null +++ b/test/fail_compilation/ice20042.d @@ -0,0 +1,29 @@ +/* +DISABLED: freebsd32 linux32 osx32 win32 +TEST_OUTPUT: +--- +fail_compilation/ice20042.d(18): Error: slice operation `cast(__vector(float[4]))nanF = [1.00000F, 2.00000F, 3.00000F, 4.00000F][0..4]` cannot be evaluated at compile time +fail_compilation/ice20042.d(25): called from here: `Vec4(cast(__vector(float[4]))[nanF, nanF, nanF, nanF]).this([1.00000F, 2.00000F, 3.00000F, 4.00000F])` +--- +*/ +void write(T...)(T t){} + +struct Vec4 +{ + __vector(float[4]) raw; + + this(const(float[4]) value...) inout pure @safe nothrow @nogc + { + __vector(float[4]) raw; + raw[] = value[]; + this.raw = raw; + } +} + +void main() +{ + static immutable Vec4 v = Vec4( 1.0f, 2.0f, 3.0f, 4.0f ); + + static foreach(d; 0 .. 4) + write(v.raw[d], " "); +} diff --git a/test/fail_compilation/ice20056.d b/test/fail_compilation/ice20056.d new file mode 100644 index 000000000000..1b991cae66dc --- /dev/null +++ b/test/fail_compilation/ice20056.d @@ -0,0 +1,25 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ice20056.d(19): Error: need `this` for `iter` of type `void()` +--- +*/ +struct Def(alias fn) +{ + alias func = alias_selector!(fn).VOverloads[0]; +} + +template alias_selector(alias fn) +{ + alias VOverloads = __traits(getOverloads, __traits(parent, fn), __traits(identifier, fn)); +} + +void init_rangewrapper() +{ + Def!(RangeWrapper.iter).func; +} + +struct RangeWrapper +{ + void iter() { } +} diff --git a/test/fail_compilation/test12385.d b/test/fail_compilation/test12385.d index cbba723fe749..9660c39f11f3 100644 --- a/test/fail_compilation/test12385.d +++ b/test/fail_compilation/test12385.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/test12385.d(29): Error: cannot modify `immutable` expression `unbundled.x` +fail_compilation/test12385.d(29): Error: cannot modify `immutable` expression `BundledState("bla", 3).x` --- */ diff --git a/test/runnable/e7804.d b/test/runnable/e7804.d index fe8230303043..d32531055f54 100644 --- a/test/runnable/e7804.d +++ b/test/runnable/e7804.d @@ -155,3 +155,25 @@ void main() (new Two).test(); (new SingleSymTuple).test(); } + +/* https://issues.dlang.org/show_bug.cgi?id=19708 */ +struct Foo19708 {} +struct Bar19708 {} +template Baz19708(T) { struct Baz19708{T t;} } +int symbol19708; + +@Foo19708 @Bar19708 @Baz19708 @symbol19708 int bar19708; + +alias TR19708 = __traits(getAttributes, bar19708); +alias TRT = __traits(getAttributes, bar19708)[2]; + +TR19708[0] a119708; +TR19708[1] a219708; +alias A3 = TRT!int; + +alias C19708 = TR19708[0]; +alias D19708 = TR19708[1]; +C19708 c1; +D19708 d1; + +static assert(__traits(isSame, TR19708[3], symbol19708)); diff --git a/test/runnable/test17885.d b/test/runnable/test17885.d new file mode 100644 index 000000000000..a6e521b03a31 --- /dev/null +++ b/test/runnable/test17885.d @@ -0,0 +1,11 @@ +module test17885; + +struct T { ulong a, b; } +T f() { return T(); } + +void main() +{ + int[T] set = [f(): 0]; + set.remove(f()); + assert(f() !in set); +} diff --git a/test/runnable/test20025.d b/test/runnable/test20025.d new file mode 100644 index 000000000000..42f8257ddb8f --- /dev/null +++ b/test/runnable/test20025.d @@ -0,0 +1,27 @@ +// https://issues.dlang.org/show_bug.cgi?id=20025 +/* +TEST_OUTPUT: +--- +--- +*/ + +struct B +{ + static int value = 77; + alias value this; + + this(ref return scope inout B rhs) inout { } +} + +void test(int x) +{ + assert(x == 77); +} + +int main() +{ + B b; + test(b); + + return 0; +} diff --git a/test/runnable/testxmm.d b/test/runnable/testxmm.d index acaa6b232997..1729beb62c15 100644 --- a/test/runnable/testxmm.d +++ b/test/runnable/testxmm.d @@ -1937,17 +1937,34 @@ void refIntrinsics() /*****************************************/ -void test6() +void test6a() { version (D_AVX2) { // stack occasionally misaligned float f = 0; long4 v; + assert((cast(size_t)&v) % 32 == 0); v += 1; } } +void test6b() +{ + version (D_AVX2) + { + struct S {long4 v;} + S s; + assert((cast(size_t)&s) % 32 == 0); + } +} + +void test6() +{ + test6a(); + test6b(); +} + /*****************************************/ version (D_AVX) @@ -1972,6 +1989,19 @@ void test7() /*****************************************/ + +auto test20052() +{ + version (D_AVX2) + { + struct S { long4 v; } + S s; + return s; + } +} + +/*****************************************/ + int main() { test1(); @@ -2011,6 +2041,7 @@ int main() test10447(); test17344(); test17356(); + test20052(); test6(); test7();