diff mbox series

[PR,d/90603] Committed fix for ICE in functionParameters

Message ID CABOHX+d+0gWZWeWrHno883oqauUX-tBRZC6ifdBwMbodvciz+Q@mail.gmail.com
State New
Headers show
Series [PR,d/90603] Committed fix for ICE in functionParameters | expand

Commit Message

Iain Buclaw June 16, 2019, 10:50 p.m. UTC
Hi,

This patch merges the dmd frontend implementation with upstream dmd 792f0fdf2.

Backports semantic pass refactoring, fixing a number of ICEs in
handling forward or recursively referenced declarations.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r272366
diff mbox series

Patch

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 0620a5ba556..d208aea3717 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 572b3e24387..bbe2f8a9d72 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 2a054306347..0018d9501f0 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 fbca54b7dae..ff261bc0ad0 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 3d899f09b52..5f7d7fdc09e 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 0749c7f487d..a1658bbd051 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 1338e1f69b0..22da0a3be3d 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 0173ee401b6..b5e3662a9e3 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 af762eb3c66..c674392095e 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 88c59a9045b..c23e332b180 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 04c70cf3b7b..11e4b2f721b 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 906fb11b634..b76b5baad25 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 b382d0adeb4..2e702ba9d86 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 2d3a11237cb..450b3f4f594 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 143864dc666..cc2b63e2466 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 1d5f3fc1064..24303835268 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
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test16214b.d b/gcc/testsuite/gdc.test/compilable/imports/test16214b.d
new file mode 100644
index 00000000000..e2036fceb9f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test16214b.d
@@ -0,0 +1,10 @@ 
+module test16214b;
+import test16214a;
+
+struct Appender() { int[] arr; }
+struct Tuple() { alias A = Appender!(); }
+
+class EventLoop
+{
+    auto f() { auto x = [Tuple!().init]; }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test16214a.d b/gcc/testsuite/gdc.test/compilable/test16214a.d
new file mode 100644
index 00000000000..2ea64d90329
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test16214a.d
@@ -0,0 +1,7 @@ 
+// EXTRA_SOURCES: imports/test16214b.d
+// REQUIRED_ARGS: -Icompilable/imports
+
+module test16214a;
+import test16214b;
+
+class LibasyncEventLoop : EventLoop {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b15875.d b/gcc/testsuite/gdc.test/fail_compilation/b15875.d
new file mode 100644
index 00000000000..daa79b74a19
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b15875.d
@@ -0,0 +1,10 @@ 
+/* TEST_OUTPUT:
+---
+fail_compilation/b15875.d(9): Error: circular reference to variable `a`
+fail_compilation/b15875.d(10): Error: circular reference to `b15875.f`
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=15875
+// https://issues.dlang.org/show_bug.cgi?id=17290
+d o(int[a]a)(){}
+f.T f(){}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b17285.d b/gcc/testsuite/gdc.test/fail_compilation/b17285.d
new file mode 100644
index 00000000000..7b79cf0666f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b17285.d
@@ -0,0 +1,15 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/b17285.d(14): Error: type `ONE` has no value
+fail_compilation/b17285.d(14): Error: type `TWO` has no value
+fail_compilation/b17285.d(14): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
+---
+*/
+
+class ONE {}
+enum TWO;
+
+void foo() {
+    foreach(key; [ONE, TWO, 1]) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19691.d b/gcc/testsuite/gdc.test/fail_compilation/b19691.d
new file mode 100644
index 00000000000..8663512fd2a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19691.d
@@ -0,0 +1,20 @@ 
+// REQUIRED_ARGS: -de
+/* TEST_OUTPUT:
+---
+fail_compilation/b19691.d(13): Error: forward reference to template `this`
+fail_compilation/b19691.d(19): Deprecation: constructor `b19691.S2.this` all parameters have default arguments, but structs cannot have default constructors.
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=19691
+module b19691;
+
+struct S1 {
+    this(T...)(T) {
+        S2("");
+    }
+}
+
+struct S2 {
+    this(string) {}
+    this(S1 s = null) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19691e.d b/gcc/testsuite/gdc.test/fail_compilation/b19691e.d
new file mode 100644
index 00000000000..21d0e908025
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19691e.d
@@ -0,0 +1,24 @@ 
+// REQUIRED_ARGS: -de
+/* TEST_OUTPUT:
+---
+fail_compilation/b19691e.d(17): Error: forward reference to template `this`
+fail_compilation/b19691e.d(17): Error: constructor `b19691e.S2.this(S1 s = "")` is not callable using argument types `(string)`
+fail_compilation/b19691e.d(17): Error: forward reference to template `this`
+fail_compilation/b19691e.d(23): Deprecation: constructor `b19691e.S2.this` all parameters have default arguments, but structs cannot have default constructors.
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=19691
+module b19691e;
+
+struct S1
+{
+    this(T)(T)
+    {
+        S2("");
+    }
+}
+
+struct S2
+{
+    this(S1 s = ""){}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19717.d b/gcc/testsuite/gdc.test/fail_compilation/b19717.d
new file mode 100644
index 00000000000..6a48b886e03
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19717.d
@@ -0,0 +1,16 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/b19717.d(16): Error: undefined identifier `Foo`, did you mean function `foo`?
+fail_compilation/b19717.d(13): Error: forward reference to template `foo`
+fail_compilation/b19717.d(13): Error: forward reference to inferred return type of function call `foo()`
+---
+*/
+
+enum bar = __traits(getMember, mixin(__MODULE__), "foo");
+
+auto foo() {
+	return foo();
+}
+
+void foo(Foo) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19717a.d b/gcc/testsuite/gdc.test/fail_compilation/b19717a.d
new file mode 100644
index 00000000000..79a9de0ad7c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19717a.d
@@ -0,0 +1,14 @@ 
+// REQUIRED_ARGS: -de
+/* TEST_OUTPUT:
+---
+fail_compilation/b19717a.d(14): Error: forward reference to template `a`
+fail_compilation/b19717a.d(14): Error: forward reference to template `a`
+fail_compilation/b19717a.d(14): Error: none of the overloads of `a` are callable using argument types `()`, candidates are:
+fail_compilation/b19717a.d(13):        `b19717a.a(int b)`
+fail_compilation/b19717a.d(14):        `b19717a.a(int b = a)`
+---
+*/
+module b19717a;
+
+auto a(int b) {}
+auto a(int b = a) {}