Skip to content

Commit

Permalink
Merge pull request #3878 from 9rnsr/fix13333
Browse files Browse the repository at this point in the history
Issue 13333 - Incorrect error ungagging during the resolution of forward references
  • Loading branch information
WalterBright authored and 9rnsr committed Aug 26, 2014
1 parent 5fed9e6 commit 9b23adf
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 45 deletions.
9 changes: 0 additions & 9 deletions src/clone.c
Expand Up @@ -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;

Expand All @@ -106,7 +104,6 @@ FuncDeclaration *hasIdentityOpAssign(AggregateDeclaration *ad, Scope *sc)
}

sc = sc->pop();
global.speculativeGag = oldspec;
global.endGagging(errors);

if (f)
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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;

Expand All @@ -427,7 +419,6 @@ FuncDeclaration *hasIdentityOpEquals(AggregateDeclaration *ad, Scope *sc)
}

sc = sc->pop();
global.speculativeGag = oldspec;
global.endGagging(errors);

if (f)
Expand Down
10 changes: 5 additions & 5 deletions src/declaration.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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())
Expand Down
5 changes: 1 addition & 4 deletions src/expression.c
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 1 addition & 6 deletions src/mars.c
Expand Up @@ -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);
Expand Down Expand Up @@ -167,11 +167,6 @@ bool Global::endGagging(unsigned oldGagged)
return anyErrs;
}

bool Global::isSpeculativeGagging()
{
return gag && gag == speculativeGag;
}

void Global::increaseErrorCount()
{
if (gag)
Expand Down
7 changes: 1 addition & 6 deletions src/mars.h
Expand Up @@ -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.
Expand Down
4 changes: 0 additions & 4 deletions src/mtype.c
Expand Up @@ -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)
{
Expand Down
3 changes: 0 additions & 3 deletions src/struct.c
Expand Up @@ -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())
Expand Down
47 changes: 42 additions & 5 deletions src/template.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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);

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -7623,19 +7633,46 @@ 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];
#if LOG
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();
}
Expand Down
3 changes: 0 additions & 3 deletions src/traits.c
Expand Up @@ -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;
Expand Down Expand Up @@ -911,7 +909,6 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
}

sc2->pop();
global.speculativeGag = oldspec;
if (global.endGagging(errors) || err)
{
goto Lfalse;
Expand Down
40 changes: 40 additions & 0 deletions 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;
}
}
52 changes: 52 additions & 0 deletions test/runnable/template9.d
Expand Up @@ -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()
Expand Down

0 comments on commit 9b23adf

Please sign in to comment.