Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 13333 - Incorrect error ungagging during the resolution of forward references #3878

Merged
merged 5 commits into from
Aug 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 0 additions & 9 deletions src/clone.c
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,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 @@ -673,7 +673,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 @@ -962,7 +962,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 @@ -1954,7 +1954,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
Original file line number Diff line number Diff line change
Expand Up @@ -3188,7 +3188,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 @@ -13913,13 +13913,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
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,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 @@ -168,11 +168,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -7083,12 +7083,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -5787,7 +5787,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 @@ -5850,7 +5854,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 @@ -5872,9 +5876,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 @@ -6900,6 +6904,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 @@ -7361,19 +7371,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
Original file line number Diff line number Diff line change
Expand Up @@ -907,8 +907,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 @@ -946,7 +944,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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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