diff --git a/src/clone.c b/src/clone.c index 6cf3ab413f9d..4827960b1e0f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -92,8 +92,6 @@ FuncDeclaration *hasIdentityOpAssign(AggregateDeclaration *ad, Scope *sc) FuncDeclaration *f = NULL; unsigned errors = global.startGagging(); // Do not report errors, even if the - unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. - global.speculativeGag = global.gag; sc = sc->push(); sc->speculative = true; @@ -106,7 +104,6 @@ FuncDeclaration *hasIdentityOpAssign(AggregateDeclaration *ad, Scope *sc) } sc = sc->pop(); - global.speculativeGag = oldspec; global.endGagging(errors); if (f) @@ -309,8 +306,6 @@ FuncDeclaration *buildOpAssign(StructDeclaration *sd, Scope *sc) sd->hasIdentityAssign = true; // temporary mark identity assignable unsigned errors = global.startGagging(); // Do not report errors, even if the - unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. - global.speculativeGag = global.gag; Scope *sc2 = sc->push(); sc2->stc = 0; sc2->linkage = LINKd; @@ -321,7 +316,6 @@ FuncDeclaration *buildOpAssign(StructDeclaration *sd, Scope *sc) fop->semantic3(sc2); sc2->pop(); - global.speculativeGag = oldspec; if (global.endGagging(errors)) // if errors happened { // Disable generated opAssign, because some members forbid identity assignment. @@ -412,8 +406,6 @@ FuncDeclaration *hasIdentityOpEquals(AggregateDeclaration *ad, Scope *sc) FuncDeclaration *f = NULL; unsigned errors = global.startGagging(); // Do not report errors, even if the - unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. - global.speculativeGag = global.gag; sc = sc->push(); sc->speculative = true; @@ -427,7 +419,6 @@ FuncDeclaration *hasIdentityOpEquals(AggregateDeclaration *ad, Scope *sc) } sc = sc->pop(); - global.speculativeGag = oldspec; global.endGagging(errors); if (f) diff --git a/src/declaration.c b/src/declaration.c index 078e34fe5088..6012807e2306 100644 --- a/src/declaration.c +++ b/src/declaration.c @@ -514,8 +514,8 @@ void AliasDeclaration::semantic(Scope *sc) // Ungag errors when not instantiated DeclDefs scope alias Ungag ungag(global.gag); - //printf("%s parent = %s, specgag= %d, instantiated = %d\n", toChars(), parent, global.isSpeculativeGagging(), isInstantiated()); - if (parent && global.isSpeculativeGagging() && !isInstantiated() && !toParent2()->isFuncDeclaration()) + //printf("%s parent = %s, gag = %d, instantiated = %d\n", toChars(), parent, global.gag, isInstantiated()); + if (parent && global.gag && !isInstantiated() && !toParent2()->isFuncDeclaration()) { //printf("%s type = %s\n", toPrettyChars(), type->toChars()); global.gag = 0; @@ -731,7 +731,7 @@ Dsymbol *AliasDeclaration::toAlias() Lerr: // Avoid breaking "recursive alias" state during errors gagged - if (global.isSpeculativeGagging()) + if (global.gag) return this; aliassym = new AliasDeclaration(loc, ident, Type::terror); @@ -1055,7 +1055,7 @@ void VarDeclaration::semantic(Scope *sc) //printf("storage_class = x%x\n", storage_class); // Calculate type size + safety checks - if (sc->func && !sc->intypeof) + if (sc->func && !sc->intypeof && !isMember()) { if (storage_class & STCgshared) { @@ -2070,7 +2070,7 @@ Expression *VarDeclaration::getConstInitializer(bool needFullType) // Ungag errors when not speculative unsigned oldgag = global.gag; - if (global.isSpeculativeGagging()) + if (global.gag) { Dsymbol *sym = toParent()->isAggregateDeclaration(); if (sym && !sym->isSpeculative()) diff --git a/src/expression.c b/src/expression.c index fe14e3a61415..26f16b92e709 100644 --- a/src/expression.c +++ b/src/expression.c @@ -3256,7 +3256,7 @@ Expression *DsymbolExp::semantic(Scope *sc) // Detect recursive initializers. // BUG: The check for speculative gagging is not correct - if (v->inuse && !global.isSpeculativeGagging()) + if (v->inuse && !global.gag) { e->error("circular initialization of %s", v->toChars()); return new ErrorExp(); @@ -14007,13 +14007,10 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0) fargs->push(ie->upr); unsigned xerrors = global.startGagging(); - unsigned oldspec = global.speculativeGag; - global.speculativeGag = global.gag; sc = sc->push(); sc->speculative = true; FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1); sc = sc->pop(); - global.speculativeGag = oldspec; global.endGagging(xerrors); if (!fslice) goto Lfallback; diff --git a/src/mars.c b/src/mars.c index d7e9ddcaf74e..2ad8c5fbe94b 100644 --- a/src/mars.c +++ b/src/mars.c @@ -83,7 +83,7 @@ Ungag Dsymbol::ungagSpeculative() { unsigned oldgag = global.gag; - if (global.isSpeculativeGagging() && !isSpeculative() && !toParent2()->isFuncDeclaration()) + if (global.gag && !isSpeculative() && !toParent2()->isFuncDeclaration()) global.gag = 0; return Ungag(oldgag); @@ -167,11 +167,6 @@ bool Global::endGagging(unsigned oldGagged) return anyErrs; } -bool Global::isSpeculativeGagging() -{ - return gag && gag == speculativeGag; -} - void Global::increaseErrorCount() { if (gag) diff --git a/src/mars.h b/src/mars.h index 43e0c6ae99b4..aa6e6c990656 100644 --- a/src/mars.h +++ b/src/mars.h @@ -243,13 +243,8 @@ struct Global unsigned gag; // !=0 means gag reporting of errors & warnings unsigned gaggedErrors; // number of errors reported while gagged - /* Gagging can either be speculative (is(typeof()), etc) - * or because of forward references + /* Start gagging. Return the current number of gagged errors */ - unsigned speculativeGag; // == gag means gagging is for is(typeof); - bool isSpeculativeGagging(); - - // Start gagging. Return the current number of gagged errors unsigned startGagging(); /* End gagging, restoring the old gagged state. diff --git a/src/mtype.c b/src/mtype.c index edafa663d6b8..3c6e63ffdceb 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -7089,12 +7089,8 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc2->intypeof = 1; sc2->speculative = true; sc2->flags |= sc->flags & SCOPEstaticif; - unsigned oldspecgag = global.speculativeGag; - if (global.gag) - global.speculativeGag = global.gag; exp = exp->semantic(sc2); exp = resolvePropertiesOnly(sc2, exp); - global.speculativeGag = oldspecgag; sc2->pop(); if (exp->op == TOKtype) { diff --git a/src/struct.c b/src/struct.c index b9d7742aa348..27cee4d7df3e 100644 --- a/src/struct.c +++ b/src/struct.c @@ -860,13 +860,10 @@ void StructDeclaration::semantic(Scope *sc) if (scall) { unsigned xerrors = global.startGagging(); - unsigned oldspec = global.speculativeGag; - global.speculativeGag = global.gag; sc = sc->push(); sc->speculative = true; FuncDeclaration *fcall = resolveFuncCall(loc, sc, scall, NULL, NULL, NULL, 1); sc = sc->pop(); - global.speculativeGag = oldspec; global.endGagging(xerrors); if (fcall && fcall->isStatic()) diff --git a/src/template.c b/src/template.c index b1abe2a9e2ec..fa079dca1473 100644 --- a/src/template.c +++ b/src/template.c @@ -6049,7 +6049,11 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) printf("Recursive template expansion\n"); #endif error(loc, "recursive template expansion"); -// inst = this; + if (global.gag) + semanticRun = PASSinit; + else + inst = this; + errors = true; return; } semanticRun = PASSsemantic; @@ -6112,7 +6116,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) goto L1; // It had succeeded, mark it is a non-speculative instantiation, // and reuse it. - inst->speculative = 0; + inst->speculative = false; } #if LOG @@ -6134,9 +6138,9 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) #endif unsigned errorsave = global.errors; inst = this; - // Mark as speculative if we are instantiated from inside is(typeof()) - if (global.gag && sc->speculative) - speculative = 1; + // Mark as speculative if we are instantiated during errors gagged + if (global.gag) + speculative = true; TemplateInstance *tempdecl_instance_idx = tempdecl->addInstance(this); @@ -7162,6 +7166,12 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) (*tiargs)[i] = tdtypes[i]; } } + else if (errors && inst) + { + // instantiation was failed with error reporting + assert(global.errors); + return false; + } else { TemplateDeclaration *tdecl = tempdecl->isTemplateDeclaration(); @@ -7623,11 +7633,21 @@ void TemplateInstance::semantic2(Scope *sc) #endif if (!errors && members) { + TemplateDeclaration *tempdecl = this->tempdecl->isTemplateDeclaration(); + assert(tempdecl); + sc = tempdecl->scope; assert(sc); sc = sc->push(argsym); sc = sc->push(this); sc->tinst = this; + + int needGagging = (speculative && !global.gag); + unsigned int olderrors = global.errors; + int oldGaggedErrors; + if (needGagging) + oldGaggedErrors = global.startGagging(); + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; @@ -7635,7 +7655,24 @@ void TemplateInstance::semantic2(Scope *sc) printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); #endif s->semantic2(sc); + if (speculative && global.errors != olderrors) + break; + } + + if (global.errors != olderrors) + { + if (!errors) + { + if (!tempdecl->literal) + error(loc, "error instantiating"); + if (tinst) + tinst->printInstantiationTrace(); + } + errors = true; } + if (needGagging) + global.endGagging(oldGaggedErrors); + sc = sc->pop(); sc->pop(); } diff --git a/src/traits.c b/src/traits.c index 8edb6141f527..0e37f1b18bb9 100644 --- a/src/traits.c +++ b/src/traits.c @@ -872,8 +872,6 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc) for (size_t i = 0; i < dim; i++) { unsigned errors = global.startGagging(); - unsigned oldspec = global.speculativeGag; - global.speculativeGag = global.gag; Scope *sc2 = sc->push(); sc2->speculative = true; sc2->flags = sc->flags & ~SCOPEctfe | SCOPEcompile; @@ -911,7 +909,6 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc) } sc2->pop(); - global.speculativeGag = oldspec; if (global.endGagging(errors) || err) { goto Lfalse; diff --git a/test/fail_compilation/diag13333.d b/test/fail_compilation/diag13333.d new file mode 100644 index 000000000000..f318a31ae72e --- /dev/null +++ b/test/fail_compilation/diag13333.d @@ -0,0 +1,40 @@ +/* +TEST_OUTPUT* +--- +fail_compilation/diag13333.d(29): Error: template instance VariantN!(maxSize!(S), T) recursive template expansion +fail_compilation/diag13333.d(29): Error: template instance diag13333.maxSize!(S) error instantiating +fail_compilation/diag13333.d(34): instantiated from here: Algebraic!(S) +--- +*/ + +template maxSize(T...) +{ + static if (T.length == 1) + { + enum size_t maxSize = T[0].sizeof; + } + else + { + enum size_t maxSize = T[0].sizeof >= maxSize!(T[1 .. $]) + ? T[0].sizeof : maxSize!(T[1 .. $]); + } +} + +struct VariantN(size_t maxDataSize, AllowedTypesX...) +{ +} + +template Algebraic(T...) +{ + alias Algebraic = VariantN!(maxSize!T, T); +} + +struct DummyScope +{ + alias A = Algebraic!S; + + static struct S // <- class + { + A entity; + } +} diff --git a/test/runnable/template9.d b/test/runnable/template9.d index a53a64b20671..85fbcf55c476 100644 --- a/test/runnable/template9.d +++ b/test/runnable/template9.d @@ -3959,6 +3959,58 @@ struct S13252 { } static assert(is(typeof(TypeTuple13252!(const S13252())[0]) == const(S13252))); static assert(is(typeof(TypeTuple13252!(immutable S13252())[0]) == immutable(S13252))); // OK <- NG +/******************************************/ +// 13333 + +template AliasThisTypeOf13333(T) +{ + static assert(0, T.stringof); // T.stringof is important +} + +template StaticArrayTypeOf13333(T) +{ + static if (is(AliasThisTypeOf13333!T AT)) + alias X = StaticArrayTypeOf13333!AT; + else + alias X = T; + + static if (is(X : E[n], E, size_t n)) + alias StaticArrayTypeOf13333 = X; + else + static assert(0, T.stringof~" is not a static array type"); +} + +enum bool isStaticArray13333(T) = is(StaticArrayTypeOf13333!T); + +struct VaraiantN13333(T) +{ + static if (isStaticArray13333!T) + ~this() { static assert(0); } +} + +struct DummyScope13333 +{ + alias A = VaraiantN13333!C; + + static class C + { + A entity; + } +} + +void test13333() +{ + struct DummyScope + { + alias A = VaraiantN13333!C; + + static class C + { + A entity; + } + } +} + /******************************************/ int main()