aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gcc.gnu.org>2019-06-16 22:50:16 +0000
committerIain Buclaw <ibuclaw@gcc.gnu.org>2019-06-16 22:50:16 +0000
commit956fba45850b476de63844b351a7cbad13a0ae46 (patch)
treeeb5cdd6e7f9857dc9c52767d850df73fb6425beb /gcc/d
parentbbd54be5a73dc82548f7fc3d17542caed679fab8 (diff)
downloadgcc-956fba45850b476de63844b351a7cbad13a0ae46.zip
gcc-956fba45850b476de63844b351a7cbad13a0ae46.tar.gz
gcc-956fba45850b476de63844b351a7cbad13a0ae46.tar.bz2
re PR d/90603 (ICE in functionParameters, at d/dmd/expression.c:1553)
PR d/90603 d/dmd: Merge upstream dmd 792f0fdf2 Fixes segmentation fault in functionParameters, and other related semantic bugs in forward or recursively referenced declarations. Reviewed-on: https://github.com/dlang/dmd/pull/10046 From-SVN: r272366
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/dclass.c10
-rw-r--r--gcc/d/dmd/declaration.c8
-rw-r--r--gcc/d/dmd/denum.c3
-rw-r--r--gcc/d/dmd/dimport.c8
-rw-r--r--gcc/d/dmd/dinterpret.c4
-rw-r--r--gcc/d/dmd/dstruct.c5
-rw-r--r--gcc/d/dmd/dtemplate.c9
-rw-r--r--gcc/d/dmd/expression.c9
-rw-r--r--gcc/d/dmd/expressionsem.c21
-rw-r--r--gcc/d/dmd/func.c5
-rw-r--r--gcc/d/dmd/mtype.c42
-rw-r--r--gcc/d/dmd/optimize.c4
-rw-r--r--gcc/d/dmd/statement.c3
-rw-r--r--gcc/d/dmd/statementsem.c4
-rw-r--r--gcc/d/dmd/traits.c6
16 files changed, 94 insertions, 49 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 0620a5b..d208aea 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-6e44734ccbeb78252a52e129a67fefb313679948
+792f0fdf249b21531dc91690024827f4f9ecbb97
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/dclass.c b/gcc/d/dmd/dclass.c
index 572b3e2..bbe2f8a 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -481,7 +481,7 @@ void ClassDeclaration::semantic(Scope *sc)
baseClass = tc->sym;
b->sym = baseClass;
- if (tc->sym->_scope && tc->sym->baseok < BASEOKdone)
+ if (tc->sym->baseok < BASEOKdone)
resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
if (tc->sym->baseok < BASEOKdone)
{
@@ -533,7 +533,7 @@ void ClassDeclaration::semantic(Scope *sc)
b->sym = tc->sym;
- if (tc->sym->_scope && tc->sym->baseok < BASEOKdone)
+ if (tc->sym->baseok < BASEOKdone)
resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
if (tc->sym->baseok < BASEOKdone)
{
@@ -918,10 +918,10 @@ bool ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
{
/* cd->baseClass might not be set if cd is forward referenced.
*/
- if (!cd->baseClass && cd->_scope && !cd->isInterfaceDeclaration())
+ if (!cd->baseClass && cd->semanticRun < PASSsemanticdone && !cd->isInterfaceDeclaration())
{
cd->semantic(NULL);
- if (!cd->baseClass && cd->_scope)
+ if (!cd->baseClass && cd->semanticRun < PASSsemanticdone)
cd->error("base class is forward referenced by %s", toChars());
}
@@ -1574,7 +1574,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
b->sym = tc->sym;
- if (tc->sym->_scope && tc->sym->baseok < BASEOKdone)
+ if (tc->sym->baseok < BASEOKdone)
resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
if (tc->sym->baseok < BASEOKdone)
{
diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c
index 2a05430..0018d95 100644
--- a/gcc/d/dmd/declaration.c
+++ b/gcc/d/dmd/declaration.c
@@ -865,6 +865,11 @@ void VarDeclaration::semantic(Scope *sc)
_scope = NULL;
}
+ if (!sc)
+ return;
+
+ semanticRun = PASSsemantic;
+
/* Pick up storage classes from context, but except synchronized,
* override, abstract, and final.
*/
@@ -1038,6 +1043,7 @@ void VarDeclaration::semantic(Scope *sc)
else if (isAliasThisTuple(e))
{
VarDeclaration *v = copyToTemp(0, "__tup", e);
+ v->semantic(sc);
VarExp *ve = new VarExp(loc, v);
ve->type = e->type;
@@ -1439,7 +1445,7 @@ Lnomatch:
if (!e)
{
error("is not a static and cannot have static initializer");
- return;
+ e = new ErrorExp();
}
}
ei = new ExpInitializer(_init->loc, e);
diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c
index fbca54b..ff261bc 100644
--- a/gcc/d/dmd/denum.c
+++ b/gcc/d/dmd/denum.c
@@ -110,6 +110,9 @@ void EnumDeclaration::semantic(Scope *sc)
_scope = NULL;
}
+ if (!sc)
+ return;
+
parent = sc->parent;
type = type->semantic(loc, sc);
diff --git a/gcc/d/dmd/dimport.c b/gcc/d/dmd/dimport.c
index 3d899f0..5f7d7fd 100644
--- a/gcc/d/dmd/dimport.c
+++ b/gcc/d/dmd/dimport.c
@@ -197,12 +197,18 @@ void Import::importAll(Scope *sc)
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s') %s\n", toPrettyChars(), id->toChars());
+ if (semanticRun > PASSinit)
+ return;
if (_scope)
{
sc = _scope;
_scope = NULL;
}
+ if (!sc)
+ return;
+
+ semanticRun = PASSsemantic;
// Load if not already done so
if (!mod)
@@ -291,6 +297,8 @@ void Import::semantic(Scope *sc)
sc = sc->pop();
}
+ semanticRun = PASSsemanticdone;
+
// object self-imports itself, so skip that (Bugzilla 7547)
// don't list pseudo modules __entrypoint.d, __main.d (Bugzilla 11117, 11164)
if (global.params.moduleDeps != NULL &&
diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c
index 0749c7f..a1658bb 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -2085,9 +2085,9 @@ public:
if (v->ident == Id::ctfe)
return new IntegerExp(loc, 1, Type::tbool);
- if (!v->originalType && v->_scope) // semantic() not yet run
+ if (!v->originalType && v->semanticRun < PASSsemanticdone) // semantic() not yet run
{
- v->semantic (v->_scope);
+ v->semantic(NULL);
if (v->type->ty == Terror)
return CTFEExp::cantexp;
}
diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c
index 1338e1f..22da0a3 100644
--- a/gcc/d/dmd/dstruct.c
+++ b/gcc/d/dmd/dstruct.c
@@ -116,7 +116,7 @@ void semanticTypeInfo(Scope *sc, Type *t)
// Bugzilla 15149, if the typeid operand type comes from a
// result of auto function, it may be yet speculative.
- unSpeculative(sc, sd);
+ // unSpeculative(sc, sd);
}
/* Step 2: If the TypeInfo generation requires sd.semantic3, run it later.
@@ -324,6 +324,7 @@ void AggregateDeclaration::semantic3(Scope *sc)
if (sd)
sd->semanticTypeInfoMembers();
+ semanticRun = PASSsemantic3done;
}
/***************************************
@@ -359,7 +360,7 @@ bool AggregateDeclaration::determineFields()
AggregateDeclaration *ad = ((SV *)param)->agg;
- if (v->_scope)
+ if (v->semanticRun < PASSsemanticdone)
v->semantic(NULL);
// Note: Aggregate fields or size could have determined during v->semantic.
if (ad->sizeok != SIZEOKnone)
diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c
index 0173ee4..b5e3662 100644
--- a/gcc/d/dmd/dtemplate.c
+++ b/gcc/d/dmd/dtemplate.c
@@ -685,6 +685,7 @@ void TemplateDeclaration::semantic(Scope *sc)
/* BUG: should check:
* o no virtual functions or non-static data members of classes
*/
+ semanticRun = PASSsemanticdone;
}
const char *TemplateDeclaration::kind() const
@@ -2169,12 +2170,14 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
if (tiargs && tiargs->dim > 0)
return 0;
- if (fd->semanticRun == PASSinit && fd->_scope)
+ // constructors need a valid scope in order to detect semantic errors
+ if (!fd->isCtorDeclaration() &&
+ fd->semanticRun < PASSsemanticdone)
{
Ungag ungag = fd->ungagSpeculative();
- fd->semantic(fd->_scope);
+ fd->semantic(NULL);
}
- if (fd->semanticRun == PASSinit)
+ if (fd->semanticRun < PASSsemanticdone)
{
::error(loc, "forward reference to template %s", fd->toChars());
return 1;
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index af762eb..c674392 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -516,9 +516,9 @@ static bool checkPropertyCall(Expression *e)
tf = (TypeFunction *)ce->f->type;
/* If a forward reference to ce->f, try to resolve it
*/
- if (!tf->deco && ce->f->_scope)
+ if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
{
- ce->f->semantic(ce->f->_scope);
+ ce->f->semantic(NULL);
tf = (TypeFunction *)ce->f->type;
}
}
@@ -1125,6 +1125,8 @@ bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
Type *t0 = NULL;
Expression *e0 = NULL; // dead-store to prevent spurious warning
size_t j0 = ~0; // dead-store to prevent spurious warning
+ bool foundType = false;
+
for (size_t i = 0; i < exps->dim; i++)
{
Expression *e = (*exps)[i];
@@ -1140,6 +1142,7 @@ bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
}
if (e->op == TOKtype)
{
+ foundType = true; // do not break immediately, there might be more errors
e->checkValue(); // report an error "type T has no value"
t0 = Type::terror;
continue;
@@ -1158,7 +1161,7 @@ bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
e = doCopyOrMove(sc, e);
- if (t0 && !t0->equals(e->type))
+ if (!foundType && t0 && !t0->equals(e->type))
{
/* This applies ?: to merge the types. It's backwards;
* ?: should call this function to merge types.
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index 88c59a9..c23e332 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -397,6 +397,7 @@ public:
// Create the magic __ctfe bool variable
VarDeclaration *vd = new VarDeclaration(exp->loc, Type::tbool, Id::ctfe, NULL);
vd->storage_class |= STCtemp;
+ vd->semanticRun = PASSsemanticdone;
Expression *e = new VarExp(exp->loc, vd);
e = semantic(e, sc);
result = e;
@@ -1441,7 +1442,10 @@ public:
void visit(VarExp *e)
{
- if (FuncDeclaration *fd = e->var->isFuncDeclaration())
+ VarDeclaration *vd = e->var->isVarDeclaration();
+ FuncDeclaration *fd = e->var->isFuncDeclaration();
+
+ if (fd)
{
//printf("L%d fd = %s\n", __LINE__, f->toChars());
if (!fd->functionSemantic())
@@ -1452,7 +1456,14 @@ public:
e->type = e->var->type;
if (e->type && !e->type->deco)
+ {
+ Declaration *decl = e->var->isDeclaration();
+ if (decl)
+ decl->inuse++;
e->type = e->type->semantic(e->loc, sc);
+ if (decl)
+ decl->inuse--;
+ }
/* Fix for 1161 doesn't work because it causes protection
* problems when instantiating imported templates passing private
@@ -1460,7 +1471,7 @@ public:
*/
//checkAccess(e->loc, sc, NULL, e->var);
- if (VarDeclaration *vd = e->var->isVarDeclaration())
+ if (vd)
{
if (vd->checkNestedReference(sc, e->loc))
return setError();
@@ -1468,7 +1479,7 @@ public:
// the purity violation error is redundant.
//checkPurity(sc, vd);
}
- else if (FuncDeclaration *fd = e->var->isFuncDeclaration())
+ else if (fd)
{
// TODO: If fd isn't yet resolved its overload, the checkNestedReference
// call would cause incorrect validation.
@@ -1962,8 +1973,8 @@ public:
ClassDeclaration *cd = ((TypeClass *)e->targ)->sym;
Parameters *args = new Parameters;
args->reserve(cd->baseclasses->dim);
- if (cd->_scope && !cd->symtab)
- cd->semantic(cd->_scope);
+ if (cd->semanticRun < PASSsemanticdone)
+ cd->semantic(NULL);
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{
BaseClass *b = (*cd->baseclasses)[i];
diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c
index 04c70cf..11e4b2f 100644
--- a/gcc/d/dmd/func.c
+++ b/gcc/d/dmd/func.c
@@ -471,6 +471,9 @@ void FuncDeclaration::semantic(Scope *sc)
_scope = NULL;
}
+ if (!sc || errors)
+ return;
+
parent = sc->parent;
Dsymbol *parent = toParent();
@@ -932,6 +935,7 @@ void FuncDeclaration::semantic(Scope *sc)
case -2:
// can't determine because of forward references
+ errors = true;
return;
default:
@@ -1049,6 +1053,7 @@ void FuncDeclaration::semantic(Scope *sc)
case -2:
// can't determine because of forward references
+ errors = true;
return;
default:
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index 906fb11..b76b5ba 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -4672,7 +4672,7 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc)
/* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up.
*/
StructDeclaration *sd = ((TypeStruct *)tbase)->sym;
- if (sd->_scope)
+ if (sd->semanticRun < PASSsemanticdone)
sd->semantic(NULL);
// duplicate a part of StructDeclaration::semanticTypeInfoMembers
@@ -4739,7 +4739,7 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc)
else if (tbase->ty == Tclass && !((TypeClass *)tbase)->sym->isInterfaceDeclaration())
{
ClassDeclaration *cd = ((TypeClass *)tbase)->sym;
- if (cd->_scope)
+ if (cd->semanticRun < PASSsemanticdone)
cd->semantic(NULL);
if (!ClassDeclaration::object)
@@ -5336,7 +5336,7 @@ int Type::covariant(Type *t, StorageClass *pstc, bool fix17349)
// If t1n is forward referenced:
ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
- if (cd->_scope)
+ if (cd->semanticRun < PASSsemanticdone && !cd->isBaseInfoComplete())
cd->semantic(NULL);
if (!cd->isBaseInfoComplete())
{
@@ -5448,6 +5448,13 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
bool errors = false;
+ if (inuse > 500)
+ {
+ inuse = 0;
+ ::error(loc, "recursive type");
+ return Type::terror;
+ }
+
/* Copy in order to not mess up original.
* This can produce redundant copies if inferring return type,
* as semantic() will get called again on this.
@@ -5532,9 +5539,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
for (size_t i = 0; i < dim; i++)
{
Parameter *fparam = Parameter::getNth(tf->parameters, i);
- tf->inuse++;
+ inuse++;
fparam->type = fparam->type->semantic(loc, argsc);
- if (tf->inuse == 1) tf->inuse--;
+ inuse--;
if (fparam->type->ty == Terror)
{
@@ -5776,13 +5783,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
tf->iswild = wildparams;
- if (tf->inuse)
- {
- error(loc, "recursive type");
- tf->inuse = 0;
- errors = true;
- }
-
if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 2))
{
error(loc, "properties can only have zero, one, or two parameter");
@@ -7444,8 +7444,8 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident, int fl
if (ident == Id::_mangleof)
return getProperty(e->loc, ident, flag & 1);
- if (sym->_scope)
- sym->semantic(sym->_scope);
+ if (sym->semanticRun < PASSsemanticdone)
+ sym->semantic(NULL);
if (!sym->members)
{
if (sym->isSpecial())
@@ -7914,8 +7914,8 @@ L1:
return e;
}
}
- if (d->semanticRun == PASSinit && d->_scope)
- d->semantic(d->_scope);
+ if (d->semanticRun == PASSinit)
+ d->semantic(NULL);
checkAccess(e->loc, sc, e, d);
VarExp *ve = new VarExp(e->loc, d);
if (d->isVarDeclaration() && d->needThis())
@@ -8443,7 +8443,7 @@ L1:
if (ident == Id::outer && sym->vthis)
{
- if (sym->vthis->_scope)
+ if (sym->vthis->semanticRun == PASSinit)
sym->vthis->semantic(NULL);
if (ClassDeclaration *cdp = sym->toParent2()->isClassDeclaration())
@@ -8670,8 +8670,8 @@ L1:
}
}
//printf("e = %s, d = %s\n", e->toChars(), d->toChars());
- if (d->semanticRun == PASSinit && d->_scope)
- d->semantic(d->_scope);
+ if (d->semanticRun == PASSinit)
+ d->semantic(NULL);
checkAccess(e->loc, sc, e, d);
VarExp *ve = new VarExp(e->loc, d);
if (d->isVarDeclaration() && d->needThis())
@@ -8727,9 +8727,9 @@ MATCH TypeClass::implicitConvTo(Type *to)
if (cdto)
{
//printf("TypeClass::implicitConvTo(to = '%s') %s, isbase = %d %d\n", to->toChars(), toChars(), cdto->isBaseInfoComplete(), sym->isBaseInfoComplete());
- if (cdto->_scope && !cdto->isBaseInfoComplete())
+ if (cdto->semanticRun < PASSsemanticdone && !cdto->isBaseInfoComplete())
cdto->semantic(NULL);
- if (sym->_scope && !sym->isBaseInfoComplete())
+ if (sym->semanticRun < PASSsemanticdone && !sym->isBaseInfoComplete())
sym->semantic(NULL);
if (cdto->isBaseOf(sym, NULL) && MODimplicitConv(mod, to->mod))
{
diff --git a/gcc/d/dmd/optimize.c b/gcc/d/dmd/optimize.c
index b382d0a..2e702ba 100644
--- a/gcc/d/dmd/optimize.c
+++ b/gcc/d/dmd/optimize.c
@@ -34,8 +34,8 @@ Expression *expandVar(int result, VarDeclaration *v)
Expression *e = NULL;
if (!v)
return e;
- if (!v->originalType && v->_scope) // semantic() not yet run
- v->semantic (v->_scope);
+ if (!v->originalType && v->semanticRun < PASSsemanticdone) // semantic() not yet run
+ v->semantic(NULL);
if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest)
{
diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c
index 2d3a112..450b3f4 100644
--- a/gcc/d/dmd/statement.c
+++ b/gcc/d/dmd/statement.c
@@ -1312,7 +1312,7 @@ Statement *OnScopeStatement::syntaxCopy()
return new OnScopeStatement(loc, tok, statement->syntaxCopy());
}
-Statement *OnScopeStatement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally)
+Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
{
//printf("OnScopeStatement::scopeCode()\n");
//print();
@@ -1340,6 +1340,7 @@ Statement *OnScopeStatement::scopeCode(Scope *, Statement **sentry, Statement **
* sfinally: if (!x) statement;
*/
VarDeclaration *v = copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool));
+ v->semantic(sc);
*sentry = new ExpStatement(loc, v);
Expression *e = new IntegerExp(Loc(), 1, Type::tbool);
diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c
index 143864dc6..cc2b63e 100644
--- a/gcc/d/dmd/statementsem.c
+++ b/gcc/d/dmd/statementsem.c
@@ -1074,6 +1074,7 @@ public:
else
{
r = copyToTemp(0, "__r", fs->aggr);
+ r->semantic(sc);
init = new ExpStatement(loc, r);
if (vinit)
init = new CompoundStatement(loc, new ExpStatement(loc, vinit), init);
@@ -1106,6 +1107,7 @@ public:
else
{
VarDeclaration *vd = copyToTemp(STCref, "__front", einit);
+ vd->semantic(sc);
makeargs = new ExpStatement(loc, vd);
Type *tfront = NULL;
@@ -2986,6 +2988,7 @@ public:
* try { body } finally { _d_monitorexit(tmp); }
*/
VarDeclaration *tmp = copyToTemp(0, "__sync", ss->exp);
+ tmp->semantic(sc);
Statements *cs = new Statements();
cs->push(new ExpStatement(ss->loc, tmp));
@@ -3133,6 +3136,7 @@ public:
* }
*/
VarDeclaration *tmp = copyToTemp(0, "__withtmp", ws->exp);
+ tmp->semantic(sc);
ExpStatement *es = new ExpStatement(ws->loc, tmp);
ws->exp = new VarExp(ws->loc, tmp);
Statement *ss = new ScopeStatement(ws->loc, new CompoundStatement(ws->loc, es, ws), ws->endloc);
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 1d5f3fc..2430383 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -671,8 +671,8 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
e->error("argument %s has no protection", o->toChars());
return new ErrorExp();
}
- if (s->_scope)
- s->semantic(s->_scope);
+ if (s->semanticRun == PASSinit)
+ s->semantic(NULL);
const char *protName = protectionToChars(s->prot().kind); // TODO: How about package(names)
assert(protName);
@@ -1240,7 +1240,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
ClassDeclaration *cd = sds->isClassDeclaration();
if (cd && e->ident == Id::allMembers)
{
- if (cd->_scope)
+ if (cd->semanticRun < PASSsemanticdone)
cd->semantic(NULL); // Bugzilla 13668: Try to resolve forward reference
struct PushBaseMembers