]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Merge upstream dmd 7132b3537
authorIain Buclaw <ibuclaw@gdcproject.org>
Tue, 9 Feb 2021 14:40:06 +0000 (15:40 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sat, 13 Feb 2021 11:50:45 +0000 (12:50 +0100)
Splits out all semantic passes for Dsymbol, Type, and TemplateParameter
nodes into Visitors in separate files, and the copyright years of all
sources have been updated.

Reviewed-on: https://github.com/dlang/dmd/pull/12190

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream dmd 7132b3537.
* Make-lang.in (D_FRONTEND_OBJS): Add d/dsymbolsem.o, d/semantic2.o,
d/semantic3.o, and d/templateparamsem.o.
* d-compiler.cc (Compiler::genCmain): Update calls to semantic
entrypoint functions.
* d-lang.cc (d_parse_file): Likewise.
* typeinfo.cc (make_frontend_typeinfo): Likewise.

139 files changed:
gcc/d/Make-lang.in
gcc/d/d-compiler.cc
gcc/d/d-lang.cc
gcc/d/dmd/MERGE
gcc/d/dmd/access.c
gcc/d/dmd/aggregate.h
gcc/d/dmd/aliasthis.c
gcc/d/dmd/aliasthis.h
gcc/d/dmd/apply.c
gcc/d/dmd/arrayop.c
gcc/d/dmd/arraytypes.h
gcc/d/dmd/ast_node.h
gcc/d/dmd/attrib.c
gcc/d/dmd/attrib.h
gcc/d/dmd/blockexit.c
gcc/d/dmd/canthrow.c
gcc/d/dmd/clone.c
gcc/d/dmd/compiler.h
gcc/d/dmd/complex_t.h
gcc/d/dmd/cond.c
gcc/d/dmd/cond.h
gcc/d/dmd/constfold.c
gcc/d/dmd/cppmangle.c
gcc/d/dmd/ctfe.h
gcc/d/dmd/ctfeexpr.c
gcc/d/dmd/dcast.c
gcc/d/dmd/dclass.c
gcc/d/dmd/declaration.c
gcc/d/dmd/declaration.h
gcc/d/dmd/delegatize.c
gcc/d/dmd/denum.c
gcc/d/dmd/dimport.c
gcc/d/dmd/dinterpret.c
gcc/d/dmd/dmacro.c
gcc/d/dmd/dmangle.c
gcc/d/dmd/dmodule.c
gcc/d/dmd/doc.c
gcc/d/dmd/doc.h
gcc/d/dmd/dscope.c
gcc/d/dmd/dstruct.c
gcc/d/dmd/dsymbol.c
gcc/d/dmd/dsymbol.h
gcc/d/dmd/dsymbolsem.c [new file with mode: 0644]
gcc/d/dmd/dtemplate.c
gcc/d/dmd/dversion.c
gcc/d/dmd/entity.c
gcc/d/dmd/enum.h
gcc/d/dmd/errors.h
gcc/d/dmd/escape.c
gcc/d/dmd/expression.c
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.c
gcc/d/dmd/func.c
gcc/d/dmd/globals.h
gcc/d/dmd/hdrgen.c
gcc/d/dmd/hdrgen.h
gcc/d/dmd/iasm.c
gcc/d/dmd/iasmgcc.c
gcc/d/dmd/identifier.c
gcc/d/dmd/identifier.h
gcc/d/dmd/idgen.c
gcc/d/dmd/impcnvgen.c
gcc/d/dmd/imphint.c
gcc/d/dmd/import.h
gcc/d/dmd/init.c
gcc/d/dmd/init.h
gcc/d/dmd/initsem.c
gcc/d/dmd/intrange.c
gcc/d/dmd/intrange.h
gcc/d/dmd/json.c
gcc/d/dmd/json.h
gcc/d/dmd/lexer.c
gcc/d/dmd/lexer.h
gcc/d/dmd/macro.h
gcc/d/dmd/mangle.h
gcc/d/dmd/mars.h
gcc/d/dmd/module.h
gcc/d/dmd/mtype.c
gcc/d/dmd/mtype.h
gcc/d/dmd/nogc.c
gcc/d/dmd/nspace.c
gcc/d/dmd/nspace.h
gcc/d/dmd/objc.c
gcc/d/dmd/objc.h
gcc/d/dmd/opover.c
gcc/d/dmd/optimize.c
gcc/d/dmd/parse.c
gcc/d/dmd/parse.h
gcc/d/dmd/root/aav.c
gcc/d/dmd/root/aav.h
gcc/d/dmd/root/array.h
gcc/d/dmd/root/bitarray.h
gcc/d/dmd/root/checkedint.c
gcc/d/dmd/root/checkedint.h
gcc/d/dmd/root/ctfloat.h
gcc/d/dmd/root/dcompat.h
gcc/d/dmd/root/file.c
gcc/d/dmd/root/file.h
gcc/d/dmd/root/filename.c
gcc/d/dmd/root/filename.h
gcc/d/dmd/root/hash.h
gcc/d/dmd/root/object.h
gcc/d/dmd/root/outbuffer.c
gcc/d/dmd/root/outbuffer.h
gcc/d/dmd/root/port.h
gcc/d/dmd/root/rmem.c
gcc/d/dmd/root/rmem.h
gcc/d/dmd/root/root.h
gcc/d/dmd/root/rootobject.c
gcc/d/dmd/root/speller.c
gcc/d/dmd/root/speller.h
gcc/d/dmd/root/stringtable.c
gcc/d/dmd/root/stringtable.h
gcc/d/dmd/safe.c
gcc/d/dmd/sapply.c
gcc/d/dmd/scope.h
gcc/d/dmd/semantic2.c [new file with mode: 0644]
gcc/d/dmd/semantic3.c [new file with mode: 0644]
gcc/d/dmd/sideeffect.c
gcc/d/dmd/statement.c
gcc/d/dmd/statement.h
gcc/d/dmd/statement_rewrite_walker.h [new file with mode: 0644]
gcc/d/dmd/statementsem.c
gcc/d/dmd/staticassert.c
gcc/d/dmd/staticassert.h
gcc/d/dmd/staticcond.c
gcc/d/dmd/target.h
gcc/d/dmd/template.h
gcc/d/dmd/templateparamsem.c [new file with mode: 0644]
gcc/d/dmd/tokens.c
gcc/d/dmd/tokens.h
gcc/d/dmd/traits.c
gcc/d/dmd/typesem.c
gcc/d/dmd/utf.c
gcc/d/dmd/utf.h
gcc/d/dmd/utils.c
gcc/d/dmd/version.h
gcc/d/dmd/visitor.h
gcc/d/typeinfo.cc

index 2b3c936a3fab595de432daa90c6c2059274af538..b0fce06e507bb7a4d3d38f34112724ad52543020 100644 (file)
@@ -84,6 +84,7 @@ D_FRONTEND_OBJS = \
        d/dscope.o \
        d/dstruct.o \
        d/dsymbol.o \
+       d/dsymbolsem.o \
        d/dtemplate.o \
        d/dversion.o \
        d/entity.o \
@@ -115,6 +116,8 @@ D_FRONTEND_OBJS = \
        d/rootobject.o \
        d/safe.o \
        d/sapply.o \
+       d/semantic2.o \
+       d/semantic3.o \
        d/sideeffect.o \
        d/speller.o \
        d/statement.o \
@@ -122,6 +125,7 @@ D_FRONTEND_OBJS = \
        d/staticassert.o \
        d/staticcond.o \
        d/stringtable.o \
+       d/templateparamsem.o \
        d/tokens.o \
        d/traits.o \
        d/typesem.o \
index 3907d0106841b861e86125d48bdcac3c3ec23d5e..512ef4bab3e185c6f70e3efe5bdf87e164031255 100644 (file)
@@ -59,9 +59,9 @@ Compiler::genCmain (Scope *sc)
     {
       m->importedFrom = m;
       m->importAll (NULL);
-      m->semantic (NULL);
-      m->semantic2 (NULL);
-      m->semantic3 (NULL);
+      dsymbolSemantic (m, NULL);
+      semantic2 (m, NULL);
+      semantic3 (m, NULL);
       d_add_entrypoint_module (m, sc->_module);
     }
 
index 0fd207da7f3b3f7e738e108572e07be29e2df090..1a51c5e4b7c6d18910568657d8f82b3d74b462e3 100644 (file)
@@ -1051,7 +1051,7 @@ d_parse_file (void)
       if (global.params.verbose)
        message ("semantic  %s", m->toChars ());
 
-      m->semantic (NULL);
+      dsymbolSemantic (m, NULL);
     }
 
   /* Do deferred semantic analysis.  */
@@ -1083,7 +1083,7 @@ d_parse_file (void)
       if (global.params.verbose)
        message ("semantic2 %s", m->toChars ());
 
-      m->semantic2 (NULL);
+      semantic2 (m, NULL);
     }
 
   Module::runDeferredSemantic2 ();
@@ -1099,7 +1099,7 @@ d_parse_file (void)
       if (global.params.verbose)
        message ("semantic3 %s", m->toChars ());
 
-      m->semantic3 (NULL);
+      semantic3 (m, NULL);
     }
 
   Module::runDeferredSemantic3 ();
index 89397c836e2d2f8ffabfd6a98be01121e83492d9..690fe4072787a533ec918cec66546b293b64abfc 100644 (file)
@@ -1,4 +1,4 @@
-46133f76172c26c89e2ebf9cd058cd1f1e8807ed
+7132b3537dc27cb353da75798082ffe7ea3d69a6
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 63f46c60f63273f9c36fd7421528e4453c9c6956..11b26c5dc5c3569b0c50aaa95d511faa5ef6ee58 100644 (file)
@@ -1,5 +1,5 @@
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 6cfc76d8c6ca60172b7e91bb3ba356f4ae638cfd..4935e6a1f5d2e368911d3f5b3791ef8ccb1457b1 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -131,8 +131,6 @@ public:
     AggregateDeclaration(Loc loc, Identifier *id);
     virtual Scope *newScope(Scope *sc);
     void setScope(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
     bool determineFields();
     bool determineSize(Loc loc);
     virtual void finalizeSize() = 0;
@@ -203,7 +201,6 @@ public:
     StructDeclaration(Loc loc, Identifier *id, bool inObject);
     static StructDeclaration *create(Loc loc, Identifier *id, bool inObject);
     Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
     void semanticTypeInfoMembers();
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
     const char *kind() const;
@@ -299,7 +296,6 @@ public:
     static ClassDeclaration *create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
     Dsymbol *syntaxCopy(Dsymbol *s);
     Scope *newScope(Scope *sc);
-    void semantic(Scope *sc);
     bool isBaseOf2(ClassDeclaration *cd);
 
     #define OFFSET_RUNTIME 0x76543210
@@ -313,7 +309,6 @@ public:
     bool hasMonitor();
     bool isFuncHidden(FuncDeclaration *fd);
     FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
-    void interfaceSemantic(Scope *sc);
     bool isCOMclass() const;
     virtual bool isCOMinterface() const;
     bool isCPPclass() const;
@@ -337,7 +332,6 @@ public:
     InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
     Dsymbol *syntaxCopy(Dsymbol *s);
     Scope *newScope(Scope *sc);
-    void semantic(Scope *sc);
     bool isBaseOf(ClassDeclaration *cd, int *poffset);
     bool isBaseOf(BaseClass *bc, int *poffset);
     const char *kind() const;
index 9da64d042eb7f05d613a9620e23f473a0916cd71..458416f495099bbc1931ccbd9c9a993c494cf12d 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2009-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2009-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
 #include "dsymbol.h"
 #include "mtype.h"
 #include "declaration.h"
+#include "expression.h"
 #include "tokens.h"
 
-Expression *semantic(Expression *e, Scope *sc);
-
 Expression *resolveAliasThis(Scope *sc, Expression *e, bool gag)
 {
     AggregateDeclaration *ad = isAggregate(e->type);
@@ -33,7 +32,7 @@ Expression *resolveAliasThis(Scope *sc, Expression *e, bool gag)
         Loc loc = e->loc;
         Type *tthis = (e->op == TOKtype ? e->type : NULL);
         e = new DotIdExp(loc, e, ad->aliasthis->ident);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         if (tthis && ad->aliasthis->needThis())
         {
             if (e->op == TOKvar)
@@ -65,7 +64,7 @@ Expression *resolveAliasThis(Scope *sc, Expression *e, bool gag)
 
         L1:
             e = new TypeExp(loc, new TypeTypeof(loc, e));
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
         }
         e = resolveProperties(sc, e);
 
@@ -89,79 +88,6 @@ Dsymbol *AliasThis::syntaxCopy(Dsymbol *s)
     return new AliasThis(loc, ident);
 }
 
-void AliasThis::semantic(Scope *sc)
-{
-    if (semanticRun != PASSinit)
-        return;
-
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    if (!sc)
-        return;
-
-    semanticRun = PASSsemantic;
-
-    Dsymbol *p = sc->parent->pastMixin();
-    AggregateDeclaration *ad = p->isAggregateDeclaration();
-    if (!ad)
-    {
-        ::error(loc, "alias this can only be a member of aggregate, not %s %s",
-            p->kind(), p->toChars());
-        return;
-    }
-
-    assert(ad->members);
-    Dsymbol *s = ad->search(loc, ident);
-    if (!s)
-    {
-        s = sc->search(loc, ident, NULL);
-        if (s)
-            ::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
-        else
-            ::error(loc, "undefined identifier %s", ident->toChars());
-        return;
-    }
-    else if (ad->aliasthis && s != ad->aliasthis)
-    {
-        ::error(loc, "there can be only one alias this");
-        return;
-    }
-
-    if (ad->type->ty == Tstruct && ((TypeStruct *)ad->type)->sym != ad)
-    {
-        AggregateDeclaration *ad2 = ((TypeStruct *)ad->type)->sym;
-        assert(ad2->type == Type::terror);
-        ad->aliasthis = ad2->aliasthis;
-        return;
-    }
-
-    /* disable the alias this conversion so the implicit conversion check
-     * doesn't use it.
-     */
-    ad->aliasthis = NULL;
-
-    Dsymbol *sx = s;
-    if (sx->isAliasDeclaration())
-        sx = sx->toAlias();
-    Declaration *d = sx->isDeclaration();
-    if (d && !d->isTupleDeclaration())
-    {
-        Type *t = d->type;
-        assert(t);
-        if (ad->type->implicitConvTo(t) > MATCHnomatch)
-        {
-            ::error(loc, "alias this is not reachable as %s already converts to %s", ad->toChars(), t->toChars());
-        }
-    }
-
-    ad->aliasthis = s;
-    semanticRun = PASSsemanticdone;
-}
-
 const char *AliasThis::kind() const
 {
     return "alias this";
index 816a4ee8f79a66f330c067789f96ab10e531f1d6..15905e417108de3bd3b389bb412843a796487b17 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2009-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2009-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -23,7 +23,6 @@ public:
     AliasThis(Loc loc, Identifier *ident);
 
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     const char *kind() const;
     AliasThis *isAliasThis() { return this; }
     void accept(Visitor *v) { v->visit(this); }
index 6f3301ed1dfd5a0de972dea4a26d4fedcc2b89b3..8a727ae66d144177e7525b12ee159815837f7df3 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 20cdb6fd1847ea8628db5b1d86f6555217d3ec7b..52d596bb87191598f3f3a5c2899be736e92693a6 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -25,7 +25,6 @@
 
 void buildArrayIdent(Expression *e, OutBuffer *buf, Expressions *arguments);
 Expression *buildArrayLoop(Expression *e, Parameters *fparams);
-Expression *semantic(Expression *e, Scope *sc);
 
 /**************************************
  * Hash table of array op functions already generated or known about.
@@ -80,10 +79,10 @@ FuncDeclaration *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc)
     sc->parent = sc->_module->importedFrom;
     sc->stc = 0;
     sc->linkage = LINKc;
-    fd->semantic(sc);
-    fd->semantic2(sc);
+    dsymbolSemantic(fd, sc);
+    semantic2(fd, sc);
     unsigned errors = global.startGagging();
-    fd->semantic3(sc);
+    semantic3(fd, sc);
     if (global.endGagging(errors))
     {
         fd->type = Type::terror;
@@ -231,7 +230,7 @@ Expression *arrayOp(BinExp *e, Scope *sc)
     Expression *ev = new VarExp(e->loc, fd);
     Expression *ec = new CallExp(e->loc, ev, arguments);
 
-    return semantic(ec, sc);
+    return expressionSemantic(ec, sc);
 }
 
 Expression *arrayOp(BinAssignExp *e, Scope *sc)
index 627464a635f2e45985d0ae2b32108e04caff4595..0ecccf170bd011c8685b2a9300158585c1f37ddd 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2006-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2006-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 09519af0e9937cfb56974bace8abb14c19895597..5576dd74e0da60b3303571018870e163ac35c97b 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 5445b9e596806526434ed7c934fdf17aed46e5ab..56b8ce816beae31f2729407e1158b75a0bce1943 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -29,8 +29,6 @@
 #include "mtype.h"
 
 bool definitelyValueParameter(Expression *e);
-Expression *semantic(Expression *e, Scope *sc);
-StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
 Dsymbols *makeTupleForeachStaticDecl(Scope *sc, ForeachStatement *fs, Dsymbols *dbody, bool needExpansion);
 
 /********************************* AttribDeclaration ****************************/
@@ -169,68 +167,6 @@ void AttribDeclaration::importAll(Scope *sc)
     }
 }
 
-void AttribDeclaration::semantic(Scope *sc)
-{
-    if (semanticRun != PASSinit)
-        return;
-    semanticRun = PASSsemantic;
-    Dsymbols *d = include(sc);
-
-    //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
-    if (d)
-    {
-        Scope *sc2 = newScope(sc);
-
-        for (size_t i = 0; i < d->length; i++)
-        {
-            Dsymbol *s = (*d)[i];
-            s->semantic(sc2);
-        }
-
-        if (sc2 != sc)
-            sc2->pop();
-    }
-    semanticRun = PASSsemanticdone;
-}
-
-void AttribDeclaration::semantic2(Scope *sc)
-{
-    Dsymbols *d = include(sc);
-
-    if (d)
-    {
-        Scope *sc2 = newScope(sc);
-
-        for (size_t i = 0; i < d->length; i++)
-        {
-            Dsymbol *s = (*d)[i];
-            s->semantic2(sc2);
-        }
-
-        if (sc2 != sc)
-            sc2->pop();
-    }
-}
-
-void AttribDeclaration::semantic3(Scope *sc)
-{
-    Dsymbols *d = include(sc);
-
-    if (d)
-    {
-        Scope *sc2 = newScope(sc);
-
-        for (size_t i = 0; i < d->length; i++)
-        {
-            Dsymbol *s = (*d)[i];
-            s->semantic3(sc2);
-        }
-
-        if (sc2 != sc)
-            sc2->pop();
-    }
-}
-
 void AttribDeclaration::addComment(const utf8_t *comment)
 {
     //printf("AttribDeclaration::addComment %s\n", comment);
@@ -474,22 +410,6 @@ void DeprecatedDeclaration::setScope(Scope *sc)
     return AttribDeclaration::setScope(sc);
 }
 
-/**
- * Run the DeprecatedDeclaration's semantic2 phase then its members.
- *
- * The message set via a `DeprecatedDeclaration` can be either of:
- * - a string literal
- * - an enum
- * - a static immutable
- * So we need to call ctfe to resolve it.
- * Afterward forwards to the members' semantic2.
- */
-void DeprecatedDeclaration::semantic2(Scope *sc)
-{
-    getMessage();
-    StorageClassDeclaration::semantic2(sc);
-}
-
 const char *DeprecatedDeclaration::getMessage()
 {
     if (Scope *sc = _scope)
@@ -497,7 +417,7 @@ const char *DeprecatedDeclaration::getMessage()
         _scope = NULL;
 
         sc = sc->startCTFE();
-        msg = ::semantic(msg, sc);
+        msg = expressionSemantic(msg, sc);
         msg = resolveProperties(sc, msg);
         sc = sc->endCTFE();
         msg = msg->ctfeInterpret();
@@ -505,7 +425,7 @@ const char *DeprecatedDeclaration::getMessage()
         if (StringExp *se = msg->toStringExp())
             msgstr = (char *)se->string;
         else
-            msg->error("compile time constant expected, not '%s'", msg->toChars());
+            msg->error("compile time constant expected, not `%s`", msg->toChars());
     }
     return msgstr;
 }
@@ -613,7 +533,7 @@ Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
 Scope *ProtDeclaration::newScope(Scope *sc)
 {
     if (pkg_identifiers)
-        semantic(sc);
+        dsymbolSemantic(this, sc);
     return createNewScope(sc, sc->stc, sc->linkage, sc->cppmangle,
         this->protection, 1, sc->aligndecl,
         sc->inlining);
@@ -634,7 +554,7 @@ void ProtDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
         Module *m = sc->_module;
         Package* pkg = m->parent ? m->parent->isPackage() : NULL;
         if (!pkg || !protection.pkg->isAncestorPackageOf(pkg))
-            error("does not bind to one of ancestor packages of module '%s'",
+            error("does not bind to one of ancestor packages of module `%s`",
                m->toPrettyChars(true));
     }
 
@@ -682,12 +602,6 @@ Scope *AlignDeclaration::newScope(Scope *sc)
         sc->inlining);
 }
 
-void AlignDeclaration::semantic2(Scope *sc)
-{
-    getAlignment(sc);
-    AttribDeclaration::semantic2(sc);
-}
-
 structalign_t AlignDeclaration::getAlignment(Scope *sc)
 {
     if (salign != 0)
@@ -697,7 +611,7 @@ structalign_t AlignDeclaration::getAlignment(Scope *sc)
         return salign = STRUCTALIGN_DEFAULT;
 
     sc = sc->startCTFE();
-    ealign = ::semantic(ealign, sc);
+    ealign = expressionSemantic(ealign, sc);
     ealign = resolveProperties(sc, ealign);
     sc = sc->endCTFE();
     ealign = ealign->ctfeInterpret();
@@ -744,38 +658,6 @@ void AnonDeclaration::setScope(Scope *sc)
     AttribDeclaration::setScope(sc);
 }
 
-void AnonDeclaration::semantic(Scope *sc)
-{
-    //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
-
-    assert(sc->parent);
-
-    Dsymbol *p = sc->parent->pastMixin();
-    AggregateDeclaration *ad = p->isAggregateDeclaration();
-    if (!ad)
-    {
-        ::error(loc, "%s can only be a part of an aggregate, not %s %s",
-            kind(), p->kind(), p->toChars());
-        errors = true;
-        return;
-    }
-
-    if (decl)
-    {
-        sc = sc->push();
-        sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
-        sc->inunion = isunion;
-        sc->flags = 0;
-
-        for (size_t i = 0; i < decl->length; i++)
-        {
-            Dsymbol *s = (*decl)[i];
-            s->semantic(sc);
-        }
-        sc = sc->pop();
-    }
-}
-
 void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
 {
     //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this);
@@ -916,269 +798,6 @@ Scope *PragmaDeclaration::newScope(Scope *sc)
     return sc;
 }
 
-static unsigned setMangleOverride(Dsymbol *s, char *sym)
-{
-    AttribDeclaration *ad = s->isAttribDeclaration();
-
-    if (ad)
-    {
-        Dsymbols *decls = ad->include(NULL);
-        unsigned nestedCount = 0;
-
-        if (decls && decls->length)
-            for (size_t i = 0; i < decls->length; ++i)
-                nestedCount += setMangleOverride((*decls)[i], sym);
-
-        return nestedCount;
-    }
-    else if (s->isFuncDeclaration() || s->isVarDeclaration())
-    {
-        s->isDeclaration()->mangleOverride = sym;
-        return 1;
-    }
-    else
-        return 0;
-}
-
-void PragmaDeclaration::semantic(Scope *sc)
-{
-    // Should be merged with PragmaStatement
-
-    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
-    if (ident == Id::msg)
-    {
-        if (args)
-        {
-            for (size_t i = 0; i < args->length; i++)
-            {
-                Expression *e = (*args)[i];
-
-                sc = sc->startCTFE();
-                e = ::semantic(e, sc);
-                e = resolveProperties(sc, e);
-                sc = sc->endCTFE();
-
-                // pragma(msg) is allowed to contain types as well as expressions
-                e = ctfeInterpretForPragmaMsg(e);
-                if (e->op == TOKerror)
-                {
-                    errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
-                    return;
-                }
-                StringExp *se = e->toStringExp();
-                if (se)
-                {
-                    se = se->toUTF8(sc);
-                    fprintf(stderr, "%.*s", (int)se->len, (char *)se->string);
-                }
-                else
-                    fprintf(stderr, "%s", e->toChars());
-            }
-            fprintf(stderr, "\n");
-        }
-        goto Lnodecl;
-    }
-    else if (ident == Id::lib)
-    {
-        if (!args || args->length != 1)
-            error("string expected for library name");
-        else
-        {
-            StringExp *se = semanticString(sc, (*args)[0], "library name");
-            if (!se)
-                goto Lnodecl;
-            (*args)[0] = se;
-
-            char *name = (char *)mem.xmalloc(se->len + 1);
-            memcpy(name, se->string, se->len);
-            name[se->len] = 0;
-            if (global.params.verbose)
-                message("library   %s", name);
-            if (global.params.moduleDeps && !global.params.moduleDepsFile.length)
-            {
-                OutBuffer *ob = global.params.moduleDeps;
-                Module *imod = sc->instantiatingModule();
-                ob->writestring("depsLib ");
-                ob->writestring(imod->toPrettyChars());
-                ob->writestring(" (");
-                escapePath(ob, imod->srcfile->toChars());
-                ob->writestring(") : ");
-                ob->writestring((char *) name);
-                ob->writenl();
-            }
-            mem.xfree(name);
-        }
-        goto Lnodecl;
-    }
-    else if (ident == Id::startaddress)
-    {
-        if (!args || args->length != 1)
-            error("function name expected for start address");
-        else
-        {
-            /* Bugzilla 11980:
-             * resolveProperties and ctfeInterpret call are not necessary.
-             */
-            Expression *e = (*args)[0];
-
-            sc = sc->startCTFE();
-            e = ::semantic(e, sc);
-            sc = sc->endCTFE();
-
-            (*args)[0] = e;
-            Dsymbol *sa = getDsymbol(e);
-            if (!sa || !sa->isFuncDeclaration())
-                error("function name expected for start address, not '%s'", e->toChars());
-        }
-        goto Lnodecl;
-    }
-    else if (ident == Id::Pinline)
-    {
-        goto Ldecl;
-    }
-    else if (ident == Id::mangle)
-    {
-        if (!args)
-            args = new Expressions();
-        if (args->length != 1)
-        {
-            error("string expected for mangled name");
-            args->setDim(1);
-            (*args)[0] = new ErrorExp();    // error recovery
-            goto Ldecl;
-        }
-
-        StringExp *se = semanticString(sc, (*args)[0], "mangled name");
-        if (!se)
-            goto Ldecl;
-        (*args)[0] = se; // Will be used for later
-
-        if (!se->len)
-        {
-            error("zero-length string not allowed for mangled name");
-            goto Ldecl;
-        }
-        if (se->sz != 1)
-        {
-            error("mangled name characters can only be of type char");
-            goto Ldecl;
-        }
-
-        /* Note: D language specification should not have any assumption about backend
-         * implementation. Ideally pragma(mangle) can accept a string of any content.
-         *
-         * Therefore, this validation is compiler implementation specific.
-         */
-        for (size_t i = 0; i < se->len; )
-        {
-            utf8_t *p = (utf8_t *)se->string;
-            dchar_t c = p[i];
-            if (c < 0x80)
-            {
-                if ((c >= 'A' && c <= 'Z') ||
-                    (c >= 'a' && c <= 'z') ||
-                    (c >= '0' && c <= '9') ||
-                    (c != 0 && strchr("$%().:?@[]_", c)))
-                {
-                    ++i;
-                    continue;
-                }
-                else
-                {
-                    error("char 0x%02x not allowed in mangled name", c);
-                    break;
-                }
-            }
-
-            if (const char* msg = utf_decodeChar((utf8_t *)se->string, se->len, &i, &c))
-            {
-                error("%s", msg);
-                break;
-            }
-
-            if (!isUniAlpha(c))
-            {
-                error("char 0x%04x not allowed in mangled name", c);
-                break;
-            }
-        }
-    }
-    else if (global.params.ignoreUnsupportedPragmas)
-    {
-        if (global.params.verbose)
-        {
-            /* Print unrecognized pragmas
-             */
-            OutBuffer buf;
-            buf.writestring(ident->toChars());
-            if (args)
-            {
-                for (size_t i = 0; i < args->length; i++)
-                {
-                    Expression *e = (*args)[i];
-
-                    sc = sc->startCTFE();
-                    e = ::semantic(e, sc);
-                    e = resolveProperties(sc, e);
-                    sc = sc->endCTFE();
-
-                    e = e->ctfeInterpret();
-                    if (i == 0)
-                        buf.writestring(" (");
-                    else
-                        buf.writeByte(',');
-                    buf.writestring(e->toChars());
-                }
-                if (args->length)
-                    buf.writeByte(')');
-            }
-            message("pragma    %s", buf.peekChars());
-        }
-        goto Lnodecl;
-    }
-    else
-        error("unrecognized pragma(%s)", ident->toChars());
-
-Ldecl:
-    if (decl)
-    {
-        Scope *sc2 = newScope(sc);
-
-        for (size_t i = 0; i < decl->length; i++)
-        {
-            Dsymbol *s = (*decl)[i];
-
-            s->semantic(sc2);
-
-            if (ident == Id::mangle)
-            {
-                assert(args && args->length == 1);
-                if (StringExp *se = (*args)[0]->toStringExp())
-                {
-                    char *name = (char *)mem.xmalloc(se->len + 1);
-                    memcpy(name, se->string, se->len);
-                    name[se->len] = 0;
-
-                    unsigned cnt = setMangleOverride(s, name);
-                    if (cnt > 1)
-                        error("can only apply to a single declaration");
-                }
-            }
-        }
-
-        if (sc2 != sc)
-            sc2->pop();
-    }
-    return;
-
-Lnodecl:
-    if (decl)
-    {
-        error("pragma is missing closing ';'");
-        goto Ldecl; // do them anyway, to avoid segfaults.
-    }
-}
-
 const char *PragmaDeclaration::kind() const
 {
     return "pragma";
@@ -1374,11 +993,6 @@ void StaticIfDeclaration::setScope(Scope *sc)
     Dsymbol::setScope(sc);
 }
 
-void StaticIfDeclaration::semantic(Scope *sc)
-{
-    AttribDeclaration::semantic(sc);
-}
-
 const char *StaticIfDeclaration::kind() const
 {
     return "static if";
@@ -1491,11 +1105,6 @@ void StaticForeachDeclaration::importAll(Scope *)
     // do not evaluate aggregate before semantic pass
 }
 
-void StaticForeachDeclaration::semantic(Scope *sc)
-{
-    AttribDeclaration::semantic(sc);
-}
-
 const char *StaticForeachDeclaration::kind() const
 {
     return "static foreach";
@@ -1582,50 +1191,6 @@ void CompileDeclaration::setScope(Scope *sc)
     Dsymbol::setScope(sc);
 }
 
-void CompileDeclaration::compileIt(Scope *sc)
-{
-    //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
-    StringExp *se = semanticString(sc, exp, "argument to mixin");
-    if (!se)
-        return;
-    se = se->toUTF8(sc);
-
-    unsigned errors = global.errors;
-    Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0);
-    p.nextToken();
-
-    decl = p.parseDeclDefs(0);
-    if (p.token.value != TOKeof)
-        exp->error("incomplete mixin declaration (%s)", se->toChars());
-    if (p.errors)
-    {
-        assert(global.errors != errors);
-        decl = NULL;
-    }
-}
-
-void CompileDeclaration::semantic(Scope *sc)
-{
-    //printf("CompileDeclaration::semantic()\n");
-
-    if (!compiled)
-    {
-        compileIt(sc);
-        AttribDeclaration::addMember(sc, scopesym);
-        compiled = true;
-
-        if (_scope && decl)
-        {
-            for (size_t i = 0; i < decl->length; i++)
-            {
-                Dsymbol *s = (*decl)[i];
-                s->setScope(_scope);
-            }
-        }
-    }
-    AttribDeclaration::semantic(sc);
-}
-
 const char *CompileDeclaration::kind() const
 {
     return "mixin";
@@ -1670,23 +1235,14 @@ void UserAttributeDeclaration::setScope(Scope *sc)
     return AttribDeclaration::setScope(sc);
 }
 
-void UserAttributeDeclaration::semantic(Scope *sc)
-{
-    //printf("UserAttributeDeclaration::semantic() %p\n", this);
-    if (decl && !_scope)
-        Dsymbol::setScope(sc);  // for function local symbols
-
-    return AttribDeclaration::semantic(sc);
-}
-
-static void udaExpressionEval(Scope *sc, Expressions *exps)
+void udaExpressionEval(Scope *sc, Expressions *exps)
 {
     for (size_t i = 0; i < exps->length; i++)
     {
         Expression *e = (*exps)[i];
         if (e)
         {
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             if (definitelyValueParameter(e))
                 e = e->ctfeInterpret();
             if (e->op == TOKtuple)
@@ -1699,17 +1255,6 @@ static void udaExpressionEval(Scope *sc, Expressions *exps)
     }
 }
 
-void UserAttributeDeclaration::semantic2(Scope *sc)
-{
-    if (decl && atts && atts->length && _scope)
-    {
-        _scope = NULL;
-        udaExpressionEval(sc, atts);
-    }
-
-    AttribDeclaration::semantic2(sc);
-}
-
 Expressions *UserAttributeDeclaration::concat(Expressions *udas1, Expressions *udas2)
 {
     Expressions *udas;
index a20e96bc92952366d19b76704f983dd60c8fb9ce..7436417612886f9b805e074a5e6e94d798a8736c 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -37,9 +37,6 @@ public:
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope *sc);
     void importAll(Scope *sc);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
     void addComment(const utf8_t *comment);
     const char *kind() const;
     bool oneMember(Dsymbol **ps, Identifier *ident);
@@ -78,7 +75,6 @@ public:
     Dsymbol *syntaxCopy(Dsymbol *s);
     Scope *newScope(Scope *sc);
     void setScope(Scope *sc);
-    void semantic2(Scope *sc);
     const char *getMessage();
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -134,7 +130,6 @@ public:
     AlignDeclaration(Loc loc, Expression *ealign, Dsymbols *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
     Scope *newScope(Scope *sc);
-    void semantic2(Scope *sc);
     structalign_t getAlignment(Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -151,7 +146,6 @@ public:
     AnonDeclaration(Loc loc, bool isunion, Dsymbols *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
     void setScope(Scope *sc);
-    void semantic(Scope *sc);
     void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
     const char *kind() const;
     AnonDeclaration *isAnonDeclaration() { return this; }
@@ -166,7 +160,6 @@ public:
     PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
     Scope *newScope(Scope *sc);
-    void semantic(Scope *sc);
     const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -199,7 +192,6 @@ public:
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope *sc);
     void importAll(Scope *sc);
-    void semantic(Scope *sc);
     const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -221,7 +213,6 @@ public:
     void addComment(const utf8_t *comment);
     void setScope(Scope *sc);
     void importAll(Scope *sc);
-    void semantic(Scope *sc);
     const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -252,8 +243,6 @@ public:
     Dsymbol *syntaxCopy(Dsymbol *s);
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope *sc);
-    void compileIt(Scope *sc);
-    void semantic(Scope *sc);
     const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -271,8 +260,6 @@ public:
     Dsymbol *syntaxCopy(Dsymbol *s);
     Scope *newScope(Scope *sc);
     void setScope(Scope *sc);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
     static Expressions *concat(Expressions *udas1, Expressions *udas2);
     Expressions *getAttributes();
     const char *kind() const;
index 4705862e025b0f43dbd9cfd7833d71a200e028d2..44e3cc13bd3f4086809aadb68d197c51c9e0add6 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -483,7 +483,7 @@ int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow)
         void visit(CompoundAsmStatement *s)
         {
             if (mustNotThrow && !(s->stc & STCnothrow))
-                s->deprecation("asm statement is assumed to throw - mark it with 'nothrow' if it does not");
+                s->deprecation("asm statement is assumed to throw - mark it with `nothrow` if it does not");
 
             // Assume the worst
             result = BEfallthru | BEreturn | BEgoto | BEhalt;
index 33d61edbcc80cc43c8bf9003f6264be422283c30..5d180f54367a68b977a1292ee7237d3644691e9b 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -77,7 +77,7 @@ bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow)
             {
                 if (ce->f)
                 {
-                    ce->error("%s '%s' is not nothrow",
+                    ce->error("%s `%s` is not nothrow",
                         ce->f->kind(), ce->f->toPrettyChars());
                 }
                 else
@@ -85,7 +85,7 @@ bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow)
                     Expression *e1 = ce->e1;
                     if (e1->op == TOKstar)   // print 'fp' if e1 is (*fp)
                         e1 = ((PtrExp *)e1)->e1;
-                    ce->error("'%s' is not nothrow", e1->toChars());
+                    ce->error("`%s` is not nothrow", e1->toChars());
                 }
             }
             stop = true;
@@ -103,7 +103,7 @@ bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow)
                     {
                         if (mustNotThrow)
                         {
-                            ne->error("%s '%s' is not nothrow",
+                            ne->error("%s `%s` is not nothrow",
                                 ne->allocator->kind(), ne->allocator->toPrettyChars());
                         }
                         stop = true;
@@ -115,7 +115,7 @@ bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow)
                 {
                     if (mustNotThrow)
                     {
-                        ne->error("%s '%s' is not nothrow",
+                        ne->error("%s `%s` is not nothrow",
                             ne->member->kind(), ne->member->toPrettyChars());
                     }
                     stop = true;
@@ -163,7 +163,7 @@ bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow)
                 {
                     if (mustNotThrow)
                     {
-                        de->error("%s '%s' is not nothrow",
+                        de->error("%s `%s` is not nothrow",
                             ad->dtor->kind(), ad->dtor->toPrettyChars());
                     }
                     stop = true;
@@ -176,7 +176,7 @@ bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow)
                 {
                     if (mustNotThrow)
                     {
-                        de->error("%s '%s' is not nothrow",
+                        de->error("%s `%s` is not nothrow",
                             ad->aggDelete->kind(), ad->aggDelete->toPrettyChars());
                     }
                     stop = true;
@@ -217,7 +217,7 @@ bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow)
             {
                 if (mustNotThrow)
                 {
-                    ae->error("%s '%s' is not nothrow",
+                    ae->error("%s `%s` is not nothrow",
                         sd->postblit->kind(), sd->postblit->toPrettyChars());
                 }
                 stop = true;
index 73c4a6603680cd60592ca389fffa5c980841a2dd..eb09076b2d207fc0c7c7560353ad7ba3864536e8 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -23,8 +23,6 @@
 #include "template.h"
 #include "tokens.h"
 
-Expression *semantic(Expression *e, Scope *sc);
-
 /*******************************************
  * Merge function attributes pure, nothrow, @safe, @nogc, and @disable
  */
@@ -326,8 +324,8 @@ FuncDeclaration *buildOpAssign(StructDeclaration *sd, Scope *sc)
     sc2->stc = 0;
     sc2->linkage = LINKd;
 
-    fop->semantic(sc2);
-    fop->semantic2(sc2);
+    dsymbolSemantic(fop, sc2);
+    semantic2(fop, sc2);
     // Bugzilla 15044: fop->semantic3 isn't run here for lazy forward reference resolution.
 
     sc2->pop();
@@ -506,7 +504,7 @@ FuncDeclaration *buildXopEquals(StructDeclaration *sd, Scope *sc)
                 parameters->push(new Parameter(STCref | STCconst, sd->type, NULL, NULL, NULL));
                 tfeqptr = new TypeFunction(ParameterList(parameters), Type::tbool, LINKd);
                 tfeqptr->mod = MODconst;
-                tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &scx);
+                tfeqptr = (TypeFunction *)typeSemantic(tfeqptr, Loc(), &scx);
             }
             fd = fd->overloadExactMatch(tfeqptr);
             if (fd)
@@ -521,7 +519,7 @@ FuncDeclaration *buildXopEquals(StructDeclaration *sd, Scope *sc)
         Expression *e = new IdentifierExp(sd->loc, Id::empty);
         e = new DotIdExp(sd->loc, e, Id::object);
         e = new DotIdExp(sd->loc, e, id);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         Dsymbol *s = getDsymbol(e);
         assert(s);
         sd->xerreq = s->isFuncDeclaration();
@@ -549,8 +547,8 @@ FuncDeclaration *buildXopEquals(StructDeclaration *sd, Scope *sc)
     sc2->stc = 0;
     sc2->linkage = LINKd;
 
-    fop->semantic(sc2);
-    fop->semantic2(sc2);
+    dsymbolSemantic(fop, sc2);
+    semantic2(fop, sc2);
 
     sc2->pop();
     if (global.endGagging(errors))    // if errors happened
@@ -586,7 +584,7 @@ FuncDeclaration *buildXopCmp(StructDeclaration *sd, Scope *sc)
                 parameters->push(new Parameter(STCref | STCconst, sd->type, NULL, NULL, NULL));
                 tfcmpptr = new TypeFunction(ParameterList(parameters), Type::tint32, LINKd);
                 tfcmpptr->mod = MODconst;
-                tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &scx);
+                tfcmpptr = (TypeFunction *)typeSemantic(tfcmpptr, Loc(), &scx);
             }
             fd = fd->overloadExactMatch(tfcmpptr);
             if (fd)
@@ -606,7 +604,7 @@ FuncDeclaration *buildXopCmp(StructDeclaration *sd, Scope *sc)
         Expression *e = new IdentifierExp(sd->loc, Id::empty);
         e = new DotIdExp(sd->loc, e, Id::object);
         e = new DotIdExp(sd->loc, e, id);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         Dsymbol *s = getDsymbol(e);
         assert(s);
         sd->xerrcmp = s->isFuncDeclaration();
@@ -638,8 +636,8 @@ FuncDeclaration *buildXopCmp(StructDeclaration *sd, Scope *sc)
     sc2->stc = 0;
     sc2->linkage = LINKd;
 
-    fop->semantic(sc2);
-    fop->semantic2(sc2);
+    dsymbolSemantic(fop, sc2);
+    semantic2(fop, sc2);
 
     sc2->pop();
     if (global.endGagging(errors))    // if errors happened
@@ -762,8 +760,8 @@ FuncDeclaration *buildXtoHash(StructDeclaration *sd, Scope *sc)
     sc2->stc = 0;
     sc2->linkage = LINKd;
 
-    fop->semantic(sc2);
-    fop->semantic2(sc2);
+    dsymbolSemantic(fop, sc2);
+    semantic2(fop, sc2);
 
     sc2->pop();
 
@@ -927,7 +925,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
         dd->fbody = (stc & STCdisable) ? NULL : new CompoundStatement(loc, a);
         sd->postblits.shift(dd);
         sd->members->push(dd);
-        dd->semantic(sc);
+        dsymbolSemantic(dd, sc);
     }
 
     FuncDeclaration *xpostblit = NULL;
@@ -961,7 +959,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
             dd->storage_class |= STCinference;
             dd->fbody = new ExpStatement(loc, e);
             sd->members->push(dd);
-            dd->semantic(sc);
+            dsymbolSemantic(dd, sc);
             xpostblit = dd;
             break;
     }
@@ -969,7 +967,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
     if (xpostblit)
     {
         AliasDeclaration *alias = new AliasDeclaration(Loc(), Id::__xpostblit, xpostblit);
-        alias->semantic(sc);
+        dsymbolSemantic(alias, sc);
         sd->members->push(alias);
         alias->addMember(sc, sd); // add to symbol table
     }
@@ -1074,7 +1072,7 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc)
         dd->fbody = new ExpStatement(loc, e);
         ad->dtors.shift(dd);
         ad->members->push(dd);
-        dd->semantic(sc);
+        dsymbolSemantic(dd, sc);
     }
 
     FuncDeclaration *xdtor = NULL;
@@ -1109,7 +1107,7 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc)
             dd->storage_class |= STCinference;
             dd->fbody = new ExpStatement(loc, e);
             ad->members->push(dd);
-            dd->semantic(sc);
+            dsymbolSemantic(dd, sc);
             xdtor = dd;
             break;
     }
@@ -1117,7 +1115,7 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc)
     if (xdtor)
     {
         AliasDeclaration *alias = new AliasDeclaration(Loc(), Id::__xdtor, xdtor);
-        alias->semantic(sc);
+        dsymbolSemantic(alias, sc);
         ad->members->push(alias);
         alias->addMember(sc, ad); // add to symbol table
     }
@@ -1175,7 +1173,7 @@ FuncDeclaration *buildInv(AggregateDeclaration *ad, Scope *sc)
             inv = new InvariantDeclaration(declLoc, Loc(), stc | stcx, Id::classInvariant);
             inv->fbody = new ExpStatement(loc, e);
             ad->members->push(inv);
-            inv->semantic(sc);
+            dsymbolSemantic(inv, sc);
             return inv;
     }
 }
index 7f9006ce851209b26c67a0c8845d942707eae7ee..e7ef5a4ccf753f0bd6a886403ea918226ffa6ba1 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index c36c4ec53cf654e52349ba133e1a7bccea2f97bd..7f1746064226a6eae04c1b9d58b67228b7256119 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 2ea3d408155e0a323c9ff89e22515b9f633ddd29..6f112ad909c073fb919f6af8d4997b4826c1851e 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -26,7 +26,6 @@
 #include "arraytypes.h"
 #include "tokens.h"
 
-Expression *semantic(Expression *e, Scope *sc);
 bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors);
 
 int findCondition(Identifiers *ids, Identifier *ident)
@@ -86,7 +85,7 @@ static void lowerArrayAggregate(StaticForeach *sfe, Scope *sc)
     Expression *aggr = sfe->aggrfe->aggr;
     Expression *el = new ArrayLengthExp(aggr->loc, aggr);
     sc = sc->startCTFE();
-    el = semantic(el, sc);
+    el = expressionSemantic(el, sc);
     sc = sc->endCTFE();
     el = el->optimize(WANTvalue);
     el = el->ctfeInterpret();
@@ -111,7 +110,7 @@ static void lowerArrayAggregate(StaticForeach *sfe, Scope *sc)
             }
         }
         sfe->aggrfe->aggr = new TupleExp(aggr->loc, es);
-        sfe->aggrfe->aggr = semantic(sfe->aggrfe->aggr, sc);
+        sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc);
         sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue);
     }
     else
@@ -292,9 +291,9 @@ static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc)
     if (sfe->rangefe)
     {
         sc = sc->startCTFE();
-        sfe->rangefe->lwr = semantic(sfe->rangefe->lwr, sc);
+        sfe->rangefe->lwr = expressionSemantic(sfe->rangefe->lwr, sc);
         sfe->rangefe->lwr = resolveProperties(sc, sfe->rangefe->lwr);
-        sfe->rangefe->upr = semantic(sfe->rangefe->upr, sc);
+        sfe->rangefe->upr = expressionSemantic(sfe->rangefe->upr, sc);
         sfe->rangefe->upr = resolveProperties(sc, sfe->rangefe->upr);
         sc = sc->endCTFE();
         sfe->rangefe->lwr = sfe->rangefe->lwr->optimize(WANTvalue);
@@ -321,7 +320,7 @@ static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc)
     Expression *aggr;
     Type *indexty;
 
-    if (sfe->rangefe && (indexty = ety->semantic(aloc, sc))->isintegral())
+    if (sfe->rangefe && (indexty = typeSemantic(ety, aloc, sc))->isintegral())
     {
         sfe->rangefe->lwr->type = indexty;
         sfe->rangefe->upr->type = indexty;
@@ -355,7 +354,7 @@ static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc)
     {
         aggr = wrapAndCall(aloc, new CompoundStatement(aloc, s2));
         sc = sc->startCTFE();
-        aggr = semantic(aggr, sc);
+        aggr = expressionSemantic(aggr, sc);
         aggr = resolveProperties(sc, aggr);
         sc = sc->endCTFE();
         aggr = aggr->optimize(WANTvalue);
@@ -382,7 +381,7 @@ void staticForeachPrepare(StaticForeach *sfe, Scope *sc)
     if (sfe->aggrfe)
     {
         sc = sc->startCTFE();
-        sfe->aggrfe->aggr = semantic(sfe->aggrfe->aggr, sc);
+        sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc);
         sc = sc->endCTFE();
         sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue);
         Type *tab = sfe->aggrfe->aggr->type->toBasetype();
@@ -624,7 +623,7 @@ static bool isReserved(const char *ident)
 void checkReserved(Loc loc, const char *ident)
 {
     if (isReserved(ident))
-        error(loc, "version identifier '%s' is reserved and cannot be set", ident);
+        error(loc, "version identifier `%s` is reserved and cannot be set", ident);
 }
 
 void VersionCondition::addGlobalIdent(const char *ident)
index 17398c1ef78b20e330e93a39addebb5323ee6e8b..593a98d10b40e6dea4cd551a676b1f090313c012 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 38e6191698d738543c6072179249766d39ec3617..8cfeac54e20ae5e745c83306d55e467b0e806ce5 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 3f571fcb14b7d915aa4e6c12de7ed78be89abb9b..a0e0b5fb993278d105df94bcbb0df462268f8319 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 1eab264f5cec218bbe8df129fe2fe91db6f514a5..359739e24a07890e0a2e8b865e63cd5a57c1e001 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index ee38033ac82e42d5d78700d3d4a0c1252cf8ac34..1d669e595e5ed9042e8b94e74fda0fe5c3af81e2 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 1fc9d936bbda23e4ad15180be9ebe7bafb95bfaf..61e28fe8d134121225def34c2506f37d802450a7 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -26,7 +26,6 @@
 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
 bool isCommutative(TOK op);
 MOD MODmerge(MOD mod1, MOD mod2);
-Expression *semantic(Expression *e, Scope *sc);
 
 /* ==================== implicitCast ====================== */
 
@@ -1431,7 +1430,7 @@ Expression *castTo(Expression *e, Scope *sc, Type *t)
                 TypeVector *tv = (TypeVector *)tob;
                 result = new CastExp(e->loc, e, tv->elementType());
                 result = new VectorExp(e->loc, result, tob);
-                result = ::semantic(result, sc);
+                result = expressionSemantic(result, sc);
                 return;
             }
             else if (tob->ty != Tvector && t1b->ty == Tvector)
@@ -1924,7 +1923,7 @@ Expression *castTo(Expression *e, Scope *sc, Type *t)
                     {
                         f->tookAddressOf++;
                         SymOffExp *se = new SymOffExp(e->loc, f, 0, false);
-                        ::semantic(se, sc);
+                        expressionSemantic(se, sc);
                         // Let SymOffExp::castTo() do the heavy lifting
                         visit(se);
                         return;
@@ -2083,7 +2082,7 @@ Expression *castTo(Expression *e, Scope *sc, Type *t)
                     (*ae->elements)[i] = ex;
                 }
                 Expression *ev = new VectorExp(e->loc, ae, tb);
-                ev = ::semantic(ev, sc);
+                ev = expressionSemantic(ev, sc);
                 result = ev;
                 return;
             }
@@ -2156,16 +2155,16 @@ Expression *castTo(Expression *e, Scope *sc, Type *t)
                         if (f->needThis() && hasThis(sc))
                         {
                             result = new DelegateExp(e->loc, new ThisExp(e->loc), f, false);
-                            result = ::semantic(result, sc);
+                            result = expressionSemantic(result, sc);
                         }
                         else if (f->isNested())
                         {
                             result = new DelegateExp(e->loc, new IntegerExp(0), f, false);
-                            result = ::semantic(result, sc);
+                            result = expressionSemantic(result, sc);
                         }
                         else if (f->needThis())
                         {
-                            e->error("no 'this' to create delegate for %s", f->toChars());
+                            e->error("no `this` to create delegate for %s", f->toChars());
                             result = new ErrorExp();
                             return;
                         }
@@ -2746,7 +2745,7 @@ Lagain:
             else
                 tx = d->pointerTo();
 
-            tx = tx->semantic(e1->loc, sc);
+            tx = typeSemantic(tx, e1->loc, sc);
 
             if (t1->implicitConvTo(tx) && t2->implicitConvTo(tx))
             {
index 7481f910e1108461765d524a22d710558cce3329..c7dbbbea5d38ea757cb0641f62f6ce8a8897e300 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -290,599 +290,6 @@ Scope *ClassDeclaration::newScope(Scope *sc)
     return sc2;
 }
 
-/* Bugzilla 12078, 12143 and 15733:
- * While resolving base classes and interfaces, a base may refer
- * the member of this derived class. In that time, if all bases of
- * this class can  be determined, we can go forward the semantc process
- * beyond the Lancestorsdone. To do the recursive semantic analysis,
- * temporarily set and unset `_scope` around exp().
- */
-static Type *resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, Type *type)
-{
-    if (!scx)
-    {
-        scx = sc->copy();
-        scx->setNoFree();
-    }
-    cd->_scope = scx;
-    Type *t = type->semantic(cd->loc, sc);
-    cd->_scope = NULL;
-    return t;
-}
-
-static void resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, ClassDeclaration *sym)
-{
-    if (!scx)
-    {
-        scx = sc->copy();
-        scx->setNoFree();
-    }
-    cd->_scope = scx;
-    sym->semantic(NULL);
-    cd->_scope = NULL;
-}
-
-static void badObjectDotD(ClassDeclaration *cd)
-{
-    cd->error("missing or corrupt object.d");
-    fatal();
-}
-
-void ClassDeclaration::semantic(Scope *sc)
-{
-    //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
-    //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
-    //printf("sc->stc = %x\n", sc->stc);
-
-    //{ static int n;  if (++n == 20) *(char*)0=0; }
-
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    unsigned errors = global.errors;
-
-    //printf("+ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
-
-    Scope *scx = NULL;
-    if (_scope)
-    {
-        sc = _scope;
-        scx = _scope;            // save so we don't make redundant copies
-        _scope = NULL;
-    }
-
-    if (!parent)
-    {
-        assert(sc->parent);
-        parent = sc->parent;
-    }
-
-    if (this->errors)
-        type = Type::terror;
-    type = type->semantic(loc, sc);
-
-    if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
-    {
-        TemplateInstance *ti = ((TypeClass *)type)->sym->isInstantiated();
-        if (ti && isError(ti))
-            ((TypeClass *)type)->sym = this;
-    }
-
-    // Ungag errors when not speculative
-    Ungag ungag = ungagSpeculative();
-
-    if (semanticRun == PASSinit)
-    {
-        protection = sc->protection;
-
-        storage_class |= sc->stc;
-        if (storage_class & STCdeprecated)
-            isdeprecated = true;
-        if (storage_class & STCauto)
-            error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
-        if (storage_class & STCscope)
-            isscope = true;
-        if (storage_class & STCabstract)
-            isabstract = ABSyes;
-
-        userAttribDecl = sc->userAttribDecl;
-
-        if (sc->linkage == LINKcpp)
-            classKind = ClassKind::cpp;
-        if (sc->linkage == LINKobjc)
-            objc()->setObjc(this);
-    }
-    else if (symtab && !scx)
-    {
-        return;
-    }
-    semanticRun = PASSsemantic;
-
-    if (baseok < BASEOKdone)
-    {
-        baseok = BASEOKin;
-
-        // Expand any tuples in baseclasses[]
-        for (size_t i = 0; i < baseclasses->length; )
-        {
-            BaseClass *b = (*baseclasses)[i];
-            b->type = resolveBase(this, sc, scx, b->type);
-
-            Type *tb = b->type->toBasetype();
-            if (tb->ty == Ttuple)
-            {
-                TypeTuple *tup = (TypeTuple *)tb;
-                baseclasses->remove(i);
-                size_t dim = Parameter::dim(tup->arguments);
-                for (size_t j = 0; j < dim; j++)
-                {
-                    Parameter *arg = Parameter::getNth(tup->arguments, j);
-                    b = new BaseClass(arg->type);
-                    baseclasses->insert(i + j, b);
-                }
-            }
-            else
-                i++;
-        }
-
-        if (baseok >= BASEOKdone)
-        {
-            //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
-            if (semanticRun >= PASSsemanticdone)
-                return;
-            goto Lancestorsdone;
-        }
-
-        // See if there's a base class as first in baseclasses[]
-        if (baseclasses->length)
-        {
-            BaseClass *b = (*baseclasses)[0];
-            Type *tb = b->type->toBasetype();
-            TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
-            if (!tc)
-            {
-                if (b->type != Type::terror)
-                    error("base type must be class or interface, not %s", b->type->toChars());
-                baseclasses->remove(0);
-                goto L7;
-            }
-
-            if (tc->sym->isDeprecated())
-            {
-                if (!isDeprecated())
-                {
-                    // Deriving from deprecated class makes this one deprecated too
-                    isdeprecated = true;
-
-                    tc->checkDeprecated(loc, sc);
-                }
-            }
-
-            if (tc->sym->isInterfaceDeclaration())
-                goto L7;
-
-            for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
-            {
-                if (cdb == this)
-                {
-                    error("circular inheritance");
-                    baseclasses->remove(0);
-                    goto L7;
-                }
-            }
-
-            /* Bugzilla 11034: Essentially, class inheritance hierarchy
-             * and instance size of each classes are orthogonal information.
-             * Therefore, even if tc->sym->sizeof == SIZEOKnone,
-             * we need to set baseClass field for class covariance check.
-             */
-            baseClass = tc->sym;
-            b->sym = baseClass;
-
-            if (tc->sym->baseok < BASEOKdone)
-                resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
-            if (tc->sym->baseok < BASEOKdone)
-            {
-                //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
-                if (tc->sym->_scope)
-                    tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
-                baseok = BASEOKnone;
-            }
-         L7: ;
-        }
-
-        // Treat the remaining entries in baseclasses as interfaces
-        // Check for errors, handle forward references
-        for (size_t i = (baseClass ? 1 : 0); i < baseclasses->length; )
-        {
-            BaseClass *b = (*baseclasses)[i];
-            Type *tb = b->type->toBasetype();
-            TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
-            if (!tc || !tc->sym->isInterfaceDeclaration())
-            {
-                if (b->type != Type::terror)
-                    error("base type must be interface, not %s", b->type->toChars());
-                baseclasses->remove(i);
-                continue;
-            }
-
-            // Check for duplicate interfaces
-            for (size_t j = (baseClass ? 1 : 0); j < i; j++)
-            {
-                BaseClass *b2 = (*baseclasses)[j];
-                if (b2->sym == tc->sym)
-                {
-                    error("inherits from duplicate interface %s", b2->sym->toChars());
-                    baseclasses->remove(i);
-                    continue;
-                }
-            }
-
-            if (tc->sym->isDeprecated())
-            {
-                if (!isDeprecated())
-                {
-                    // Deriving from deprecated class makes this one deprecated too
-                    isdeprecated = true;
-
-                    tc->checkDeprecated(loc, sc);
-                }
-            }
-
-            b->sym = tc->sym;
-
-            if (tc->sym->baseok < BASEOKdone)
-                resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
-            if (tc->sym->baseok < BASEOKdone)
-            {
-                //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
-                if (tc->sym->_scope)
-                    tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
-                baseok = BASEOKnone;
-            }
-            i++;
-        }
-        if (baseok == BASEOKnone)
-        {
-            // Forward referencee of one or more bases, try again later
-            _scope = scx ? scx : sc->copy();
-            _scope->setNoFree();
-            _scope->_module->addDeferredSemantic(this);
-            //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
-            return;
-        }
-        baseok = BASEOKdone;
-
-        // If no base class, and this is not an Object, use Object as base class
-        if (!baseClass && ident != Id::Object && !isCPPclass())
-        {
-            if (!object || object->errors)
-                badObjectDotD(this);
-
-            Type *t = object->type;
-            t = t->semantic(loc, sc)->toBasetype();
-            if (t->ty == Terror)
-                badObjectDotD(this);
-            assert(t->ty == Tclass);
-            TypeClass *tc = (TypeClass *)t;
-
-            BaseClass *b = new BaseClass(tc);
-            baseclasses->shift(b);
-
-            baseClass = tc->sym;
-            assert(!baseClass->isInterfaceDeclaration());
-            b->sym = baseClass;
-        }
-        if (baseClass)
-        {
-            if (baseClass->storage_class & STCfinal)
-                error("cannot inherit from final class %s", baseClass->toChars());
-
-            // Inherit properties from base class
-            if (baseClass->isCOMclass())
-                com = true;
-            if (baseClass->isCPPclass())
-                classKind = ClassKind::cpp;
-            if (baseClass->isscope)
-                isscope = true;
-            enclosing = baseClass->enclosing;
-            storage_class |= baseClass->storage_class & STC_TYPECTOR;
-        }
-
-        interfaces.length = baseclasses->length - (baseClass ? 1 : 0);
-        interfaces.ptr = baseclasses->tdata() + (baseClass ? 1 : 0);
-
-        for (size_t i = 0; i < interfaces.length; i++)
-        {
-            BaseClass *b = interfaces.ptr[i];
-            // If this is an interface, and it derives from a COM interface,
-            // then this is a COM interface too.
-            if (b->sym->isCOMinterface())
-                com = true;
-            if (isCPPclass() && !b->sym->isCPPinterface())
-            {
-                ::error(loc, "C++ class '%s' cannot implement D interface '%s'",
-                    toPrettyChars(), b->sym->toPrettyChars());
-            }
-        }
-
-        interfaceSemantic(sc);
-    }
-Lancestorsdone:
-    //printf("\tClassDeclaration::semantic(%s) baseok = %d\n", toChars(), baseok);
-
-    if (!members)               // if opaque declaration
-    {
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-    if (!symtab)
-    {
-        symtab = new DsymbolTable();
-
-        /* Bugzilla 12152: The semantic analysis of base classes should be finished
-         * before the members semantic analysis of this class, in order to determine
-         * vtbl in this class. However if a base class refers the member of this class,
-         * it can be resolved as a normal forward reference.
-         * Call addMember() and setScope() to make this class members visible from the base classes.
-         */
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->addMember(sc, this);
-        }
-
-        Scope *sc2 = newScope(sc);
-
-        /* Set scope so if there are forward references, we still might be able to
-         * resolve individual members like enums.
-         */
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            //printf("[%d] setScope %s %s, sc2 = %p\n", i, s->kind(), s->toChars(), sc2);
-            s->setScope(sc2);
-        }
-
-        sc2->pop();
-    }
-
-    for (size_t i = 0; i < baseclasses->length; i++)
-    {
-        BaseClass *b = (*baseclasses)[i];
-        Type *tb = b->type->toBasetype();
-        assert(tb->ty == Tclass);
-        TypeClass *tc = (TypeClass *)tb;
-
-        if (tc->sym->semanticRun < PASSsemanticdone)
-        {
-            // Forward referencee of one or more bases, try again later
-            _scope = scx ? scx : sc->copy();
-            _scope->setNoFree();
-            if (tc->sym->_scope)
-                tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
-            _scope->_module->addDeferredSemantic(this);
-            //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
-            return;
-        }
-    }
-
-    if (baseok == BASEOKdone)
-    {
-        baseok = BASEOKsemanticdone;
-
-        // initialize vtbl
-        if (baseClass)
-        {
-            if (isCPPclass() && baseClass->vtbl.length == 0)
-            {
-                error("C++ base class %s needs at least one virtual function", baseClass->toChars());
-            }
-
-            // Copy vtbl[] from base class
-            vtbl.setDim(baseClass->vtbl.length);
-            memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.length);
-
-            vthis = baseClass->vthis;
-        }
-        else
-        {
-            // No base class, so this is the root of the class hierarchy
-            vtbl.setDim(0);
-            if (vtblOffset())
-                vtbl.push(this);            // leave room for classinfo as first member
-        }
-
-        /* If this is a nested class, add the hidden 'this'
-         * member which is a pointer to the enclosing scope.
-         */
-        if (vthis)              // if inheriting from nested class
-        {
-            // Use the base class's 'this' member
-            if (storage_class & STCstatic)
-                error("static class cannot inherit from nested class %s", baseClass->toChars());
-            if (toParent2() != baseClass->toParent2() &&
-                (!toParent2() ||
-                 !baseClass->toParent2()->getType() ||
-                 !baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
-            {
-                if (toParent2())
-                {
-                    error("is nested within %s, but super class %s is nested within %s",
-                        toParent2()->toChars(),
-                        baseClass->toChars(),
-                        baseClass->toParent2()->toChars());
-                }
-                else
-                {
-                    error("is not nested, but super class %s is nested within %s",
-                        baseClass->toChars(),
-                        baseClass->toParent2()->toChars());
-                }
-                enclosing = NULL;
-            }
-        }
-        else
-            makeNested();
-    }
-
-    Scope *sc2 = newScope(sc);
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->importAll(sc2);
-    }
-
-    // Note that members.length can grow due to tuple expansion during semantic()
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->semantic(sc2);
-    }
-
-    if (!determineFields())
-    {
-        assert(type == Type::terror);
-        sc2->pop();
-        return;
-    }
-
-    /* Following special member functions creation needs semantic analysis
-     * completion of sub-structs in each field types.
-     */
-    for (size_t i = 0; i < fields.length; i++)
-    {
-        VarDeclaration *v = fields[i];
-        Type *tb = v->type->baseElemOf();
-        if (tb->ty != Tstruct)
-            continue;
-        StructDeclaration *sd = ((TypeStruct *)tb)->sym;
-        if (sd->semanticRun >= PASSsemanticdone)
-            continue;
-
-        sc2->pop();
-
-        _scope = scx ? scx : sc->copy();
-        _scope->setNoFree();
-        _scope->_module->addDeferredSemantic(this);
-        //printf("\tdeferring %s\n", toChars());
-        return;
-    }
-
-    /* Look for special member functions.
-     * They must be in this class, not in a base class.
-     */
-
-    // Can be in base class
-    aggNew    =    (NewDeclaration *)search(Loc(), Id::classNew);
-    aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete);
-
-    // Look for the constructor
-    ctor = searchCtor();
-
-    if (!ctor && noDefaultCtor)
-    {
-        // A class object is always created by constructor, so this check is legitimate.
-        for (size_t i = 0; i < fields.length; i++)
-        {
-            VarDeclaration *v = fields[i];
-            if (v->storage_class & STCnodefaultctor)
-                ::error(v->loc, "field %s must be initialized in constructor", v->toChars());
-        }
-    }
-
-    // If this class has no constructor, but base class has a default
-    // ctor, create a constructor:
-    //    this() { }
-    if (!ctor && baseClass && baseClass->ctor)
-    {
-        FuncDeclaration *fd = resolveFuncCall(loc, sc2, baseClass->ctor, NULL, type, NULL, 1);
-        if (!fd) // try shared base ctor instead
-            fd = resolveFuncCall(loc, sc2, baseClass->ctor, NULL, type->sharedOf(), NULL, 1);
-        if (fd && !fd->errors)
-        {
-            //printf("Creating default this(){} for class %s\n", toChars());
-            TypeFunction *btf = fd->type->toTypeFunction();
-            TypeFunction *tf = new TypeFunction(ParameterList(), NULL, LINKd, fd->storage_class);
-            tf->mod = btf->mod;
-            tf->purity = btf->purity;
-            tf->isnothrow = btf->isnothrow;
-            tf->isnogc = btf->isnogc;
-            tf->trust = btf->trust;
-
-            CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf);
-            ctor->fbody = new CompoundStatement(Loc(), new Statements());
-
-            members->push(ctor);
-            ctor->addMember(sc, this);
-            ctor->semantic(sc2);
-
-            this->ctor = ctor;
-            defaultCtor = ctor;
-        }
-        else
-        {
-            error("cannot implicitly generate a default ctor when base class %s is missing a default ctor",
-                baseClass->toPrettyChars());
-        }
-    }
-
-    dtor = buildDtor(this, sc2);
-
-    if (FuncDeclaration *f = hasIdentityOpAssign(this, sc2))
-    {
-        if (!(f->storage_class & STCdisable))
-            error(f->loc, "identity assignment operator overload is illegal");
-    }
-
-    inv = buildInv(this, sc2);
-
-    Module::dprogress++;
-    semanticRun = PASSsemanticdone;
-    //printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type);
-    //members.print();
-
-    sc2->pop();
-
-    if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
-    {
-        // https://issues.dlang.org/show_bug.cgi?id=17492
-        ClassDeclaration *cd = ((TypeClass *)type)->sym;
-        error("already exists at %s. Perhaps in another function with the same name?", cd->loc.toChars());
-    }
-
-    if (global.errors != errors)
-    {
-        // The type is no good.
-        type = Type::terror;
-        this->errors = true;
-        if (deferred)
-            deferred->errors = true;
-    }
-
-    // Verify fields of a synchronized class are not public
-    if (storage_class & STCsynchronized)
-    {
-        for (size_t i = 0; i < fields.length; i++)
-        {
-            VarDeclaration *vd = fields[i];
-            if (!vd->isThisDeclaration() &&
-                !vd->prot().isMoreRestrictiveThan(Prot(Prot::public_)))
-            {
-                vd->error("Field members of a synchronized class cannot be %s",
-                    protectionToChars(vd->prot().kind));
-            }
-        }
-    }
-
-    if (deferred && !global.gag)
-    {
-        deferred->semantic2(sc);
-        deferred->semantic3(sc);
-    }
-    //printf("-ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
-}
-
 /*********************************************
  * Determine if 'this' is a base class of cd.
  * This is used to detect circular inheritance only.
@@ -917,7 +324,7 @@ bool ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
          */
         if (!cd->baseClass && cd->semanticRun < PASSsemanticdone && !cd->isInterfaceDeclaration())
         {
-            cd->semantic(NULL);
+            dsymbolSemantic(cd, NULL);
             if (!cd->baseClass && cd->semanticRun < PASSsemanticdone)
                 cd->error("base class is forward referenced by %s", toChars());
         }
@@ -951,14 +358,14 @@ Dsymbol *ClassDeclaration::search(const Loc &loc, Identifier *ident, int flags)
         {
             // must semantic on base class/interfaces
             ++inuse;
-            semantic(NULL);
+            dsymbolSemantic(this, NULL);
             --inuse;
         }
     }
 
     if (!members || !symtab)    // opaque or addMember is not yet done
     {
-        error("is forward referenced when looking for '%s'", ident->toChars());
+        error("is forward referenced when looking for `%s`", ident->toChars());
         //*(char*)0=0;
         return NULL;
     }
@@ -1277,19 +684,6 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
     return fdmatch;
 }
 
-void ClassDeclaration::interfaceSemantic(Scope *)
-{
-    vtblInterfaces = new BaseClasses();
-    vtblInterfaces->reserve(interfaces.length);
-
-    for (size_t i = 0; i < interfaces.length; i++)
-    {
-        BaseClass *b = interfaces.ptr[i];
-        vtblInterfaces->push(b);
-        b->copyBaseInterfaces(vtblInterfaces);
-    }
-}
-
 /****************************************
  */
 
@@ -1336,7 +730,7 @@ bool ClassDeclaration::isAbstract()
                 return 0;
 
             if (fd->_scope)
-                fd->semantic(NULL);
+                dsymbolSemantic(fd, NULL);
 
             if (fd->isAbstract())
                 return 1;
@@ -1435,303 +829,6 @@ Scope *InterfaceDeclaration::newScope(Scope *sc)
     return sc2;
 }
 
-void InterfaceDeclaration::semantic(Scope *sc)
-{
-    //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    unsigned errors = global.errors;
-
-    //printf("+InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
-
-    Scope *scx = NULL;
-    if (_scope)
-    {
-        sc = _scope;
-        scx = _scope;            // save so we don't make redundant copies
-        _scope = NULL;
-    }
-
-    if (!parent)
-    {
-        assert(sc->parent && sc->func);
-        parent = sc->parent;
-    }
-    assert(parent && !isAnonymous());
-
-    if (this->errors)
-        type = Type::terror;
-    type = type->semantic(loc, sc);
-
-    if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
-    {
-        TemplateInstance *ti = ((TypeClass *)type)->sym->isInstantiated();
-        if (ti && isError(ti))
-            ((TypeClass *)type)->sym = this;
-    }
-
-    // Ungag errors when not speculative
-    Ungag ungag = ungagSpeculative();
-
-    if (semanticRun == PASSinit)
-    {
-        protection = sc->protection;
-
-        storage_class |= sc->stc;
-        if (storage_class & STCdeprecated)
-            isdeprecated = true;
-
-        userAttribDecl = sc->userAttribDecl;
-    }
-    else if (symtab)
-    {
-        if (sizeok == SIZEOKdone || !scx)
-        {
-            semanticRun = PASSsemanticdone;
-            return;
-        }
-    }
-    semanticRun = PASSsemantic;
-
-    if (baseok < BASEOKdone)
-    {
-        baseok = BASEOKin;
-
-        // Expand any tuples in baseclasses[]
-        for (size_t i = 0; i < baseclasses->length; )
-        {
-            BaseClass *b = (*baseclasses)[i];
-            b->type = resolveBase(this, sc, scx, b->type);
-
-            Type *tb = b->type->toBasetype();
-            if (tb->ty == Ttuple)
-            {
-                TypeTuple *tup = (TypeTuple *)tb;
-                baseclasses->remove(i);
-                size_t dim = Parameter::dim(tup->arguments);
-                for (size_t j = 0; j < dim; j++)
-                {
-                    Parameter *arg = Parameter::getNth(tup->arguments, j);
-                    b = new BaseClass(arg->type);
-                    baseclasses->insert(i + j, b);
-                }
-            }
-            else
-                i++;
-        }
-
-        if (baseok >= BASEOKdone)
-        {
-            //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
-            if (semanticRun >= PASSsemanticdone)
-                return;
-            goto Lancestorsdone;
-        }
-
-        if (!baseclasses->length && sc->linkage == LINKcpp)
-            classKind = ClassKind::cpp;
-        if (sc->linkage == LINKobjc)
-            objc()->setObjc(this);
-
-        // Check for errors, handle forward references
-        for (size_t i = 0; i < baseclasses->length; )
-        {
-            BaseClass *b = (*baseclasses)[i];
-            Type *tb = b->type->toBasetype();
-            TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
-            if (!tc || !tc->sym->isInterfaceDeclaration())
-            {
-                if (b->type != Type::terror)
-                    error("base type must be interface, not %s", b->type->toChars());
-                baseclasses->remove(i);
-                continue;
-            }
-
-            // Check for duplicate interfaces
-            for (size_t j = 0; j < i; j++)
-            {
-                BaseClass *b2 = (*baseclasses)[j];
-                if (b2->sym == tc->sym)
-                {
-                    error("inherits from duplicate interface %s", b2->sym->toChars());
-                    baseclasses->remove(i);
-                    continue;
-                }
-            }
-
-            if (tc->sym == this || isBaseOf2(tc->sym))
-            {
-                error("circular inheritance of interface");
-                baseclasses->remove(i);
-                continue;
-            }
-
-            if (tc->sym->isDeprecated())
-            {
-                if (!isDeprecated())
-                {
-                    // Deriving from deprecated class makes this one deprecated too
-                    isdeprecated = true;
-
-                    tc->checkDeprecated(loc, sc);
-                }
-            }
-
-            b->sym = tc->sym;
-
-            if (tc->sym->baseok < BASEOKdone)
-                resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
-            if (tc->sym->baseok < BASEOKdone)
-            {
-                //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
-                if (tc->sym->_scope)
-                    tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
-                baseok = BASEOKnone;
-            }
-            i++;
-        }
-        if (baseok == BASEOKnone)
-        {
-            // Forward referencee of one or more bases, try again later
-            _scope = scx ? scx : sc->copy();
-            _scope->setNoFree();
-            _scope->_module->addDeferredSemantic(this);
-            return;
-        }
-        baseok = BASEOKdone;
-
-        interfaces.length = baseclasses->length;
-        interfaces.ptr = baseclasses->tdata();
-
-        for (size_t i = 0; i < interfaces.length; i++)
-        {
-            BaseClass *b = interfaces.ptr[i];
-            // If this is an interface, and it derives from a COM interface,
-            // then this is a COM interface too.
-            if (b->sym->isCOMinterface())
-                com = true;
-            if (b->sym->isCPPinterface())
-                classKind = ClassKind::cpp;
-        }
-
-        interfaceSemantic(sc);
-    }
-Lancestorsdone:
-
-    if (!members)               // if opaque declaration
-    {
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-    if (!symtab)
-        symtab = new DsymbolTable();
-
-    for (size_t i = 0; i < baseclasses->length; i++)
-    {
-        BaseClass *b = (*baseclasses)[i];
-        Type *tb = b->type->toBasetype();
-        assert(tb->ty == Tclass);
-        TypeClass *tc = (TypeClass *)tb;
-
-        if (tc->sym->semanticRun < PASSsemanticdone)
-        {
-            // Forward referencee of one or more bases, try again later
-            _scope = scx ? scx : sc->copy();
-            _scope->setNoFree();
-            if (tc->sym->_scope)
-                tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
-            _scope->_module->addDeferredSemantic(this);
-            return;
-        }
-    }
-
-    if (baseok == BASEOKdone)
-    {
-        baseok = BASEOKsemanticdone;
-
-        // initialize vtbl
-        if (vtblOffset())
-            vtbl.push(this);                // leave room at vtbl[0] for classinfo
-
-        // Cat together the vtbl[]'s from base interfaces
-        for (size_t i = 0; i < interfaces.length; i++)
-        {
-            BaseClass *b = interfaces.ptr[i];
-
-            // Skip if b has already appeared
-            for (size_t k = 0; k < i; k++)
-            {
-                if (b == interfaces.ptr[k])
-                    goto Lcontinue;
-            }
-
-            // Copy vtbl[] from base class
-            if (b->sym->vtblOffset())
-            {
-                size_t d = b->sym->vtbl.length;
-                if (d > 1)
-                {
-                    vtbl.reserve(d - 1);
-                    for (size_t j = 1; j < d; j++)
-                        vtbl.push(b->sym->vtbl[j]);
-                }
-            }
-            else
-            {
-                vtbl.append(&b->sym->vtbl);
-            }
-
-          Lcontinue:
-            ;
-        }
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->addMember(sc, this);
-    }
-
-    Scope *sc2 = newScope(sc);
-
-    /* Set scope so if there are forward references, we still might be able to
-     * resolve individual members like enums.
-     */
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        //printf("setScope %s %s\n", s->kind(), s->toChars());
-        s->setScope(sc2);
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->importAll(sc2);
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->semantic(sc2);
-    }
-
-    Module::dprogress++;
-    semanticRun = PASSsemanticdone;
-    //printf("-InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
-    //members->print();
-
-    sc2->pop();
-
-    if (global.errors != errors)
-    {
-        // The type is no good.
-        type = Type::terror;
-    }
-
-    assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
-}
-
 /*******************************************
  * Determine if 'this' is a base class of cd.
  * (Actually, if it is an interface supported by cd)
@@ -1901,7 +998,7 @@ bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newin
             //printf("newinstance = %d fd->toParent() = %s ifd->toParent() = %s\n",
                 //newinstance, fd->toParent()->toChars(), ifd->toParent()->toChars());
             if (newinstance && fd->toParent() != cd && ifd->toParent() == sym)
-                cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
+                cd->error("interface function `%s` is not implemented", ifd->toFullSignature());
 
             if (fd->toParent() == cd)
                 result = true;
@@ -1911,7 +1008,7 @@ bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newin
             //printf("            not found %p\n", fd);
             // BUG: should mark this class as abstract?
             if (!cd->isAbstract())
-                cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
+                cd->error("interface function `%s` is not implemented", ifd->toFullSignature());
 
             fd = NULL;
         }
index d20f6636445f7a2954704941b08704d9365807ac..a9394dcce7fb6bb9efdf7f3deee68c77dee445ed 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
 #include "hdrgen.h"
 
 bool checkNestedRef(Dsymbol *s, Dsymbol *p);
-VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
-Expression *semantic(Expression *e, Scope *sc);
-Initializer *inferType(Initializer *init, Scope *sc);
-Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
 
 /************************************
  * Check to see the aggregate type is nested and its context pointer is
@@ -81,10 +77,6 @@ Declaration::Declaration(Identifier *id)
     mangleOverride = NULL;
 }
 
-void Declaration::semantic(Scope *)
-{
-}
-
 const char *Declaration::kind() const
 {
     return "declaration";
@@ -139,7 +131,7 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *, Expression *e1, int fla
             if (scx->func == parent && (scx->flags & SCOPEcontract))
             {
                 const char *s = isParameter() && parent->ident != Id::ensure ? "parameter" : "result";
-                if (!flag) error(loc, "cannot modify %s '%s' in contract", s, toChars());
+                if (!flag) error(loc, "cannot modify %s `%s` in contract", s, toChars());
                 return 2;   // do not report type related errors
             }
         }
@@ -291,7 +283,7 @@ Type *TupleDeclaration::getType()
 
         tupletype = new TypeTuple(args);
         if (hasdeco)
-            return tupletype->semantic(Loc(), NULL);
+            return typeSemantic(tupletype, Loc(), NULL);
     }
 
     return tupletype;
@@ -380,173 +372,6 @@ Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
     return sa;
 }
 
-void AliasDeclaration::semantic(Scope *sc)
-{
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    assert(semanticRun <= PASSsemantic);
-
-    storage_class |= sc->stc & STCdeprecated;
-    protection = sc->protection;
-    userAttribDecl = sc->userAttribDecl;
-
-    if (!sc->func && inNonRoot())
-        return;
-
-    aliasSemantic(sc);
-}
-
-void AliasDeclaration::aliasSemantic(Scope *sc)
-{
-    //printf("AliasDeclaration::semantic() %s\n", toChars());
-
-    // as AliasDeclaration::semantic, in case we're called first.
-    // see https://issues.dlang.org/show_bug.cgi?id=21001
-    storage_class |= sc->stc & STCdeprecated;
-    protection = sc->protection;
-    userAttribDecl = sc->userAttribDecl;
-
-    // TypeTraits needs to know if it's located in an AliasDeclaration
-    sc->flags |= SCOPEalias;
-
-    if (aliassym)
-    {
-        FuncDeclaration *fd = aliassym->isFuncLiteralDeclaration();
-        TemplateDeclaration *td = aliassym->isTemplateDeclaration();
-        if (fd || (td && td->literal))
-        {
-            if (fd && fd->semanticRun >= PASSsemanticdone)
-            {
-                sc->flags &= ~SCOPEalias;
-                return;
-            }
-
-            Expression *e = new FuncExp(loc, aliassym);
-            e = ::semantic(e, sc);
-            if (e->op == TOKfunction)
-            {
-                FuncExp *fe = (FuncExp *)e;
-                aliassym = fe->td ? (Dsymbol *)fe->td : fe->fd;
-            }
-            else
-            {
-                aliassym = NULL;
-                type = Type::terror;
-            }
-            sc->flags &= ~SCOPEalias;
-            return;
-        }
-
-        if (aliassym->isTemplateInstance())
-            aliassym->semantic(sc);
-        sc->flags &= ~SCOPEalias;
-        return;
-    }
-    inuse = 1;
-
-    // Given:
-    //  alias foo.bar.abc def;
-    // it is not knowable from the syntax whether this is an alias
-    // for a type or an alias for a symbol. It is up to the semantic()
-    // pass to distinguish.
-    // If it is a type, then type is set and getType() will return that
-    // type. If it is a symbol, then aliassym is set and type is NULL -
-    // toAlias() will return aliasssym.
-
-    unsigned int errors = global.errors;
-    Type *oldtype = type;
-
-    // Ungag errors when not instantiated DeclDefs scope alias
-    Ungag ungag(global.gag);
-    //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;
-    }
-
-    /* This section is needed because Type::resolve() will:
-     *   const x = 3;
-     *   alias y = x;
-     * try to convert identifier x to 3.
-     */
-    Dsymbol *s = type->toDsymbol(sc);
-    if (errors != global.errors)
-    {
-        s = NULL;
-        type = Type::terror;
-    }
-    if (s && s == this)
-    {
-        error("cannot resolve");
-        s = NULL;
-        type = Type::terror;
-    }
-    if (!s || !s->isEnumMember())
-    {
-        Type *t;
-        Expression *e;
-        Scope *sc2 = sc;
-        if (storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable))
-        {
-            // For 'ref' to be attached to function types, and picked
-            // up by Type::resolve(), it has to go into sc.
-            sc2 = sc->push();
-            sc2->stc |= storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCshared | STCdisable);
-        }
-        type = type->addSTC(storage_class);
-        type->resolve(loc, sc2, &e, &t, &s);
-        if (sc2 != sc)
-            sc2->pop();
-
-        if (e)  // Try to convert Expression to Dsymbol
-        {
-            s = getDsymbol(e);
-            if (!s)
-            {
-                if (e->op != TOKerror)
-                    error("cannot alias an expression %s", e->toChars());
-                t = Type::terror;
-            }
-        }
-        type = t;
-    }
-    if (s == this)
-    {
-        assert(global.errors);
-        type = Type::terror;
-        s = NULL;
-    }
-    if (!s) // it's a type alias
-    {
-        //printf("alias %s resolved to type %s\n", toChars(), type->toChars());
-        type = type->semantic(loc, sc);
-        aliassym = NULL;
-    }
-    else    // it's a symbolic alias
-    {
-        //printf("alias %s resolved to %s %s\n", toChars(), s->kind(), s->toChars());
-        type = NULL;
-        aliassym = s;
-    }
-    if (global.gag && errors != global.errors)
-    {
-        type = oldtype;
-        aliassym = NULL;
-    }
-    inuse = 0;
-    semanticRun = PASSsemanticdone;
-
-    if (Dsymbol *sx = overnext)
-    {
-        overnext = NULL;
-
-        if (!overloadInsert(sx))
-            ScopeDsymbol::multiplyDefined(Loc(), sx, this);
-    }
-    sc->flags &= ~SCOPEalias;
-}
-
 bool AliasDeclaration::overloadInsert(Dsymbol *s)
 {
     //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
@@ -684,7 +509,7 @@ Dsymbol *AliasDeclaration::toAlias()
         }
         else
         {
-            Type *t = type->semantic(loc, _scope);
+            Type *t = typeSemantic(type, loc, _scope);
             if (t->ty == Terror)
                 goto Lerr;
             if (global.errors != olderrors)
@@ -723,11 +548,11 @@ Dsymbol *AliasDeclaration::toAlias()
             /* If this is an internal alias for selective/renamed import,
              * load the module first.
              */
-            _import->semantic(NULL);
+            dsymbolSemantic(_import, NULL);
         }
         if (_scope)
         {
-            aliasSemantic(_scope);
+            aliasSemantic(this, _scope);
         }
     }
 
@@ -783,10 +608,6 @@ const char *OverDeclaration::kind() const
     return "overload alias";    // todo
 }
 
-void OverDeclaration::semantic(Scope *)
-{
-}
-
 bool OverDeclaration::equals(RootObject *o)
 {
     if (this == o)
@@ -922,852 +743,6 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
     return v;
 }
 
-
-void VarDeclaration::semantic(Scope *sc)
-{
-//    if (semanticRun > PASSinit)
-//      return;
-//    semanticRun = PASSsemantic;
-
-    if (semanticRun >= PASSsemanticdone)
-        return;
-
-    Scope *scx = NULL;
-    if (_scope)
-    {
-        sc = _scope;
-        scx = sc;
-        _scope = NULL;
-    }
-
-    if (!sc)
-        return;
-
-    semanticRun = PASSsemantic;
-
-    /* Pick up storage classes from context, but except synchronized,
-     * override, abstract, and final.
-     */
-    storage_class |= (sc->stc & ~(STCsynchronized | STCoverride | STCabstract | STCfinal));
-    if (storage_class & STCextern && _init)
-        error("extern symbols cannot have initializers");
-
-    userAttribDecl = sc->userAttribDecl;
-
-    AggregateDeclaration *ad = isThis();
-    if (ad)
-        storage_class |= ad->storage_class & STC_TYPECTOR;
-
-    /* If auto type inference, do the inference
-     */
-    int inferred = 0;
-    if (!type)
-    {
-        inuse++;
-
-        // Infering the type requires running semantic,
-        // so mark the scope as ctfe if required
-        bool needctfe = (storage_class & (STCmanifest | STCstatic)) != 0;
-        if (needctfe) sc = sc->startCTFE();
-
-        //printf("inferring type for %s with init %s\n", toChars(), _init->toChars());
-        _init = inferType(_init, sc);
-        type = initializerToExpression(_init)->type;
-
-        if (needctfe) sc = sc->endCTFE();
-
-        inuse--;
-        inferred = 1;
-
-        /* This is a kludge to support the existing syntax for RAII
-         * declarations.
-         */
-        storage_class &= ~STCauto;
-        originalType = type->syntaxCopy();
-    }
-    else
-    {
-        if (!originalType)
-            originalType = type->syntaxCopy();
-
-        /* Prefix function attributes of variable declaration can affect
-         * its type:
-         *      pure nothrow void function() fp;
-         *      static assert(is(typeof(fp) == void function() pure nothrow));
-         */
-        Scope *sc2 = sc->push();
-        sc2->stc |= (storage_class & STC_FUNCATTR);
-        inuse++;
-        type = type->semantic(loc, sc2);
-        inuse--;
-        sc2->pop();
-    }
-    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
-    if (type->ty == Terror)
-        errors = true;
-
-    type->checkDeprecated(loc, sc);
-    linkage = sc->linkage;
-    this->parent = sc->parent;
-    //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
-    protection = sc->protection;
-
-    /* If scope's alignment is the default, use the type's alignment,
-     * otherwise the scope overrrides.
-     */
-    alignment = sc->alignment();
-    if (alignment == STRUCTALIGN_DEFAULT)
-        alignment = type->alignment();          // use type's alignment
-
-    //printf("sc->stc = %x\n", sc->stc);
-    //printf("storage_class = x%x\n", storage_class);
-
-    if (global.params.vcomplex)
-        type->checkComplexTransition(loc);
-
-    // Calculate type size + safety checks
-    if (sc->func && !sc->intypeof)
-    {
-        if ((storage_class & STCgshared) && !isMember())
-        {
-            if (sc->func->setUnsafe())
-                error("__gshared not allowed in safe functions; use shared");
-        }
-    }
-
-    Dsymbol *parent = toParent();
-
-    Type *tb = type->toBasetype();
-    Type *tbn = tb->baseElemOf();
-    if (tb->ty == Tvoid && !(storage_class & STClazy))
-    {
-        if (inferred)
-        {
-            error("type %s is inferred from initializer %s, and variables cannot be of type void",
-                type->toChars(), _init->toChars());
-        }
-        else
-            error("variables cannot be of type void");
-        type = Type::terror;
-        tb = type;
-    }
-    if (tb->ty == Tfunction)
-    {
-        error("cannot be declared to be a function");
-        type = Type::terror;
-        tb = type;
-    }
-    if (tb->ty == Tstruct)
-    {
-        TypeStruct *ts = (TypeStruct *)tb;
-        if (!ts->sym->members)
-        {
-            error("no definition of struct %s", ts->toChars());
-        }
-    }
-    if ((storage_class & STCauto) && !inferred)
-        error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?");
-
-    if (tb->ty == Ttuple)
-    {
-        /* Instead, declare variables for each of the tuple elements
-         * and add those.
-         */
-        TypeTuple *tt = (TypeTuple *)tb;
-        size_t nelems = Parameter::dim(tt->arguments);
-        Expression *ie = (_init && !_init->isVoidInitializer()) ? initializerToExpression(_init) : NULL;
-        if (ie)
-            ie = ::semantic(ie, sc);
-
-        if (nelems > 0 && ie)
-        {
-            Expressions *iexps = new Expressions();
-            iexps->push(ie);
-
-            Expressions *exps = new Expressions();
-
-            for (size_t pos = 0; pos < iexps->length; pos++)
-            {
-            Lexpand1:
-                Expression *e = (*iexps)[pos];
-                Parameter *arg = Parameter::getNth(tt->arguments, pos);
-                arg->type = arg->type->semantic(loc, sc);
-                //printf("[%d] iexps->length = %d, ", pos, iexps->length);
-                //printf("e = (%s %s, %s), ", Token::tochars[e->op], e->toChars(), e->type->toChars());
-                //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars());
-
-                if (e != ie)
-                {
-                if (iexps->length > nelems)
-                    goto Lnomatch;
-                if (e->type->implicitConvTo(arg->type))
-                    continue;
-                }
-
-                if (e->op == TOKtuple)
-                {
-                    TupleExp *te = (TupleExp *)e;
-                    if (iexps->length - 1 + te->exps->length > nelems)
-                        goto Lnomatch;
-
-                    iexps->remove(pos);
-                    iexps->insert(pos, te->exps);
-                    (*iexps)[pos] = Expression::combine(te->e0, (*iexps)[pos]);
-                    goto Lexpand1;
-                }
-                else if (isAliasThisTuple(e))
-                {
-                    VarDeclaration *v = copyToTemp(0, "__tup", e);
-                    v->semantic(sc);
-                    VarExp *ve = new VarExp(loc, v);
-                    ve->type = e->type;
-
-                    exps->setDim(1);
-                    (*exps)[0] = ve;
-                    expandAliasThisTuples(exps, 0);
-
-                    for (size_t u = 0; u < exps->length ; u++)
-                    {
-                    Lexpand2:
-                        Expression *ee = (*exps)[u];
-                        arg = Parameter::getNth(tt->arguments, pos + u);
-                        arg->type = arg->type->semantic(loc, sc);
-                        //printf("[%d+%d] exps->length = %d, ", pos, u, exps->length);
-                        //printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars());
-                        //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars());
-
-                        size_t iexps_dim = iexps->length - 1 + exps->length;
-                        if (iexps_dim > nelems)
-                            goto Lnomatch;
-                        if (ee->type->implicitConvTo(arg->type))
-                            continue;
-
-                        if (expandAliasThisTuples(exps, u) != -1)
-                            goto Lexpand2;
-                    }
-
-                    if ((*exps)[0] != ve)
-                    {
-                        Expression *e0 = (*exps)[0];
-                        (*exps)[0] = new CommaExp(loc, new DeclarationExp(loc, v), e0);
-                        (*exps)[0]->type = e0->type;
-
-                        iexps->remove(pos);
-                        iexps->insert(pos, exps);
-                        goto Lexpand1;
-                    }
-                }
-            }
-            if (iexps->length < nelems)
-                goto Lnomatch;
-
-            ie = new TupleExp(_init->loc, iexps);
-        }
-Lnomatch:
-
-        if (ie && ie->op == TOKtuple)
-        {
-            TupleExp *te = (TupleExp *)ie;
-            size_t tedim = te->exps->length;
-            if (tedim != nelems)
-            {
-                ::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems);
-                for (size_t u = tedim; u < nelems; u++) // fill dummy expression
-                    te->exps->push(new ErrorExp());
-            }
-        }
-
-        Objects *exps = new Objects();
-        exps->setDim(nelems);
-        for (size_t i = 0; i < nelems; i++)
-        {
-            Parameter *arg = Parameter::getNth(tt->arguments, i);
-
-            OutBuffer buf;
-            buf.printf("__%s_field_%llu", ident->toChars(), (ulonglong)i);
-            const char *name = buf.extractChars();
-            Identifier *id = Identifier::idPool(name);
-
-            Initializer *ti;
-            if (ie)
-            {
-                Expression *einit = ie;
-                if (ie->op == TOKtuple)
-                {
-                    TupleExp *te = (TupleExp *)ie;
-                    einit = (*te->exps)[i];
-                    if (i == 0)
-                        einit = Expression::combine(te->e0, einit);
-                }
-                ti = new ExpInitializer(einit->loc, einit);
-            }
-            else
-                ti = _init ? _init->syntaxCopy() : NULL;
-
-            VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
-            v->storage_class |= STCtemp | storage_class;
-            if (arg->storageClass & STCparameter)
-                v->storage_class |= arg->storageClass;
-            //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
-            v->semantic(sc);
-
-            if (sc->scopesym)
-            {
-                //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
-                if (sc->scopesym->members)
-                    sc->scopesym->members->push(v);
-            }
-
-            Expression *e = new DsymbolExp(loc, v);
-            (*exps)[i] = e;
-        }
-        TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
-        v2->parent = this->parent;
-        v2->isexp = true;
-        aliassym = v2;
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-
-    /* Storage class can modify the type
-     */
-    type = type->addStorageClass(storage_class);
-
-    /* Adjust storage class to reflect type
-     */
-    if (type->isConst())
-    {
-        storage_class |= STCconst;
-        if (type->isShared())
-            storage_class |= STCshared;
-    }
-    else if (type->isImmutable())
-        storage_class |= STCimmutable;
-    else if (type->isShared())
-        storage_class |= STCshared;
-    else if (type->isWild())
-        storage_class |= STCwild;
-
-    if (StorageClass stc = storage_class & (STCsynchronized | STCoverride | STCabstract | STCfinal))
-    {
-        if (stc == STCfinal)
-            error("cannot be final, perhaps you meant const?");
-        else
-        {
-            OutBuffer buf;
-            stcToBuffer(&buf, stc);
-            error("cannot be %s", buf.peekChars());
-        }
-        storage_class &= ~stc;  // strip off
-    }
-
-    if (storage_class & STCscope)
-    {
-        StorageClass stc = storage_class & (STCstatic | STCextern | STCmanifest | STCtls | STCgshared);
-        if (stc)
-        {
-            OutBuffer buf;
-            stcToBuffer(&buf, stc);
-            error("cannot be 'scope' and '%s'", buf.peekChars());
-        }
-        else if (isMember())
-        {
-            error("field cannot be 'scope'");
-        }
-        else if (!type->hasPointers())
-        {
-            storage_class &= ~STCscope;     // silently ignore; may occur in generic code
-        }
-    }
-
-    if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe))
-    {
-    }
-    else
-    {
-        AggregateDeclaration *aad = parent->isAggregateDeclaration();
-        if (aad)
-        {
-            if (global.params.vfield &&
-                storage_class & (STCconst | STCimmutable) && _init && !_init->isVoidInitializer())
-            {
-                const char *s = (storage_class & STCimmutable) ? "immutable" : "const";
-                message(loc, "`%s.%s` is `%s` field", ad->toPrettyChars(), toChars(), s);
-            }
-            storage_class |= STCfield;
-            if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor)
-            {
-                if (!isThisDeclaration() && !_init)
-                    aad->noDefaultCtor = true;
-            }
-        }
-
-        InterfaceDeclaration *id = parent->isInterfaceDeclaration();
-        if (id)
-        {
-            error("field not allowed in interface");
-        }
-        else if (aad && aad->sizeok == SIZEOKdone)
-        {
-            error("cannot be further field because it will change the determined %s size", aad->toChars());
-        }
-
-        /* Templates cannot add fields to aggregates
-         */
-        TemplateInstance *ti = parent->isTemplateInstance();
-        if (ti)
-        {
-            // Take care of nested templates
-            while (1)
-            {
-                TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
-                if (!ti2)
-                    break;
-                ti = ti2;
-            }
-
-            // If it's a member template
-            AggregateDeclaration *ad2 = ti->tempdecl->isMember();
-            if (ad2 && storage_class != STCundefined)
-            {
-                error("cannot use template to add field to aggregate '%s'", ad2->toChars());
-            }
-        }
-    }
-
-    if ((storage_class & (STCref | STCparameter | STCforeach | STCtemp | STCresult)) == STCref && ident != Id::This)
-    {
-        error("only parameters or foreach declarations can be ref");
-    }
-
-    if (type->hasWild())
-    {
-        if (storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield) ||
-            isDataseg()
-            )
-        {
-            error("only parameters or stack based variables can be inout");
-        }
-        FuncDeclaration *func = sc->func;
-        if (func)
-        {
-            if (func->fes)
-                func = func->fes->func;
-            bool isWild = false;
-            for (FuncDeclaration *fd = func; fd; fd = fd->toParent2()->isFuncDeclaration())
-            {
-                if (((TypeFunction *)fd->type)->iswild)
-                {
-                    isWild = true;
-                    break;
-                }
-            }
-            if (!isWild)
-            {
-                error("inout variables can only be declared inside inout functions");
-            }
-        }
-    }
-
-    if (!(storage_class & (STCctfe | STCref | STCresult)) && tbn->ty == Tstruct &&
-        ((TypeStruct *)tbn)->sym->noDefaultCtor)
-    {
-        if (!_init)
-        {
-            if (isField())
-            {
-                /* For fields, we'll check the constructor later to make sure it is initialized
-                 */
-                storage_class |= STCnodefaultctor;
-            }
-            else if (storage_class & STCparameter)
-                ;
-            else
-                error("default construction is disabled for type %s", type->toChars());
-        }
-    }
-
-    FuncDeclaration *fd = parent->isFuncDeclaration();
-    if (type->isscope() && !(storage_class & STCnodtor))
-    {
-        if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd)
-        {
-            error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope");
-        }
-
-        if (!(storage_class & STCscope))
-        {
-            if (!(storage_class & STCparameter) && ident != Id::withSym)
-                error("reference to scope class must be scope");
-        }
-    }
-
-    // Calculate type size + safety checks
-    if (sc->func && !sc->intypeof)
-    {
-        if (_init && _init->isVoidInitializer() && type->hasPointers()) // get type size
-        {
-            if (sc->func->setUnsafe())
-                error("void initializers for pointers not allowed in safe functions");
-        }
-        else if (!_init &&
-                 !(storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield | STCparameter)) &&
-                 type->hasVoidInitPointers())
-        {
-            if (sc->func->setUnsafe())
-                error("void initializers for pointers not allowed in safe functions");
-        }
-    }
-
-    if (!_init && !fd)
-    {
-        // If not mutable, initializable by constructor only
-        storage_class |= STCctorinit;
-    }
-
-    if (_init)
-        storage_class |= STCinit;     // remember we had an explicit initializer
-    else if (storage_class & STCmanifest)
-        error("manifest constants must have initializers");
-
-    bool isBlit = false;
-    d_uns64 sz = 0;
-    if (!_init && !sc->inunion && !(storage_class & (STCstatic | STCgshared | STCextern)) && fd &&
-        (!(storage_class & (STCfield | STCin | STCforeach | STCparameter | STCresult))
-         || (storage_class & STCout)) &&
-        (sz = type->size()) != 0)
-    {
-        // Provide a default initializer
-        //printf("Providing default initializer for '%s'\n", toChars());
-        if (sz == SIZE_INVALID && type->ty != Terror)
-            error("size of type %s is invalid", type->toChars());
-
-        Type *tv = type;
-        while (tv->ty == Tsarray)    // Don't skip Tenum
-            tv = tv->nextOf();
-        if (tv->needsNested())
-        {
-            /* Nested struct requires valid enclosing frame pointer.
-             * In StructLiteralExp::toElem(), it's calculated.
-             */
-            assert(tv->toBasetype()->ty == Tstruct);
-            checkFrameAccess(loc, sc, ((TypeStruct *)tbn)->sym);
-
-            Expression *e = tv->defaultInitLiteral(loc);
-            e = new BlitExp(loc, new VarExp(loc, this), e);
-            e = ::semantic(e, sc);
-            _init = new ExpInitializer(loc, e);
-            goto Ldtor;
-        }
-        if (tv->ty == Tstruct && ((TypeStruct *)tv)->sym->zeroInit == 1)
-        {
-            /* If a struct is all zeros, as a special case
-             * set it's initializer to the integer 0.
-             * In AssignExp::toElem(), we check for this and issue
-             * a memset() to initialize the struct.
-             * Must do same check in interpreter.
-             */
-            Expression *e = new IntegerExp(loc, 0, Type::tint32);
-            e = new BlitExp(loc, new VarExp(loc, this), e);
-            e->type = type;         // don't type check this, it would fail
-            _init = new ExpInitializer(loc, e);
-            goto Ldtor;
-        }
-        if (type->baseElemOf()->ty == Tvoid)
-        {
-            error("%s does not have a default initializer", type->toChars());
-        }
-        else if (Expression *e = type->defaultInit(loc))
-        {
-            _init = new ExpInitializer(loc, e);
-        }
-        // Default initializer is always a blit
-        isBlit = true;
-    }
-
-    if (_init)
-    {
-        sc = sc->push();
-        sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCnogc | STCref | STCdisable);
-
-        ExpInitializer *ei = _init->isExpInitializer();
-        if (ei)     // Bugzilla 13424: Preset the required type to fail in FuncLiteralDeclaration::semantic3
-            ei->exp = inferType(ei->exp, type);
-
-        // If inside function, there is no semantic3() call
-        if (sc->func || sc->intypeof == 1)
-        {
-            // If local variable, use AssignExp to handle all the various
-            // possibilities.
-            if (fd &&
-                !(storage_class & (STCmanifest | STCstatic | STCtls | STCgshared | STCextern)) &&
-                !_init->isVoidInitializer())
-            {
-                //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
-                if (!ei)
-                {
-                    ArrayInitializer *ai = _init->isArrayInitializer();
-                    Expression *e;
-                    if (ai && tb->ty == Taarray)
-                        e = ai->toAssocArrayLiteral();
-                    else
-                        e = initializerToExpression(_init);
-                    if (!e)
-                    {
-                        // Run semantic, but don't need to interpret
-                        _init = ::semantic(_init, sc, type, INITnointerpret);
-                        e = initializerToExpression(_init);
-                        if (!e)
-                        {
-                            error("is not a static and cannot have static initializer");
-                            e = new ErrorExp();
-                        }
-                    }
-                    ei = new ExpInitializer(_init->loc, e);
-                    _init = ei;
-                }
-
-                Expression *exp = ei->exp;
-                Expression *e1 = new VarExp(loc, this);
-                if (isBlit)
-                    exp = new BlitExp(loc, e1, exp);
-                else
-                    exp = new ConstructExp(loc, e1, exp);
-                canassign++;
-                exp = ::semantic(exp, sc);
-                canassign--;
-                exp = exp->optimize(WANTvalue);
-
-                if (exp->op == TOKerror)
-                {
-                    _init = new ErrorInitializer();
-                    ei = NULL;
-                }
-                else
-                    ei->exp = exp;
-
-                if (ei && isScope())
-                {
-                    Expression *ex = ei->exp;
-                    while (ex->op == TOKcomma)
-                        ex = ((CommaExp *)ex)->e2;
-                    if (ex->op == TOKblit || ex->op == TOKconstruct)
-                        ex = ((AssignExp *)ex)->e2;
-                    if (ex->op == TOKnew)
-                    {
-                        // See if initializer is a NewExp that can be allocated on the stack
-                        NewExp *ne = (NewExp *)ex;
-                        if (type->toBasetype()->ty == Tclass)
-                        {
-                            if (ne->newargs && ne->newargs->length > 1)
-                            {
-                                mynew = true;
-                            }
-                            else
-                            {
-                                ne->onstack = true;
-                                onstack = true;
-                            }
-                        }
-                    }
-                    else if (ex->op == TOKfunction)
-                    {
-                        // or a delegate that doesn't escape a reference to the function
-                        FuncDeclaration *f = ((FuncExp *)ex)->fd;
-                        f->tookAddressOf--;
-                    }
-                }
-            }
-            else
-            {
-                // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof
-                _init = ::semantic(_init, sc, type, sc->intypeof == 1 ? INITnointerpret : INITinterpret);
-            }
-        }
-        else if (parent->isAggregateDeclaration())
-        {
-            _scope = scx ? scx : sc->copy();
-            _scope->setNoFree();
-        }
-        else if (storage_class & (STCconst | STCimmutable | STCmanifest) ||
-                 type->isConst() || type->isImmutable())
-        {
-            /* Because we may need the results of a const declaration in a
-             * subsequent type, such as an array dimension, before semantic2()
-             * gets ordinarily run, try to run semantic2() now.
-             * Ignore failure.
-             */
-
-            if (!inferred)
-            {
-                unsigned errors = global.errors;
-                inuse++;
-                if (ei)
-                {
-                    Expression *exp = ei->exp->syntaxCopy();
-
-                    bool needctfe = isDataseg() || (storage_class & STCmanifest);
-                    if (needctfe) sc = sc->startCTFE();
-                    exp = ::semantic(exp, sc);
-                    exp = resolveProperties(sc, exp);
-                    if (needctfe) sc = sc->endCTFE();
-
-                    Type *tb2 = type->toBasetype();
-                    Type *ti = exp->type->toBasetype();
-
-                    /* The problem is the following code:
-                     *  struct CopyTest {
-                     *     double x;
-                     *     this(double a) { x = a * 10.0;}
-                     *     this(this) { x += 2.0; }
-                     *  }
-                     *  const CopyTest z = CopyTest(5.3);  // ok
-                     *  const CopyTest w = z;              // not ok, postblit not run
-                     *  static assert(w.x == 55.0);
-                     * because the postblit doesn't get run on the initialization of w.
-                     */
-                    if (ti->ty == Tstruct)
-                    {
-                        StructDeclaration *sd = ((TypeStruct *)ti)->sym;
-                        /* Look to see if initializer involves a copy constructor
-                         * (which implies a postblit)
-                         */
-                         // there is a copy constructor
-                         // and exp is the same struct
-                        if (sd->postblit &&
-                            tb2->toDsymbol(NULL) == sd)
-                        {
-                            // The only allowable initializer is a (non-copy) constructor
-                            if (exp->isLvalue())
-                                error("of type struct %s uses this(this), which is not allowed in static initialization", tb2->toChars());
-                        }
-                    }
-                    ei->exp = exp;
-                }
-                _init = ::semantic(_init, sc, type, INITinterpret);
-                inuse--;
-                if (global.errors > errors)
-                {
-                    _init = new ErrorInitializer();
-                    type = Type::terror;
-                }
-            }
-            else
-            {
-                _scope = scx ? scx : sc->copy();
-                _scope->setNoFree();
-            }
-        }
-        sc = sc->pop();
-    }
-
-Ldtor:
-    /* Build code to execute destruction, if necessary
-     */
-    edtor = callScopeDtor(sc);
-    if (edtor)
-    {
-        if (sc->func && storage_class & (STCstatic | STCgshared))
-            edtor = ::semantic(edtor, sc->_module->_scope);
-        else
-            edtor = ::semantic(edtor, sc);
-
-#if 0 // currently disabled because of std.stdio.stdin, stdout and stderr
-        if (isDataseg() && !(storage_class & STCextern))
-            error("static storage variables cannot have destructors");
-#endif
-    }
-
-    semanticRun = PASSsemanticdone;
-
-    if (type->toBasetype()->ty == Terror)
-        errors = true;
-
-    if (sc->scopesym && !sc->scopesym->isAggregateDeclaration())
-    {
-        for (ScopeDsymbol *sym = sc->scopesym; sym && endlinnum == 0;
-             sym = sym->parent ? sym->parent->isScopeDsymbol() : NULL)
-            endlinnum = sym->endlinnum;
-    }
-}
-
-void VarDeclaration::semantic2(Scope *sc)
-{
-    if (semanticRun < PASSsemanticdone && inuse)
-        return;
-
-    //printf("VarDeclaration::semantic2('%s')\n", toChars());
-
-    if (_init && !toParent()->isFuncDeclaration())
-    {
-        inuse++;
-        // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof
-        _init = ::semantic(_init, sc, type, sc->intypeof == 1 ? INITnointerpret : INITinterpret);
-        inuse--;
-    }
-    if (_init && storage_class & STCmanifest)
-    {
-        /* Cannot initializer enums with CTFE classreferences and addresses of struct literals.
-         * Scan initializer looking for them. Issue error if found.
-         */
-        if (ExpInitializer *ei = _init->isExpInitializer())
-        {
-            struct EnumInitializer
-            {
-                static bool arrayHasInvalidEnumInitializer(Expressions *elems)
-                {
-                    for (size_t i = 0; i < elems->length; i++)
-                    {
-                        Expression *e = (*elems)[i];
-                        if (e && hasInvalidEnumInitializer(e))
-                            return true;
-                    }
-                    return false;
-                }
-
-                static bool hasInvalidEnumInitializer(Expression *e)
-                {
-                    if (e->op == TOKclassreference)
-                        return true;
-                    if (e->op == TOKaddress && ((AddrExp *)e)->e1->op == TOKstructliteral)
-                        return true;
-                    if (e->op == TOKarrayliteral)
-                        return arrayHasInvalidEnumInitializer(((ArrayLiteralExp *)e)->elements);
-                    if (e->op == TOKstructliteral)
-                        return arrayHasInvalidEnumInitializer(((StructLiteralExp *)e)->elements);
-                    if (e->op == TOKassocarrayliteral)
-                    {
-                        AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e;
-                        return arrayHasInvalidEnumInitializer(ae->values) ||
-                            arrayHasInvalidEnumInitializer(ae->keys);
-                    }
-                    return false;
-                }
-            };
-            if (EnumInitializer::hasInvalidEnumInitializer(ei->exp))
-                error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead.");
-        }
-    }
-    else if (_init && isThreadlocal())
-    {
-        if ((type->ty == Tclass) && type->isMutable() && !type->isShared())
-        {
-            ExpInitializer *ei = _init->isExpInitializer();
-            if (ei && ei->exp->op == TOKclassreference)
-                error("is mutable. Only const or immutable class thread local variable are allowed, not %s", type->toChars());
-        }
-        else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct && type->nextOf()->isMutable() &&!type->nextOf()->isShared())
-        {
-            ExpInitializer *ei = _init->isExpInitializer();
-            if (ei && ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral)
-            {
-                error("is a pointer to mutable struct. Only pointers to const, immutable or shared struct thread local variable are allowed, not %s", type->toChars());
-            }
-        }
-    }
-    semanticRun = PASSsemantic2done;
-}
-
 void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
 {
     //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad->toChars(), toChars());
@@ -1863,7 +838,7 @@ Dsymbol *VarDeclaration::toAlias()
 {
     //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
     if ((!type || !type->deco) && _scope)
-        semantic(_scope);
+        dsymbolSemantic(this, _scope);
 
     assert(this != aliassym);
     Dsymbol *s = aliassym ? aliassym->toAlias() : this;
@@ -2035,7 +1010,7 @@ Expression *VarDeclaration::getConstInitializer(bool needFullType)
     if (_scope)
     {
         inuse++;
-        _init = ::semantic(_init, _scope, type, INITinterpret);
+        _init = initializerSemantic(_init, _scope, type, INITinterpret);
         _scope = NULL;
         inuse--;
     }
@@ -2300,11 +1275,6 @@ Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *)
     return NULL;
 }
 
-void TypeInfoDeclaration::semantic(Scope *)
-{
-    assert(linkage == LINKc);
-}
-
 const char *TypeInfoDeclaration::toChars()
 {
     //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo->toChars());
index 6a3ec9e7d5c4457abba65c4259edf6aea59c55c3..81b563f4b0fe79f3016ed9d506d5dedd498a6abd 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -30,6 +30,7 @@ struct Ensure
     Ensure syntaxCopy();
     static Ensures *arraySyntaxCopy(Ensures *a);
 };
+class AliasDeclaration;
 class FuncDeclaration;
 class ExpInitializer;
 class StructDeclaration;
@@ -119,6 +120,7 @@ struct Match
 
 void functionResolve(Match *m, Dsymbol *fd, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs);
 int overloadApply(Dsymbol *fstart, void *param, int (*fp)(void *, Dsymbol *));
+void aliasSemantic(AliasDeclaration *ds, Scope *sc);
 
 void ObjectNotFound(Identifier *id);
 
@@ -136,7 +138,6 @@ public:
     DString mangleOverride;     // overridden symbol with pragma(mangle, "...")
 
     Declaration(Identifier *id);
-    void semantic(Scope *sc);
     const char *kind() const;
     d_uns64 size(Loc loc);
     bool checkDisabled(Loc loc, Scope *sc, bool isAliasedDeclaration = false);
@@ -211,8 +212,6 @@ public:
     AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
     static AliasDeclaration *create(Loc loc, Identifier *id, Type *type);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void aliasSemantic(Scope *sc);
     bool overloadInsert(Dsymbol *s);
     const char *kind() const;
     Type *getType();
@@ -235,7 +234,6 @@ public:
 
     OverDeclaration(Identifier *ident, Dsymbol *s, bool hasOverloads = true);
     const char *kind() const;
-    void semantic(Scope *sc);
     bool equals(RootObject *o);
     bool overloadInsert(Dsymbol *s);
 
@@ -279,9 +277,7 @@ public:
     VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
     static VarDeclaration *create(Loc loc, Type *t, Identifier *id, Initializer *init);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
-    void semantic2(Scope *sc);
     const char *kind() const;
     AggregateDeclaration *isThis();
     bool needThis();
@@ -330,7 +326,6 @@ public:
     TypeInfoDeclaration(Type *tinfo);
     static TypeInfoDeclaration *create(Type *tinfo);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     const char *toChars();
 
     TypeInfoDeclaration *isTypeInfoDeclaration() { return this; }
@@ -648,9 +643,6 @@ public:
     FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type);
     static FuncDeclaration *create(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
     bool functionSemantic();
     bool functionSemantic3();
     bool checkForwardRef(Loc loc);
@@ -710,6 +702,8 @@ public:
     bool hasNestedFrameRefs();
     void buildResultVar(Scope *sc, Type *tret);
     Statement *mergeFrequire(Statement *);
+    static bool needsFensure(FuncDeclaration *fd);
+    void buildEnsureRequire();
     Statement *mergeFensure(Statement *, Identifier *oid);
     ParameterList getParameterList();
 
@@ -776,7 +770,6 @@ class CtorDeclaration : public FuncDeclaration
 public:
     CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     const char *kind() const;
     const char *toChars();
     bool isVirtual();
@@ -792,7 +785,6 @@ class PostBlitDeclaration : public FuncDeclaration
 public:
     PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     bool isVirtual();
     bool addPreInvariant();
     bool addPostInvariant();
@@ -808,7 +800,6 @@ public:
     DtorDeclaration(Loc loc, Loc endloc);
     DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     const char *kind() const;
     const char *toChars();
     bool isVirtual();
@@ -826,7 +817,6 @@ public:
     StaticCtorDeclaration(Loc loc, Loc endloc, StorageClass stc);
     StaticCtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     AggregateDeclaration *isThis();
     bool isVirtual();
     bool addPreInvariant();
@@ -855,7 +845,6 @@ public:
     StaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc);
     StaticDtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     AggregateDeclaration *isThis();
     bool isVirtual();
     bool hasStaticCtorOrDtor();
@@ -881,7 +870,6 @@ class InvariantDeclaration : public FuncDeclaration
 public:
     InvariantDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id = NULL);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     bool isVirtual();
     bool addPreInvariant();
     bool addPostInvariant();
@@ -900,7 +888,6 @@ public:
 
     UnitTestDeclaration(Loc loc, Loc endloc, StorageClass stc, char *codedoc);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     AggregateDeclaration *isThis();
     bool isVirtual();
     bool addPreInvariant();
@@ -918,7 +905,6 @@ public:
 
     NewDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *arguments, VarArg varargs);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     const char *kind() const;
     bool isVirtual();
     bool addPreInvariant();
@@ -936,7 +922,6 @@ public:
 
     DeleteDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *arguments);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     const char *kind() const;
     bool isDelete();
     bool isVirtual();
index 3aec39372c1acaad91e9f03c70e9a49ad0013555..b3019aae4b8d503745c8d9d0319c456611dab842 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -25,7 +25,6 @@
 bool walkPostorder(Expression *e, StoppableVisitor *v);
 void lambdaSetParent(Expression *e, Scope *sc);
 bool lambdaCheckForNestedRef(Expression *e, Scope *sc);
-Expression *semantic(Expression *e, Scope *sc);
 
 /********************************************
  * Convert from expression to delegate that returns the expression,
@@ -62,7 +61,7 @@ Expression *toDelegate(Expression *e, Type* t, Scope *sc)
     fld->fbody = s;
 
     e = new FuncExp(loc, fld);
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     return e;
 }
 
index d15d94a31572a572c25af1cbd1fcb7d5f4a21e27..ca1d3bb771cb54d21ff015df2f615903a55f4f94 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -22,8 +22,6 @@
 #include "declaration.h"
 #include "init.h"
 
-Expression *semantic(Expression *e, Scope *sc);
-
 /********************************* EnumDeclaration ****************************/
 
 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
@@ -86,190 +84,6 @@ void EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
     added = true;
 }
 
-
-void EnumDeclaration::semantic(Scope *sc)
-{
-    //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
-    //printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
-    if (semanticRun >= PASSsemanticdone)
-        return;             // semantic() already completed
-    if (semanticRun == PASSsemantic)
-    {
-        assert(memtype);
-        ::error(loc, "circular reference to enum base type %s", memtype->toChars());
-        errors = true;
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-    unsigned dprogress_save = Module::dprogress;
-
-    Scope *scx = NULL;
-    if (_scope)
-    {
-        sc = _scope;
-        scx = _scope;            // save so we don't make redundant copies
-        _scope = NULL;
-    }
-
-    if (!sc)
-        return;
-
-    parent = sc->parent;
-    type = type->semantic(loc, sc);
-
-    protection = sc->protection;
-    if (sc->stc & STCdeprecated)
-        isdeprecated = true;
-    userAttribDecl = sc->userAttribDecl;
-
-    semanticRun = PASSsemantic;
-
-    if (!members && !memtype)               // enum ident;
-    {
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-
-    if (!symtab)
-        symtab = new DsymbolTable();
-
-    /* The separate, and distinct, cases are:
-     *  1. enum { ... }
-     *  2. enum : memtype { ... }
-     *  3. enum ident { ... }
-     *  4. enum ident : memtype { ... }
-     *  5. enum ident : memtype;
-     *  6. enum ident;
-     */
-
-    if (memtype)
-    {
-        memtype = memtype->semantic(loc, sc);
-
-        /* Check to see if memtype is forward referenced
-         */
-        if (memtype->ty == Tenum)
-        {
-            EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
-            if (!sym->memtype || !sym->members || !sym->symtab || sym->_scope)
-            {
-                // memtype is forward referenced, so try again later
-                _scope = scx ? scx : sc->copy();
-                _scope->setNoFree();
-                _scope->_module->addDeferredSemantic(this);
-                Module::dprogress = dprogress_save;
-                //printf("\tdeferring %s\n", toChars());
-                semanticRun = PASSinit;
-                return;
-            }
-        }
-        if (memtype->ty == Tvoid)
-        {
-            error("base type must not be void");
-            memtype = Type::terror;
-        }
-        if (memtype->ty == Terror)
-        {
-            errors = true;
-            if (members)
-            {
-                for (size_t i = 0; i < members->length; i++)
-                {
-                    Dsymbol *s = (*members)[i];
-                    s->errors = true;               // poison all the members
-                }
-            }
-            semanticRun = PASSsemanticdone;
-            return;
-        }
-    }
-
-    semanticRun = PASSsemanticdone;
-
-    if (!members)               // enum ident : memtype;
-        return;
-
-    if (members->length == 0)
-    {
-        error("enum %s must have at least one member", toChars());
-        errors = true;
-        return;
-    }
-
-    Module::dprogress++;
-
-    Scope *sce;
-    if (isAnonymous())
-        sce = sc;
-    else
-    {
-        sce = sc->push(this);
-        sce->parent = this;
-    }
-    sce = sce->startCTFE();
-    sce->setNoFree();                   // needed for getMaxMinValue()
-
-    /* Each enum member gets the sce scope
-     */
-    for (size_t i = 0; i < members->length; i++)
-    {
-        EnumMember *em = (*members)[i]->isEnumMember();
-        if (em)
-            em->_scope = sce;
-    }
-
-    if (!added)
-    {
-        /* addMember() is not called when the EnumDeclaration appears as a function statement,
-         * so we have to do what addMember() does and install the enum members in the right symbol
-         * table
-         */
-        ScopeDsymbol *scopesym = NULL;
-        if (isAnonymous())
-        {
-            /* Anonymous enum members get added to enclosing scope.
-             */
-            for (Scope *sct = sce; 1; sct = sct->enclosing)
-            {
-                assert(sct);
-                if (sct->scopesym)
-                {
-                    scopesym = sct->scopesym;
-                    if (!sct->scopesym->symtab)
-                        sct->scopesym->symtab = new DsymbolTable();
-                    break;
-                }
-            }
-        }
-        else
-        {
-            // Otherwise enum members are in the EnumDeclaration's symbol table
-            scopesym = this;
-        }
-
-        for (size_t i = 0; i < members->length; i++)
-        {
-            EnumMember *em = (*members)[i]->isEnumMember();
-            if (em)
-            {
-                em->ed = this;
-                em->addMember(sc, scopesym);
-            }
-        }
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        EnumMember *em = (*members)[i]->isEnumMember();
-        if (em)
-            em->semantic(em->_scope);
-    }
-    //printf("defaultval = %lld\n", defaultval);
-
-    //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
-    //printf("members = %s\n", members->toChars());
-}
-
 /******************************
  * Get the value of the .max/.min property as an Expression
  * Input:
@@ -292,7 +106,7 @@ Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
         goto Ldone;
 
     if (_scope)
-        semantic(_scope);
+        dsymbolSemantic(this, _scope);
     if (errors)
         goto Lerrors;
     if (semanticRun == PASSinit || !members)
@@ -343,7 +157,7 @@ Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
              */
             Expression *ec = new CmpExp(id == Id::max ? TOKgt : TOKlt, em->loc, e, *pval);
             inuse++;
-            ec = ::semantic(ec, em->_scope);
+            ec = expressionSemantic(ec, em->_scope);
             inuse--;
             ec = ec->ctfeInterpret();
             if (ec->toInteger())
@@ -387,7 +201,7 @@ Expression *EnumDeclaration::getDefaultValue(Loc loc)
         return defaultval;
 
     if (_scope)
-        semantic(_scope);
+        dsymbolSemantic(this, _scope);
     if (errors)
         goto Lerrors;
     if (semanticRun == PASSinit || !members)
@@ -428,7 +242,7 @@ Type *EnumDeclaration::getMemtype(Loc loc)
          * just the base type
          */
         if (memtype)
-            memtype = memtype->semantic(loc, _scope);
+            memtype = typeSemantic(memtype, loc, _scope);
         else
         {
             if (!isAnonymous() && members)
@@ -481,12 +295,12 @@ Dsymbol *EnumDeclaration::search(const Loc &loc, Identifier *ident, int flags)
     if (_scope)
     {
         // Try one last time to resolve this enum
-        semantic(_scope);
+        dsymbolSemantic(this, _scope);
     }
 
     if (!members || !symtab || _scope)
     {
-        error("is forward referenced when looking for '%s'", ident->toChars());
+        error("is forward referenced when looking for `%s`", ident->toChars());
         //*(char*)0=0;
         return NULL;
     }
@@ -535,236 +349,9 @@ const char *EnumMember::kind() const
     return "enum member";
 }
 
-void EnumMember::semantic(Scope *sc)
-{
-    //printf("EnumMember::semantic() %s\n", toChars());
-    if (errors || semanticRun >= PASSsemanticdone)
-        return;
-    if (semanticRun == PASSsemantic)
-    {
-        error("circular reference to enum member");
-    Lerrors:
-        errors = true;
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-    assert(ed);
-
-    ed->semantic(sc);
-    if (ed->errors)
-        goto Lerrors;
-
-    if (errors || semanticRun >= PASSsemanticdone)
-        return;
-
-    if (_scope)
-        sc = _scope;
-    if (!sc)
-        return;
-
-    semanticRun = PASSsemantic;
-
-    protection = ed->isAnonymous() ? ed->protection : Prot(Prot::public_);
-    linkage = LINKd;
-    storage_class |= STCmanifest;
-
-    // https://issues.dlang.org/show_bug.cgi?id=9701
-    if (ed->isAnonymous())
-    {
-        if (userAttribDecl)
-            userAttribDecl->userAttribDecl = ed->userAttribDecl;
-        else
-            userAttribDecl = ed->userAttribDecl;
-    }
-
-    // The first enum member is special
-    bool first = (this == (*ed->members)[0]);
-
-    if (origType)
-    {
-        origType = origType->semantic(loc, sc);
-        type = origType;
-        assert(value());          // "type id;" is not a valid enum member declaration
-    }
-
-    if (value())
-    {
-        Expression *e = value();
-        assert(e->dyncast() == DYNCAST_EXPRESSION);
-        e = ::semantic(e, sc);
-        e = resolveProperties(sc, e);
-        e = e->ctfeInterpret();
-        if (e->op == TOKerror)
-            goto Lerrors;
-        if (first && !ed->memtype && !ed->isAnonymous())
-        {
-            ed->memtype = e->type;
-            if (ed->memtype->ty == Terror)
-            {
-                ed->errors = true;
-                goto Lerrors;
-            }
-            if (ed->memtype->ty != Terror)
-            {
-                /* Bugzilla 11746: All of named enum members should have same type
-                 * with the first member. If the following members were referenced
-                 * during the first member semantic, their types should be unified.
-                 */
-                for (size_t i = 0; i < ed->members->length; i++)
-                {
-                    EnumMember *em = (*ed->members)[i]->isEnumMember();
-                    if (!em || em == this || em->semanticRun < PASSsemanticdone || em->origType)
-                        continue;
-
-                    //printf("[%d] em = %s, em->semanticRun = %d\n", i, toChars(), em->semanticRun);
-                    Expression *ev = em->value();
-                    ev = ev->implicitCastTo(sc, ed->memtype);
-                    ev = ev->ctfeInterpret();
-                    ev = ev->castTo(sc, ed->type);
-                    if (ev->op == TOKerror)
-                        ed->errors = true;
-                    em->value() = ev;
-                }
-                if (ed->errors)
-                {
-                    ed->memtype = Type::terror;
-                    goto Lerrors;
-                }
-            }
-        }
-
-        if (ed->memtype && !origType)
-        {
-            e = e->implicitCastTo(sc, ed->memtype);
-            e = e->ctfeInterpret();
-
-            // save origValue for better json output
-            origValue = e;
-
-            if (!ed->isAnonymous())
-            {
-                e = e->castTo(sc, ed->type);
-                e = e->ctfeInterpret();
-            }
-        }
-        else if (origType)
-        {
-            e = e->implicitCastTo(sc, origType);
-            e = e->ctfeInterpret();
-            assert(ed->isAnonymous());
-
-            // save origValue for better json output
-            origValue = e;
-        }
-        value() = e;
-    }
-    else if (first)
-    {
-        Type *t;
-        if (ed->memtype)
-            t = ed->memtype;
-        else
-        {
-            t = Type::tint32;
-            if (!ed->isAnonymous())
-                ed->memtype = t;
-        }
-        Expression *e = new IntegerExp(loc, 0, Type::tint32);
-        e = e->implicitCastTo(sc, t);
-        e = e->ctfeInterpret();
-
-        // save origValue for better json output
-        origValue = e;
-
-        if (!ed->isAnonymous())
-        {
-            e = e->castTo(sc, ed->type);
-            e = e->ctfeInterpret();
-        }
-        value() = e;
-    }
-    else
-    {
-        /* Find the previous enum member,
-         * and set this to be the previous value + 1
-         */
-        EnumMember *emprev = NULL;
-        for (size_t i = 0; i < ed->members->length; i++)
-        {
-            EnumMember *em = (*ed->members)[i]->isEnumMember();
-            if (em)
-            {
-                if (em == this)
-                    break;
-                emprev = em;
-            }
-        }
-        assert(emprev);
-        if (emprev->semanticRun < PASSsemanticdone)    // if forward reference
-            emprev->semantic(emprev->_scope);    // resolve it
-        if (emprev->errors)
-            goto Lerrors;
-
-        Expression *eprev = emprev->value();
-        Type *tprev = eprev->type->equals(ed->type) ? ed->memtype : eprev->type;
-
-        Expression *emax = tprev->getProperty(ed->loc, Id::max, 0);
-        emax = ::semantic(emax, sc);
-        emax = emax->ctfeInterpret();
-
-        // Set value to (eprev + 1).
-        // But first check that (eprev != emax)
-        assert(eprev);
-        Expression *e = new EqualExp(TOKequal, loc, eprev, emax);
-        e = ::semantic(e, sc);
-        e = e->ctfeInterpret();
-        if (e->toInteger())
-        {
-            error("initialization with (%s.%s + 1) causes overflow for type '%s'", emprev->ed->toChars(), emprev->toChars(), ed->type->toBasetype()->toChars());
-            goto Lerrors;
-        }
-
-        // Now set e to (eprev + 1)
-        e = new AddExp(loc, eprev, new IntegerExp(loc, 1, Type::tint32));
-        e = ::semantic(e, sc);
-        e = e->castTo(sc, eprev->type);
-        e = e->ctfeInterpret();
-
-        // save origValue (without cast) for better json output
-        if (e->op != TOKerror)  // avoid duplicate diagnostics
-        {
-            assert(emprev->origValue);
-            origValue = new AddExp(loc, emprev->origValue, new IntegerExp(loc, 1, Type::tint32));
-            origValue = ::semantic(origValue, sc);
-            origValue = origValue->ctfeInterpret();
-        }
-
-        if (e->op == TOKerror)
-            goto Lerrors;
-        if (e->type->isfloating())
-        {
-            // Check that e != eprev (not always true for floats)
-            Expression *etest = new EqualExp(TOKequal, loc, e, eprev);
-            etest = ::semantic(etest, sc);
-            etest = etest->ctfeInterpret();
-            if (etest->toInteger())
-            {
-                error("has inexact value, due to loss of precision");
-                goto Lerrors;
-            }
-        }
-        value() = e;
-    }
-    if (!origType)
-        type = value()->type;
-
-    assert(origValue);
-    semanticRun = PASSsemanticdone;
-}
-
 Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
 {
-    semantic(sc);
+    dsymbolSemantic(this, sc);
     if (errors)
         return new ErrorExp();
     checkDisabled(loc, sc);
@@ -776,5 +363,5 @@ Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
     if (errors)
         return new ErrorExp();
     Expression *e = new VarExp(loc, this);
-    return ::semantic(e, sc);
+    return expressionSemantic(e, sc);
 }
index 4b969d4dd600048164ab73e0641a6a20bf1795c0..0d93ed80e587f3e621af0925564cd786c500b036 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -194,211 +194,6 @@ 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)
-    {
-        load(sc);
-        if (mod)
-            mod->importAll(NULL);
-    }
-
-    if (mod)
-    {
-        // Modules need a list of each imported module
-        //printf("%s imports %s\n", sc->_module->toChars(), mod->toChars());
-        sc->_module->aimports.push(mod);
-
-        if (sc->explicitProtection)
-            protection = sc->protection;
-
-        if (!aliasId && !names.length) // neither a selective nor a renamed import
-        {
-            ScopeDsymbol *scopesym = NULL;
-            if (sc->explicitProtection)
-                protection = sc->protection.kind;
-            for (Scope *scd = sc; scd; scd = scd->enclosing)
-            {
-                if (!scd->scopesym)
-                    continue;
-                scopesym = scd->scopesym;
-                break;
-            }
-
-            if (!isstatic)
-            {
-                scopesym->importScope(mod, protection);
-            }
-
-            // Mark the imported packages as accessible from the current
-            // scope. This access check is necessary when using FQN b/c
-            // we're using a single global package tree. See Bugzilla 313.
-            if (packages)
-            {
-                // import a.b.c.d;
-                Package *p = pkg; // a
-                scopesym->addAccessiblePackage(p, protection);
-                for (size_t i = 1; i < packages->length; i++) // [b, c]
-                {
-                    Identifier *id = (*packages)[i];
-                    p = (Package *) p->symtab->lookup(id);
-                    scopesym->addAccessiblePackage(p, protection);
-                }
-            }
-            scopesym->addAccessiblePackage(mod, protection); // d
-        }
-
-        mod->semantic(NULL);
-
-        if (mod->needmoduleinfo)
-        {
-            //printf("module4 %s because of %s\n", sc->_module->toChars(), mod->toChars());
-            sc->_module->needmoduleinfo = 1;
-        }
-
-        sc = sc->push(mod);
-        sc->protection = protection;
-        for (size_t i = 0; i < aliasdecls.length; i++)
-        {
-            AliasDeclaration *ad = aliasdecls[i];
-            //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), aliases[i]->toChars(), names[i]->toChars(), ad->_scope);
-            if (mod->search(loc, names[i]))
-            {
-                ad->semantic(sc);
-                // If the import declaration is in non-root module,
-                // analysis of the aliased symbol is deferred.
-                // Therefore, don't see the ad->aliassym or ad->type here.
-            }
-            else
-            {
-                Dsymbol *s = mod->search_correct(names[i]);
-                if (s)
-                    mod->error(loc, "import '%s' not found, did you mean %s '%s'?", names[i]->toChars(), s->kind(), s->toChars());
-                else
-                    mod->error(loc, "import '%s' not found", names[i]->toChars());
-                ad->type = Type::terror;
-            }
-        }
-        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 &&
-        !(id == Id::object && sc->_module->ident == Id::object) &&
-        sc->_module->ident != Id::entrypoint &&
-        strcmp(sc->_module->ident->toChars(), "__main") != 0)
-    {
-        /* The grammar of the file is:
-         *      ImportDeclaration
-         *          ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
-         *      ModuleAliasIdentifier ] "\n"
-         *
-         *      BasicImportDeclaration
-         *          ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
-         *              " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
-         *
-         *      FilePath
-         *          - any string with '(', ')' and '\' escaped with the '\' character
-         */
-
-        OutBuffer *ob = global.params.moduleDeps;
-        Module* imod = sc->instantiatingModule();
-        if (!global.params.moduleDepsFile.length)
-            ob->writestring("depsImport ");
-        ob->writestring(imod->toPrettyChars());
-        ob->writestring(" (");
-        escapePath(ob,  imod->srcfile->toChars());
-        ob->writestring(") : ");
-
-        // use protection instead of sc->protection because it couldn't be
-        // resolved yet, see the comment above
-        protectionToBuffer(ob, protection);
-        ob->writeByte(' ');
-        if (isstatic)
-        {
-            stcToBuffer(ob, STCstatic);
-            ob->writeByte(' ');
-        }
-        ob->writestring(": ");
-
-        if (packages)
-        {
-            for (size_t i = 0; i < packages->length; i++)
-            {
-                Identifier *pid = (*packages)[i];
-                ob->printf("%s.", pid->toChars());
-            }
-        }
-
-        ob->writestring(id->toChars());
-        ob->writestring(" (");
-        if (mod)
-            escapePath(ob, mod->srcfile->toChars());
-        else
-            ob->writestring("???");
-        ob->writeByte(')');
-
-        for (size_t i = 0; i < names.length; i++)
-        {
-            if (i == 0)
-                ob->writeByte(':');
-            else
-                ob->writeByte(',');
-
-            Identifier *name = names[i];
-            Identifier *alias = aliases[i];
-
-            if (!alias)
-            {
-                ob->printf("%s", name->toChars());
-                alias = name;
-            }
-            else
-                ob->printf("%s=%s", alias->toChars(), name->toChars());
-        }
-
-        if (aliasId)
-                ob->printf(" -> %s", aliasId->toChars());
-
-        ob->writenl();
-    }
-
-    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
-}
-
-void Import::semantic2(Scope *sc)
-{
-    //printf("Import::semantic2('%s')\n", toChars());
-    if (mod)
-    {
-        mod->semantic2(NULL);
-        if (mod->needmoduleinfo)
-        {
-            //printf("module5 %s because of %s\n", sc->_module->toChars(), mod->toChars());
-            if (sc)
-                sc->_module->needmoduleinfo = 1;
-        }
-    }
-}
-
 Dsymbol *Import::toAlias()
 {
     if (aliasId)
@@ -466,7 +261,7 @@ Dsymbol *Import::search(const Loc &loc, Identifier *ident, int flags)
     {
         load(NULL);
         mod->importAll(NULL);
-        mod->semantic(NULL);
+        dsymbolSemantic(mod, NULL);
     }
 
     // Forward it to the package/module
index f868790f9e73dd4f5a9274f91c8e6a6fdf82a5ef..5e71f3b24a1891b454ccdb349c49d349f6fe9375 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -40,8 +40,6 @@ enum CtfeGoal
 bool walkPostorder(Expression *e, StoppableVisitor *v);
 Expression *interpret(Statement *s, InterState *istate);
 Expression *interpret(Expression *e, InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
-Expression *semantic(Expression *e, Scope *sc);
-Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
 
 static Expression *interpret(UnionExp *pue, Expression *e, InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
 static Expression *interpret(UnionExp *pue, Statement *s, InterState *istate);
@@ -778,7 +776,7 @@ static Expression *interpretFunction(UnionExp *pue, FuncDeclaration *fd, InterSt
     {
         // error, no this. Prevent segfault.
         // Here should be unreachable by the strict 'this' check in front-end.
-        fd->error("need 'this' to access member %s", fd->toChars());
+        fd->error("need `this` to access member %s", fd->toChars());
         return CTFEExp::cantexp;
     }
 
@@ -802,7 +800,7 @@ static Expression *interpretFunction(UnionExp *pue, FuncDeclaration *fd, InterSt
             if (!istate && (fparam->storageClass & STCout))
             {
                 // initializing an out parameter involves writing to it.
-                earg->error("global %s cannot be passed as an 'out' parameter at compile time", earg->toChars());
+                earg->error("global %s cannot be passed as an `out` parameter at compile time", earg->toChars());
                 return CTFEExp::cantexp;
             }
             // Convert all reference arguments into lvalue references
@@ -1861,7 +1859,7 @@ public:
                    result->op == TOKclassreference);
             return;
         }
-        e->error("value of 'this' is not known at compile time");
+        e->error("value of `this` is not known at compile time");
         result = CTFEExp::cantexp;
     }
 
@@ -2085,7 +2083,7 @@ public:
 
             if (!v->originalType && v->semanticRun < PASSsemanticdone) // semantic() not yet run
             {
-                v->semantic(NULL);
+                dsymbolSemantic(v, NULL);
                 if (v->type->ty == Terror)
                     return CTFEExp::cantexp;
             }
@@ -2096,13 +2094,13 @@ public:
             {
                 if (v->inuse)
                 {
-                    error(loc, "circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
+                    error(loc, "circular initialization of %s `%s`", v->kind(), v->toPrettyChars());
                     return CTFEExp::cantexp;
                 }
                 if (v->_scope)
                 {
                     v->inuse++;
-                    v->_init = ::semantic(v->_init, v->_scope, v->type, INITinterpret); // might not be run on aggregate members
+                    v->_init = initializerSemantic(v->_init, v->_scope, v->type, INITinterpret); // might not be run on aggregate members
                     v->inuse--;
                 }
                 e = initializerToExpression(v->_init, v->type);
@@ -2196,7 +2194,7 @@ public:
             e = s->dsym->type->defaultInitLiteral(loc);
             if (e->op == TOKerror)
                 error(loc, "CTFE failed because of previous errors in %s.init", s->toChars());
-            e = ::semantic(e, NULL);
+            e = expressionSemantic(e, NULL);
             if (e->op == TOKerror)
                 e = CTFEExp::cantexp;
             else // Convert NULL to CTFEExp
@@ -2394,7 +2392,7 @@ public:
 
             if (result->op == TOKnull)
             {
-                e->error("null pointer dereference evaluating typeid. '%s' is null", ex->toChars());
+                e->error("null pointer dereference evaluating typeid. `%s` is null", ex->toChars());
                 result = CTFEExp::cantexp;
                 return;
             }
@@ -2823,7 +2821,7 @@ public:
                     VarDeclaration *v = c->fields[i];
                     if (v->inuse)
                     {
-                        e->error("circular reference to '%s'", v->toPrettyChars());
+                        e->error("circular reference to `%s`", v->toPrettyChars());
                         result = CTFEExp::cantexp;
                         return;
                     }
@@ -5478,7 +5476,7 @@ public:
         {
             if (result->op != TOKclassreference)
             {
-                e->error("delete on invalid class reference '%s'", result->toChars());
+                e->error("delete on invalid class reference `%s`", result->toChars());
                 result = CTFEExp::cantexp;
                 return;
             }
@@ -5509,7 +5507,7 @@ public:
                 if (result->op != TOKaddress ||
                     ((AddrExp *)result)->e1->op != TOKstructliteral)
                 {
-                    e->error("delete on invalid struct pointer '%s'", result->toChars());
+                    e->error("delete on invalid struct pointer `%s`", result->toChars());
                     result = CTFEExp::cantexp;
                     return;
                 }
@@ -5540,7 +5538,7 @@ public:
             {
                 if (result->op != TOKarrayliteral)
                 {
-                    e->error("delete on invalid struct array '%s'", result->toChars());
+                    e->error("delete on invalid struct array `%s`", result->toChars());
                     result = CTFEExp::cantexp;
                     return;
                 }
@@ -5899,9 +5897,9 @@ public:
         if (result->op != TOKaddress)
         {
             if (result->op == TOKnull)
-                e->error("dereference of null pointer '%s'", e->e1->toChars());
+                e->error("dereference of null pointer `%s`", e->e1->toChars());
             else
-                e->error("dereference of invalid pointer '%s'", result->toChars());
+                e->error("dereference of invalid pointer `%s`", result->toChars());
             result = CTFEExp::cantexp;
             return;
         }
@@ -5952,9 +5950,9 @@ public:
         if (ex->op == TOKnull)
         {
             if (ex->type->toBasetype()->ty == Tclass)
-                e->error("class '%s' is null and cannot be dereferenced", e->e1->toChars());
+                e->error("class `%s` is null and cannot be dereferenced", e->e1->toChars());
             else
-                e->error("CTFE internal error: null this '%s'", e->e1->toChars());
+                e->error("CTFE internal error: null this `%s`", e->e1->toChars());
             result = CTFEExp::cantexp;
             return;
         }
@@ -6181,7 +6179,7 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
     }
     else if (e->op == TOKvoid)
     {
-        error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars());
+        error(loc, "uninitialized variable `%s` cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars());
         return new ErrorExp();
     }
 
index cefd3b037aa77f2281a32e6b1914d78820a498b3..91cbe50713ce6bd2174e3755cdbe974475416ea3 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 4a9a118ebba67b39a69d5d41dfd7138db477093c..303ae617874013593bbe3b5ff0abd5a704fc5c6f 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 95c263fc42533cb42c8bf082f8125c55c1de36c3..a2b01f534eb593558e794e91ced6284d7751fcd4 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -34,8 +34,6 @@ Dsymbols Module::deferred2; // deferred Dsymbol's needing semantic2() run on the
 Dsymbols Module::deferred3; // deferred Dsymbol's needing semantic3() run on them
 unsigned Module::dprogress;
 
-StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
-
 void Module::_init()
 {
     modules = new DsymbolTable();
@@ -815,113 +813,6 @@ void Module::importAll(Scope *)
     sc->pop();          // 2 pops because Scope::createGlobal() created 2
 }
 
-void Module::semantic(Scope *)
-{
-    if (semanticRun != PASSinit)
-        return;
-
-    //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
-    semanticRun = PASSsemantic;
-
-    // Note that modules get their own scope, from scratch.
-    // This is so regardless of where in the syntax a module
-    // gets imported, it is unaffected by context.
-    Scope *sc = _scope;                  // see if already got one from importAll()
-    if (!sc)
-    {
-        Scope::createGlobal(this);      // create root scope
-    }
-
-    //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
-
-    // Pass 1 semantic routines: do public side of the definition
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-
-        //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
-        s->semantic(sc);
-        runDeferredSemantic();
-    }
-
-    if (userAttribDecl)
-    {
-        userAttribDecl->semantic(sc);
-    }
-
-    if (!_scope)
-    {
-        sc = sc->pop();
-        sc->pop();              // 2 pops because Scope::createGlobal() created 2
-    }
-    semanticRun = PASSsemanticdone;
-    //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
-}
-
-void Module::semantic2(Scope*)
-{
-    //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
-    if (semanticRun != PASSsemanticdone)       // semantic() not completed yet - could be recursive call
-        return;
-    semanticRun = PASSsemantic2;
-
-    // Note that modules get their own scope, from scratch.
-    // This is so regardless of where in the syntax a module
-    // gets imported, it is unaffected by context.
-    Scope *sc = Scope::createGlobal(this);      // create root scope
-    //printf("Module = %p\n", sc.scopesym);
-
-    // Pass 2 semantic routines: do initializers and function bodies
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->semantic2(sc);
-    }
-
-    if (userAttribDecl)
-    {
-        userAttribDecl->semantic2(sc);
-    }
-
-    sc = sc->pop();
-    sc->pop();
-    semanticRun = PASSsemantic2done;
-    //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
-}
-
-void Module::semantic3(Scope*)
-{
-    //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
-    if (semanticRun != PASSsemantic2done)
-        return;
-    semanticRun = PASSsemantic3;
-
-    // Note that modules get their own scope, from scratch.
-    // This is so regardless of where in the syntax a module
-    // gets imported, it is unaffected by context.
-    Scope *sc = Scope::createGlobal(this);      // create root scope
-    //printf("Module = %p\n", sc.scopesym);
-
-    // Pass 3 semantic routines: do initializers and function bodies
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
-        s->semantic3(sc);
-
-        runDeferredSemantic2();
-    }
-
-    if (userAttribDecl)
-    {
-        userAttribDecl->semantic3(sc);
-    }
-
-    sc = sc->pop();
-    sc->pop();
-    semanticRun = PASSsemantic3done;
-}
-
 /**********************************
  * Determine if we need to generate an instance of ModuleInfo
  * for this Module.
@@ -1074,7 +965,7 @@ void Module::runDeferredSemantic()
         {
             Dsymbol *s = todo[i];
 
-            s->semantic(NULL);
+            dsymbolSemantic(s, NULL);
             //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
         }
         //printf("\tdeferred.length = %d, len = %d, dprogress = %d\n", deferred.length, len, dprogress);
@@ -1094,7 +985,7 @@ void Module::runDeferredSemantic2()
     {
         Dsymbol *s = (*a)[i];
         //printf("[%d] %s semantic2a\n", i, s->toPrettyChars());
-        s->semantic2(NULL);
+        semantic2(s, NULL);
 
         if (global.errors)
             break;
@@ -1112,7 +1003,7 @@ void Module::runDeferredSemantic3()
         Dsymbol *s = (*a)[i];
         //printf("[%d] %s semantic3a\n", i, s->toPrettyChars());
 
-        s->semantic3(NULL);
+        semantic3(s, NULL);
 
         if (global.errors)
             break;
@@ -1296,12 +1187,6 @@ bool Package::isAncestorPackageOf(const Package * const pkg) const
     return isAncestorPackageOf(pkg->parent->isPackage());
 }
 
-void Package::semantic(Scope *)
-{
-    if (semanticRun < PASSsemanticdone)
-        semanticRun = PASSsemanticdone;
-}
-
 /****************************************************
  * Input:
  *      packages[]      the pkg1.pkg2 of pkg1.pkg2.mod
index 92783b89ab36aacf2d7bceb023f4081765598c51..5d2da1ccdb91f974c10b1312135716a1037a9123 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -663,7 +663,8 @@ static size_t getCodeIndent(const char *src)
 /** Recursively expand template mixin member docs into the scope. */
 static void expandTemplateMixinComments(TemplateMixin *tm, OutBuffer *buf, Scope *sc)
 {
-    if (!tm->semanticRun) tm->semantic(sc);
+    if (!tm->semanticRun)
+        dsymbolSemantic(tm, sc);
     TemplateDeclaration *td = (tm && tm->tempdecl) ?
         tm->tempdecl->isTemplateDeclaration() : NULL;
     if (td && td->members)
@@ -1105,9 +1106,9 @@ void toDocBuffer(Dsymbol *s, OutBuffer *buf, Scope *sc)
             emitProtection(buf, ad->protection);
             buf->printf("alias %s = ", ad->toChars());
 
-            if (Dsymbol *s = ad->aliassym)  // ident alias
+            if (Dsymbol *sa = ad->aliassym)  // ident alias
             {
-                prettyPrintDsymbol(s, ad->parent);
+                prettyPrintDsymbol(sa, ad->parent);
             }
             else if (Type *type = ad->getType())  // type alias
             {
index c06ffe6c3a0a11225dc4ac2d5105378edafec200..6d13ab1c1213252dd4e2e1ab9892e2592fc4baea 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 72dc0893af59b1e8e14cd1efcd526979e809db16..65e6734b035a73cb7c11854f9f09d09b7b65e392 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -398,7 +398,7 @@ static Dsymbol *searchScopes(Scope *scope, Loc loc, Identifier *ident, Dsymbol *
                 ident == Id::length && sc->scopesym->isArrayScopeSymbol() &&
                 sc->enclosing && sc->enclosing->search(loc, ident, NULL, flags))
             {
-                warning(s->loc, "array 'length' hides other 'length' name in outer scope");
+                warning(s->loc, "array `length` hides other `length` name in outer scope");
             }
             if (pscopesym)
                 *pscopesym = sc->scopesym;
@@ -473,11 +473,11 @@ Dsymbol *Scope::insert(Dsymbol *s)
     }
     else if (WithScopeSymbol *ss = s->isWithScopeSymbol())
     {
-        if (VarDeclaration *vd = ss->withstate->wthis)
+        if (VarDeclaration *wthis = ss->withstate->wthis)
         {
             if (lastVar)
-                vd->lastVar = lastVar;
-            lastVar = vd;
+                wthis->lastVar = lastVar;
+            lastVar = wthis;
         }
         return NULL;
     }
index 8829367dab4560bf17c59ca5db31c91d15d60bc9..40c67ceb0844573a05af67b56d72f268a11c30e9 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -247,89 +247,6 @@ void AggregateDeclaration::setScope(Scope *sc)
         ScopeDsymbol::setScope(sc);
 }
 
-void AggregateDeclaration::semantic2(Scope *sc)
-{
-    //printf("AggregateDeclaration::semantic2(%s) type = %s, errors = %d\n", toChars(), type->toChars(), errors);
-    if (!members)
-        return;
-
-    if (_scope)
-    {
-        error("has forward references");
-        return;
-    }
-
-    Scope *sc2 = newScope(sc);
-
-    determineSize(loc);
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        //printf("\t[%d] %s\n", i, s->toChars());
-        s->semantic2(sc2);
-    }
-
-    sc2->pop();
-}
-
-void AggregateDeclaration::semantic3(Scope *sc)
-{
-    //printf("AggregateDeclaration::semantic3(%s) type = %s, errors = %d\n", toChars(), type->toChars(), errors);
-    if (!members)
-        return;
-
-    StructDeclaration *sd = isStructDeclaration();
-    if (!sc)    // from runDeferredSemantic3 for TypeInfo generation
-    {
-        assert(sd);
-        sd->semanticTypeInfoMembers();
-        return;
-    }
-
-    Scope *sc2 = newScope(sc);
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->semantic3(sc2);
-    }
-
-    sc2->pop();
-
-    // don't do it for unused deprecated types
-    // or error types
-    if (!getRTInfo && Type::rtinfo &&
-        (!isDeprecated() || global.params.useDeprecated != DIAGNOSTICerror) &&
-        (type && type->ty != Terror))
-    {
-        // Evaluate: RTinfo!type
-        Objects *tiargs = new Objects();
-        tiargs->push(type);
-        TemplateInstance *ti = new TemplateInstance(loc, Type::rtinfo, tiargs);
-
-        Scope *sc3 = ti->tempdecl->_scope->startCTFE();
-        sc3->tinst = sc->tinst;
-        sc3->minst = sc->minst;
-        if (isDeprecated())
-            sc3->stc |= STCdeprecated;
-
-        ti->semantic(sc3);
-        ti->semantic2(sc3);
-        ti->semantic3(sc3);
-        Expression *e = resolve(Loc(), sc3, ti->toAlias(), false);
-
-        sc3->endCTFE();
-
-        e = e->ctfeInterpret();
-        getRTInfo = e;
-    }
-
-    if (sd)
-        sd->semanticTypeInfoMembers();
-    semanticRun = PASSsemantic3done;
-}
-
 /***************************************
  * Find all instance fields, then push them into `fields`.
  *
@@ -364,7 +281,7 @@ bool AggregateDeclaration::determineFields()
             AggregateDeclaration *ad = ((SV *)param)->agg;
 
             if (v->semanticRun < PASSsemanticdone)
-                v->semantic(NULL);
+                dsymbolSemantic(v, NULL);
             // Note: Aggregate fields or size could have determined during v->semantic.
             if (ad->sizeok != SIZEOKnone)
                 return 1;
@@ -437,7 +354,7 @@ bool AggregateDeclaration::determineSize(Loc loc)
     }
 
     if (_scope)
-        semantic(NULL);
+        dsymbolSemantic(this, NULL);
 
     // Determine the instance size of base class first.
     if (ClassDeclaration *cd = isClassDeclaration())
@@ -480,7 +397,7 @@ void StructDeclaration::semanticTypeInfoMembers()
         xeq->semanticRun < PASSsemantic3done)
     {
         unsigned errors = global.startGagging();
-        xeq->semantic3(xeq->_scope);
+        semantic3(xeq, xeq->_scope);
         if (global.endGagging(errors))
             xeq = xerreq;
     }
@@ -490,7 +407,7 @@ void StructDeclaration::semanticTypeInfoMembers()
         xcmp->semanticRun < PASSsemantic3done)
     {
         unsigned errors = global.startGagging();
-        xcmp->semantic3(xcmp->_scope);
+        semantic3(xcmp, xcmp->_scope);
         if (global.endGagging(errors))
             xcmp = xerrcmp;
     }
@@ -500,28 +417,28 @@ void StructDeclaration::semanticTypeInfoMembers()
         ftostr->_scope &&
         ftostr->semanticRun < PASSsemantic3done)
     {
-        ftostr->semantic3(ftostr->_scope);
+        semantic3(ftostr, ftostr->_scope);
     }
 
     if (xhash &&
         xhash->_scope &&
         xhash->semanticRun < PASSsemantic3done)
     {
-        xhash->semantic3(xhash->_scope);
+        semantic3(xhash, xhash->_scope);
     }
 
     if (postblit &&
         postblit->_scope &&
         postblit->semanticRun < PASSsemantic3done)
     {
-        postblit->semantic3(postblit->_scope);
+        semantic3(postblit, postblit->_scope);
     }
 
     if (dtor &&
         dtor->_scope &&
         dtor->semanticRun < PASSsemantic3done)
     {
-        dtor->semantic3(dtor->_scope);
+        semantic3(dtor, dtor->_scope);
     }
 }
 
@@ -964,7 +881,7 @@ Dsymbol *AggregateDeclaration::searchCtor()
             {
                 CtorDeclaration *f = s->isCtorDeclaration();
                 if (f && f->semanticRun == PASSinit)
-                    f->semantic(NULL);
+                    dsymbolSemantic(f, NULL);
                 return 0;
             }
         };
@@ -1020,227 +937,16 @@ Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
     return ScopeDsymbol::syntaxCopy(sd);
 }
 
-void StructDeclaration::semantic(Scope *sc)
-{
-    //printf("StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);
-
-    //static int count; if (++count == 20) halt();
-
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    unsigned errors = global.errors;
-
-    //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);
-    Scope *scx = NULL;
-    if (_scope)
-    {
-        sc = _scope;
-        scx = _scope;            // save so we don't make redundant copies
-        _scope = NULL;
-    }
-
-    if (!parent)
-    {
-        assert(sc->parent && sc->func);
-        parent = sc->parent;
-    }
-    assert(parent && !isAnonymous());
-
-    if (this->errors)
-        type = Type::terror;
-    if (semanticRun == PASSinit)
-        type = type->addSTC(sc->stc | storage_class);
-    type = type->semantic(loc, sc);
-
-    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
-    {
-        TemplateInstance *ti = ((TypeStruct *)type)->sym->isInstantiated();
-        if (ti && isError(ti))
-            ((TypeStruct *)type)->sym = this;
-    }
-
-    // Ungag errors when not speculative
-    Ungag ungag = ungagSpeculative();
-
-    if (semanticRun == PASSinit)
-    {
-        protection = sc->protection;
-
-        alignment = sc->alignment();
-
-        storage_class |= sc->stc;
-        if (storage_class & STCdeprecated)
-            isdeprecated = true;
-        if (storage_class & STCabstract)
-            error("structs, unions cannot be abstract");
-        userAttribDecl = sc->userAttribDecl;
-
-        if (sc->linkage == LINKcpp)
-            classKind = ClassKind::cpp;
-    }
-    else if (symtab && !scx)
-    {
-        return;
-    }
-    semanticRun = PASSsemantic;
-
-    if (!members)               // if opaque declaration
-    {
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-    if (!symtab)
-    {
-        symtab = new DsymbolTable();
-
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
-            s->addMember(sc, this);
-        }
-    }
-
-    Scope *sc2 = newScope(sc);
-
-    /* Set scope so if there are forward references, we still might be able to
-     * resolve individual members like enums.
-     */
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        //printf("struct: setScope %s %s\n", s->kind(), s->toChars());
-        s->setScope(sc2);
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->importAll(sc2);
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->semantic(sc2);
-    }
-
-    if (!determineFields())
-    {
-        assert(type->ty == Terror);
-        sc2->pop();
-        semanticRun = PASSsemanticdone;
-        return;
-    }
-
-    /* Following special member functions creation needs semantic analysis
-     * completion of sub-structs in each field types. For example, buildDtor
-     * needs to check existence of elaborate dtor in type of each fields.
-     * See the case in compilable/test14838.d
-     */
-    for (size_t i = 0; i < fields.length; i++)
-    {
-        VarDeclaration *v = fields[i];
-        Type *tb = v->type->baseElemOf();
-        if (tb->ty != Tstruct)
-            continue;
-        StructDeclaration *sd = ((TypeStruct *)tb)->sym;
-        if (sd->semanticRun >= PASSsemanticdone)
-            continue;
-
-        sc2->pop();
-
-        _scope = scx ? scx : sc->copy();
-        _scope->setNoFree();
-        _scope->_module->addDeferredSemantic(this);
-
-        //printf("\tdeferring %s\n", toChars());
-        return;
-    }
-
-    /* Look for special member functions.
-     */
-    aggNew =       (NewDeclaration *)search(Loc(), Id::classNew);
-    aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete);
-
-    // Look for the constructor
-    ctor = searchCtor();
-
-    dtor = buildDtor(this, sc2);
-    postblit = buildPostBlit(this, sc2);
-
-    buildOpAssign(this, sc2);
-    buildOpEquals(this, sc2);
-
-    if (global.params.useTypeInfo && Type::dtypeinfo)  // these functions are used for TypeInfo
-    {
-        xeq = buildXopEquals(this, sc2);
-        xcmp = buildXopCmp(this, sc2);
-        xhash = buildXtoHash(this, sc2);
-    }
-
-    inv = buildInv(this, sc2);
-
-    Module::dprogress++;
-    semanticRun = PASSsemanticdone;
-    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
-
-    sc2->pop();
-
-    if (ctor)
-    {
-        Dsymbol *scall = search(Loc(), Id::call);
-        if (scall)
-        {
-            unsigned xerrors = global.startGagging();
-            sc = sc->push();
-            sc->tinst = NULL;
-            sc->minst = NULL;
-            FuncDeclaration *fcall = resolveFuncCall(loc, sc, scall, NULL, NULL, NULL, 1);
-            sc = sc->pop();
-            global.endGagging(xerrors);
-
-            if (fcall && fcall->isStatic())
-            {
-                error(fcall->loc, "static opCall is hidden by constructors and can never be called");
-                errorSupplemental(fcall->loc, "Please use a factory method instead, or replace all constructors with static opCall.");
-            }
-        }
-    }
-
-    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
-    {
-        // https://issues.dlang.org/show_bug.cgi?id=19024
-        StructDeclaration *sd = ((TypeStruct *)type)->sym;
-        error("already exists at %s. Perhaps in another function with the same name?", sd->loc.toChars());
-    }
-
-    if (global.errors != errors)
-    {
-        // The type is no good.
-        type = Type::terror;
-        this->errors = true;
-        if (deferred)
-            deferred->errors = true;
-    }
-
-    if (deferred && !global.gag)
-    {
-        deferred->semantic2(sc);
-        deferred->semantic3(sc);
-    }
-}
-
 Dsymbol *StructDeclaration::search(const Loc &loc, Identifier *ident, int flags)
 {
     //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
 
     if (_scope && !symtab)
-        semantic(_scope);
+        dsymbolSemantic(this, _scope);
 
     if (!members || !symtab)    // opaque or semantic() is not yet called
     {
-        error("is forward referenced when looking for '%s'", ident->toChars());
+        error("is forward referenced when looking for `%s`", ident->toChars());
         return NULL;
     }
 
index 293484cae601b9185a299df6b8acecb9bc31cb29..89c55576a55f88dcde0edc76c36031ade26f5160 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -35,7 +35,6 @@
 bool symbolIsVisible(Dsymbol *origin, Dsymbol *s);
 typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
 int ScopeDsymbol_foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn = NULL);
-Expression *semantic(Expression *e, Scope *sc);
 
 
 /****************************** Dsymbol ******************************/
@@ -462,33 +461,6 @@ void Dsymbol::importAll(Scope *)
 {
 }
 
-/*************************************
- * Does semantic analysis on the public face of declarations.
- */
-
-void Dsymbol::semantic(Scope *)
-{
-    error("%p has no semantic routine", this);
-}
-
-/*************************************
- * Does semantic analysis on initializers and members of aggregates.
- */
-
-void Dsymbol::semantic2(Scope *)
-{
-    // Most Dsymbols have no further semantic analysis needed
-}
-
-/*************************************
- * Does semantic analysis on function bodies.
- */
-
-void Dsymbol::semantic3(Scope *)
-{
-    // Most Dsymbols have no further semantic analysis needed
-}
-
 /*********************************************
  * Search for ident as member of s.
  * Params:
@@ -553,7 +525,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
     {
         if (d->inuse)
         {
-            ::error(loc, "circular reference to '%s'", d->toPrettyChars());
+            ::error(loc, "circular reference to `%s`", d->toPrettyChars());
             return NULL;
         }
     }
@@ -575,10 +547,10 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
             {
                 sm = s->search_correct(ti->name);
                 if (sm)
-                    ::error(loc, "template identifier '%s' is not a member of %s '%s', did you mean %s '%s'?",
+                    ::error(loc, "template identifier `%s` is not a member of %s `%s`, did you mean %s `%s`?",
                           ti->name->toChars(), s->kind(), s->toPrettyChars(), sm->kind(), sm->toChars());
                 else
-                    ::error(loc, "template identifier '%s' is not a member of %s '%s'",
+                    ::error(loc, "template identifier `%s` is not a member of %s `%s`",
                           ti->name->toChars(), s->kind(), s->toPrettyChars());
                 return NULL;
             }
@@ -591,7 +563,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
             }
             ti->tempdecl = td;
             if (!ti->semanticRun)
-                ti->semantic(sc);
+                dsymbolSemantic(ti, sc);
             sm = ti->toAlias();
             break;
         }
@@ -612,7 +584,7 @@ bool Dsymbol::overloadInsert(Dsymbol *)
 
 d_uns64 Dsymbol::size(Loc)
 {
-    error("Dsymbol '%s' has no size", toChars());
+    error("Dsymbol `%s` has no size", toChars());
     return SIZE_INVALID;
 }
 
@@ -1015,10 +987,6 @@ void ForwardingScopeDsymbol::importScope(Dsymbol *s, Prot protection)
     forward->importScope(s, protection);
 }
 
-void ForwardingScopeDsymbol::semantic(Scope *)
-{
-}
-
 const char *ForwardingScopeDsymbol::kind() const
 {
     return "local scope";
@@ -1055,10 +1023,6 @@ Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
     return sds;
 }
 
-void ScopeDsymbol::semantic(Scope *)
-{
-}
-
 /*****************************************
  * This function is #1 on the list of functions that eat cpu time.
  * Be very, very careful about slowing it down.
@@ -1593,7 +1557,7 @@ Dsymbol *ArrayScopeSymbol::search(const Loc &loc, Identifier *ident, int)
             Expression *e = new IntegerExp(Loc(), td->objects->length, Type::tsize_t);
             v->_init = new ExpInitializer(Loc(), e);
             v->storage_class |= STCtemp | STCstatic | STCconst;
-            v->semantic(sc);
+            dsymbolSemantic(v, sc);
             return v;
         }
 
@@ -1605,7 +1569,7 @@ Dsymbol *ArrayScopeSymbol::search(const Loc &loc, Identifier *ident, int)
             Expression *e = new IntegerExp(Loc(), type->arguments->length, Type::tsize_t);
             v->_init = new ExpInitializer(Loc(), e);
             v->storage_class |= STCtemp | STCstatic | STCconst;
-            v->semantic(sc);
+            dsymbolSemantic(v, sc);
             return v;
         }
 
@@ -1709,7 +1673,7 @@ Dsymbol *ArrayScopeSymbol::search(const Loc &loc, Identifier *ident, int)
 
                     Objects *tiargs = new Objects();
                     Expression *edim = new IntegerExp(Loc(), dim, Type::tsize_t);
-                    edim = ::semantic(edim, sc);
+                    edim = expressionSemantic(edim, sc);
                     tiargs->push(edim);
                     e = new DotTemplateInstanceExp(loc, ce, td->ident, tiargs);
                 }
@@ -1729,7 +1693,7 @@ Dsymbol *ArrayScopeSymbol::search(const Loc &loc, Identifier *ident, int)
                     assert(d);
                     e = new DotVarExp(loc, ce, d);
                 }
-                e = ::semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 if (!e->type)
                     exp->error("%s has no value", e->toChars());
                 t = e->type->toBasetype();
@@ -1752,7 +1716,7 @@ Dsymbol *ArrayScopeSymbol::search(const Loc &loc, Identifier *ident, int)
             }
             *pvar = v;
         }
-        (*pvar)->semantic(sc);
+        dsymbolSemantic(*pvar, sc);
         return (*pvar);
     }
     return NULL;
index 6555f12e7b4bb75df707aed6f883b27a07ad32f1..1ddfe06e6a169a86860129c03e8ac5c9d0c751e9 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -83,6 +83,10 @@ struct Ungag
     ~Ungag() { global.gag = oldgag; }
 };
 
+void dsymbolSemantic(Dsymbol *dsym, Scope *sc);
+void semantic2(Dsymbol *dsym, Scope* sc);
+void semantic3(Dsymbol *dsym, Scope* sc);
+
 struct Prot
 {
     enum Kind
@@ -201,9 +205,6 @@ public:
     virtual void addMember(Scope *sc, ScopeDsymbol *sds);
     virtual void setScope(Scope *sc);
     virtual void importAll(Scope *sc);
-    virtual void semantic(Scope *sc);
-    virtual void semantic2(Scope *sc);
-    virtual void semantic3(Scope *sc);
     virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
     Dsymbol *search_correct(Identifier *id);
     Dsymbol *searchX(Loc loc, Scope *sc, RootObject *id);
@@ -320,7 +321,6 @@ public:
     static Dsymbol *getNth(Dsymbols *members, size_t nth, size_t *pn = NULL);
 
     ScopeDsymbol *isScopeDsymbol() { return this; }
-    void semantic(Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -382,7 +382,6 @@ public:
     Dsymbol *symtabInsert(Dsymbol *s);
     Dsymbol *symtabLookup(Dsymbol *s, Identifier *id);
     void importScope(Dsymbol *s, Prot protection);
-    void semantic(Scope *sc);
     const char *kind() const;
 
     ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return this; }
diff --git a/gcc/d/dmd/dsymbolsem.c b/gcc/d/dmd/dsymbolsem.c
new file mode 100644 (file)
index 0000000..5d5c9fc
--- /dev/null
@@ -0,0 +1,5486 @@
+
+/* Compiler implementation of the D programming language
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * written by Walter Bright
+ * http://www.digitalmars.com
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#include "root/dsystem.h"
+#include "root/aav.h"
+
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "aliasthis.h"
+#include "attrib.h"
+#include "cond.h"
+#include "declaration.h"
+#include "enum.h"
+#include "errors.h"
+#include "hdrgen.h"
+#include "id.h"
+#include "import.h"
+#include "init.h"
+#include "mars.h"
+#include "module.h"
+#include "nspace.h"
+#include "objc.h"
+#include "parse.h"
+#include "scope.h"
+#include "statement.h"
+#include "staticassert.h"
+#include "target.h"
+#include "template.h"
+#include "utf.h"
+#include "version.h"
+#include "visitor.h"
+
+bool allowsContractWithoutBody(FuncDeclaration *funcdecl);
+bool checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad, size_t istart = 0);
+VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
+Initializer *inferType(Initializer *init, Scope *sc);
+void MODtoBuffer(OutBuffer *buf, MOD mod);
+bool reliesOnTident(Type *t, TemplateParameters *tparams = NULL, size_t iStart = 0);
+Objc *objc();
+
+static unsigned setMangleOverride(Dsymbol *s, char *sym)
+{
+    AttribDeclaration *ad = s->isAttribDeclaration();
+
+    if (ad)
+    {
+        Dsymbols *decls = ad->include(NULL);
+        unsigned nestedCount = 0;
+
+        if (decls && decls->length)
+            for (size_t i = 0; i < decls->length; ++i)
+                nestedCount += setMangleOverride((*decls)[i], sym);
+
+        return nestedCount;
+    }
+    else if (s->isFuncDeclaration() || s->isVarDeclaration())
+    {
+        s->isDeclaration()->mangleOverride = sym;
+        return 1;
+    }
+    else
+        return 0;
+}
+
+/**********************************
+ * Decide if attributes for this function can be inferred from examining
+ * the function body.
+ * Returns:
+ *  true if can
+ */
+static bool canInferAttributes(FuncDeclaration *fd, Scope *sc)
+{
+    if (!fd->fbody)
+        return false;
+
+    if (fd->isVirtualMethod())
+        return false;               // since they may be overridden
+
+    if (sc->func &&
+        /********** this is for backwards compatibility for the moment ********/
+        (!fd->isMember() || (sc->func->isSafeBypassingInference() && !fd->isInstantiated())))
+        return true;
+
+    if (fd->isFuncLiteralDeclaration() ||               // externs are not possible with literals
+        (fd->storage_class & STCinference) ||           // do attribute inference
+        (fd->inferRetType && !fd->isCtorDeclaration()))
+        return true;
+
+    if (fd->isInstantiated())
+    {
+        TemplateInstance *ti = fd->parent->isTemplateInstance();
+        if (ti == NULL || ti->isTemplateMixin() || ti->tempdecl->ident == fd->ident)
+            return true;
+    }
+
+    return false;
+}
+
+/*****************************************
+ * Initialize for inferring the attributes of this function.
+ */
+static void initInferAttributes(FuncDeclaration *fd)
+{
+    //printf("initInferAttributes() for %s\n", toPrettyChars());
+    TypeFunction *tf = fd->type->toTypeFunction();
+    if (tf->purity == PUREimpure) // purity not specified
+        fd->flags |= FUNCFLAGpurityInprocess;
+
+    if (tf->trust == TRUSTdefault)
+        fd->flags |= FUNCFLAGsafetyInprocess;
+
+    if (!tf->isnothrow)
+        fd->flags |= FUNCFLAGnothrowInprocess;
+
+    if (!tf->isnogc)
+        fd->flags |= FUNCFLAGnogcInprocess;
+
+    if (!fd->isVirtual() || fd->introducing)
+        fd->flags |= FUNCFLAGreturnInprocess;
+
+    // Initialize for inferring STCscope
+    if (global.params.vsafe)
+        fd->flags |= FUNCFLAGinferScope;
+}
+
+static void badObjectDotD(ClassDeclaration *cd)
+{
+    cd->error("missing or corrupt object.d");
+    fatal();
+}
+
+/* Bugzilla 12078, 12143 and 15733:
+ * While resolving base classes and interfaces, a base may refer
+ * the member of this derived class. In that time, if all bases of
+ * this class can  be determined, we can go forward the semantc process
+ * beyond the Lancestorsdone. To do the recursive semantic analysis,
+ * temporarily set and unset `_scope` around exp().
+ */
+static Type *resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, Type *type)
+{
+    if (!scx)
+    {
+        scx = sc->copy();
+        scx->setNoFree();
+    }
+    cd->_scope = scx;
+    Type *t = typeSemantic(type, cd->loc, sc);
+    cd->_scope = NULL;
+    return t;
+}
+
+static void resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, ClassDeclaration *sym)
+{
+    if (!scx)
+    {
+        scx = sc->copy();
+        scx->setNoFree();
+    }
+    cd->_scope = scx;
+    dsymbolSemantic(sym, NULL);
+    cd->_scope = NULL;
+}
+
+class DsymbolSemanticVisitor : public Visitor
+{
+public:
+    Scope *sc;
+
+    DsymbolSemanticVisitor(Scope *sc)
+    {
+        this->sc = sc;
+    }
+
+    void visit(Dsymbol *dsym)
+    {
+        dsym->error("%p has no semantic routine", dsym);
+    }
+
+    void visit(ScopeDsymbol *) { }
+    void visit(Declaration *) { }
+
+    void visit(AliasThis *dsym)
+    {
+        if (dsym->semanticRun != PASSinit)
+            return;
+
+        if (dsym->_scope)
+        {
+            sc = dsym->_scope;
+            dsym->_scope = NULL;
+        }
+
+        if (!sc)
+            return;
+
+        dsym->semanticRun = PASSsemantic;
+
+        Dsymbol *p = sc->parent->pastMixin();
+        AggregateDeclaration *ad = p->isAggregateDeclaration();
+        if (!ad)
+        {
+            error(dsym->loc, "alias this can only be a member of aggregate, not %s %s",
+                p->kind(), p->toChars());
+            return;
+        }
+
+        assert(ad->members);
+        Dsymbol *s = ad->search(dsym->loc, dsym->ident);
+        if (!s)
+        {
+            s = sc->search(dsym->loc, dsym->ident, NULL);
+            if (s)
+                error(dsym->loc, "%s is not a member of %s", s->toChars(), ad->toChars());
+            else
+                error(dsym->loc, "undefined identifier %s", dsym->ident->toChars());
+            return;
+        }
+        else if (ad->aliasthis && s != ad->aliasthis)
+        {
+            error(dsym->loc, "there can be only one alias this");
+            return;
+        }
+
+        if (ad->type->ty == Tstruct && ((TypeStruct *)ad->type)->sym != ad)
+        {
+            AggregateDeclaration *ad2 = ((TypeStruct *)ad->type)->sym;
+            assert(ad2->type == Type::terror);
+            ad->aliasthis = ad2->aliasthis;
+            return;
+        }
+
+        /* disable the alias this conversion so the implicit conversion check
+         * doesn't use it.
+         */
+        ad->aliasthis = NULL;
+
+        Dsymbol *sx = s;
+        if (sx->isAliasDeclaration())
+            sx = sx->toAlias();
+        Declaration *d = sx->isDeclaration();
+        if (d && !d->isTupleDeclaration())
+        {
+            Type *t = d->type;
+            assert(t);
+            if (ad->type->implicitConvTo(t) > MATCHnomatch)
+            {
+                error(dsym->loc, "alias this is not reachable as %s already converts to %s", ad->toChars(), t->toChars());
+            }
+        }
+
+        ad->aliasthis = s;
+        dsym->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(AliasDeclaration *dsym)
+    {
+        if (dsym->semanticRun >= PASSsemanticdone)
+            return;
+        assert(dsym->semanticRun <= PASSsemantic);
+
+        dsym->storage_class |= sc->stc & STCdeprecated;
+        dsym->protection = sc->protection;
+        dsym->userAttribDecl = sc->userAttribDecl;
+
+        if (!sc->func && dsym->inNonRoot())
+            return;
+
+        aliasSemantic(dsym, sc);
+    }
+
+    void visit(VarDeclaration *dsym)
+    {
+        //if (dsym->semanticRun > PASSinit)
+        //    return;
+        //dsym->semanticRun = PASSsemantic;
+
+        if (dsym->semanticRun >= PASSsemanticdone)
+            return;
+
+        Scope *scx = NULL;
+        if (dsym->_scope)
+        {
+            sc = dsym->_scope;
+            scx = sc;
+            dsym->_scope = NULL;
+        }
+
+        if (!sc)
+            return;
+
+        dsym->semanticRun = PASSsemantic;
+
+        /* Pick up storage classes from context, but except synchronized,
+         * override, abstract, and final.
+         */
+        dsym->storage_class |= (sc->stc & ~(STCsynchronized | STCoverride | STCabstract | STCfinal));
+        if (dsym->storage_class & STCextern && dsym->_init)
+            dsym->error("extern symbols cannot have initializers");
+
+        dsym->userAttribDecl = sc->userAttribDecl;
+
+        AggregateDeclaration *ad = dsym->isThis();
+        if (ad)
+            dsym->storage_class |= ad->storage_class & STC_TYPECTOR;
+
+        /* If auto type inference, do the inference
+         */
+        int inferred = 0;
+        if (!dsym->type)
+        {
+            dsym->inuse++;
+
+            // Infering the type requires running semantic,
+            // so mark the scope as ctfe if required
+            bool needctfe = (dsym->storage_class & (STCmanifest | STCstatic)) != 0;
+            if (needctfe) sc = sc->startCTFE();
+
+            //printf("inferring type for %s with init %s\n", dsym->toChars(), dsym->_init->toChars());
+            dsym->_init = inferType(dsym->_init, sc);
+            dsym->type = initializerToExpression(dsym->_init)->type;
+
+            if (needctfe) sc = sc->endCTFE();
+
+            dsym->inuse--;
+            inferred = 1;
+
+            /* This is a kludge to support the existing syntax for RAII
+             * declarations.
+             */
+            dsym->storage_class &= ~STCauto;
+            dsym->originalType = dsym->type->syntaxCopy();
+        }
+        else
+        {
+            if (!dsym->originalType)
+                dsym->originalType = dsym->type->syntaxCopy();
+
+            /* Prefix function attributes of variable declaration can affect
+             * its type:
+             *      pure nothrow void function() fp;
+             *      static assert(is(typeof(fp) == void function() pure nothrow));
+             */
+            Scope *sc2 = sc->push();
+            sc2->stc |= (dsym->storage_class & STC_FUNCATTR);
+            dsym->inuse++;
+            dsym->type = typeSemantic(dsym->type, dsym->loc, sc2);
+            dsym->inuse--;
+            sc2->pop();
+        }
+        //printf(" semantic type = %s\n", dsym->type ? dsym->type->toChars() : "null");
+        if (dsym->type->ty == Terror)
+            dsym->errors = true;
+
+        dsym->type->checkDeprecated(dsym->loc, sc);
+        dsym->linkage = sc->linkage;
+        dsym->parent = sc->parent;
+        //printf("this = %p, parent = %p, '%s'\n", dsym, dsym->parent, dsym->parent->toChars());
+        dsym->protection = sc->protection;
+
+        /* If scope's alignment is the default, use the type's alignment,
+         * otherwise the scope overrrides.
+         */
+        dsym->alignment = sc->alignment();
+        if (dsym->alignment == STRUCTALIGN_DEFAULT)
+            dsym->alignment = dsym->type->alignment();          // use type's alignment
+
+        //printf("sc->stc = %x\n", sc->stc);
+        //printf("storage_class = x%x\n", dsym->storage_class);
+
+        if (global.params.vcomplex)
+            dsym->type->checkComplexTransition(dsym->loc);
+
+        // Calculate type size + safety checks
+        if (sc->func && !sc->intypeof)
+        {
+            if ((dsym->storage_class & STCgshared) && !dsym->isMember())
+            {
+                if (sc->func->setUnsafe())
+                    dsym->error("__gshared not allowed in safe functions; use shared");
+            }
+        }
+
+        Dsymbol *parent = dsym->toParent();
+
+        Type *tb = dsym->type->toBasetype();
+        Type *tbn = tb->baseElemOf();
+        if (tb->ty == Tvoid && !(dsym->storage_class & STClazy))
+        {
+            if (inferred)
+            {
+                dsym->error("type %s is inferred from initializer %s, and variables cannot be of type void",
+                    dsym->type->toChars(), dsym->_init->toChars());
+            }
+            else
+                dsym->error("variables cannot be of type void");
+            dsym->type = Type::terror;
+            tb = dsym->type;
+        }
+        if (tb->ty == Tfunction)
+        {
+            dsym->error("cannot be declared to be a function");
+            dsym->type = Type::terror;
+            tb = dsym->type;
+        }
+        if (tb->ty == Tstruct)
+        {
+            TypeStruct *ts = (TypeStruct *)tb;
+            if (!ts->sym->members)
+            {
+                dsym->error("no definition of struct %s", ts->toChars());
+            }
+        }
+        if ((dsym->storage_class & STCauto) && !inferred)
+            dsym->error("storage class `auto` has no effect if type is not inferred, did you mean `scope`?");
+
+        if (tb->ty == Ttuple)
+        {
+            /* Instead, declare variables for each of the tuple elements
+             * and add those.
+             */
+            TypeTuple *tt = (TypeTuple *)tb;
+            size_t nelems = Parameter::dim(tt->arguments);
+            Expression *ie = (dsym->_init && !dsym->_init->isVoidInitializer()) ? initializerToExpression(dsym->_init) : NULL;
+            if (ie)
+                ie = expressionSemantic(ie, sc);
+
+            if (nelems > 0 && ie)
+            {
+                Expressions *iexps = new Expressions();
+                iexps->push(ie);
+
+                Expressions *exps = new Expressions();
+
+                for (size_t pos = 0; pos < iexps->length; pos++)
+                {
+                Lexpand1:
+                    Expression *e = (*iexps)[pos];
+                    Parameter *arg = Parameter::getNth(tt->arguments, pos);
+                    arg->type = typeSemantic(arg->type, dsym->loc, sc);
+                    //printf("[%d] iexps->length = %d, ", pos, iexps->length);
+                    //printf("e = (%s %s, %s), ", Token::tochars[e->op], e->toChars(), e->type->toChars());
+                    //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars());
+
+                    if (e != ie)
+                    {
+                    if (iexps->length > nelems)
+                        goto Lnomatch;
+                    if (e->type->implicitConvTo(arg->type))
+                        continue;
+                    }
+
+                    if (e->op == TOKtuple)
+                    {
+                        TupleExp *te = (TupleExp *)e;
+                        if (iexps->length - 1 + te->exps->length > nelems)
+                            goto Lnomatch;
+
+                        iexps->remove(pos);
+                        iexps->insert(pos, te->exps);
+                        (*iexps)[pos] = Expression::combine(te->e0, (*iexps)[pos]);
+                        goto Lexpand1;
+                    }
+                    else if (isAliasThisTuple(e))
+                    {
+                        VarDeclaration *v = copyToTemp(0, "__tup", e);
+                        dsymbolSemantic(v, sc);
+                        VarExp *ve = new VarExp(dsym->loc, v);
+                        ve->type = e->type;
+
+                        exps->setDim(1);
+                        (*exps)[0] = ve;
+                        expandAliasThisTuples(exps, 0);
+
+                        for (size_t u = 0; u < exps->length ; u++)
+                        {
+                        Lexpand2:
+                            Expression *ee = (*exps)[u];
+                            arg = Parameter::getNth(tt->arguments, pos + u);
+                            arg->type = typeSemantic(arg->type, dsym->loc, sc);
+                            //printf("[%d+%d] exps->length = %d, ", pos, u, exps->length);
+                            //printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars());
+                            //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars());
+
+                            size_t iexps_dim = iexps->length - 1 + exps->length;
+                            if (iexps_dim > nelems)
+                                goto Lnomatch;
+                            if (ee->type->implicitConvTo(arg->type))
+                                continue;
+
+                            if (expandAliasThisTuples(exps, u) != -1)
+                                goto Lexpand2;
+                        }
+
+                        if ((*exps)[0] != ve)
+                        {
+                            Expression *e0 = (*exps)[0];
+                            (*exps)[0] = new CommaExp(dsym->loc, new DeclarationExp(dsym->loc, v), e0);
+                            (*exps)[0]->type = e0->type;
+
+                            iexps->remove(pos);
+                            iexps->insert(pos, exps);
+                            goto Lexpand1;
+                        }
+                    }
+                }
+                if (iexps->length < nelems)
+                    goto Lnomatch;
+
+                ie = new TupleExp(dsym->_init->loc, iexps);
+            }
+    Lnomatch:
+
+            if (ie && ie->op == TOKtuple)
+            {
+                TupleExp *te = (TupleExp *)ie;
+                size_t tedim = te->exps->length;
+                if (tedim != nelems)
+                {
+                    error(dsym->loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems);
+                    for (size_t u = tedim; u < nelems; u++) // fill dummy expression
+                        te->exps->push(new ErrorExp());
+                }
+            }
+
+            Objects *exps = new Objects();
+            exps->setDim(nelems);
+            for (size_t i = 0; i < nelems; i++)
+            {
+                Parameter *arg = Parameter::getNth(tt->arguments, i);
+
+                OutBuffer buf;
+                buf.printf("__%s_field_%llu", dsym->ident->toChars(), (ulonglong)i);
+                const char *name = buf.extractChars();
+                Identifier *id = Identifier::idPool(name);
+
+                Initializer *ti;
+                if (ie)
+                {
+                    Expression *einit = ie;
+                    if (ie->op == TOKtuple)
+                    {
+                        TupleExp *te = (TupleExp *)ie;
+                        einit = (*te->exps)[i];
+                        if (i == 0)
+                            einit = Expression::combine(te->e0, einit);
+                    }
+                    ti = new ExpInitializer(einit->loc, einit);
+                }
+                else
+                    ti = dsym->_init ? dsym->_init->syntaxCopy() : NULL;
+
+                VarDeclaration *v = new VarDeclaration(dsym->loc, arg->type, id, ti);
+                v->storage_class |= STCtemp | dsym->storage_class;
+                if (arg->storageClass & STCparameter)
+                    v->storage_class |= arg->storageClass;
+                //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
+                dsymbolSemantic(v, sc);
+
+                if (sc->scopesym)
+                {
+                    //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
+                    if (sc->scopesym->members)
+                        sc->scopesym->members->push(v);
+                }
+
+                Expression *e = new DsymbolExp(dsym->loc, v);
+                (*exps)[i] = e;
+            }
+            TupleDeclaration *v2 = new TupleDeclaration(dsym->loc, dsym->ident, exps);
+            v2->parent = dsym->parent;
+            v2->isexp = true;
+            dsym->aliassym = v2;
+            dsym->semanticRun = PASSsemanticdone;
+            return;
+        }
+
+        /* Storage class can modify the type
+         */
+        dsym->type = dsym->type->addStorageClass(dsym->storage_class);
+
+        /* Adjust storage class to reflect type
+         */
+        if (dsym->type->isConst())
+        {
+            dsym->storage_class |= STCconst;
+            if (dsym->type->isShared())
+                dsym->storage_class |= STCshared;
+        }
+        else if (dsym->type->isImmutable())
+            dsym->storage_class |= STCimmutable;
+        else if (dsym->type->isShared())
+            dsym->storage_class |= STCshared;
+        else if (dsym->type->isWild())
+            dsym->storage_class |= STCwild;
+
+        if (StorageClass stc = dsym->storage_class & (STCsynchronized | STCoverride | STCabstract | STCfinal))
+        {
+            if (stc == STCfinal)
+                dsym->error("cannot be final, perhaps you meant const?");
+            else
+            {
+                OutBuffer buf;
+                stcToBuffer(&buf, stc);
+                dsym->error("cannot be %s", buf.peekChars());
+            }
+            dsym->storage_class &= ~stc;  // strip off
+        }
+
+        if (dsym->storage_class & STCscope)
+        {
+            StorageClass stc = dsym->storage_class & (STCstatic | STCextern | STCmanifest | STCtls | STCgshared);
+            if (stc)
+            {
+                OutBuffer buf;
+                stcToBuffer(&buf, stc);
+                dsym->error("cannot be `scope` and `%s`", buf.peekChars());
+            }
+            else if (dsym->isMember())
+            {
+                dsym->error("field cannot be `scope`");
+            }
+            else if (!dsym->type->hasPointers())
+            {
+                dsym->storage_class &= ~STCscope;     // silently ignore; may occur in generic code
+            }
+        }
+
+        if (dsym->storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe))
+        {
+        }
+        else
+        {
+            AggregateDeclaration *aad = parent->isAggregateDeclaration();
+            if (aad)
+            {
+                if (global.params.vfield &&
+                    dsym->storage_class & (STCconst | STCimmutable) && dsym->_init && !dsym->_init->isVoidInitializer())
+                {
+                    const char *s = (dsym->storage_class & STCimmutable) ? "immutable" : "const";
+                    message(dsym->loc, "`%s.%s` is `%s` field", ad->toPrettyChars(), dsym->toChars(), s);
+                }
+                dsym->storage_class |= STCfield;
+                if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor)
+                {
+                    if (!dsym->isThisDeclaration() && !dsym->_init)
+                        aad->noDefaultCtor = true;
+                }
+            }
+
+            InterfaceDeclaration *id = parent->isInterfaceDeclaration();
+            if (id)
+            {
+                dsym->error("field not allowed in interface");
+            }
+            else if (aad && aad->sizeok == SIZEOKdone)
+            {
+                dsym->error("cannot be further field because it will change the determined %s size", aad->toChars());
+            }
+
+            /* Templates cannot add fields to aggregates
+             */
+            TemplateInstance *ti = parent->isTemplateInstance();
+            if (ti)
+            {
+                // Take care of nested templates
+                while (1)
+                {
+                    TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
+                    if (!ti2)
+                        break;
+                    ti = ti2;
+                }
+
+                // If it's a member template
+                AggregateDeclaration *ad2 = ti->tempdecl->isMember();
+                if (ad2 && dsym->storage_class != STCundefined)
+                {
+                    dsym->error("cannot use template to add field to aggregate `%s`", ad2->toChars());
+                }
+            }
+        }
+
+        if ((dsym->storage_class & (STCref | STCparameter | STCforeach | STCtemp | STCresult)) == STCref && dsym->ident != Id::This)
+        {
+            dsym->error("only parameters or foreach declarations can be ref");
+        }
+
+        if (dsym->type->hasWild())
+        {
+            if (dsym->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield) ||
+                dsym->isDataseg()
+                )
+            {
+                dsym->error("only parameters or stack based variables can be inout");
+            }
+            FuncDeclaration *func = sc->func;
+            if (func)
+            {
+                if (func->fes)
+                    func = func->fes->func;
+                bool isWild = false;
+                for (FuncDeclaration *fd = func; fd; fd = fd->toParent2()->isFuncDeclaration())
+                {
+                    if (((TypeFunction *)fd->type)->iswild)
+                    {
+                        isWild = true;
+                        break;
+                    }
+                }
+                if (!isWild)
+                {
+                    dsym->error("inout variables can only be declared inside inout functions");
+                }
+            }
+        }
+
+        if (!(dsym->storage_class & (STCctfe | STCref | STCresult)) && tbn->ty == Tstruct &&
+            ((TypeStruct *)tbn)->sym->noDefaultCtor)
+        {
+            if (!dsym->_init)
+            {
+                if (dsym->isField())
+                {
+                    /* For fields, we'll check the constructor later to make sure it is initialized
+                     */
+                    dsym->storage_class |= STCnodefaultctor;
+                }
+                else if (dsym->storage_class & STCparameter)
+                    ;
+                else
+                    dsym->error("default construction is disabled for type %s", dsym->type->toChars());
+            }
+        }
+
+        FuncDeclaration *fd = parent->isFuncDeclaration();
+        if (dsym->type->isscope() && !(dsym->storage_class & STCnodtor))
+        {
+            if (dsym->storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd)
+            {
+                dsym->error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope");
+            }
+
+            if (!(dsym->storage_class & STCscope))
+            {
+                if (!(dsym->storage_class & STCparameter) && dsym->ident != Id::withSym)
+                    dsym->error("reference to scope class must be scope");
+            }
+        }
+
+        // Calculate type size + safety checks
+        if (sc->func && !sc->intypeof)
+        {
+            if (dsym->_init && dsym->_init->isVoidInitializer() && dsym->type->hasPointers()) // get type size
+            {
+                if (sc->func->setUnsafe())
+                    dsym->error("void initializers for pointers not allowed in safe functions");
+            }
+            else if (!dsym->_init &&
+                     !(dsym->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield | STCparameter)) &&
+                     dsym->type->hasVoidInitPointers())
+            {
+                if (sc->func->setUnsafe())
+                    dsym->error("void initializers for pointers not allowed in safe functions");
+            }
+        }
+
+        if (!dsym->_init && !fd)
+        {
+            // If not mutable, initializable by constructor only
+            dsym->storage_class |= STCctorinit;
+        }
+
+        if (dsym->_init)
+            dsym->storage_class |= STCinit;     // remember we had an explicit initializer
+        else if (dsym->storage_class & STCmanifest)
+            dsym->error("manifest constants must have initializers");
+
+        bool isBlit = false;
+        d_uns64 sz = 0;
+        if (!dsym->_init && !sc->inunion && !(dsym->storage_class & (STCstatic | STCgshared | STCextern)) && fd &&
+            (!(dsym->storage_class & (STCfield | STCin | STCforeach | STCparameter | STCresult))
+             || (dsym->storage_class & STCout)) &&
+            (sz = dsym->type->size()) != 0)
+        {
+            // Provide a default initializer
+            //printf("Providing default initializer for '%s'\n", dsym->toChars());
+            if (sz == SIZE_INVALID && dsym->type->ty != Terror)
+                dsym->error("size of type %s is invalid", dsym->type->toChars());
+
+            Type *tv = dsym->type;
+            while (tv->ty == Tsarray)    // Don't skip Tenum
+                tv = tv->nextOf();
+            if (tv->needsNested())
+            {
+                /* Nested struct requires valid enclosing frame pointer.
+                 * In StructLiteralExp::toElem(), it's calculated.
+                 */
+                assert(tv->toBasetype()->ty == Tstruct);
+                checkFrameAccess(dsym->loc, sc, ((TypeStruct *)tbn)->sym);
+
+                Expression *e = tv->defaultInitLiteral(dsym->loc);
+                e = new BlitExp(dsym->loc, new VarExp(dsym->loc, dsym), e);
+                e = expressionSemantic(e, sc);
+                dsym->_init = new ExpInitializer(dsym->loc, e);
+                goto Ldtor;
+            }
+            if (tv->ty == Tstruct && ((TypeStruct *)tv)->sym->zeroInit == 1)
+            {
+                /* If a struct is all zeros, as a special case
+                 * set it's initializer to the integer 0.
+                 * In AssignExp::toElem(), we check for this and issue
+                 * a memset() to initialize the struct.
+                 * Must do same check in interpreter.
+                 */
+                Expression *e = new IntegerExp(dsym->loc, 0, Type::tint32);
+                e = new BlitExp(dsym->loc, new VarExp(dsym->loc, dsym), e);
+                e->type = dsym->type;         // don't type check this, it would fail
+                dsym->_init = new ExpInitializer(dsym->loc, e);
+                goto Ldtor;
+            }
+            if (dsym->type->baseElemOf()->ty == Tvoid)
+            {
+                dsym->error("%s does not have a default initializer", dsym->type->toChars());
+            }
+            else if (Expression *e = dsym->type->defaultInit(dsym->loc))
+            {
+                dsym->_init = new ExpInitializer(dsym->loc, e);
+            }
+            // Default initializer is always a blit
+            isBlit = true;
+        }
+
+        if (dsym->_init)
+        {
+            sc = sc->push();
+            sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCnogc | STCref | STCdisable);
+
+            ExpInitializer *ei = dsym->_init->isExpInitializer();
+            if (ei)     // Bugzilla 13424: Preset the required type to fail in FuncLiteralDeclaration::semantic3
+                ei->exp = inferType(ei->exp, dsym->type);
+
+            // If inside function, there is no semantic3() call
+            if (sc->func || sc->intypeof == 1)
+            {
+                // If local variable, use AssignExp to handle all the various
+                // possibilities.
+                if (fd &&
+                    !(dsym->storage_class & (STCmanifest | STCstatic | STCtls | STCgshared | STCextern)) &&
+                    !dsym->_init->isVoidInitializer())
+                {
+                    //printf("fd = '%s', var = '%s'\n", fd->toChars(), dsym->toChars());
+                    if (!ei)
+                    {
+                        ArrayInitializer *ai = dsym->_init->isArrayInitializer();
+                        Expression *e;
+                        if (ai && tb->ty == Taarray)
+                            e = ai->toAssocArrayLiteral();
+                        else
+                            e = initializerToExpression(dsym->_init);
+                        if (!e)
+                        {
+                            // Run semantic, but don't need to interpret
+                            dsym->_init = initializerSemantic(dsym->_init, sc, dsym->type, INITnointerpret);
+                            e = initializerToExpression(dsym->_init);
+                            if (!e)
+                            {
+                                dsym->error("is not a static and cannot have static initializer");
+                                e = new ErrorExp();
+                            }
+                        }
+                        ei = new ExpInitializer(dsym->_init->loc, e);
+                        dsym->_init = ei;
+                    }
+
+                    Expression *exp = ei->exp;
+                    Expression *e1 = new VarExp(dsym->loc, dsym);
+                    if (isBlit)
+                        exp = new BlitExp(dsym->loc, e1, exp);
+                    else
+                        exp = new ConstructExp(dsym->loc, e1, exp);
+                    dsym->canassign++;
+                    exp = expressionSemantic(exp, sc);
+                    dsym->canassign--;
+                    exp = exp->optimize(WANTvalue);
+
+                    if (exp->op == TOKerror)
+                    {
+                        dsym->_init = new ErrorInitializer();
+                        ei = NULL;
+                    }
+                    else
+                        ei->exp = exp;
+
+                    if (ei && dsym->isScope())
+                    {
+                        Expression *ex = ei->exp;
+                        while (ex->op == TOKcomma)
+                            ex = ((CommaExp *)ex)->e2;
+                        if (ex->op == TOKblit || ex->op == TOKconstruct)
+                            ex = ((AssignExp *)ex)->e2;
+                        if (ex->op == TOKnew)
+                        {
+                            // See if initializer is a NewExp that can be allocated on the stack
+                            NewExp *ne = (NewExp *)ex;
+                            if (dsym->type->toBasetype()->ty == Tclass)
+                            {
+                                if (ne->newargs && ne->newargs->length > 1)
+                                {
+                                    dsym->mynew = true;
+                                }
+                                else
+                                {
+                                    ne->onstack = true;
+                                    dsym->onstack = true;
+                                }
+                            }
+                        }
+                        else if (ex->op == TOKfunction)
+                        {
+                            // or a delegate that doesn't escape a reference to the function
+                            FuncDeclaration *f = ((FuncExp *)ex)->fd;
+                            f->tookAddressOf--;
+                        }
+                    }
+                }
+                else
+                {
+                    // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof
+                    dsym->_init = initializerSemantic(dsym->_init, sc, dsym->type, sc->intypeof == 1 ? INITnointerpret : INITinterpret);
+                }
+            }
+            else if (parent->isAggregateDeclaration())
+            {
+                dsym->_scope = scx ? scx : sc->copy();
+                dsym->_scope->setNoFree();
+            }
+            else if (dsym->storage_class & (STCconst | STCimmutable | STCmanifest) ||
+                     dsym->type->isConst() || dsym->type->isImmutable())
+            {
+                /* Because we may need the results of a const declaration in a
+                 * subsequent type, such as an array dimension, before semantic2()
+                 * gets ordinarily run, try to run semantic2() now.
+                 * Ignore failure.
+                 */
+
+                if (!inferred)
+                {
+                    unsigned errors = global.errors;
+                    dsym->inuse++;
+                    if (ei)
+                    {
+                        Expression *exp = ei->exp->syntaxCopy();
+
+                        bool needctfe = dsym->isDataseg() || (dsym->storage_class & STCmanifest);
+                        if (needctfe) sc = sc->startCTFE();
+                        exp = expressionSemantic(exp, sc);
+                        exp = resolveProperties(sc, exp);
+                        if (needctfe) sc = sc->endCTFE();
+
+                        Type *tb2 = dsym->type->toBasetype();
+                        Type *ti = exp->type->toBasetype();
+
+                        /* The problem is the following code:
+                         *  struct CopyTest {
+                         *     double x;
+                         *     this(double a) { x = a * 10.0;}
+                         *     this(this) { x += 2.0; }
+                         *  }
+                         *  const CopyTest z = CopyTest(5.3);  // ok
+                         *  const CopyTest w = z;              // not ok, postblit not run
+                         *  static assert(w.x == 55.0);
+                         * because the postblit doesn't get run on the initialization of w.
+                         */
+                        if (ti->ty == Tstruct)
+                        {
+                            StructDeclaration *sd = ((TypeStruct *)ti)->sym;
+                            /* Look to see if initializer involves a copy constructor
+                             * (which implies a postblit)
+                             */
+                             // there is a copy constructor
+                             // and exp is the same struct
+                            if (sd->postblit &&
+                                tb2->toDsymbol(NULL) == sd)
+                            {
+                                // The only allowable initializer is a (non-copy) constructor
+                                if (exp->isLvalue())
+                                    dsym->error("of type struct %s uses this(this), which is not allowed in static initialization", tb2->toChars());
+                            }
+                        }
+                        ei->exp = exp;
+                    }
+                    dsym->_init = initializerSemantic(dsym->_init, sc, dsym->type, INITinterpret);
+                    dsym->inuse--;
+                    if (global.errors > errors)
+                    {
+                        dsym->_init = new ErrorInitializer();
+                        dsym->type = Type::terror;
+                    }
+                }
+                else
+                {
+                    dsym->_scope = scx ? scx : sc->copy();
+                    dsym->_scope->setNoFree();
+                }
+            }
+            sc = sc->pop();
+        }
+
+    Ldtor:
+        /* Build code to execute destruction, if necessary
+         */
+        dsym->edtor = dsym->callScopeDtor(sc);
+        if (dsym->edtor)
+        {
+            if (sc->func && dsym->storage_class & (STCstatic | STCgshared))
+                dsym->edtor = expressionSemantic(dsym->edtor, sc->_module->_scope);
+            else
+                dsym->edtor = expressionSemantic(dsym->edtor, sc);
+
+    #if 0 // currently disabled because of std.stdio.stdin, stdout and stderr
+            if (dsym->isDataseg() && !(dsym->storage_class & STCextern))
+                dsym->error("static storage variables cannot have destructors");
+    #endif
+        }
+
+        dsym->semanticRun = PASSsemanticdone;
+
+        if (dsym->type->toBasetype()->ty == Terror)
+            dsym->errors = true;
+
+        if (sc->scopesym && !sc->scopesym->isAggregateDeclaration())
+        {
+            for (ScopeDsymbol *sym = sc->scopesym; sym && dsym->endlinnum == 0;
+                 sym = sym->parent ? sym->parent->isScopeDsymbol() : NULL)
+                dsym->endlinnum = sym->endlinnum;
+        }
+    }
+
+    void visit(TypeInfoDeclaration *dsym)
+    {
+        assert(dsym->linkage == LINKc);
+    }
+
+    void visit(Import *imp)
+    {
+        //printf("Import::semantic('%s') %s\n", toPrettyChars(), imp->id->toChars());
+        if (imp->semanticRun > PASSinit)
+            return;
+
+        if (imp->_scope)
+        {
+            sc = imp->_scope;
+            imp->_scope = NULL;
+        }
+        if (!sc)
+            return;
+
+        imp->semanticRun = PASSsemantic;
+
+        // Load if not already done so
+        if (!imp->mod)
+        {
+            imp->load(sc);
+            if (imp->mod)
+                imp->mod->importAll(NULL);
+        }
+
+        if (imp->mod)
+        {
+            // Modules need a list of each imported module
+            //printf("%s imports %s\n", sc->_module->toChars(), imp->mod->toChars());
+            sc->_module->aimports.push(imp->mod);
+
+            if (sc->explicitProtection)
+                imp->protection = sc->protection;
+
+            if (!imp->aliasId && !imp->names.length) // neither a selective nor a renamed import
+            {
+                ScopeDsymbol *scopesym = NULL;
+                if (sc->explicitProtection)
+                    imp->protection = sc->protection.kind;
+                for (Scope *scd = sc; scd; scd = scd->enclosing)
+                {
+                    if (!scd->scopesym)
+                        continue;
+                    scopesym = scd->scopesym;
+                    break;
+                }
+
+                if (!imp->isstatic)
+                {
+                    scopesym->importScope(imp->mod, imp->protection);
+                }
+
+                // Mark the imported packages as accessible from the current
+                // scope. This access check is necessary when using FQN b/c
+                // we're using a single global package tree. See Bugzilla 313.
+                if (imp->packages)
+                {
+                    // import a.b.c.d;
+                    Package *p = imp->pkg; // a
+                    scopesym->addAccessiblePackage(p, imp->protection);
+                    for (size_t i = 1; i < imp->packages->length; i++) // [b, c]
+                    {
+                        Identifier *id = (*imp->packages)[i];
+                        p = (Package *) p->symtab->lookup(id);
+                        scopesym->addAccessiblePackage(p, imp->protection);
+                    }
+                }
+                scopesym->addAccessiblePackage(imp->mod, imp->protection); // d
+            }
+
+            dsymbolSemantic(imp->mod, NULL);
+
+            if (imp->mod->needmoduleinfo)
+            {
+                //printf("module4 %s because of %s\n", sc->_module->toChars(), imp->mod->toChars());
+                sc->_module->needmoduleinfo = 1;
+            }
+
+            sc = sc->push(imp->mod);
+            sc->protection = imp->protection;
+            for (size_t i = 0; i < imp->aliasdecls.length; i++)
+            {
+                AliasDeclaration *ad = imp->aliasdecls[i];
+                //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), imp->aliases[i]->toChars(), imp->names[i]->toChars(), ad->_scope);
+                if (imp->mod->search(imp->loc, imp->names[i]))
+                {
+                    dsymbolSemantic(ad, sc);
+                    // If the import declaration is in non-root module,
+                    // analysis of the aliased symbol is deferred.
+                    // Therefore, don't see the ad->aliassym or ad->type here.
+                }
+                else
+                {
+                    Dsymbol *s = imp->mod->search_correct(imp->names[i]);
+                    if (s)
+                        imp->mod->error(imp->loc, "import `%s` not found, did you mean %s `%s`?", imp->names[i]->toChars(), s->kind(), s->toChars());
+                    else
+                        imp->mod->error(imp->loc, "import `%s` not found", imp->names[i]->toChars());
+                    ad->type = Type::terror;
+                }
+            }
+            sc = sc->pop();
+        }
+
+        imp->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 &&
+            !(imp->id == Id::object && sc->_module->ident == Id::object) &&
+            sc->_module->ident != Id::entrypoint &&
+            strcmp(sc->_module->ident->toChars(), "__main") != 0)
+        {
+            /* The grammar of the file is:
+             *      ImportDeclaration
+             *          ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
+             *      ModuleAliasIdentifier ] "\n"
+             *
+             *      BasicImportDeclaration
+             *          ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
+             *              " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
+             *
+             *      FilePath
+             *          - any string with '(', ')' and '\' escaped with the '\' character
+             */
+
+            OutBuffer *ob = global.params.moduleDeps;
+            Module* imod = sc->instantiatingModule();
+            if (!global.params.moduleDepsFile.length)
+                ob->writestring("depsImport ");
+            ob->writestring(imod->toPrettyChars());
+            ob->writestring(" (");
+            escapePath(ob,  imod->srcfile->toChars());
+            ob->writestring(") : ");
+
+            // use protection instead of sc->protection because it couldn't be
+            // resolved yet, see the comment above
+            protectionToBuffer(ob, imp->protection);
+            ob->writeByte(' ');
+            if (imp->isstatic)
+            {
+                stcToBuffer(ob, STCstatic);
+                ob->writeByte(' ');
+            }
+            ob->writestring(": ");
+
+            if (imp->packages)
+            {
+                for (size_t i = 0; i < imp->packages->length; i++)
+                {
+                    Identifier *pid = (*imp->packages)[i];
+                    ob->printf("%s.", pid->toChars());
+                }
+            }
+
+            ob->writestring(imp->id->toChars());
+            ob->writestring(" (");
+            if (imp->mod)
+                escapePath(ob, imp->mod->srcfile->toChars());
+            else
+                ob->writestring("???");
+            ob->writeByte(')');
+
+            for (size_t i = 0; i < imp->names.length; i++)
+            {
+                if (i == 0)
+                    ob->writeByte(':');
+                else
+                    ob->writeByte(',');
+
+                Identifier *name = imp->names[i];
+                Identifier *alias = imp->aliases[i];
+
+                if (!alias)
+                {
+                    ob->printf("%s", name->toChars());
+                    alias = name;
+                }
+                else
+                    ob->printf("%s=%s", alias->toChars(), name->toChars());
+            }
+
+            if (imp->aliasId)
+                    ob->printf(" -> %s", imp->aliasId->toChars());
+
+            ob->writenl();
+        }
+
+        //printf("-Import::semantic('%s'), pkg = %p\n", imp->toChars(), imp->pkg);
+    }
+
+    void attribSemantic(AttribDeclaration *ad)
+    {
+        if (ad->semanticRun != PASSinit)
+            return;
+        ad->semanticRun = PASSsemantic;
+        Dsymbols *d = ad->include(sc);
+        //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
+        if (d)
+        {
+            Scope *sc2 = ad->newScope(sc);
+            bool errors = false;
+            for (size_t i = 0; i < d->length; i++)
+            {
+                Dsymbol *s = (*d)[i];
+                dsymbolSemantic(s, sc2);
+                errors |= s->errors;
+            }
+            ad->errors |= errors;
+            if (sc2 != sc)
+                sc2->pop();
+        }
+        ad->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(AttribDeclaration *atd)
+    {
+        attribSemantic(atd);
+    }
+
+    void visit(AnonDeclaration *scd)
+    {
+        //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", scd);
+        assert(sc->parent);
+        Dsymbol *p = sc->parent->pastMixin();
+        AggregateDeclaration *ad = p->isAggregateDeclaration();
+        if (!ad)
+        {
+            error(scd->loc, "%s can only be a part of an aggregate, not %s %s",
+                scd->kind(), p->kind(), p->toChars());
+            scd->errors = true;
+            return;
+        }
+
+        if (scd->decl)
+        {
+            sc = sc->push();
+            sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
+            sc->inunion = scd->isunion;
+            sc->flags = 0;
+
+            for (size_t i = 0; i < scd->decl->length; i++)
+            {
+                Dsymbol *s = (*scd->decl)[i];
+                dsymbolSemantic(s, sc);
+            }
+            sc = sc->pop();
+        }
+    }
+
+    void visit(PragmaDeclaration *pd)
+    {
+        // Should be merged with PragmaStatement
+        //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
+        if (pd->ident == Id::msg)
+        {
+            if (pd->args)
+            {
+                for (size_t i = 0; i < pd->args->length; i++)
+                {
+                    Expression *e = (*pd->args)[i];
+
+                    sc = sc->startCTFE();
+                    e = expressionSemantic(e, sc);
+                    e = resolveProperties(sc, e);
+                    sc = sc->endCTFE();
+
+                    // pragma(msg) is allowed to contain types as well as expressions
+                    e = ctfeInterpretForPragmaMsg(e);
+                    if (e->op == TOKerror)
+                    {
+                        errorSupplemental(pd->loc, "while evaluating pragma(msg, %s)", (*pd->args)[i]->toChars());
+                        return;
+                    }
+                    StringExp *se = e->toStringExp();
+                    if (se)
+                    {
+                        se = se->toUTF8(sc);
+                        fprintf(stderr, "%.*s", (int)se->len, (char *)se->string);
+                    }
+                    else
+                        fprintf(stderr, "%s", e->toChars());
+                }
+                fprintf(stderr, "\n");
+            }
+            goto Lnodecl;
+        }
+        else if (pd->ident == Id::lib)
+        {
+            if (!pd->args || pd->args->length != 1)
+                pd->error("string expected for library name");
+            else
+            {
+                StringExp *se = semanticString(sc, (*pd->args)[0], "library name");
+                if (!se)
+                    goto Lnodecl;
+                (*pd->args)[0] = se;
+
+                char *name = (char *)mem.xmalloc(se->len + 1);
+                memcpy(name, se->string, se->len);
+                name[se->len] = 0;
+                if (global.params.verbose)
+                    message("library   %s", name);
+                if (global.params.moduleDeps && !global.params.moduleDepsFile.length)
+                {
+                    OutBuffer *ob = global.params.moduleDeps;
+                    Module *imod = sc->instantiatingModule();
+                    ob->writestring("depsLib ");
+                    ob->writestring(imod->toPrettyChars());
+                    ob->writestring(" (");
+                    escapePath(ob, imod->srcfile->toChars());
+                    ob->writestring(") : ");
+                    ob->writestring((char *) name);
+                    ob->writenl();
+                }
+                mem.xfree(name);
+            }
+            goto Lnodecl;
+        }
+        else if (pd->ident == Id::startaddress)
+        {
+            if (!pd->args || pd->args->length != 1)
+                pd->error("function name expected for start address");
+            else
+            {
+                /* Bugzilla 11980:
+                 * resolveProperties and ctfeInterpret call are not necessary.
+                 */
+                Expression *e = (*pd->args)[0];
+
+                sc = sc->startCTFE();
+                e = expressionSemantic(e, sc);
+                sc = sc->endCTFE();
+
+                (*pd->args)[0] = e;
+                Dsymbol *sa = getDsymbol(e);
+                if (!sa || !sa->isFuncDeclaration())
+                    pd->error("function name expected for start address, not `%s`", e->toChars());
+            }
+            goto Lnodecl;
+        }
+        else if (pd->ident == Id::Pinline)
+        {
+            goto Ldecl;
+        }
+        else if (pd->ident == Id::mangle)
+        {
+            if (!pd->args)
+                pd->args = new Expressions();
+            if (pd->args->length != 1)
+            {
+                pd->error("string expected for mangled name");
+                pd->args->setDim(1);
+                (*pd->args)[0] = new ErrorExp();    // error recovery
+                goto Ldecl;
+            }
+
+            StringExp *se = semanticString(sc, (*pd->args)[0], "mangled name");
+            if (!se)
+                goto Ldecl;
+            (*pd->args)[0] = se; // Will be used for later
+
+            if (!se->len)
+            {
+                pd->error("zero-length string not allowed for mangled name");
+                goto Ldecl;
+            }
+            if (se->sz != 1)
+            {
+                pd->error("mangled name characters can only be of type char");
+                goto Ldecl;
+            }
+
+            /* Note: D language specification should not have any assumption about backend
+             * implementation. Ideally pragma(mangle) can accept a string of any content.
+             *
+             * Therefore, this validation is compiler implementation specific.
+             */
+            for (size_t i = 0; i < se->len; )
+            {
+                utf8_t *p = (utf8_t *)se->string;
+                dchar_t c = p[i];
+                if (c < 0x80)
+                {
+                    if ((c >= 'A' && c <= 'Z') ||
+                        (c >= 'a' && c <= 'z') ||
+                        (c >= '0' && c <= '9') ||
+                        (c != 0 && strchr("$%().:?@[]_", c)))
+                    {
+                        ++i;
+                        continue;
+                    }
+                    else
+                    {
+                        pd->error("char 0x%02x not allowed in mangled name", c);
+                        break;
+                    }
+                }
+
+                if (const char* msg = utf_decodeChar((utf8_t *)se->string, se->len, &i, &c))
+                {
+                    pd->error("%s", msg);
+                    break;
+                }
+
+                if (!isUniAlpha(c))
+                {
+                    pd->error("char 0x%04x not allowed in mangled name", c);
+                    break;
+                }
+            }
+        }
+        else if (global.params.ignoreUnsupportedPragmas)
+        {
+            if (global.params.verbose)
+            {
+                /* Print unrecognized pragmas
+                 */
+                OutBuffer buf;
+                buf.writestring(pd->ident->toChars());
+                if (pd->args)
+                {
+                    for (size_t i = 0; i < pd->args->length; i++)
+                    {
+                        Expression *e = (*pd->args)[i];
+
+                        sc = sc->startCTFE();
+                        e = expressionSemantic(e, sc);
+                        e = resolveProperties(sc, e);
+                        sc = sc->endCTFE();
+
+                        e = e->ctfeInterpret();
+                        if (i == 0)
+                            buf.writestring(" (");
+                        else
+                            buf.writeByte(',');
+                        buf.writestring(e->toChars());
+                    }
+                    if (pd->args->length)
+                        buf.writeByte(')');
+                }
+                message("pragma    %s", buf.peekChars());
+            }
+            goto Lnodecl;
+        }
+        else
+            error(pd->loc, "unrecognized pragma(%s)", pd->ident->toChars());
+
+    Ldecl:
+        if (pd->decl)
+        {
+            Scope *sc2 = pd->newScope(sc);
+
+            for (size_t i = 0; i < pd->decl->length; i++)
+            {
+                Dsymbol *s = (*pd->decl)[i];
+
+                dsymbolSemantic(s, sc2);
+
+                if (pd->ident == Id::mangle)
+                {
+                    assert(pd->args && pd->args->length == 1);
+                    if (StringExp *se = (*pd->args)[0]->toStringExp())
+                    {
+                        char *name = (char *)mem.xmalloc(se->len + 1);
+                        memcpy(name, se->string, se->len);
+                        name[se->len] = 0;
+
+                        unsigned cnt = setMangleOverride(s, name);
+                        if (cnt > 1)
+                            pd->error("can only apply to a single declaration");
+                    }
+                }
+            }
+
+            if (sc2 != sc)
+                sc2->pop();
+        }
+        return;
+
+    Lnodecl:
+        if (pd->decl)
+        {
+            pd->error("pragma is missing closing `;`");
+            goto Ldecl; // do them anyway, to avoid segfaults.
+        }
+    }
+
+    void visit(StaticIfDeclaration *sid)
+    {
+        attribSemantic(sid);
+    }
+
+    void visit(StaticForeachDeclaration *sfd)
+    {
+        attribSemantic(sfd);
+    }
+
+    Dsymbols *compileIt(CompileDeclaration *cd)
+    {
+        //printf("CompileDeclaration::compileIt(loc = %d) %s\n", cd->loc.linnum, cd->exp->toChars());
+        StringExp *se = semanticString(sc, cd->exp, "argument to mixin");
+        if (!se)
+            return NULL;
+        se = se->toUTF8(sc);
+
+        unsigned errors = global.errors;
+        Parser p(cd->loc, sc->_module, (utf8_t *)se->string, se->len, 0);
+        p.nextToken();
+
+        Dsymbols *d = p.parseDeclDefs(0);
+        if (global.errors != errors)
+            return NULL;
+
+        if (p.token.value != TOKeof)
+        {
+            cd->exp->error("incomplete mixin declaration (%s)", se->toChars());
+            return NULL;
+        }
+        return d;
+    }
+
+    void visit(CompileDeclaration *cd)
+    {
+        //printf("CompileDeclaration::semantic()\n");
+        if (!cd->compiled)
+        {
+            cd->decl = compileIt(cd);
+            cd->AttribDeclaration::addMember(sc, cd->scopesym);
+            cd->compiled = true;
+
+            if (cd->_scope && cd->decl)
+            {
+                for (size_t i = 0; i < cd->decl->length; i++)
+                {
+                    Dsymbol *s = (*cd->decl)[i];
+                    s->setScope(cd->_scope);
+                }
+            }
+        }
+        attribSemantic(cd);
+    }
+
+    void visit(UserAttributeDeclaration *uad)
+    {
+        //printf("UserAttributeDeclaration::semantic() %p\n", this);
+        if (uad->decl && !uad->_scope)
+            uad->Dsymbol::setScope(sc);  // for function local symbols
+
+        attribSemantic(uad);
+    }
+
+    void visit(StaticAssert *sa)
+    {
+            if (sa->semanticRun < PASSsemanticdone)
+                sa->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(DebugSymbol *ds)
+    {
+        //printf("DebugSymbol::semantic() %s\n", ds->toChars());
+        if (ds->semanticRun < PASSsemanticdone)
+            ds->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(VersionSymbol *vs)
+    {
+        if (vs->semanticRun < PASSsemanticdone)
+            vs->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(Package *pkg)
+    {
+        if (pkg->semanticRun < PASSsemanticdone)
+            pkg->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(Module *m)
+    {
+        if (m->semanticRun != PASSinit)
+            return;
+
+        //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, m->toChars(), parent);
+        m->semanticRun = PASSsemantic;
+
+        // Note that modules get their own scope, from scratch.
+        // This is so regardless of where in the syntax a module
+        // gets imported, it is unaffected by context.
+        Scope *sc = m->_scope;                  // see if already got one from importAll()
+        if (!sc)
+        {
+            Scope::createGlobal(m);      // create root scope
+        }
+
+        //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
+
+        // Pass 1 semantic routines: do public side of the definition
+        for (size_t i = 0; i < m->members->length; i++)
+        {
+            Dsymbol *s = (*m->members)[i];
+
+            //printf("\tModule('%s'): '%s'.semantic()\n", m->toChars(), s->toChars());
+            dsymbolSemantic(s, sc);
+            m->runDeferredSemantic();
+        }
+
+        if (m->userAttribDecl)
+        {
+            dsymbolSemantic(m->userAttribDecl, sc);
+        }
+
+        if (!m->_scope)
+        {
+            sc = sc->pop();
+            sc->pop();              // 2 pops because Scope::createGlobal() created 2
+        }
+        m->semanticRun = PASSsemanticdone;
+        //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", m, m->toChars(), parent);
+    }
+
+    void visit(EnumDeclaration *ed)
+    {
+        //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), ed->toChars());
+        //printf("EnumDeclaration::semantic() %p %s\n", ed, ed->toChars());
+        if (ed->semanticRun >= PASSsemanticdone)
+            return;             // semantic() already completed
+        if (ed->semanticRun == PASSsemantic)
+        {
+            assert(ed->memtype);
+            error(ed->loc, "circular reference to enum base type %s", ed->memtype->toChars());
+            ed->errors = true;
+            ed->semanticRun = PASSsemanticdone;
+            return;
+        }
+        unsigned dprogress_save = Module::dprogress;
+
+        Scope *scx = NULL;
+        if (ed->_scope)
+        {
+            sc = ed->_scope;
+            scx = ed->_scope;            // save so we don't make redundant copies
+            ed->_scope = NULL;
+        }
+
+        if (!sc)
+            return;
+
+        ed->parent = sc->parent;
+        ed->type = typeSemantic(ed->type, ed->loc, sc);
+
+        ed->protection = sc->protection;
+        if (sc->stc & STCdeprecated)
+            ed->isdeprecated = true;
+        ed->userAttribDecl = sc->userAttribDecl;
+
+        ed->semanticRun = PASSsemantic;
+
+        if (!ed->members && !ed->memtype)               // enum ident;
+        {
+            ed->semanticRun = PASSsemanticdone;
+            return;
+        }
+
+        if (!ed->symtab)
+            ed->symtab = new DsymbolTable();
+
+        /* The separate, and distinct, cases are:
+         *  1. enum { ... }
+         *  2. enum : memtype { ... }
+         *  3. enum ident { ... }
+         *  4. enum ident : memtype { ... }
+         *  5. enum ident : memtype;
+         *  6. enum ident;
+         */
+
+        if (ed->memtype)
+        {
+            ed->memtype = typeSemantic(ed->memtype, ed->loc, sc);
+
+            /* Check to see if memtype is forward referenced
+             */
+            if (ed->memtype->ty == Tenum)
+            {
+                EnumDeclaration *sym = (EnumDeclaration *)ed->memtype->toDsymbol(sc);
+                if (!sym->memtype || !sym->members || !sym->symtab || sym->_scope)
+                {
+                    // memtype is forward referenced, so try again later
+                    ed->_scope = scx ? scx : sc->copy();
+                    ed->_scope->setNoFree();
+                    ed->_scope->_module->addDeferredSemantic(ed);
+                    Module::dprogress = dprogress_save;
+                    //printf("\tdeferring %s\n", ed->toChars());
+                    ed->semanticRun = PASSinit;
+                    return;
+                }
+            }
+            if (ed->memtype->ty == Tvoid)
+            {
+                ed->error("base type must not be void");
+                ed->memtype = Type::terror;
+            }
+            if (ed->memtype->ty == Terror)
+            {
+                ed->errors = true;
+                if (ed->members)
+                {
+                    for (size_t i = 0; i < ed->members->length; i++)
+                    {
+                        Dsymbol *s = (*ed->members)[i];
+                        s->errors = true;               // poison all the members
+                    }
+                }
+                ed->semanticRun = PASSsemanticdone;
+                return;
+            }
+        }
+
+        ed->semanticRun = PASSsemanticdone;
+
+        if (!ed->members)               // enum ident : memtype;
+            return;
+
+        if (ed->members->length == 0)
+        {
+            ed->error("enum %s must have at least one member", ed->toChars());
+            ed->errors = true;
+            return;
+        }
+
+        Module::dprogress++;
+
+        Scope *sce;
+        if (ed->isAnonymous())
+            sce = sc;
+        else
+        {
+            sce = sc->push(ed);
+            sce->parent = ed;
+        }
+        sce = sce->startCTFE();
+        sce->setNoFree();                   // needed for getMaxMinValue()
+
+        /* Each enum member gets the sce scope
+         */
+        for (size_t i = 0; i < ed->members->length; i++)
+        {
+            EnumMember *em = (*ed->members)[i]->isEnumMember();
+            if (em)
+                em->_scope = sce;
+        }
+
+        if (!ed->added)
+        {
+            /* addMember() is not called when the EnumDeclaration appears as a function statement,
+             * so we have to do what addMember() does and install the enum members in the right symbol
+             * table
+             */
+            ScopeDsymbol *scopesym = NULL;
+            if (ed->isAnonymous())
+            {
+                /* Anonymous enum members get added to enclosing scope.
+                 */
+                for (Scope *sct = sce; 1; sct = sct->enclosing)
+                {
+                    assert(sct);
+                    if (sct->scopesym)
+                    {
+                        scopesym = sct->scopesym;
+                        if (!sct->scopesym->symtab)
+                            sct->scopesym->symtab = new DsymbolTable();
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                // Otherwise enum members are in the EnumDeclaration's symbol table
+                scopesym = ed;
+            }
+
+            for (size_t i = 0; i < ed->members->length; i++)
+            {
+                EnumMember *em = (*ed->members)[i]->isEnumMember();
+                if (em)
+                {
+                    em->ed = ed;
+                    em->addMember(sc, scopesym);
+                }
+            }
+        }
+
+        for (size_t i = 0; i < ed->members->length; i++)
+        {
+            EnumMember *em = (*ed->members)[i]->isEnumMember();
+            if (em)
+                dsymbolSemantic(em, em->_scope);
+        }
+        //printf("defaultval = %lld\n", defaultval);
+
+        //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
+        //printf("members = %s\n", ed->members->toChars());
+    }
+
+    void visit(EnumMember *em)
+    {
+        //printf("EnumMember::semantic() %s\n", em->toChars());
+        if (em->errors || em->semanticRun >= PASSsemanticdone)
+            return;
+        if (em->semanticRun == PASSsemantic)
+        {
+            em->error("circular reference to enum member");
+        Lerrors:
+            em->errors = true;
+            em->semanticRun = PASSsemanticdone;
+            return;
+        }
+        assert(em->ed);
+
+        dsymbolSemantic(em->ed, sc);
+        if (em->ed->errors)
+            goto Lerrors;
+
+        if (em->errors || em->semanticRun >= PASSsemanticdone)
+            return;
+
+        if (em->_scope)
+            sc = em->_scope;
+        if (!sc)
+            return;
+
+        em->semanticRun = PASSsemantic;
+
+        em->protection = em->ed->isAnonymous() ? em->ed->protection : Prot(Prot::public_);
+        em->linkage = LINKd;
+        em->storage_class |= STCmanifest;
+
+        // https://issues.dlang.org/show_bug.cgi?id=9701
+        if (em->ed->isAnonymous())
+        {
+            if (em->userAttribDecl)
+                em->userAttribDecl->userAttribDecl = em->ed->userAttribDecl;
+            else
+                em->userAttribDecl = em->ed->userAttribDecl;
+        }
+
+        // The first enum member is special
+        bool first = (em == (*em->ed->members)[0]);
+
+        if (em->origType)
+        {
+            em->origType = typeSemantic(em->origType, em->loc, sc);
+            em->type = em->origType;
+            assert(em->value());          // "type id;" is not a valid enum member declaration
+        }
+
+        if (em->value())
+        {
+            Expression *e = em->value();
+            assert(e->dyncast() == DYNCAST_EXPRESSION);
+            e = expressionSemantic(e, sc);
+            e = resolveProperties(sc, e);
+            e = e->ctfeInterpret();
+            if (e->op == TOKerror)
+                goto Lerrors;
+            if (first && !em->ed->memtype && !em->ed->isAnonymous())
+            {
+                em->ed->memtype = e->type;
+                if (em->ed->memtype->ty == Terror)
+                {
+                    em->ed->errors = true;
+                    goto Lerrors;
+                }
+                if (em->ed->memtype->ty != Terror)
+                {
+                    /* Bugzilla 11746: All of named enum members should have same type
+                     * with the first member. If the following members were referenced
+                     * during the first member semantic, their types should be unified.
+                     */
+                    for (size_t i = 0; i < em->ed->members->length; i++)
+                    {
+                        EnumMember *enm = (*em->ed->members)[i]->isEnumMember();
+                        if (!enm || enm == em || enm->semanticRun < PASSsemanticdone || enm->origType)
+                            continue;
+
+                        //printf("[%d] enm = %s, enm->semanticRun = %d\n", i, enm->toChars(), enm->semanticRun);
+                        Expression *ev = enm->value();
+                        ev = ev->implicitCastTo(sc, em->ed->memtype);
+                        ev = ev->ctfeInterpret();
+                        ev = ev->castTo(sc, em->ed->type);
+                        if (ev->op == TOKerror)
+                            em->ed->errors = true;
+                        enm->value() = ev;
+                    }
+                    if (em->ed->errors)
+                    {
+                        em->ed->memtype = Type::terror;
+                        goto Lerrors;
+                    }
+                }
+            }
+
+            if (em->ed->memtype && !em->origType)
+            {
+                e = e->implicitCastTo(sc, em->ed->memtype);
+                e = e->ctfeInterpret();
+
+                // save origValue for better json output
+                em->origValue = e;
+
+                if (!em->ed->isAnonymous())
+                {
+                    e = e->castTo(sc, em->ed->type);
+                    e = e->ctfeInterpret();
+                }
+            }
+            else if (em->origType)
+            {
+                e = e->implicitCastTo(sc, em->origType);
+                e = e->ctfeInterpret();
+                assert(em->ed->isAnonymous());
+
+                // save origValue for better json output
+                em->origValue = e;
+            }
+            em->value() = e;
+        }
+        else if (first)
+        {
+            Type *t;
+            if (em->ed->memtype)
+                t = em->ed->memtype;
+            else
+            {
+                t = Type::tint32;
+                if (!em->ed->isAnonymous())
+                    em->ed->memtype = t;
+            }
+            Expression *e = new IntegerExp(em->loc, 0, Type::tint32);
+            e = e->implicitCastTo(sc, t);
+            e = e->ctfeInterpret();
+
+            // save origValue for better json output
+            em->origValue = e;
+
+            if (!em->ed->isAnonymous())
+            {
+                e = e->castTo(sc, em->ed->type);
+                e = e->ctfeInterpret();
+            }
+            em->value() = e;
+        }
+        else
+        {
+            /* Find the previous enum member,
+             * and set this to be the previous value + 1
+             */
+            EnumMember *emprev = NULL;
+            for (size_t i = 0; i < em->ed->members->length; i++)
+            {
+                EnumMember *enm = (*em->ed->members)[i]->isEnumMember();
+                if (enm)
+                {
+                    if (enm == em)
+                        break;
+                    emprev = enm;
+                }
+            }
+            assert(emprev);
+            if (emprev->semanticRun < PASSsemanticdone)    // if forward reference
+                dsymbolSemantic(emprev, emprev->_scope);    // resolve it
+            if (emprev->errors)
+                goto Lerrors;
+
+            Expression *eprev = emprev->value();
+            Type *tprev = eprev->type->equals(em->ed->type) ? em->ed->memtype : eprev->type;
+
+            Expression *emax = tprev->getProperty(em->ed->loc, Id::max, 0);
+            emax = expressionSemantic(emax, sc);
+            emax = emax->ctfeInterpret();
+
+            // Set value to (eprev + 1).
+            // But first check that (eprev != emax)
+            assert(eprev);
+            Expression *e = new EqualExp(TOKequal, em->loc, eprev, emax);
+            e = expressionSemantic(e, sc);
+            e = e->ctfeInterpret();
+            if (e->toInteger())
+            {
+                em->error("initialization with (%s.%s + 1) causes overflow for type `%s`", emprev->ed->toChars(), emprev->toChars(), em->ed->type->toBasetype()->toChars());
+                goto Lerrors;
+            }
+
+            // Now set e to (eprev + 1)
+            e = new AddExp(em->loc, eprev, new IntegerExp(em->loc, 1, Type::tint32));
+            e = expressionSemantic(e, sc);
+            e = e->castTo(sc, eprev->type);
+            e = e->ctfeInterpret();
+
+            // save origValue (without cast) for better json output
+            if (e->op != TOKerror)  // avoid duplicate diagnostics
+            {
+                assert(emprev->origValue);
+                em->origValue = new AddExp(em->loc, emprev->origValue, new IntegerExp(em->loc, 1, Type::tint32));
+                em->origValue = expressionSemantic(em->origValue, sc);
+                em->origValue = em->origValue->ctfeInterpret();
+            }
+
+            if (e->op == TOKerror)
+                goto Lerrors;
+            if (e->type->isfloating())
+            {
+                // Check that e != eprev (not always true for floats)
+                Expression *etest = new EqualExp(TOKequal, em->loc, e, eprev);
+                etest = expressionSemantic(etest, sc);
+                etest = etest->ctfeInterpret();
+                if (etest->toInteger())
+                {
+                    em->error("has inexact value, due to loss of precision");
+                    goto Lerrors;
+                }
+            }
+            em->value() = e;
+        }
+        if (!em->origType)
+            em->type = em->value()->type;
+
+        assert(em->origValue);
+        em->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(TemplateDeclaration *tempdecl)
+    {
+        if (tempdecl->semanticRun != PASSinit)
+            return;         // semantic() already run
+
+        // Remember templates defined in module object that we need to know about
+        if (sc->_module && sc->_module->ident == Id::object)
+        {
+            if (tempdecl->ident == Id::RTInfo)
+                Type::rtinfo = tempdecl;
+        }
+
+        /* Remember Scope for later instantiations, but make
+         * a copy since attributes can change.
+         */
+        if (!tempdecl->_scope)
+        {
+            tempdecl->_scope = sc->copy();
+            tempdecl->_scope->setNoFree();
+        }
+
+        tempdecl->semanticRun = PASSsemantic;
+
+        tempdecl->parent = sc->parent;
+        tempdecl->protection = sc->protection;
+        tempdecl->isstatic = tempdecl->toParent()->isModule() || (tempdecl->_scope->stc & STCstatic);
+
+        if (!tempdecl->isstatic)
+        {
+            if (AggregateDeclaration *ad = tempdecl->parent->pastMixin()->isAggregateDeclaration())
+                ad->makeNested();
+        }
+
+        // Set up scope for parameters
+        ScopeDsymbol *paramsym = new ScopeDsymbol();
+        paramsym->parent = tempdecl->parent;
+        Scope *paramscope = sc->push(paramsym);
+        paramscope->stc = 0;
+
+        if (global.params.doDocComments)
+        {
+            tempdecl->origParameters = new TemplateParameters();
+            tempdecl->origParameters->setDim(tempdecl->parameters->length);
+            for (size_t i = 0; i < tempdecl->parameters->length; i++)
+            {
+                TemplateParameter *tp = (*tempdecl->parameters)[i];
+                (*tempdecl->origParameters)[i] = tp->syntaxCopy();
+            }
+        }
+
+        for (size_t i = 0; i < tempdecl->parameters->length; i++)
+        {
+            TemplateParameter *tp = (*tempdecl->parameters)[i];
+
+            if (!tp->declareParameter(paramscope))
+            {
+                error(tp->loc, "parameter `%s` multiply defined", tp->ident->toChars());
+                tempdecl->errors = true;
+            }
+            if (!tpsemantic(tp, paramscope, tempdecl->parameters))
+            {
+                tempdecl->errors = true;
+            }
+            if (i + 1 != tempdecl->parameters->length && tp->isTemplateTupleParameter())
+            {
+                tempdecl->error("template tuple parameter must be last one");
+                tempdecl->errors = true;
+            }
+        }
+
+        /* Calculate TemplateParameter::dependent
+         */
+        TemplateParameters tparams;
+        tparams.setDim(1);
+        for (size_t i = 0; i < tempdecl->parameters->length; i++)
+        {
+            TemplateParameter *tp = (*tempdecl->parameters)[i];
+            tparams[0] = tp;
+
+            for (size_t j = 0; j < tempdecl->parameters->length; j++)
+            {
+                // Skip cases like: X(T : T)
+                if (i == j)
+                    continue;
+
+                if (TemplateTypeParameter *ttp = (*tempdecl->parameters)[j]->isTemplateTypeParameter())
+                {
+                    if (reliesOnTident(ttp->specType, &tparams))
+                        tp->dependent = true;
+                }
+                else if (TemplateAliasParameter *tap = (*tempdecl->parameters)[j]->isTemplateAliasParameter())
+                {
+                    if (reliesOnTident(tap->specType, &tparams) ||
+                        reliesOnTident(isType(tap->specAlias), &tparams))
+                    {
+                        tp->dependent = true;
+                    }
+                }
+            }
+        }
+
+        paramscope->pop();
+
+        // Compute again
+        tempdecl->onemember = NULL;
+        if (tempdecl->members)
+        {
+            Dsymbol *s;
+            if (Dsymbol::oneMembers(tempdecl->members, &s, tempdecl->ident) && s)
+            {
+                tempdecl->onemember = s;
+                s->parent = tempdecl;
+            }
+        }
+
+        /* BUG: should check:
+         *  o no virtual functions or non-static data members of classes
+         */
+        tempdecl->semanticRun = PASSsemanticdone;
+    }
+
+    void visit(TemplateInstance *ti)
+    {
+        templateInstanceSemantic(ti, sc, NULL);
+    }
+
+    void visit(TemplateMixin *tm)
+    {
+        if (tm->semanticRun != PASSinit)
+        {
+            // When a class/struct contains mixin members, and is done over
+            // because of forward references, never reach here so semanticRun
+            // has been reset to PASSinit.
+            return;
+        }
+        tm->semanticRun = PASSsemantic;
+
+        Scope *scx = NULL;
+        if (tm->_scope)
+        {
+            sc = tm->_scope;
+            scx = tm->_scope;            // save so we don't make redundant copies
+            tm->_scope = NULL;
+        }
+
+        /* Run semantic on each argument, place results in tiargs[],
+         * then find best match template with tiargs
+         */
+        if (!tm->findTempDecl(sc) ||
+            !tm->semanticTiargs(sc) ||
+            !tm->findBestMatch(sc, NULL))
+        {
+            if (tm->semanticRun == PASSinit)    // forward reference had occured
+            {
+                //printf("forward reference - deferring\n");
+                tm->_scope = scx ? scx : sc->copy();
+                tm->_scope->setNoFree();
+                tm->_scope->_module->addDeferredSemantic(tm);
+                return;
+            }
+
+            tm->inst = tm;
+            tm->errors = true;
+            return;         // error recovery
+        }
+        TemplateDeclaration *tempdecl = tm->tempdecl->isTemplateDeclaration();
+        assert(tempdecl);
+
+        if (!tm->ident)
+        {
+            /* Assign scope local unique identifier, as same as lambdas.
+             */
+            const char *s = "__mixin";
+
+            if (FuncDeclaration *func = sc->parent->isFuncDeclaration())
+            {
+                tm->symtab = func->localsymtab;
+                if (tm->symtab)
+                {
+                    // Inside template constraint, symtab is not set yet.
+                    goto L1;
+                }
+            }
+            else
+            {
+                tm->symtab = sc->parent->isScopeDsymbol()->symtab;
+            L1:
+                assert(tm->symtab);
+                int num = (int)dmd_aaLen(tm->symtab->tab) + 1;
+                tm->ident = Identifier::generateId(s, num);
+                tm->symtab->insert(tm);
+            }
+        }
+
+        tm->inst = tm;
+        tm->parent = sc->parent;
+
+        /* Detect recursive mixin instantiations.
+         */
+        for (Dsymbol *s = tm->parent; s; s = s->parent)
+        {
+            //printf("\ts = '%s'\n", s->toChars());
+            TemplateMixin *tmix = s->isTemplateMixin();
+            if (!tmix || tempdecl != tmix->tempdecl)
+                continue;
+
+            /* Different argument list lengths happen with variadic args
+             */
+            if (tm->tiargs->length != tmix->tiargs->length)
+                continue;
+
+            for (size_t i = 0; i < tm->tiargs->length; i++)
+            {
+                RootObject *o = (*tm->tiargs)[i];
+                Type *ta = isType(o);
+                Expression *ea = isExpression(o);
+                Dsymbol *sa = isDsymbol(o);
+                RootObject *tmo = (*tmix->tiargs)[i];
+                if (ta)
+                {
+                    Type *tmta = isType(tmo);
+                    if (!tmta)
+                        goto Lcontinue;
+                    if (!ta->equals(tmta))
+                        goto Lcontinue;
+                }
+                else if (ea)
+                {
+                    Expression *tme = isExpression(tmo);
+                    if (!tme || !ea->equals(tme))
+                        goto Lcontinue;
+                }
+                else if (sa)
+                {
+                    Dsymbol *tmsa = isDsymbol(tmo);
+                    if (sa != tmsa)
+                        goto Lcontinue;
+                }
+                else
+                    assert(0);
+            }
+            tm->error("recursive mixin instantiation");
+            return;
+
+        Lcontinue:
+            continue;
+        }
+
+        // Copy the syntax trees from the TemplateDeclaration
+        tm->members = Dsymbol::arraySyntaxCopy(tempdecl->members);
+        if (!tm->members)
+            return;
+
+        tm->symtab = new DsymbolTable();
+
+        for (Scope *sce = sc; 1; sce = sce->enclosing)
+        {
+            ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym;
+            if (sds)
+            {
+                sds->importScope(tm, Prot(Prot::public_));
+                break;
+            }
+        }
+
+        Scope *scy = sc->push(tm);
+        scy->parent = tm;
+
+        tm->argsym = new ScopeDsymbol();
+        tm->argsym->parent = scy->parent;
+        Scope *argscope = scy->push(tm->argsym);
+
+        unsigned errorsave = global.errors;
+
+        // Declare each template parameter as an alias for the argument type
+        tm->declareParameters(argscope);
+
+        // Add members to enclosing scope, as well as this scope
+        for (size_t i = 0; i < tm->members->length; i++)
+        {
+            Dsymbol *s = (*tm->members)[i];
+            s->addMember(argscope, tm);
+            //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
+            //printf("s->parent = %s\n", s->parent->toChars());
+        }
+
+        // Do semantic() analysis on template instance members
+        Scope *sc2 = argscope->push(tm);
+        //size_t deferred_dim = Module::deferred.length;
+
+        static int nest;
+        //printf("%d\n", nest);
+        if (++nest > global.recursionLimit)
+        {
+            global.gag = 0;                 // ensure error message gets printed
+            tm->error("recursive expansion");
+            fatal();
+        }
+
+        for (size_t i = 0; i < tm->members->length; i++)
+        {
+            Dsymbol *s = (*tm->members)[i];
+            s->setScope(sc2);
+        }
+
+        for (size_t i = 0; i < tm->members->length; i++)
+        {
+            Dsymbol *s = (*tm->members)[i];
+            s->importAll(sc2);
+        }
+
+        for (size_t i = 0; i < tm->members->length; i++)
+        {
+            Dsymbol *s = (*tm->members)[i];
+            dsymbolSemantic(s, sc2);
+        }
+
+        nest--;
+
+        /* In DeclDefs scope, TemplateMixin does not have to handle deferred symbols.
+         * Because the members would already call Module::addDeferredSemantic() for themselves.
+         * See Struct, Class, Interface, and EnumDeclaration::semantic().
+         */
+        //if (!sc->func && Module::deferred.length > deferred_dim) {}
+
+        AggregateDeclaration *ad = tm->toParent()->isAggregateDeclaration();
+        if (sc->func && !ad)
+        {
+            semantic2(tm, sc2);
+            semantic3(tm, sc2);
+        }
+
+        // Give additional context info if error occurred during instantiation
+        if (global.errors != errorsave)
+        {
+            tm->error("error instantiating");
+            tm->errors = true;
+        }
+
+        sc2->pop();
+        argscope->pop();
+        scy->pop();
+    }
+
+    void visit(Nspace *ns)
+    {
+        if (ns->semanticRun != PASSinit)
+            return;
+        if (ns->_scope)
+        {
+            sc = ns->_scope;
+            ns->_scope = NULL;
+        }
+        if (!sc)
+            return;
+
+        ns->semanticRun = PASSsemantic;
+        ns->parent = sc->parent;
+        if (ns->members)
+        {
+            assert(sc);
+            sc = sc->push(ns);
+            sc->linkage = LINKcpp;          // note that namespaces imply C++ linkage
+            sc->parent = ns;
+
+            for (size_t i = 0; i < ns->members->length; i++)
+            {
+                Dsymbol *s = (*ns->members)[i];
+                s->importAll(sc);
+            }
+
+            for (size_t i = 0; i < ns->members->length; i++)
+            {
+                Dsymbol *s = (*ns->members)[i];
+                dsymbolSemantic(s, sc);
+            }
+            sc->pop();
+        }
+        ns->semanticRun = PASSsemanticdone;
+    }
+
+    void funcDeclarationSemantic(FuncDeclaration *funcdecl)
+    {
+        TypeFunction *f;
+        AggregateDeclaration *ad;
+        InterfaceDeclaration *id;
+
+        if (funcdecl->semanticRun != PASSinit && funcdecl->isFuncLiteralDeclaration())
+        {
+            /* Member functions that have return types that are
+             * forward references can have semantic() run more than
+             * once on them.
+             * See test\interface2.d, test20
+             */
+            return;
+        }
+
+        if (funcdecl->semanticRun >= PASSsemanticdone)
+            return;
+        assert(funcdecl->semanticRun <= PASSsemantic);
+        funcdecl->semanticRun = PASSsemantic;
+
+        if (funcdecl->_scope)
+        {
+            sc = funcdecl->_scope;
+            funcdecl->_scope = NULL;
+        }
+
+        if (!sc || funcdecl->errors)
+            return;
+
+        funcdecl->parent = sc->parent;
+        Dsymbol *parent = funcdecl->toParent();
+
+        funcdecl->foverrides.setDim(0);       // reset in case semantic() is being retried for this function
+
+        funcdecl->storage_class |= sc->stc & ~STCref;
+        ad = funcdecl->isThis();
+        // Don't nest structs b/c of generated methods which should not access the outer scopes.
+        // https://issues.dlang.org/show_bug.cgi?id=16627
+        if (ad && !funcdecl->generated)
+        {
+            funcdecl->storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
+            ad->makeNested();
+        }
+        if (sc->func)
+            funcdecl->storage_class |= sc->func->storage_class & STCdisable;
+        // Remove prefix storage classes silently.
+        if ((funcdecl->storage_class & STC_TYPECTOR) && !(ad || funcdecl->isNested()))
+            funcdecl->storage_class &= ~STC_TYPECTOR;
+
+        //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", funcdecl->storage_class, sc->stc, Declaration::isFinal());
+
+        FuncLiteralDeclaration *fld = funcdecl->isFuncLiteralDeclaration();
+        if (fld && fld->treq)
+        {
+            Type *treq = fld->treq;
+            assert(treq->nextOf()->ty == Tfunction);
+            if (treq->ty == Tdelegate)
+                fld->tok = TOKdelegate;
+            else if (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction)
+                fld->tok = TOKfunction;
+            else
+                assert(0);
+            funcdecl->linkage = treq->nextOf()->toTypeFunction()->linkage;
+        }
+        else
+            funcdecl->linkage = sc->linkage;
+        funcdecl->inlining = sc->inlining;
+        funcdecl->protection = sc->protection;
+        funcdecl->userAttribDecl = sc->userAttribDecl;
+
+        if (!funcdecl->originalType)
+            funcdecl->originalType = funcdecl->type->syntaxCopy();
+        if (funcdecl->type->ty != Tfunction)
+        {
+            if (funcdecl->type->ty != Terror)
+            {
+                funcdecl->error("%s must be a function instead of %s", funcdecl->toChars(), funcdecl->type->toChars());
+                funcdecl->type = Type::terror;
+            }
+            funcdecl->errors = true;
+            return;
+        }
+        if (!funcdecl->type->deco)
+        {
+            sc = sc->push();
+            sc->stc |= funcdecl->storage_class & (STCdisable | STCdeprecated);  // forward to function type
+            TypeFunction *tf = funcdecl->type->toTypeFunction();
+
+            if (sc->func)
+            {
+                /* If the nesting parent is pure without inference,
+                 * then this function defaults to pure too.
+                 *
+                 *  auto foo() pure {
+                 *    auto bar() {}     // become a weak purity funciton
+                 *    class C {         // nested class
+                 *      auto baz() {}   // become a weak purity funciton
+                 *    }
+                 *
+                 *    static auto boo() {}   // typed as impure
+                 *    // Even though, boo cannot call any impure functions.
+                 *    // See also Expression::checkPurity().
+                 *  }
+                 */
+                if (tf->purity == PUREimpure && (funcdecl->isNested() || funcdecl->isThis()))
+                {
+                    FuncDeclaration *fd = NULL;
+                    for (Dsymbol *p = funcdecl->toParent2(); p; p = p->toParent2())
+                    {
+                        if (AggregateDeclaration *adx = p->isAggregateDeclaration())
+                        {
+                            if (adx->isNested())
+                                continue;
+                            break;
+                        }
+                        if ((fd = p->isFuncDeclaration()) != NULL)
+                            break;
+                    }
+
+                    /* If the parent's purity is inferred, then this function's purity needs
+                     * to be inferred first.
+                     */
+                    if (fd && fd->isPureBypassingInference() >= PUREweak &&
+                        !funcdecl->isInstantiated())
+                    {
+                        tf->purity = PUREfwdref;            // default to pure
+                    }
+                }
+            }
+
+            if (tf->isref)      sc->stc |= STCref;
+            if (tf->isscope)    sc->stc |= STCscope;
+            if (tf->isnothrow)  sc->stc |= STCnothrow;
+            if (tf->isnogc)     sc->stc |= STCnogc;
+            if (tf->isproperty) sc->stc |= STCproperty;
+            if (tf->purity == PUREfwdref)   sc->stc |= STCpure;
+            if (tf->trust != TRUSTdefault)
+                sc->stc &= ~(STCsafe | STCsystem | STCtrusted);
+            if (tf->trust == TRUSTsafe)     sc->stc |= STCsafe;
+            if (tf->trust == TRUSTsystem)   sc->stc |= STCsystem;
+            if (tf->trust == TRUSTtrusted)  sc->stc |= STCtrusted;
+
+            if (funcdecl->isCtorDeclaration())
+            {
+                sc->flags |= SCOPEctor;
+
+                Type *tret = ad->handleType();
+                assert(tret);
+                tret = tret->addStorageClass(funcdecl->storage_class | sc->stc);
+                tret = tret->addMod(funcdecl->type->mod);
+                tf->next = tret;
+
+                if (ad->isStructDeclaration())
+                    sc->stc |= STCref;
+            }
+
+            // 'return' on a non-static class member function implies 'scope' as well
+            if (ad && ad->isClassDeclaration() && (tf->isreturn || sc->stc & STCreturn) && !(sc->stc & STCstatic))
+                sc->stc |= STCscope;
+
+            // If 'this' has no pointers, remove 'scope' as it has no meaning
+            if (sc->stc & STCscope && ad && ad->isStructDeclaration() && !ad->type->hasPointers())
+            {
+                sc->stc &= ~STCscope;
+                tf->isscope = false;
+            }
+
+            sc->linkage = funcdecl->linkage;
+
+            if (!tf->isNaked() && !(funcdecl->isThis() || funcdecl->isNested()))
+            {
+                OutBuffer buf;
+                MODtoBuffer(&buf, tf->mod);
+                funcdecl->error("without `this` cannot be %s", buf.peekChars());
+                tf->mod = 0;    // remove qualifiers
+            }
+
+            /* Apply const, immutable, wild and shared storage class
+             * to the function type. Do this before type semantic.
+             */
+            StorageClass stc = funcdecl->storage_class;
+            if (funcdecl->type->isImmutable())
+                stc |= STCimmutable;
+            if (funcdecl->type->isConst())
+                stc |= STCconst;
+            if (funcdecl->type->isShared() || funcdecl->storage_class & STCsynchronized)
+                stc |= STCshared;
+            if (funcdecl->type->isWild())
+                stc |= STCwild;
+            switch (stc & STC_TYPECTOR)
+            {
+                case STCimmutable:
+                case STCimmutable | STCconst:
+                case STCimmutable | STCwild:
+                case STCimmutable | STCwild | STCconst:
+                case STCimmutable | STCshared:
+                case STCimmutable | STCshared | STCconst:
+                case STCimmutable | STCshared | STCwild:
+                case STCimmutable | STCshared | STCwild | STCconst:
+                    // Don't use immutableOf(), as that will do a merge()
+                    funcdecl->type = funcdecl->type->makeImmutable();
+                    break;
+
+                case STCconst:
+                    funcdecl->type = funcdecl->type->makeConst();
+                    break;
+
+                case STCwild:
+                    funcdecl->type = funcdecl->type->makeWild();
+                    break;
+
+                case STCwild | STCconst:
+                    funcdecl->type = funcdecl->type->makeWildConst();
+                    break;
+
+                case STCshared:
+                    funcdecl->type = funcdecl->type->makeShared();
+                    break;
+
+                case STCshared | STCconst:
+                    funcdecl->type = funcdecl->type->makeSharedConst();
+                    break;
+
+                case STCshared | STCwild:
+                    funcdecl->type = funcdecl->type->makeSharedWild();
+                    break;
+
+                case STCshared | STCwild | STCconst:
+                    funcdecl->type = funcdecl->type->makeSharedWildConst();
+                    break;
+
+                case 0:
+                    break;
+
+                default:
+                    assert(0);
+            }
+
+            funcdecl->type = typeSemantic(funcdecl->type, funcdecl->loc, sc);
+            sc = sc->pop();
+        }
+        if (funcdecl->type->ty != Tfunction)
+        {
+            if (funcdecl->type->ty != Terror)
+            {
+                funcdecl->error("%s must be a function instead of %s", funcdecl->toChars(), funcdecl->type->toChars());
+                funcdecl->type = Type::terror;
+            }
+            funcdecl->errors = true;
+            return;
+        }
+        else
+        {
+            // Merge back function attributes into 'originalType'.
+            // It's used for mangling, ddoc, and json output.
+            TypeFunction *tfo = funcdecl->originalType->toTypeFunction();
+            TypeFunction *tfx = funcdecl->type->toTypeFunction();
+            tfo->mod        = tfx->mod;
+            tfo->isscope    = tfx->isscope;
+            tfo->isscopeinferred = tfx->isscopeinferred;
+            tfo->isref      = tfx->isref;
+            tfo->isnothrow  = tfx->isnothrow;
+            tfo->isnogc     = tfx->isnogc;
+            tfo->isproperty = tfx->isproperty;
+            tfo->purity     = tfx->purity;
+            tfo->trust      = tfx->trust;
+
+            funcdecl->storage_class &= ~(STC_TYPECTOR | STC_FUNCATTR);
+        }
+
+        f = (TypeFunction *)funcdecl->type;
+
+        if ((funcdecl->storage_class & STCauto) && !f->isref && !funcdecl->inferRetType)
+            funcdecl->error("storage class `auto` has no effect if return type is not inferred");
+        /* Functions can only be 'scope' if they have a 'this'
+         */
+        if (f->isscope && !funcdecl->isNested() && !ad)
+        {
+            funcdecl->error("functions cannot be scope");
+        }
+
+        if (f->isreturn && !funcdecl->needThis() && !funcdecl->isNested())
+        {
+            /* Non-static nested functions have a hidden 'this' pointer to which
+             * the 'return' applies
+             */
+            funcdecl->error("static member has no `this` to which `return` can apply");
+        }
+
+        if (funcdecl->isAbstract() && !funcdecl->isVirtual())
+        {
+            const char *sfunc;
+            if (funcdecl->isStatic())
+                sfunc = "static";
+            else if (funcdecl->protection.kind == Prot::private_ || funcdecl->protection.kind == Prot::package_)
+                sfunc = protectionToChars(funcdecl->protection.kind);
+            else
+                sfunc = "non-virtual";
+            funcdecl->error("%s functions cannot be abstract", sfunc);
+        }
+
+        if (funcdecl->isOverride() && !funcdecl->isVirtual())
+        {
+            Prot::Kind kind = funcdecl->prot().kind;
+            if ((kind == Prot::private_ || kind == Prot::package_) && funcdecl->isMember())
+                funcdecl->error("%s method is not virtual and cannot override", protectionToChars(kind));
+            else
+                funcdecl->error("cannot override a non-virtual function");
+        }
+
+        if (funcdecl->isAbstract() && funcdecl->isFinalFunc())
+            funcdecl->error("cannot be both final and abstract");
+
+        id = parent->isInterfaceDeclaration();
+        if (id)
+        {
+            funcdecl->storage_class |= STCabstract;
+
+            if (funcdecl->isCtorDeclaration() ||
+                funcdecl->isPostBlitDeclaration() ||
+                funcdecl->isDtorDeclaration() ||
+                funcdecl->isInvariantDeclaration() ||
+                funcdecl->isNewDeclaration() || funcdecl->isDelete())
+                funcdecl->error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface %s", id->toChars());
+            if (funcdecl->fbody && funcdecl->isVirtual())
+                funcdecl->error("function body only allowed in final functions in interface %s", id->toChars());
+        }
+
+        if (UnionDeclaration *ud = parent->isUnionDeclaration())
+        {
+            if (funcdecl->isPostBlitDeclaration() ||
+                funcdecl->isDtorDeclaration() ||
+                funcdecl->isInvariantDeclaration())
+                funcdecl->error("destructors, postblits and invariants are not allowed in union %s", ud->toChars());
+        }
+
+        if (parent->isStructDeclaration())
+        {
+            if (funcdecl->isCtorDeclaration())
+            {
+                goto Ldone;
+            }
+        }
+
+        if (ClassDeclaration *cd = parent->isClassDeclaration())
+        {
+            if (funcdecl->isCtorDeclaration())
+            {
+                goto Ldone;
+            }
+
+            if (funcdecl->storage_class & STCabstract)
+                cd->isabstract = ABSyes;
+
+            // if static function, do not put in vtbl[]
+            if (!funcdecl->isVirtual())
+            {
+                //printf("\tnot virtual\n");
+                goto Ldone;
+            }
+            // Suppress further errors if the return type is an error
+            if (funcdecl->type->nextOf() == Type::terror)
+                goto Ldone;
+
+            bool may_override = false;
+            for (size_t i = 0; i < cd->baseclasses->length; i++)
+            {
+                BaseClass *b = (*cd->baseclasses)[i];
+                ClassDeclaration *cbd = b->type->toBasetype()->isClassHandle();
+                if (!cbd)
+                    continue;
+                for (size_t j = 0; j < cbd->vtbl.length; j++)
+                {
+                    FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration();
+                    if (!f2 || f2->ident != funcdecl->ident)
+                        continue;
+                    if (cbd->parent && cbd->parent->isTemplateInstance())
+                    {
+                        if (!f2->functionSemantic())
+                            goto Ldone;
+                    }
+                    may_override = true;
+                }
+            }
+            if (may_override && funcdecl->type->nextOf() == NULL)
+            {
+                /* If same name function exists in base class but 'this' is auto return,
+                 * cannot find index of base class's vtbl[] to override.
+                 */
+                funcdecl->error("return type inference is not supported if may override base class function");
+            }
+
+            /* Find index of existing function in base class's vtbl[] to override
+             * (the index will be the same as in cd's current vtbl[])
+             */
+            int vi = cd->baseClass ? funcdecl->findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.length)
+                                   : -1;
+
+            bool doesoverride = false;
+            switch (vi)
+            {
+                case -1:
+            Lintro:
+                    /* Didn't find one, so
+                     * This is an 'introducing' function which gets a new
+                     * slot in the vtbl[].
+                     */
+
+                    // Verify this doesn't override previous final function
+                    if (cd->baseClass)
+                    {
+                        Dsymbol *s = cd->baseClass->search(funcdecl->loc, funcdecl->ident);
+                        if (s)
+                        {
+                            FuncDeclaration *f2 = s->isFuncDeclaration();
+                            if (f2)
+                            {
+                                f2 = f2->overloadExactMatch(funcdecl->type);
+                                if (f2 && f2->isFinalFunc() && f2->prot().kind != Prot::private_)
+                                    funcdecl->error("cannot override final function %s", f2->toPrettyChars());
+                            }
+                        }
+                    }
+
+                    /* These quirky conditions mimic what VC++ appears to do
+                     */
+                    if (global.params.mscoff && cd->isCPPclass() &&
+                        cd->baseClass && cd->baseClass->vtbl.length)
+                    {
+                        /* if overriding an interface function, then this is not
+                         * introducing and don't put it in the class vtbl[]
+                         */
+                        funcdecl->interfaceVirtual = funcdecl->overrideInterface();
+                        if (funcdecl->interfaceVirtual)
+                        {
+                            //printf("\tinterface function %s\n", funcdecl->toChars());
+                            cd->vtblFinal.push(funcdecl);
+                            goto Linterfaces;
+                        }
+                    }
+
+                    if (funcdecl->isFinalFunc())
+                    {
+                        // Don't check here, as it may override an interface function
+                        //if (funcdecl->isOverride())
+                            //funcdecl->error("is marked as override, but does not override any function");
+                        cd->vtblFinal.push(funcdecl);
+                    }
+                    else
+                    {
+                        //printf("\tintroducing function %s\n", funcdecl->toChars());
+                        funcdecl->introducing = 1;
+                        if (cd->isCPPclass() && target.cpp.reverseOverloads)
+                        {
+                            // with dmc, overloaded functions are grouped and in reverse order
+                            funcdecl->vtblIndex = (int)cd->vtbl.length;
+                            for (int i = 0; i < (int)cd->vtbl.length; i++)
+                            {
+                                if (cd->vtbl[i]->ident == funcdecl->ident && cd->vtbl[i]->parent == parent)
+                                {
+                                    funcdecl->vtblIndex = (int)i;
+                                    break;
+                                }
+                            }
+                            // shift all existing functions back
+                            for (int i = (int)cd->vtbl.length; i > funcdecl->vtblIndex; i--)
+                            {
+                                FuncDeclaration *fd = cd->vtbl[i-1]->isFuncDeclaration();
+                                assert(fd);
+                                fd->vtblIndex++;
+                            }
+                            cd->vtbl.insert(funcdecl->vtblIndex, funcdecl);
+                        }
+                        else
+                        {
+                            // Append to end of vtbl[]
+                            vi = (int)cd->vtbl.length;
+                            cd->vtbl.push(funcdecl);
+                            funcdecl->vtblIndex = vi;
+                        }
+                    }
+                    break;
+
+                case -2:
+                    // can't determine because of forward references
+                    funcdecl->errors = true;
+                    return;
+
+                default:
+                {
+                    FuncDeclaration *fdv = cd->baseClass->vtbl[vi]->isFuncDeclaration();
+                    FuncDeclaration *fdc = cd->vtbl[vi]->isFuncDeclaration();
+                    // This function is covariant with fdv
+
+                    if (fdc == funcdecl)
+                    {
+                        doesoverride = true;
+                        break;
+                    }
+
+                    if (fdc->toParent() == parent)
+                    {
+                        //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc  = %p %s %s @ [%s]\n\tfdv  = %p %s %s @ [%s]\n",
+                        //        vi, funcdecl, funcdecl->toChars(), funcdecl->type->toChars(), funcdecl->loc.toChars(),
+                        //            fdc,  fdc ->toChars(), fdc ->type->toChars(), fdc ->loc.toChars(),
+                        //            fdv,  fdv ->toChars(), fdv ->type->toChars(), fdv ->loc.toChars());
+
+                        // fdc overrides fdv exactly, then this introduces new function.
+                        if (fdc->type->mod == fdv->type->mod && funcdecl->type->mod != fdv->type->mod)
+                            goto Lintro;
+                    }
+
+                    // This function overrides fdv
+                    if (fdv->isFinalFunc())
+                        funcdecl->error("cannot override final function %s", fdv->toPrettyChars());
+
+                    if (!funcdecl->isOverride())
+                    {
+                        if (fdv->isFuture())
+                        {
+                            ::deprecation(funcdecl->loc, "@__future base class method %s is being overridden by %s; rename the latter",
+                                fdv->toPrettyChars(), funcdecl->toPrettyChars());
+                            // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
+                            goto Lintro;
+                        }
+                        else
+                        {
+                            int vi2 = funcdecl->findVtblIndex(&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.length, false);
+                            if (vi2 < 0)
+                                // https://issues.dlang.org/show_bug.cgi?id=17349
+                                ::deprecation(funcdecl->loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
+                                    fdv->toPrettyChars(), funcdecl->toPrettyChars());
+                            else
+                                error(funcdecl->loc, "implicitly overriding base class method %s with %s deprecated; add `override` attribute",
+                                    fdv->toPrettyChars(), funcdecl->toPrettyChars());
+                        }
+                    }
+
+                    doesoverride = true;
+                    if (fdc->toParent() == parent)
+                    {
+                        // If both are mixins, or both are not, then error.
+                        // If either is not, the one that is not overrides the other.
+                        bool thismixin = funcdecl->parent->isClassDeclaration() != NULL;
+                        bool fdcmixin = fdc->parent->isClassDeclaration() != NULL;
+                        if (thismixin == fdcmixin)
+                        {
+                            funcdecl->error("multiple overrides of same function");
+                        }
+                        else if (!thismixin)    // fdc overrides fdv
+                        {
+                            // this doesn't override any function
+                            break;
+                        }
+                    }
+                    cd->vtbl[vi] = funcdecl;
+                    funcdecl->vtblIndex = vi;
+
+                    /* Remember which functions this overrides
+                     */
+                    funcdecl->foverrides.push(fdv);
+
+                    /* This works by whenever this function is called,
+                     * it actually returns tintro, which gets dynamically
+                     * cast to type. But we know that tintro is a base
+                     * of type, so we could optimize it by not doing a
+                     * dynamic cast, but just subtracting the isBaseOf()
+                     * offset if the value is != null.
+                     */
+
+                    if (fdv->tintro)
+                        funcdecl->tintro = fdv->tintro;
+                    else if (!funcdecl->type->equals(fdv->type))
+                    {
+                        /* Only need to have a tintro if the vptr
+                         * offsets differ
+                         */
+                        int offset;
+                        if (fdv->type->nextOf()->isBaseOf(funcdecl->type->nextOf(), &offset))
+                        {
+                            funcdecl->tintro = fdv->type;
+                        }
+                    }
+                    break;
+                }
+            }
+
+            /* Go through all the interface bases.
+             * If this function is covariant with any members of those interface
+             * functions, set the tintro.
+             */
+        Linterfaces:
+            for (size_t i = 0; i < cd->interfaces.length; i++)
+            {
+                BaseClass *b = cd->interfaces.ptr[i];
+                vi = funcdecl->findVtblIndex((Dsymbols *)&b->sym->vtbl, (int)b->sym->vtbl.length);
+                switch (vi)
+                {
+                    case -1:
+                        break;
+
+                    case -2:
+                        // can't determine because of forward references
+                        funcdecl->errors = true;
+                        return;
+
+                    default:
+                    {
+                        FuncDeclaration *fdv = (FuncDeclaration *)b->sym->vtbl[vi];
+                        Type *ti = NULL;
+
+                        /* Remember which functions this overrides
+                         */
+                        funcdecl->foverrides.push(fdv);
+
+                        /* Should we really require 'override' when implementing
+                         * an interface function?
+                         */
+                        //if (!funcdecl->isOverride())
+                            //warning(funcdecl->loc, "overrides base class function %s, but is not marked with `override`", fdv->toPrettyChars());
+
+                        if (fdv->tintro)
+                            ti = fdv->tintro;
+                        else if (!funcdecl->type->equals(fdv->type))
+                        {
+                            /* Only need to have a tintro if the vptr
+                             * offsets differ
+                             */
+                            int offset;
+                            if (fdv->type->nextOf()->isBaseOf(funcdecl->type->nextOf(), &offset))
+                            {
+                                ti = fdv->type;
+                            }
+                        }
+                        if (ti)
+                        {
+                            if (funcdecl->tintro)
+                            {
+                                if (!funcdecl->tintro->nextOf()->equals(ti->nextOf()) &&
+                                    !funcdecl->tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
+                                    !ti->nextOf()->isBaseOf(funcdecl->tintro->nextOf(), NULL))
+                                {
+                                    funcdecl->error("incompatible covariant types %s and %s", funcdecl->tintro->toChars(), ti->toChars());
+                                }
+                            }
+                            funcdecl->tintro = ti;
+                        }
+                        goto L2;
+                    }
+                }
+            }
+
+            if (!doesoverride && funcdecl->isOverride() && (funcdecl->type->nextOf() || !may_override))
+            {
+                BaseClass *bc = NULL;
+                Dsymbol *s = NULL;
+                for (size_t i = 0; i < cd->baseclasses->length; i++)
+                {
+                    bc = (*cd->baseclasses)[i];
+                    s = bc->sym->search_correct(funcdecl->ident);
+                    if (s) break;
+                }
+
+                if (s)
+                    funcdecl->error("does not override any function, did you mean to override `%s%s`?",
+                        bc->sym->isCPPclass() ? "extern (C++) " : "", s->toPrettyChars());
+                else
+                    funcdecl->error("does not override any function");
+            }
+
+        L2: ;
+
+            /* Go through all the interface bases.
+             * Disallow overriding any final functions in the interface(s).
+             */
+            for (size_t i = 0; i < cd->interfaces.length; i++)
+            {
+                BaseClass *b = cd->interfaces.ptr[i];
+                if (b->sym)
+                {
+                    Dsymbol *s = search_function(b->sym, funcdecl->ident);
+                    if (s)
+                    {
+                        FuncDeclaration *f2 = s->isFuncDeclaration();
+                        if (f2)
+                        {
+                            f2 = f2->overloadExactMatch(funcdecl->type);
+                            if (f2 && f2->isFinalFunc() && f2->prot().kind != Prot::private_)
+                                funcdecl->error("cannot override final function %s.%s", b->sym->toChars(), f2->toPrettyChars());
+                        }
+                    }
+                }
+            }
+
+            if (funcdecl->isOverride())
+            {
+                if (funcdecl->storage_class & STCdisable)
+                    funcdecl->deprecation("overridden functions cannot be annotated @disable");
+                if (funcdecl->isDeprecated())
+                    funcdecl->deprecation("deprecated functions cannot be annotated @disable");
+            }
+        }
+        else if (funcdecl->isOverride() && !parent->isTemplateInstance())
+            funcdecl->error("override only applies to class member functions");
+
+        // Reflect this->type to f because it could be changed by findVtblIndex
+        f = funcdecl->type->toTypeFunction();
+
+    Ldone:
+        /* Contracts can only appear without a body when they are virtual interface functions
+         */
+        if (!funcdecl->fbody && !allowsContractWithoutBody(funcdecl))
+            funcdecl->error("in and out contracts can only appear without a body when they are virtual interface functions or abstract");
+
+        /* Do not allow template instances to add virtual functions
+         * to a class.
+         */
+        if (funcdecl->isVirtual())
+        {
+            TemplateInstance *ti = parent->isTemplateInstance();
+            if (ti)
+            {
+                // Take care of nested templates
+                while (1)
+                {
+                    TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
+                    if (!ti2)
+                        break;
+                    ti = ti2;
+                }
+
+                // If it's a member template
+                ClassDeclaration *cd = ti->tempdecl->isClassMember();
+                if (cd)
+                {
+                    funcdecl->error("cannot use template to add virtual function to class `%s`", cd->toChars());
+                }
+            }
+        }
+
+        if (funcdecl->isMain())
+            funcdecl->checkDmain();       // Check main() parameters and return type
+
+        /* Purity and safety can be inferred for some functions by examining
+         * the function body.
+         */
+        if (canInferAttributes(funcdecl, sc))
+            initInferAttributes(funcdecl);
+
+        Module::dprogress++;
+        funcdecl->semanticRun = PASSsemanticdone;
+
+        /* Save scope for possible later use (if we need the
+         * function internals)
+         */
+        funcdecl->_scope = sc->copy();
+        funcdecl->_scope->setNoFree();
+
+        static bool printedMain = false;  // semantic might run more than once
+        if (global.params.verbose && !printedMain)
+        {
+            const char *type = funcdecl->isMain() ? "main" : funcdecl->isWinMain() ? "winmain" : funcdecl->isDllMain() ? "dllmain" : (const char *)NULL;
+            Module *mod = sc->_module;
+
+            if (type && mod)
+            {
+                printedMain = true;
+                const char *name = mod->srcfile->toChars();
+                const char *path = FileName::searchPath(global.path, name, true);
+                message("entry     %-10s\t%s", type, path ? path : name);
+            }
+        }
+
+        if (funcdecl->fbody && funcdecl->isMain() && sc->_module->isRoot())
+            Compiler::genCmain(sc);
+
+        assert(funcdecl->type->ty != Terror || funcdecl->errors);
+
+        // semantic for parameters' UDAs
+        const size_t nparams = f->parameterList.length();
+        for (size_t i = 0; i < nparams; i++)
+        {
+            Parameter *param = f->parameterList[i];
+            if (param && param->userAttribDecl)
+                dsymbolSemantic(param->userAttribDecl, sc);
+        }
+    }
+
+    // Do the semantic analysis on the external interface to the function.
+    void visit(FuncDeclaration *funcdecl)
+    {
+        funcDeclarationSemantic(funcdecl);
+    }
+
+    void visit(CtorDeclaration *ctd)
+    {
+        //printf("CtorDeclaration::semantic() %s\n", ctd->toChars());
+        if (ctd->semanticRun >= PASSsemanticdone)
+            return;
+        if (ctd->_scope)
+        {
+            sc = ctd->_scope;
+            ctd->_scope = NULL;
+        }
+
+        ctd->parent = sc->parent;
+        Dsymbol *p = ctd->toParent2();
+        AggregateDeclaration *ad = p->isAggregateDeclaration();
+        if (!ad)
+        {
+            error(ctd->loc, "constructor can only be a member of aggregate, not %s %s",
+                p->kind(), p->toChars());
+            ctd->type = Type::terror;
+            ctd->errors = true;
+            return;
+        }
+
+        sc = sc->push();
+        sc->stc &= ~STCstatic;              // not a static constructor
+        sc->flags |= SCOPEctor;
+
+        funcDeclarationSemantic(ctd);
+
+        sc->pop();
+
+        if (ctd->errors)
+            return;
+
+        TypeFunction *tf = ctd->type->toTypeFunction();
+
+        /* See if it's the default constructor
+         * But, template constructor should not become a default constructor.
+         */
+        if (ad && (!ctd->parent->isTemplateInstance() || ctd->parent->isTemplateMixin()))
+        {
+            const size_t dim = tf->parameterList.length();
+
+            if (StructDeclaration *sd = ad->isStructDeclaration())
+            {
+                if (dim == 0 && tf->parameterList.varargs == VARARGnone) // empty default ctor w/o any varargs
+                {
+                    if (ctd->fbody || !(ctd->storage_class & STCdisable) || dim)
+                    {
+                        ctd->error("default constructor for structs only allowed "
+                            "with @disable, no body, and no parameters");
+                        ctd->storage_class |= STCdisable;
+                        ctd->fbody = NULL;
+                    }
+                    sd->noDefaultCtor = true;
+                }
+                else if (dim == 0 && tf->parameterList.varargs) // allow varargs only ctor
+                {
+                }
+                else if (dim && tf->parameterList[0]->defaultArg)
+                {
+                    // if the first parameter has a default argument, then the rest does as well
+                    if (ctd->storage_class & STCdisable)
+                    {
+                        ctd->deprecation("@disable'd constructor cannot have default "
+                                         "arguments for all parameters.");
+                        deprecationSupplemental(ctd->loc, "Use @disable this(); if you want to disable default initialization.");
+                    }
+                    else
+                        ctd->deprecation("all parameters have default arguments, "
+                                         "but structs cannot have default constructors.");
+                }
+
+            }
+            else if (dim == 0 && tf->parameterList.varargs == VARARGnone)
+            {
+                ad->defaultCtor = ctd;
+            }
+        }
+    }
+
+    void visit(PostBlitDeclaration *pbd)
+    {
+        //printf("PostBlitDeclaration::semantic() %s\n", pbd->toChars());
+        //printf("ident: %s, %s, %p, %p\n", pbd->ident->toChars(), Id::dtor->toChars(), pbd->ident, Id::dtor);
+        //printf("stc = x%llx\n", sc->stc);
+        if (pbd->semanticRun >= PASSsemanticdone)
+            return;
+        if (pbd->_scope)
+        {
+            sc = pbd->_scope;
+            pbd->_scope = NULL;
+        }
+
+        pbd->parent = sc->parent;
+        Dsymbol *p = pbd->toParent2();
+        StructDeclaration *ad = p->isStructDeclaration();
+        if (!ad)
+        {
+            error(pbd->loc, "postblit can only be a member of struct/union, not %s %s",
+                p->kind(), p->toChars());
+            pbd->type = Type::terror;
+            pbd->errors = true;
+            return;
+        }
+        if (pbd->ident == Id::postblit && pbd->semanticRun < PASSsemantic)
+            ad->postblits.push(pbd);
+        if (!pbd->type)
+            pbd->type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, pbd->storage_class);
+
+        sc = sc->push();
+        sc->stc &= ~STCstatic;              // not static
+        sc->linkage = LINKd;
+
+        funcDeclarationSemantic(pbd);
+
+        sc->pop();
+    }
+
+    void visit(DtorDeclaration *dd)
+    {
+        //printf("DtorDeclaration::semantic() %s\n", dd->toChars());
+        //printf("ident: %s, %s, %p, %p\n", dd->ident->toChars(), Id::dtor->toChars(), dd->ident, Id::dtor);
+        if (dd->semanticRun >= PASSsemanticdone)
+            return;
+        if (dd->_scope)
+        {
+            sc = dd->_scope;
+            dd->_scope = NULL;
+        }
+
+        dd->parent = sc->parent;
+        Dsymbol *p = dd->toParent2();
+        AggregateDeclaration *ad = p->isAggregateDeclaration();
+        if (!ad)
+        {
+            error(dd->loc, "destructor can only be a member of aggregate, not %s %s",
+                p->kind(), p->toChars());
+            dd->type = Type::terror;
+            dd->errors = true;
+            return;
+        }
+        if (dd->ident == Id::dtor && dd->semanticRun < PASSsemantic)
+            ad->dtors.push(dd);
+        if (!dd->type)
+            dd->type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, dd->storage_class);
+
+        sc = sc->push();
+        sc->stc &= ~STCstatic;              // not a static destructor
+        if (sc->linkage != LINKcpp)
+            sc->linkage = LINKd;
+
+        funcDeclarationSemantic(dd);
+
+        sc->pop();
+    }
+
+    void visit(StaticCtorDeclaration *scd)
+    {
+        //printf("StaticCtorDeclaration::semantic()\n");
+        if (scd->semanticRun >= PASSsemanticdone)
+            return;
+        if (scd->_scope)
+        {
+            sc = scd->_scope;
+            scd->_scope = NULL;
+        }
+
+        scd->parent = sc->parent;
+        Dsymbol *p = scd->parent->pastMixin();
+        if (!p->isScopeDsymbol())
+        {
+            const char *s = (scd->isSharedStaticCtorDeclaration() ? "shared " : "");
+            error(scd->loc, "%sstatic constructor can only be member of module/aggregate/template, not %s %s",
+                s, p->kind(), p->toChars());
+            scd->type = Type::terror;
+            scd->errors = true;
+            return;
+        }
+        if (!scd->type)
+            scd->type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, scd->storage_class);
+
+        /* If the static ctor appears within a template instantiation,
+         * it could get called multiple times by the module constructors
+         * for different modules. Thus, protect it with a gate.
+         */
+        if (scd->isInstantiated() && scd->semanticRun < PASSsemantic)
+        {
+            /* Add this prefix to the function:
+             *      static int gate;
+             *      if (++gate != 1) return;
+             * Note that this is not thread safe; should not have threads
+             * during static construction.
+             */
+            VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
+            v->storage_class = STCtemp | (scd->isSharedStaticCtorDeclaration() ? STCstatic : STCtls);
+            Statements *sa = new Statements();
+            Statement *s = new ExpStatement(Loc(), v);
+            sa->push(s);
+            Expression *e = new IdentifierExp(Loc(), v->ident);
+            e = new AddAssignExp(Loc(), e, new IntegerExp(1));
+            e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(1));
+            s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
+            sa->push(s);
+            if (scd->fbody)
+                sa->push(scd->fbody);
+            scd->fbody = new CompoundStatement(Loc(), sa);
+        }
+
+        funcDeclarationSemantic(scd);
+
+        // We're going to need ModuleInfo
+        Module *m = scd->getModule();
+        if (!m)
+            m = sc->_module;
+        if (m)
+        {
+            m->needmoduleinfo = 1;
+            //printf("module1 %s needs moduleinfo\n", m->toChars());
+        }
+    }
+
+    void visit(StaticDtorDeclaration *sdd)
+    {
+        if (sdd->semanticRun >= PASSsemanticdone)
+            return;
+        if (sdd->_scope)
+        {
+            sc = sdd->_scope;
+            sdd->_scope = NULL;
+        }
+
+        sdd->parent = sc->parent;
+        Dsymbol *p = sdd->parent->pastMixin();
+        if (!p->isScopeDsymbol())
+        {
+            const char *s = (sdd->isSharedStaticDtorDeclaration() ? "shared " : "");
+            error(sdd->loc, "%sstatic destructor can only be member of module/aggregate/template, not %s %s",
+                s, p->kind(), p->toChars());
+            sdd->type = Type::terror;
+            sdd->errors = true;
+            return;
+        }
+        if (!sdd->type)
+            sdd->type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, sdd->storage_class);
+
+        /* If the static ctor appears within a template instantiation,
+         * it could get called multiple times by the module constructors
+         * for different modules. Thus, protect it with a gate.
+         */
+        if (sdd->isInstantiated() && sdd->semanticRun < PASSsemantic)
+        {
+            /* Add this prefix to the function:
+             *      static int gate;
+             *      if (--gate != 0) return;
+             * Increment gate during constructor execution.
+             * Note that this is not thread safe; should not have threads
+             * during static destruction.
+             */
+            VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
+            v->storage_class = STCtemp | (sdd->isSharedStaticDtorDeclaration() ? STCstatic : STCtls);
+            Statements *sa = new Statements();
+            Statement *s = new ExpStatement(Loc(), v);
+            sa->push(s);
+            Expression *e = new IdentifierExp(Loc(), v->ident);
+            e = new AddAssignExp(Loc(), e, new IntegerExp(-1));
+            e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(0));
+            s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
+            sa->push(s);
+            if (sdd->fbody)
+                sa->push(sdd->fbody);
+            sdd->fbody = new CompoundStatement(Loc(), sa);
+            sdd->vgate = v;
+        }
+
+        funcDeclarationSemantic(sdd);
+
+        // We're going to need ModuleInfo
+        Module *m = sdd->getModule();
+        if (!m)
+            m = sc->_module;
+        if (m)
+        {
+            m->needmoduleinfo = 1;
+            //printf("module2 %s needs moduleinfo\n", m->toChars());
+        }
+    }
+
+    void visit(InvariantDeclaration *invd)
+    {
+        if (invd->semanticRun >= PASSsemanticdone)
+            return;
+        if (invd->_scope)
+        {
+            sc = invd->_scope;
+            invd->_scope = NULL;
+        }
+
+        invd->parent = sc->parent;
+        Dsymbol *p = invd->parent->pastMixin();
+        AggregateDeclaration *ad = p->isAggregateDeclaration();
+        if (!ad)
+        {
+            error(invd->loc, "invariant can only be a member of aggregate, not %s %s",
+                p->kind(), p->toChars());
+            invd->type = Type::terror;
+            invd->errors = true;
+            return;
+        }
+        if (invd->ident != Id::classInvariant &&
+            invd->semanticRun < PASSsemantic &&
+            !ad->isUnionDeclaration()           // users are on their own with union fields
+           )
+            ad->invs.push(invd);
+        if (!invd->type)
+            invd->type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, invd->storage_class);
+
+        sc = sc->push();
+        sc->stc &= ~STCstatic;              // not a static invariant
+        sc->stc |= STCconst;                // invariant() is always const
+        sc->flags = (sc->flags & ~SCOPEcontract) | SCOPEinvariant;
+        sc->linkage = LINKd;
+
+        funcDeclarationSemantic(invd);
+
+        sc->pop();
+    }
+
+    void visit(UnitTestDeclaration *utd)
+    {
+        if (utd->semanticRun >= PASSsemanticdone)
+            return;
+        if (utd->_scope)
+        {
+            sc = utd->_scope;
+            utd->_scope = NULL;
+        }
+
+        utd->protection = sc->protection;
+
+        utd->parent = sc->parent;
+        Dsymbol *p = utd->parent->pastMixin();
+        if (!p->isScopeDsymbol())
+        {
+            error(utd->loc, "unittest can only be a member of module/aggregate/template, not %s %s",
+                p->kind(), p->toChars());
+            utd->type = Type::terror;
+            utd->errors = true;
+            return;
+        }
+
+        if (global.params.useUnitTests)
+        {
+            if (!utd->type)
+                utd->type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, utd->storage_class);
+            Scope *sc2 = sc->push();
+            sc2->linkage = LINKd;
+            funcDeclarationSemantic(utd);
+            sc2->pop();
+        }
+    }
+
+    void visit(NewDeclaration *nd)
+    {
+        //printf("NewDeclaration::semantic()\n");
+        if (nd->semanticRun >= PASSsemanticdone)
+            return;
+        if (nd->_scope)
+        {
+            sc = nd->_scope;
+            nd->_scope = NULL;
+        }
+
+        nd->parent = sc->parent;
+        Dsymbol *p = nd->parent->pastMixin();
+        if (!p->isAggregateDeclaration())
+        {
+            error(nd->loc, "allocator can only be a member of aggregate, not %s %s",
+                p->kind(), p->toChars());
+            nd->type = Type::terror;
+            nd->errors = true;
+            return;
+        }
+        Type *tret = Type::tvoid->pointerTo();
+        if (!nd->type)
+            nd->type = new TypeFunction(ParameterList(nd->parameters, nd->varargs), tret, LINKd, nd->storage_class);
+
+        nd->type = typeSemantic(nd->type, nd->loc, sc);
+
+        // Check that there is at least one argument of type size_t
+        TypeFunction *tf = nd->type->toTypeFunction();
+        if (tf->parameterList.length() < 1)
+        {
+            nd->error("at least one argument of type size_t expected");
+        }
+        else
+        {
+            Parameter *fparam = tf->parameterList[0];
+            if (!fparam->type->equals(Type::tsize_t))
+                nd->error("first argument must be type size_t, not %s", fparam->type->toChars());
+        }
+
+        funcDeclarationSemantic(nd);
+    }
+
+    void visit(DeleteDeclaration *deld)
+    {
+        //printf("DeleteDeclaration::semantic()\n");
+        if (deld->semanticRun >= PASSsemanticdone)
+            return;
+        if (deld->_scope)
+        {
+            sc = deld->_scope;
+            deld->_scope = NULL;
+        }
+
+        deld->parent = sc->parent;
+        Dsymbol *p = deld->parent->pastMixin();
+        if (!p->isAggregateDeclaration())
+        {
+            error(deld->loc, "deallocator can only be a member of aggregate, not %s %s",
+                p->kind(), p->toChars());
+            deld->type = Type::terror;
+            deld->errors = true;
+            return;
+        }
+        if (!deld->type)
+            deld->type = new TypeFunction(ParameterList(deld->parameters), Type::tvoid, LINKd, deld->storage_class);
+
+        deld->type = typeSemantic(deld->type, deld->loc, sc);
+
+        // Check that there is only one argument of type void*
+        TypeFunction *tf = deld->type->toTypeFunction();
+        if (tf->parameterList.length() != 1)
+        {
+            deld->error("one argument of type void* expected");
+        }
+        else
+        {
+            Parameter *fparam = tf->parameterList[0];
+            if (!fparam->type->equals(Type::tvoid->pointerTo()))
+                deld->error("one argument of type void* expected, not %s", fparam->type->toChars());
+        }
+
+        funcDeclarationSemantic(deld);
+    }
+
+    void visit(StructDeclaration *sd)
+    {
+        //printf("StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", sd, sd->parent->toChars(), sd->toChars(), sizeok);
+
+        //static int count; if (++count == 20) halt();
+
+        if (sd->semanticRun >= PASSsemanticdone)
+            return;
+        unsigned errors = global.errors;
+
+        //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", sd, sd->parent->toChars(), sd->toChars(), sizeok);
+        Scope *scx = NULL;
+        if (sd->_scope)
+        {
+            sc = sd->_scope;
+            scx = sd->_scope;            // save so we don't make redundant copies
+            sd->_scope = NULL;
+        }
+
+        if (!sd->parent)
+        {
+            assert(sc->parent && sc->func);
+            sd->parent = sc->parent;
+        }
+        assert(sd->parent && !sd->isAnonymous());
+
+        if (sd->errors)
+            sd->type = Type::terror;
+        if (sd->semanticRun == PASSinit)
+            sd->type = sd->type->addSTC(sc->stc | sd->storage_class);
+        sd->type = typeSemantic(sd->type, sd->loc, sc);
+
+        if (sd->type->ty == Tstruct && ((TypeStruct *)sd->type)->sym != sd)
+        {
+            TemplateInstance *ti = ((TypeStruct *)sd->type)->sym->isInstantiated();
+            if (ti && isError(ti))
+                ((TypeStruct *)sd->type)->sym = sd;
+        }
+
+        // Ungag errors when not speculative
+        Ungag ungag = sd->ungagSpeculative();
+
+        if (sd->semanticRun == PASSinit)
+        {
+            sd->protection = sc->protection;
+
+            sd->alignment = sc->alignment();
+
+            sd->storage_class |= sc->stc;
+            if (sd->storage_class & STCdeprecated)
+                sd->isdeprecated = true;
+            if (sd->storage_class & STCabstract)
+                sd->error("structs, unions cannot be abstract");
+            sd->userAttribDecl = sc->userAttribDecl;
+
+            if (sc->linkage == LINKcpp)
+                sd->classKind = ClassKind::cpp;
+        }
+        else if (sd->symtab && !scx)
+        {
+            return;
+        }
+        sd->semanticRun = PASSsemantic;
+
+        if (!sd->members)               // if opaque declaration
+        {
+            sd->semanticRun = PASSsemanticdone;
+            return;
+        }
+        if (!sd->symtab)
+        {
+            sd->symtab = new DsymbolTable();
+
+            for (size_t i = 0; i < sd->members->length; i++)
+            {
+                Dsymbol *s = (*sd->members)[i];
+                //printf("adding member '%s' to '%s'\n", s->toChars(), sd->toChars());
+                s->addMember(sc, sd);
+            }
+        }
+
+        Scope *sc2 = sd->newScope(sc);
+
+        /* Set scope so if there are forward references, we still might be able to
+         * resolve individual members like enums.
+         */
+        for (size_t i = 0; i < sd->members->length; i++)
+        {
+            Dsymbol *s = (*sd->members)[i];
+            //printf("struct: setScope %s %s\n", s->kind(), s->toChars());
+            s->setScope(sc2);
+        }
+
+        for (size_t i = 0; i < sd->members->length; i++)
+        {
+            Dsymbol *s = (*sd->members)[i];
+            s->importAll(sc2);
+        }
+
+        for (size_t i = 0; i < sd->members->length; i++)
+        {
+            Dsymbol *s = (*sd->members)[i];
+            dsymbolSemantic(s, sc2);
+        }
+
+        if (!sd->determineFields())
+        {
+            assert(sd->type->ty == Terror);
+            sc2->pop();
+            sd->semanticRun = PASSsemanticdone;
+            return;
+        }
+
+        /* Following special member functions creation needs semantic analysis
+         * completion of sub-structs in each field types. For example, buildDtor
+         * needs to check existence of elaborate dtor in type of each fields.
+         * See the case in compilable/test14838.d
+         */
+        for (size_t i = 0; i < sd->fields.length; i++)
+        {
+            VarDeclaration *v = sd->fields[i];
+            Type *tb = v->type->baseElemOf();
+            if (tb->ty != Tstruct)
+                continue;
+            StructDeclaration *sdec = ((TypeStruct *)tb)->sym;
+            if (sdec->semanticRun >= PASSsemanticdone)
+                continue;
+
+            sc2->pop();
+
+            sd->_scope = scx ? scx : sc->copy();
+            sd->_scope->setNoFree();
+            sd->_scope->_module->addDeferredSemantic(sd);
+
+            //printf("\tdeferring %s\n", sd->toChars());
+            return;
+        }
+
+        /* Look for special member functions.
+         */
+        sd->aggNew =       (NewDeclaration *)sd->search(Loc(), Id::classNew);
+        sd->aggDelete = (DeleteDeclaration *)sd->search(Loc(), Id::classDelete);
+
+        // Look for the constructor
+        sd->ctor = sd->searchCtor();
+
+        sd->dtor = buildDtor(sd, sc2);
+        sd->postblit = buildPostBlit(sd, sc2);
+
+        buildOpAssign(sd, sc2);
+        buildOpEquals(sd, sc2);
+
+        if (global.params.useTypeInfo && Type::dtypeinfo)  // these functions are used for TypeInfo
+        {
+            sd->xeq = buildXopEquals(sd, sc2);
+            sd->xcmp = buildXopCmp(sd, sc2);
+            sd->xhash = buildXtoHash(sd, sc2);
+        }
+
+        sd->inv = buildInv(sd, sc2);
+
+        Module::dprogress++;
+        sd->semanticRun = PASSsemanticdone;
+        //printf("-StructDeclaration::semantic(this=%p, '%s')\n", sd, sd->toChars());
+
+        sc2->pop();
+
+        if (sd->ctor)
+        {
+            Dsymbol *scall = sd->search(Loc(), Id::call);
+            if (scall)
+            {
+                unsigned xerrors = global.startGagging();
+                sc = sc->push();
+                sc->tinst = NULL;
+                sc->minst = NULL;
+                FuncDeclaration *fcall = resolveFuncCall(sd->loc, sc, scall, NULL, NULL, NULL, 1);
+                sc = sc->pop();
+                global.endGagging(xerrors);
+
+                if (fcall && fcall->isStatic())
+                {
+                    sd->error(fcall->loc, "`static opCall` is hidden by constructors and can never be called");
+                    errorSupplemental(fcall->loc, "Please use a factory method instead, or replace all constructors with `static opCall`.");
+                }
+            }
+        }
+
+        if (sd->type->ty == Tstruct && ((TypeStruct *)sd->type)->sym != sd)
+        {
+            // https://issues.dlang.org/show_bug.cgi?id=19024
+            StructDeclaration *sym = ((TypeStruct *)sd->type)->sym;
+            sd->error("already exists at %s. Perhaps in another function with the same name?", sym->loc.toChars());
+        }
+
+        if (global.errors != errors)
+        {
+            // The type is no good.
+            sd->type = Type::terror;
+            sd->errors = true;
+            if (sd->deferred)
+                sd->deferred->errors = true;
+        }
+
+        if (sd->deferred && !global.gag)
+        {
+            semantic2(sd->deferred, sc);
+            semantic3(sd->deferred, sc);
+        }
+    }
+
+    void interfaceSemantic(ClassDeclaration *cd)
+    {
+        cd->vtblInterfaces = new BaseClasses();
+        cd->vtblInterfaces->reserve(cd->interfaces.length);
+
+        for (size_t i = 0; i < cd->interfaces.length; i++)
+        {
+            BaseClass *b = cd->interfaces.ptr[i];
+            cd->vtblInterfaces->push(b);
+            b->copyBaseInterfaces(cd->vtblInterfaces);
+        }
+    }
+
+    void visit(ClassDeclaration *cldec)
+    {
+        //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", cldec->toChars(), cldec->type, sizeok, cldec);
+        //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
+        //printf("sc->stc = %x\n", sc->stc);
+
+        //{ static int n;  if (++n == 20) *(char*)0=0; }
+
+        if (cldec->semanticRun >= PASSsemanticdone)
+            return;
+        unsigned errors = global.errors;
+
+        //printf("+ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", cldec->toChars(), cldec->type, sizeok, cldec);
+
+        Scope *scx = NULL;
+        if (cldec->_scope)
+        {
+            sc = cldec->_scope;
+            scx = cldec->_scope;            // save so we don't make redundant copies
+            cldec->_scope = NULL;
+        }
+
+        if (!cldec->parent)
+        {
+            assert(sc->parent);
+            cldec->parent = sc->parent;
+        }
+
+        if (cldec->errors)
+            cldec->type = Type::terror;
+        cldec->type = typeSemantic(cldec->type, cldec->loc, sc);
+
+        if (cldec->type->ty == Tclass && ((TypeClass *)cldec->type)->sym != cldec)
+        {
+            TemplateInstance *ti = ((TypeClass *)cldec->type)->sym->isInstantiated();
+            if (ti && isError(ti))
+                ((TypeClass *)cldec->type)->sym = cldec;
+        }
+
+        // Ungag errors when not speculative
+        Ungag ungag = cldec->ungagSpeculative();
+
+        if (cldec->semanticRun == PASSinit)
+        {
+            cldec->protection = sc->protection;
+
+            cldec->storage_class |= sc->stc;
+            if (cldec->storage_class & STCdeprecated)
+                cldec->isdeprecated = true;
+            if (cldec->storage_class & STCauto)
+                cldec->error("storage class `auto` is invalid when declaring a class, did you mean to use `scope`?");
+            if (cldec->storage_class & STCscope)
+                cldec->isscope = true;
+            if (cldec->storage_class & STCabstract)
+                cldec->isabstract = ABSyes;
+
+            cldec->userAttribDecl = sc->userAttribDecl;
+
+            if (sc->linkage == LINKcpp)
+                cldec->classKind = ClassKind::cpp;
+            if (sc->linkage == LINKobjc)
+                objc()->setObjc(cldec);
+        }
+        else if (cldec->symtab && !scx)
+        {
+            return;
+        }
+        cldec->semanticRun = PASSsemantic;
+
+        if (cldec->baseok < BASEOKdone)
+        {
+            cldec->baseok = BASEOKin;
+
+            // Expand any tuples in baseclasses[]
+            for (size_t i = 0; i < cldec->baseclasses->length; )
+            {
+                BaseClass *b = (*cldec->baseclasses)[i];
+                b->type = resolveBase(cldec, sc, scx, b->type);
+
+                Type *tb = b->type->toBasetype();
+                if (tb->ty == Ttuple)
+                {
+                    TypeTuple *tup = (TypeTuple *)tb;
+                    cldec->baseclasses->remove(i);
+                    size_t dim = Parameter::dim(tup->arguments);
+                    for (size_t j = 0; j < dim; j++)
+                    {
+                        Parameter *arg = Parameter::getNth(tup->arguments, j);
+                        b = new BaseClass(arg->type);
+                        cldec->baseclasses->insert(i + j, b);
+                    }
+                }
+                else
+                    i++;
+            }
+
+            if (cldec->baseok >= BASEOKdone)
+            {
+                //printf("%s already semantic analyzed, semanticRun = %d\n", cldec->toChars(), cldec->semanticRun);
+                if (cldec->semanticRun >= PASSsemanticdone)
+                    return;
+                goto Lancestorsdone;
+            }
+
+            // See if there's a base class as first in baseclasses[]
+            if (cldec->baseclasses->length)
+            {
+                BaseClass *b = (*cldec->baseclasses)[0];
+                Type *tb = b->type->toBasetype();
+                TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
+                if (!tc)
+                {
+                    if (b->type != Type::terror)
+                        cldec->error("base type must be class or interface, not %s", b->type->toChars());
+                    cldec->baseclasses->remove(0);
+                    goto L7;
+                }
+
+                if (tc->sym->isDeprecated())
+                {
+                    if (!cldec->isDeprecated())
+                    {
+                        // Deriving from deprecated class makes this one deprecated too
+                        cldec->isdeprecated = true;
+
+                        tc->checkDeprecated(cldec->loc, sc);
+                    }
+                }
+
+                if (tc->sym->isInterfaceDeclaration())
+                    goto L7;
+
+                for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
+                {
+                    if (cdb == cldec)
+                    {
+                        cldec->error("circular inheritance");
+                        cldec->baseclasses->remove(0);
+                        goto L7;
+                    }
+                }
+
+                /* Bugzilla 11034: Essentially, class inheritance hierarchy
+                 * and instance size of each classes are orthogonal information.
+                 * Therefore, even if tc->sym->sizeof == SIZEOKnone,
+                 * we need to set baseClass field for class covariance check.
+                 */
+                cldec->baseClass = tc->sym;
+                b->sym = cldec->baseClass;
+
+                if (tc->sym->baseok < BASEOKdone)
+                    resolveBase(cldec, sc, scx, tc->sym); // Try to resolve forward reference
+                if (tc->sym->baseok < BASEOKdone)
+                {
+                    //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
+                    if (tc->sym->_scope)
+                        tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                    cldec->baseok = BASEOKnone;
+                }
+             L7: ;
+            }
+
+            // Treat the remaining entries in baseclasses as interfaces
+            // Check for errors, handle forward references
+            for (size_t i = (cldec->baseClass ? 1 : 0); i < cldec->baseclasses->length; )
+            {
+                BaseClass *b = (*cldec->baseclasses)[i];
+                Type *tb = b->type->toBasetype();
+                TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
+                if (!tc || !tc->sym->isInterfaceDeclaration())
+                {
+                    if (b->type != Type::terror)
+                        cldec->error("base type must be interface, not %s", b->type->toChars());
+                    cldec->baseclasses->remove(i);
+                    continue;
+                }
+
+                // Check for duplicate interfaces
+                for (size_t j = (cldec->baseClass ? 1 : 0); j < i; j++)
+                {
+                    BaseClass *b2 = (*cldec->baseclasses)[j];
+                    if (b2->sym == tc->sym)
+                    {
+                        cldec->error("inherits from duplicate interface %s", b2->sym->toChars());
+                        cldec->baseclasses->remove(i);
+                        continue;
+                    }
+                }
+
+                if (tc->sym->isDeprecated())
+                {
+                    if (!cldec->isDeprecated())
+                    {
+                        // Deriving from deprecated class makes this one deprecated too
+                        cldec->isdeprecated = true;
+
+                        tc->checkDeprecated(cldec->loc, sc);
+                    }
+                }
+
+                b->sym = tc->sym;
+
+                if (tc->sym->baseok < BASEOKdone)
+                    resolveBase(cldec, sc, scx, tc->sym); // Try to resolve forward reference
+                if (tc->sym->baseok < BASEOKdone)
+                {
+                    //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
+                    if (tc->sym->_scope)
+                        tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                    cldec->baseok = BASEOKnone;
+                }
+                i++;
+            }
+            if (cldec->baseok == BASEOKnone)
+            {
+                // Forward referencee of one or more bases, try again later
+                cldec->_scope = scx ? scx : sc->copy();
+                cldec->_scope->setNoFree();
+                cldec->_scope->_module->addDeferredSemantic(cldec);
+                //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, cldec->toChars());
+                return;
+            }
+            cldec->baseok = BASEOKdone;
+
+            // If no base class, and this is not an Object, use Object as base class
+            if (!cldec->baseClass && cldec->ident != Id::Object && !cldec->isCPPclass())
+            {
+                if (!ClassDeclaration::object || ClassDeclaration::object->errors)
+                    badObjectDotD(cldec);
+
+                Type *t = ClassDeclaration::object->type;
+                t = typeSemantic(t, cldec->loc, sc)->toBasetype();
+                if (t->ty == Terror)
+                    badObjectDotD(cldec);
+                assert(t->ty == Tclass);
+                TypeClass *tc = (TypeClass *)t;
+
+                BaseClass *b = new BaseClass(tc);
+                cldec->baseclasses->shift(b);
+
+                cldec->baseClass = tc->sym;
+                assert(!cldec->baseClass->isInterfaceDeclaration());
+                b->sym = cldec->baseClass;
+            }
+            if (cldec->baseClass)
+            {
+                if (cldec->baseClass->storage_class & STCfinal)
+                    cldec->error("cannot inherit from final class %s", cldec->baseClass->toChars());
+
+                // Inherit properties from base class
+                if (cldec->baseClass->isCOMclass())
+                    cldec->com = true;
+                if (cldec->baseClass->isCPPclass())
+                    cldec->classKind = ClassKind::cpp;
+                if (cldec->baseClass->isscope)
+                    cldec->isscope = true;
+                cldec->enclosing = cldec->baseClass->enclosing;
+                cldec->storage_class |= cldec->baseClass->storage_class & STC_TYPECTOR;
+            }
+
+            cldec->interfaces.length = cldec->baseclasses->length - (cldec->baseClass ? 1 : 0);
+            cldec->interfaces.ptr = cldec->baseclasses->tdata() + (cldec->baseClass ? 1 : 0);
+
+            for (size_t i = 0; i < cldec->interfaces.length; i++)
+            {
+                BaseClass *b = cldec->interfaces.ptr[i];
+                // If this is an interface, and it derives from a COM interface,
+                // then this is a COM interface too.
+                if (b->sym->isCOMinterface())
+                    cldec->com = true;
+                if (cldec->isCPPclass() && !b->sym->isCPPinterface())
+                {
+                    error(cldec->loc, "C++ class `%s` cannot implement D interface `%s`",
+                        cldec->toPrettyChars(), b->sym->toPrettyChars());
+                }
+            }
+
+            interfaceSemantic(cldec);
+        }
+    Lancestorsdone:
+        //printf("\tClassDeclaration::semantic(%s) baseok = %d\n", cldec->toChars(), cldec->baseok);
+
+        if (!cldec->members)               // if opaque declaration
+        {
+            cldec->semanticRun = PASSsemanticdone;
+            return;
+        }
+        if (!cldec->symtab)
+        {
+            cldec->symtab = new DsymbolTable();
+
+            /* Bugzilla 12152: The semantic analysis of base classes should be finished
+             * before the members semantic analysis of this class, in order to determine
+             * vtbl in this class. However if a base class refers the member of this class,
+             * it can be resolved as a normal forward reference.
+             * Call addMember() and setScope() to make this class members visible from the base classes.
+             */
+            for (size_t i = 0; i < cldec->members->length; i++)
+            {
+                Dsymbol *s = (*cldec->members)[i];
+                s->addMember(sc, cldec);
+            }
+
+            Scope *sc2 = cldec->newScope(sc);
+
+            /* Set scope so if there are forward references, we still might be able to
+             * resolve individual members like enums.
+             */
+            for (size_t i = 0; i < cldec->members->length; i++)
+            {
+                Dsymbol *s = (*cldec->members)[i];
+                //printf("[%d] setScope %s %s, sc2 = %p\n", i, s->kind(), s->toChars(), sc2);
+                s->setScope(sc2);
+            }
+
+            sc2->pop();
+        }
+
+        for (size_t i = 0; i < cldec->baseclasses->length; i++)
+        {
+            BaseClass *b = (*cldec->baseclasses)[i];
+            Type *tb = b->type->toBasetype();
+            assert(tb->ty == Tclass);
+            TypeClass *tc = (TypeClass *)tb;
+
+            if (tc->sym->semanticRun < PASSsemanticdone)
+            {
+                // Forward referencee of one or more bases, try again later
+                cldec->_scope = scx ? scx : sc->copy();
+                cldec->_scope->setNoFree();
+                if (tc->sym->_scope)
+                    tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                cldec->_scope->_module->addDeferredSemantic(cldec);
+                //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, cldec->toChars());
+                return;
+            }
+        }
+
+        if (cldec->baseok == BASEOKdone)
+        {
+            cldec->baseok = BASEOKsemanticdone;
+
+            // initialize vtbl
+            if (cldec->baseClass)
+            {
+                if (cldec->isCPPclass() && cldec->baseClass->vtbl.length == 0)
+                {
+                    cldec->error("C++ base class %s needs at least one virtual function", cldec->baseClass->toChars());
+                }
+
+                // Copy vtbl[] from base class
+                cldec->vtbl.setDim(cldec->baseClass->vtbl.length);
+                memcpy(cldec->vtbl.tdata(), cldec->baseClass->vtbl.tdata(), sizeof(void *) * cldec->vtbl.length);
+
+                cldec->vthis = cldec->baseClass->vthis;
+            }
+            else
+            {
+                // No base class, so this is the root of the class hierarchy
+                cldec->vtbl.setDim(0);
+                if (cldec->vtblOffset())
+                    cldec->vtbl.push(cldec);            // leave room for classinfo as first member
+            }
+
+            /* If this is a nested class, add the hidden 'this'
+             * member which is a pointer to the enclosing scope.
+             */
+            if (cldec->vthis)              // if inheriting from nested class
+            {
+                // Use the base class's 'this' member
+                if (cldec->storage_class & STCstatic)
+                    cldec->error("static class cannot inherit from nested class %s", cldec->baseClass->toChars());
+                if (cldec->toParent2() != cldec->baseClass->toParent2() &&
+                    (!cldec->toParent2() ||
+                     !cldec->baseClass->toParent2()->getType() ||
+                     !cldec->baseClass->toParent2()->getType()->isBaseOf(cldec->toParent2()->getType(), NULL)))
+                {
+                    if (cldec->toParent2())
+                    {
+                        cldec->error("is nested within %s, but super class %s is nested within %s",
+                            cldec->toParent2()->toChars(),
+                            cldec->baseClass->toChars(),
+                            cldec->baseClass->toParent2()->toChars());
+                    }
+                    else
+                    {
+                        cldec->error("is not nested, but super class %s is nested within %s",
+                            cldec->baseClass->toChars(),
+                            cldec->baseClass->toParent2()->toChars());
+                    }
+                    cldec->enclosing = NULL;
+                }
+            }
+            else
+                cldec->makeNested();
+        }
+
+        Scope *sc2 = cldec->newScope(sc);
+
+        for (size_t i = 0; i < cldec->members->length; i++)
+        {
+            Dsymbol *s = (*cldec->members)[i];
+            s->importAll(sc2);
+        }
+
+        // Note that members.length can grow due to tuple expansion during semantic()
+        for (size_t i = 0; i < cldec->members->length; i++)
+        {
+            Dsymbol *s = (*cldec->members)[i];
+            dsymbolSemantic(s, sc2);
+        }
+
+        if (!cldec->determineFields())
+        {
+            assert(cldec->type == Type::terror);
+            sc2->pop();
+            return;
+        }
+
+        /* Following special member functions creation needs semantic analysis
+         * completion of sub-structs in each field types.
+         */
+        for (size_t i = 0; i < cldec->fields.length; i++)
+        {
+            VarDeclaration *v = cldec->fields[i];
+            Type *tb = v->type->baseElemOf();
+            if (tb->ty != Tstruct)
+                continue;
+            StructDeclaration *sd = ((TypeStruct *)tb)->sym;
+            if (sd->semanticRun >= PASSsemanticdone)
+                continue;
+
+            sc2->pop();
+
+            cldec->_scope = scx ? scx : sc->copy();
+            cldec->_scope->setNoFree();
+            cldec->_scope->_module->addDeferredSemantic(cldec);
+            //printf("\tdeferring %s\n", cldec->toChars());
+            return;
+        }
+
+        /* Look for special member functions.
+         * They must be in this class, not in a base class.
+         */
+
+        // Can be in base class
+        cldec->aggNew    =    (NewDeclaration *)cldec->search(Loc(), Id::classNew);
+        cldec->aggDelete = (DeleteDeclaration *)cldec->search(Loc(), Id::classDelete);
+
+        // Look for the constructor
+        cldec->ctor = cldec->searchCtor();
+
+        if (!cldec->ctor && cldec->noDefaultCtor)
+        {
+            // A class object is always created by constructor, so this check is legitimate.
+            for (size_t i = 0; i < cldec->fields.length; i++)
+            {
+                VarDeclaration *v = cldec->fields[i];
+                if (v->storage_class & STCnodefaultctor)
+                    error(v->loc, "field %s must be initialized in constructor", v->toChars());
+            }
+        }
+
+        // If this class has no constructor, but base class has a default
+        // ctor, create a constructor:
+        //    this() { }
+        if (!cldec->ctor && cldec->baseClass && cldec->baseClass->ctor)
+        {
+            FuncDeclaration *fd = resolveFuncCall(cldec->loc, sc2, cldec->baseClass->ctor, NULL, cldec->type, NULL, 1);
+            if (!fd) // try shared base ctor instead
+                fd = resolveFuncCall(cldec->loc, sc2, cldec->baseClass->ctor, NULL, cldec->type->sharedOf(), NULL, 1);
+            if (fd && !fd->errors)
+            {
+                //printf("Creating default this(){} for class %s\n", cldec->toChars());
+                TypeFunction *btf = fd->type->toTypeFunction();
+                TypeFunction *tf = new TypeFunction(ParameterList(), NULL, LINKd, fd->storage_class);
+                tf->mod = btf->mod;
+                tf->purity = btf->purity;
+                tf->isnothrow = btf->isnothrow;
+                tf->isnogc = btf->isnogc;
+                tf->trust = btf->trust;
+
+                CtorDeclaration *ctor = new CtorDeclaration(cldec->loc, Loc(), 0, tf);
+                ctor->fbody = new CompoundStatement(Loc(), new Statements());
+
+                cldec->members->push(ctor);
+                ctor->addMember(sc, cldec);
+                dsymbolSemantic(ctor, sc2);
+
+                cldec->ctor = ctor;
+                cldec->defaultCtor = ctor;
+            }
+            else
+            {
+                cldec->error("cannot implicitly generate a default ctor when base class %s is missing a default ctor",
+                    cldec->baseClass->toPrettyChars());
+            }
+        }
+
+        cldec->dtor = buildDtor(cldec, sc2);
+
+        if (FuncDeclaration *f = hasIdentityOpAssign(cldec, sc2))
+        {
+            if (!(f->storage_class & STCdisable))
+                cldec->error(f->loc, "identity assignment operator overload is illegal");
+        }
+
+        cldec->inv = buildInv(cldec, sc2);
+
+        Module::dprogress++;
+        cldec->semanticRun = PASSsemanticdone;
+        //printf("-ClassDeclaration.semantic(%s), type = %p\n", cldec->toChars(), cldec->type);
+        //members.print();
+
+        sc2->pop();
+
+        if (cldec->type->ty == Tclass && ((TypeClass *)cldec->type)->sym != cldec)
+        {
+            // https://issues.dlang.org/show_bug.cgi?id=17492
+            ClassDeclaration *cd = ((TypeClass *)cldec->type)->sym;
+            cldec->error("already exists at %s. Perhaps in another function with the same name?", cd->loc.toChars());
+        }
+
+        if (global.errors != errors)
+        {
+            // The type is no good.
+            cldec->type = Type::terror;
+            cldec->errors = true;
+            if (cldec->deferred)
+                cldec->deferred->errors = true;
+        }
+
+        // Verify fields of a synchronized class are not public
+        if (cldec->storage_class & STCsynchronized)
+        {
+            for (size_t i = 0; i < cldec->fields.length; i++)
+            {
+                VarDeclaration *vd = cldec->fields[i];
+                if (!vd->isThisDeclaration() &&
+                    !vd->prot().isMoreRestrictiveThan(Prot(Prot::public_)))
+                {
+                    vd->error("Field members of a synchronized class cannot be %s",
+                        protectionToChars(vd->prot().kind));
+                }
+            }
+        }
+
+        if (cldec->deferred && !global.gag)
+        {
+            semantic2(cldec->deferred, sc);
+            semantic3(cldec->deferred, sc);
+        }
+        //printf("-ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", cldec->toChars(), cldec->type, sizeok, cldec);
+    }
+
+    void visit(InterfaceDeclaration *idec)
+    {
+        //printf("InterfaceDeclaration::semantic(%s), type = %p\n", idec->toChars(), idec->type);
+        if (idec->semanticRun >= PASSsemanticdone)
+            return;
+        unsigned errors = global.errors;
+
+        //printf("+InterfaceDeclaration.semantic(%s), type = %p\n", idec->toChars(), idec->type);
+
+        Scope *scx = NULL;
+        if (idec->_scope)
+        {
+            sc = idec->_scope;
+            scx = idec->_scope;            // save so we don't make redundant copies
+            idec->_scope = NULL;
+        }
+
+        if (!idec->parent)
+        {
+            assert(sc->parent && sc->func);
+            idec->parent = sc->parent;
+        }
+        assert(idec->parent && !idec->isAnonymous());
+
+        if (idec->errors)
+            idec->type = Type::terror;
+        idec->type = typeSemantic(idec->type, idec->loc, sc);
+
+        if (idec->type->ty == Tclass && ((TypeClass *)idec->type)->sym != idec)
+        {
+            TemplateInstance *ti = ((TypeClass *)idec->type)->sym->isInstantiated();
+            if (ti && isError(ti))
+                ((TypeClass *)idec->type)->sym = idec;
+        }
+
+        // Ungag errors when not speculative
+        Ungag ungag = idec->ungagSpeculative();
+
+        if (idec->semanticRun == PASSinit)
+        {
+            idec->protection = sc->protection;
+
+            idec->storage_class |= sc->stc;
+            if (idec->storage_class & STCdeprecated)
+                idec->isdeprecated = true;
+
+            idec->userAttribDecl = sc->userAttribDecl;
+        }
+        else if (idec->symtab)
+        {
+            if (idec->sizeok == SIZEOKdone || !scx)
+            {
+                idec->semanticRun = PASSsemanticdone;
+                return;
+            }
+        }
+        idec->semanticRun = PASSsemantic;
+
+        if (idec->baseok < BASEOKdone)
+        {
+            idec->baseok = BASEOKin;
+
+            // Expand any tuples in baseclasses[]
+            for (size_t i = 0; i < idec->baseclasses->length; )
+            {
+                BaseClass *b = (*idec->baseclasses)[i];
+                b->type = resolveBase(idec, sc, scx, b->type);
+
+                Type *tb = b->type->toBasetype();
+                if (tb->ty == Ttuple)
+                {
+                    TypeTuple *tup = (TypeTuple *)tb;
+                    idec->baseclasses->remove(i);
+                    size_t dim = Parameter::dim(tup->arguments);
+                    for (size_t j = 0; j < dim; j++)
+                    {
+                        Parameter *arg = Parameter::getNth(tup->arguments, j);
+                        b = new BaseClass(arg->type);
+                        idec->baseclasses->insert(i + j, b);
+                    }
+                }
+                else
+                    i++;
+            }
+
+            if (idec->baseok >= BASEOKdone)
+            {
+                //printf("%s already semantic analyzed, semanticRun = %d\n", idec->toChars(), idec->semanticRun);
+                if (idec->semanticRun >= PASSsemanticdone)
+                    return;
+                goto Lancestorsdone;
+            }
+
+            if (!idec->baseclasses->length && sc->linkage == LINKcpp)
+                idec->classKind = ClassKind::cpp;
+            if (sc->linkage == LINKobjc)
+                objc()->setObjc(idec);
+
+            // Check for errors, handle forward references
+            for (size_t i = 0; i < idec->baseclasses->length; )
+            {
+                BaseClass *b = (*idec->baseclasses)[i];
+                Type *tb = b->type->toBasetype();
+                TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
+                if (!tc || !tc->sym->isInterfaceDeclaration())
+                {
+                    if (b->type != Type::terror)
+                        idec->error("base type must be interface, not %s", b->type->toChars());
+                    idec->baseclasses->remove(i);
+                    continue;
+                }
+
+                // Check for duplicate interfaces
+                for (size_t j = 0; j < i; j++)
+                {
+                    BaseClass *b2 = (*idec->baseclasses)[j];
+                    if (b2->sym == tc->sym)
+                    {
+                        idec->error("inherits from duplicate interface %s", b2->sym->toChars());
+                        idec->baseclasses->remove(i);
+                        continue;
+                    }
+                }
+
+                if (tc->sym == idec || idec->isBaseOf2(tc->sym))
+                {
+                    idec->error("circular inheritance of interface");
+                    idec->baseclasses->remove(i);
+                    continue;
+                }
+
+                if (tc->sym->isDeprecated())
+                {
+                    if (!idec->isDeprecated())
+                    {
+                        // Deriving from deprecated class makes this one deprecated too
+                        idec->isdeprecated = true;
+
+                        tc->checkDeprecated(idec->loc, sc);
+                    }
+                }
+
+                b->sym = tc->sym;
+
+                if (tc->sym->baseok < BASEOKdone)
+                    resolveBase(idec, sc, scx, tc->sym); // Try to resolve forward reference
+                if (tc->sym->baseok < BASEOKdone)
+                {
+                    //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
+                    if (tc->sym->_scope)
+                        tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                    idec->baseok = BASEOKnone;
+                }
+                i++;
+            }
+            if (idec->baseok == BASEOKnone)
+            {
+                // Forward referencee of one or more bases, try again later
+                idec->_scope = scx ? scx : sc->copy();
+                idec->_scope->setNoFree();
+                idec->_scope->_module->addDeferredSemantic(idec);
+                return;
+            }
+            idec->baseok = BASEOKdone;
+
+            idec->interfaces.length = idec->baseclasses->length;
+            idec->interfaces.ptr = idec->baseclasses->tdata();
+
+            for (size_t i = 0; i < idec->interfaces.length; i++)
+            {
+                BaseClass *b = idec->interfaces.ptr[i];
+                // If this is an interface, and it derives from a COM interface,
+                // then this is a COM interface too.
+                if (b->sym->isCOMinterface())
+                    idec->com = true;
+                if (b->sym->isCPPinterface())
+                    idec->classKind = ClassKind::cpp;
+            }
+
+            interfaceSemantic(idec);
+        }
+    Lancestorsdone:
+
+        if (!idec->members)               // if opaque declaration
+        {
+            idec->semanticRun = PASSsemanticdone;
+            return;
+        }
+        if (!idec->symtab)
+            idec->symtab = new DsymbolTable();
+
+        for (size_t i = 0; i < idec->baseclasses->length; i++)
+        {
+            BaseClass *b = (*idec->baseclasses)[i];
+            Type *tb = b->type->toBasetype();
+            assert(tb->ty == Tclass);
+            TypeClass *tc = (TypeClass *)tb;
+
+            if (tc->sym->semanticRun < PASSsemanticdone)
+            {
+                // Forward referencee of one or more bases, try again later
+                idec->_scope = scx ? scx : sc->copy();
+                idec->_scope->setNoFree();
+                if (tc->sym->_scope)
+                    tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                idec->_scope->_module->addDeferredSemantic(idec);
+                return;
+            }
+        }
+
+        if (idec->baseok == BASEOKdone)
+        {
+            idec->baseok = BASEOKsemanticdone;
+
+            // initialize vtbl
+            if (idec->vtblOffset())
+                idec->vtbl.push(idec);                // leave room at vtbl[0] for classinfo
+
+            // Cat together the vtbl[]'s from base cldec->interfaces
+            for (size_t i = 0; i < idec->interfaces.length; i++)
+            {
+                BaseClass *b = idec->interfaces.ptr[i];
+
+                // Skip if b has already appeared
+                for (size_t k = 0; k < i; k++)
+                {
+                    if (b == idec->interfaces.ptr[k])
+                        goto Lcontinue;
+                }
+
+                // Copy vtbl[] from base class
+                if (b->sym->vtblOffset())
+                {
+                    size_t d = b->sym->vtbl.length;
+                    if (d > 1)
+                    {
+                        idec->vtbl.reserve(d - 1);
+                        for (size_t j = 1; j < d; j++)
+                            idec->vtbl.push(b->sym->vtbl[j]);
+                    }
+                }
+                else
+                {
+                    idec->vtbl.append(&b->sym->vtbl);
+                }
+
+              Lcontinue:
+                ;
+            }
+        }
+
+        for (size_t i = 0; i < idec->members->length; i++)
+        {
+            Dsymbol *s = (*idec->members)[i];
+            s->addMember(sc, idec);
+        }
+
+        Scope *sc2 = idec->newScope(sc);
+
+        /* Set scope so if there are forward references, we still might be able to
+         * resolve individual members like enums.
+         */
+        for (size_t i = 0; i < idec->members->length; i++)
+        {
+            Dsymbol *s = (*idec->members)[i];
+            //printf("setScope %s %s\n", s->kind(), s->toChars());
+            s->setScope(sc2);
+        }
+
+        for (size_t i = 0; i < idec->members->length; i++)
+        {
+            Dsymbol *s = (*idec->members)[i];
+            s->importAll(sc2);
+        }
+
+        for (size_t i = 0; i < idec->members->length; i++)
+        {
+            Dsymbol *s = (*idec->members)[i];
+            dsymbolSemantic(s, sc2);
+        }
+
+        Module::dprogress++;
+        idec->semanticRun = PASSsemanticdone;
+        //printf("-InterfaceDeclaration.semantic(%s), type = %p\n", idec->toChars(), idec->type);
+        //members->print();
+
+        sc2->pop();
+
+        if (global.errors != errors)
+        {
+            // The type is no good.
+            idec->type = Type::terror;
+        }
+
+        assert(idec->type->ty != Tclass || ((TypeClass *)idec->type)->sym == idec);
+    }
+};
+
+void templateInstanceSemantic(TemplateInstance *tempinst, Scope *sc, Expressions *fargs)
+{
+    //printf("[%s] TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst->loc.toChars(), tempinst->toChars(), tempinst, global.gag, sc);
+    if (tempinst->inst)           // if semantic() was already run
+    {
+        return;
+    }
+    if (tempinst->semanticRun != PASSinit)
+    {
+        Ungag ungag(global.gag);
+        if (!tempinst->gagged)
+            global.gag = 0;
+        tempinst->error(tempinst->loc, "recursive template expansion");
+        if (tempinst->gagged)
+            tempinst->semanticRun = PASSinit;
+        else
+            tempinst->inst = tempinst;
+        tempinst->errors = true;
+        return;
+    }
+
+    // Get the enclosing template instance from the scope tinst
+    tempinst->tinst = sc->tinst;
+
+    // Get the instantiating module from the scope minst
+    tempinst->minst = sc->minst;
+    // Bugzilla 10920: If the enclosing function is non-root symbol,
+    // this instance should be speculative.
+    if (!tempinst->tinst && sc->func && sc->func->inNonRoot())
+    {
+        tempinst->minst = NULL;
+    }
+
+    tempinst->gagged = (global.gag > 0);
+
+    tempinst->semanticRun = PASSsemantic;
+
+    /* Find template declaration first,
+     * then run semantic on each argument (place results in tiargs[]),
+     * last find most specialized template from overload list/set.
+     */
+    if (!tempinst->findTempDecl(sc, NULL) ||
+        !tempinst->semanticTiargs(sc) ||
+        !tempinst->findBestMatch(sc, fargs))
+    {
+Lerror:
+        if (tempinst->gagged)
+        {
+            // Bugzilla 13220: Rollback status for later semantic re-running.
+            tempinst->semanticRun = PASSinit;
+        }
+        else
+            tempinst->inst = tempinst;
+        tempinst->errors = true;
+        return;
+    }
+    TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration();
+    assert(tempdecl);
+
+    // If tempdecl is a mixin, disallow it
+    if (tempdecl->ismixin)
+    {
+        tempinst->error("mixin templates are not regular templates");
+        goto Lerror;
+    }
+
+    tempinst->hasNestedArgs(tempinst->tiargs, tempdecl->isstatic);
+    if (tempinst->errors)
+        goto Lerror;
+
+    /* See if there is an existing TemplateInstantiation that already
+     * implements the typeargs. If so, just refer to that one instead.
+     */
+    tempinst->inst = tempdecl->findExistingInstance(tempinst, fargs);
+    TemplateInstance *errinst = NULL;
+    if (!tempinst->inst)
+    {
+        // So, we need to implement 'this' instance.
+    }
+    else if (tempinst->inst->gagged && !tempinst->gagged && tempinst->inst->errors)
+    {
+        // If the first instantiation had failed, re-run semantic,
+        // so that error messages are shown.
+        errinst = tempinst->inst;
+    }
+    else
+    {
+        // It's a match
+        tempinst->parent = tempinst->inst->parent;
+        tempinst->errors = tempinst->inst->errors;
+
+        // If both this and the previous instantiation were gagged,
+        // use the number of errors that happened last time.
+        global.errors += tempinst->errors;
+        global.gaggedErrors += tempinst->errors;
+
+        // If the first instantiation was gagged, but this is not:
+        if (tempinst->inst->gagged)
+        {
+            // It had succeeded, mark it is a non-gagged instantiation,
+            // and reuse it.
+            tempinst->inst->gagged = tempinst->gagged;
+        }
+
+        tempinst->tnext = tempinst->inst->tnext;
+        tempinst->inst->tnext = tempinst;
+
+        /* A module can have explicit template instance and its alias
+         * in module scope (e,g, `alias Base64 = Base64Impl!('+', '/');`).
+         * If the first instantiation 'inst' had happened in non-root module,
+         * compiler can assume that its instantiated code would be included
+         * in the separately compiled obj/lib file (e.g. phobos.lib).
+         *
+         * However, if 'this' second instantiation happened in root module,
+         * compiler might need to invoke its codegen (Bugzilla 2500 & 2644).
+         * But whole import graph is not determined until all semantic pass finished,
+         * so 'inst' should conservatively finish the semantic3 pass for the codegen.
+         */
+        if (tempinst->minst && tempinst->minst->isRoot() && !(tempinst->inst->minst && tempinst->inst->minst->isRoot()))
+        {
+            /* Swap the position of 'inst' and 'this' in the instantiation graph.
+             * Then, the primary instance `inst` will be changed to a root instance,
+             * along with all members of `inst` having their scopes updated.
+             *
+             * Before:
+             *  non-root -> A!() -> B!()[inst] -> C!() { members[non-root] }
+             *                      |
+             *  root     -> D!() -> B!()[this]
+             *
+             * After:
+             *  non-root -> A!() -> B!()[this]
+             *                      |
+             *  root     -> D!() -> B!()[inst] -> C!() { members[root] }
+             */
+            Module *mi = tempinst->minst;
+            TemplateInstance *ti = tempinst->tinst;
+            tempinst->minst = tempinst->inst->minst;
+            tempinst->tinst = tempinst->inst->tinst;
+            tempinst->inst->minst = mi;
+            tempinst->inst->tinst = ti;
+
+            /* https://issues.dlang.org/show_bug.cgi?id=21299
+               `minst` has been updated on the primary instance `inst` so it is
+               now coming from a root module, however all Dsymbol `inst.members`
+               of the instance still have their `_scope.minst` pointing at the
+               original non-root module. We must now propagate `minst` to all
+               members so that forward referenced dependencies that get
+               instantiated will also be appended to the root module, otherwise
+               there will be undefined references at link-time.  */
+            class InstMemberWalker : public Visitor
+            {
+            public:
+                TemplateInstance *inst;
+
+                InstMemberWalker(TemplateInstance *inst)
+                    : inst(inst) { }
+
+                void visit(Dsymbol *d)
+                {
+                    if (d->_scope)
+                        d->_scope->minst = inst->minst;
+                }
+
+                void visit(ScopeDsymbol *sds)
+                {
+                    if (!sds->members)
+                        return;
+                    for (size_t i = 0; i < sds->members->length; i++)
+                    {
+                        Dsymbol *s = (*sds->members)[i];
+                        s->accept(this);
+                    }
+                    visit((Dsymbol *)sds);
+                }
+
+                void visit(AttribDeclaration *ad)
+                {
+                    Dsymbols *d = ad->include(NULL);
+                    if (!d)
+                        return;
+                    for (size_t i = 0; i < d->length; i++)
+                    {
+                        Dsymbol *s = (*d)[i];
+                        s->accept(this);
+                    }
+                    visit((Dsymbol *)ad);
+                }
+
+                void visit(ConditionalDeclaration *cd)
+                {
+                    if (cd->condition->inc)
+                        visit((AttribDeclaration *)cd);
+                    else
+                        visit((Dsymbol *)cd);
+                }
+            };
+            InstMemberWalker v(tempinst->inst);
+            tempinst->inst->accept(&v);
+
+            if (tempinst->minst)  // if inst was not speculative
+            {
+                /* Add 'inst' once again to the root module members[], then the
+                 * instance members will get codegen chances.
+                 */
+                tempinst->inst->appendToModuleMember();
+            }
+        }
+
+        return;
+    }
+    unsigned errorsave = global.errors;
+
+    tempinst->inst = tempinst;
+    tempinst->parent = tempinst->enclosing ? tempinst->enclosing : tempdecl->parent;
+    //printf("parent = '%s'\n", tempinst->parent->kind());
+
+    TemplateInstance *tempdecl_instance_idx = tempdecl->addInstance(tempinst);
+
+    //getIdent();
+
+    // Store the place we added it to in target_symbol_list(_idx) so we can
+    // remove it later if we encounter an error.
+    Dsymbols *target_symbol_list = tempinst->appendToModuleMember();
+    size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list->length - 1 : 0;
+
+    // Copy the syntax trees from the TemplateDeclaration
+    tempinst->members = Dsymbol::arraySyntaxCopy(tempdecl->members);
+
+    // resolve TemplateThisParameter
+    for (size_t i = 0; i < tempdecl->parameters->length; i++)
+    {
+        if ((*tempdecl->parameters)[i]->isTemplateThisParameter() == NULL)
+            continue;
+        Type *t = isType((*tempinst->tiargs)[i]);
+        assert(t);
+        if (StorageClass stc = ModToStc(t->mod))
+        {
+            //printf("t = %s, stc = x%llx\n", t->toChars(), stc);
+            Dsymbols *s = new Dsymbols();
+            s->push(new StorageClassDeclaration(stc, tempinst->members));
+            tempinst->members = s;
+        }
+        break;
+    }
+
+    // Create our own scope for the template parameters
+    Scope *scope = tempdecl->_scope;
+    if (tempdecl->semanticRun == PASSinit)
+    {
+        tempinst->error("template instantiation %s forward references template declaration %s", tempinst->toChars(), tempdecl->toChars());
+        return;
+    }
+
+    tempinst->argsym = new ScopeDsymbol();
+    tempinst->argsym->parent = scope->parent;
+    scope = scope->push(tempinst->argsym);
+    scope->tinst = tempinst;
+    scope->minst = tempinst->minst;
+    //scope->stc = 0;
+
+    // Declare each template parameter as an alias for the argument type
+    Scope *paramscope = scope->push();
+    paramscope->stc = 0;
+    paramscope->protection = Prot(Prot::public_);  // Bugzilla 14169: template parameters should be public
+    tempinst->declareParameters(paramscope);
+    paramscope->pop();
+
+    // Add members of template instance to template instance symbol table
+//    tempinst->parent = scope->scopesym;
+    tempinst->symtab = new DsymbolTable();
+    for (size_t i = 0; i < tempinst->members->length; i++)
+    {
+        Dsymbol *s = (*tempinst->members)[i];
+        s->addMember(scope, tempinst);
+    }
+
+    /* See if there is only one member of template instance, and that
+     * member has the same name as the template instance.
+     * If so, this template instance becomes an alias for that member.
+     */
+    //printf("members->length = %d\n", tempinst->members->length);
+    if (tempinst->members->length)
+    {
+        Dsymbol *s;
+        if (Dsymbol::oneMembers(tempinst->members, &s, tempdecl->ident) && s)
+        {
+            //printf("tempdecl->ident = %s, s = '%s'\n", tempdecl->ident->toChars(), s->kind(), s->toPrettyChars());
+            //printf("setting aliasdecl\n");
+            tempinst->aliasdecl = s;
+        }
+    }
+
+    /* If function template declaration
+     */
+    if (fargs && tempinst->aliasdecl)
+    {
+        FuncDeclaration *fd = tempinst->aliasdecl->isFuncDeclaration();
+        if (fd)
+        {
+            /* Transmit fargs to type so that TypeFunction::semantic() can
+             * resolve any "auto ref" storage classes.
+             */
+            TypeFunction *tf = (TypeFunction *)fd->type;
+            if (tf && tf->ty == Tfunction)
+                tf->fargs = fargs;
+        }
+    }
+
+    // Do semantic() analysis on template instance members
+    Scope *sc2;
+    sc2 = scope->push(tempinst);
+    //printf("enclosing = %d, sc->parent = %s\n", tempinst->enclosing, sc->parent->toChars());
+    sc2->parent = tempinst;
+    sc2->tinst = tempinst;
+    sc2->minst = tempinst->minst;
+
+    tempinst->tryExpandMembers(sc2);
+
+    tempinst->semanticRun = PASSsemanticdone;
+
+    /* ConditionalDeclaration may introduce eponymous declaration,
+     * so we should find it once again after semantic.
+     */
+    if (tempinst->members->length)
+    {
+        Dsymbol *s;
+        if (Dsymbol::oneMembers(tempinst->members, &s, tempdecl->ident) && s)
+        {
+            if (!tempinst->aliasdecl || tempinst->aliasdecl != s)
+            {
+                //printf("tempdecl->ident = %s, s = '%s'\n", tempdecl->ident->toChars(), s->kind(), s->toPrettyChars());
+                //printf("setting aliasdecl 2\n");
+                tempinst->aliasdecl = s;
+            }
+        }
+    }
+
+    if (global.errors != errorsave)
+        goto Laftersemantic;
+
+    /* If any of the instantiation members didn't get semantic() run
+     * on them due to forward references, we cannot run semantic2()
+     * or semantic3() yet.
+     */
+    {
+    bool found_deferred_ad = false;
+    for (size_t i = 0; i < Module::deferred.length; i++)
+    {
+        Dsymbol *sd = Module::deferred[i];
+        AggregateDeclaration *ad = sd->isAggregateDeclaration();
+        if (ad && ad->parent && ad->parent->isTemplateInstance())
+        {
+            //printf("deferred template aggregate: %s %s\n",
+            //        sd->parent->toChars(), sd->toChars());
+            found_deferred_ad = true;
+            if (ad->parent == tempinst)
+            {
+                ad->deferred = tempinst;
+                break;
+            }
+        }
+    }
+    if (found_deferred_ad || Module::deferred.length)
+        goto Laftersemantic;
+    }
+
+    /* The problem is when to parse the initializer for a variable.
+     * Perhaps VarDeclaration::semantic() should do it like it does
+     * for initializers inside a function.
+     */
+    //if (sc->parent->isFuncDeclaration())
+    {
+        /* BUG 782: this has problems if the classes this depends on
+         * are forward referenced. Find a way to defer semantic()
+         * on this template.
+         */
+        semantic2(tempinst, sc2);
+    }
+    if (global.errors != errorsave)
+        goto Laftersemantic;
+
+    if ((sc->func || (sc->flags & SCOPEfullinst)) && !tempinst->tinst)
+    {
+        /* If a template is instantiated inside function, the whole instantiation
+         * should be done at that position. But, immediate running semantic3 of
+         * dependent templates may cause unresolved forward reference (Bugzilla 9050).
+         * To avoid the issue, don't run semantic3 until semantic and semantic2 done.
+         */
+        TemplateInstances deferred;
+        tempinst->deferred = &deferred;
+
+        //printf("Run semantic3 on %s\n", tempinst->toChars());
+        tempinst->trySemantic3(sc2);
+
+        for (size_t i = 0; i < deferred.length; i++)
+        {
+            //printf("+ run deferred semantic3 on %s\n", deferred[i]->toChars());
+            semantic3(deferred[i], NULL);
+        }
+
+        tempinst->deferred = NULL;
+    }
+    else if (tempinst->tinst)
+    {
+        bool doSemantic3 = false;
+        if (sc->func && tempinst->aliasdecl && tempinst->aliasdecl->toAlias()->isFuncDeclaration())
+        {
+            /* Template function instantiation should run semantic3 immediately
+             * for attribute inference.
+             */
+            tempinst->trySemantic3(sc2);
+        }
+        else if (sc->func)
+        {
+            /* A lambda function in template arguments might capture the
+             * instantiated scope context. For the correct context inference,
+             * all instantiated functions should run the semantic3 immediately.
+             * See also compilable/test14973.d
+             */
+            for (size_t i = 0; i < tempinst->tdtypes.length; i++)
+            {
+                RootObject *oarg = tempinst->tdtypes[i];
+                Dsymbol *s = getDsymbol(oarg);
+                if (!s)
+                    continue;
+
+                if (TemplateDeclaration *td = s->isTemplateDeclaration())
+                {
+                    if (!td->literal)
+                        continue;
+                    assert(td->members && td->members->length == 1);
+                    s = (*td->members)[0];
+                }
+                if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
+                {
+                    if (fld->tok == TOKreserved)
+                    {
+                        doSemantic3 = true;
+                        break;
+                    }
+                }
+            }
+            //printf("[%s] %s doSemantic3 = %d\n", tempinst->loc.toChars(), tempinst->toChars(), doSemantic3);
+        }
+        if (doSemantic3)
+            tempinst->trySemantic3(sc2);
+
+        TemplateInstance *ti = tempinst->tinst;
+        int nest = 0;
+        while (ti && !ti->deferred && ti->tinst)
+        {
+            ti = ti->tinst;
+            if (++nest > global.recursionLimit)
+            {
+                global.gag = 0;            // ensure error message gets printed
+                tempinst->error("recursive expansion");
+                fatal();
+            }
+        }
+        if (ti && ti->deferred)
+        {
+            //printf("deferred semantic3 of %p %s, ti = %s, ti->deferred = %p\n", tempinst, tempinst->toChars(), ti->toChars());
+            for (size_t i = 0; ; i++)
+            {
+                if (i == ti->deferred->length)
+                {
+                    ti->deferred->push(tempinst);
+                    break;
+                }
+                if ((*ti->deferred)[i] == tempinst)
+                    break;
+            }
+        }
+    }
+
+    if (tempinst->aliasdecl)
+    {
+        /* Bugzilla 13816: AliasDeclaration tries to resolve forward reference
+         * twice (See inuse check in AliasDeclaration::toAlias()). It's
+         * necessary to resolve mutual references of instantiated symbols, but
+         * it will left a true recursive alias in tuple declaration - an
+         * AliasDeclaration A refers TupleDeclaration B, and B contains A
+         * in its elements.  To correctly make it an error, we strictly need to
+         * resolve the alias of eponymous member.
+         */
+        tempinst->aliasdecl = tempinst->aliasdecl->toAlias2();
+    }
+
+  Laftersemantic:
+    sc2->pop();
+
+    scope->pop();
+
+    // Give additional context info if error occurred during instantiation
+    if (global.errors != errorsave)
+    {
+        if (!tempinst->errors)
+        {
+            if (!tempdecl->literal)
+                tempinst->error(tempinst->loc, "error instantiating");
+            if (tempinst->tinst)
+                tempinst->tinst->printInstantiationTrace();
+        }
+        tempinst->errors = true;
+        if (tempinst->gagged)
+        {
+            // Errors are gagged, so remove the template instance from the
+            // instance/symbol lists we added it to and reset our state to
+            // finish clean and so we can try to instantiate it again later
+            // (see bugzilla 4302 and 6602).
+            tempdecl->removeInstance(tempdecl_instance_idx);
+            if (target_symbol_list)
+            {
+                // Because we added 'this' in the last position above, we
+                // should be able to remove it without messing other indices up.
+                assert((*target_symbol_list)[target_symbol_list_idx] == tempinst);
+                target_symbol_list->remove(target_symbol_list_idx);
+                tempinst->memberOf = NULL;                    // no longer a member
+            }
+            tempinst->semanticRun = PASSinit;
+            tempinst->inst = NULL;
+            tempinst->symtab = NULL;
+        }
+    }
+    else if (errinst)
+    {
+        /* Bugzilla 14541: If the previous gagged instance had failed by
+         * circular references, currrent "error reproduction instantiation"
+         * might succeed, because of the difference of instantiated context.
+         * On such case, the cached error instance needs to be overridden by the
+         * succeeded instance.
+         */
+        //printf("replaceInstance()\n");
+        TemplateInstances *tinstances = (TemplateInstances *)dmd_aaGetRvalue((AA *)tempdecl->instances, (void *)tempinst->hash);
+        assert(tinstances);
+        for (size_t i = 0; i < tinstances->length; i++)
+        {
+            TemplateInstance *ti = (*tinstances)[i];
+            if (ti == errinst)
+            {
+                (*tinstances)[i] = tempinst;     // override
+                break;
+            }
+        }
+    }
+}
+
+// function used to perform semantic on AliasDeclaration
+void aliasSemantic(AliasDeclaration *ds, Scope *sc)
+{
+    //printf("AliasDeclaration::semantic() %s\n", ds->toChars());
+
+    // as AliasDeclaration::semantic, in case we're called first.
+    // see https://issues.dlang.org/show_bug.cgi?id=21001
+    ds->storage_class |= sc->stc & STCdeprecated;
+    ds->protection = sc->protection;
+    ds->userAttribDecl = sc->userAttribDecl;
+
+    // TypeTraits needs to know if it's located in an AliasDeclaration
+    sc->flags |= SCOPEalias;
+
+    if (ds->aliassym)
+    {
+        FuncDeclaration *fd = ds->aliassym->isFuncLiteralDeclaration();
+        TemplateDeclaration *td = ds->aliassym->isTemplateDeclaration();
+        if (fd || (td && td->literal))
+        {
+            if (fd && fd->semanticRun >= PASSsemanticdone)
+            {
+                sc->flags &= ~SCOPEalias;
+                return;
+            }
+
+            Expression *e = new FuncExp(ds->loc, ds->aliassym);
+            e = expressionSemantic(e, sc);
+            if (e->op == TOKfunction)
+            {
+                FuncExp *fe = (FuncExp *)e;
+                ds->aliassym = fe->td ? (Dsymbol *)fe->td : fe->fd;
+            }
+            else
+            {
+                ds->aliassym = NULL;
+                ds->type = Type::terror;
+            }
+            sc->flags &= ~SCOPEalias;
+            return;
+        }
+
+        if (ds->aliassym->isTemplateInstance())
+            dsymbolSemantic(ds->aliassym, sc);
+        sc->flags &= ~SCOPEalias;
+        return;
+    }
+    ds->inuse = 1;
+
+    // Given:
+    //  alias foo.bar.abc def;
+    // it is not knowable from the syntax whether this is an alias
+    // for a type or an alias for a symbol. It is up to the semantic()
+    // pass to distinguish.
+    // If it is a type, then type is set and getType() will return that
+    // type. If it is a symbol, then aliassym is set and type is NULL -
+    // toAlias() will return aliasssym.
+
+    unsigned int errors = global.errors;
+    Type *oldtype = ds->type;
+
+    // Ungag errors when not instantiated DeclDefs scope alias
+    Ungag ungag(global.gag);
+    //printf("%s parent = %s, gag = %d, instantiated = %d\n", ds->toChars(), ds->parent, global.gag, ds->isInstantiated());
+    if (ds->parent && global.gag && !ds->isInstantiated() && !ds->toParent2()->isFuncDeclaration())
+    {
+        //printf("%s type = %s\n", ds->toPrettyChars(), ds->type->toChars());
+        global.gag = 0;
+    }
+
+    /* This section is needed because Type::resolve() will:
+     *   const x = 3;
+     *   alias y = x;
+     * try to convert identifier x to 3.
+     */
+    Dsymbol *s = ds->type->toDsymbol(sc);
+    if (errors != global.errors)
+    {
+        s = NULL;
+        ds->type = Type::terror;
+    }
+    if (s && s == ds)
+    {
+        ds->error("cannot resolve");
+        s = NULL;
+        ds->type = Type::terror;
+    }
+    if (!s || !s->isEnumMember())
+    {
+        Type *t;
+        Expression *e;
+        Scope *sc2 = sc;
+        if (ds->storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable))
+        {
+            // For 'ref' to be attached to function types, and picked
+            // up by Type::resolve(), it has to go into sc.
+            sc2 = sc->push();
+            sc2->stc |= ds->storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCshared | STCdisable);
+        }
+        ds->type = ds->type->addSTC(ds->storage_class);
+        ds->type->resolve(ds->loc, sc2, &e, &t, &s);
+        if (sc2 != sc)
+            sc2->pop();
+
+        if (e)  // Try to convert Expression to Dsymbol
+        {
+            s = getDsymbol(e);
+            if (!s)
+            {
+                if (e->op != TOKerror)
+                    ds->error("cannot alias an expression %s", e->toChars());
+                t = Type::terror;
+            }
+        }
+        ds->type = t;
+    }
+    if (s == ds)
+    {
+        assert(global.errors);
+        ds->type = Type::terror;
+        s = NULL;
+    }
+    if (!s) // it's a type alias
+    {
+        //printf("alias %s resolved to type %s\n", ds->toChars(), ds->type->toChars());
+        ds->type = typeSemantic(ds->type, ds->loc, sc);
+        ds->aliassym = NULL;
+    }
+    else    // it's a symbolic alias
+    {
+        //printf("alias %s resolved to %s %s\n", ds->toChars(), s->kind(), s->toChars());
+        ds->type = NULL;
+        ds->aliassym = s;
+    }
+    if (global.gag && errors != global.errors)
+    {
+        ds->type = oldtype;
+        ds->aliassym = NULL;
+    }
+    ds->inuse = 0;
+    ds->semanticRun = PASSsemanticdone;
+
+    if (Dsymbol *sx = ds->overnext)
+    {
+        ds->overnext = NULL;
+
+        if (!ds->overloadInsert(sx))
+            ScopeDsymbol::multiplyDefined(Loc(), sx, ds);
+    }
+    sc->flags &= ~SCOPEalias;
+}
+
+
+/*************************************
+ * Does semantic analysis on the public face of declarations.
+ */
+void dsymbolSemantic(Dsymbol *dsym, Scope *sc)
+{
+    DsymbolSemanticVisitor v(sc);
+    dsym->accept(&v);
+}
index 316f105b9e33cc0f27116357ed8e614715ee90a0..b868e9ad3887a07af86394e37c695e6c0d9da665 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -47,8 +47,7 @@ static size_t templateParameterLookup(Type *tparam, TemplateParameters *paramete
 static int arrayObjectMatch(Objects *oa1, Objects *oa2);
 static unsigned char deduceWildHelper(Type *t, Type **at, Type *tparam);
 static MATCH deduceTypeHelper(Type *t, Type **at, Type *tparam);
-static bool reliesOnTident(Type *t, TemplateParameters *tparams = NULL, size_t iStart = 0);
-Expression *semantic(Expression *e, Scope *sc);
+bool reliesOnTident(Type *t, TemplateParameters *tparams = NULL, size_t iStart = 0);
 bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors);
 
 /********************************************
@@ -568,127 +567,6 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
         Dsymbol::arraySyntaxCopy(members), ismixin, literal);
 }
 
-void TemplateDeclaration::semantic(Scope *sc)
-{
-    if (semanticRun != PASSinit)
-        return;         // semantic() already run
-
-    // Remember templates defined in module object that we need to know about
-    if (sc->_module && sc->_module->ident == Id::object)
-    {
-        if (ident == Id::RTInfo)
-            Type::rtinfo = this;
-    }
-
-    /* Remember Scope for later instantiations, but make
-     * a copy since attributes can change.
-     */
-    if (!this->_scope)
-    {
-        this->_scope = sc->copy();
-        this->_scope->setNoFree();
-    }
-
-    semanticRun = PASSsemantic;
-
-    parent = sc->parent;
-    protection = sc->protection;
-    isstatic = toParent()->isModule() || (_scope->stc & STCstatic);
-
-    if (!isstatic)
-    {
-        if (AggregateDeclaration *ad = parent->pastMixin()->isAggregateDeclaration())
-            ad->makeNested();
-    }
-
-    // Set up scope for parameters
-    ScopeDsymbol *paramsym = new ScopeDsymbol();
-    paramsym->parent = parent;
-    Scope *paramscope = sc->push(paramsym);
-    paramscope->stc = 0;
-
-    if (global.params.doDocComments)
-    {
-        origParameters = new TemplateParameters();
-        origParameters->setDim(parameters->length);
-        for (size_t i = 0; i < parameters->length; i++)
-        {
-            TemplateParameter *tp = (*parameters)[i];
-            (*origParameters)[i] = tp->syntaxCopy();
-        }
-    }
-
-    for (size_t i = 0; i < parameters->length; i++)
-    {
-        TemplateParameter *tp = (*parameters)[i];
-
-        if (!tp->declareParameter(paramscope))
-        {
-            error(tp->loc, "parameter '%s' multiply defined", tp->ident->toChars());
-            errors = true;
-        }
-        if (!tp->semantic(paramscope, parameters))
-        {
-            errors = true;
-        }
-        if (i + 1 != parameters->length && tp->isTemplateTupleParameter())
-        {
-            error("template tuple parameter must be last one");
-            errors = true;
-        }
-    }
-
-    /* Calculate TemplateParameter::dependent
-     */
-    TemplateParameters tparams;
-    tparams.setDim(1);
-    for (size_t i = 0; i < parameters->length; i++)
-    {
-        TemplateParameter *tp = (*parameters)[i];
-        tparams[0] = tp;
-
-        for (size_t j = 0; j < parameters->length; j++)
-        {
-            // Skip cases like: X(T : T)
-            if (i == j)
-                continue;
-
-            if (TemplateTypeParameter *ttp = (*parameters)[j]->isTemplateTypeParameter())
-            {
-                if (reliesOnTident(ttp->specType, &tparams))
-                    tp->dependent = true;
-            }
-            else if (TemplateAliasParameter *tap = (*parameters)[j]->isTemplateAliasParameter())
-            {
-                if (reliesOnTident(tap->specType, &tparams) ||
-                    reliesOnTident(isType(tap->specAlias), &tparams))
-                {
-                    tp->dependent = true;
-                }
-            }
-        }
-    }
-
-    paramscope->pop();
-
-    // Compute again
-    onemember = NULL;
-    if (members)
-    {
-        Dsymbol *s;
-        if (Dsymbol::oneMembers(members, &s, ident) && s)
-        {
-            onemember = s;
-            s->parent = this;
-        }
-    }
-
-    /* BUG: should check:
-     *  o no virtual functions or non-static data members of classes
-     */
-    semanticRun = PASSsemanticdone;
-}
-
 const char *TemplateDeclaration::kind() const
 {
     return (onemember && onemember->isAggregateDeclaration())
@@ -806,7 +684,7 @@ bool TemplateDeclaration::evaluateConstraint(
                 continue;                       // don't add it, if it has no name
             VarDeclaration *v = new VarDeclaration(loc, fparam->type, fparam->ident, NULL);
             v->storage_class = fparam->storageClass;
-            v->semantic(scx);
+            dsymbolSemantic(v, scx);
             if (!ti->symtab)
                 ti->symtab = new DsymbolTable();
             if (!scx->insert(v))
@@ -904,7 +782,7 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
             m = m2;
 
         if (!flag)
-            sparam->semantic(paramscope);
+            dsymbolSemantic(sparam, paramscope);
         if (!paramscope->insert(sparam))    // TODO: This check can make more early
             goto Lnomatch;                  // in TemplateDeclaration::semantic, and
                                             // then we don't need to make sparam if flags == 0
@@ -951,7 +829,7 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
             // Resolve parameter types and 'auto ref's.
             tf->fargs = fargs;
             unsigned olderrors = global.startGagging();
-            fd->type = tf->semantic(loc, paramscope);
+            fd->type = typeSemantic(tf, loc, paramscope);
             if (global.endGagging(olderrors))
             {
                 assert(fd->type->ty != Tfunction);
@@ -1187,7 +1065,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(
             if (m < matchTiargs)
                 matchTiargs = m;
 
-            sparam->semantic(paramscope);
+            dsymbolSemantic(sparam, paramscope);
             if (!paramscope->insert(sparam))
                 goto Lnomatch;
         }
@@ -1351,7 +1229,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(
                     Parameter *p = fparameters[j];
                     if (!reliesOnTident(p->type, parameters, inferStart))
                     {
-                        Type *pt = p->type->syntaxCopy()->semantic(fd->loc, paramscope);
+                        Type *pt = typeSemantic(p->type->syntaxCopy(), fd->loc, paramscope);
                         rem += pt->ty == Ttuple ? ((TypeTuple *)pt)->arguments->length : 1;
                     }
                     else
@@ -1423,7 +1301,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(
         if (!reliesOnTident(prmtype, parameters, inferStart))
         {
             // should copy prmtype to avoid affecting semantic result
-            prmtype = prmtype->syntaxCopy()->semantic(fd->loc, paramscope);
+            prmtype = typeSemantic(prmtype->syntaxCopy(), fd->loc, paramscope);
 
             if (prmtype->ty == Ttuple)
             {
@@ -1551,7 +1429,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(
 
             // Deduce prmtype from the defaultArg.
             farg = fparam->defaultArg->syntaxCopy();
-            farg = ::semantic(farg, paramscope);
+            farg = expressionSemantic(farg, paramscope);
             farg = resolveProperties(paramscope, farg);
         }
         else
@@ -1773,7 +1651,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(
                         }
                         else
                         {
-                            Type *vt = tvp->valType->semantic(Loc(), sc);
+                            Type *vt = typeSemantic(tvp->valType, Loc(), sc);
                             MATCH m = (MATCH)dim->implicitConvTo(vt);
                             if (m <= MATCHnomatch)
                                 goto Lnomatch;
@@ -2079,7 +1957,7 @@ RootObject *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *
 
     if (!sc->insert(d))
         error("declaration %s is already defined", tp->ident->toChars());
-    d->semantic(sc);
+    dsymbolSemantic(d, sc);
 
     /* So the caller's o gets updated with the result of semantic() being run on o
      */
@@ -2176,7 +2054,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
                 fd->semanticRun < PASSsemanticdone)
             {
                 Ungag ungag = fd->ungagSpeculative();
-                fd->semantic(NULL);
+                dsymbolSemantic(fd, NULL);
             }
             if (fd->semanticRun < PASSsemanticdone)
             {
@@ -2313,7 +2191,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
             {
                 // Try to fix forward reference. Ungag errors while doing so.
                 Ungag ungag = td->ungagSpeculative();
-                td->semantic(td->_scope);
+                dsymbolSemantic(td, td->_scope);
             }
             if (td->semanticRun == PASSinit)
             {
@@ -2341,7 +2219,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
                 if (mta <= MATCHnomatch || mta < ta_last)      // no match or less match
                     return 0;
 
-                ti->semantic(sc, fargs);
+                templateInstanceSemantic(ti, sc, fargs);
                 if (!ti->inst)                  // if template failed to expand
                     return 0;
 
@@ -2583,7 +2461,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
             sc = p.td_best->_scope; // workaround for Type::aliasthisOf
 
         TemplateInstance *ti = new TemplateInstance(loc, p.td_best, p.ti_best->tiargs);
-        ti->semantic(sc, fargs);
+        templateInstanceSemantic(ti, sc, fargs);
 
         m->lastf = ti->toAlias()->isFuncDeclaration();
         if (!m->lastf)
@@ -2623,7 +2501,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
          */
         if (tf->next && !m->lastf->inferRetType)
         {
-            m->lastf->type = tf->semantic(loc, sc);
+            m->lastf->type = typeSemantic(tf, loc, sc);
         }
     }
     else if (m->lastf)
@@ -2713,7 +2591,7 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(
         tf->next = NULL;
     fd->type = tf;
     fd->type = fd->type->addSTC(scx->stc);
-    fd->type = fd->type->semantic(fd->loc, scx);
+    fd->type = typeSemantic(fd->type, fd->loc, scx);
     scx = scx->pop();
 
     if (fd->type->ty != Tfunction)
@@ -3199,7 +3077,7 @@ MATCH deduceType(RootObject *o, Scope *sc, Type *tparam, TemplateParameters *par
                     /* BUG: what if tparam is a template instance, that
                      * has as an argument another Tident?
                      */
-                    tparam = tparam->semantic(loc, sc);
+                    tparam = typeSemantic(tparam, loc, sc);
                     assert(tparam->ty != Tident);
                     result = deduceType(t, sc, tparam, parameters, dedtypes, wm);
                     return;
@@ -3371,7 +3249,7 @@ MATCH deduceType(RootObject *o, Scope *sc, Type *tparam, TemplateParameters *par
                     loc = tp->loc;
                 }
 
-                tparam = tparam->semantic(loc, sc);
+                tparam = typeSemantic(tparam, loc, sc);
             }
             if (t->ty != tparam->ty)
             {
@@ -3848,7 +3726,7 @@ MATCH deduceType(RootObject *o, Scope *sc, Type *tparam, TemplateParameters *par
                             // (it may be from a parent template, for example)
                         }
 
-                        e2 = ::semantic(e2, sc);      // Bugzilla 13417
+                        e2 = expressionSemantic(e2, sc);      // Bugzilla 13417
                         e2 = e2->ctfeInterpret();
 
                         //printf("e1 = %s, type = %s %d\n", e1->toChars(), e1->type->toChars(), e1->type->ty);
@@ -4459,7 +4337,7 @@ MATCH deduceType(RootObject *o, Scope *sc, Type *tparam, TemplateParameters *par
                     Type *t = pto->type->syntaxCopy();  // Bugzilla 11774
                     if (reliesOnTident(t, parameters, inferStart))
                         return;
-                    t = t->semantic(e->loc, sc);
+                    t = typeSemantic(t, e->loc, sc);
                     if (t->ty == Terror)
                         return;
                     tiargs->push(t);
@@ -4471,7 +4349,7 @@ MATCH deduceType(RootObject *o, Scope *sc, Type *tparam, TemplateParameters *par
 
                 TemplateInstance *ti = new TemplateInstance(e->loc, e->td, tiargs);
                 Expression *ex = new ScopeExp(e->loc, ti);
-                ex = ::semantic(ex, e->td->_scope);
+                ex = expressionSemantic(ex, e->td->_scope);
 
                 // Reset inference target for the later re-semantic
                 e->fd->treq = NULL;
@@ -5041,16 +4919,6 @@ bool TemplateTypeParameter::declareParameter(Scope *sc)
     return sc->insert(ad) != NULL;
 }
 
-bool TemplateTypeParameter::semantic(Scope *sc, TemplateParameters *parameters)
-{
-    //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
-    if (specType && !reliesOnTident(specType, parameters))
-    {
-        specType = specType->semantic(loc, sc);
-    }
-    return !(specType && isError(specType));
-}
-
 MATCH TemplateTypeParameter::matchArg(Scope *sc, RootObject *oarg,
         size_t i, TemplateParameters *parameters, Objects *dedtypes,
         Declaration **psparam)
@@ -5171,7 +5039,7 @@ RootObject *TemplateTypeParameter::defaultArg(Loc, Scope *sc)
     if (t)
     {
         t = t->syntaxCopy();
-        t = t->semantic(loc, sc);   // use the parameter loc
+        t = typeSemantic(t, loc, sc);   // use the parameter loc
     }
     return t;
 }
@@ -5240,42 +5108,6 @@ bool TemplateAliasParameter::declareParameter(Scope *sc)
     return sc->insert(ad) != NULL;
 }
 
-static RootObject *aliasParameterSemantic(Loc loc, Scope *sc, RootObject *o, TemplateParameters *parameters)
-{
-    if (o)
-    {
-        Expression *ea = isExpression(o);
-        Type *ta = isType(o);
-        if (ta && (!parameters || !reliesOnTident(ta, parameters)))
-        {
-            Dsymbol *s = ta->toDsymbol(sc);
-            if (s)
-                o = s;
-            else
-                o = ta->semantic(loc, sc);
-        }
-        else if (ea)
-        {
-            sc = sc->startCTFE();
-            ea = ::semantic(ea, sc);
-            sc = sc->endCTFE();
-            o = ea->ctfeInterpret();
-        }
-    }
-    return o;
-}
-
-bool TemplateAliasParameter::semantic(Scope *sc, TemplateParameters *parameters)
-{
-    if (specType && !reliesOnTident(specType, parameters))
-    {
-        specType = specType->semantic(loc, sc);
-    }
-    specAlias = aliasParameterSemantic(loc, sc, specAlias, parameters);
-    return !(specType  && isError(specType)) &&
-           !(specAlias && isError(specAlias));
-}
-
 MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
         size_t i, TemplateParameters *parameters, Objects *dedtypes,
         Declaration **psparam)
@@ -5391,7 +5223,7 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
             Initializer *init = new ExpInitializer(loc, ea);
             VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
             v->storage_class = STCmanifest;
-            v->semantic(sc);
+            dsymbolSemantic(v, sc);
             *psparam = v;
         }
     }
@@ -5491,13 +5323,6 @@ bool TemplateValueParameter::declareParameter(Scope *sc)
     return sc->insert(v) != NULL;
 }
 
-bool TemplateValueParameter::semantic(Scope *sc, TemplateParameters *)
-{
-    valType = valType->semantic(loc, sc);
-
-    return !isError(valType);
-}
-
 MATCH TemplateValueParameter::matchArg(Scope *sc, RootObject *oarg,
         size_t i, TemplateParameters *, Objects *dedtypes, Declaration **psparam)
 {
@@ -5516,7 +5341,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, RootObject *oarg,
             goto Lnomatch;
 
         ei = new VarExp(loc, f);
-        ei = ::semantic(ei, sc);
+        ei = expressionSemantic(ei, sc);
 
         /* If a function is really property-like, and then
          * it's CTFEable, ei will be a literal expression.
@@ -5552,7 +5377,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, RootObject *oarg,
     }
 
     //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty);
-    vt = valType->semantic(loc, sc);
+    vt = typeSemantic(valType, loc, sc);
     //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars());
     //printf("vt = %s\n", vt->toChars());
 
@@ -5576,7 +5401,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, RootObject *oarg,
         Expression *e = specValue;
 
         sc = sc->startCTFE();
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         e = resolveProperties(sc, e);
         sc = sc->endCTFE();
         e = e->implicitCastTo(sc, vt);
@@ -5584,7 +5409,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, RootObject *oarg,
 
         ei = ei->syntaxCopy();
         sc = sc->startCTFE();
-        ei = ::semantic(ei, sc);
+        ei = expressionSemantic(ei, sc);
         sc = sc->endCTFE();
         ei = ei->implicitCastTo(sc, vt);
         ei = ei->ctfeInterpret();
@@ -5660,7 +5485,7 @@ RootObject *TemplateValueParameter::defaultArg(Loc instLoc, Scope *sc)
     if (e)
     {
         e = e->syntaxCopy();
-        if ((e = ::semantic(e, sc)) == NULL)
+        if ((e = expressionSemantic(e, sc)) == NULL)
             return NULL;
         if ((e = resolveProperties(sc, e)) == NULL)
             return NULL;
@@ -5702,11 +5527,6 @@ bool TemplateTupleParameter::declareParameter(Scope *sc)
     return sc->insert(ad) != NULL;
 }
 
-bool TemplateTupleParameter::semantic(Scope *, TemplateParameters *)
-{
-    return true;
-}
-
 MATCH TemplateTupleParameter::matchArg(Loc, Scope *sc, Objects *tiargs,
         size_t i, TemplateParameters *parameters, Objects *dedtypes,
         Declaration **psparam)
@@ -5902,11 +5722,6 @@ Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
     return ti;
 }
 
-void TemplateInstance::semantic(Scope *sc)
-{
-    semantic(sc, NULL);
-}
-
 void TemplateInstance::expandMembers(Scope *sc2)
 {
     for (size_t i = 0; i < members->length; i++)
@@ -5929,7 +5744,7 @@ void TemplateInstance::expandMembers(Scope *sc2)
 //      if (enclosing)
 //          s->parent = sc->parent;
         //printf("test3: enclosing = %d, s->parent = %s\n", enclosing, s->parent->toChars());
-        s->semantic(sc2);
+        dsymbolSemantic(s, sc2);
         //printf("test4: enclosing = %d, s->parent = %s\n", enclosing, s->parent->toChars());
         Module::runDeferredSemantic();
     }
@@ -5963,559 +5778,11 @@ void TemplateInstance::trySemantic3(Scope *sc2)
         error("recursive expansion exceeded allowed nesting limit");
         fatal();
     }
-    semantic3(sc2);
+    semantic3(this, sc2);
 
     --nest;
 }
 
-void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
-{
-    //printf("[%s] TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", loc.toChars(), toChars(), this, global.gag, sc);
-    if (inst)           // if semantic() was already run
-    {
-        return;
-    }
-    if (semanticRun != PASSinit)
-    {
-        Ungag ungag(global.gag);
-        if (!gagged)
-            global.gag = 0;
-        error(loc, "recursive template expansion");
-        if (gagged)
-            semanticRun = PASSinit;
-        else
-            inst = this;
-        errors = true;
-        return;
-    }
-
-    // Get the enclosing template instance from the scope tinst
-    tinst = sc->tinst;
-
-    // Get the instantiating module from the scope minst
-    minst = sc->minst;
-    // Bugzilla 10920: If the enclosing function is non-root symbol,
-    // this instance should be speculative.
-    if (!tinst && sc->func && sc->func->inNonRoot())
-    {
-        minst = NULL;
-    }
-
-    gagged = (global.gag > 0);
-
-    semanticRun = PASSsemantic;
-
-    /* Find template declaration first,
-     * then run semantic on each argument (place results in tiargs[]),
-     * last find most specialized template from overload list/set.
-     */
-    if (!findTempDecl(sc, NULL) ||
-        !semanticTiargs(sc) ||
-        !findBestMatch(sc, fargs))
-    {
-Lerror:
-        if (gagged)
-        {
-            // Bugzilla 13220: Rollback status for later semantic re-running.
-            semanticRun = PASSinit;
-        }
-        else
-            inst = this;
-        errors = true;
-        return;
-    }
-    TemplateDeclaration *tempdecl = this->tempdecl->isTemplateDeclaration();
-    assert(tempdecl);
-
-    // If tempdecl is a mixin, disallow it
-    if (tempdecl->ismixin)
-    {
-        error("mixin templates are not regular templates");
-        goto Lerror;
-    }
-
-    hasNestedArgs(tiargs, tempdecl->isstatic);
-    if (errors)
-        goto Lerror;
-
-    /* See if there is an existing TemplateInstantiation that already
-     * implements the typeargs. If so, just refer to that one instead.
-     */
-    inst = tempdecl->findExistingInstance(this, fargs);
-    TemplateInstance *errinst = NULL;
-    if (!inst)
-    {
-        // So, we need to implement 'this' instance.
-    }
-    else if (inst->gagged && !gagged && inst->errors)
-    {
-        // If the first instantiation had failed, re-run semantic,
-        // so that error messages are shown.
-        errinst = inst;
-    }
-    else
-    {
-        // It's a match
-        parent = inst->parent;
-        errors = inst->errors;
-
-        // If both this and the previous instantiation were gagged,
-        // use the number of errors that happened last time.
-        global.errors += errors;
-        global.gaggedErrors += errors;
-
-        // If the first instantiation was gagged, but this is not:
-        if (inst->gagged)
-        {
-            // It had succeeded, mark it is a non-gagged instantiation,
-            // and reuse it.
-            inst->gagged = gagged;
-        }
-
-        this->tnext = inst->tnext;
-        inst->tnext = this;
-
-        /* A module can have explicit template instance and its alias
-         * in module scope (e,g, `alias Base64 = Base64Impl!('+', '/');`).
-         * If the first instantiation 'inst' had happened in non-root module,
-         * compiler can assume that its instantiated code would be included
-         * in the separately compiled obj/lib file (e.g. phobos.lib).
-         *
-         * However, if 'this' second instantiation happened in root module,
-         * compiler might need to invoke its codegen (Bugzilla 2500 & 2644).
-         * But whole import graph is not determined until all semantic pass finished,
-         * so 'inst' should conservatively finish the semantic3 pass for the codegen.
-         */
-        if (minst && minst->isRoot() && !(inst->minst && inst->minst->isRoot()))
-        {
-            /* Swap the position of 'inst' and 'this' in the instantiation graph.
-             * Then, the primary instance `inst` will be changed to a root instance,
-             * along with all members of `inst` having their scopes updated.
-             *
-             * Before:
-             *  non-root -> A!() -> B!()[inst] -> C!() { members[non-root] }
-             *                      |
-             *  root     -> D!() -> B!()[this]
-             *
-             * After:
-             *  non-root -> A!() -> B!()[this]
-             *                      |
-             *  root     -> D!() -> B!()[inst] -> C!() { members[root] }
-             */
-            Module *mi = minst;
-            TemplateInstance *ti = tinst;
-            minst = inst->minst;
-            tinst = inst->tinst;
-            inst->minst = mi;
-            inst->tinst = ti;
-
-            /* https://issues.dlang.org/show_bug.cgi?id=21299
-               `minst` has been updated on the primary instance `inst` so it is
-               now coming from a root module, however all Dsymbol `inst.members`
-               of the instance still have their `_scope.minst` pointing at the
-               original non-root module. We must now propagate `minst` to all
-               members so that forward referenced dependencies that get
-               instantiated will also be appended to the root module, otherwise
-               there will be undefined references at link-time.  */
-            class InstMemberWalker : public Visitor
-            {
-            public:
-                TemplateInstance *inst;
-
-                InstMemberWalker(TemplateInstance *inst)
-                    : inst(inst) { }
-
-                void visit(Dsymbol *d)
-                {
-                    if (d->_scope)
-                        d->_scope->minst = inst->minst;
-                }
-
-                void visit(ScopeDsymbol *sds)
-                {
-                    if (!sds->members)
-                        return;
-                    for (size_t i = 0; i < sds->members->length; i++)
-                    {
-                        Dsymbol *s = (*sds->members)[i];
-                        s->accept(this);
-                    }
-                    visit((Dsymbol *)sds);
-                }
-
-                void visit(AttribDeclaration *ad)
-                {
-                    Dsymbols *d = ad->include(NULL);
-                    if (!d)
-                        return;
-                    for (size_t i = 0; i < d->length; i++)
-                    {
-                        Dsymbol *s = (*d)[i];
-                        s->accept(this);
-                    }
-                    visit((Dsymbol *)ad);
-                }
-
-                void visit(ConditionalDeclaration *cd)
-                {
-                    if (cd->condition->inc)
-                        visit((AttribDeclaration *)cd);
-                    else
-                        visit((Dsymbol *)cd);
-                }
-            };
-            InstMemberWalker v(inst);
-            inst->accept(&v);
-
-            if (minst)  // if inst was not speculative
-            {
-                /* Add 'inst' once again to the root module members[], then the
-                 * instance members will get codegen chances.
-                 */
-                inst->appendToModuleMember();
-            }
-        }
-
-        return;
-    }
-    unsigned errorsave = global.errors;
-
-    inst = this;
-    parent = enclosing ? enclosing : tempdecl->parent;
-    //printf("parent = '%s'\n", parent->kind());
-
-    TemplateInstance *tempdecl_instance_idx = tempdecl->addInstance(this);
-
-    //getIdent();
-
-    // Store the place we added it to in target_symbol_list(_idx) so we can
-    // remove it later if we encounter an error.
-    Dsymbols *target_symbol_list = appendToModuleMember();
-    size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list->length - 1 : 0;
-
-    // Copy the syntax trees from the TemplateDeclaration
-    members = Dsymbol::arraySyntaxCopy(tempdecl->members);
-
-    // resolve TemplateThisParameter
-    for (size_t i = 0; i < tempdecl->parameters->length; i++)
-    {
-        if ((*tempdecl->parameters)[i]->isTemplateThisParameter() == NULL)
-            continue;
-        Type *t = isType((*tiargs)[i]);
-        assert(t);
-        if (StorageClass stc = ModToStc(t->mod))
-        {
-            //printf("t = %s, stc = x%llx\n", t->toChars(), stc);
-            Dsymbols *s = new Dsymbols();
-            s->push(new StorageClassDeclaration(stc, members));
-            members = s;
-        }
-        break;
-    }
-
-    // Create our own scope for the template parameters
-    Scope *scope = tempdecl->_scope;
-    if (tempdecl->semanticRun == PASSinit)
-    {
-        error("template instantiation %s forward references template declaration %s", toChars(), tempdecl->toChars());
-        return;
-    }
-
-    argsym = new ScopeDsymbol();
-    argsym->parent = scope->parent;
-    scope = scope->push(argsym);
-    scope->tinst = this;
-    scope->minst = minst;
-    //scope->stc = 0;
-
-    // Declare each template parameter as an alias for the argument type
-    Scope *paramscope = scope->push();
-    paramscope->stc = 0;
-    paramscope->protection = Prot(Prot::public_);  // Bugzilla 14169: template parameters should be public
-    declareParameters(paramscope);
-    paramscope->pop();
-
-    // Add members of template instance to template instance symbol table
-//    parent = scope->scopesym;
-    symtab = new DsymbolTable();
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->addMember(scope, this);
-    }
-
-    /* See if there is only one member of template instance, and that
-     * member has the same name as the template instance.
-     * If so, this template instance becomes an alias for that member.
-     */
-    //printf("members->length = %d\n", members->length);
-    if (members->length)
-    {
-        Dsymbol *s;
-        if (Dsymbol::oneMembers(members, &s, tempdecl->ident) && s)
-        {
-            //printf("tempdecl->ident = %s, s = '%s'\n", tempdecl->ident->toChars(), s->kind(), s->toPrettyChars());
-            //printf("setting aliasdecl\n");
-            aliasdecl = s;
-        }
-    }
-
-    /* If function template declaration
-     */
-    if (fargs && aliasdecl)
-    {
-        FuncDeclaration *fd = aliasdecl->isFuncDeclaration();
-        if (fd)
-        {
-            /* Transmit fargs to type so that TypeFunction::semantic() can
-             * resolve any "auto ref" storage classes.
-             */
-            TypeFunction *tf = (TypeFunction *)fd->type;
-            if (tf && tf->ty == Tfunction)
-                tf->fargs = fargs;
-        }
-    }
-
-    // Do semantic() analysis on template instance members
-    Scope *sc2;
-    sc2 = scope->push(this);
-    //printf("enclosing = %d, sc->parent = %s\n", enclosing, sc->parent->toChars());
-    sc2->parent = this;
-    sc2->tinst = this;
-    sc2->minst = minst;
-
-    tryExpandMembers(sc2);
-
-    semanticRun = PASSsemanticdone;
-
-    /* ConditionalDeclaration may introduce eponymous declaration,
-     * so we should find it once again after semantic.
-     */
-    if (members->length)
-    {
-        Dsymbol *s;
-        if (Dsymbol::oneMembers(members, &s, tempdecl->ident) && s)
-        {
-            if (!aliasdecl || aliasdecl != s)
-            {
-                //printf("tempdecl->ident = %s, s = '%s'\n", tempdecl->ident->toChars(), s->kind(), s->toPrettyChars());
-                //printf("setting aliasdecl 2\n");
-                aliasdecl = s;
-            }
-        }
-    }
-
-    if (global.errors != errorsave)
-        goto Laftersemantic;
-
-    /* If any of the instantiation members didn't get semantic() run
-     * on them due to forward references, we cannot run semantic2()
-     * or semantic3() yet.
-     */
-    {
-    bool found_deferred_ad = false;
-    for (size_t i = 0; i < Module::deferred.length; i++)
-    {
-        Dsymbol *sd = Module::deferred[i];
-        AggregateDeclaration *ad = sd->isAggregateDeclaration();
-        if (ad && ad->parent && ad->parent->isTemplateInstance())
-        {
-            //printf("deferred template aggregate: %s %s\n",
-            //        sd->parent->toChars(), sd->toChars());
-            found_deferred_ad = true;
-            if (ad->parent == this)
-            {
-                ad->deferred = this;
-                break;
-            }
-        }
-    }
-    if (found_deferred_ad || Module::deferred.length)
-        goto Laftersemantic;
-    }
-
-    /* The problem is when to parse the initializer for a variable.
-     * Perhaps VarDeclaration::semantic() should do it like it does
-     * for initializers inside a function.
-     */
-    //if (sc->parent->isFuncDeclaration())
-    {
-        /* BUG 782: this has problems if the classes this depends on
-         * are forward referenced. Find a way to defer semantic()
-         * on this template.
-         */
-        semantic2(sc2);
-    }
-    if (global.errors != errorsave)
-        goto Laftersemantic;
-
-    if ((sc->func || (sc->flags & SCOPEfullinst)) && !tinst)
-    {
-        /* If a template is instantiated inside function, the whole instantiation
-         * should be done at that position. But, immediate running semantic3 of
-         * dependent templates may cause unresolved forward reference (Bugzilla 9050).
-         * To avoid the issue, don't run semantic3 until semantic and semantic2 done.
-         */
-        TemplateInstances deferred;
-        this->deferred = &deferred;
-
-        //printf("Run semantic3 on %s\n", toChars());
-        trySemantic3(sc2);
-
-        for (size_t i = 0; i < deferred.length; i++)
-        {
-            //printf("+ run deferred semantic3 on %s\n", deferred[i]->toChars());
-            deferred[i]->semantic3(NULL);
-        }
-
-        this->deferred = NULL;
-    }
-    else if (tinst)
-    {
-        bool doSemantic3 = false;
-        if (sc->func && aliasdecl && aliasdecl->toAlias()->isFuncDeclaration())
-        {
-            /* Template function instantiation should run semantic3 immediately
-             * for attribute inference.
-             */
-            trySemantic3(sc2);
-        }
-        else if (sc->func)
-        {
-            /* A lambda function in template arguments might capture the
-             * instantiated scope context. For the correct context inference,
-             * all instantiated functions should run the semantic3 immediately.
-             * See also compilable/test14973.d
-             */
-            for (size_t i = 0; i < tdtypes.length; i++)
-            {
-                RootObject *oarg = tdtypes[i];
-                Dsymbol *s = getDsymbol(oarg);
-                if (!s)
-                    continue;
-
-                if (TemplateDeclaration *td = s->isTemplateDeclaration())
-                {
-                    if (!td->literal)
-                        continue;
-                    assert(td->members && td->members->length == 1);
-                    s = (*td->members)[0];
-                }
-                if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
-                {
-                    if (fld->tok == TOKreserved)
-                    {
-                        doSemantic3 = true;
-                        break;
-                    }
-                }
-            }
-            //printf("[%s] %s doSemantic3 = %d\n", loc.toChars(), toChars(), doSemantic3);
-        }
-        if (doSemantic3)
-            trySemantic3(sc2);
-
-        TemplateInstance *ti = tinst;
-        int nest = 0;
-        while (ti && !ti->deferred && ti->tinst)
-        {
-            ti = ti->tinst;
-            if (++nest > global.recursionLimit)
-            {
-                global.gag = 0;            // ensure error message gets printed
-                error("recursive expansion");
-                fatal();
-            }
-        }
-        if (ti && ti->deferred)
-        {
-            //printf("deferred semantic3 of %p %s, ti = %s, ti->deferred = %p\n", this, toChars(), ti->toChars());
-            for (size_t i = 0; ; i++)
-            {
-                if (i == ti->deferred->length)
-                {
-                    ti->deferred->push(this);
-                    break;
-                }
-                if ((*ti->deferred)[i] == this)
-                    break;
-            }
-        }
-    }
-
-    if (aliasdecl)
-    {
-        /* Bugzilla 13816: AliasDeclaration tries to resolve forward reference
-         * twice (See inuse check in AliasDeclaration::toAlias()). It's
-         * necessary to resolve mutual references of instantiated symbols, but
-         * it will left a true recursive alias in tuple declaration - an
-         * AliasDeclaration A refers TupleDeclaration B, and B contains A
-         * in its elements.  To correctly make it an error, we strictly need to
-         * resolve the alias of eponymous member.
-         */
-        aliasdecl = aliasdecl->toAlias2();
-    }
-
-  Laftersemantic:
-    sc2->pop();
-
-    scope->pop();
-
-    // Give additional context info if error occurred during instantiation
-    if (global.errors != errorsave)
-    {
-        if (!errors)
-        {
-            if (!tempdecl->literal)
-                error(loc, "error instantiating");
-            if (tinst)
-                tinst->printInstantiationTrace();
-        }
-        errors = true;
-        if (gagged)
-        {
-            // Errors are gagged, so remove the template instance from the
-            // instance/symbol lists we added it to and reset our state to
-            // finish clean and so we can try to instantiate it again later
-            // (see bugzilla 4302 and 6602).
-            tempdecl->removeInstance(tempdecl_instance_idx);
-            if (target_symbol_list)
-            {
-                // Because we added 'this' in the last position above, we
-                // should be able to remove it without messing other indices up.
-                assert((*target_symbol_list)[target_symbol_list_idx] == this);
-                target_symbol_list->remove(target_symbol_list_idx);
-                memberOf = NULL;                    // no longer a member
-            }
-            semanticRun = PASSinit;
-            inst = NULL;
-            symtab = NULL;
-        }
-    }
-    else if (errinst)
-    {
-        /* Bugzilla 14541: If the previous gagged instance had failed by
-         * circular references, currrent "error reproduction instantiation"
-         * might succeed, because of the difference of instantiated context.
-         * On such case, the cached error instance needs to be overridden by the
-         * succeeded instance.
-         */
-        //printf("replaceInstance()\n");
-        TemplateInstances *tinstances = (TemplateInstances *)dmd_aaGetRvalue((AA *)tempdecl->instances, (void *)hash);
-        assert(tinstances);
-        for (size_t i = 0; i < tinstances->length; i++)
-        {
-            TemplateInstance *ti = (*tinstances)[i];
-            if (ti == errinst)
-            {
-                (*tinstances)[i] = this;     // override
-                break;
-            }
-        }
-    }
-}
-
-
 /**********************************************
  * Find template declaration corresponding to template instance.
  *
@@ -6549,9 +5816,9 @@ bool TemplateInstance::findTempDecl(Scope *sc, WithScopeSymbol **pwithsym)
         {
             s = sc->search_correct(id);
             if (s)
-                error("template '%s' is not defined, did you mean %s?", id->toChars(), s->toChars());
+                error("template `%s` is not defined, did you mean %s?", id->toChars(), s->toChars());
             else
-                error("template '%s' is not defined", id->toChars());
+                error("template `%s` is not defined", id->toChars());
             return false;
         }
 
@@ -6601,7 +5868,7 @@ bool TemplateInstance::findTempDecl(Scope *sc, WithScopeSymbol **pwithsym)
             {
                 // Try to fix forward reference. Ungag errors while doing so.
                 Ungag ungag = td->ungagSpeculative();
-                td->semantic(td->_scope);
+                dsymbolSemantic(td, td->_scope);
             }
             if (td->semanticRun == PASSinit)
             {
@@ -6667,7 +5934,7 @@ bool TemplateInstance::updateTempDecl(Scope *sc, Dsymbol *s)
             }
             if (!s)
             {
-                error("template '%s' is not defined", id->toChars());
+                error("template `%s` is not defined", id->toChars());
                 return false;
             }
         }
@@ -6827,7 +6094,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
             //printf("+[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
             if (flags & 1) // only used by __traits
             {
-                ea = ::semantic(ea, sc);
+                ea = expressionSemantic(ea, sc);
 
                 // must not interpret the args, excepting template parameters
                 if (ea->op != TOKvar ||
@@ -6839,7 +6106,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
             else
             {
                 sc = sc->startCTFE();
-                ea = ::semantic(ea, sc);
+                ea = expressionSemantic(ea, sc);
                 sc = sc->endCTFE();
 
                 if (ea->op == TOKvar)
@@ -6966,7 +6233,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
             TemplateDeclaration *td = sa->isTemplateDeclaration();
             if (td && td->semanticRun == PASSinit && td->literal)
             {
-                td->semantic(sc);
+                dsymbolSemantic(td, sc);
             }
             FuncDeclaration *fd = sa->isFuncDeclaration();
             if (fd)
@@ -7286,7 +6553,7 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag)
                 {
                     // Try to fix forward reference. Ungag errors while doing so.
                     Ungag ungag = td->ungagSpeculative();
-                    td->semantic(td->_scope);
+                    dsymbolSemantic(td, td->_scope);
                 }
                 if (td->semanticRun == PASSinit)
                 {
@@ -7449,7 +6716,7 @@ bool TemplateInstance::hasNestedArgs(Objects *args, bool isstatic)
                 }
                 else
                 {
-                    error("cannot use local '%s' as parameter to non-global template %s", sa->toChars(), tempdecl->toChars());
+                    error("cannot use local `%s` as parameter to non-global template %s", sa->toChars(), tempdecl->toChars());
                     errors = true;
                 }
             }
@@ -7588,111 +6855,6 @@ void TemplateInstance::declareParameters(Scope *sc)
     }
 }
 
-void TemplateInstance::semantic2(Scope *sc)
-{
-    if (semanticRun >= PASSsemantic2)
-        return;
-    semanticRun = PASSsemantic2;
-    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;
-        sc->minst = minst;
-
-        int needGagging = (gagged && !global.gag);
-        unsigned int olderrors = global.errors;
-        int oldGaggedErrors = -1;       // dead-store to prevent spurious warning
-        if (needGagging)
-            oldGaggedErrors = global.startGagging();
-
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->semantic2(sc);
-            if (gagged && 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();
-    }
-}
-
-void TemplateInstance::semantic3(Scope *sc)
-{
-//if (toChars()[0] == 'D') *(char*)0=0;
-    if (semanticRun >= PASSsemantic3)
-        return;
-    semanticRun = PASSsemantic3;
-    if (!errors && members)
-    {
-        TemplateDeclaration *tempdecl = this->tempdecl->isTemplateDeclaration();
-        assert(tempdecl);
-
-        sc = tempdecl->_scope;
-        sc = sc->push(argsym);
-        sc = sc->push(this);
-        sc->tinst = this;
-        sc->minst = minst;
-
-        int needGagging = (gagged && !global.gag);
-        unsigned int olderrors = global.errors;
-        int oldGaggedErrors = -1;       // dead-store to prevent spurious warning
-        /* If this is a gagged instantiation, gag errors.
-         * Future optimisation: If the results are actually needed, errors
-         * would already be gagged, so we don't really need to run semantic
-         * on the members.
-         */
-        if (needGagging)
-            oldGaggedErrors = global.startGagging();
-
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->semantic3(sc);
-            if (gagged && 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();
-    }
-}
-
 /**************************************
  * Given an error instantiating the TemplateInstance,
  * give the nested TemplateInstance instantiations that got
@@ -7781,7 +6943,7 @@ Dsymbol *TemplateInstance::toAlias()
         // Maybe we can resolve it
         if (_scope)
         {
-            semantic(_scope);
+            dsymbolSemantic(this, _scope);
         }
         if (!inst)
         {
@@ -8209,7 +7371,7 @@ bool TemplateMixin::findTempDecl(Scope *sc)
         if (td->semanticRun == PASSinit)
         {
             if (td->_scope)
-                td->semantic(td->_scope);
+                dsymbolSemantic(td, td->_scope);
             else
             {
                 tm->semanticRun = PASSinit;
@@ -8230,264 +7392,6 @@ bool TemplateMixin::findTempDecl(Scope *sc)
     return true;
 }
 
-void TemplateMixin::semantic(Scope *sc)
-{
-    if (semanticRun != PASSinit)
-    {
-        // When a class/struct contains mixin members, and is done over
-        // because of forward references, never reach here so semanticRun
-        // has been reset to PASSinit.
-        return;
-    }
-    semanticRun = PASSsemantic;
-
-    Scope *scx = NULL;
-    if (_scope)
-    {
-        sc = _scope;
-        scx = _scope;            // save so we don't make redundant copies
-        _scope = NULL;
-    }
-
-    /* Run semantic on each argument, place results in tiargs[],
-     * then find best match template with tiargs
-     */
-    if (!findTempDecl(sc) ||
-        !semanticTiargs(sc) ||
-        !findBestMatch(sc, NULL))
-    {
-        if (semanticRun == PASSinit)    // forward reference had occured
-        {
-            //printf("forward reference - deferring\n");
-            _scope = scx ? scx : sc->copy();
-            _scope->setNoFree();
-            _scope->_module->addDeferredSemantic(this);
-            return;
-        }
-
-        inst = this;
-        errors = true;
-        return;         // error recovery
-    }
-    TemplateDeclaration *tempdecl = this->tempdecl->isTemplateDeclaration();
-    assert(tempdecl);
-
-    if (!ident)
-    {
-        /* Assign scope local unique identifier, as same as lambdas.
-         */
-        const char *s = "__mixin";
-
-        DsymbolTable *symtab;
-        if (FuncDeclaration *func = sc->parent->isFuncDeclaration())
-        {
-            symtab = func->localsymtab;
-            if (symtab)
-            {
-                // Inside template constraint, symtab is not set yet.
-                goto L1;
-            }
-        }
-        else
-        {
-            symtab = sc->parent->isScopeDsymbol()->symtab;
-        L1:
-            assert(symtab);
-            int num = (int)dmd_aaLen(symtab->tab) + 1;
-            ident = Identifier::generateId(s, num);
-            symtab->insert(this);
-        }
-    }
-
-    inst = this;
-    parent = sc->parent;
-
-    /* Detect recursive mixin instantiations.
-     */
-    for (Dsymbol *s = parent; s; s = s->parent)
-    {
-        //printf("\ts = '%s'\n", s->toChars());
-        TemplateMixin *tm = s->isTemplateMixin();
-        if (!tm || tempdecl != tm->tempdecl)
-            continue;
-
-        /* Different argument list lengths happen with variadic args
-         */
-        if (tiargs->length != tm->tiargs->length)
-            continue;
-
-        for (size_t i = 0; i < tiargs->length; i++)
-        {
-            RootObject *o = (*tiargs)[i];
-            Type *ta = isType(o);
-            Expression *ea = isExpression(o);
-            Dsymbol *sa = isDsymbol(o);
-            RootObject *tmo = (*tm->tiargs)[i];
-            if (ta)
-            {
-                Type *tmta = isType(tmo);
-                if (!tmta)
-                    goto Lcontinue;
-                if (!ta->equals(tmta))
-                    goto Lcontinue;
-            }
-            else if (ea)
-            {
-                Expression *tme = isExpression(tmo);
-                if (!tme || !ea->equals(tme))
-                    goto Lcontinue;
-            }
-            else if (sa)
-            {
-                Dsymbol *tmsa = isDsymbol(tmo);
-                if (sa != tmsa)
-                    goto Lcontinue;
-            }
-            else
-                assert(0);
-        }
-        error("recursive mixin instantiation");
-        return;
-
-    Lcontinue:
-        continue;
-    }
-
-    // Copy the syntax trees from the TemplateDeclaration
-    members = Dsymbol::arraySyntaxCopy(tempdecl->members);
-    if (!members)
-        return;
-
-    symtab = new DsymbolTable();
-
-    for (Scope *sce = sc; 1; sce = sce->enclosing)
-    {
-        ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym;
-        if (sds)
-        {
-            sds->importScope(this, Prot(Prot::public_));
-            break;
-        }
-    }
-
-    Scope *scy = sc->push(this);
-    scy->parent = this;
-
-    argsym = new ScopeDsymbol();
-    argsym->parent = scy->parent;
-    Scope *argscope = scy->push(argsym);
-
-    unsigned errorsave = global.errors;
-
-    // Declare each template parameter as an alias for the argument type
-    declareParameters(argscope);
-
-    // Add members to enclosing scope, as well as this scope
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->addMember(argscope, this);
-        //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
-        //printf("s->parent = %s\n", s->parent->toChars());
-    }
-
-    // Do semantic() analysis on template instance members
-    Scope *sc2 = argscope->push(this);
-    //size_t deferred_dim = Module::deferred.length;
-
-    static int nest;
-    //printf("%d\n", nest);
-    if (++nest > global.recursionLimit)
-    {
-        global.gag = 0;                 // ensure error message gets printed
-        error("recursive expansion");
-        fatal();
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->setScope(sc2);
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->importAll(sc2);
-    }
-
-    for (size_t i = 0; i < members->length; i++)
-    {
-        Dsymbol *s = (*members)[i];
-        s->semantic(sc2);
-    }
-
-    nest--;
-
-    /* In DeclDefs scope, TemplateMixin does not have to handle deferred symbols.
-     * Because the members would already call Module::addDeferredSemantic() for themselves.
-     * See Struct, Class, Interface, and EnumDeclaration::semantic().
-     */
-    //if (!sc->func && Module::deferred.length > deferred_dim) {}
-
-    AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
-    if (sc->func && !ad)
-    {
-        semantic2(sc2);
-        semantic3(sc2);
-    }
-
-    // Give additional context info if error occurred during instantiation
-    if (global.errors != errorsave)
-    {
-        error("error instantiating");
-        errors = true;
-    }
-
-    sc2->pop();
-    argscope->pop();
-    scy->pop();
-}
-
-void TemplateMixin::semantic2(Scope *sc)
-{
-    if (semanticRun >= PASSsemantic2)
-        return;
-    semanticRun = PASSsemantic2;
-    if (members)
-    {
-        assert(sc);
-        sc = sc->push(argsym);
-        sc = sc->push(this);
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->semantic2(sc);
-        }
-        sc = sc->pop();
-        sc->pop();
-    }
-}
-
-void TemplateMixin::semantic3(Scope *sc)
-{
-    if (semanticRun >= PASSsemantic3)
-        return;
-    semanticRun = PASSsemantic3;
-    if (members)
-    {
-        sc = sc->push(argsym);
-        sc = sc->push(this);
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->semantic3(sc);
-        }
-        sc = sc->pop();
-        sc->pop();
-    }
-}
-
 const char *TemplateMixin::kind() const
 {
     return "mixin";
@@ -8501,7 +7405,7 @@ bool TemplateMixin::oneMember(Dsymbol **ps, Identifier *ident)
 int TemplateMixin::apply(Dsymbol_apply_ft_t fp, void *param)
 {
     if (_scope) // if fwd reference
-        semantic(NULL); // try to resolve it
+        dsymbolSemantic(this, NULL); // try to resolve it
     if (members)
     {
         for (size_t i = 0; i < members->length; i++)
@@ -8540,7 +7444,7 @@ void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
 {
     //printf("TemplateMixin::setFieldOffset() %s\n", toChars());
     if (_scope)                  // if fwd reference
-        semantic(NULL);         // try to resolve it
+        dsymbolSemantic(this, NULL);         // try to resolve it
     if (members)
     {
         for (size_t i = 0; i < members->length; i++)
index f88fca561c5448e5be3a2c338f3c90e525e7c84c..269d92466cdf3784177e959283176242919dd29d 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -97,13 +97,6 @@ void DebugSymbol::addMember(Scope *, ScopeDsymbol *sds)
     }
 }
 
-void DebugSymbol::semantic(Scope *)
-{
-    //printf("DebugSymbol::semantic() %s\n", toChars());
-    if (semanticRun < PASSsemanticdone)
-        semanticRun = PASSsemanticdone;
-}
-
 const char *DebugSymbol::kind() const
 {
     return "debug";
@@ -188,12 +181,6 @@ void VersionSymbol::addMember(Scope *, ScopeDsymbol *sds)
     }
 }
 
-void VersionSymbol::semantic(Scope *)
-{
-    if (semanticRun < PASSsemanticdone)
-        semanticRun = PASSsemanticdone;
-}
-
 const char *VersionSymbol::kind() const
 {
     return "version";
index 50067637b13a78bd15b28f1206098618f884a600..cac901d1a6e9ea9c3a86ec0ebcb754e9bf01c9b7 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 6d389ed76e01249cf7415744d4f55a4c71b29f49..ae5ea214a735e04497fa2f9573b99b29aa59ff6e 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -47,7 +47,6 @@ public:
     Dsymbol *syntaxCopy(Dsymbol *s);
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope *sc);
-    void semantic(Scope *sc);
     bool oneMember(Dsymbol **ps, Identifier *ident);
     Type *getType();
     const char *kind() const;
@@ -89,7 +88,6 @@ public:
         StorageClass stc, UserAttributeDeclaration *uad, DeprecatedDeclaration *dd);
     Dsymbol *syntaxCopy(Dsymbol *s);
     const char *kind() const;
-    void semantic(Scope *sc);
     Expression *getVarExp(Loc loc, Scope *sc);
 
     EnumMember *isEnumMember() { return this; }
index 165da693ca0ce906219b208ce0e283ff6a1efafa..a92ae2abbc4c2d78c9dfc17c694949e00adf9cb4 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index b3fccd9ef467f75e1c04c19ee123cf833d41ca90..cd0382b0a22cdf27266160285ce77a114053fd0e 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 3314d0c096c3222022b5533ec18c2bf02056eb98..c90392d16a283c313d3b7f4fb39c7a66e1307422 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -45,11 +45,6 @@ char *MODtoChars(MOD mod);
 bool MODimplicitConv(MOD modfrom, MOD modto);
 MOD MODmerge(MOD mod1, MOD mod2);
 void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod);
-Expression *trySemantic(Expression *e, Scope *sc);
-Expression *semantic(Expression *e, Scope *sc);
-Expression *semanticX(DotIdExp *exp, Scope *sc);
-Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
-Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag);
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
 bool checkUnsafeAccess(Scope *sc, Expression *e, bool readonly, bool printmsg);
 
@@ -103,7 +98,7 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
                 e1->type = tcd->vthis->type;
                 e1->type = e1->type->addMod(t->mod);
                 // Do not call checkNestedRef()
-                //e1 = semantic(e1, sc);
+                //e1 = expressionSemantic(e1, sc);
 
                 // Skip up over nested functions, and get the enclosing
                 // class type.
@@ -122,7 +117,7 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
                     }
                     else
                     {
-                        e1->error("need 'this' of type %s to access member %s"
+                        e1->error("need `this` of type %s to access member %s"
                                   " from static function %s",
                             ad->toChars(), var->toChars(), f->toChars());
                         e1 = new ErrorExp();
@@ -134,10 +129,10 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
                     e1->type = s->isClassDeclaration()->type;
                     e1->type = e1->type->addMod(t->mod);
                     if (n > 1)
-                        e1 = semantic(e1, sc);
+                        e1 = expressionSemantic(e1, sc);
                 }
                 else
-                    e1 = semantic(e1, sc);
+                    e1 = expressionSemantic(e1, sc);
                 goto L1;
             }
 
@@ -269,7 +264,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
         FuncDeclaration *fd = NULL;
         if (e2)
         {
-            e2 = semantic(e2, sc);
+            e2 = expressionSemantic(e2, sc);
             if (e2->op == TOKerror)
                 return new ErrorExp();
             e2 = resolveProperties(sc, e2);
@@ -291,7 +286,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
             if (fd)
             {
                 Expression *e = new CallExp(loc, e1, e2);
-                return semantic(e, sc);
+                return expressionSemantic(e, sc);
             }
         }
         {
@@ -314,7 +309,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
                 Expression *e = new CallExp(loc, e1);
                 if (e2)
                     e = new AssignExp(loc, e, e2);
-                return semantic(e, sc);
+                return expressionSemantic(e, sc);
             }
         }
         if (e2)
@@ -383,7 +378,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
         assert(s);
         if (e2)
         {
-            e2 = semantic(e2, sc);
+            e2 = expressionSemantic(e2, sc);
             if (e2->op == TOKerror)
                 return new ErrorExp();
             e2 = resolveProperties(sc, e2);
@@ -398,7 +393,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
                     return new ErrorExp();
                 assert(fd->type->ty == Tfunction);
                 Expression *e = new CallExp(loc, e1, e2);
-                return semantic(e, sc);
+                return expressionSemantic(e, sc);
             }
         }
         {
@@ -414,7 +409,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
                     Expression *e = new CallExp(loc, e1);
                     if (e2)
                         e = new AssignExp(loc, e, e2);
-                    return semantic(e, sc);
+                    return expressionSemantic(e, sc);
                 }
             }
         }
@@ -423,7 +418,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
             // Keep better diagnostic message for invalid property usage of functions
             assert(fd->type->ty == Tfunction);
             Expression *e = new CallExp(loc, e1, e2);
-            return semantic(e, sc);
+            return expressionSemantic(e, sc);
         }
         if (e2)
             goto Leprop;
@@ -450,7 +445,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
             if (ve->var->storage_class & STClazy)
             {
                 Expression *e = new CallExp(loc, e1);
-                return semantic(e, sc);
+                return expressionSemantic(e, sc);
             }
         }
         else if (e1->op == TOKdotvar)
@@ -518,7 +513,7 @@ static bool checkPropertyCall(Expression *e)
              */
             if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
             {
-                ce->f->semantic(NULL);
+                dsymbolSemantic(ce->f, NULL);
                 tf = (TypeFunction *)ce->f->type;
             }
         }
@@ -787,7 +782,7 @@ Expression *resolveUFCS(Scope *sc, CallExp *ce)
                     return new ErrorExp();
                 }
                 Expression *key = (*ce->arguments)[0];
-                key = semantic(key, sc);
+                key = expressionSemantic(key, sc);
                 key = resolveProperties(sc, key);
 
                 TypeAArray *taa = (TypeAArray *)t;
@@ -811,7 +806,7 @@ Expression *resolveUFCS(Scope *sc, CallExp *ce)
                 if (isDotOpDispatch(ey))
                 {
                     unsigned errors = global.startGagging();
-                    e = semantic(ce->syntaxCopy(), sc);
+                    e = expressionSemantic(ce->syntaxCopy(), sc);
                     if (!global.endGagging(errors))
                         return e;
                     /* fall down to UFCS */
@@ -878,7 +873,7 @@ Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NU
     if (e2)
     {
         // run semantic without gagging
-        e2 = semantic(e2, sc);
+        e2 = expressionSemantic(e2, sc);
 
         /* f(e1) = e2
          */
@@ -902,12 +897,12 @@ Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NU
             if (!e)
             {   checkPropertyCall(ex);
                 ex = new AssignExp(loc, ex, e2);
-                return semantic(ex, sc);
+                return expressionSemantic(ex, sc);
             }
         }
         else
         {   // strict setter prints errors if fails
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
         }
         checkPropertyCall(e);
         return e;
@@ -920,9 +915,9 @@ Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NU
         arguments->setDim(1);
         (*arguments)[0] = eleft;
         e = new CallExp(loc, e, arguments);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         checkPropertyCall(e);
-        return semantic(e, sc);
+        return expressionSemantic(e, sc);
     }
 }
 
@@ -940,7 +935,7 @@ bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors)
             Expression *e = (*exps)[i];
             if (e)
             {
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 if (e->op == TOKerror)
                     err = true;
                 if (preserveErrors || e->op != TOKerror)
@@ -1137,7 +1132,7 @@ bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
             condexp.e1 = e0;
             condexp.e2 = e;
             condexp.loc = e->loc;
-            Expression *ex = semantic(&condexp, sc);
+            Expression *ex = expressionSemantic(&condexp, sc);
             if (ex->op == TOKerror)
                 e = ex;
             else
@@ -1298,7 +1293,7 @@ Expression *callCpCtor(Scope *sc, Expression *e)
              */
             VarDeclaration *tmp = copyToTemp(STCrvalue, "__copytmp", e);
             tmp->storage_class |= STCnodtor;
-            tmp->semantic(sc);
+            dsymbolSemantic(tmp, sc);
             Expression *de = new DeclarationExp(e->loc, tmp);
             Expression *ve = new VarExp(e->loc, tmp);
             de->type = Type::tvoid;
@@ -1508,7 +1503,7 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
                         }
                         break;
                 }
-                arg = semantic(arg, sc);
+                arg = expressionSemantic(arg, sc);
                 //printf("\targ = '%s'\n", arg->toChars());
                 arguments->setDim(i + 1);
                 (*arguments)[i] =  arg;
@@ -1810,10 +1805,10 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
             Identifier *idtmp = Identifier::generateId("__gate");
             gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL);
             gate->storage_class |= STCtemp | STCctfe | STCvolatile;
-            gate->semantic(sc);
+            dsymbolSemantic(gate, sc);
 
             Expression *ae = new DeclarationExp(loc, gate);
-            eprefix = semantic(ae, sc);
+            eprefix = expressionSemantic(ae, sc);
         }
 
         for (ptrdiff_t i = start; i != end; i += step)
@@ -1844,7 +1839,7 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
                 VarDeclaration *tmp = copyToTemp(0,
                     needsDtor ? "__pfx" : "__pfy",
                     !isRef ? arg : arg->addressOf());
-                tmp->semantic(sc);
+                dsymbolSemantic(tmp, sc);
 
                 /* Modify the destructor so it only runs if gate==false, i.e.,
                  * only if there was a throw while constructing the args
@@ -1863,21 +1858,21 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
                     assert(tmp->edtor);
                     Expression *e = tmp->edtor;
                     e = new LogicalExp(e->loc, TOKoror, new VarExp(e->loc, gate), e);
-                    tmp->edtor = semantic(e, sc);
+                    tmp->edtor = expressionSemantic(e, sc);
                     //printf("edtor: %s\n", tmp->edtor->toChars());
                 }
 
                 // eprefix => (eprefix, auto __pfx/y = arg)
                 DeclarationExp *ae = new DeclarationExp(loc, tmp);
-                eprefix = Expression::combine(eprefix, semantic(ae, sc));
+                eprefix = Expression::combine(eprefix, expressionSemantic(ae, sc));
 
                 // arg => __pfx/y
                 arg = new VarExp(loc, tmp);
-                arg = semantic(arg, sc);
+                arg = expressionSemantic(arg, sc);
                 if (isRef)
                 {
                     arg = new PtrExp(loc, arg);
-                    arg = semantic(arg, sc);
+                    arg = expressionSemantic(arg, sc);
                 }
 
                 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
@@ -1891,7 +1886,7 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
                 if (i == lastthrow)
                 {
                     Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool));
-                    eprefix = Expression::combine(eprefix, semantic(e, sc));
+                    eprefix = Expression::combine(eprefix, expressionSemantic(e, sc));
                     gate = NULL;
                 }
             }
@@ -1926,7 +1921,7 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
 
         TypeTuple *tup = new TypeTuple(args);
         Expression *e = new TypeidExp(loc, tup);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         arguments->insert(0, e);
     }
 
@@ -2179,7 +2174,7 @@ Expression *Expression::toLvalue(Scope *, Expression *e)
         loc = e->loc;
 
     if (e->op == TOKtype)
-        error("%s '%s' is a type, not an lvalue", e->type->kind(), e->type->toChars());
+        error("%s `%s` is a type, not an lvalue", e->type->kind(), e->type->toChars());
     else
         error("%s is not an lvalue", e->toChars());
 
@@ -2263,7 +2258,7 @@ bool Expression::checkScalar()
         return true;
     if (!type->isscalar())
     {
-        error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
+        error("`%s` is not a scalar, it is a %s", toChars(), type->toChars());
         return true;
     }
     return checkValue();
@@ -2277,7 +2272,7 @@ bool Expression::checkNoBool()
         return true;
     if (type->toBasetype()->ty == Tbool)
     {
-        error("operation not allowed on bool '%s'", toChars());
+        error("operation not allowed on bool `%s`", toChars());
         return true;
     }
     return false;
@@ -2291,7 +2286,7 @@ bool Expression::checkIntegral()
         return true;
     if (!type->isintegral())
     {
-        error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
+        error("`%s` is not of integral type, it is a %s", toChars(), type->toChars());
         return true;
     }
     return checkValue();
@@ -2305,7 +2300,7 @@ bool Expression::checkArithmetic()
         return true;
     if (!type->isintegral() && !type->isfloating())
     {
-        error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
+        error("`%s` is not of arithmetic type, it is a %s", toChars(), type->toChars());
         return true;
     }
     return checkValue();
@@ -2413,7 +2408,7 @@ bool Expression::checkPurity(Scope *sc, FuncDeclaration *f)
         FuncDeclaration *ff = outerfunc;
         if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure())
         {
-            error("pure %s '%s' cannot call impure %s '%s'",
+            error("pure %s `%s` cannot call impure %s `%s`",
                 ff->kind(), ff->toPrettyChars(), f->kind(), f->toPrettyChars());
             return true;
         }
@@ -2478,7 +2473,7 @@ bool Expression::checkPurity(Scope *sc, VarDeclaration *v)
                 break;
             if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure())
             {
-                error("pure %s '%s' cannot access mutable static data '%s'",
+                error("pure %s `%s` cannot access mutable static data `%s`",
                     ff->kind(), ff->toPrettyChars(), v->toChars());
                 err = true;
                 break;
@@ -2532,7 +2527,7 @@ bool Expression::checkPurity(Scope *sc, VarDeclaration *v)
                     OutBuffer vbuf;
                     MODMatchToBuffer(&ffbuf, ff->type->mod, v->type->mod);
                     MODMatchToBuffer(&vbuf, v->type->mod, ff->type->mod);
-                    error("%s%s '%s' cannot access %sdata '%s'",
+                    error("%s%s `%s` cannot access %sdata `%s`",
                         ffbuf.peekChars(), ff->kind(), ff->toPrettyChars(), vbuf.peekChars(), v->toChars());
                     err = true;
                     break;
@@ -2549,7 +2544,7 @@ bool Expression::checkPurity(Scope *sc, VarDeclaration *v)
     {
         if (sc->func->setUnsafe())
         {
-            error("safe %s '%s' cannot access __gshared data '%s'",
+            error("safe %s `%s` cannot access __gshared data `%s`",
                 sc->func->kind(), sc->func->toChars(), v->toChars());
             err = true;
         }
@@ -2582,7 +2577,7 @@ bool Expression::checkSafety(Scope *sc, FuncDeclaration *f)
             if (loc.linnum == 0)  // e.g. implicitly generated dtor
                 loc = sc->func->loc;
 
-            error("@safe %s '%s' cannot call @system %s '%s'",
+            error("@safe %s `%s` cannot call @system %s `%s`",
                 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars());
             return true;
         }
@@ -2614,7 +2609,7 @@ bool Expression::checkNogc(Scope *sc, FuncDeclaration *f)
             if (loc.linnum == 0)  // e.g. implicitly generated dtor
                 loc = sc->func->loc;
 
-            error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
+            error("@nogc %s `%s` cannot call non-@nogc %s `%s`",
                 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars());
             return true;
         }
@@ -2661,7 +2656,7 @@ bool Expression::checkRightThis(Scope *sc)
         {
             //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
             //        sc->intypeof, sc->getStructClassScope(), func, fdthis);
-            error("need 'this' for '%s' of type '%s'", ve->var->toChars(), ve->var->type->toChars());
+            error("need `this` for `%s` of type `%s`", ve->var->toChars(), ve->var->type->toChars());
             return true;
         }
     }
@@ -2729,7 +2724,7 @@ Lagain:
         if (fd)
         {
             e = new CastExp(loc, e, Type::tbool);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
 
@@ -3717,9 +3712,9 @@ Lagain:
             (!v->type->deco && v->inuse))  // during variable type semantic
         {
             if (v->inuse)    // variable type depends on the variable itself
-                ::error(loc, "circular reference to %s '%s'", v->kind(), v->toPrettyChars());
+                ::error(loc, "circular reference to %s `%s`", v->kind(), v->toPrettyChars());
             else             // variable type cannot be determined
-                ::error(loc, "forward reference to %s '%s'", v->kind(), v->toPrettyChars());
+                ::error(loc, "forward reference to %s `%s`", v->kind(), v->toPrettyChars());
             return new ErrorExp();
         }
         if (v->type->ty == Terror)
@@ -3729,13 +3724,13 @@ Lagain:
         {
             if (v->inuse)
             {
-                ::error(loc, "circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
+                ::error(loc, "circular initialization of %s `%s`", v->kind(), v->toPrettyChars());
                 return new ErrorExp();
             }
 
             e = v->expandInitializer(loc);
             v->inuse++;
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             v->inuse--;
             return e;
         }
@@ -3748,14 +3743,14 @@ Lagain:
             e = new DotVarExp(loc, new ThisExp(loc), v);
         else
             e = new VarExp(loc, v);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
     if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
     {
         //printf("'%s' is a function literal\n", fld->toChars());
         e = new FuncExp(loc, fld);
-        return semantic(e, sc);
+        return expressionSemantic(e, sc);
     }
     if (FuncDeclaration *f = s->isFuncDeclaration())
     {
@@ -3790,28 +3785,28 @@ Lagain:
             return new ErrorExp();
         }
         ScopeExp *ie = new ScopeExp(loc, imp->pkg);
-        return semantic(ie, sc);
+        return expressionSemantic(ie, sc);
     }
     if (Package *pkg = s->isPackage())
     {
         ScopeExp *ie = new ScopeExp(loc, pkg);
-        return semantic(ie, sc);
+        return expressionSemantic(ie, sc);
     }
     if (Module *mod = s->isModule())
     {
         ScopeExp *ie = new ScopeExp(loc, mod);
-        return semantic(ie, sc);
+        return expressionSemantic(ie, sc);
     }
 
     if (Nspace *ns = s->isNspace())
     {
         ScopeExp *ie = new ScopeExp(loc, ns);
-        return semantic(ie, sc);
+        return expressionSemantic(ie, sc);
     }
 
     if (Type *t = s->getType())
     {
-        return semantic(new TypeExp(loc, t), sc);
+        return expressionSemantic(new TypeExp(loc, t), sc);
     }
 
     if (TupleDeclaration *tup = s->isTupleDeclaration())
@@ -3820,20 +3815,20 @@ Lagain:
             e = new DotVarExp(loc, new ThisExp(loc), tup);
         else
             e = new TupleExp(loc, tup);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
 
     if (TemplateInstance *ti = s->isTemplateInstance())
     {
-        ti->semantic(sc);
+        dsymbolSemantic(ti, sc);
         if (!ti->inst || ti->errors)
             return new ErrorExp();
         s = ti->toAlias();
         if (!s->isTemplateInstance())
             goto Lagain;
         e = new ScopeExp(loc, ti);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
     if (TemplateDeclaration *td = s->isTemplateDeclaration())
@@ -3848,11 +3843,11 @@ Lagain:
         }
         else
             e = new TemplateExp(loc, td);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
 
-    ::error(loc, "%s '%s' is not a variable", s->kind(), s->toChars());
+    ::error(loc, "%s `%s` is not a variable", s->kind(), s->toChars());
     return new ErrorExp();
 }
 
@@ -4553,7 +4548,7 @@ Expression *StructLiteralExp::addDtorHook(Scope *sc)
         VarDeclaration *tmp = copyToTemp(0, buf, this);
         Expression *ae = new DeclarationExp(loc, tmp);
         Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
     return this;
@@ -4850,7 +4845,7 @@ SymOffExp::SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverl
         // FIXME: This error report will never be handled anyone.
         // It should be done before the SymOffExp construction.
         if (v->needThis())
-            ::error(loc, "need 'this' for address of %s", v->toChars());
+            ::error(loc, "need `this` for address of %s", v->toChars());
     }
     this->offset = offset;
 }
@@ -4903,7 +4898,7 @@ Expression *VarExp::toLvalue(Scope *, Expression *)
 {
     if (var->storage_class & STCmanifest)
     {
-        error("manifest constant '%s' is not lvalue", var->toChars());
+        error("manifest constant `%s` is not lvalue", var->toChars());
         return new ErrorExp();
     }
     if (var->storage_class & STClazy)
@@ -4918,7 +4913,7 @@ Expression *VarExp::toLvalue(Scope *, Expression *)
     }
     if (var->ident == Id::dollar)   // Bugzilla 13574
     {
-        error("'$' is not an lvalue");
+        error("`$` is not an lvalue");
         return new ErrorExp();
     }
     return this;
@@ -4936,7 +4931,7 @@ Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
     //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
     if (var->storage_class & STCmanifest)
     {
-        error("cannot modify manifest constant '%s'", toChars());
+        error("cannot modify manifest constant `%s`", toChars());
         return new ErrorExp();
     }
     // See if this expression is a modifiable lvalue (i.e. not const)
@@ -5146,7 +5141,7 @@ MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag)
         if (tok == TOKfunction)
         {
             if (!flag)
-                error("cannot match function literal to delegate type '%s'", to->toChars());
+                error("cannot match function literal to delegate type `%s`", to->toChars());
             return MATCHnomatch;
         }
         tof = (TypeFunction *)to->nextOf();
@@ -5156,7 +5151,7 @@ MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag)
         if (tok == TOKdelegate)
         {
             if (!flag)
-                error("cannot match delegate literal to function pointer type '%s'", to->toChars());
+                error("cannot match delegate literal to function pointer type `%s`", to->toChars());
             return MATCHnomatch;
         }
         tof = (TypeFunction *)to->nextOf();
@@ -5213,7 +5208,7 @@ MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag)
 
         TemplateInstance *ti = new TemplateInstance(loc, td, tiargs);
         Expression *ex = new ScopeExp(loc, ti);
-        ex = ::semantic(ex, td->_scope);
+        ex = expressionSemantic(ex, td->_scope);
 
         // Reset inference target for the later re-semantic
         fd->treq = NULL;
@@ -5453,12 +5448,12 @@ Expression *UnaExp::incompatibleTypes()
 
     if (e1->op == TOKtype)
     {
-        error("incompatible type for (%s(%s)): cannot use '%s' with types",
+        error("incompatible type for (%s(%s)): cannot use `%s` with types",
               Token::toChars(op), e1->toChars(), Token::toChars(op));
     }
     else
     {
-        error("incompatible type for (%s(%s)): '%s'",
+        error("incompatible type for (%s(%s)): `%s`",
               Token::toChars(op), e1->toChars(), e1->type->toChars());
     }
     return new ErrorExp();
@@ -5646,12 +5641,12 @@ Expression *BinExp::incompatibleTypes()
     TOK thisOp = (op == TOKquestion) ? TOKcolon : op;
     if (e1->op == TOKtype || e2->op == TOKtype)
     {
-        error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types",
+        error("incompatible types for ((%s) %s (%s)): cannot use `%s` with types",
             e1->toChars(), Token::toChars(thisOp), e2->toChars(), Token::toChars(op));
     }
     else
     {
-        error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
+        error("incompatible types for ((%s) %s (%s)): `%s` and `%s`",
             e1->toChars(), Token::toChars(thisOp), e2->toChars(),
             e1->type->toChars(), e2->type->toChars());
     }
@@ -5820,7 +5815,7 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1)
                     else
                     {
                         const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod);
-                        ::error(loc, "%s field '%s' initialized multiple times", modStr, var->toChars());
+                        ::error(loc, "%s field `%s` initialized multiple times", modStr, var->toChars());
                     }
                 }
                 else if (sc->noctor || (fi & CSXlabel))
@@ -5830,7 +5825,7 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1)
                     else
                     {
                         const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod);
-                        ::error(loc, "%s field '%s' initialization is not allowed in loops or after labels", modStr, var->toChars());
+                        ::error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var->toChars());
                     }
                 }
                 sc->fieldinit[i] |= CSXthis_ctor;
@@ -5853,13 +5848,13 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1)
                 else if (sc->func->fes)
                 {
                     const char *p = var->isField() ? "field" : var->kind();
-                    ::error(loc, "%s %s '%s' initialization is not allowed in foreach loop",
+                    ::error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
                         MODtoChars(var->type->mod), p, var->toChars());
                 }
                 else
                 {
                     const char *p = var->isField() ? "field" : var->kind();
-                    ::error(loc, "%s %s '%s' initialization is not allowed in nested function '%s'",
+                    ::error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
                         MODtoChars(var->type->mod), p, var->toChars(), sc->func->toChars());
                 }
             }
@@ -5930,7 +5925,7 @@ bool DotTemplateInstanceExp::findTempDecl(Scope *sc)
         return true;
 
     Expression *e = new DotIdExp(loc, e1, ti->name);
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     if (e->op == TOKdot)
         e = ((DotExp *)e)->e2;
 
@@ -6079,7 +6074,7 @@ Expression *CallExp::addDtorHook(Scope *sc)
             DeclarationExp *de = new DeclarationExp(loc, tmp);
             VarExp *ve = new VarExp(loc, tmp);
             Expression *e = new CommaExp(loc, de, ve);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
     }
@@ -7062,10 +7057,10 @@ void CondExp::hookDtors(Scope *sc)
                     if (!vcond)
                     {
                         vcond = copyToTemp(STCvolatile, "__cond", ce->econd);
-                        vcond->semantic(sc);
+                        dsymbolSemantic(vcond, sc);
 
                         Expression *de = new DeclarationExp(ce->econd->loc, vcond);
-                        de = semantic(de, sc);
+                        de = expressionSemantic(de, sc);
 
                         Expression *ve = new VarExp(ce->econd->loc, vcond);
                         ce->econd = Expression::combine(de, ve);
@@ -7077,7 +7072,7 @@ void CondExp::hookDtors(Scope *sc)
                         v->edtor = new LogicalExp(v->edtor->loc, TOKandand, ve, v->edtor);
                     else
                         v->edtor = new LogicalExp(v->edtor->loc, TOKoror, ve, v->edtor);
-                    v->edtor = semantic(v->edtor, sc);
+                    v->edtor = expressionSemantic(v->edtor, sc);
                     //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
                 }
             }
@@ -7158,7 +7153,7 @@ Expression *FileInitExp::resolveLoc(Loc loc, Scope *sc)
         s = loc.filename != NULL ? loc.filename : sc->_module->ident->toChars();
 
     Expression *e = new StringExp(loc, const_cast<char *>(s));
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     e = e->castTo(sc, type);
     return e;
 }
@@ -7192,7 +7187,7 @@ Expression *ModuleInitExp::resolveLoc(Loc loc, Scope *sc)
     else
         s = sc->_module->toPrettyChars();
     Expression *e = new StringExp(loc, const_cast<char *>(s));
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     e = e->castTo(sc, type);
     return e;
 }
@@ -7214,7 +7209,7 @@ Expression *FuncInitExp::resolveLoc(Loc loc, Scope *sc)
     else
         s = "";
     Expression *e = new StringExp(loc, const_cast<char *>(s));
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     e = e->castTo(sc, type);
     return e;
 }
@@ -7248,7 +7243,7 @@ Expression *PrettyFuncInitExp::resolveLoc(Loc loc, Scope *sc)
     }
 
     Expression *e = new StringExp(loc, const_cast<char *>(s));
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     e = e->castTo(sc, type);
     return e;
 }
@@ -7318,14 +7313,14 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
         ae->lengthVar = NULL;       // Create it only if required
         ae->currentDimension = i;   // Dimension for $, if required
 
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         e = resolveProperties(sc, e);
 
         if (ae->lengthVar && sc->func)
         {
             // If $ was used, declare it now
             Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
-            de = semantic(de, sc);
+            de = expressionSemantic(de, sc);
             *pe0 = Expression::combine(*pe0, de);
         }
         sc = sc->pop();
@@ -7336,7 +7331,7 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
 
             Objects *tiargs = new Objects();
             Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t);
-            edim = semantic(edim, sc);
+            edim = expressionSemantic(edim, sc);
             tiargs->push(edim);
 
             Expressions *fargs = new Expressions();
@@ -7353,7 +7348,7 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
 
             e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs);
             e = new CallExp(ae->loc, e, fargs);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
         }
 
         if (!e->type)
@@ -7382,7 +7377,7 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
 StringExp *semanticString(Scope *sc, Expression *exp, const char *s)
 {
     sc = sc->startCTFE();
-    exp = semantic(exp, sc);
+    exp = expressionSemantic(exp, sc);
     exp = resolveProperties(sc, exp);
     sc = sc->endCTFE();
 
@@ -7428,7 +7423,7 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression
     for (size_t i = 0; i < 2; ++i)
     {
         Expression *e = i == 0 ? ie->lwr : ie->upr;
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         e = resolveProperties(sc, e);
         if (!e->type)
         {
@@ -7442,7 +7437,7 @@ Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression
     {
         // If $ was used, declare it now
         Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
-        de = semantic(de, sc);
+        de = expressionSemantic(de, sc);
         *pe0 = Expression::combine(*pe0, de);
     }
     sc = sc->pop();
index 15a4d8770c65e894047763ebf51c24f1ef15a522..f0ae2805df453f59fd586c838f866c65b87ed67f 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -43,6 +43,9 @@ class TemplateInstance;
 class TemplateDeclaration;
 class ClassDeclaration;
 class BinExp;
+class UnaExp;
+class DotIdExp;
+class DotTemplateInstanceExp;
 class OverloadSet;
 class Initializer;
 class StringExp;
@@ -55,6 +58,16 @@ typedef union tree_node Symbol;
 struct Symbol;          // back end symbol
 #endif
 
+Expression *expressionSemantic(Expression *e, Scope *sc);
+Expression *semanticX(DotIdExp *exp, Scope *sc);
+Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
+Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag);
+Expression *trySemantic(Expression *e, Scope *sc);
+Expression *unaSemantic(UnaExp *e, Scope *sc);
+Expression *binSemantic(BinExp *e, Scope *sc);
+Expression *binSemanticProp(BinExp *e, Scope *sc);
+StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
+
 Expression *resolveProperties(Scope *sc, Expression *e);
 Expression *resolvePropertiesOnly(Scope *sc, Expression *e1);
 bool checkAccess(Loc loc, Scope *sc, Expression *e, Declaration *d);
index 7cebd9a3023ad23e6f28a245a4e51d3c5524fd21..7cccd95696647559f0b350fa4b8411c04cbf0644 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -67,15 +67,6 @@ Expression *callCpCtor(Scope *sc, Expression *e);
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
 Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL);
 Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL);
-Expression *trySemantic(Expression *e, Scope *sc);
-Expression *unaSemantic(UnaExp *e, Scope *sc);
-Expression *binSemantic(BinExp *e, Scope *sc);
-Expression *binSemanticProp(BinExp *e, Scope *sc);
-Expression *semantic(Expression *e, Scope *sc);
-Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
-Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag);
-StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
-Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
 
 /****************************************
  * Preprocess arguments to function.
@@ -278,7 +269,7 @@ public:
     void visit(Expression *e)
     {
         if (e->type)
-            e->type = e->type->semantic(e->loc, sc);
+            e->type = typeSemantic(e->type, e->loc, sc);
         else
             e->type = Type::tvoid;
         result = e;
@@ -299,7 +290,7 @@ public:
         if (!e->type)
             e->type = Type::tfloat64;
         else
-            e->type = e->type->semantic(e->loc, sc);
+            e->type = typeSemantic(e->type, e->loc, sc);
         result = e;
     }
 
@@ -308,7 +299,7 @@ public:
         if (!e->type)
             e->type = Type::tcomplex80;
         else
-            e->type = e->type->semantic(e->loc, sc);
+            e->type = typeSemantic(e->type, e->loc, sc);
         result = e;
     }
 
@@ -363,7 +354,7 @@ public:
                 //  The redudancy should be removed.
                 e = new VarExp(exp->loc, withsym->withstate->wthis);
                 e = new DotIdExp(exp->loc, e, exp->ident);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
             }
             else
             {
@@ -381,7 +372,7 @@ public:
                         e = withsym->withstate->exp;
                     }
                     e = new DotIdExp(exp->loc, e, exp->ident);
-                    result = semantic(e, sc);
+                    result = expressionSemantic(e, sc);
                     return;
                 }
 
@@ -397,7 +388,7 @@ public:
                         if (td->overroot)       // if not start of overloaded list of TemplateDeclaration's
                             td = td->overroot;  // then get the start
                         e = new TemplateExp(exp->loc, td, f);
-                        e = semantic(e, sc);
+                        e = expressionSemantic(e, sc);
                         result = e;
                         return;
                     }
@@ -440,7 +431,7 @@ public:
             vd->storage_class |= STCtemp;
             vd->semanticRun = PASSsemanticdone;
             Expression *e = new VarExp(exp->loc, vd);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -544,7 +535,7 @@ public:
         return;
 
     Lerr:
-        e->error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
+        e->error("`this` is only defined in non-static member functions, not %s", sc->parent->toChars());
         return setError();
     }
 
@@ -579,7 +570,7 @@ public:
                     cd = cd->baseClass;
                     if (!cd)
                     {
-                        e->error("class %s has no 'super'", s->toChars());
+                        e->error("class %s has no `super`", s->toChars());
                         goto Lerr;
                     }
                     e->type = cd->type;
@@ -624,7 +615,7 @@ public:
         return;
 
     Lerr:
-        e->error("'super' is only allowed in non-static class member functions");
+        e->error("`super` is only allowed in non-static class member functions");
         return setError();
     }
 
@@ -712,7 +703,7 @@ public:
                 e->type = new TypeDArray(Type::tchar->immutableOf());
                 break;
         }
-        e->type = e->type->semantic(e->loc, sc);
+        e->type = typeSemantic(e->type, e->loc, sc);
         //e->type = e->type->immutableOf();
         //printf("type = %s\n", e->type->toChars());
 
@@ -731,7 +722,7 @@ public:
         */
 
         if (e->basis)
-            e->basis = semantic(e->basis, sc);
+            e->basis = expressionSemantic(e->basis, sc);
         if (arrayExpressionSemantic(e->elements, sc) || (e->basis && e->basis->op == TOKerror))
             return setError();
         expandTuples(e->elements);
@@ -746,7 +737,7 @@ public:
             return setError();
 
         e->type = t0->arrayOf();
-        e->type = e->type->semantic(e->loc, sc);
+        e->type = typeSemantic(e->type, e->loc, sc);
 
         /* Disallow array literals of type void being used.
         */
@@ -794,7 +785,7 @@ public:
             return setError();
 
         e->type = new TypeAArray(tvalue, tkey);
-        e->type = e->type->semantic(e->loc, sc);
+        e->type = typeSemantic(e->type, e->loc, sc);
 
         semanticTypeInfo(sc, e->type);
 
@@ -865,12 +856,12 @@ public:
                 e = new DotVarExp(exp->loc, new ThisExp(exp->loc), ve->var, false);
             }
             //printf("e = %s %s\n", Token::toChars(e->op), e->toChars());
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
         }
         else if (t)
         {
             //printf("t = %d %s\n", t->ty, t->toChars());
-            exp->type = t->semantic(exp->loc, sc);
+            exp->type = typeSemantic(t, exp->loc, sc);
             e = exp;
         }
         else if (s)
@@ -907,7 +898,7 @@ public:
             {
                 Expression *e = new VarExp(exp->loc, withsym->withstate->wthis);
                 e = new DotTemplateInstanceExp(exp->loc, e, ti);
-                result = semantic(e, sc);
+                result = expressionSemantic(e, sc);
                 return;
             }
             if (ti->needsTypeInference(sc))
@@ -921,7 +912,7 @@ public:
                         (td->_scope->stc & STCstatic) == 0)
                     {
                         Expression *e = new DotTemplateInstanceExp(exp->loc, new ThisExp(exp->loc), ti->name, ti->tiargs);
-                        result = semantic(e, sc);
+                        result = expressionSemantic(e, sc);
                         return;
                     }
                 }
@@ -932,7 +923,7 @@ public:
                     if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad)
                     {
                         Expression *e = new DotTemplateInstanceExp(exp->loc, new ThisExp(exp->loc), ti->name, ti->tiargs);
-                        result = semantic(e, sc);
+                        result = expressionSemantic(e, sc);
                         return;
                     }
                 }
@@ -942,7 +933,7 @@ public:
                 result = exp;
                 return;
             }
-            ti->semantic(sc);
+            dsymbolSemantic(ti, sc);
             if (!ti->inst || ti->errors)
                 return setError();
 
@@ -987,13 +978,13 @@ public:
                      */
                     if (ti->inuse)
                     {
-                        exp->error("recursive expansion of %s '%s'", ti->kind(), ti->toPrettyChars());
+                        exp->error("recursive expansion of %s `%s`", ti->kind(), ti->toPrettyChars());
                         return setError();
                     }
 
                     Expression *e = v->expandInitializer(exp->loc);
                     ti->inuse++;
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     ti->inuse--;
                     result = e;
                     return;
@@ -1009,18 +1000,18 @@ public:
 
         //printf("sds2 = %s, '%s'\n", sds2->kind(), sds2->toChars());
         //printf("\tparent = '%s'\n", sds2->parent->toChars());
-        sds2->semantic(sc);
+        dsymbolSemantic(sds2, sc);
 
         if (Type *t = sds2->getType())    // (Aggregate|Enum)Declaration
         {
             Expression *ex = new TypeExp(exp->loc, t);
-            result = semantic(ex, sc);
+            result = expressionSemantic(ex, sc);
             return;
         }
 
         if (TemplateDeclaration *td = sds2->isTemplateDeclaration())
         {
-            result = semantic(new TemplateExp(exp->loc, td), sc);
+            result = expressionSemantic(new TemplateExp(exp->loc, td), sc);
             return;
         }
 
@@ -1051,23 +1042,23 @@ public:
         ClassDeclaration *cdthis = NULL;
         if (exp->thisexp)
         {
-            exp->thisexp = semantic(exp->thisexp, sc);
+            exp->thisexp = expressionSemantic(exp->thisexp, sc);
             if (exp->thisexp->op == TOKerror)
                 return setError();
             cdthis = exp->thisexp->type->isClassHandle();
             if (!cdthis)
             {
-                exp->error("'this' for nested class must be a class type, not %s", exp->thisexp->type->toChars());
+                exp->error("`this` for nested class must be a class type, not %s", exp->thisexp->type->toChars());
                 return setError();
             }
 
             sc = sc->push(cdthis);
-            exp->type = exp->newtype->semantic(exp->loc, sc);
+            exp->type = typeSemantic(exp->newtype, exp->loc, sc);
             sc = sc->pop();
         }
         else
         {
-            exp->type = exp->newtype->semantic(exp->loc, sc);
+            exp->type = typeSemantic(exp->newtype, exp->loc, sc);
         }
         if (exp->type->ty == Terror)
             return setError();
@@ -1078,7 +1069,7 @@ public:
             {
                 // --> new T[edim]
                 exp->type = new TypeSArray(exp->type, edim);
-                exp->type = exp->type->semantic(exp->loc, sc);
+                exp->type = typeSemantic(exp->type, exp->loc, sc);
                 if (exp->type->ty == Terror)
                     return setError();
             }
@@ -1141,7 +1132,7 @@ public:
                 {
                     FuncDeclaration *fd = cd->vtbl[i]->isFuncDeclaration();
                     if (fd && fd->isAbstract())
-                        errorSupplemental(exp->loc, "function '%s' is not implemented", fd->toFullSignature());
+                        errorSupplemental(exp->loc, "function `%s` is not implemented", fd->toFullSignature());
                 }
                 return setError();
             }
@@ -1164,7 +1155,7 @@ public:
                         {
                             if (!sp)
                             {
-                                exp->error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
+                                exp->error("outer class %s `this` needed to `new` nested class %s", cdn->toChars(), cd->toChars());
                                 return setError();
                             }
                             ClassDeclaration *cdp = sp->isClassDeclaration();
@@ -1175,7 +1166,7 @@ public:
                             // Add a '.outer' and try again
                             exp->thisexp = new DotIdExp(exp->loc, exp->thisexp, Id::outer);
                         }
-                        exp->thisexp = semantic(exp->thisexp, sc);
+                        exp->thisexp = expressionSemantic(exp->thisexp, sc);
                         if (exp->thisexp->op == TOKerror)
                             return setError();
                         cdthis = exp->thisexp->type->isClassHandle();
@@ -1183,7 +1174,7 @@ public:
                     if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
                     {
                         //printf("cdthis = %s\n", cdthis->toChars());
-                        exp->error("'this' for nested class must be of type %s, not %s",
+                        exp->error("`this` for nested class must be of type %s, not %s",
                             cdn->toChars(), exp->thisexp->type->toChars());
                         return setError();
                     }
@@ -1204,7 +1195,7 @@ public:
                     // make sure the parent context fdn of cd is reachable from sc
                     if (checkNestedRef(sc->parent, fdn))
                     {
-                        exp->error("outer function context of %s is needed to 'new' nested class %s",
+                        exp->error("outer function context of %s is needed to `new` nested class %s",
                             fdn->toPrettyChars(), cd->toPrettyChars());
                         return setError();
                     }
@@ -1294,7 +1285,7 @@ public:
                             v->_init->isVoidInitializer())
                             continue;
                         v->inuse++;
-                        v->_init = semantic(v->_init, v->_scope, v->type, INITinterpret);
+                        v->_init = initializerSemantic(v->_init, v->_scope, v->type, INITinterpret);
                         v->inuse--;
                     }
                 }
@@ -1462,7 +1453,7 @@ public:
         Expression *d = new DeclarationExp(e->loc, e->cd);
         sc = sc->push();            // just create new scope
         sc->flags &= ~SCOPEctfe;    // temporary stop CTFE
-        d = semantic(d, sc);
+        d = expressionSemantic(d, sc);
         sc = sc->pop();
 
         if (!e->cd->errors && sc->intypeof && !sc->parent->inNonRoot())
@@ -1474,12 +1465,12 @@ public:
         Expression *n = new NewExp(e->loc, e->thisexp, e->newargs, e->cd->type, e->arguments);
 
         Expression *c = new CommaExp(e->loc, d, n);
-        result = semantic(c, sc);
+        result = expressionSemantic(c, sc);
     }
 
     void visit(SymOffExp *e)
     {
-        //var->semantic(sc);
+        //dsymbolSemantic(var, sc);
         if (!e->type)
             e->type = e->var->type->pointerTo();
         if (VarDeclaration *v = e->var->isVarDeclaration())
@@ -1515,7 +1506,7 @@ public:
             Declaration *decl = e->var->isDeclaration();
             if (decl)
                 decl->inuse++;
-            e->type = e->type->semantic(e->loc, sc);
+            e->type = typeSemantic(e->type, e->loc, sc);
             if (decl)
                 decl->inuse--;
         }
@@ -1559,14 +1550,14 @@ public:
         }
 
         if (exp->e0)
-            exp->e0 = semantic(exp->e0, sc);
+            exp->e0 = expressionSemantic(exp->e0, sc);
 
         // Run semantic() on each argument
         bool err = false;
         for (size_t i = 0; i < exp->exps->length; i++)
         {
             Expression *e = (*exp->exps)[i];
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             if (!e->type)
             {
                 exp->error("%s has no value", e->toChars());
@@ -1582,7 +1573,7 @@ public:
 
         expandTuples(exp->exps);
         exp->type = new TypeTuple(exp->exps);
-        exp->type = exp->type->semantic(exp->loc, sc);
+        exp->type = typeSemantic(exp->type, exp->loc, sc);
         //printf("-TupleExp::semantic(%s)\n", exp->toChars());
         result = exp;
     }
@@ -1603,7 +1594,7 @@ public:
              * foo(a=>a); // in IFTI, treq == T delegate(int)
              */
             //if (exp->fd->treq)
-            //    exp->fd->treq = exp->fd->treq->semantic(exp->loc, sc);
+            //    exp->fd->treq = typeSemantic(exp->fd->treq, exp->loc, sc);
 
             exp->genIdent(sc);
 
@@ -1625,7 +1616,7 @@ public:
             if (exp->td)
             {
                 assert(exp->td->parameters && exp->td->parameters->length);
-                exp->td->semantic(sc);
+                dsymbolSemantic(exp->td, sc);
                 exp->type = Type::tvoid; // temporary type
 
                 if (exp->fd->treq)       // defer type determination
@@ -1640,12 +1631,12 @@ public:
             }
 
             unsigned olderrors = global.errors;
-            exp->fd->semantic(sc);
+            dsymbolSemantic(exp->fd, sc);
             if (olderrors == global.errors)
             {
-                exp->fd->semantic2(sc);
+                semantic2(exp->fd, sc);
                 if (olderrors == global.errors)
-                    exp->fd->semantic3(sc);
+                    semantic3(exp->fd, sc);
             }
             if (olderrors != global.errors)
             {
@@ -1660,14 +1651,14 @@ public:
                 (exp->tok == TOKreserved && exp->fd->treq && exp->fd->treq->ty == Tdelegate))
             {
                 exp->type = new TypeDelegate(exp->fd->type);
-                exp->type = exp->type->semantic(exp->loc, sc);
+                exp->type = typeSemantic(exp->type, exp->loc, sc);
 
                 exp->fd->tok = TOKdelegate;
             }
             else
             {
                 exp->type = new TypePointer(exp->fd->type);
-                exp->type = exp->type->semantic(exp->loc, sc);
+                exp->type = typeSemantic(exp->type, exp->loc, sc);
                 //exp->type = exp->fd->type->pointerTo();
 
                 /* A lambda expression deduced to function pointer might become
@@ -1706,7 +1697,7 @@ public:
             exp->genIdent(sc);
 
             assert(exp->td->parameters && exp->td->parameters->length);
-            exp->td->semantic(sc);
+            dsymbolSemantic(exp->td, sc);
 
             TypeFunction *tfl = (TypeFunction *)exp->fd->type;
             size_t dim = tfl->parameterList.length();
@@ -1739,12 +1730,12 @@ public:
 
                 TemplateInstance *ti = new TemplateInstance(exp->loc, exp->td, tiargs);
                 Expression *se = new ScopeExp(exp->loc, ti);
-                return semantic(se, sc);
+                return expressionSemantic(se, sc);
             }
             exp->error("cannot infer function literal type");
             return new ErrorExp();
         }
-        return semantic(exp, sc);
+        return expressionSemantic(exp, sc);
     }
 
     void visit(DeclarationExp *e)
@@ -1783,7 +1774,7 @@ public:
             // Do semantic() on initializer first, so:
             //      int a = a;
             // will be illegal.
-            e->declaration->semantic(sc);
+            dsymbolSemantic(e->declaration, sc);
             s->parent = sc->parent;
         }
 
@@ -1848,17 +1839,17 @@ public:
             if (sc2->stc & (STCpure | STCnothrow | STCnogc))
                 sc2 = sc->push();
             sc2->stc &= ~(STCpure | STCnothrow | STCnogc);
-            e->declaration->semantic(sc2);
+            dsymbolSemantic(e->declaration, sc2);
             if (sc2 != sc)
                 sc2->pop();
             s->parent = sc->parent;
         }
         if (global.errors == olderrors)
         {
-            e->declaration->semantic2(sc);
+            semantic2(e->declaration, sc);
             if (global.errors == olderrors)
             {
-                e->declaration->semantic3(sc);
+                semantic3(e->declaration, sc);
             }
         }
         // todo: error in declaration should be propagated.
@@ -1885,7 +1876,7 @@ public:
             if (Dsymbol *sym = getDsymbol(ea))
                 ea = resolve(exp->loc, sc, sym, false);
             else
-                ea = semantic(ea, sc);
+                ea = expressionSemantic(ea, sc);
             ea = resolveProperties(sc, ea);
             ta = ea->type;
             if (ea->op == TOKtype)
@@ -1914,7 +1905,7 @@ public:
             {
                 /* Get the dynamic type, which is .classinfo
                 */
-                ea = semantic(ea, sc);
+                ea = expressionSemantic(ea, sc);
                 e = new TypeidExp(ea->loc, ea);
                 e->type = Type::typeinfoclass->type;
             }
@@ -1934,7 +1925,7 @@ public:
             if (ea)
             {
                 e = new CommaExp(exp->loc, ea, e);       // execute ea
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
             }
         }
         result = e;
@@ -2063,7 +2054,7 @@ public:
                         Parameters *args = new Parameters;
                         args->reserve(cd->baseclasses->length);
                         if (cd->semanticRun < PASSsemanticdone)
-                            cd->semantic(NULL);
+                            dsymbolSemantic(cd, NULL);
                         for (size_t i = 0; i < cd->baseclasses->length; i++)
                         {
                             BaseClass *b = (*cd->baseclasses)[i];
@@ -2171,7 +2162,7 @@ public:
              * is(targ == tspec)
              * is(targ : tspec)
              */
-            e->tspec = e->tspec->semantic(e->loc, sc);
+            e->tspec = typeSemantic(e->tspec, e->loc, sc);
             //printf("targ  = %s, %s\n", e->targ->toChars(), e->targ->deco);
             //printf("tspec = %s, %s\n", e->tspec->toChars(), e->tspec->deco);
             if (e->tok == TOKcolon)
@@ -2235,7 +2226,7 @@ public:
                     m = tp->matchArg(e->loc, sc, &tiargs, i, e->parameters, &dedtypes, &s);
                     if (m <= MATCHnomatch)
                         goto Lno;
-                    s->semantic(sc);
+                    dsymbolSemantic(s, sc);
                     if (!sc->insert(s))
                         e->error("declaration %s is already defined", s->toChars());
 
@@ -2262,7 +2253,7 @@ public:
                 s = new TupleDeclaration(e->loc, e->id, &(tup->objects));
             else
                 s = new AliasDeclaration(e->loc, e->id, tded);
-            s->semantic(sc);
+            dsymbolSemantic(s, sc);
             /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
              * More investigation is needed.
              */
@@ -2302,7 +2293,7 @@ public:
         {
             // arr.length op= e2;
             e = ArrayLengthExp::rewriteOpAssign(exp);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -2330,7 +2321,7 @@ public:
             return;
         }
 
-        exp->e1 = semantic(exp->e1, sc);
+        exp->e1 = expressionSemantic(exp->e1, sc);
         exp->e1 = exp->e1->optimize(WANTvalue);
         exp->e1 = exp->e1->modifiableLvalue(sc, exp->e1);
         exp->type = exp->e1->type;
@@ -2412,7 +2403,7 @@ public:
             exp->error("incomplete mixin expression (%s)", se->toChars());
             return setError();
         }
-        result = semantic(e, sc);
+        result = expressionSemantic(e, sc);
     }
 
     void visit(ImportExp *e)
@@ -2477,7 +2468,7 @@ public:
                 se = new StringExp(e->loc, f.buffer, f.len);
             }
         }
-        result = semantic(se, sc);
+        result = expressionSemantic(se, sc);
     }
 
     void visit(AssertExp *exp)
@@ -2493,7 +2484,7 @@ public:
         exp->e1 = exp->e1->toBoolean(sc);
         if (exp->msg)
         {
-            exp->msg = semantic(exp->msg, sc);
+            exp->msg = expressionSemantic(exp->msg, sc);
             exp->msg = resolveProperties(sc, exp->msg);
             exp->msg = exp->msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
             exp->msg = exp->msg->optimize(WANTvalue);
@@ -2530,7 +2521,7 @@ public:
             if (global.params.useAssert == CHECKENABLEoff)
             {
                 Expression *e = new HaltExp(exp->loc);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 result = e;
                 return;
             }
@@ -2586,7 +2577,7 @@ public:
 
         exp->var = exp->var->toAlias()->isDeclaration();
 
-        exp->e1 = semantic(exp->e1, sc);
+        exp->e1 = expressionSemantic(exp->e1, sc);
 
         if (TupleDeclaration *tup = exp->var->isTupleDeclaration())
         {
@@ -2630,7 +2621,7 @@ public:
             }
 
             Expression *e = new TupleExp(exp->loc, e0, exps);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -2688,7 +2679,7 @@ public:
                 /* Later checkRightThis will report correct error for invalid field variable access.
                 */
                 Expression *e = new VarExp(exp->loc, exp->var);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 result = e;
                 return;
             }
@@ -2711,7 +2702,7 @@ public:
                 checkAccess(exp->loc, sc, exp->e1, v);
                 Expression *e = new VarExp(exp->loc, v);
                 e = new CommaExp(exp->loc, exp->e1, e);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 result = e;
                 return;
             }
@@ -2738,9 +2729,9 @@ public:
             return;
         }
 
-        e->e1 = semantic(e->e1, sc);
+        e->e1 = expressionSemantic(e->e1, sc);
         e->type = new TypeDelegate(e->func->type);
-        e->type = e->type->semantic(e->loc, sc);
+        e->type = typeSemantic(e->type, e->loc, sc);
         FuncDeclaration *f = e->func->toAliasFunc();
         AggregateDeclaration *ad = f->toParent()->isAggregateDeclaration();
         if (f->needThis())
@@ -2762,7 +2753,7 @@ public:
         {
             // A downcast is required for interfaces, see Bugzilla 3706
             e->e1 = new CastExp(e->loc, e->e1, ad->type);
-            e->e1 = semantic(e->e1, sc);
+            e->e1 = expressionSemantic(e->e1, sc);
         }
         result = e;
     }
@@ -2806,7 +2797,7 @@ public:
             CommaExp *ce = (CommaExp *)exp->e1;
             exp->e1 = ce->e2;
             ce->e2 = exp;
-            result = semantic(ce, sc);
+            result = expressionSemantic(ce, sc);
             return;
         }
 
@@ -2814,7 +2805,7 @@ public:
         {
             DelegateExp *de = (DelegateExp *)exp->e1;
             exp->e1 = new DotVarExp(de->loc, de->e1, de->func, de->hasOverloads);
-            result = semantic(exp, sc);
+            result = expressionSemantic(exp, sc);
             return;
         }
 
@@ -2881,7 +2872,7 @@ public:
                 }
                 else
                 {
-                    Expression *e1x = semantic(exp->e1, sc);
+                    Expression *e1x = expressionSemantic(exp->e1, sc);
                     if (e1x->op == TOKerror)
                     {
                         result = e1x;
@@ -2926,7 +2917,7 @@ public:
                 }
                 else
                 {
-                    Expression *e1x = semantic(exp->e1, sc);
+                    Expression *e1x = expressionSemantic(exp->e1, sc);
                     if (e1x->op == TOKerror)
                     {
                         result =e1x;
@@ -2949,7 +2940,7 @@ public:
             if (exp->e1->op == TOKdotid)
             {
                 DotIdExp *die = (DotIdExp *)exp->e1;
-                exp->e1 = semantic(die, sc);
+                exp->e1 = expressionSemantic(die, sc);
                 /* Look for e1 having been rewritten to expr.opDispatch!(string)
                  * We handle such earlier, so go back.
                  * Note that in the rewrite, we carefully did not run semantic() on e1
@@ -2988,9 +2979,9 @@ public:
                     Type *tw = ve->var->type;
                     Type *tc = ve->var->type->substWildTo(MODconst);
                     TypeFunction *tf = new TypeFunction(ParameterList(), tc, LINKd, STCsafe | STCpure);
-                    (tf = (TypeFunction *)tf->semantic(exp->loc, sc))->next = tw;    // hack for bug7757
+                    (tf = (TypeFunction *)typeSemantic(tf, exp->loc, sc))->next = tw;    // hack for bug7757
                     TypeDelegate *t = new TypeDelegate(tf);
-                    ve->type = t->semantic(exp->loc, sc);
+                    ve->type = typeSemantic(t, exp->loc, sc);
                 }
                 VarDeclaration *v = ve->var->isVarDeclaration();
                 if (v && ve->checkPurity(sc, v))
@@ -3001,7 +2992,7 @@ public:
             {
                 SymOffExp *se = (SymOffExp *)exp->e1;
                 exp->e1 = new VarExp(se->loc, se->var, true);
-                exp->e1 = semantic(exp->e1, sc);
+                exp->e1 = expressionSemantic(exp->e1, sc);
             }
             else if (exp->e1->op == TOKdot)
             {
@@ -3081,7 +3072,7 @@ public:
                     else
                         assert(0);
                     e = new CallExp(exp->loc, e, exp->arguments);
-                    result = semantic(e, sc);
+                    result = expressionSemantic(e, sc);
                     return;
                 }
                 // No constructor, look for overload of opCall
@@ -3105,7 +3096,7 @@ public:
                 */
             Lx:
                 Expression *e = new StructLiteralExp(exp->loc, sd, exp->arguments, exp->e1->type);
-                result = semantic(e, sc);
+                result = expressionSemantic(e, sc);
                 return;
             }
             else if (t1->ty == Tclass)
@@ -3114,7 +3105,7 @@ public:
                 // Rewrite as e1.call(arguments)
                 Expression *e = new DotIdExp(exp->loc, exp->e1, Id::call);
                 e = new CallExp(exp->loc, e, exp->arguments);
-                result = semantic(e, sc);
+                result = expressionSemantic(e, sc);
                 return;
             }
             else if (exp->e1->op == TOKtype && t1->isscalar())
@@ -3143,7 +3134,7 @@ public:
                     exp->error("more than one argument for construction of %s", t1->toChars());
                     e = new ErrorExp();
                 }
-                result = semantic(e, sc);
+                result = expressionSemantic(e, sc);
                 return;
             }
         }
@@ -3192,7 +3183,7 @@ public:
                 BaseClass *b = exp->f->interfaceVirtual;
                 ClassDeclaration *ad2 = b->sym;
                 ue->e1 = ue->e1->castTo(sc, ad2->type->addMod(ue->e1->type->mod));
-                ue->e1 = semantic(ue->e1, sc);
+                ue->e1 = expressionSemantic(ue->e1, sc);
                 ue1 = ue->e1;
                 int vi = exp->f->findVtblIndex((Dsymbols*)&ad2->vtbl, (int)ad2->vtbl.length);
                 assert(vi >= 0);
@@ -3251,7 +3242,7 @@ public:
                 else
                 {
                     exp->e1 = new DotVarExp(exp->loc, dte->e1, exp->f, false);
-                    exp->e1 = semantic(exp->e1, sc);
+                    exp->e1 = expressionSemantic(exp->e1, sc);
                     if (exp->e1->op == TOKerror)
                         return setError();
                     ue = (UnaExp *)exp->e1;
@@ -3275,7 +3266,7 @@ public:
                     if (ad != cd)
                     {
                         ue->e1 = ue->e1->castTo(sc, ad->type->addMod(ue->e1->type->mod));
-                        ue->e1 = semantic(ue->e1, sc);
+                        ue->e1 = expressionSemantic(ue->e1, sc);
                     }
                 }
             }
@@ -3331,7 +3322,7 @@ public:
             checkAccess(exp->loc, sc, NULL, exp->f);
 
             exp->e1 = new DotVarExp(exp->e1->loc, exp->e1, exp->f, false);
-            exp->e1 = semantic(exp->e1, sc);
+            exp->e1 = expressionSemantic(exp->e1, sc);
             t1 = exp->e1->type;
         }
         else if (exp->e1->op == TOKthis)
@@ -3377,7 +3368,7 @@ public:
             //checkAccess(exp->loc, sc, NULL, exp->f);    // necessary?
 
             exp->e1 = new DotVarExp(exp->e1->loc, exp->e1, exp->f, false);
-            exp->e1 = semantic(exp->e1, sc);
+            exp->e1 = expressionSemantic(exp->e1, sc);
             t1 = exp->e1->type;
 
             // BUG: this should really be done by checking the static
@@ -3402,7 +3393,7 @@ public:
         }
         else if (!t1)
         {
-            exp->error("function expected before (), not '%s'", exp->e1->toChars());
+            exp->error("function expected before (), not `%s`", exp->e1->toChars());
             return setError();
         }
         else if (t1->ty == Terror)
@@ -3451,7 +3442,7 @@ public:
                 }
                 exp->e1 = new VarExp(dve->loc, exp->f, false);
                 Expression *e = new CommaExp(exp->loc, dve->e1, exp);
-                result = semantic(e, sc);
+                result = expressionSemantic(e, sc);
                 return;
             }
             else if (exp->e1->op == TOKvar &&
@@ -3474,13 +3465,13 @@ public:
                         // Supply an implicit 'this', as in
                         //    this.ident
                         Expression *ex = new ThisExp(exp->loc);
-                        ex = semantic(ex, sc);
+                        ex = expressionSemantic(ex, sc);
                         exp->e1 = new DotVarExp(exp->loc, ex, exp->f, false);
                         goto Lagain;
                     }
                     else if (isNeedThisScope(sc, exp->f))
                     {
-                        exp->error("need 'this' for '%s' of type '%s'", exp->f->toChars(), exp->f->type->toChars());
+                        exp->error("need `this` for `%s` of type `%s`", exp->f->toChars(), exp->f->type->toChars());
                         return setError();
                     }
                 }
@@ -3525,19 +3516,19 @@ public:
                 bool err = false;
                 if (!tf->purity && !(sc->flags & SCOPEdebug) && sc->func->setImpure())
                 {
-                    exp->error("pure %s '%s' cannot call impure %s '%s'",
+                    exp->error("pure %s `%s` cannot call impure %s `%s`",
                           sc->func->kind(), sc->func->toPrettyChars(), p, exp->e1->toChars());
                     err = true;
                 }
                 if (!tf->isnogc && sc->func->setGC())
                 {
-                    exp->error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
+                    exp->error("@nogc %s `%s` cannot call non-@nogc %s `%s`",
                           sc->func->kind(), sc->func->toPrettyChars(), p, exp->e1->toChars());
                     err = true;
                 }
                 if (tf->trust <= TRUSTsystem && sc->func->setUnsafe())
                 {
-                    exp->error("@safe %s '%s' cannot call @system %s '%s'",
+                    exp->error("@safe %s `%s` cannot call @system %s `%s`",
                           sc->func->kind(), sc->func->toPrettyChars(), p, exp->e1->toChars());
                     err = true;
                 }
@@ -3599,7 +3590,7 @@ public:
                     //    this.ident
 
                     Expression *ex = new ThisExp(exp->loc);
-                    ex = semantic(ex, sc);
+                    ex = expressionSemantic(ex, sc);
                     exp->e1 = new DotVarExp(exp->loc, ex, ve->var);
                     // Note: we cannot use f directly, because further overload resolution
                     // through the supplied 'this' may cause different result.
@@ -3607,7 +3598,7 @@ public:
                 }
                 else if (isNeedThisScope(sc, exp->f))
                 {
-                    exp->error("need 'this' for '%s' of type '%s'", exp->f->toChars(), exp->f->type->toChars());
+                    exp->error("need `this` for `%s` of type `%s`", exp->f->toChars(), exp->f->type->toChars());
                     return setError();
                 }
             }
@@ -3642,7 +3633,7 @@ public:
         if (!exp->type)
         {
             exp->e1 = e1org;     // Bugzilla 10922, avoid recursive expression printing
-            exp->error("forward reference to inferred return type of function call '%s'", exp->toChars());
+            exp->error("forward reference to inferred return type of function call `%s`", exp->toChars());
             return setError();
         }
 
@@ -3690,7 +3681,7 @@ public:
             TemplateInstance *ti = dti->ti;
             {
                 //assert(ti->needsTypeInference(sc));
-                ti->semantic(sc);
+                dsymbolSemantic(ti, sc);
                 if (!ti->inst || ti->errors)    // if template failed to expand
                     return setError();
                 Dsymbol *s = ti->toAlias();
@@ -3698,7 +3689,7 @@ public:
                 if (f)
                 {
                     exp->e1 = new DotVarExp(exp->e1->loc, dti->e1, f);
-                    exp->e1 = semantic(exp->e1, sc);
+                    exp->e1 = expressionSemantic(exp->e1, sc);
                 }
             }
         }
@@ -3708,7 +3699,7 @@ public:
             if (ti)
             {
                 //assert(ti->needsTypeInference(sc));
-                ti->semantic(sc);
+                dsymbolSemantic(ti, sc);
                 if (!ti->inst || ti->errors)    // if template failed to expand
                     return setError();
                 Dsymbol *s = ti->toAlias();
@@ -3716,7 +3707,7 @@ public:
                 if (f)
                 {
                     exp->e1 = new VarExp(exp->e1->loc, f);
-                    exp->e1 = semantic(exp->e1, sc);
+                    exp->e1 = expressionSemantic(exp->e1, sc);
                 }
             }
         }
@@ -3772,7 +3763,7 @@ public:
                     e = new DelegateExp(exp->loc, dve->e1, f, dve->hasOverloads);
                 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
                     e = new CommaExp(exp->loc, dve->e1, new AddrExp(exp->loc, new VarExp(exp->loc, f, dve->hasOverloads)));
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 result = e;
                 return;
             }
@@ -3833,13 +3824,13 @@ public:
                             /* Supply a 'null' for a this pointer if no this is available
                             */
                             Expression *e = new DelegateExp(exp->loc, new NullExp(exp->loc, Type::tnull), f, ve->hasOverloads);
-                            e = semantic(e, sc);
+                            e = expressionSemantic(e, sc);
                             result = e;
                             return;
                         }
                     }
                     Expression *e = new DelegateExp(exp->loc, exp->e1, f, ve->hasOverloads);
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     result = e;
                     return;
                 }
@@ -3852,7 +3843,7 @@ public:
                          */
                         Expression *ethis = new ThisExp(exp->loc);
                         Expression *e = new DelegateExp(exp->loc, ethis, f, ve->hasOverloads);
-                        e = semantic(e, sc);
+                        e = expressionSemantic(e, sc);
                         result = e;
                         return;
                     }
@@ -3860,7 +3851,7 @@ public:
                     {
                         if (sc->func->setUnsafe())
                         {
-                            exp->error("'this' reference necessary to take address of member %s in @safe function %s",
+                            exp->error("`this` reference necessary to take address of member %s in @safe function %s",
                                 f->toChars(), sc->func->toChars());
                         }
                     }
@@ -3926,9 +3917,9 @@ public:
 
             // Re-run semantic on the address expressions only
             ce->e1->type = NULL;
-            ce->e1 = semantic(ce->e1, sc);
+            ce->e1 = expressionSemantic(ce->e1, sc);
             ce->e2->type = NULL;
-            ce->e2 = semantic(ce->e2, sc);
+            ce->e2 = expressionSemantic(ce->e2, sc);
         }
 
         result = exp->optimize(WANTvalue);
@@ -3964,7 +3955,7 @@ public:
                 break;
 
             default:
-                exp->error("can only * a pointer, not a '%s'", exp->e1->type->toChars());
+                exp->error("can only * a pointer, not a `%s`", exp->e1->type->toChars());
                 /* fall through */
 
             case Terror:
@@ -4184,7 +4175,7 @@ public:
                 if (fd && f)
                 {
                     v = copyToTemp(0, "__tmpea", exp->e1);
-                    v->semantic(sc);
+                    dsymbolSemantic(v, sc);
                     ea = new DeclarationExp(exp->loc, v);
                     ea->type = v->type;
                 }
@@ -4194,7 +4185,7 @@ public:
                     Expression *e = ea ? new VarExp(exp->loc, v) : exp->e1;
                     e = new DotVarExp(Loc(), e, fd, false);
                     eb = new CallExp(exp->loc, e);
-                    eb = semantic(eb, sc);
+                    eb = expressionSemantic(eb, sc);
                 }
 
                 if (f)
@@ -4202,7 +4193,7 @@ public:
                     Type *tpv = Type::tvoid->pointerTo();
                     Expression *e = ea ? new VarExp(exp->loc, v) : exp->e1->castTo(sc, tpv);
                     e = new CallExp(exp->loc, new VarExp(exp->loc, f, false), e);
-                    ec = semantic(e, sc);
+                    ec = expressionSemantic(e, sc);
                 }
                 ea = Expression::combine(ea, eb);
                 ea = Expression::combine(ea, ec);
@@ -4271,7 +4262,7 @@ public:
 
         if (exp->to)
         {
-            exp->to = exp->to->semantic(exp->loc, sc);
+            exp->to = typeSemantic(exp->to, exp->loc, sc);
             if (exp->to == Type::terror)
                 return setError();
 
@@ -4307,7 +4298,7 @@ public:
         if (!exp->to)    // Handle cast(const) and cast(immutable), etc.
         {
             exp->to = exp->e1->type->castMod(exp->mod);
-            exp->to = exp->to->semantic(exp->loc, sc);
+            exp->to = typeSemantic(exp->to, exp->loc, sc);
             if (exp->to == Type::terror)
                 return setError();
         }
@@ -4405,8 +4396,8 @@ public:
             return;
         }
 
-        exp->e1 = semantic(exp->e1, sc);
-        exp->type = exp->to->semantic(exp->loc, sc);
+        exp->e1 = expressionSemantic(exp->e1, sc);
+        exp->type = typeSemantic(exp->to, exp->loc, sc);
         if (exp->e1->op == TOKerror || exp->type->ty == Terror)
         {
             result = exp->e1;
@@ -4477,11 +4468,11 @@ public:
         {
             if (exp->lwr || exp->upr)
             {
-                exp->error("cannot slice type '%s'", exp->e1->toChars());
+                exp->error("cannot slice type `%s`", exp->e1->toChars());
                 return setError();
             }
             Expression *e = new TypeExp(exp->loc, exp->e1->type->arrayOf());
-            result = semantic(e, sc);
+            result = expressionSemantic(e, sc);
             return;
         }
         if (!exp->lwr && !exp->upr)
@@ -4630,7 +4621,7 @@ public:
         if (exp->lwr)
         {
             if (t1b->ty == Ttuple) sc = sc->startCTFE();
-            exp->lwr = semantic(exp->lwr, sc);
+            exp->lwr = expressionSemantic(exp->lwr, sc);
             exp->lwr = resolveProperties(sc, exp->lwr);
             if (t1b->ty == Ttuple) sc = sc->endCTFE();
             exp->lwr = exp->lwr->implicitCastTo(sc, Type::tsize_t);
@@ -4638,7 +4629,7 @@ public:
         if (exp->upr)
         {
             if (t1b->ty == Ttuple) sc = sc->startCTFE();
-            exp->upr = semantic(exp->upr, sc);
+            exp->upr = expressionSemantic(exp->upr, sc);
             exp->upr = resolveProperties(sc, exp->upr);
             if (t1b->ty == Ttuple) sc = sc->endCTFE();
             exp->upr = exp->upr->implicitCastTo(sc, Type::tsize_t);
@@ -4706,7 +4697,7 @@ public:
                 }
                 e = new TypeExp(exp->e1->loc, new TypeTuple(args));
             }
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -4727,7 +4718,7 @@ public:
             if (t1b->ty == Tsarray || t1b->ty == Tarray)
             {
                 Expression *el = new ArrayLengthExp(exp->loc, exp->e1);
-                el = semantic(el, sc);
+                el = expressionSemantic(el, sc);
                 el = el->optimize(WANTvalue);
                 if (el->op == TOKint64)
                 {
@@ -4779,11 +4770,11 @@ public:
         }
 
         Expression *le = e->lwr;
-        le = semantic(le, sc);
+        le = expressionSemantic(le, sc);
         le = resolveProperties(sc, le);
 
         Expression *ue = e->upr;
-        ue = semantic(ue, sc);
+        ue = expressionSemantic(ue, sc);
         ue = resolveProperties(sc, ue);
 
         if (le->op == TOKerror)
@@ -4858,8 +4849,8 @@ public:
 
     void visit(DotExp *exp)
     {
-        exp->e1 = semantic(exp->e1, sc);
-        exp->e2 = semantic(exp->e2, sc);
+        exp->e1 = expressionSemantic(exp->e1, sc);
+        exp->e2 = expressionSemantic(exp->e2, sc);
 
         if (exp->e1->op == TOKtype)
         {
@@ -4875,7 +4866,7 @@ public:
         {
             TemplateDeclaration *td = ((TemplateExp *)exp->e2)->td;
             Expression *e = new DotTemplateExp(exp->loc, exp->e1, td);
-            result = semantic(e, sc);
+            result = expressionSemantic(e, sc);
             return;
         }
         if (!exp->type)
@@ -4927,11 +4918,11 @@ public:
         // operator overloading should be handled in ArrayExp already.
 
         if (!exp->e1->type)
-            exp->e1 = semantic(exp->e1, sc);
+            exp->e1 = expressionSemantic(exp->e1, sc);
         assert(exp->e1->type);           // semantic() should already be run on it
         if (exp->e1->op == TOKtype && exp->e1->type->ty != Ttuple)
         {
-            exp->e2 = semantic(exp->e2, sc);
+            exp->e2 = expressionSemantic(exp->e2, sc);
             exp->e2 = resolveProperties(sc, exp->e2);
             Type *nt;
             if (exp->e2->op == TOKtype)
@@ -4939,7 +4930,7 @@ public:
             else
                 nt = new TypeSArray(exp->e1->type, exp->e2);
             Expression *e = new TypeExp(exp->loc, nt);
-            result = semantic(e, sc);
+            result = expressionSemantic(e, sc);
             return;
         }
         if (exp->e1->op == TOKerror)
@@ -4975,7 +4966,7 @@ public:
             sc = sc->push(sym);
         }
         if (t1b->ty == Ttuple) sc = sc->startCTFE();
-        exp->e2 = semantic(exp->e2, sc);
+        exp->e2 = expressionSemantic(exp->e2, sc);
         exp->e2 = resolveProperties(sc, exp->e2);
         if (t1b->ty == Ttuple) sc = sc->endCTFE();
         if (exp->e2->op == TOKtuple)
@@ -5008,7 +4999,7 @@ public:
                     ;
                 else if (sc->func && sc->func->setUnsafe())
                 {
-                    exp->error("safe function '%s' cannot index pointer '%s'",
+                    exp->error("safe function `%s` cannot index pointer `%s`",
                         sc->func->toPrettyChars(), exp->e1->toChars());
                     return setError();
                 }
@@ -5104,7 +5095,7 @@ public:
         if (t1b->ty == Tsarray || t1b->ty == Tarray)
         {
             Expression *el = new ArrayLengthExp(exp->loc, exp->e1);
-            el = semantic(el, sc);
+            el = expressionSemantic(el, sc);
             el = el->optimize(WANTvalue);
             if (el->op == TOKint64)
             {
@@ -5154,7 +5145,7 @@ public:
         if (exp->e1->op == TOKslice)
         {
             const char *s = exp->op == TOKplusplus ? "increment" : "decrement";
-            exp->error("cannot post-%s array slice '%s', use pre-%s instead", s, exp->e1->toChars(), s);
+            exp->error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp->e1->toChars(), s);
             return setError();
         }
 
@@ -5194,7 +5185,7 @@ public:
                 ea = new CommaExp(exp->loc, de, ea);
             e = new CommaExp(exp->loc, ea, eb);
             e = new CommaExp(exp->loc, e, ec);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -5231,7 +5222,7 @@ public:
             e = new AddAssignExp(exp->loc, exp->e1, new IntegerExp(exp->loc, 1, Type::tint32));
         else
             e = new MinAssignExp(exp->loc, exp->e1, new IntegerExp(exp->loc, 1, Type::tint32));
-        result = semantic(e, sc);
+        result = expressionSemantic(e, sc);
     }
 
     void visit(AssignExp *exp)
@@ -5255,7 +5246,7 @@ public:
             Expression *e0;
             exp->e2 = Expression::extractLast(exp->e2, &e0);
             Expression *e = Expression::combine(e0, exp);
-            result = semantic(e, sc);
+            result = expressionSemantic(e, sc);
             return;
         }
 
@@ -5268,7 +5259,7 @@ public:
             Expression *res;
 
             ArrayExp *ae = (ArrayExp *)exp->e1;
-            ae->e1 = semantic(ae->e1, sc);
+            ae->e1 = expressionSemantic(ae->e1, sc);
             ae->e1 = resolveProperties(sc, ae->e1);
             Expression *ae1old = ae->e1;
 
@@ -5309,7 +5300,7 @@ public:
                         return;
                     }
 
-                    res = semantic(exp->e2, sc);
+                    res = expressionSemantic(exp->e2, sc);
                     if (res->op == TOKerror)
                     {
                         result = res;
@@ -5327,7 +5318,7 @@ public:
                     if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
                         res = trySemantic(res, sc);
                     else
-                        res = semantic(res, sc);
+                        res = expressionSemantic(res, sc);
                     if (res)
                     {
                         res = Expression::combine(e0, res);
@@ -5346,7 +5337,7 @@ public:
                         return;
                     }
 
-                    res = semantic(exp->e2, sc);
+                    res = expressionSemantic(exp->e2, sc);
                     if (res->op == TOKerror)
                     {
                         result = res;
@@ -5366,7 +5357,7 @@ public:
                     }
                     res = new DotIdExp(exp->loc, ae->e1, Id::sliceass);
                     res = new CallExp(exp->loc, res, a);
-                    res = semantic(res, sc);
+                    res = expressionSemantic(res, sc);
                     res = Expression::combine(e0, res);
                     result = res;
                     return;
@@ -5442,7 +5433,7 @@ public:
                 if (e1x->op == TOKslice)
                     ((SliceExp *)e1x)->arrayop = true;
 
-                e1x = semantic(e1x, sc);
+                e1x = expressionSemantic(e1x, sc);
             }
 
             /* We have f = value.
@@ -5470,7 +5461,7 @@ public:
         {
             Expression *e2x = inferType(exp->e2, t1->baseElemOf());
 
-            e2x = semantic(e2x, sc);
+            e2x = expressionSemantic(e2x, sc);
             e2x = resolveProperties(sc, e2x);
 
             if (e2x->op == TOKtype)
@@ -5520,7 +5511,7 @@ public:
                     }
                     e = new TupleExp(exp->loc, Expression::combine(tup1->e0, tup2->e0), exps);
                 }
-                result = semantic(e, sc);
+                result = expressionSemantic(e, sc);
                 return;
             }
 
@@ -5564,7 +5555,7 @@ public:
                     }
                 }
                 e2x = new TupleExp(e2x->loc, e0, iexps);
-                e2x = semantic(e2x, sc);
+                e2x = expressionSemantic(e2x, sc);
                 if (e2x->op == TOKerror)
                 {
                     result = e2x;
@@ -5673,7 +5664,7 @@ public:
 
                         Expression *e = Expression::combine(ae, cx);
                         e = Expression::combine(e0, e);
-                        e = semantic(e, sc);
+                        e = expressionSemantic(e, sc);
                         result = e;
                         return;
                     }
@@ -5690,7 +5681,7 @@ public:
                             Expression *ea1 = new ConstructExp(econd->e1->loc, e1x, econd->e1);
                             Expression *ea2 = new ConstructExp(econd->e1->loc, e1x, econd->e2);
                             Expression *e = new CondExp(exp->loc, econd->econd, ea1, ea2);
-                            result = semantic(e, sc);
+                            result = expressionSemantic(e, sc);
                             return;
                         }
 
@@ -5713,7 +5704,7 @@ public:
                             e = new BlitExp(exp->loc, e, e2x);
                             e = new DotVarExp(exp->loc, e, sd->postblit, false);
                             e = new CallExp(exp->loc, e);
-                            result = semantic(e, sc);
+                            result = expressionSemantic(e, sc);
                             return;
                         }
                         else
@@ -5747,7 +5738,7 @@ public:
                         e = new DotIdExp(exp->loc, e1x, Id::ctor);
                         e = new CallExp(exp->loc, e, e2x);
                         e = new CommaExp(exp->loc, einit, e);
-                        e = semantic(e, sc);
+                        e = expressionSemantic(e, sc);
                         result = e;
                         return;
                     }
@@ -5761,7 +5752,7 @@ public:
                         e2x = typeDotIdExp(e2x->loc, e1x->type, Id::call);
                         e2x = new CallExp(exp->loc, e2x, exp->e2);
 
-                        e2x = semantic(e2x, sc);
+                        e2x = expressionSemantic(e2x, sc);
                         e2x = resolveProperties(sc, e2x);
                         if (e2x->op == TOKerror)
                         {
@@ -5784,7 +5775,7 @@ public:
                          *      (e1 op e2.aliasthis)
                          */
                         exp->e2 = new DotIdExp(exp->e2->loc, exp->e2, ad2->aliasthis->ident);
-                        result = semantic(exp, sc);
+                        result = expressionSemantic(exp, sc);
                         return;
                     }
                 }
@@ -5815,7 +5806,7 @@ public:
 
                     AssignExp *ae = (AssignExp *)exp->copy();
                     ae->e1 = new IndexExp(exp->loc, ea, ek);
-                    ae->e1 = semantic(ae->e1, sc);
+                    ae->e1 = expressionSemantic(ae->e1, sc);
                     ae->e1 = ae->e1->optimize(WANTvalue);
                     ae->e2 = ev;
                     Expression *e = ae->op_overload(sc);
@@ -5839,11 +5830,11 @@ public:
                         {
                             Expression *ex;
                             ex = new IndexExp(exp->loc, ea, ek);
-                            ex = semantic(ex, sc);
+                            ex = expressionSemantic(ex, sc);
                             ex = ex->optimize(WANTvalue);
                             ex = ex->modifiableLvalue(sc, ex);  // allocate new slot
                             ey = new ConstructExp(exp->loc, ex, ey);
-                            ey = semantic(ey, sc);
+                            ey = expressionSemantic(ey, sc);
                             if (ey->op == TOKerror)
                             {
                                 result = ey;
@@ -5863,7 +5854,7 @@ public:
                             e = new CondExp(exp->loc, new InExp(exp->loc, ek, ea), ex, ey);
                         }
                         e = Expression::combine(e0, e);
-                        e = semantic(e, sc);
+                        e = expressionSemantic(e, sc);
                         result = e;
                         return;
                     }
@@ -5923,7 +5914,7 @@ public:
                     // e.g. e1[] = a[] + b[];
                     SliceExp *sle = new SliceExp(e1x->loc, e1x, NULL, NULL);
                     sle->arrayop = true;
-                    e1x = semantic(sle, sc);
+                    e1x = expressionSemantic(sle, sc);
                 }
                 else
                 {
@@ -5965,7 +5956,7 @@ public:
                 }
                 SliceExp *sle = new SliceExp(e1x->loc, e1x, NULL, NULL);
                 sle->arrayop = true;
-                e1x = semantic(sle, sc);
+                e1x = expressionSemantic(sle, sc);
             }
             if (e1x->op == TOKerror)
             {
@@ -6421,7 +6412,7 @@ public:
                 e = new CommaExp(exp->loc, de, e);
             }
             e = Expression::combine(e0, e);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -6939,7 +6930,7 @@ public:
                     exp->e1->type = exp->type;
                     exp->e2->type = exp->type;
                     e = new NegExp(exp->loc, exp);
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     result = e;
                     return;
                 }
@@ -7013,7 +7004,7 @@ public:
                     // x/iv = i(-x/v)
                     exp->e2->type = t1;
                     e = new NegExp(exp->loc, exp);
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     result = e;
                     return;
                 }
@@ -7130,7 +7121,7 @@ public:
             if (s->mod)
             {
                 s->mod->importAll(NULL);
-                s->mod->semantic(NULL);
+                dsymbolSemantic(s->mod, NULL);
             }
             impStdMath = s;
         }
@@ -7192,7 +7183,7 @@ public:
         e = exp->optimize(WANTvalue);
         if (e->op != TOKpow)
         {
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -7219,7 +7210,7 @@ public:
             if (intpow == 3)
                 me = new MulExp(exp->loc, me, ve);
             e = new CommaExp(exp->loc, de, me);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             result = e;
             return;
         }
@@ -7252,7 +7243,7 @@ public:
             // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
             e = new CallExp(exp->loc, new DotIdExp(exp->loc, e, Id::_pow), exp->e1, exp->e2);
         }
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         result = e;
     }
 
@@ -7543,7 +7534,7 @@ public:
 
         setNoderefOperands(exp);
 
-        Expression *e1x = semantic(exp->e1, sc);
+        Expression *e1x = expressionSemantic(exp->e1, sc);
 
         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
         if (e1x->op == TOKtype)
@@ -7565,7 +7556,7 @@ public:
             }
         }
 
-        Expression *e2x = semantic(exp->e2, sc);
+        Expression *e2x = expressionSemantic(exp->e2, sc);
         sc->mergeCallSuper(exp->loc, cs1);
 
         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
@@ -7706,7 +7697,7 @@ public:
             if (e->op == TOKcall)
             {
                 e = new CmpExp(exp->op, exp->loc, e, new IntegerExp(exp->loc, 0, Type::tint32));
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
             }
             result = e;
             return;
@@ -7796,7 +7787,7 @@ public:
             (t1->ty == Tarray || t1->ty == Tsarray ||
              t2->ty == Tarray || t2->ty == Tsarray))
         {
-            exp->error("'%s' is not defined for array comparisons", Token::toChars(exp->op));
+            exp->error("`%s` is not defined for array comparisons", Token::toChars(exp->op));
             return setError();
         }
         if (altop != TOKreserved)
@@ -7806,18 +7797,18 @@ public:
                 if (altop == TOKerror)
                 {
                     const char *s = exp->op == TOKunord ? "false" : "true";
-                    exp->error("floating point operator '%s' always returns %s for non-floating comparisons",
+                    exp->error("floating point operator `%s` always returns %s for non-floating comparisons",
                         Token::toChars(exp->op), s);
                 }
                 else
                 {
-                    exp->error("use '%s' for non-floating comparisons rather than floating point operator '%s'",
+                    exp->error("use `%s` for non-floating comparisons rather than floating point operator `%s`",
                         Token::toChars(altop), Token::toChars(exp->op));
                 }
             }
             else
             {
-                exp->error("use std.math.isNaN to deal with NaN operands rather than floating point operator '%s'",
+                exp->error("use std.math.isNaN to deal with NaN operands rather than floating point operator `%s`",
                     Token::toChars(exp->op));
             }
             return setError();
@@ -7987,20 +7978,20 @@ public:
         if (exp->econd->op == TOKdotid)
             ((DotIdExp *)exp->econd)->noderef = true;
 
-        Expression *ec = semantic(exp->econd, sc);
+        Expression *ec = expressionSemantic(exp->econd, sc);
         ec = resolveProperties(sc, ec);
         ec = ec->toBoolean(sc);
 
         unsigned cs0 = sc->callSuper;
         unsigned *fi0 = sc->saveFieldInit();
-        Expression *e1x = semantic(exp->e1, sc);
+        Expression *e1x = expressionSemantic(exp->e1, sc);
         e1x = resolveProperties(sc, e1x);
 
         unsigned cs1 = sc->callSuper;
         unsigned *fi1 = sc->fieldinit;
         sc->callSuper = cs0;
         sc->fieldinit = fi0;
-        Expression *e2x = semantic(exp->e2, sc);
+        Expression *e2x = expressionSemantic(exp->e2, sc);
         e2x = resolveProperties(sc, e2x);
 
         sc->mergeCallSuper(exp->loc, cs1);
@@ -8151,7 +8142,7 @@ Expression *trySemantic(Expression *exp, Scope* sc)
 {
     //printf("+trySemantic(%s)\n", toChars());
     unsigned errors = global.startGagging();
-    Expression *e = semantic(exp, sc);
+    Expression *e = expressionSemantic(exp, sc);
     if (global.endGagging(errors))
     {
         e = NULL;
@@ -8166,7 +8157,7 @@ Expression *trySemantic(Expression *exp, Scope* sc)
  */
 Expression *unaSemantic(UnaExp *e, Scope *sc)
 {
-    Expression *e1x = semantic(e->e1, sc);
+    Expression *e1x = expressionSemantic(e->e1, sc);
     if (e1x->op == TOKerror)
         return e1x;
     e->e1 = e1x;
@@ -8179,8 +8170,8 @@ Expression *unaSemantic(UnaExp *e, Scope *sc)
  */
 Expression *binSemantic(BinExp *e, Scope *sc)
 {
-    Expression *e1x = semantic(e->e1, sc);
-    Expression *e2x = semantic(e->e2, sc);
+    Expression *e1x = expressionSemantic(e->e1, sc);
+    Expression *e2x = expressionSemantic(e->e2, sc);
 
     // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
     if (e1x->op == TOKtype)
@@ -8213,7 +8204,7 @@ Expression *binSemanticProp(BinExp *e, Scope *sc)
 }
 
 // entrypoint for semantic ExpressionSemanticVisitor
-Expression *semantic(Expression *e, Scope *sc)
+Expression *expressionSemantic(Expression *e, Scope *sc)
 {
     ExpressionSemanticVisitor v = ExpressionSemanticVisitor(sc);
     e->accept(&v);
@@ -8261,7 +8252,7 @@ Expression *semanticX(DotIdExp *exp, Scope *sc)
                     mangleToBuffer(ds, &buf);
                     const char *s = buf.extractChars();
                     Expression *e = new StringExp(exp->loc, const_cast<char*>(s), strlen(s));
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     return e;
                 }
             default:
@@ -8292,13 +8283,13 @@ Expression *semanticX(DotIdExp *exp, Scope *sc)
         for (size_t i = 0; i < exps->length; i++)
         {
             Expression *e = (*te->exps)[i];
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             e = new DotIdExp(e->loc, e, Id::offsetof);
             (*exps)[i] = e;
         }
         // Don't evaluate te->e0 in runtime
         Expression *e = new TupleExp(exp->loc, NULL, exps);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
     if (exp->e1->op == TOKtuple && exp->ident == Id::length)
@@ -8312,13 +8303,13 @@ Expression *semanticX(DotIdExp *exp, Scope *sc)
     // Bugzilla 14416: Template has no built-in properties except for 'stringof'.
     if ((exp->e1->op == TOKdottd || exp->e1->op == TOKtemplate) && exp->ident != Id::stringof)
     {
-        exp->error("template %s does not have property '%s'", exp->e1->toChars(), exp->ident->toChars());
+        exp->error("template %s does not have property `%s`", exp->e1->toChars(), exp->ident->toChars());
         return new ErrorExp();
     }
 
     if (!exp->e1->type)
     {
-        exp->error("expression %s does not have property '%s'", exp->e1->toChars(), exp->ident->toChars());
+        exp->error("expression %s does not have property `%s`", exp->e1->toChars(), exp->ident->toChars());
         return new ErrorExp();
     }
 
@@ -8425,9 +8416,9 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                     (!v->type->deco && v->inuse))
                 {
                     if (v->inuse)
-                        exp->error("circular reference to %s '%s'", v->kind(), v->toPrettyChars());
+                        exp->error("circular reference to %s `%s`", v->kind(), v->toPrettyChars());
                     else
-                        exp->error("forward reference to %s '%s'", v->kind(), v->toPrettyChars());
+                        exp->error("forward reference to %s `%s`", v->kind(), v->toPrettyChars());
                     return new ErrorExp();
                 }
                 if (v->type->ty == Terror)
@@ -8441,12 +8432,12 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                      */
                     if (v->inuse)
                     {
-                        ::error(exp->loc, "circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
+                        ::error(exp->loc, "circular initialization of %s `%s`", v->kind(), v->toPrettyChars());
                         return new ErrorExp();
                     }
                     e = v->expandInitializer(exp->loc);
                     v->inuse++;
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     v->inuse--;
                     return e;
                 }
@@ -8456,7 +8447,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                     if (!eleft)
                         eleft = new ThisExp(exp->loc);
                     e = new DotVarExp(exp->loc, eleft, v);
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                 }
                 else
                 {
@@ -8467,7 +8458,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                     }
                 }
                 e = e->deref();
-                return semantic(e, sc);
+                return expressionSemantic(e, sc);
             }
 
             FuncDeclaration *f = s->isFuncDeclaration();
@@ -8481,7 +8472,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                     if (!eleft)
                         eleft = new ThisExp(exp->loc);
                     e = new DotVarExp(exp->loc, eleft, f, true);
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                 }
                 else
                 {
@@ -8499,7 +8490,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                     e = new DotTemplateExp(exp->loc, eleft, td);
                 else
                     e = new TemplateExp(exp->loc, td);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 return e;
             }
             if (OverDeclaration *od = s->isOverDeclaration())
@@ -8520,7 +8511,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
 
             if (Type *t = s->getType())
             {
-                return semantic(new TypeExp(exp->loc, t), sc);
+                return expressionSemantic(new TypeExp(exp->loc, t), sc);
             }
 
             TupleDeclaration *tup = s->isTupleDeclaration();
@@ -8529,11 +8520,11 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                 if (eleft)
                 {
                     e = new DotVarExp(exp->loc, eleft, tup);
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     return e;
                 }
                 e = new TupleExp(exp->loc, tup);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 return e;
             }
 
@@ -8542,7 +8533,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
             {
                 //printf("it's a ScopeDsymbol %s\n", exp->ident->toChars());
                 e = new ScopeExp(exp->loc, sds);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 if (eleft)
                     e = new DotExp(exp->loc, eleft, e);
                 return e;
@@ -8552,7 +8543,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
             if (imp)
             {
                 ie = new ScopeExp(exp->loc, imp->pkg);
-                return semantic(ie, sc);
+                return expressionSemantic(ie, sc);
             }
 
             // BUG: handle other cases like in IdentifierExp::semantic()
@@ -8562,7 +8553,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
         {
             const char *p = ie->toChars();
             e = new StringExp(exp->loc, const_cast<char *>(p), strlen(p));
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
         if (ie->sds->isPackage() ||
@@ -8580,11 +8571,11 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
                 exp->error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`",
                     exp->ident->toChars(), ie->sds->kind(), ie->sds->toPrettyChars(), s->toPrettyChars());
             else
-                exp->error("undefined identifier '%s' in %s '%s', did you mean %s '%s'?",
+                exp->error("undefined identifier `%s` in %s `%s`, did you mean %s `%s`?",
                     exp->ident->toChars(), ie->sds->kind(), ie->sds->toPrettyChars(), s->kind(), s->toChars());
         }
         else
-            exp->error("undefined identifier '%s' in %s '%s'",
+            exp->error("undefined identifier `%s` in %s `%s`",
                        exp->ident->toChars(), ie->sds->kind(), ie->sds->toPrettyChars());
         return new ErrorExp();
     }
@@ -8609,7 +8600,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
         if (flag && t1bn->ty == Tvoid)
             return NULL;
         e = new PtrExp(exp->loc, exp->e1);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e->type->dotExp(sc, e, exp->ident, flag | (exp->noderef ? 2 : 0));
     }
     else
@@ -8618,7 +8609,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
             flag = 0;
         e = exp->e1->type->dotExp(sc, exp->e1, exp->ident, flag | (exp->noderef ? 2 : 0));
         if (e)
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
         return e;
     }
 }
@@ -8668,7 +8659,7 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
             if (td)
             {
                 e = new DotTemplateExp(dve->loc, dve->e1, td);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
             }
         }
         else if (dve->var->isOverDeclaration())
@@ -8678,7 +8669,7 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
                 goto Lerr;
             if (exp->ti->needsTypeInference(sc))
                 return exp;
-            exp->ti->semantic(sc);
+            dsymbolSemantic(exp->ti, sc);
             if (!exp->ti->inst || exp->ti->errors)    // if template failed to expand
                 return new ErrorExp();
             Dsymbol *s = exp->ti->toAlias();
@@ -8686,14 +8677,14 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
             if (v)
             {
                 if (v->type && !v->type->deco)
-                    v->type = v->type->semantic(v->loc, sc);
+                    v->type = typeSemantic(v->type, v->loc, sc);
                 e = new DotVarExp(exp->loc, exp->e1, v);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 return e;
             }
             e = new ScopeExp(exp->loc, exp->ti);
             e = new DotExp(exp->loc, exp->e1, e);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
     }
@@ -8706,14 +8697,14 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
             if (td)
             {
                 e = new TemplateExp(ve->loc, td);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
             }
         }
         else if (OverDeclaration *od = ve->var->isOverDeclaration())
         {
             exp->ti->tempdecl = od;
             e = new ScopeExp(exp->loc, exp->ti);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
     }
@@ -8727,7 +8718,7 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
             return new ErrorExp();
         if (exp->ti->needsTypeInference(sc))
             return exp;
-        exp->ti->semantic(sc);
+        dsymbolSemantic(exp->ti, sc);
         if (!exp->ti->inst || exp->ti->errors)    // if template failed to expand
             return new ErrorExp();
         Dsymbol *s = exp->ti->toAlias();
@@ -8735,19 +8726,19 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
         if (v && (v->isFuncDeclaration() || v->isVarDeclaration()))
         {
             e = new DotVarExp(exp->loc, exp->e1, v);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
         e = new ScopeExp(exp->loc, exp->ti);
         e = new DotExp(exp->loc, exp->e1, e);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
     else if (e->op == TOKtemplate)
     {
         exp->ti->tempdecl = ((TemplateExp *)e)->td;
         e = new ScopeExp(exp->loc, exp->ti);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
     else if (e->op == TOKdot)
@@ -8763,7 +8754,7 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
             }
             if (exp->ti->needsTypeInference(sc))
                 return exp;
-            exp->ti->semantic(sc);
+            dsymbolSemantic(exp->ti, sc);
             if (!exp->ti->inst || exp->ti->errors)    // if template failed to expand
                 return new ErrorExp();
             Dsymbol *s = exp->ti->toAlias();
@@ -8771,14 +8762,14 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
             if (v)
             {
                 if (v->type && !v->type->deco)
-                    v->type = v->type->semantic(v->loc, sc);
+                    v->type = typeSemantic(v->type, v->loc, sc);
                 e = new DotVarExp(exp->loc, exp->e1, v);
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 return e;
             }
             e = new ScopeExp(exp->loc, exp->ti);
             e = new DotExp(exp->loc, exp->e1, e);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
     }
@@ -8787,7 +8778,7 @@ Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag)
         OverExp *oe = (OverExp *)e;
         exp->ti->tempdecl = oe->vars;
         e = new ScopeExp(exp->loc, exp->ti);
-        e = semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
 Lerr:
index 2f1d648bf3526c75c915a528e7c5f8a2751c7a13..7a216a97941b1aee81dd3f7a2bcfe32ec45421c0 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
 #include "id.h"
 #include "module.h"
 #include "statement.h"
+#include "statement_rewrite_walker.h"
 #include "template.h"
 #include "hdrgen.h"
 #include "target.h"
 #include "parse.h"
 #include "root/rmem.h"
 #include "visitor.h"
-#include "objc.h"
 
-Expression *addInvariant(AggregateDeclaration *ad, VarDeclaration *vthis);
-bool checkReturnEscape(Scope *sc, Expression *e, bool gag);
-bool checkReturnEscapeRef(Scope *sc, Expression *e, bool gag);
 bool checkNestedRef(Dsymbol *s, Dsymbol *p);
-Statement *semantic(Statement *s, Scope *sc);
-void semantic(Catch *c, Scope *sc);
-Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
-Expression *semantic(Expression *e, Scope *sc);
 int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
 TypeIdentifier *getThrowable();
 
-void MODtoBuffer(OutBuffer *buf, MOD mod);
-char *MODtoChars(MOD mod);
 bool MODimplicitConv(MOD modfrom, MOD modto);
 MATCH MODmethodConv(MOD modfrom, MOD modto);
-void allocFieldinit(Scope *sc, size_t dim);
-void freeFieldinit(Scope *sc);
-Objc *objc();
-
-
-/* A visitor to walk entire statements and provides ability to replace any sub-statements.
- */
-class StatementRewriteWalker : public Visitor
-{
-    /* Point the currently visited statement.
-     * By using replaceCurrent() method, you can replace AST during walking.
-     */
-    Statement **ps;
-public:
-    void visitStmt(Statement *&s) { ps = &s; s->accept(this); }
-    void replaceCurrent(Statement *s) { *ps = s; }
-
-    void visit(ErrorStatement *) {  }
-    void visit(PeelStatement *s)
-    {
-        if (s->s)
-            visitStmt(s->s);
-    }
-    void visit(ExpStatement *) {  }
-    void visit(DtorExpStatement *) {  }
-    void visit(CompileStatement *) {  }
-    void visit(CompoundStatement *s)
-    {
-        if (s->statements && s->statements->length)
-        {
-            for (size_t i = 0; i < s->statements->length; i++)
-            {
-                if ((*s->statements)[i])
-                    visitStmt((*s->statements)[i]);
-            }
-        }
-    }
-    void visit(CompoundDeclarationStatement *s) { visit((CompoundStatement *)s); }
-    void visit(UnrolledLoopStatement *s)
-    {
-        if (s->statements && s->statements->length)
-        {
-            for (size_t i = 0; i < s->statements->length; i++)
-            {
-                if ((*s->statements)[i])
-                    visitStmt((*s->statements)[i]);
-            }
-        }
-    }
-    void visit(ScopeStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(WhileStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(DoStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(ForStatement *s)
-    {
-        if (s->_init)
-            visitStmt(s->_init);
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(ForeachStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(ForeachRangeStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(IfStatement *s)
-    {
-        if (s->ifbody)
-            visitStmt(s->ifbody);
-        if (s->elsebody)
-            visitStmt(s->elsebody);
-    }
-    void visit(ConditionalStatement *) {  }
-    void visit(PragmaStatement *) {  }
-    void visit(StaticAssertStatement *) {  }
-    void visit(SwitchStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(CaseStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(CaseRangeStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(DefaultStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(GotoDefaultStatement *) {  }
-    void visit(GotoCaseStatement *) {  }
-    void visit(SwitchErrorStatement *) {  }
-    void visit(ReturnStatement *) {  }
-    void visit(BreakStatement *) {  }
-    void visit(ContinueStatement *) {  }
-    void visit(SynchronizedStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(WithStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-    }
-    void visit(TryCatchStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-        if (s->catches && s->catches->length)
-        {
-            for (size_t i = 0; i < s->catches->length; i++)
-            {
-                Catch *c = (*s->catches)[i];
-                if (c && c->handler)
-                    visitStmt(c->handler);
-            }
-        }
-    }
-    void visit(TryFinallyStatement *s)
-    {
-        if (s->_body)
-            visitStmt(s->_body);
-        if (s->finalbody)
-            visitStmt(s->finalbody);
-    }
-    void visit(ScopeGuardStatement *) {  }
-    void visit(ThrowStatement *) {  }
-    void visit(DebugStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(GotoStatement *) {  }
-    void visit(LabelStatement *s)
-    {
-        if (s->statement)
-            visitStmt(s->statement);
-    }
-    void visit(AsmStatement *) {  }
-    void visit(ImportStatement *) {  }
-};
-
-/* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
- */
-class NrvoWalker : public StatementRewriteWalker
-{
-public:
-    FuncDeclaration *fd;
-    Scope *sc;
-
-    void visit(ReturnStatement *s)
-    {
-        // See if all returns are instead to be replaced with a goto returnLabel;
-        if (fd->returnLabel)
-        {
-            /* Rewrite:
-             *  return exp;
-             * as:
-             *  vresult = exp; goto Lresult;
-             */
-            GotoStatement *gs = new GotoStatement(s->loc, Id::returnLabel);
-            gs->label = fd->returnLabel;
-
-            Statement *s1 = gs;
-            if (s->exp)
-                s1 = new CompoundStatement(s->loc, new ExpStatement(s->loc, s->exp), gs);
-
-            replaceCurrent(s1);
-        }
-    }
-    void visit(TryFinallyStatement *s)
-    {
-        DtorExpStatement *des;
-        if (fd->nrvo_can &&
-            s->finalbody && (des = s->finalbody->isDtorExpStatement()) != NULL &&
-            fd->nrvo_var == des->var)
-        {
-            if (!(global.params.useExceptions && ClassDeclaration::throwable))
-            {
-                /* Don't need to call destructor at all, since it is nrvo
-                 */
-                replaceCurrent(s->_body);
-                s->_body->accept(this);
-                return;
-            }
-
-            /* Normally local variable dtors are called regardless exceptions.
-             * But for nrvo_var, its dtor should be called only when exception is thrown.
-             *
-             * Rewrite:
-             *      try { s->body; } finally { nrvo_var->edtor; }
-             *      // equivalent with:
-             *      //    s->body; scope(exit) nrvo_var->edtor;
-             * as:
-             *      try { s->body; } catch(Throwable __o) { nrvo_var->edtor; throw __o; }
-             *      // equivalent with:
-             *      //    s->body; scope(failure) nrvo_var->edtor;
-             */
-            Statement *sexception = new DtorExpStatement(Loc(), fd->nrvo_var->edtor, fd->nrvo_var);
-            Identifier *id = Identifier::generateId("__o");
-
-            Statement *handler = new PeelStatement(sexception);
-            if (blockExit(sexception, fd, false) & BEfallthru)
-            {
-                ThrowStatement *ts = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id));
-                ts->internalThrow = true;
-                handler = new CompoundStatement(Loc(), handler, ts);
-            }
-
-            Catches *catches = new Catches();
-            Catch *ctch = new Catch(Loc(), getThrowable(), id, handler);
-            ctch->internalCatch = true;
-            ::semantic(ctch, sc);     // Run semantic to resolve identifier '__o'
-            catches->push(ctch);
-
-            Statement *s2 = new TryCatchStatement(Loc(), s->_body, catches);
-            replaceCurrent(s2);
-            s2->accept(this);
-        }
-        else
-            StatementRewriteWalker::visit(s);
-    }
-};
 
 /***********************************************************
  * Tuple of result identifier (possibly null) and statement.
@@ -416,69 +161,8 @@ Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
     return f;
 }
 
-/**********************************
- * Decide if attributes for this function can be inferred from examining
- * the function body.
- * Returns:
- *  true if can
- */
-static bool canInferAttributes(FuncDeclaration *fd, Scope *sc)
-{
-    if (!fd->fbody)
-        return false;
-
-    if (fd->isVirtualMethod())
-        return false;               // since they may be overridden
-
-    if (sc->func &&
-        /********** this is for backwards compatibility for the moment ********/
-        (!fd->isMember() || (sc->func->isSafeBypassingInference() && !fd->isInstantiated())))
-        return true;
-
-    if (fd->isFuncLiteralDeclaration() ||               // externs are not possible with literals
-        (fd->storage_class & STCinference) ||           // do attribute inference
-        (fd->inferRetType && !fd->isCtorDeclaration()))
-        return true;
-
-    if (fd->isInstantiated())
-    {
-        TemplateInstance *ti = fd->parent->isTemplateInstance();
-        if (ti == NULL || ti->isTemplateMixin() || ti->tempdecl->ident == fd->ident)
-            return true;
-    }
-
-    return false;
-}
-
-/*****************************************
- * Initialize for inferring the attributes of this function.
- */
-static void initInferAttributes(FuncDeclaration *fd)
-{
-    //printf("initInferAttributes() for %s\n", toPrettyChars());
-    TypeFunction *tf = fd->type->toTypeFunction();
-    if (tf->purity == PUREimpure) // purity not specified
-        fd->flags |= FUNCFLAGpurityInprocess;
-
-    if (tf->trust == TRUSTdefault)
-        fd->flags |= FUNCFLAGsafetyInprocess;
-
-    if (!tf->isnothrow)
-        fd->flags |= FUNCFLAGnothrowInprocess;
-
-    if (!tf->isnogc)
-        fd->flags |= FUNCFLAGnogcInprocess;
-
-    if (!fd->isVirtual() || fd->introducing)
-        fd->flags |= FUNCFLAGreturnInprocess;
-
-    // Initialize for inferring STCscope
-    if (global.params.vsafe)
-        fd->flags |= FUNCFLAGinferScope;
-}
-
 // Returns true if a contract can appear without a function body.
-static bool allowsContractWithoutBody(FuncDeclaration *funcdecl)
+bool allowsContractWithoutBody(FuncDeclaration *funcdecl)
 {
     assert(!funcdecl->fbody);
 
@@ -499,2019 +183,166 @@ static bool allowsContractWithoutBody(FuncDeclaration *funcdecl)
     return true;
 }
 
-// Do the semantic analysis on the external interface to the function.
-
-void FuncDeclaration::semantic(Scope *sc)
+/****************************************************
+ * Determine whether an 'out' contract is declared inside
+ * the given function or any of its overrides.
+ * Params:
+ *      fd = the function to search
+ * Returns:
+ *      true    found an 'out' contract
+ *      false   didn't find one
+ */
+bool FuncDeclaration::needsFensure(FuncDeclaration *fd)
 {
-    TypeFunction *f;
-    AggregateDeclaration *ad;
-    InterfaceDeclaration *id;
-
-    if (semanticRun != PASSinit && isFuncLiteralDeclaration())
-    {
-        /* Member functions that have return types that are
-         * forward references can have semantic() run more than
-         * once on them.
-         * See test\interface2.d, test20
-         */
-        return;
-    }
-
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    assert(semanticRun <= PASSsemantic);
-    semanticRun = PASSsemantic;
-
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    if (!sc || errors)
-        return;
-
-    parent = sc->parent;
-    Dsymbol *parent = toParent();
-
-    foverrides.setDim(0);       // reset in case semantic() is being retried for this function
-
-    storage_class |= sc->stc & ~STCref;
-    ad = isThis();
-    // Don't nest structs b/c of generated methods which should not access the outer scopes.
-    // https://issues.dlang.org/show_bug.cgi?id=16627
-    if (ad && !generated)
-    {
-        storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
-        ad->makeNested();
-    }
-    if (sc->func)
-        storage_class |= sc->func->storage_class & STCdisable;
-    // Remove prefix storage classes silently.
-    if ((storage_class & STC_TYPECTOR) && !(ad || isNested()))
-        storage_class &= ~STC_TYPECTOR;
-
-    //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
-
-    FuncLiteralDeclaration *fld = isFuncLiteralDeclaration();
-    if (fld && fld->treq)
-    {
-        Type *treq = fld->treq;
-        assert(treq->nextOf()->ty == Tfunction);
-        if (treq->ty == Tdelegate)
-            fld->tok = TOKdelegate;
-        else if (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction)
-            fld->tok = TOKfunction;
-        else
-            assert(0);
-        linkage = treq->nextOf()->toTypeFunction()->linkage;
-    }
-    else
-        linkage = sc->linkage;
-    inlining = sc->inlining;
-    protection = sc->protection;
-    userAttribDecl = sc->userAttribDecl;
-
-    if (!originalType)
-        originalType = type->syntaxCopy();
-    if (type->ty != Tfunction)
-    {
-        if (type->ty != Terror)
-        {
-            error("%s must be a function instead of %s", toChars(), type->toChars());
-            type = Type::terror;
-        }
-        errors = true;
-        return;
-    }
-    if (!type->deco)
-    {
-        sc = sc->push();
-        sc->stc |= storage_class & (STCdisable | STCdeprecated);  // forward to function type
-        TypeFunction *tf = type->toTypeFunction();
-
-        if (sc->func)
-        {
-            /* If the nesting parent is pure without inference,
-             * then this function defaults to pure too.
-             *
-             *  auto foo() pure {
-             *    auto bar() {}     // become a weak purity funciton
-             *    class C {         // nested class
-             *      auto baz() {}   // become a weak purity funciton
-             *    }
-             *
-             *    static auto boo() {}   // typed as impure
-             *    // Even though, boo cannot call any impure functions.
-             *    // See also Expression::checkPurity().
-             *  }
-             */
-            if (tf->purity == PUREimpure && (isNested() || isThis()))
-            {
-                FuncDeclaration *fd = NULL;
-                for (Dsymbol *p = toParent2(); p; p = p->toParent2())
-                {
-                    if (AggregateDeclaration *adx = p->isAggregateDeclaration())
-                    {
-                        if (adx->isNested())
-                            continue;
-                        break;
-                    }
-                    if ((fd = p->isFuncDeclaration()) != NULL)
-                        break;
-                }
-
-                /* If the parent's purity is inferred, then this function's purity needs
-                 * to be inferred first.
-                 */
-                if (fd && fd->isPureBypassingInference() >= PUREweak &&
-                    !isInstantiated())
-                {
-                    tf->purity = PUREfwdref;            // default to pure
-                }
-            }
-        }
-
-        if (tf->isref)      sc->stc |= STCref;
-        if (tf->isscope)    sc->stc |= STCscope;
-        if (tf->isnothrow)  sc->stc |= STCnothrow;
-        if (tf->isnogc)     sc->stc |= STCnogc;
-        if (tf->isproperty) sc->stc |= STCproperty;
-        if (tf->purity == PUREfwdref)   sc->stc |= STCpure;
-        if (tf->trust != TRUSTdefault)
-            sc->stc &= ~(STCsafe | STCsystem | STCtrusted);
-        if (tf->trust == TRUSTsafe)     sc->stc |= STCsafe;
-        if (tf->trust == TRUSTsystem)   sc->stc |= STCsystem;
-        if (tf->trust == TRUSTtrusted)  sc->stc |= STCtrusted;
-
-        if (isCtorDeclaration())
-        {
-            sc->flags |= SCOPEctor;
-
-            Type *tret = ad->handleType();
-            assert(tret);
-            tret = tret->addStorageClass(storage_class | sc->stc);
-            tret = tret->addMod(type->mod);
-            tf->next = tret;
-
-            if (ad->isStructDeclaration())
-                sc->stc |= STCref;
-        }
-
-        // 'return' on a non-static class member function implies 'scope' as well
-        if (ad && ad->isClassDeclaration() && (tf->isreturn || sc->stc & STCreturn) && !(sc->stc & STCstatic))
-            sc->stc |= STCscope;
-
-        // If 'this' has no pointers, remove 'scope' as it has no meaning
-        if (sc->stc & STCscope && ad && ad->isStructDeclaration() && !ad->type->hasPointers())
-        {
-            sc->stc &= ~STCscope;
-            tf->isscope = false;
-        }
-
-        sc->linkage = linkage;
-
-        if (!tf->isNaked() && !(isThis() || isNested()))
-        {
-            OutBuffer buf;
-            MODtoBuffer(&buf, tf->mod);
-            error("without 'this' cannot be %s", buf.peekChars());
-            tf->mod = 0;    // remove qualifiers
-        }
-
-        /* Apply const, immutable, wild and shared storage class
-         * to the function type. Do this before type semantic.
-         */
-        StorageClass stc = storage_class;
-        if (type->isImmutable())
-            stc |= STCimmutable;
-        if (type->isConst())
-            stc |= STCconst;
-        if (type->isShared() || storage_class & STCsynchronized)
-            stc |= STCshared;
-        if (type->isWild())
-            stc |= STCwild;
-        switch (stc & STC_TYPECTOR)
-        {
-            case STCimmutable:
-            case STCimmutable | STCconst:
-            case STCimmutable | STCwild:
-            case STCimmutable | STCwild | STCconst:
-            case STCimmutable | STCshared:
-            case STCimmutable | STCshared | STCconst:
-            case STCimmutable | STCshared | STCwild:
-            case STCimmutable | STCshared | STCwild | STCconst:
-                // Don't use immutableOf(), as that will do a merge()
-                type = type->makeImmutable();
-                break;
-
-            case STCconst:
-                type = type->makeConst();
-                break;
-
-            case STCwild:
-                type = type->makeWild();
-                break;
-
-            case STCwild | STCconst:
-                type = type->makeWildConst();
-                break;
-
-            case STCshared:
-                type = type->makeShared();
-                break;
-
-            case STCshared | STCconst:
-                type = type->makeSharedConst();
-                break;
-
-            case STCshared | STCwild:
-                type = type->makeSharedWild();
-                break;
-
-            case STCshared | STCwild | STCconst:
-                type = type->makeSharedWildConst();
-                break;
-
-            case 0:
-                break;
-
-            default:
-                assert(0);
-        }
+    if (fd->fensures)
+        return true;
 
-        type = type->semantic(loc, sc);
-        sc = sc->pop();
-    }
-    if (type->ty != Tfunction)
-    {
-        if (type->ty != Terror)
-        {
-            error("%s must be a function instead of %s", toChars(), type->toChars());
-            type = Type::terror;
-        }
-        errors = true;
-        return;
-    }
-    else
+    for (size_t i = 0; i < fd->foverrides.length; i++)
     {
-        // Merge back function attributes into 'originalType'.
-        // It's used for mangling, ddoc, and json output.
-        TypeFunction *tfo = originalType->toTypeFunction();
-        TypeFunction *tfx = type->toTypeFunction();
-        tfo->mod        = tfx->mod;
-        tfo->isscope    = tfx->isscope;
-        tfo->isscopeinferred = tfx->isscopeinferred;
-        tfo->isref      = tfx->isref;
-        tfo->isnothrow  = tfx->isnothrow;
-        tfo->isnogc     = tfx->isnogc;
-        tfo->isproperty = tfx->isproperty;
-        tfo->purity     = tfx->purity;
-        tfo->trust      = tfx->trust;
-
-        storage_class &= ~(STC_TYPECTOR | STC_FUNCATTR);
-    }
-
-    f = (TypeFunction *)type;
+        FuncDeclaration *fdv = fd->foverrides[i];
 
-    if ((storage_class & STCauto) && !f->isref && !inferRetType)
-        error("storage class 'auto' has no effect if return type is not inferred");
-    /* Functions can only be 'scope' if they have a 'this'
-     */
-    if (f->isscope && !isNested() && !ad)
-    {
-        error("functions cannot be scope");
-    }
+        if (fdv->fensure)
+            return true;
 
-    if (f->isreturn && !needThis() && !isNested())
-    {
-        /* Non-static nested functions have a hidden 'this' pointer to which
-         * the 'return' applies
-         */
-        error("static member has no 'this' to which 'return' can apply");
+        if (needsFensure(fdv))
+            return true;
     }
+    return false;
+}
 
-    if (isAbstract() && !isVirtual())
-    {
-        const char *sfunc;
-        if (isStatic())
-            sfunc = "static";
-        else if (protection.kind == Prot::private_ || protection.kind == Prot::package_)
-            sfunc = protectionToChars(protection.kind);
-        else
-            sfunc = "non-virtual";
-        error("%s functions cannot be abstract", sfunc);
-    }
+/****************************************************
+ * Check whether result variable can be built.
+ * Returns:
+ *     `true` if the function has a return type that
+ *     is different from `void`.
+ */
+static bool canBuildResultVar(FuncDeclaration *fd)
+{
+    TypeFunction *f = (TypeFunction *)fd->type;
+    return f && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid;
+}
 
-    if (isOverride() && !isVirtual())
-    {
-        Prot::Kind kind = prot().kind;
-        if ((kind == Prot::private_ || kind == Prot::package_) && isMember())
-            error("%s method is not virtual and cannot override", protectionToChars(kind));
-        else
-            error("cannot override a non-virtual function");
-    }
-
-    if (isAbstract() && isFinalFunc())
-        error("cannot be both final and abstract");
-
-    id = parent->isInterfaceDeclaration();
-    if (id)
-    {
-        storage_class |= STCabstract;
-
-        if (isCtorDeclaration() ||
-            isPostBlitDeclaration() ||
-            isDtorDeclaration() ||
-            isInvariantDeclaration() ||
-            isNewDeclaration() || isDelete())
-            error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface %s", id->toChars());
-        if (fbody && isVirtual())
-            error("function body only allowed in final functions in interface %s", id->toChars());
-    }
-
-    if (UnionDeclaration *ud = parent->isUnionDeclaration())
-    {
-        if (isPostBlitDeclaration() ||
-            isDtorDeclaration() ||
-            isInvariantDeclaration())
-            error("destructors, postblits and invariants are not allowed in union %s", ud->toChars());
-    }
-
-    if (parent->isStructDeclaration())
-    {
-        if (isCtorDeclaration())
-        {
-            goto Ldone;
-        }
-    }
-
-    if (ClassDeclaration *cd = parent->isClassDeclaration())
-    {
-        if (isCtorDeclaration())
-        {
-            goto Ldone;
-        }
-
-        if (storage_class & STCabstract)
-            cd->isabstract = ABSyes;
-
-        // if static function, do not put in vtbl[]
-        if (!isVirtual())
-        {
-            //printf("\tnot virtual\n");
-            goto Ldone;
-        }
-        // Suppress further errors if the return type is an error
-        if (type->nextOf() == Type::terror)
-            goto Ldone;
-
-        bool may_override = false;
-        for (size_t i = 0; i < cd->baseclasses->length; i++)
-        {
-            BaseClass *b = (*cd->baseclasses)[i];
-            ClassDeclaration *cbd = b->type->toBasetype()->isClassHandle();
-            if (!cbd)
-                continue;
-            for (size_t j = 0; j < cbd->vtbl.length; j++)
-            {
-                FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration();
-                if (!f2 || f2->ident != ident)
-                    continue;
-                if (cbd->parent && cbd->parent->isTemplateInstance())
-                {
-                    if (!f2->functionSemantic())
-                        goto Ldone;
-                }
-                may_override = true;
-            }
-        }
-        if (may_override && type->nextOf() == NULL)
-        {
-            /* If same name function exists in base class but 'this' is auto return,
-             * cannot find index of base class's vtbl[] to override.
-             */
-            error("return type inference is not supported if may override base class function");
-        }
-
-        /* Find index of existing function in base class's vtbl[] to override
-         * (the index will be the same as in cd's current vtbl[])
-         */
-        int vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.length)
-                               : -1;
-
-        bool doesoverride = false;
-        switch (vi)
-        {
-            case -1:
-        Lintro:
-                /* Didn't find one, so
-                 * This is an 'introducing' function which gets a new
-                 * slot in the vtbl[].
-                 */
-
-                // Verify this doesn't override previous final function
-                if (cd->baseClass)
-                {
-                    Dsymbol *s = cd->baseClass->search(loc, ident);
-                    if (s)
-                    {
-                        FuncDeclaration *f2 = s->isFuncDeclaration();
-                        if (f2)
-                        {
-                            f2 = f2->overloadExactMatch(type);
-                            if (f2 && f2->isFinalFunc() && f2->prot().kind != Prot::private_)
-                                error("cannot override final function %s", f2->toPrettyChars());
-                        }
-                    }
-                }
-
-                /* These quirky conditions mimic what VC++ appears to do
-                 */
-                if (global.params.mscoff && cd->isCPPclass() &&
-                    cd->baseClass && cd->baseClass->vtbl.length)
-                {
-                    /* if overriding an interface function, then this is not
-                     * introducing and don't put it in the class vtbl[]
-                     */
-                    interfaceVirtual = overrideInterface();
-                    if (interfaceVirtual)
-                    {
-                        //printf("\tinterface function %s\n", toChars());
-                        cd->vtblFinal.push(this);
-                        goto Linterfaces;
-                    }
-                }
-
-                if (isFinalFunc())
-                {
-                    // Don't check here, as it may override an interface function
-                    //if (isOverride())
-                        //error("is marked as override, but does not override any function");
-                    cd->vtblFinal.push(this);
-                }
-                else
-                {
-                    //printf("\tintroducing function %s\n", toChars());
-                    introducing = 1;
-                    if (cd->isCPPclass() && target.cpp.reverseOverloads)
-                    {
-                        // with dmc, overloaded functions are grouped and in reverse order
-                        vtblIndex = (int)cd->vtbl.length;
-                        for (int i = 0; i < (int)cd->vtbl.length; i++)
-                        {
-                            if (cd->vtbl[i]->ident == ident && cd->vtbl[i]->parent == parent)
-                            {
-                                vtblIndex = (int)i;
-                                break;
-                            }
-                        }
-                        // shift all existing functions back
-                        for (int i = (int)cd->vtbl.length; i > vtblIndex; i--)
-                        {
-                            FuncDeclaration *fd = cd->vtbl[i-1]->isFuncDeclaration();
-                            assert(fd);
-                            fd->vtblIndex++;
-                        }
-                        cd->vtbl.insert(vtblIndex, this);
-                    }
-                    else
-                    {
-                        // Append to end of vtbl[]
-                        vi = (int)cd->vtbl.length;
-                        cd->vtbl.push(this);
-                        vtblIndex = vi;
-                    }
-                }
-                break;
-
-            case -2:
-                // can't determine because of forward references
-                errors = true;
-                return;
-
-            default:
-            {
-                FuncDeclaration *fdv = cd->baseClass->vtbl[vi]->isFuncDeclaration();
-                FuncDeclaration *fdc = cd->vtbl[vi]->isFuncDeclaration();
-                // This function is covariant with fdv
-
-                if (fdc == this)
-                {
-                    doesoverride = true;
-                    break;
-                }
-
-                if (fdc->toParent() == parent)
-                {
-                    //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc  = %p %s %s @ [%s]\n\tfdv  = %p %s %s @ [%s]\n",
-                    //        vi, this, this->toChars(), this->type->toChars(), this->loc.toChars(),
-                    //            fdc,  fdc ->toChars(), fdc ->type->toChars(), fdc ->loc.toChars(),
-                    //            fdv,  fdv ->toChars(), fdv ->type->toChars(), fdv ->loc.toChars());
-
-                    // fdc overrides fdv exactly, then this introduces new function.
-                    if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod)
-                        goto Lintro;
-                }
-
-                // This function overrides fdv
-                if (fdv->isFinalFunc())
-                    error("cannot override final function %s", fdv->toPrettyChars());
-
-                if (!isOverride())
-                {
-                    if (fdv->isFuture())
-                    {
-                        ::deprecation(loc, "@__future base class method %s is being overridden by %s; rename the latter",
-                            fdv->toPrettyChars(), toPrettyChars());
-                        // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
-                        goto Lintro;
-                    }
-                    else
-                    {
-                        int vi2 = findVtblIndex(&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.length, false);
-                        if (vi2 < 0)
-                            // https://issues.dlang.org/show_bug.cgi?id=17349
-                            ::deprecation(loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
-                                fdv->toPrettyChars(), toPrettyChars());
-                        else
-                            ::error(loc, "implicitly overriding base class method %s with %s deprecated; add 'override' attribute",
-                                fdv->toPrettyChars(), toPrettyChars());
-                    }
-                }
-
-                doesoverride = true;
-                if (fdc->toParent() == parent)
-                {
-                    // If both are mixins, or both are not, then error.
-                    // If either is not, the one that is not overrides the other.
-                    bool thismixin = this->parent->isClassDeclaration() != NULL;
-                    bool fdcmixin = fdc->parent->isClassDeclaration() != NULL;
-                    if (thismixin == fdcmixin)
-                    {
-                        error("multiple overrides of same function");
-                    }
-                    else if (!thismixin)    // fdc overrides fdv
-                    {
-                        // this doesn't override any function
-                        break;
-                    }
-                }
-                cd->vtbl[vi] = this;
-                vtblIndex = vi;
-
-                /* Remember which functions this overrides
-                 */
-                foverrides.push(fdv);
-
-                /* This works by whenever this function is called,
-                 * it actually returns tintro, which gets dynamically
-                 * cast to type. But we know that tintro is a base
-                 * of type, so we could optimize it by not doing a
-                 * dynamic cast, but just subtracting the isBaseOf()
-                 * offset if the value is != null.
-                 */
-
-                if (fdv->tintro)
-                    tintro = fdv->tintro;
-                else if (!type->equals(fdv->type))
-                {
-                    /* Only need to have a tintro if the vptr
-                     * offsets differ
-                     */
-                    int offset;
-                    if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
-                    {
-                        tintro = fdv->type;
-                    }
-                }
-                break;
-            }
-        }
-
-        /* Go through all the interface bases.
-         * If this function is covariant with any members of those interface
-         * functions, set the tintro.
-         */
-    Linterfaces:
-        for (size_t i = 0; i < cd->interfaces.length; i++)
-        {
-            BaseClass *b = cd->interfaces.ptr[i];
-            vi = findVtblIndex((Dsymbols *)&b->sym->vtbl, (int)b->sym->vtbl.length);
-            switch (vi)
-            {
-                case -1:
-                    break;
-
-                case -2:
-                    // can't determine because of forward references
-                    errors = true;
-                    return;
-
-                default:
-                {
-                    FuncDeclaration *fdv = (FuncDeclaration *)b->sym->vtbl[vi];
-                    Type *ti = NULL;
-
-                    /* Remember which functions this overrides
-                     */
-                    foverrides.push(fdv);
-
-                    /* Should we really require 'override' when implementing
-                     * an interface function?
-                     */
-                    //if (!isOverride())
-                        //warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
-
-                    if (fdv->tintro)
-                        ti = fdv->tintro;
-                    else if (!type->equals(fdv->type))
-                    {
-                        /* Only need to have a tintro if the vptr
-                         * offsets differ
-                         */
-                        int offset;
-                        if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
-                        {
-                            ti = fdv->type;
-                        }
-                    }
-                    if (ti)
-                    {
-                        if (tintro)
-                        {
-                            if (!tintro->nextOf()->equals(ti->nextOf()) &&
-                                !tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
-                                !ti->nextOf()->isBaseOf(tintro->nextOf(), NULL))
-                            {
-                                error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
-                            }
-                        }
-                        tintro = ti;
-                    }
-                    goto L2;
-                }
-            }
-        }
-
-        if (!doesoverride && isOverride() && (type->nextOf() || !may_override))
-        {
-            BaseClass *bc = NULL;
-            Dsymbol *s = NULL;
-            for (size_t i = 0; i < cd->baseclasses->length; i++)
-            {
-                bc = (*cd->baseclasses)[i];
-                s = bc->sym->search_correct(ident);
-                if (s) break;
-            }
-
-            if (s)
-                error("does not override any function, did you mean to override '%s%s'?",
-                    bc->sym->isCPPclass() ? "extern (C++) " : "", s->toPrettyChars());
-            else
-                error("does not override any function");
-        }
-
-    L2: ;
-
-        /* Go through all the interface bases.
-         * Disallow overriding any final functions in the interface(s).
-         */
-        for (size_t i = 0; i < cd->interfaces.length; i++)
-        {
-            BaseClass *b = cd->interfaces.ptr[i];
-            if (b->sym)
-            {
-                Dsymbol *s = search_function(b->sym, ident);
-                if (s)
-                {
-                    FuncDeclaration *f2 = s->isFuncDeclaration();
-                    if (f2)
-                    {
-                        f2 = f2->overloadExactMatch(type);
-                        if (f2 && f2->isFinalFunc() && f2->prot().kind != Prot::private_)
-                            error("cannot override final function %s.%s", b->sym->toChars(), f2->toPrettyChars());
-                    }
-                }
-            }
-        }
-
-        if (isOverride())
-        {
-            if (storage_class & STCdisable)
-                deprecation("overridden functions cannot be annotated @disable");
-            if (isDeprecated())
-                deprecation("deprecated functions cannot be annotated @disable");
-        }
-    }
-    else if (isOverride() && !parent->isTemplateInstance())
-        error("override only applies to class member functions");
-
-    // Reflect this->type to f because it could be changed by findVtblIndex
-    f = type->toTypeFunction();
-
-Ldone:
-    /* Contracts can only appear without a body when they are virtual interface functions
-     */
-    if (!fbody && !allowsContractWithoutBody(this))
-        error("in and out contracts can only appear without a body when they are virtual interface functions or abstract");
-
-    /* Do not allow template instances to add virtual functions
-     * to a class.
-     */
-    if (isVirtual())
-    {
-        TemplateInstance *ti = parent->isTemplateInstance();
-        if (ti)
-        {
-            // Take care of nested templates
-            while (1)
-            {
-                TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
-                if (!ti2)
-                    break;
-                ti = ti2;
-            }
-
-            // If it's a member template
-            ClassDeclaration *cd = ti->tempdecl->isClassMember();
-            if (cd)
-            {
-                error("cannot use template to add virtual function to class '%s'", cd->toChars());
-            }
-        }
-    }
-
-    if (isMain())
-        checkDmain();       // Check main() parameters and return type
-
-    /* Purity and safety can be inferred for some functions by examining
-     * the function body.
-     */
-    if (canInferAttributes(this, sc))
-        initInferAttributes(this);
-
-    Module::dprogress++;
-    semanticRun = PASSsemanticdone;
-
-    /* Save scope for possible later use (if we need the
-     * function internals)
-     */
-    _scope = sc->copy();
-    _scope->setNoFree();
-
-    static bool printedMain = false;  // semantic might run more than once
-    if (global.params.verbose && !printedMain)
-    {
-        const char *type = isMain() ? "main" : isWinMain() ? "winmain" : isDllMain() ? "dllmain" : (const char *)NULL;
-        Module *mod = sc->_module;
-
-        if (type && mod)
-        {
-            printedMain = true;
-            const char *name = mod->srcfile->toChars();
-            const char *path = FileName::searchPath(global.path, name, true);
-            message("entry     %-10s\t%s", type, path ? path : name);
-        }
-    }
-
-    if (fbody && isMain() && sc->_module->isRoot())
-        Compiler::genCmain(sc);
-
-    assert(type->ty != Terror || errors);
-
-    // semantic for parameters' UDAs
-    const size_t nparams = f->parameterList.length();
-    for (size_t i = 0; i < nparams; i++)
-    {
-        Parameter *param = f->parameterList[i];
-        if (param && param->userAttribDecl)
-            param->userAttribDecl->semantic(sc);
-    }
-}
-
-void FuncDeclaration::semantic2(Scope *sc)
-{
-    if (semanticRun >= PASSsemantic2done)
-        return;
-    assert(semanticRun <= PASSsemantic2);
-    semanticRun = PASSsemantic2;
-
-    objc()->setSelector(this, sc);
-    objc()->validateSelector(this);
-
-    if (parent->isClassDeclaration())
-    {
-        objc()->checkLinkage(this);
-    }
-    if (!type || type->ty != Tfunction)
-        return;
-    TypeFunction *f = type->toTypeFunction();
-    const size_t nparams = f->parameterList.length();
-    // semantic for parameters' UDAs
-    for (size_t i = 0; i < nparams; i++)
-    {
-        Parameter *param = f->parameterList[i];
-        if (param && param->userAttribDecl)
-            param->userAttribDecl->semantic2(sc);
-    }
-}
-
-/****************************************************
- * Determine whether an 'out' contract is declared inside
- * the given function or any of its overrides.
- * Params:
- *      fd = the function to search
- * Returns:
- *      true    found an 'out' contract
- *      false   didn't find one
- */
-static bool needsFensure(FuncDeclaration *fd)
-{
-    if (fd->fensures)
-        return true;
-
-    for (size_t i = 0; i < fd->foverrides.length; i++)
-    {
-        FuncDeclaration *fdv = fd->foverrides[i];
-
-        if (fdv->fensure)
-            return true;
-
-        if (needsFensure(fdv))
-            return true;
-    }
-    return false;
-}
-
-/****************************************************
- * Check whether result variable can be built.
- * Returns:
- *     `true` if the function has a return type that
- *     is different from `void`.
- */
-static bool canBuildResultVar(FuncDeclaration *fd)
-{
-    TypeFunction *f = (TypeFunction *)fd->type;
-    return f && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid;
-}
-
-/****************************************************
- * Rewrite contracts as statements.
- * Params:
- *      fdx = the function to rewrite contracts for
- */
-static void buildEnsureRequire(FuncDeclaration *fdx)
-{
-    if (fdx->frequires)
+/****************************************************
+ * Rewrite contracts as statements.
+ */
+void FuncDeclaration::buildEnsureRequire()
+{
+    if (frequires)
     {
         /*   in { statements1... }
          *   in { statements2... }
          *   ...
          * becomes:
-         *   in { { statements1... } { statements2... } ... }
-         */
-        assert(fdx->frequires->length);
-        Loc loc = (*fdx->frequires)[0]->loc;
-        Statements *s = new Statements;
-        for (size_t i = 0; i < fdx->frequires->length; i++)
-        {
-            Statement *r = (*fdx->frequires)[i];
-            s->push(new ScopeStatement(r->loc, r, r->loc));
-        }
-        fdx->frequire = new CompoundStatement(loc, s);
-    }
-
-    if (fdx->fensures)
-    {
-        /*   out(id1) { statements1... }
-         *   out(id2) { statements2... }
-         *   ...
-         * becomes:
-         *   out(__result) { { ref id1 = __result; { statements1... } }
-         *                   { ref id2 = __result; { statements2... } } ... }
-         */
-        assert(fdx->fensures->length);
-        Loc loc = (*fdx->fensures)[0].ensure->loc;
-        Statements *s = new Statements;
-        for (size_t i = 0; i < fdx->fensures->length; i++)
-        {
-            Ensure r = (*fdx->fensures)[i];
-            if (r.id && canBuildResultVar(fdx))
-            {
-                Loc rloc = r.ensure->loc;
-                IdentifierExp *resultId = new IdentifierExp(rloc, Id::result);
-                ExpInitializer *init = new ExpInitializer(rloc, resultId);
-                StorageClass stc = STCref | STCtemp | STCresult;
-                VarDeclaration *decl = new VarDeclaration(rloc, NULL, r.id, init);
-                decl->storage_class = stc;
-                ExpStatement *sdecl = new ExpStatement(rloc, decl);
-                s->push(new ScopeStatement(rloc, new CompoundStatement(rloc, sdecl, r.ensure), rloc));
-            }
-            else
-            {
-                s->push(r.ensure);
-            }
-        }
-        fdx->fensure = new CompoundStatement(loc, s);
-    }
-
-    if (!fdx->isVirtual())
-        return;
-
-    /* Rewrite contracts as nested functions, then call them. Doing it as nested
-     * functions means that overriding functions can call them.
-     */
-    TypeFunction *f = (TypeFunction *)fdx->type;
-
-    if (fdx->frequire)
-    {
-        /*   in { ... }
-         * becomes:
-         *   void __require() { ... }
-         *   __require();
-         */
-        Loc loc = fdx->frequire->loc;
-        TypeFunction *tf = new TypeFunction(ParameterList(), Type::tvoid, LINKd);
-        tf->isnothrow = f->isnothrow;
-        tf->isnogc = f->isnogc;
-        tf->purity = f->purity;
-        tf->trust = f->trust;
-        FuncDeclaration *fd = new FuncDeclaration(loc, loc,
-                                                  Id::require, STCundefined, tf);
-        fd->fbody = fdx->frequire;
-        Statement *s1 = new ExpStatement(loc, fd);
-        Expression *e = new CallExp(loc, new VarExp(loc, fd, false), (Expressions *)NULL);
-        Statement *s2 = new ExpStatement(loc, e);
-        fdx->frequire = new CompoundStatement(loc, s1, s2);
-        fdx->fdrequire = fd;
-    }
-
-    if (fdx->fensure)
-    {
-        /*   out (result) { ... }
-         * becomes:
-         *   void __ensure(ref tret result) { ... }
-         *   __ensure(result);
-         */
-        Loc loc = fdx->fensure->loc;
-        Parameters *fparams = new Parameters();
-        Parameter *p = NULL;
-        if (canBuildResultVar(fdx))
-        {
-            p = new Parameter(STCref | STCconst, f->nextOf(), Id::result, NULL, NULL);
-            fparams->push(p);
-        }
-        TypeFunction *tf = new TypeFunction(ParameterList(fparams), Type::tvoid, LINKd);
-        tf->isnothrow = f->isnothrow;
-        tf->isnogc = f->isnogc;
-        tf->purity = f->purity;
-        tf->trust = f->trust;
-        FuncDeclaration *fd = new FuncDeclaration(loc, loc,
-                                                  Id::ensure, STCundefined, tf);
-        fd->fbody = fdx->fensure;
-        Statement *s1 = new ExpStatement(loc, fd);
-        Expression *eresult = NULL;
-        if (canBuildResultVar(fdx))
-            eresult = new IdentifierExp(loc, Id::result);
-        Expression *e = new CallExp(loc, new VarExp(loc, fd, false), eresult);
-        Statement *s2 = new ExpStatement(loc, e);
-        fdx->fensure = new CompoundStatement(loc, s1, s2);
-        fdx->fdensure = fd;
-    }
-}
-
-/* Determine if function should add `return 0;`
- */
-static bool addReturn0(FuncDeclaration *funcdecl)
-{
-    TypeFunction *f = (TypeFunction *)funcdecl->type;
-
-    return f->next->ty == Tvoid &&
-        (funcdecl->isMain() || (global.params.betterC && funcdecl->isCMain()));
-}
-
-// Do the semantic analysis on the internals of the function.
-
-void FuncDeclaration::semantic3(Scope *sc)
-{
-    VarDeclaration *_arguments = NULL;
-
-    if (!parent)
-    {
-        if (global.errors)
-            return;
-        //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
-        assert(0);
-    }
-    if (errors || isError(parent))
-    {
-        errors = true;
-        return;
-    }
-    //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars());
-    //fflush(stdout);
-    //printf("storage class = x%x %x\n", sc->stc, storage_class);
-    //{ static int x; if (++x == 2) *(char*)0=0; }
-    //printf("\tlinkage = %d\n", sc->linkage);
-
-    if (ident == Id::assign && !inuse)
-    {
-        if (storage_class & STCinference)
-        {
-            /* Bugzilla 15044: For generated opAssign function, any errors
-             * from its body need to be gagged.
-             */
-            unsigned oldErrors = global.startGagging();
-            ++inuse;
-            semantic3(sc);
-            --inuse;
-            if (global.endGagging(oldErrors))   // if errors happened
-            {
-                // Disable generated opAssign, because some members forbid identity assignment.
-                storage_class |= STCdisable;
-                fbody = NULL;   // remove fbody which contains the error
-                semantic3Errors = false;
-            }
-            return;
-        }
-    }
-
-    //printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract));
-    if (semanticRun >= PASSsemantic3)
-        return;
-    semanticRun = PASSsemantic3;
-    semantic3Errors = false;
-
-    if (!type || type->ty != Tfunction)
-        return;
-    TypeFunction *f = (TypeFunction *)type;
-    if (!inferRetType && f->next->ty == Terror)
-        return;
-
-    if (!fbody && inferRetType && !f->next)
-    {
-        error("has no function body with return type inference");
-        return;
-    }
-
-    unsigned oldErrors = global.errors;
-
-    if (frequires)
-    {
-        for (size_t i = 0; i < foverrides.length; i++)
-        {
-            FuncDeclaration *fdv = foverrides[i];
-
-            if (fdv->fbody && !fdv->frequires)
-            {
-                error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars());
-                break;
-            }
-        }
-    }
-
-    // Remember whether we need to generate an 'out' contract.
-    const bool needEnsure = needsFensure(this);
-
-    if (fbody || frequires || needEnsure)
-    {
-        /* Symbol table into which we place parameters and nested functions,
-         * solely to diagnose name collisions.
-         */
-        localsymtab = new DsymbolTable();
-
-        // Establish function scope
-        ScopeDsymbol *ss = new ScopeDsymbol();
-        // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
-        for (Scope *scx = sc; ; scx = scx->enclosing)
-        {
-            if (scx->scopesym)
-            {
-                ss->parent = scx->scopesym;
-                break;
-            }
-        }
-        ss->loc = loc;
-        ss->endlinnum = endloc.linnum;
-        Scope *sc2 = sc->push(ss);
-        sc2->func = this;
-        sc2->parent = this;
-        sc2->callSuper = 0;
-        sc2->sbreak = NULL;
-        sc2->scontinue = NULL;
-        sc2->sw = NULL;
-        sc2->fes = fes;
-        sc2->linkage = LINKd;
-        sc2->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCabstract |
-                        STCdeprecated | STCoverride |
-                        STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | STCreturn |
-                        STCproperty | STCnothrow | STCpure | STCsafe | STCtrusted | STCsystem);
-        sc2->protection = Prot(Prot::public_);
-        sc2->explicitProtection = 0;
-        sc2->aligndecl = NULL;
-        if (this->ident != Id::require && this->ident != Id::ensure)
-            sc2->flags = sc->flags & ~SCOPEcontract;
-        sc2->flags &= ~SCOPEcompile;
-        sc2->tf = NULL;
-        sc2->os = NULL;
-        sc2->noctor = 0;
-        sc2->userAttribDecl = NULL;
-        if (sc2->intypeof == 1) sc2->intypeof = 2;
-        sc2->fieldinit = NULL;
-        sc2->fieldinit_dim = 0;
-
-        /* Note: When a lambda is defined immediately under aggregate member
-         * scope, it should be contextless due to prevent interior pointers.
-         * e.g.
-         *      // dg points 'this' - it's interior pointer
-         *      class C { int x; void delegate() dg = (){ this.x = 1; }; }
-         *
-         * However, lambdas could be used inside typeof, in order to check
-         * some expressions varidity at compile time. For such case the lambda
-         * body can access aggregate instance members.
-         * e.g.
-         *      class C { int x; static assert(is(typeof({ this.x = 1; }))); }
-         *
-         * To properly accept it, mark these lambdas as member functions.
-         */
-        if (FuncLiteralDeclaration *fld = isFuncLiteralDeclaration())
-        {
-            if (AggregateDeclaration *ad = isMember2())
-            {
-                if (!sc->intypeof)
-                {
-                    if (fld->tok == TOKdelegate)
-                        error("cannot be %s members", ad->kind());
-                    else
-                        fld->tok = TOKfunction;
-                }
-                else
-                {
-                    if (fld->tok != TOKfunction)
-                        fld->tok = TOKdelegate;
-                }
-            }
-        }
-
-        // Declare 'this'
-        AggregateDeclaration *ad = isThis();
-        vthis = declareThis(sc2, ad);
-        //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis);
-        //if (vthis) printf("\tvthis->type = %s\n", vthis->type->toChars());
-
-        // Declare hidden variable _arguments[] and _argptr
-        if (f->parameterList.varargs == VARARGvariadic)
-        {
-            if (f->linkage == LINKd)
-            {
-                // Variadic arguments depend on Typeinfo being defined
-                if (!global.params.useTypeInfo || !Type::dtypeinfo || !Type::typeinfotypelist)
-                {
-                    if (!global.params.useTypeInfo)
-                        error("D-style variadic functions cannot be used with -betterC");
-                    else if (!Type::typeinfotypelist)
-                        error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
-                    else
-                        error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
-                    fatal();
-                }
-
-                // Declare _arguments[]
-                v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
-                v_arguments->storage_class |= STCtemp | STCparameter;
-                v_arguments->semantic(sc2);
-                sc2->insert(v_arguments);
-                v_arguments->parent = this;
-
-                //Type *t = Type::typeinfo->type->constOf()->arrayOf();
-                Type *t = Type::dtypeinfo->type->arrayOf();
-                _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
-                _arguments->storage_class |= STCtemp;
-                _arguments->semantic(sc2);
-                sc2->insert(_arguments);
-                _arguments->parent = this;
-            }
-            if (f->linkage == LINKd || f->parameterList.length())
-            {
-                // Declare _argptr
-                Type *t = target.va_listType(loc, sc);
-                v_argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
-                v_argptr->storage_class |= STCtemp;
-                v_argptr->semantic(sc2);
-                sc2->insert(v_argptr);
-                v_argptr->parent = this;
-            }
-        }
-
-        /* Declare all the function parameters as variables
-         * and install them in parameters[]
-         */
-        size_t nparams = f->parameterList.length();
-        if (nparams)
-        {
-            /* parameters[] has all the tuples removed, as the back end
-             * doesn't know about tuples
-             */
-            parameters = new VarDeclarations();
-            parameters->reserve(nparams);
-            for (size_t i = 0; i < nparams; i++)
-            {
-                Parameter *fparam = f->parameterList[i];
-                Identifier *id = fparam->ident;
-                StorageClass stc = 0;
-                if (!id)
-                {
-                    /* Generate identifier for un-named parameter,
-                     * because we need it later on.
-                     */
-                    fparam->ident = id = Identifier::generateId("_param_", i);
-                    stc |= STCtemp;
-                }
-                Type *vtype = fparam->type;
-                VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
-                //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
-                stc |= STCparameter;
-                if (f->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
-                    stc |= STCvariadic;
-                if (flags & FUNCFLAGinferScope && !(fparam->storageClass & STCscope))
-                    stc |= STCmaybescope;
-                stc |= fparam->storageClass & (STCin | STCout | STCref | STCreturn | STCscope | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
-                v->storage_class = stc;
-                v->semantic(sc2);
-                if (!sc2->insert(v))
-                    error("parameter %s.%s is already defined", toChars(), v->toChars());
-                else
-                    parameters->push(v);
-                localsymtab->insert(v);
-                v->parent = this;
-                if (fparam->userAttribDecl)
-                    v->userAttribDecl = fparam->userAttribDecl;
-            }
-        }
-
-        // Declare the tuple symbols and put them in the symbol table,
-        // but not in parameters[].
-        if (f->parameterList.parameters)
-        {
-            for (size_t i = 0; i < f->parameterList.parameters->length; i++)
-            {
-                Parameter *fparam = (*f->parameterList.parameters)[i];
-
-                if (!fparam->ident)
-                    continue;                   // never used, so ignore
-                if (fparam->type->ty == Ttuple)
-                {
-                    TypeTuple *t = (TypeTuple *)fparam->type;
-                    size_t dim = Parameter::dim(t->arguments);
-                    Objects *exps = new Objects();
-                    exps->setDim(dim);
-                    for (size_t j = 0; j < dim; j++)
-                    {
-                        Parameter *narg = Parameter::getNth(t->arguments, j);
-                        assert(narg->ident);
-                        VarDeclaration *v = sc2->search(Loc(), narg->ident, NULL)->isVarDeclaration();
-                        assert(v);
-                        Expression *e = new VarExp(v->loc, v);
-                        (*exps)[j] = e;
-                    }
-                    assert(fparam->ident);
-                    TupleDeclaration *v = new TupleDeclaration(loc, fparam->ident, exps);
-                    //printf("declaring tuple %s\n", v->toChars());
-                    v->isexp = true;
-                    if (!sc2->insert(v))
-                        error("parameter %s.%s is already defined", toChars(), v->toChars());
-                    localsymtab->insert(v);
-                    v->parent = this;
-                }
-            }
-        }
-
-        // Precondition invariant
-        Statement *fpreinv = NULL;
-        if (addPreInvariant())
-        {
-            Expression *e = addInvariant(ad, vthis);
-            if (e)
-                fpreinv = new ExpStatement(Loc(), e);
-        }
-
-        // Postcondition invariant
-        Statement *fpostinv = NULL;
-        if (addPostInvariant())
-        {
-            Expression *e = addInvariant(ad, vthis);
-            if (e)
-                fpostinv = new ExpStatement(Loc(), e);
-        }
-
-        // Pre/Postcondition contract
-        if (!fbody)
-            buildEnsureRequire(this);
-
-        Scope *scout = NULL;
-        if (needEnsure || addPostInvariant())
-        {
-            if ((needEnsure && global.params.useOut == CHECKENABLEon) || fpostinv)
-            {
-                returnLabel = new LabelDsymbol(Id::returnLabel);
-            }
-
-            // scope of out contract (need for vresult->semantic)
-            ScopeDsymbol *sym = new ScopeDsymbol();
-            sym->parent = sc2->scopesym;
-            sym->loc = loc;
-            sym->endlinnum = endloc.linnum;
-            scout = sc2->push(sym);
-        }
-
-        if (fbody)
-        {
-            ScopeDsymbol *sym = new ScopeDsymbol();
-            sym->parent = sc2->scopesym;
-            sym->loc = loc;
-            sym->endlinnum = endloc.linnum;
-            sc2 = sc2->push(sym);
-
-            AggregateDeclaration *ad2 = isMember2();
-
-            /* If this is a class constructor
-             */
-            if (ad2 && isCtorDeclaration())
-            {
-                allocFieldinit(sc2, ad2->fields.length);
-                for (size_t i = 0; i < ad2->fields.length; i++)
-                {
-                    VarDeclaration *v = ad2->fields[i];
-                    v->ctorinit = 0;
-                }
-            }
-
-            bool inferRef = (f->isref && (storage_class & STCauto));
-
-            fbody = ::semantic(fbody, sc2);
-            if (!fbody)
-                fbody = new CompoundStatement(Loc(), new Statements());
-
-            if (naked)
-            {
-                fpreinv = NULL;         // can't accommodate with no stack frame
-                fpostinv = NULL;
-            }
-
-            assert(type == f ||
-                   (type->ty == Tfunction &&
-                    f->purity == PUREimpure &&
-                    ((TypeFunction *)type)->purity >= PUREfwdref));
-            f = (TypeFunction *)type;
-
-            if (inferRetType)
-            {
-                // If no return type inferred yet, then infer a void
-                if (!f->next)
-                    f->next = Type::tvoid;
-                if (f->checkRetType(loc))
-                    fbody = new ErrorStatement();
-            }
-            if (global.params.vcomplex && f->next != NULL)
-                f->next->checkComplexTransition(loc);
-
-            if (returns && !fbody->isErrorStatement())
-            {
-                for (size_t i = 0; i < returns->length; )
-                {
-                    Expression *exp = (*returns)[i]->exp;
-                    if (exp->op == TOKvar && ((VarExp *)exp)->var == vresult)
-                    {
-                        if (addReturn0(this))
-                            exp->type = Type::tint32;
-                        else
-                            exp->type = f->next;
-                        // Remove `return vresult;` from returns
-                        returns->remove(i);
-                        continue;
-                    }
-                    if (inferRef && f->isref && !exp->type->constConv(f->next))     // Bugzilla 13336
-                        f->isref = false;
-                    i++;
-                }
-            }
-            if (f->isref)   // Function returns a reference
-            {
-                if (storage_class & STCauto)
-                    storage_class &= ~STCauto;
-            }
-            if (!target.isReturnOnStack(f, needThis()) || !checkNRVO())
-                nrvo_can = 0;
-
-            if (fbody->isErrorStatement())
-                ;
-            else if (isStaticCtorDeclaration())
-            {
-                /* It's a static constructor. Ensure that all
-                 * ctor consts were initialized.
-                 */
-                ScopeDsymbol *pd = toParent()->isScopeDsymbol();
-                for (size_t i = 0; i < pd->members->length; i++)
-                {
-                    Dsymbol *s = (*pd->members)[i];
-                    s->checkCtorConstInit();
-                }
-            }
-            else if (ad2 && isCtorDeclaration())
-            {
-                ClassDeclaration *cd = ad2->isClassDeclaration();
-
-                // Verify that all the ctorinit fields got initialized
-                if (!(sc2->callSuper & CSXthis_ctor))
-                {
-                    for (size_t i = 0; i < ad2->fields.length; i++)
-                    {
-                        VarDeclaration *v = ad2->fields[i];
-                        if (v->isThisDeclaration())
-                            continue;
-                        if (v->ctorinit == 0)
-                        {
-                            /* Current bugs in the flow analysis:
-                             * 1. union members should not produce error messages even if
-                             *    not assigned to
-                             * 2. structs should recognize delegating opAssign calls as well
-                             *    as delegating calls to other constructors
-                             */
-                            if (v->isCtorinit() && !v->type->isMutable() && cd)
-                                error("missing initializer for %s field %s", MODtoChars(v->type->mod), v->toChars());
-                            else if (v->storage_class & STCnodefaultctor)
-                                ::error(loc, "field %s must be initialized in constructor", v->toChars());
-                            else if (v->type->needsNested())
-                                ::error(loc, "field %s must be initialized in constructor, because it is nested struct", v->toChars());
-                        }
-                        else
-                        {
-                            bool mustInit = (v->storage_class & STCnodefaultctor ||
-                                             v->type->needsNested());
-                            if (mustInit && !(sc2->fieldinit[i] & CSXthis_ctor))
-                            {
-                                error("field %s must be initialized but skipped", v->toChars());
-                            }
-                        }
-                    }
-                }
-                freeFieldinit(sc2);
-
-                if (cd &&
-                    !(sc2->callSuper & CSXany_ctor) &&
-                    cd->baseClass && cd->baseClass->ctor)
-                {
-                    sc2->callSuper = 0;
-
-                    // Insert implicit super() at start of fbody
-                    FuncDeclaration *fd = resolveFuncCall(Loc(), sc2, cd->baseClass->ctor, NULL, vthis->type, NULL, 1);
-                    if (!fd)
-                    {
-                        error("no match for implicit super() call in constructor");
-                    }
-                    else if (fd->storage_class & STCdisable)
-                    {
-                        error("cannot call super() implicitly because it is annotated with @disable");
-                    }
-                    else
-                    {
-                        Expression *e1 = new SuperExp(Loc());
-                        Expression *e = new CallExp(Loc(), e1);
-                        e = ::semantic(e, sc2);
-
-                        Statement *s = new ExpStatement(Loc(), e);
-                        fbody = new CompoundStatement(Loc(), s, fbody);
-                    }
-                }
-                //printf("callSuper = x%x\n", sc2->callSuper);
-            }
-
-            /* https://issues.dlang.org/show_bug.cgi?id=17502
-             * Wait until after the return type has been inferred before
-             * generating the contracts for this function, and merging contracts
-             * from overrides.
-             *
-             * https://issues.dlang.org/show_bug.cgi?id=17893
-             * However should take care to generate this before inferered
-             * function attributes are applied, such as 'nothrow'.
-             *
-             * This was originally at the end of the first semantic pass, but
-             * required a fix-up to be done here for the '__result' variable
-             * type of __ensure() inside auto functions, but this didn't work
-             * if the out parameter was implicit.
-             */
-            buildEnsureRequire(this);
-
-            int blockexit = BEnone;
-            if (!fbody->isErrorStatement())
-            {
-                // Check for errors related to 'nothrow'.
-                unsigned int nothrowErrors = global.errors;
-                blockexit = blockExit(fbody, this, f->isnothrow);
-                if (f->isnothrow && (global.errors != nothrowErrors))
-                    ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars());
-                if (flags & FUNCFLAGnothrowInprocess)
-                {
-                    if (type == f) f = (TypeFunction *)f->copy();
-                    f->isnothrow = !(blockexit & BEthrow);
-                }
-            }
-
-            if (fbody->isErrorStatement())
-                ;
-            else if (ad2 && isCtorDeclaration())
-            {
-                /* Append:
-                 *  return this;
-                 * to function body
-                 */
-                if (blockexit & BEfallthru)
-                {
-                    Statement *s = new ReturnStatement(loc, NULL);
-                    s = ::semantic(s, sc2);
-                    fbody = new CompoundStatement(loc, fbody, s);
-                    hasReturnExp |= (hasReturnExp & 1 ? 16 : 1);
-                }
-            }
-            else if (fes)
-            {
-                // For foreach(){} body, append a return 0;
-                if (blockexit & BEfallthru)
-                {
-                    Expression *e = new IntegerExp(0);
-                    Statement *s = new ReturnStatement(Loc(), e);
-                    fbody = new CompoundStatement(Loc(), fbody, s);
-                    hasReturnExp |= (hasReturnExp & 1 ? 16 : 1);
-                }
-                assert(!returnLabel);
-            }
-            else
-            {
-                const bool inlineAsm = (hasReturnExp & 8) != 0;
-                if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm)
-                {
-                    Expression *e;
-                    if (!hasReturnExp)
-                        error("has no return statement, but is expected to return a value of type %s", f->next->toChars());
-                    else
-                        error("no return exp; or assert(0); at end of function");
-                    if (global.params.useAssert == CHECKENABLEon &&
-                        !global.params.useInline)
-                    {
-                        /* Add an assert(0, msg); where the missing return
-                         * should be.
-                         */
-                        e = new AssertExp(
-                              endloc,
-                              new IntegerExp(0),
-                              new StringExp(loc, const_cast<char *>("missing return expression"))
-                            );
-                    }
-                    else
-                        e = new HaltExp(endloc);
-                    e = new CommaExp(Loc(), e, f->next->defaultInit());
-                    e = ::semantic(e, sc2);
-                    Statement *s = new ExpStatement(Loc(), e);
-                    fbody = new CompoundStatement(Loc(), fbody, s);
-                }
-            }
-
-            if (returns)
-            {
-                bool implicit0 = addReturn0(this);
-                Type *tret = implicit0 ? Type::tint32 : f->next;
-                assert(tret->ty != Tvoid);
-                if (vresult || returnLabel)
-                    buildResultVar(scout ? scout : sc2, tret);
-
-                /* Cannot move this loop into NrvoWalker, because
-                 * returns[i] may be in the nested delegate for foreach-body.
-                 */
-                for (size_t i = 0; i < returns->length; i++)
-                {
-                    ReturnStatement *rs = (*returns)[i];
-                    Expression *exp = rs->exp;
-                    if (exp->op == TOKerror)
-                        continue;
-                    if (tret->ty == Terror)
-                    {
-                        // Bugzilla 13702
-                        exp = checkGC(sc2, exp);
-                        continue;
-                    }
-
-                    if (!exp->implicitConvTo(tret) &&
-                        parametersIntersect(exp->type))
-                    {
-                        if (exp->type->immutableOf()->implicitConvTo(tret))
-                            exp = exp->castTo(sc2, exp->type->immutableOf());
-                        else if (exp->type->wildOf()->implicitConvTo(tret))
-                            exp = exp->castTo(sc2, exp->type->wildOf());
-                    }
-                    exp = exp->implicitCastTo(sc2, tret);
-
-                    if (f->isref)
-                    {
-                        // Function returns a reference
-                        exp = exp->toLvalue(sc2, exp);
-                        checkReturnEscapeRef(sc2, exp, false);
-                    }
-                    else
-                    {
-                        exp = exp->optimize(WANTvalue);
-
-                        /* Bugzilla 10789:
-                         * If NRVO is not possible, all returned lvalues should call their postblits.
-                         */
-                        if (!nrvo_can)
-                            exp = doCopyOrMove(sc2, exp);
-
-                        if (tret->hasPointers())
-                            checkReturnEscape(sc2, exp, false);
-                    }
-
-                    exp = checkGC(sc2, exp);
-
-                    if (vresult)
-                    {
-                        // Create: return vresult = exp;
-                        exp = new BlitExp(rs->loc, vresult, exp);
-                        exp->type = vresult->type;
-
-                        if (rs->caseDim)
-                            exp = Expression::combine(exp, new IntegerExp(rs->caseDim));
-                    }
-                    else if (tintro && !tret->equals(tintro->nextOf()))
-                    {
-                        exp = exp->implicitCastTo(sc2, tintro->nextOf());
-                    }
-                    rs->exp = exp;
-                }
-            }
-            if (nrvo_var || returnLabel)
-            {
-                NrvoWalker nw;
-                nw.fd = this;
-                nw.sc = sc2;
-                nw.visitStmt(fbody);
-            }
-
-            sc2 = sc2->pop();
-        }
-
-        frequire = mergeFrequire(frequire);
-        fensure = mergeFensure(fensure, Id::result);
-
-        Statement *freq = frequire;
-        Statement *fens = fensure;
-
-        /* Do the semantic analysis on the [in] preconditions and
-         * [out] postconditions.
-         */
-        if (freq)
-        {
-            /* frequire is composed of the [in] contracts
-             */
-            ScopeDsymbol *sym = new ScopeDsymbol();
-            sym->parent = sc2->scopesym;
-            sym->loc = loc;
-            sym->endlinnum = endloc.linnum;
-            sc2 = sc2->push(sym);
-            sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire;
-
-            // BUG: need to error if accessing out parameters
-            // BUG: need to disallow returns and throws
-            // BUG: verify that all in and ref parameters are read
-            freq = ::semantic(freq, sc2);
-            blockExit(freq, this, false);
-
-            sc2 = sc2->pop();
-
-            if (global.params.useIn == CHECKENABLEoff)
-                freq = NULL;
-        }
-
-        if (fens)
-        {
-            /* fensure is composed of the [out] contracts
-             */
-            if (f->next->ty == Tvoid && fensures)
-            {
-                for (size_t i = 0; i < fensures->length; i++)
-                {
-                    Ensure e = (*fensures)[i];
-                    if (e.id)
-                    {
-                        error(e.ensure->loc, "`void` functions have no result");
-                        //fens = NULL;
-                    }
-                }
-            }
-
-            sc2 = scout;    //push
-            sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure;
-
-            // BUG: need to disallow returns and throws
-            if (fensure && f->next->ty != Tvoid)
-                buildResultVar(scout, f->next);
-
-            fens = ::semantic(fens, sc2);
-            blockExit(fens, this, false);
-
-            sc2 = sc2->pop();
-
-            if (global.params.useOut == CHECKENABLEoff)
-                fens = NULL;
-        }
-
-        if (fbody && fbody->isErrorStatement())
-            ;
-        else
-        {
-            Statements *a = new Statements();
-
-            // Merge in initialization of 'out' parameters
-            if (parameters)
-            {
-                for (size_t i = 0; i < parameters->length; i++)
-                {
-                    VarDeclaration *v = (*parameters)[i];
-                    if (v->storage_class & STCout)
-                    {
-                        assert(v->_init);
-                        ExpInitializer *ie = v->_init->isExpInitializer();
-                        assert(ie);
-                        if (ie->exp->op == TOKconstruct)
-                            ie->exp->op = TOKassign; // construction occured in parameter processing
-                        a->push(new ExpStatement(Loc(), ie->exp));
-                    }
-                }
-            }
-
-            if (v_argptr)
-            {
-                // Handled in FuncDeclaration::toObjFile
-                v_argptr->_init = new VoidInitializer(loc);
-            }
-
-            if (_arguments)
-            {
-                /* Advance to elements[] member of TypeInfo_Tuple with:
-                 *  _arguments = v_arguments.elements;
-                 */
-                Expression *e = new VarExp(Loc(), v_arguments);
-                e = new DotIdExp(Loc(), e, Id::elements);
-                e = new ConstructExp(Loc(), _arguments, e);
-                e = ::semantic(e, sc2);
-
-                _arguments->_init = new ExpInitializer(Loc(), e);
-                DeclarationExp *de = new DeclarationExp(Loc(), _arguments);
-                a->push(new ExpStatement(Loc(), de));
-            }
-
-            // Merge contracts together with body into one compound statement
-
-            if (freq || fpreinv)
-            {
-                if (!freq)
-                    freq = fpreinv;
-                else if (fpreinv)
-                    freq = new CompoundStatement(Loc(), freq, fpreinv);
-
-                a->push(freq);
-            }
-
-            if (fbody)
-                a->push(fbody);
-
-            if (fens || fpostinv)
-            {
-                if (!fens)
-                    fens = fpostinv;
-                else if (fpostinv)
-                    fens = new CompoundStatement(Loc(), fpostinv, fens);
-
-                LabelStatement *ls = new LabelStatement(Loc(), Id::returnLabel, fens);
-                returnLabel->statement = ls;
-                a->push(returnLabel->statement);
-
-                if (f->next->ty != Tvoid && vresult)
-                {
-                    // Create: return vresult;
-                    Expression *e = new VarExp(Loc(), vresult);
-                    if (tintro)
-                    {
-                        e = e->implicitCastTo(sc, tintro->nextOf());
-                        e = ::semantic(e, sc);
-                    }
-                    ReturnStatement *s = new ReturnStatement(Loc(), e);
-                    a->push(s);
-                }
-            }
-            if (addReturn0(this))
-            {
-                // Add a return 0; statement
-                Statement *s = new ReturnStatement(Loc(), new IntegerExp(0));
-                a->push(s);
-            }
-
-            Statement *sbody = new CompoundStatement(Loc(), a);
-            /* Append destructor calls for parameters as finally blocks.
-             */
-            if (parameters)
-            {
-                for (size_t i = 0; i < parameters->length; i++)
-                {
-                    VarDeclaration *v = (*parameters)[i];
-
-                    if (v->storage_class & (STCref | STCout | STClazy))
-                        continue;
-
-                    if (v->needsScopeDtor())
-                    {
-                        // same with ExpStatement.scopeCode()
-                        Statement *s = new DtorExpStatement(Loc(), v->edtor, v);
-                        v->storage_class |= STCnodtor;
-
-                        s = ::semantic(s, sc2);
-
-                        bool isnothrow = f->isnothrow & !(flags & FUNCFLAGnothrowInprocess);
-                        int blockexit = blockExit(s, this, isnothrow);
-                        if (f->isnothrow && isnothrow && blockexit & BEthrow)
-                            ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars());
-                        if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
-                            f->isnothrow = false;
-                        if (blockExit(sbody, this, f->isnothrow) == BEfallthru)
-                            sbody = new CompoundStatement(Loc(), sbody, s);
-                        else
-                            sbody = new TryFinallyStatement(Loc(), sbody, s);
-                    }
-                }
-            }
-            // from this point on all possible 'throwers' are checked
-            flags &= ~FUNCFLAGnothrowInprocess;
-
-            if (isSynchronized())
-            {
-                /* Wrap the entire function body in a synchronized statement
-                 */
-                ClassDeclaration *cd = isThis() ? isThis()->isClassDeclaration() : parent->isClassDeclaration();
-
-                if (cd)
-                {
-                    if (!global.params.is64bit &&
-                        global.params.isWindows &&
-                        !isStatic() && !sbody->usesEH() && !global.params.trace)
-                    {
-                        /* The back end uses the "jmonitor" hack for syncing;
-                         * no need to do the sync at this level.
-                         */
-                    }
-                    else
-                    {
-                        Expression *vsync;
-                        if (isStatic())
-                        {
-                            // The monitor is in the ClassInfo
-                            vsync = new DotIdExp(loc, resolve(loc, sc2, cd, false), Id::classinfo);
-                        }
-                        else
-                        {
-                            // 'this' is the monitor
-                            vsync = new VarExp(loc, vthis);
-                        }
-                        sbody = new PeelStatement(sbody);       // don't redo semantic()
-                        sbody = new SynchronizedStatement(loc, vsync, sbody);
-                        sbody = ::semantic(sbody, sc2);
-                    }
-                }
-                else
-                {
-                    error("synchronized function %s must be a member of a class", toChars());
-                }
-            }
-
-            // If declaration has no body, don't set sbody to prevent incorrect codegen.
-            if (fbody || allowsContractWithoutBody(this))
-                fbody = sbody;
-        }
-
-        // Fix up forward-referenced gotos
-        if (gotos)
-        {
-            for (size_t i = 0; i < gotos->length; ++i)
-            {
-                (*gotos)[i]->checkLabel();
-            }
-        }
-
-        if (naked && (fensures || frequires))
-            error("naked assembly functions with contracts are not supported");
-
-        sc2->callSuper = 0;
-        sc2->pop();
-    }
-
-    if (checkClosure())
-    {
-        // We should be setting errors here instead of relying on the global error count.
-        //errors = true;
-    }
-
-    /* If function survived being marked as impure, then it is pure
-     */
-    if (flags & FUNCFLAGpurityInprocess)
-    {
-        flags &= ~FUNCFLAGpurityInprocess;
-        if (type == f)
-            f = (TypeFunction *)f->copy();
-        f->purity = PUREfwdref;
-    }
-
-    if (flags & FUNCFLAGsafetyInprocess)
-    {
-        flags &= ~FUNCFLAGsafetyInprocess;
-        if (type == f)
-            f = (TypeFunction *)f->copy();
-        f->trust = TRUSTsafe;
-    }
-
-    if (flags & FUNCFLAGnogcInprocess)
-    {
-        flags &= ~FUNCFLAGnogcInprocess;
-        if (type == f)
-            f = (TypeFunction *)f->copy();
-        f->isnogc = true;
-    }
-
-    if (flags & FUNCFLAGreturnInprocess)
-    {
-        flags &= ~FUNCFLAGreturnInprocess;
-        if (storage_class & STCreturn)
+         *   in { { statements1... } { statements2... } ... }
+         */
+        assert(frequires->length);
+        Loc loc = (*frequires)[0]->loc;
+        Statements *s = new Statements;
+        for (size_t i = 0; i < frequires->length; i++)
         {
-            if (type == f)
-                f = (TypeFunction *)f->copy();
-            f->isreturn = true;
+            Statement *r = (*frequires)[i];
+            s->push(new ScopeStatement(r->loc, r, r->loc));
         }
+        frequire = new CompoundStatement(loc, s);
     }
 
-    flags &= ~FUNCFLAGinferScope;
-
-    // Infer STCscope
-    if (parameters)
+    if (fensures)
     {
-        size_t nfparams = f->parameterList.length();
-        assert(nfparams == parameters->length);
-        for (size_t u = 0; u < parameters->length; u++)
+        /*   out(id1) { statements1... }
+         *   out(id2) { statements2... }
+         *   ...
+         * becomes:
+         *   out(__result) { { ref id1 = __result; { statements1... } }
+         *                   { ref id2 = __result; { statements2... } } ... }
+         */
+        assert(fensures->length);
+        Loc loc = (*fensures)[0].ensure->loc;
+        Statements *s = new Statements;
+        for (size_t i = 0; i < fensures->length; i++)
         {
-            VarDeclaration *v = (*parameters)[u];
-            if (v->storage_class & STCmaybescope)
+            Ensure r = (*fensures)[i];
+            if (r.id && canBuildResultVar(this))
+            {
+                Loc rloc = r.ensure->loc;
+                IdentifierExp *resultId = new IdentifierExp(rloc, Id::result);
+                ExpInitializer *init = new ExpInitializer(rloc, resultId);
+                StorageClass stc = STCref | STCtemp | STCresult;
+                VarDeclaration *decl = new VarDeclaration(rloc, NULL, r.id, init);
+                decl->storage_class = stc;
+                ExpStatement *sdecl = new ExpStatement(rloc, decl);
+                s->push(new ScopeStatement(rloc, new CompoundStatement(rloc, sdecl, r.ensure), rloc));
+            }
+            else
             {
-                //printf("Inferring scope for %s\n", v->toChars());
-                Parameter *p = f->parameterList[u];
-                v->storage_class &= ~STCmaybescope;
-                v->storage_class |= STCscope | STCscopeinferred;
-                p->storageClass |= STCscope | STCscopeinferred;
-                assert(!(p->storageClass & STCmaybescope));
+                s->push(r.ensure);
             }
         }
+        fensure = new CompoundStatement(loc, s);
     }
 
-    if (vthis && vthis->storage_class & STCmaybescope)
-    {
-        vthis->storage_class &= ~STCmaybescope;
-        vthis->storage_class |= STCscope | STCscopeinferred;
-        f->isscope = true;
-        f->isscopeinferred = true;
-    }
+    if (!isVirtual())
+        return;
 
-    // reset deco to apply inference result to mangled name
-    if (f != type)
-        f->deco = NULL;
+    /* Rewrite contracts as nested functions, then call them. Doing it as nested
+     * functions means that overriding functions can call them.
+     */
+    TypeFunction *f = (TypeFunction *)type;
 
-    // Do semantic type AFTER pure/nothrow inference.
-    if (!f->deco && ident != Id::xopEquals && ident != Id::xopCmp)
+    if (frequire)
     {
-        sc = sc->push();
-        if (isCtorDeclaration()) // Bugzilla #15665
-            sc->flags |= SCOPEctor;
-        sc->stc = 0;
-        sc->linkage = linkage;  // Bugzilla 8496
-        type = f->semantic(loc, sc);
-        sc = sc->pop();
+        /*   in { ... }
+         * becomes:
+         *   void __require() { ... }
+         *   __require();
+         */
+        Loc loc = frequire->loc;
+        TypeFunction *tf = new TypeFunction(ParameterList(), Type::tvoid, LINKd);
+        tf->isnothrow = f->isnothrow;
+        tf->isnogc = f->isnogc;
+        tf->purity = f->purity;
+        tf->trust = f->trust;
+        FuncDeclaration *fd = new FuncDeclaration(loc, loc,
+                                                  Id::require, STCundefined, tf);
+        fd->fbody = frequire;
+        Statement *s1 = new ExpStatement(loc, fd);
+        Expression *e = new CallExp(loc, new VarExp(loc, fd, false), (Expressions *)NULL);
+        Statement *s2 = new ExpStatement(loc, e);
+        frequire = new CompoundStatement(loc, s1, s2);
+        fdrequire = fd;
     }
 
-    /* If this function had instantiated with gagging, error reproduction will be
-     * done by TemplateInstance::semantic.
-     * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
-     */
-    semanticRun = PASSsemantic3done;
-    semantic3Errors = (global.errors != oldErrors) || (fbody && fbody->isErrorStatement());
-    if (type->ty == Terror)
-        errors = true;
-    //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
-    //fflush(stdout);
+    if (fensure)
+    {
+        /*   out (result) { ... }
+         * becomes:
+         *   void __ensure(ref tret result) { ... }
+         *   __ensure(result);
+         */
+        Loc loc = fensure->loc;
+        Parameters *fparams = new Parameters();
+        Parameter *p = NULL;
+        if (canBuildResultVar(this))
+        {
+            p = new Parameter(STCref | STCconst, f->nextOf(), Id::result, NULL, NULL);
+            fparams->push(p);
+        }
+        TypeFunction *tf = new TypeFunction(ParameterList(fparams), Type::tvoid, LINKd);
+        tf->isnothrow = f->isnothrow;
+        tf->isnogc = f->isnogc;
+        tf->purity = f->purity;
+        tf->trust = f->trust;
+        FuncDeclaration *fd = new FuncDeclaration(loc, loc,
+                                                  Id::ensure, STCundefined, tf);
+        fd->fbody = fensure;
+        Statement *s1 = new ExpStatement(loc, fd);
+        Expression *eresult = NULL;
+        if (canBuildResultVar(this))
+            eresult = new IdentifierExp(loc, Id::result);
+        Expression *e = new CallExp(loc, new VarExp(loc, fd, false), eresult);
+        Statement *s2 = new ExpStatement(loc, e);
+        fensure = new CompoundStatement(loc, s1, s2);
+        fdensure = fd;
+    }
 }
 
 /****************************************************
@@ -2531,7 +362,7 @@ bool FuncDeclaration::functionSemantic()
         unsigned oldgag = global.gag;
         if (global.gag && !spec)
             global.gag = 0;
-        semantic(_scope);
+        dsymbolSemantic(this, _scope);
         global.gag = oldgag;
         if (spec && global.errors != olderrs)
             spec->errors = (global.errors - olderrs != 0);
@@ -2586,7 +417,7 @@ bool FuncDeclaration::functionSemantic3()
         unsigned oldgag = global.gag;
         if (global.gag && !spec)
             global.gag = 0;
-        semantic3(_scope);
+        semantic3(this, _scope);
         global.gag = oldgag;
 
         // If it is a speculatively-instantiated template, and errors occur,
@@ -2615,7 +446,7 @@ bool FuncDeclaration::checkForwardRef(Loc loc)
     if (!type->deco)
     {
         bool inSemantic3 = (inferRetType && semanticRun >= PASSsemantic3);
-        ::error(loc, "forward reference to %s'%s'",
+        ::error(loc, "forward reference to %s`%s`",
             (inSemantic3 ? "inferred return type of function " : ""),
             toChars());
         return true;
@@ -2655,7 +486,7 @@ VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad
             if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope))
                 v->storage_class |= STCmaybescope;
 
-            v->semantic(sc);
+            dsymbolSemantic(v, sc);
             if (!sc->insert(v))
                 assert(0);
             v->parent = this;
@@ -2681,7 +512,7 @@ VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad
         if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope))
             v->storage_class |= STCmaybescope;
 
-        v->semantic(sc);
+        dsymbolSemantic(v, sc);
         if (!sc->insert(v))
             assert(0);
         v->parent = this;
@@ -2756,7 +587,7 @@ void FuncDeclaration::buildResultVar(Scope *sc, Type *tret)
             vresult->storage_class |= STCref;
         vresult->type = tret;
 
-        vresult->semantic(sc);
+        dsymbolSemantic(vresult, sc);
 
         if (!sc->insert(vresult))
             error("out result %s is already defined", vresult->toChars());
@@ -2816,7 +647,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf)
             assert(fdv->_scope);
             Scope *sc = fdv->_scope->push();
             sc->stc &= ~STCoverride;
-            fdv->semantic3(sc);
+            semantic3(fdv, sc);
             sc->pop();
         }
 
@@ -2874,7 +705,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Identifier *oid)
             assert(fdv->_scope);
             Scope *sc = fdv->_scope->push();
             sc->stc &= ~STCoverride;
-            fdv->semantic3(sc);
+            semantic3(fdv, sc);
             sc->pop();
         }
 
@@ -3706,7 +1537,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
         }
         else if (od)
         {
-            ::error(loc, "none of the overloads of '%s' are callable using argument types !(%s)%s",
+            ::error(loc, "none of the overloads of `%s` are callable using argument types !(%s)%s",
                 od->ident->toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
         }
         else
@@ -3721,7 +1552,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
                 MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod);
                 MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod);
                 if (hasOverloads)
-                    ::error(loc, "none of the overloads of '%s' are callable using a %sobject, candidates are:",
+                    ::error(loc, "none of the overloads of `%s` are callable using a %sobject, candidates are:",
                         fd->ident->toChars(), thisBuf.peekChars());
                 else
                     ::error(loc, "%smethod %s is not callable using a %sobject",
@@ -3731,7 +1562,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
             {
                 //printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco);
                 if (hasOverloads)
-                    ::error(loc, "none of the overloads of '%s' are callable using argument types %s, candidates are:",
+                    ::error(loc, "none of the overloads of `%s` are callable using argument types %s, candidates are:",
                             fd->ident->toChars(), fargsBuf.peekChars());
                 else
                     fd->error(loc, "%s%s is not callable using argument types %s",
@@ -4296,56 +2127,6 @@ bool FuncDeclaration::addPostInvariant()
             !naked);
 }
 
-/********************************************************
- * Generate Expression to call the invariant.
- * Input:
- *      ad      aggregate with the invariant
- *      vthis   variable with 'this'
- * Returns:
- *      void expression that calls the invariant
- */
-Expression *addInvariant(AggregateDeclaration *ad, VarDeclaration *vthis)
-{
-    Expression *e = NULL;
-
-    // Call invariant directly only if it exists
-    FuncDeclaration *inv = ad->inv;
-    ClassDeclaration *cd = ad->isClassDeclaration();
-
-    while (!inv && cd)
-    {
-        cd = cd->baseClass;
-        if (!cd)
-            break;
-        inv = cd->inv;
-    }
-    if (inv)
-    {
-    #if 1
-        // Workaround for bugzilla 13394: For the correct mangling,
-        // run attribute inference on inv if needed.
-        inv->functionSemantic();
-    #endif
-
-        //e = new DsymbolExp(Loc(), inv);
-        //e = new CallExp(Loc(), e);
-        //e = e->semantic(sc2);
-
-        /* https://issues.dlang.org/show_bug.cgi?id=13113
-         * Currently virtual invariant calls completely
-         * bypass attribute enforcement.
-         * Change the behavior of pre-invariant call by following it.
-         */
-        e = new ThisExp(Loc());
-        e->type = vthis->type;
-        e = new DotVarExp(Loc(), e, inv, false);
-        e->type = inv->type;
-        e = new CallExp(Loc(), e);
-        e->type = Type::tvoid;
-    }
-    return e;
-}
-
 /**********************************
  * Generate a FuncDeclaration for a runtime library function.
  */
@@ -4987,87 +2768,6 @@ Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(f);
 }
 
-void CtorDeclaration::semantic(Scope *sc)
-{
-    //printf("CtorDeclaration::semantic() %s\n", toChars());
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = toParent2();
-    AggregateDeclaration *ad = p->isAggregateDeclaration();
-    if (!ad)
-    {
-        ::error(loc, "constructor can only be a member of aggregate, not %s %s",
-            p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;              // not a static constructor
-    sc->flags |= SCOPEctor;
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-
-    if (errors)
-        return;
-
-    TypeFunction *tf = type->toTypeFunction();
-
-    /* See if it's the default constructor
-     * But, template constructor should not become a default constructor.
-     */
-    if (ad && (!parent->isTemplateInstance() || parent->isTemplateMixin()))
-    {
-        const size_t dim = tf->parameterList.length();
-
-        if (StructDeclaration *sd = ad->isStructDeclaration())
-        {
-            if (dim == 0 && tf->parameterList.varargs == VARARGnone) // empty default ctor w/o any varargs
-            {
-                if (fbody || !(storage_class & STCdisable) || dim)
-                {
-                    error("default constructor for structs only allowed "
-                        "with @disable, no body, and no parameters");
-                    storage_class |= STCdisable;
-                    fbody = NULL;
-                }
-                sd->noDefaultCtor = true;
-            }
-            else if (dim == 0 && tf->parameterList.varargs) // allow varargs only ctor
-            {
-            }
-            else if (dim && tf->parameterList[0]->defaultArg)
-            {
-                // if the first parameter has a default argument, then the rest does as well
-                if (storage_class & STCdisable)
-                {
-                    deprecation("@disable'd constructor cannot have default "
-                                "arguments for all parameters.");
-                    deprecationSupplemental(loc, "Use @disable this(); if you want to disable default initialization.");
-                }
-                else
-                    deprecation("all parameters have default arguments, "
-                                "but structs cannot have default constructors.");
-            }
-
-        }
-        else if (dim == 0 && tf->parameterList.varargs == VARARGnone)
-        {
-            ad->defaultCtor = this;
-        }
-    }
-}
-
 const char *CtorDeclaration::kind() const
 {
     return "constructor";
@@ -5108,44 +2808,6 @@ Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(dd);
 }
 
-void PostBlitDeclaration::semantic(Scope *sc)
-{
-    //printf("PostBlitDeclaration::semantic() %s\n", toChars());
-    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
-    //printf("stc = x%llx\n", sc->stc);
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = toParent2();
-    StructDeclaration *ad = p->isStructDeclaration();
-    if (!ad)
-    {
-        ::error(loc, "postblit can only be a member of struct/union, not %s %s",
-            p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-    if (ident == Id::postblit && semanticRun < PASSsemantic)
-        ad->postblits.push(this);
-    if (!type)
-        type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class);
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;              // not static
-    sc->linkage = LINKd;
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-}
-
 bool PostBlitDeclaration::overloadInsert(Dsymbol *)
 {
     return false;       // cannot overload postblits
@@ -5185,44 +2847,6 @@ Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(dd);
 }
 
-void DtorDeclaration::semantic(Scope *sc)
-{
-    //printf("DtorDeclaration::semantic() %s\n", toChars());
-    //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = toParent2();
-    AggregateDeclaration *ad = p->isAggregateDeclaration();
-    if (!ad)
-    {
-        ::error(loc, "destructor can only be a member of aggregate, not %s %s",
-            p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-    if (ident == Id::dtor && semanticRun < PASSsemantic)
-        ad->dtors.push(this);
-    if (!type)
-        type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class);
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;              // not a static destructor
-    if (sc->linkage != LINKcpp)
-        sc->linkage = LINKd;
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-}
-
 bool DtorDeclaration::overloadInsert(Dsymbol *)
 {
     return false;       // cannot overload destructors
@@ -5275,71 +2899,6 @@ Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(scd);
 }
 
-void StaticCtorDeclaration::semantic(Scope *sc)
-{
-    //printf("StaticCtorDeclaration::semantic()\n");
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = parent->pastMixin();
-    if (!p->isScopeDsymbol())
-    {
-        const char *s = (isSharedStaticCtorDeclaration() ? "shared " : "");
-        ::error(loc, "%sstatic constructor can only be member of module/aggregate/template, not %s %s",
-            s, p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-    if (!type)
-        type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class);
-
-    /* If the static ctor appears within a template instantiation,
-     * it could get called multiple times by the module constructors
-     * for different modules. Thus, protect it with a gate.
-     */
-    if (isInstantiated() && semanticRun < PASSsemantic)
-    {
-        /* Add this prefix to the function:
-         *      static int gate;
-         *      if (++gate != 1) return;
-         * Note that this is not thread safe; should not have threads
-         * during static construction.
-         */
-        VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
-        v->storage_class = STCtemp | (isSharedStaticCtorDeclaration() ? STCstatic : STCtls);
-        Statements *sa = new Statements();
-        Statement *s = new ExpStatement(Loc(), v);
-        sa->push(s);
-        Expression *e = new IdentifierExp(Loc(), v->ident);
-        e = new AddAssignExp(Loc(), e, new IntegerExp(1));
-        e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(1));
-        s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
-        sa->push(s);
-        if (fbody)
-            sa->push(fbody);
-        fbody = new CompoundStatement(Loc(), sa);
-    }
-
-    FuncDeclaration::semantic(sc);
-
-    // We're going to need ModuleInfo
-    Module *m = getModule();
-    if (!m)
-        m = sc->_module;
-    if (m)
-    {
-        m->needmoduleinfo = 1;
-        //printf("module1 %s needs moduleinfo\n", m->toChars());
-    }
-}
-
 AggregateDeclaration *StaticCtorDeclaration::isThis()
 {
     return NULL;
@@ -5402,72 +2961,6 @@ Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(sdd);
 }
 
-void StaticDtorDeclaration::semantic(Scope *sc)
-{
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = parent->pastMixin();
-    if (!p->isScopeDsymbol())
-    {
-        const char *s = (isSharedStaticDtorDeclaration() ? "shared " : "");
-        ::error(loc, "%sstatic destructor can only be member of module/aggregate/template, not %s %s",
-            s, p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-    if (!type)
-        type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class);
-
-    /* If the static ctor appears within a template instantiation,
-     * it could get called multiple times by the module constructors
-     * for different modules. Thus, protect it with a gate.
-     */
-    if (isInstantiated() && semanticRun < PASSsemantic)
-    {
-        /* Add this prefix to the function:
-         *      static int gate;
-         *      if (--gate != 0) return;
-         * Increment gate during constructor execution.
-         * Note that this is not thread safe; should not have threads
-         * during static destruction.
-         */
-        VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
-        v->storage_class = STCtemp | (isSharedStaticDtorDeclaration() ? STCstatic : STCtls);
-        Statements *sa = new Statements();
-        Statement *s = new ExpStatement(Loc(), v);
-        sa->push(s);
-        Expression *e = new IdentifierExp(Loc(), v->ident);
-        e = new AddAssignExp(Loc(), e, new IntegerExp(-1));
-        e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(0));
-        s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
-        sa->push(s);
-        if (fbody)
-            sa->push(fbody);
-        fbody = new CompoundStatement(Loc(), sa);
-        vgate = v;
-    }
-
-    FuncDeclaration::semantic(sc);
-
-    // We're going to need ModuleInfo
-    Module *m = getModule();
-    if (!m)
-        m = sc->_module;
-    if (m)
-    {
-        m->needmoduleinfo = 1;
-        //printf("module2 %s needs moduleinfo\n", m->toChars());
-    }
-}
-
 AggregateDeclaration *StaticDtorDeclaration::isThis()
 {
     return NULL;
@@ -5523,46 +3016,6 @@ Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(id);
 }
 
-void InvariantDeclaration::semantic(Scope *sc)
-{
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = parent->pastMixin();
-    AggregateDeclaration *ad = p->isAggregateDeclaration();
-    if (!ad)
-    {
-        ::error(loc, "invariant can only be a member of aggregate, not %s %s",
-            p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-    if (ident != Id::classInvariant &&
-        semanticRun < PASSsemantic &&
-        !ad->isUnionDeclaration()           // users are on their own with union fields
-       )
-        ad->invs.push(this);
-    if (!type)
-        type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class);
-
-    sc = sc->push();
-    sc->stc &= ~STCstatic;              // not a static invariant
-    sc->stc |= STCconst;                // invariant() is always const
-    sc->flags = (sc->flags & ~SCOPEcontract) | SCOPEinvariant;
-    sc->linkage = LINKd;
-
-    FuncDeclaration::semantic(sc);
-
-    sc->pop();
-}
-
 bool InvariantDeclaration::isVirtual()
 {
     return false;
@@ -5605,40 +3058,6 @@ Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(utd);
 }
 
-void UnitTestDeclaration::semantic(Scope *sc)
-{
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    protection = sc->protection;
-
-    parent = sc->parent;
-    Dsymbol *p = parent->pastMixin();
-    if (!p->isScopeDsymbol())
-    {
-        ::error(loc, "unittest can only be a member of module/aggregate/template, not %s %s",
-            p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-
-    if (global.params.useUnitTests)
-    {
-        if (!type)
-            type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class);
-        Scope *sc2 = sc->push();
-        sc2->linkage = LINKd;
-        FuncDeclaration::semantic(sc2);
-        sc2->pop();
-    }
-}
-
 AggregateDeclaration *UnitTestDeclaration::isThis()
 {
     return NULL;
@@ -5676,49 +3095,6 @@ Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(f);
 }
 
-void NewDeclaration::semantic(Scope *sc)
-{
-    //printf("NewDeclaration::semantic()\n");
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = parent->pastMixin();
-    if (!p->isAggregateDeclaration())
-    {
-        ::error(loc, "allocator can only be a member of aggregate, not %s %s",
-            p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-    Type *tret = Type::tvoid->pointerTo();
-    if (!type)
-        type = new TypeFunction(ParameterList(parameters, varargs), tret, LINKd, storage_class);
-
-    type = type->semantic(loc, sc);
-
-    // Check that there is at least one argument of type size_t
-    TypeFunction *tf = type->toTypeFunction();
-    if (tf->parameterList.length() < 1)
-    {
-        error("at least one argument of type size_t expected");
-    }
-    else
-    {
-        Parameter *fparam = tf->parameterList[0];
-        if (!fparam->type->equals(Type::tsize_t))
-            error("first argument must be type size_t, not %s", fparam->type->toChars());
-    }
-
-    FuncDeclaration::semantic(sc);
-}
-
 const char *NewDeclaration::kind() const
 {
     return "allocator";
@@ -5755,48 +3131,6 @@ Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
     return FuncDeclaration::syntaxCopy(f);
 }
 
-void DeleteDeclaration::semantic(Scope *sc)
-{
-    //printf("DeleteDeclaration::semantic()\n");
-    if (semanticRun >= PASSsemanticdone)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-
-    parent = sc->parent;
-    Dsymbol *p = parent->pastMixin();
-    if (!p->isAggregateDeclaration())
-    {
-        ::error(loc, "deallocator can only be a member of aggregate, not %s %s",
-            p->kind(), p->toChars());
-        type = Type::terror;
-        errors = true;
-        return;
-    }
-    if (!type)
-        type = new TypeFunction(ParameterList(parameters), Type::tvoid, LINKd, storage_class);
-
-    type = type->semantic(loc, sc);
-
-    // Check that there is only one argument of type void*
-    TypeFunction *tf = type->toTypeFunction();
-    if (tf->parameterList.length() != 1)
-    {
-        error("one argument of type void* expected");
-    }
-    else
-    {
-        Parameter *fparam = tf->parameterList[0];
-        if (!fparam->type->equals(Type::tvoid->pointerTo()))
-            error("one argument of type void* expected, not %s", fparam->type->toChars());
-    }
-
-    FuncDeclaration::semantic(sc);
-}
-
 const char *DeleteDeclaration::kind() const
 {
     return "deallocator";
index 6e65d86eb5a3b5e8365258a7e616b641a2c674b4..d9d59d685cad749107146e48dbcc15f949e46748 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index a351930ce457389b5b9bdada2c14cee94f7aa7f7..a11c9c353d9130b35e9c66f74b456b0d1cd4eb19 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Dave Fladebo
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 1bad506bb2890521a33cdbf1baead55170030ab3..d464d4aa618a6d46811a6b9e9fee806c0529e79b 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Dave Fladebo
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 459a3a622bc92283602e46a409edd07ce947a9cd..fc58a3c4462fd64a22efdfd2193df620a6fbac73 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2018-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2018-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 5cc9025a7b312c38674be401840b9c59e8377432..e3940a8adbf4da0d4f1ce9114f5028e1b395959a 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2018-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2018-2021 by The D Language Foundation, All Rights Reserved
  * written by Iain Buclaw
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  */
 
 #include "scope.h"
+#include "expression.h"
 #include "declaration.h"
 #include "errors.h"
 #include "parse.h"
 #include "statement.h"
 
-Expression *semantic(Expression *e, Scope *sc);
-Statement *semantic(Statement *s, Scope *sc);
-
 /***********************************
  * Parse list of extended asm input or output operands.
  * Grammar:
@@ -321,7 +319,7 @@ Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc)
     s->stc = sc->stc;
 
     // Fold the instruction template string.
-    s->insn = semantic(s->insn, sc);
+    s->insn = expressionSemantic(s->insn, sc);
     s->insn = s->insn->ctfeInterpret();
 
     if (s->insn->op != TOKstring || ((StringExp *) s->insn)->sz != 1)
@@ -336,7 +334,7 @@ Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc)
         for (size_t i = 0; i < s->args->length; i++)
         {
             Expression *e = (*s->args)[i];
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             // Check argument is a valid lvalue/rvalue.
             if (i < s->outputargs)
                 e = e->modifiableLvalue(sc, NULL);
@@ -345,7 +343,7 @@ Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc)
             (*s->args)[i] = e;
 
             e = (*s->constraints)[i];
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             assert(e->op == TOKstring && ((StringExp *) e)->sz == 1);
             (*s->constraints)[i] = e;
         }
@@ -357,7 +355,7 @@ Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc)
         for (size_t i = 0; i < s->clobbers->length; i++)
         {
             Expression *e = (*s->clobbers)[i];
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             assert(e->op == TOKstring && ((StringExp *) e)->sz == 1);
             (*s->clobbers)[i] = e;
         }
@@ -373,7 +371,7 @@ Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc)
             if (!s->gotos)
                 s->gotos = new GotoStatements();
             s->gotos->push(gs);
-            semantic(gs, sc);
+            statementSemantic(gs, sc);
         }
     }
 
index 1bd453fc53c222133966d299d909527c32f1031f..197d288e5323a7270c63f952823df05a21989014 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index c611bf1dc355699cbcbc2cfd643deecab361c552..278ce9b8a7671c6918d0cefcbdd96e1268a0ee07 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 322a293cf09100d8740fe0c87f3149b972babd6b..59faa993b9bb473958a7fbc8703496b36162e431 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index c221cd203dcd1b853646eadf998d43e1b2e02346..d7c27eaa7714051be4b1db40d1b23dd972cf8e10 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index d08e374add2b5a03ff38c9b61f7364947f2260c1..239cb07333266b2c3054c3481982899a2adb8230 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2010-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index d1739313c11cc9a1c98cfa1e7a84eaa52e5ce961..e49ad15c2d30e6eb2cfca115d8788b122d4c7e1c 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -47,8 +47,6 @@ public:
     Dsymbol *syntaxCopy(Dsymbol *s);    // copy only syntax trees
     void load(Scope *sc);
     void importAll(Scope *sc);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
     Dsymbol *toAlias();
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope* sc);
index 28b4187b2e6c0e224d2b65179402e521cbe3c32c..d18e0549aace1411b2505c11484462a8f8262bed 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -25,9 +25,6 @@
 #include "id.h"
 #include "tokens.h"
 
-Expression *semantic(Expression *e, Scope *sc);
-Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
-
 /********************************** Initializer *******************************/
 
 Initializer::Initializer(Loc loc)
index 6f98fdb494686af48745ac5e7eb4db9f65e21d5a..4ba18d6a47457fc86eebaaf2a0dd3a14c02750e7 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -21,6 +21,7 @@ class Expression;
 struct Scope;
 class Type;
 class AggregateDeclaration;
+class Initializer;
 class ErrorInitializer;
 class VoidInitializer;
 class StructInitializer;
@@ -29,6 +30,8 @@ class ExpInitializer;
 
 enum NeedInterpret { INITnointerpret, INITinterpret };
 
+Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
+
 class Initializer : public ASTNode
 {
 public:
index 9381da46b2916d5046e877efd3ef761497b416cb..c7d1dfe0deb8a5e84f6bb59353186ff11b2027f9 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -20,9 +20,7 @@
 #include "id.h"
 
 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
-Expression *semantic(Expression *e, Scope *sc);
 Initializer *inferType(Initializer *init, Scope *sc);
-Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
 bool hasNonConstPointers(Expression *e);
 
 class InitializerSemanticVisitor : public Visitor
@@ -97,10 +95,10 @@ public:
                     {
                         s = sd->search_correct(id);
                         if (s)
-                            error(i->loc, "'%s' is not a member of '%s', did you mean %s '%s'?",
+                            error(i->loc, "`%s` is not a member of `%s`, did you mean %s `%s`?",
                                   id->toChars(), sd->toChars(), s->kind(), s->toChars());
                         else
-                            error(i->loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
+                            error(i->loc, "`%s` is not a member of `%s`", id->toChars(), sd->toChars());
                         result = new ErrorInitializer();
                         return;
                     }
@@ -130,7 +128,7 @@ public:
                 VarDeclaration *vd = sd->fields[fieldi];
                 if ((*elements)[fieldi])
                 {
-                    error(i->loc, "duplicate initializer for field '%s'", vd->toChars());
+                    error(i->loc, "duplicate initializer for field `%s`", vd->toChars());
                     errors = true;
                     continue;
                 }
@@ -148,7 +146,7 @@ public:
 
                 assert(sc);
                 Initializer *iz = i->value[j];
-                iz = ::semantic(iz, sc, vd->type->addMod(t->mod), needInterpret);
+                iz = initializerSemantic(iz, sc, vd->type->addMod(t->mod), needInterpret);
                 Expression *ex = initializerToExpression(iz);
                 if (ex->op == TOKerror)
                 {
@@ -174,7 +172,7 @@ public:
             sle->type = t;
 
             ExpInitializer *ie = new ExpInitializer(i->loc, sle);
-            result = ::semantic(ie, sc, t, needInterpret);
+            result = initializerSemantic(ie, sc, t, needInterpret);
             return;
         }
         else if ((t->ty == Tdelegate || (t->ty == Tpointer && t->nextOf()->ty == Tfunction)) && i->value.length == 0)
@@ -188,7 +186,7 @@ public:
             fd->endloc = i->loc;
             Expression *e = new FuncExp(i->loc, fd);
             ExpInitializer *ie = new ExpInitializer(i->loc, e);
-            result = ::semantic(ie, sc, t, needInterpret);
+            result = initializerSemantic(ie, sc, t, needInterpret);
             return;
         }
 
@@ -235,7 +233,7 @@ public:
                         goto Lerr;
                     }
                     ExpInitializer *ei = new ExpInitializer(e->loc, e);
-                    result = ::semantic(ei, sc, t, needInterpret);
+                    result = initializerSemantic(ei, sc, t, needInterpret);
                     return;
                 }
             case Tpointer:
@@ -257,7 +255,7 @@ public:
             if (idx)
             {
                 sc = sc->startCTFE();
-                idx = ::semantic(idx, sc);
+                idx = expressionSemantic(idx, sc);
                 sc = sc->endCTFE();
                 idx = idx->ctfeInterpret();
                 i->index[j] = idx;
@@ -276,7 +274,7 @@ public:
             ExpInitializer *ei = val->isExpInitializer();
             if (ei && !idx)
                 ei->expandTuples = true;
-            val = ::semantic(val, sc, t->nextOf(), needInterpret);
+            val = initializerSemantic(val, sc, t->nextOf(), needInterpret);
             if (val->isErrorInitializer())
                 errors = true;
 
@@ -344,7 +342,7 @@ public:
     {
         //printf("ExpInitializer::semantic(%s), type = %s\n", i->exp->toChars(), t->toChars());
         if (needInterpret) sc = sc->startCTFE();
-        i->exp = ::semantic(i->exp, sc);
+        i->exp = expressionSemantic(i->exp, sc);
         i->exp = resolveProperties(sc, i->exp);
         if (needInterpret) sc = sc->endCTFE();
         if (i->exp->op == TOKerror)
@@ -388,7 +386,7 @@ public:
         }
         if (i->exp->op == TOKtype)
         {
-            i->exp->error("initializer must be an expression, not '%s'", i->exp->toChars());
+            i->exp->error("initializer must be an expression, not `%s`", i->exp->toChars());
             result = new ErrorInitializer();
             return;
         }
@@ -396,7 +394,7 @@ public:
         // Make sure all pointers are constants
         if (needInterpret && hasNonConstPointers(i->exp))
         {
-            i->exp->error("cannot use non-constant CTFE pointer in an initializer '%s'", i->exp->toChars());
+            i->exp->error("cannot use non-constant CTFE pointer in an initializer `%s`", i->exp->toChars());
             result = new ErrorInitializer();
             return;
         }
@@ -444,7 +442,7 @@ public:
                 e = new StructLiteralExp(i->loc, sd, NULL);
                 e = new DotIdExp(i->loc, e, Id::ctor);
                 e = new CallExp(i->loc, e, i->exp);
-                e = ::semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 if (needInterpret)
                     i->exp = e->ctfeInterpret();
                 else
@@ -513,7 +511,7 @@ public:
 };
 
 // Performs semantic analisys on Initializer AST nodes
-Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret)
+Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret)
 {
     InitializerSemanticVisitor v = InitializerSemanticVisitor(sc, t, needInterpret);
     init->accept(&v);
@@ -633,7 +631,7 @@ public:
     void visit(ExpInitializer *init)
     {
         //printf("ExpInitializer::inferType() %s\n", init->toChars());
-        init->exp = ::semantic(init->exp, sc);
+        init->exp = expressionSemantic(init->exp, sc);
         init->exp = resolveProperties(sc, init->exp);
 
         if (init->exp->op == TOKscope)
@@ -897,8 +895,8 @@ public:
                 size_t d = (size_t)tsa->dim->toInteger();
                 Expressions *elements = new Expressions();
                 elements->setDim(d);
-                for (size_t i = 0; i < d; i++)
-                    (*elements)[i] = e;
+                for (size_t j = 0; j < d; j++)
+                    (*elements)[j] = e;
                 ArrayLiteralExp *ae = new ArrayLiteralExp(e->loc, itype, elements);
                 result = ae;
                 return;
index 788b37b18a4beda5c5728c2315958a238b12a851..36af8dac9eedadfa0e576d0d9b90c8f3225df399 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by KennyTM
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 58ec5b9b43453136c53825a070e218dfb99f75a6..fd6153205c91e3da847164da00298fd46a6a9488 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by KennyTM
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 802de81c4c2cc4723a4803580c08bfa112319cda..832e559a875c2613ef87de3f44aaf8db9582c837 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 2dbcc0c0f903ad0c90e765e4e3fcd5afbeb8ec5c..d680001000fe4f4248102c229127276b53fe5fe3 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index db989b0b528f8fbe81184b83e38ea0a11ef24518..3ea932c036eb38adcb8a8a4c8d1337bfb37ab493 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -1699,7 +1699,7 @@ TOK Lexer::number(Token *t)
                 ++p;
                 if (base < 10 && !err)
                 {
-                    error("radix %d digit expected, not '%c'", base, c);
+                    error("radix %d digit expected, not `%c`", base, c);
                     err = true;
                 }
                 d = c - '0';
@@ -1714,7 +1714,7 @@ TOK Lexer::number(Token *t)
                         goto Lreal;
                     if (!err)
                     {
-                        error("radix %d digit expected, not '%c'", base, c);
+                        error("radix %d digit expected, not `%c`", base, c);
                         err = true;
                     }
                 }
@@ -2049,7 +2049,7 @@ TOK Lexer::inreal(Token *t)
     if (isOutOfRange && !isLong)
     {
         const char *suffix = (result == TOKfloat32v || result == TOKimaginary32v) ? "f" : "";
-        error(scanloc, "number '%s%s' is not representable", (char *)stringbuffer.slice().ptr, suffix);
+        error(scanloc, "number `%s%s` is not representable", (char *)stringbuffer.slice().ptr, suffix);
     }
     return result;
 }
index 555b6c65b8433cc64a186bfd428e40bfe34a3728..b36e7f7bdaf3dbc527085f4fa1db499160b9cd33 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 26710b4771b5bb374b30c56671fce16590ba1d08..80ec36e00e6b5303cf3817b964257cecb5122128 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index c60f4a73440466341ef1b5b3838a6d1ee624919c..544f77b8b0ba0ca95071df0fdd502b55b2b3e85c 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index ddccd6c7d99306413755f91d120690df580a94a3..9b9c278c8a78842d50f96ce6ec0e04171006ca5a 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 4968ec7e1b540bc6b37a30ea182f782485fbe308..03078b5e83307e5c4256f22de39eed6a34a179ac 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -43,7 +43,6 @@ public:
 
     bool isAncestorPackageOf(const Package * const pkg) const;
 
-    void semantic(Scope *);
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
     void accept(Visitor *v) { v->visit(this); }
 
@@ -124,9 +123,6 @@ public:
     bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
     Module *parse();    // syntactic parse
     void importAll(Scope *sc);
-    void semantic(Scope *);    // semantic analysis
-    void semantic2(Scope *);   // pass 2 semantic analysis
-    void semantic3(Scope *);   // pass 3 semantic analysis
     int needModuleInfo();
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
     bool isPackageAccessible(Package *p, Prot protection, int flags = 0);
index cc8eb226019972fb1fa4bf6ff03aef2a11d151a9..c1071b2f278ea11641ec3b0481e4764474191a49 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -37,12 +37,8 @@ int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *p
 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
 Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false);
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
-Expression *semantic(Expression *e, Scope *sc);
-Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
-Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag);
 Expression *typeToExpression(Type *t);
 Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
-Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
 
 /***************************** Type *****************************/
 
@@ -282,22 +278,11 @@ unsigned Type::alignsize()
     return (unsigned)size(Loc());
 }
 
-Type *Type::semantic(Loc loc, Scope *)
-{
-    if (ty == Tint128 || ty == Tuns128)
-    {
-        error(loc, "cent and ucent types not implemented");
-        return terror;
-    }
-
-    return merge();
-}
-
 Type *Type::trySemantic(Loc loc, Scope *sc)
 {
     //printf("+trySemantic(%s) %d\n", toChars(), global.errors);
     unsigned errors = global.startGagging();
-    Type *t = semantic(loc, sc);
+    Type *t = typeSemantic(this, loc, sc);
     if (global.endGagging(errors) || t->ty == Terror)        // if any errors happened
     {
         t = NULL;
@@ -2070,7 +2055,7 @@ Expression *Type::getProperty(Loc loc, Identifier *ident, int flag)
         {
             e = new StringExp(loc, (char *)deco, strlen(deco));
             Scope sc;
-            e = ::semantic(e, &sc);
+            e = expressionSemantic(e, &sc);
         }
     }
     else if (ident == Id::stringof)
@@ -2078,7 +2063,7 @@ Expression *Type::getProperty(Loc loc, Identifier *ident, int flag)
         const char *s = toChars();
         e = new StringExp(loc, const_cast<char *>(s), strlen(s));
         Scope sc;
-        e = ::semantic(e, &sc);
+        e = expressionSemantic(e, &sc);
     }
     else if (flag && this != Type::terror)
     {
@@ -2094,9 +2079,9 @@ Expression *Type::getProperty(Loc loc, Identifier *ident, int flag)
         if (this != Type::terror)
         {
             if (s)
-                error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident->toChars(), toChars(), s->toChars());
+                error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident->toChars(), toChars(), s->toChars());
             else
-                error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
+                error(loc, "no property `%s` for type `%s`", ident->toChars(), toChars());
         }
         e = new ErrorExp();
     }
@@ -2164,7 +2149,7 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
 
 Lreturn:
     if (e)
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
     return e;
 }
 
@@ -2223,7 +2208,7 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident, int flag
              */
             e = build_overload(e->loc, sc, e, NULL, fd);
             e = new DotIdExp(e->loc, e, ident);
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             --nest;
             return e;
         }
@@ -2442,7 +2427,7 @@ TypeFunction *Type::toTypeFunction()
 void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool)
 {
     //printf("Type::resolve() %s, %d\n", toChars(), ty);
-    Type *t = semantic(loc, sc);
+    Type *t = typeSemantic(this, loc, sc);
     *pt = t;
     *pe = NULL;
     *ps = NULL;
@@ -3576,7 +3561,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident, int f
         return Type::dotExp(sc, e, ident, flag);
     }
     if (!(flag & 1) || e)
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
     return e;
 }
 
@@ -3803,39 +3788,6 @@ Type *TypeVector::syntaxCopy()
     return new TypeVector(basetype->syntaxCopy());
 }
 
-Type *TypeVector::semantic(Loc loc, Scope *sc)
-{
-    unsigned int errors = global.errors;
-    basetype = basetype->semantic(loc, sc);
-    if (errors != global.errors)
-        return terror;
-    basetype = basetype->toBasetype()->mutableOf();
-    if (basetype->ty != Tsarray)
-    {
-        error(loc, "T in __vector(T) must be a static array, not %s", basetype->toChars());
-        return terror;
-    }
-    TypeSArray *t = (TypeSArray *)basetype;
-    int sz = (int)t->size(loc);
-    switch (target.isVectorTypeSupported(sz, t->nextOf()))
-    {
-    case 0: // valid
-        break;
-    case 1: // no support at all
-        error(loc, "SIMD vector types not supported on this platform");
-        return terror;
-    case 2: // invalid base type
-        error(loc, "vector type %s is not supported on this platform", toChars());
-        return terror;
-    case 3: // invalid size
-        error(loc, "%d byte vector type %s is not supported on this platform", sz, toChars());
-        return terror;
-    default:
-        assert(0);
-    }
-    return merge();
-}
-
 TypeBasic *TypeVector::elementType()
 {
     assert(basetype->ty == Tsarray);
@@ -3873,7 +3825,7 @@ Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident, int
          * __vector(float[4]), and a type paint won't do.
          */
         e = new AddrExp(e->loc, e);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         e = e->castTo(sc, basetype->nextOf()->pointerTo());
         return e;
     }
@@ -3882,7 +3834,7 @@ Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident, int
         //e = e->castTo(sc, basetype);
         // Keep lvalue-ness
         e = new VectorArrayExp(e->loc, e);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
     if (ident == Id::_init || ident == Id::offsetof || ident == Id::stringof || ident == Id::__xalignof)
@@ -3984,7 +3936,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int f
     e = Type::dotExp(sc, e, ident, flag);
 
     if (!(flag & 1) || e)
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
     return e;
 }
 
@@ -4033,48 +3985,6 @@ unsigned TypeSArray::alignsize()
     return next->alignsize();
 }
 
-/**************************
- * This evaluates exp while setting length to be the number
- * of elements in the tuple t.
- */
-Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
-{
-    if (t->ty == Ttuple)
-    {
-        ScopeDsymbol *sym = new ArrayScopeSymbol(sc, (TypeTuple *)t);
-        sym->parent = sc->scopesym;
-        sc = sc->push(sym);
-
-        sc = sc->startCTFE();
-        exp = ::semantic(exp, sc);
-        sc = sc->endCTFE();
-
-        sc->pop();
-    }
-    else
-    {
-        sc = sc->startCTFE();
-        exp = ::semantic(exp, sc);
-        sc = sc->endCTFE();
-    }
-
-    return exp;
-}
-
-Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
-{
-    ScopeDsymbol *sym = new ArrayScopeSymbol(sc, s);
-    sym->parent = sc->scopesym;
-    sc = sc->push(sym);
-
-    sc = sc->startCTFE();
-    exp = ::semantic(exp, sc);
-    sc = sc->endCTFE();
-
-    sc->pop();
-    return exp;
-}
-
 void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
 {
     //printf("TypeSArray::resolve() %s\n", toChars());
@@ -4097,7 +4007,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
             sym->parent = sc->scopesym;
             sc = sc->push(sym);
             sc = sc->startCTFE();
-            dim = ::semantic(dim, sc);
+            dim = expressionSemantic(dim, sc);
             sc = sc->endCTFE();
             sc = sc->pop();
 
@@ -4163,140 +4073,6 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
     }
 }
 
-Type *TypeSArray::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypeSArray::semantic() %s\n", toChars());
-
-    Type *t;
-    Expression *e;
-    Dsymbol *s;
-    next->resolve(loc, sc, &e, &t, &s);
-    if (dim && s && s->isTupleDeclaration())
-    {   TupleDeclaration *sd = s->isTupleDeclaration();
-
-        dim = semanticLength(sc, sd, dim);
-        dim = dim->ctfeInterpret();
-        uinteger_t d = dim->toUInteger();
-
-        if (d >= sd->objects->length)
-        {   error(loc, "tuple index %llu exceeds %u", d, sd->objects->length);
-            return Type::terror;
-        }
-        RootObject *o = (*sd->objects)[(size_t)d];
-        if (o->dyncast() != DYNCAST_TYPE)
-        {   error(loc, "%s is not a type", toChars());
-            return Type::terror;
-        }
-        t = ((Type *)o)->addMod(this->mod);
-        return t;
-    }
-
-    Type *tn = next->semantic(loc, sc);
-    if (tn->ty == Terror)
-        return terror;
-
-    Type *tbn = tn->toBasetype();
-
-    if (dim)
-    {
-        unsigned int errors = global.errors;
-        dim = semanticLength(sc, tbn, dim);
-        if (errors != global.errors)
-            goto Lerror;
-
-        dim = dim->optimize(WANTvalue);
-        dim = dim->ctfeInterpret();
-        if (dim->op == TOKerror)
-            goto Lerror;
-        errors = global.errors;
-        dinteger_t d1 = dim->toInteger();
-        if (errors != global.errors)
-            goto Lerror;
-
-        dim = dim->implicitCastTo(sc, tsize_t);
-        dim = dim->optimize(WANTvalue);
-        if (dim->op == TOKerror)
-            goto Lerror;
-        errors = global.errors;
-        dinteger_t d2 = dim->toInteger();
-        if (errors != global.errors)
-            goto Lerror;
-
-        if (dim->op == TOKerror)
-            goto Lerror;
-
-        if (d1 != d2)
-        {
-        Loverflow:
-            error(loc, "%s size %llu * %llu exceeds 0x%llx size limit for static array",
-                toChars(), (unsigned long long)tbn->size(loc), (unsigned long long)d1, target.maxStaticDataSize);
-            goto Lerror;
-        }
-
-        Type *tbx = tbn->baseElemOf();
-        if ((tbx->ty == Tstruct && !((TypeStruct *)tbx)->sym->members) ||
-            (tbx->ty == Tenum && !((TypeEnum *)tbx)->sym->members))
-        {
-            /* To avoid meaningless error message, skip the total size limit check
-             * when the bottom of element type is opaque.
-             */
-        }
-        else if (tbn->isTypeBasic() ||
-                 tbn->ty == Tpointer ||
-                 tbn->ty == Tarray ||
-                 tbn->ty == Tsarray ||
-                 tbn->ty == Taarray ||
-                 (tbn->ty == Tstruct && (((TypeStruct *)tbn)->sym->sizeok == SIZEOKdone)) ||
-                 tbn->ty == Tclass)
-        {
-            /* Only do this for types that don't need to have semantic()
-             * run on them for the size, since they may be forward referenced.
-             */
-            bool overflow = false;
-            if (mulu(tbn->size(loc), d2, overflow) >= target.maxStaticDataSize || overflow)
-                goto Loverflow;
-        }
-    }
-    switch (tbn->ty)
-    {
-        case Ttuple:
-        {   // Index the tuple to get the type
-            assert(dim);
-            TypeTuple *tt = (TypeTuple *)tbn;
-            uinteger_t d = dim->toUInteger();
-
-            if (d >= tt->arguments->length)
-            {   error(loc, "tuple index %llu exceeds %u", d, tt->arguments->length);
-                goto Lerror;
-            }
-            Type *telem = (*tt->arguments)[(size_t)d]->type;
-            return telem->addMod(this->mod);
-        }
-        case Tfunction:
-        case Tnone:
-            error(loc, "can't have array of %s", tbn->toChars());
-            goto Lerror;
-        default:
-            break;
-    }
-    if (tbn->isscope())
-    {   error(loc, "cannot have array of scope %s", tbn->toChars());
-        goto Lerror;
-    }
-
-    /* Ensure things like const(immutable(T)[3]) become immutable(T[3])
-     * and const(T)[3] become const(T[3])
-     */
-    next = tn;
-    transitive();
-    t = addMod(tn->mod);
-
-    return t->merge();
-
-Lerror:
-    return Type::terror;
-}
-
 Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
 {
     if (ident == Id::length)
@@ -4324,7 +4100,7 @@ Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int
         e = TypeArray::dotExp(sc, e, ident, flag);
     }
     if (!(flag & 1) || e)
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
     return e;
 }
 
@@ -4502,32 +4278,6 @@ unsigned TypeDArray::alignsize()
     return target.ptrsize;
 }
 
-Type *TypeDArray::semantic(Loc loc, Scope *sc)
-{
-    Type *tn = next->semantic(loc,sc);
-    Type *tbn = tn->toBasetype();
-    switch (tbn->ty)
-    {
-        case Ttuple:
-            return tbn;
-        case Tfunction:
-        case Tnone:
-            error(loc, "can't have array of %s", tbn->toChars());
-            return Type::terror;
-        case Terror:
-            return Type::terror;
-        default:
-            break;
-    }
-    if (tn->isscope())
-    {   error(loc, "cannot have array of scope %s", tn->toChars());
-        return Type::terror;
-    }
-    next = tn;
-    transitive();
-    return merge();
-}
-
 void TypeDArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
 {
     //printf("TypeDArray::resolve() %s\n", toChars());
@@ -4694,188 +4444,6 @@ d_uns64 TypeAArray::size(Loc)
     return target.ptrsize;
 }
 
-Type *TypeAArray::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
-    if (deco)
-        return this;
-
-    this->loc = loc;
-    this->sc = sc;
-    if (sc)
-        sc->setNoFree();
-
-    // Deal with the case where we thought the index was a type, but
-    // in reality it was an expression.
-    if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray ||
-        index->ty == Ttypeof || index->ty == Treturn)
-    {
-        Expression *e;
-        Type *t;
-        Dsymbol *s;
-
-        index->resolve(loc, sc, &e, &t, &s);
-        if (e)
-        {
-            // It was an expression -
-            // Rewrite as a static array
-            TypeSArray *tsa = new TypeSArray(next, e);
-            return tsa->semantic(loc, sc);
-        }
-        else if (t)
-            index = t->semantic(loc, sc);
-        else
-        {
-            index->error(loc, "index is not a type or an expression");
-            return Type::terror;
-        }
-    }
-    else
-        index = index->semantic(loc,sc);
-    index = index->merge2();
-
-    if (index->nextOf() && !index->nextOf()->isImmutable())
-    {
-        index = index->constOf()->mutableOf();
-    }
-
-    switch (index->toBasetype()->ty)
-    {
-        case Tfunction:
-        case Tvoid:
-        case Tnone:
-        case Ttuple:
-            error(loc, "can't have associative array key of %s", index->toBasetype()->toChars());
-            /* fall through */
-        case Terror:
-            return Type::terror;
-        default:
-            break;
-    }
-    Type *tbase = index->baseElemOf();
-    while (tbase->ty == Tarray)
-        tbase = tbase->nextOf()->baseElemOf();
-    if (tbase->ty == Tstruct)
-    {
-        /* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up.
-         */
-        StructDeclaration *sd = ((TypeStruct *)tbase)->sym;
-        if (sd->semanticRun < PASSsemanticdone)
-            sd->semantic(NULL);
-
-        // duplicate a part of StructDeclaration::semanticTypeInfoMembers
-        //printf("AA = %s, key: xeq = %p, xerreq = %p xhash = %p\n", toChars(), sd->xeq, sd->xerreq, sd->xhash);
-        if (sd->xeq &&
-            sd->xeq->_scope &&
-            sd->xeq->semanticRun < PASSsemantic3done)
-        {
-            unsigned errors = global.startGagging();
-            sd->xeq->semantic3(sd->xeq->_scope);
-            if (global.endGagging(errors))
-                sd->xeq = sd->xerreq;
-        }
-
-        const char *s = (index->toBasetype()->ty != Tstruct) ? "bottom of " : "";
-        if (!sd->xeq)
-        {
-            // If sd->xhash != NULL:
-            //   sd or its fields have user-defined toHash.
-            //   AA assumes that its result is consistent with bitwise equality.
-            // else:
-            //   bitwise equality & hashing
-        }
-        else if (sd->xeq == sd->xerreq)
-        {
-            if (search_function(sd, Id::eq))
-            {
-                error(loc, "%sAA key type %s does not have 'bool opEquals(ref const %s) const'",
-                        s, sd->toChars(), sd->toChars());
-            }
-            else
-            {
-                error(loc, "%sAA key type %s does not support const equality",
-                        s, sd->toChars());
-            }
-            return Type::terror;
-        }
-        else if (!sd->xhash)
-        {
-            if (search_function(sd, Id::eq))
-            {
-                error(loc, "%sAA key type %s should have 'size_t toHash() const nothrow @safe' if opEquals defined",
-                        s, sd->toChars());
-            }
-            else
-            {
-                error(loc, "%sAA key type %s supports const equality but doesn't support const hashing",
-                        s, sd->toChars());
-            }
-            return Type::terror;
-        }
-        else
-        {
-            // defined equality & hashing
-            assert(sd->xeq && sd->xhash);
-
-            /* xeq and xhash may be implicitly defined by compiler. For example:
-             *   struct S { int[] arr; }
-             * With 'arr' field equality and hashing, compiler will implicitly
-             * generate functions for xopEquals and xtoHash in TypeInfo_Struct.
-             */
-        }
-    }
-    else if (tbase->ty == Tclass && !((TypeClass *)tbase)->sym->isInterfaceDeclaration())
-    {
-        ClassDeclaration *cd = ((TypeClass *)tbase)->sym;
-        if (cd->semanticRun < PASSsemanticdone)
-            cd->semantic(NULL);
-
-        if (!ClassDeclaration::object)
-        {
-            error(Loc(), "missing or corrupt object.d");
-            fatal();
-        }
-
-        static FuncDeclaration *feq   = NULL;
-        static FuncDeclaration *fcmp  = NULL;
-        static FuncDeclaration *fhash = NULL;
-        if (!feq)   feq   = search_function(ClassDeclaration::object, Id::eq)->isFuncDeclaration();
-        if (!fcmp)  fcmp  = search_function(ClassDeclaration::object, Id::cmp)->isFuncDeclaration();
-        if (!fhash) fhash = search_function(ClassDeclaration::object, Id::tohash)->isFuncDeclaration();
-        assert(fcmp && feq && fhash);
-
-        if (feq->vtblIndex < (int)cd->vtbl.length && cd->vtbl[feq ->vtblIndex] == feq)
-        {
-            if (fcmp->vtblIndex < (int)cd->vtbl.length && cd->vtbl[fcmp->vtblIndex] != fcmp)
-            {
-                const char *s = (index->toBasetype()->ty != Tclass) ? "bottom of " : "";
-                error(loc, "%sAA key type %s now requires equality rather than comparison",
-                    s, cd->toChars());
-                errorSupplemental(loc, "Please override Object.opEquals and toHash.");
-            }
-        }
-    }
-    next = next->semantic(loc,sc)->merge2();
-    transitive();
-
-    switch (next->toBasetype()->ty)
-    {
-        case Tfunction:
-        case Tvoid:
-        case Tnone:
-        case Ttuple:
-            error(loc, "can't have associative array of %s", next->toChars());
-            /* fall through */
-        case Terror:
-            return Type::terror;
-    }
-    if (next->isscope())
-    {   error(loc, "cannot have array of scope %s", next->toChars());
-        return Type::terror;
-    }
-    return merge();
-}
-
 void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
 {
     //printf("TypeAArray::resolve() %s\n", toChars());
@@ -5018,40 +4586,6 @@ Type *TypePointer::syntaxCopy()
     return t;
 }
 
-Type *TypePointer::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypePointer::semantic() %s\n", toChars());
-    if (deco)
-        return this;
-    Type *n = next->semantic(loc, sc);
-    switch (n->toBasetype()->ty)
-    {
-        case Ttuple:
-            error(loc, "can't have pointer to %s", n->toChars());
-            /* fall through */
-        case Terror:
-            return Type::terror;
-        default:
-            break;
-    }
-    if (n != next)
-    {
-        deco = NULL;
-    }
-    next = n;
-    if (next->ty != Tfunction)
-    {   transitive();
-        return merge();
-    }
-    deco = merge()->deco;
-    /* Don't return merge(), because arg identifiers and default args
-     * can be different
-     * even though the types match
-     */
-    return this;
-}
-
-
 d_uns64 TypePointer::size(Loc)
 {
     return target.ptrsize;
@@ -5184,18 +4718,6 @@ Type *TypeReference::syntaxCopy()
     return t;
 }
 
-Type *TypeReference::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypeReference::semantic()\n");
-    Type *n = next->semantic(loc, sc);
-    if (n != next)
-        deco = NULL;
-    next = n;
-    transitive();
-    return merge();
-}
-
-
 d_uns64 TypeReference::size(Loc)
 {
     return target.ptrsize;
@@ -5425,7 +4947,7 @@ int Type::covariant(Type *t, StorageClass *pstc, bool fix17349)
         // If t1n is forward referenced:
         ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
         if (cd->semanticRun < PASSsemanticdone && !cd->isBaseInfoComplete())
-            cd->semantic(NULL);
+            dsymbolSemantic(cd, NULL);
         if (!cd->isBaseInfoComplete())
         {
             return 3;   // forward references
@@ -5524,379 +5046,6 @@ Lnotcovariant:
     return 2;
 }
 
-Type *TypeFunction::semantic(Loc loc, Scope *sc)
-{
-    if (deco)                   // if semantic() already run
-    {
-        //printf("already done\n");
-        return this;
-    }
-    //printf("TypeFunction::semantic() this = %p\n", this);
-    //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs);
-
-    bool errors = false;
-
-    if (inuse > global.recursionLimit)
-    {
-        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.
-     */
-    TypeFunction *tf = copy()->toTypeFunction();
-    if (parameterList.parameters)
-    {
-        tf->parameterList.parameters = parameterList.parameters->copy();
-        for (size_t i = 0; i < parameterList.parameters->length; i++)
-        {
-            void *pp = mem.xmalloc(sizeof(Parameter));
-            Parameter *p = (Parameter *)memcpy(pp, (void *)(*parameterList.parameters)[i],
-                                               sizeof(Parameter));
-            (*tf->parameterList.parameters)[i] = p;
-        }
-    }
-
-    if (sc->stc & STCpure)
-        tf->purity = PUREfwdref;
-    if (sc->stc & STCnothrow)
-        tf->isnothrow = true;
-    if (sc->stc & STCnogc)
-        tf->isnogc = true;
-    if (sc->stc & STCref)
-        tf->isref = true;
-    if (sc->stc & STCreturn)
-        tf->isreturn = true;
-    if (sc->stc & STCscope)
-        tf->isscope = true;
-    if (sc->stc & STCscopeinferred)
-        tf->isscopeinferred = true;
-
-//    if ((sc->stc & (STCreturn | STCref)) == STCreturn)
-//        tf->isscope = true;                                 // return by itself means 'return scope'
-
-    if (tf->trust == TRUSTdefault)
-    {
-        if (sc->stc & STCsafe)
-            tf->trust = TRUSTsafe;
-        if (sc->stc & STCsystem)
-            tf->trust = TRUSTsystem;
-        if (sc->stc & STCtrusted)
-            tf->trust = TRUSTtrusted;
-    }
-
-    if (sc->stc & STCproperty)
-        tf->isproperty = true;
-
-    tf->linkage = sc->linkage;
-    bool wildreturn = false;
-    if (tf->next)
-    {
-        sc = sc->push();
-        sc->stc &= ~(STC_TYPECTOR | STC_FUNCATTR);
-        tf->next = tf->next->semantic(loc, sc);
-        sc = sc->pop();
-        errors |= tf->checkRetType(loc);
-        if (tf->next->isscope() && !(sc->flags & SCOPEctor))
-        {
-            error(loc, "functions cannot return scope %s", tf->next->toChars());
-            errors = true;
-        }
-        if (tf->next->hasWild())
-            wildreturn = true;
-
-        if (tf->isreturn && !tf->isref && !tf->next->hasPointers())
-        {
-            error(loc, "function type '%s' has 'return' but does not return any indirections", tf->toChars());
-        }
-    }
-
-    unsigned char wildparams = 0;
-    if (tf->parameterList.parameters)
-    {
-        /* Create a scope for evaluating the default arguments for the parameters
-         */
-        Scope *argsc = sc->push();
-        argsc->stc = 0;                 // don't inherit storage class
-        argsc->protection = Prot(Prot::public_);
-        argsc->func = NULL;
-
-        size_t dim = tf->parameterList.length();
-        for (size_t i = 0; i < dim; i++)
-        {
-            Parameter *fparam = tf->parameterList[i];
-            inuse++;
-            fparam->type = fparam->type->semantic(loc, argsc);
-            inuse--;
-
-            if (fparam->type->ty == Terror)
-            {
-                errors = true;
-                continue;
-            }
-
-            fparam->type = fparam->type->addStorageClass(fparam->storageClass);
-
-            if (fparam->storageClass & (STCauto | STCalias | STCstatic))
-            {
-                if (!fparam->type)
-                    continue;
-            }
-
-            Type *t = fparam->type->toBasetype();
-
-            if (t->ty == Tfunction)
-            {
-                error(loc, "cannot have parameter of function type %s", fparam->type->toChars());
-                errors = true;
-            }
-            else if (!(fparam->storageClass & (STCref | STCout)) &&
-                     (t->ty == Tstruct || t->ty == Tsarray || t->ty == Tenum))
-            {
-                Type *tb2 = t->baseElemOf();
-                if ((tb2->ty == Tstruct && !((TypeStruct *)tb2)->sym->members) ||
-                    (tb2->ty == Tenum && !((TypeEnum *)tb2)->sym->memtype))
-                {
-                    error(loc, "cannot have parameter of opaque type %s by value", fparam->type->toChars());
-                    errors = true;
-                }
-            }
-            else if (!(fparam->storageClass & STClazy) && t->ty == Tvoid)
-            {
-                error(loc, "cannot have parameter of type %s", fparam->type->toChars());
-                errors = true;
-            }
-
-            if ((fparam->storageClass & (STCref | STCwild)) == (STCref | STCwild))
-            {
-                // 'ref inout' implies 'return'
-                fparam->storageClass |= STCreturn;
-            }
-
-            if (fparam->storageClass & STCreturn)
-            {
-                if (fparam->storageClass & (STCref | STCout))
-                {
-                    // Disabled for the moment awaiting improvement to allow return by ref
-                    // to be transformed into return by scope.
-                    if (0 && !tf->isref)
-                    {
-                        StorageClass stc = fparam->storageClass & (STCref | STCout);
-                        error(loc, "parameter %s is 'return %s' but function does not return by ref",
-                            fparam->ident ? fparam->ident->toChars() : "",
-                            stcToChars(stc));
-                        errors = true;
-                    }
-                }
-                else
-                {
-                    fparam->storageClass |= STCscope;        // 'return' implies 'scope'
-                    if (tf->isref)
-                    {
-                    }
-                    else if (!tf->isref && tf->next && !tf->next->hasPointers())
-                    {
-                        error(loc, "parameter %s is 'return' but function does not return any indirections",
-                            fparam->ident ? fparam->ident->toChars() : "");
-                        errors = true;
-                    }
-                }
-            }
-
-            if (fparam->storageClass & (STCref | STClazy))
-            {
-            }
-            else if (fparam->storageClass & STCout)
-            {
-                if (unsigned char m = fparam->type->mod & (MODimmutable | MODconst | MODwild))
-                {
-                    error(loc, "cannot have %s out parameter of type %s", MODtoChars(m), t->toChars());
-                    errors = true;
-                }
-                else
-                {
-                    Type *tv = t;
-                    while (tv->ty == Tsarray)
-                        tv = tv->nextOf()->toBasetype();
-                    if (tv->ty == Tstruct && ((TypeStruct *)tv)->sym->noDefaultCtor)
-                    {
-                        error(loc, "cannot have out parameter of type %s because the default construction is disabled",
-                            fparam->type->toChars());
-                        errors = true;
-                    }
-                }
-            }
-
-            if (fparam->storageClass & STCscope && !fparam->type->hasPointers() && fparam->type->ty != Ttuple)
-            {
-                fparam->storageClass &= ~STCscope;
-                if (!(fparam->storageClass & STCref))
-                    fparam->storageClass &= ~STCreturn;
-            }
-
-            if (t->hasWild())
-            {
-                wildparams |= 1;
-                //if (tf->next && !wildreturn)
-                //    error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')");
-            }
-
-            if (fparam->defaultArg)
-            {
-                Expression *e = fparam->defaultArg;
-                if (fparam->storageClass & (STCref | STCout))
-                {
-                    e = ::semantic(e, argsc);
-                    e = resolveProperties(argsc, e);
-                }
-                else
-                {
-                    e = inferType(e, fparam->type);
-                    Initializer *iz = new ExpInitializer(e->loc, e);
-                    iz = ::semantic(iz, argsc, fparam->type, INITnointerpret);
-                    e = initializerToExpression(iz);
-                }
-                if (e->op == TOKfunction)               // see Bugzilla 4820
-                {
-                    FuncExp *fe = (FuncExp *)e;
-                    // Replace function literal with a function symbol,
-                    // since default arg expression must be copied when used
-                    // and copying the literal itself is wrong.
-                    e = new VarExp(e->loc, fe->fd, false);
-                    e = new AddrExp(e->loc, e);
-                    e = ::semantic(e, argsc);
-                }
-                e = e->implicitCastTo(argsc, fparam->type);
-
-                // default arg must be an lvalue
-                if (fparam->storageClass & (STCout | STCref))
-                    e = e->toLvalue(argsc, e);
-
-                fparam->defaultArg = e;
-                if (e->op == TOKerror)
-                    errors = true;
-            }
-
-            /* If fparam after semantic() turns out to be a tuple, the number of parameters may
-             * change.
-             */
-            if (t->ty == Ttuple)
-            {
-                /* TypeFunction::parameter also is used as the storage of
-                 * Parameter objects for FuncDeclaration. So we should copy
-                 * the elements of TypeTuple::arguments to avoid unintended
-                 * sharing of Parameter object among other functions.
-                 */
-                TypeTuple *tt = (TypeTuple *)t;
-                if (tt->arguments && tt->arguments->length)
-                {
-                    /* Propagate additional storage class from tuple parameters to their
-                     * element-parameters.
-                     * Make a copy, as original may be referenced elsewhere.
-                     */
-                    size_t tdim = tt->arguments->length;
-                    Parameters *newparams = new Parameters();
-                    newparams->setDim(tdim);
-                    for (size_t j = 0; j < tdim; j++)
-                    {
-                        Parameter *narg = (*tt->arguments)[j];
-
-                        // Bugzilla 12744: If the storage classes of narg
-                        // conflict with the ones in fparam, it's ignored.
-                        StorageClass stc  = fparam->storageClass | narg->storageClass;
-                        StorageClass stc1 = fparam->storageClass & (STCref | STCout | STClazy);
-                        StorageClass stc2 =   narg->storageClass & (STCref | STCout | STClazy);
-                        if (stc1 && stc2 && stc1 != stc2)
-                        {
-                            OutBuffer buf1;  stcToBuffer(&buf1, stc1 | ((stc1 & STCref) ? (fparam->storageClass & STCauto) : 0));
-                            OutBuffer buf2;  stcToBuffer(&buf2, stc2);
-
-                            error(loc, "incompatible parameter storage classes '%s' and '%s'",
-                                      buf1.peekChars(), buf2.peekChars());
-                            errors = true;
-                            stc = stc1 | (stc & ~(STCref | STCout | STClazy));
-                        }
-
-                        (*newparams)[j] = new Parameter(
-                                stc, narg->type, narg->ident, narg->defaultArg, narg->userAttribDecl);
-                    }
-                    fparam->type = new TypeTuple(newparams);
-                }
-                fparam->storageClass = 0;
-
-                /* Reset number of parameters, and back up one to do this fparam again,
-                 * now that it is a tuple
-                 */
-                dim = tf->parameterList.length();
-                i--;
-                continue;
-            }
-
-            /* Resolve "auto ref" storage class to be either ref or value,
-             * based on the argument matching the parameter
-             */
-            if (fparam->storageClass & STCauto)
-            {
-                if (fargs && i < fargs->length && (fparam->storageClass & STCref))
-                {
-                    Expression *farg = (*fargs)[i];
-                    if (farg->isLvalue())
-                        ;                               // ref parameter
-                    else
-                        fparam->storageClass &= ~STCref;        // value parameter
-                    fparam->storageClass &= ~STCauto;    // Bugzilla 14656
-                    fparam->storageClass |= STCautoref;
-                }
-                else
-                {
-                    error(loc, "'auto' can only be used as part of 'auto ref' for template function parameters");
-                    errors = true;
-                }
-            }
-
-            // Remove redundant storage classes for type, they are already applied
-            fparam->storageClass &= ~(STC_TYPECTOR | STCin);
-        }
-        argsc->pop();
-    }
-    if (tf->isWild())
-        wildparams |= 2;
-
-    if (wildreturn && !wildparams)
-    {
-        error(loc, "inout on return means inout must be on a parameter as well for %s", toChars());
-        errors = true;
-    }
-    tf->iswild = wildparams;
-
-    if (tf->isproperty && (tf->parameterList.varargs != VARARGnone || tf->parameterList.length() > 2))
-    {
-        error(loc, "properties can only have zero, one, or two parameter");
-        errors = true;
-    }
-
-    if (tf->parameterList.varargs == VARARGvariadic && tf->linkage != LINKd && tf->parameterList.length() == 0)
-    {
-        error(loc, "variadic functions with non-D linkage must have at least one parameter");
-        errors = true;
-    }
-
-    if (errors)
-        return terror;
-
-    if (tf->next)
-        tf->deco = tf->merge()->deco;
-
-    /* Don't return merge(), because arg identifiers and default args
-     * can be different
-     * even though the types match
-     */
-    return tf;
-}
-
 bool TypeFunction::checkRetType(Loc loc)
 {
     Type *tb = next->toBasetype();
@@ -6525,30 +5674,6 @@ Type *TypeDelegate::syntaxCopy()
     return t;
 }
 
-Type *TypeDelegate::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypeDelegate::semantic() %s\n", toChars());
-    if (deco)                   // if semantic() already run
-    {
-        //printf("already done\n");
-        return this;
-    }
-    next = next->semantic(loc,sc);
-    if (next->ty != Tfunction)
-        return terror;
-
-    /* In order to deal with Bugzilla 4028, perhaps default arguments should
-     * be removed from next before the merge.
-     */
-
-    /* Don't return merge(), because arg identifiers and default args
-     * can be different
-     * even though the types match
-     */
-    deco = merge()->deco;
-    return this;
-}
-
 Type *TypeDelegate::addStorageClass(StorageClass stc)
 {
     TypeDelegate *t = (TypeDelegate*)Type::addStorageClass(stc);
@@ -6630,7 +5755,7 @@ Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident, in
     if (ident == Id::ptr)
     {
         e = new DelegatePtrExp(e->loc, e);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
     }
     else if (ident == Id::funcptr)
     {
@@ -6640,7 +5765,7 @@ Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident, in
             return new ErrorExp();
         }
         e = new DelegateFuncptrExp(e->loc, e);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
     }
     else
     {
@@ -6672,128 +5797,13 @@ Type *TypeTraits::syntaxCopy()
     return tt;
 }
 
-Type *TypeTraits::semantic(Loc, Scope *sc)
-{
-    if (ty == Terror)
-        return this;
-
-    const int inAlias = (sc->flags & SCOPEalias) != 0;
-    if (exp->ident != Id::allMembers &&
-        exp->ident != Id::derivedMembers &&
-        exp->ident != Id::getMember &&
-        exp->ident != Id::parent &&
-        exp->ident != Id::child &&
-        exp->ident != Id::getOverloads &&
-        exp->ident != Id::getVirtualFunctions &&
-        exp->ident != Id::getVirtualMethods &&
-        exp->ident != Id::getAttributes &&
-        exp->ident != Id::getUnitTests &&
-        exp->ident != Id::getAliasThis)
-    {
-        static const char *ctxt[2] = {"as type", "in alias"};
-        ::error(loc, "trait `%s` is either invalid or not supported %s",
-                exp->ident->toChars(), ctxt[inAlias]);
-        ty = Terror;
-        return this;
-    }
-
-    Type *result = NULL;
-
-    if (Expression *e = semanticTraits(exp, sc))
-    {
-        switch (e->op)
-        {
-        case TOKdotvar:
-            sym = ((DotVarExp *)e)->var;
-            break;
-        case TOKvar:
-            sym = ((VarExp *)e)->var;
-            break;
-        case TOKfunction:
-        {
-            FuncExp *fe = (FuncExp *)e;
-            if (fe->td)
-                sym = fe->td;
-            else
-                sym = fe->fd;
-            break;
-        }
-        case TOKdottd:
-            sym = ((DotTemplateExp*)e)->td;
-            break;
-        case TOKdsymbol:
-            sym = ((DsymbolExp *)e)->s;
-            break;
-        case TOKtemplate:
-            sym = ((TemplateExp *)e)->td;
-            break;
-        case TOKscope:
-            sym = ((ScopeExp *)e)->sds;
-            break;
-        case TOKtuple:
-        {
-            TupleExp *te = e->toTupleExp();
-            Objects *elems = new Objects;
-            elems->setDim(te->exps->length);
-            for (size_t i = 0; i < elems->length; i++)
-            {
-                Expression *src = (*te->exps)[i];
-                switch (src->op)
-                {
-                case TOKtype:
-                    (*elems)[i] = ((TypeExp *)src)->type;
-                    break;
-                case TOKdottype:
-                    (*elems)[i] = ((DotTypeExp *)src)->type;
-                    break;
-                case TOKoverloadset:
-                    (*elems)[i] = ((OverExp *)src)->type;
-                    break;
-                default:
-                    if (Dsymbol *sym = isDsymbol(src))
-                        (*elems)[i] = sym;
-                    else
-                        (*elems)[i] = src;
-                }
-            }
-            TupleDeclaration *td = new TupleDeclaration(e->loc,
-                Identifier::generateId("__aliastup"), elems);
-            sym = td;
-            break;
-        }
-        case TOKdottype:
-            result = isType(((DotTypeExp *)e)->sym);
-            break;
-        case TOKtype:
-            result = ((TypeExp *)e)->type;
-            break;
-        case TOKoverloadset:
-            result = ((OverExp *)e)->type;
-            break;
-        default:
-            break;
-        }
-    }
-
-    if (result)
-        result = result->addMod(mod);
-    if (!inAlias && !result)
-    {
-        if (!global.errors)
-            ::error(loc, "`%s` does not give a valid type", toChars());
-        return Type::terror;
-    }
-
-    return result;
-}
-
 void TypeTraits::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool)
 {
     *pt = NULL;
     *pe = NULL;
     *ps = NULL;
 
-    if (Type *t = semantic(loc, sc))
+    if (Type *t = typeSemantic(this, loc, sc))
         *pt = t;
     else if (sym)
         *ps = sym;
@@ -6889,7 +5899,7 @@ void TypeQualified::resolveTupleIndex(Loc loc, Scope *sc, Dsymbol *s,
         else if (sindex)
             eindex = ::resolve(loc, sc, sindex, false);
         Expression *e = new IndexExp(loc, ::resolve(loc, sc, s, false), eindex);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         resolveExp(e, pt, pe, ps);
         return;
     }
@@ -6906,7 +5916,7 @@ void TypeQualified::resolveTupleIndex(Loc loc, Scope *sc, Dsymbol *s,
         return;
     }
     sc = sc->startCTFE();
-    eindex = ::semantic(eindex, sc);
+    eindex = expressionSemantic(eindex, sc);
     sc = sc->endCTFE();
 
     eindex = eindex->ctfeInterpret();
@@ -6930,7 +5940,7 @@ void TypeQualified::resolveTupleIndex(Loc loc, Scope *sc, Dsymbol *s,
     *pe = isExpression(o);
 
     if (*pt)
-        *pt = (*pt)->semantic(loc, sc);
+        *pt = typeSemantic(*pt, loc, sc);
     if (*pe)
         resolveExp(*pe, pt, pe, ps);
 }
@@ -6986,7 +5996,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
                 assert(ex);
 
                 ex = typeToExpressionHelper(this, ex, i + 1);
-                ex = ::semantic(ex, sc);
+                ex = expressionSemantic(ex, sc);
                 resolveExp(ex, pt, pe, ps);
                 return;
             }
@@ -7012,7 +6022,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
                 // https://issues.dlang.org/show_bug.cgi?id=19913
                 // v->type would be null if it is a forward referenced member.
                 if (v->type == NULL)
-                    v->semantic(sc);
+                    dsymbolSemantic(v, sc);
                 if (v->storage_class & (STCconst | STCimmutable | STCmanifest) ||
                     v->type->isConst() || v->type->isImmutable())
                 {
@@ -7056,7 +6066,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
                         e = new VarExp(loc, s->isDeclaration(), true);
 
                     e = typeToExpressionHelper(this, e, i);
-                    e = ::semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     resolveExp(e, pt, pe, ps);
                     return;
                 }
@@ -7072,10 +6082,10 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
                         assert(id->dyncast() == DYNCAST_IDENTIFIER);
                         sm = s->search_correct((Identifier *)id);
                         if (sm)
-                            error(loc, "identifier '%s' of '%s' is not defined, did you mean %s '%s'?",
+                            error(loc, "identifier `%s` of `%s` is not defined, did you mean %s `%s`?",
                                   id->toChars(), toChars(), sm->kind(), sm->toChars());
                         else
-                            error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
+                            error(loc, "identifier `%s` of `%s` is not defined", id->toChars(), toChars());
                     }
                     *pe = new ErrorExp();
                 }
@@ -7107,9 +6117,9 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
                 (!v->type->deco && v->inuse))
             {
                 if (v->inuse)   // Bugzilla 9494
-                    error(loc, "circular reference to %s '%s'", v->kind(), v->toPrettyChars());
+                    error(loc, "circular reference to %s `%s`", v->kind(), v->toPrettyChars());
                 else
-                    error(loc, "forward reference to %s '%s'", v->kind(), v->toPrettyChars());
+                    error(loc, "forward reference to %s `%s`", v->kind(), v->toPrettyChars());
                 *pt = Type::terror;
                 return;
             }
@@ -7123,7 +6133,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
         {
             //printf("'%s' is a function literal\n", fld->toChars());
             *pe = new FuncExp(loc, fld);
-            *pe = ::semantic(*pe, sc);
+            *pe = expressionSemantic(*pe, sc);
             return;
         }
 L1:
@@ -7144,7 +6154,7 @@ L1:
         if (t->ty == Tinstance && t != this && !t->deco)
         {
             if (!((TypeInstance *)t)->tempinst->errors)
-                error(loc, "forward reference to '%s'", t->toChars());
+                error(loc, "forward reference to `%s`", t->toChars());
             *pt = Type::terror;
             return;
         }
@@ -7267,34 +6277,6 @@ Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
     return s;
 }
 
-Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
-{
-    Type *t;
-    Expression *e;
-    Dsymbol *s;
-
-    //printf("TypeIdentifier::semantic(%s)\n", toChars());
-    resolve(loc, sc, &e, &t, &s);
-    if (t)
-    {
-        //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
-        t = t->addMod(mod);
-    }
-    else
-    {
-        if (s)
-        {
-            s->error(loc, "is used as a type");
-            //halt();
-        }
-        else
-            error(loc, "%s is used as a type", toChars());
-        t = terror;
-    }
-    //t->print();
-    return t;
-}
-
 /***************************** TypeInstance *****************************/
 
 TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
@@ -7324,7 +6306,7 @@ void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymb
     *pt = NULL;
     *ps = NULL;
     //printf("TypeInstance::resolve(sc = %p, tempinst = '%s')\n", sc, tempinst->toChars());
-    tempinst->semantic(sc);
+    dsymbolSemantic(tempinst, sc);
     if (!global.gag && tempinst->errors)
     {
         *pt = terror;
@@ -7337,36 +6319,6 @@ void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymb
     //if (*pt) printf("pt = '%s'\n", (*pt)->toChars());
 }
 
-Type *TypeInstance::semantic(Loc loc, Scope *sc)
-{
-    Type *t;
-    Expression *e;
-    Dsymbol *s;
-
-    //printf("TypeInstance::semantic(%p, %s)\n", this, toChars());
-    {
-        unsigned errors = global.errors;
-        resolve(loc, sc, &e, &t, &s);
-        // if we had an error evaluating the symbol, suppress further errors
-        if (!t && errors != global.errors)
-            return terror;
-    }
-
-    if (!t)
-    {
-        if (!e && s && s->errors)
-        {
-            // if there was an error evaluating the symbol, it might actually
-            // be a type. Avoid misleading error messages.
-            error(loc, "%s had previous errors", toChars());
-        }
-        else
-            error(loc, "%s is used as a type", toChars());
-        t = terror;
-    }
-    return t;
-}
-
 Dsymbol *TypeInstance::toDsymbol(Scope *sc)
 {
     Type *t;
@@ -7456,7 +6408,7 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
          */
         Scope *sc2 = sc->push();
         sc2->intypeof = 1;
-        Expression *exp2 = ::semantic(exp, sc2);
+        Expression *exp2 = expressionSemantic(exp, sc2);
         exp2 = resolvePropertiesOnly(sc2, exp2);
         sc2->pop();
 
@@ -7514,7 +6466,7 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
         else
         {
             Expression *e = typeToExpressionHelper(this, new TypeExp(loc, t));
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             resolveExp(e, pt, pe, ps);
         }
     }
@@ -7524,24 +6476,6 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
     return;
 }
 
-Type *TypeTypeof::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypeTypeof::semantic() %s\n", toChars());
-
-    Expression *e;
-    Type *t;
-    Dsymbol *s;
-    resolve(loc, sc, &e, &t, &s);
-    if (s && (t = s->getType()) != NULL)
-        t = t->addMod(mod);
-    if (!t)
-    {
-        error(loc, "%s is used as a type", toChars());
-        t = Type::terror;
-    }
-    return t;
-}
-
 d_uns64 TypeTypeof::size(Loc loc)
 {
     if (exp->type)
@@ -7616,7 +6550,7 @@ void TypeReturn::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
         else
         {
             Expression *e = typeToExpressionHelper(this, new TypeExp(loc, t));
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             resolveExp(e, pt, pe, ps);
         }
     }
@@ -7629,24 +6563,6 @@ Lerr:
     return;
 }
 
-Type *TypeReturn::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypeReturn::semantic() %s\n", toChars());
-
-    Expression *e;
-    Type *t;
-    Dsymbol *s;
-    resolve(loc, sc, &e, &t, &s);
-    if (s && (t = s->getType()) != NULL)
-        t = t->addMod(mod);
-    if (!t)
-    {
-        error(loc, "%s is used as a type", toChars());
-        t = Type::terror;
-    }
-    return t;
-}
-
 /***************************** TypeEnum *****************************/
 
 TypeEnum::TypeEnum(EnumDeclaration *sym)
@@ -7665,14 +6581,6 @@ Type *TypeEnum::syntaxCopy()
     return this;
 }
 
-Type *TypeEnum::semantic(Loc, Scope *)
-{
-    //printf("TypeEnum::semantic() %s\n", toChars());
-    if (deco)
-        return this;
-    return merge();
-}
-
 d_uns64 TypeEnum::size(Loc loc)
 {
     return sym->getMemtype(loc)->size(loc);
@@ -7706,7 +6614,7 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident, int fl
         return getProperty(e->loc, ident, flag & 1);
 
     if (sym->semanticRun < PASSsemanticdone)
-        sym->semantic(NULL);
+        dsymbolSemantic(sym, NULL);
     if (!sym->members)
     {
         if (sym->isSpecial())
@@ -7717,7 +6625,7 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident, int fl
         }
         else if (!(flag & 1))
         {
-            sym->error("is forward referenced when looking for '%s'", ident->toChars());
+            sym->error("is forward referenced when looking for `%s`", ident->toChars());
             e = new ErrorExp();
         }
         else
@@ -7738,10 +6646,10 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident, int fl
         if (!(flag & 1) && !res)
         {
             if (Dsymbol *ns = sym->search_correct(ident))
-                e->error("no property '%s' for type '%s'. Did you mean '%s.%s' ?",
+                e->error("no property `%s` for type `%s`. Did you mean `%s.%s` ?",
                     ident->toChars(), toChars(), toChars(), ns->toChars());
             else
-                e->error("no property '%s' for type '%s'",
+                e->error("no property `%s` for type `%s`",
                     ident->toChars(), toChars());
 
             return new ErrorExp();
@@ -7768,7 +6676,7 @@ Expression *TypeEnum::getProperty(Loc loc, Identifier *ident, int flag)
         const char *s = toChars();
         e = new StringExp(loc, const_cast<char *>(s), strlen(s));
         Scope sc;
-        e = ::semantic(e, &sc);
+        e = expressionSemantic(e, &sc);
     }
     else if (ident == Id::_mangleof)
     {
@@ -7921,34 +6829,6 @@ Type *TypeStruct::syntaxCopy()
     return this;
 }
 
-Type *TypeStruct::semantic(Loc, Scope *sc)
-{
-    //printf("TypeStruct::semantic('%s')\n", sym->toChars());
-    if (deco)
-    {
-        if (sc && sc->cppmangle != CPPMANGLEdefault)
-        {
-            if (this->cppmangle == CPPMANGLEdefault)
-                this->cppmangle = sc->cppmangle;
-            else
-                assert(this->cppmangle == sc->cppmangle);
-        }
-        return this;
-    }
-
-    /* Don't semantic for sym because it should be deferred until
-     * sizeof needed or its members accessed.
-     */
-    // instead, parent should be set correctly
-    assert(sym->parent);
-
-    if (sym->type->ty == Terror)
-        return Type::terror;
-    if (sc)
-        this->cppmangle = sc->cppmangle;
-    return merge();
-}
-
 d_uns64 TypeStruct::size(Loc loc)
 {
     return sym->size(loc);
@@ -7982,7 +6862,7 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident, int
         /* Create a TupleExp out of the fields of the struct e:
          * (e.field0, e.field1, e.field2, ...)
          */
-        e = ::semantic(e, sc);  // do this before turning on noaccesscheck
+        e = expressionSemantic(e, sc);  // do this before turning on noaccesscheck
 
         sym->size(e->loc);      // do semantic of type
 
@@ -8010,7 +6890,7 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident, int
         e = new TupleExp(e->loc, e0, exps);
         Scope *sc2 = sc->push();
         sc2->flags = sc->flags | SCOPEnoaccesscheck;
-        e = ::semantic(e, sc2);
+        e = expressionSemantic(e, sc2);
         sc2->pop();
         return e;
     }
@@ -8046,9 +6926,9 @@ L1:
             (!v->type->deco && v->inuse))
         {
             if (v->inuse) // Bugzilla 9494
-                e->error("circular reference to %s '%s'", v->kind(), v->toPrettyChars());
+                e->error("circular reference to %s `%s`", v->kind(), v->toPrettyChars());
             else
-                e->error("forward reference to %s '%s'", v->kind(), v->toPrettyChars());
+                e->error("forward reference to %s `%s`", v->kind(), v->toPrettyChars());
             return new ErrorExp();
         }
         if (v->type->ty == Terror)
@@ -8058,19 +6938,19 @@ L1:
         {
             if (v->inuse)
             {
-                e->error("circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
+                e->error("circular initialization of %s `%s`", v->kind(), v->toPrettyChars());
                 return new ErrorExp();
             }
             checkAccess(e->loc, sc, NULL, v);
             Expression *ve = new VarExp(e->loc, v);
-            ve = ::semantic(ve, sc);
+            ve = expressionSemantic(ve, sc);
             return ve;
         }
     }
 
     if (Type *t = s->getType())
     {
-        return ::semantic(new TypeExp(e->loc, t), sc);
+        return expressionSemantic(new TypeExp(e->loc, t), sc);
     }
 
     TemplateMixin *tm = s->isTemplateMixin();
@@ -8088,7 +6968,7 @@ L1:
             e = new TemplateExp(e->loc, td);
         else
             e = new DotTemplateExp(e->loc, e, td);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
 
@@ -8097,7 +6977,7 @@ L1:
     {
         if (!ti->semanticRun)
         {
-            ti->semantic(sc);
+            dsymbolSemantic(ti, sc);
             if (!ti->inst || ti->errors)    // if template failed to expand
                 return new ErrorExp();
         }
@@ -8108,7 +6988,7 @@ L1:
             e = new ScopeExp(e->loc, ti);
         else
             e = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
-        return ::semantic(e, sc);
+        return expressionSemantic(e, sc);
     }
 
     if (s->isImport() || s->isModule() || s->isPackage())
@@ -8141,7 +7021,7 @@ L1:
         if (TupleDeclaration *tup = d->isTupleDeclaration())
         {
             e = new TupleExp(e->loc, tup);
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
         if (d->needThis() && sc->intypeof != 1)
@@ -8152,12 +7032,12 @@ L1:
             if (hasThis(sc))
             {
                 e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
-                e = ::semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 return e;
             }
         }
         if (d->semanticRun == PASSinit)
-            d->semantic(NULL);
+            dsymbolSemantic(d, NULL);
         checkAccess(e->loc, sc, e, d);
         VarExp *ve = new VarExp(e->loc, d);
         if (d->isVarDeclaration() && d->needThis())
@@ -8172,12 +7052,12 @@ L1:
         checkAccess(e->loc, sc, e, d);
         Expression *ve = new VarExp(e->loc, d);
         e = unreal ? ve : new CommaExp(e->loc, e, ve);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
 
     e = new DotVarExp(e->loc, e, d);
-    e = ::semantic(e, sc);
+    e = expressionSemantic(e, sc);
     return e;
 }
 
@@ -8215,7 +7095,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
         Expression *e;
         if (vd->inuse)
         {
-            error(loc, "circular reference to '%s'", vd->toPrettyChars());
+            error(loc, "circular reference to `%s`", vd->toPrettyChars());
             return new ErrorExp();
         }
         if (vd->offset < offset || vd->type->size() == 0)
@@ -8463,34 +7343,6 @@ Type *TypeClass::syntaxCopy()
     return this;
 }
 
-Type *TypeClass::semantic(Loc, Scope *sc)
-{
-    //printf("TypeClass::semantic(%s)\n", sym->toChars());
-    if (deco)
-    {
-        if (sc && sc->cppmangle != CPPMANGLEdefault)
-        {
-            if (this->cppmangle == CPPMANGLEdefault)
-                this->cppmangle = sc->cppmangle;
-            else
-                assert(this->cppmangle == sc->cppmangle);
-        }
-        return this;
-    }
-
-    /* Don't semantic for sym because it should be deferred until
-     * sizeof needed or its members accessed.
-     */
-    // instead, parent should be set correctly
-    assert(sym->parent);
-
-    if (sym->type->ty == Terror)
-        return Type::terror;
-    if (sc)
-        this->cppmangle = sc->cppmangle;
-    return merge();
-}
-
 d_uns64 TypeClass::size(Loc)
 {
     return target.ptrsize;
@@ -8518,7 +7370,7 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int f
     {
         /* Create a TupleExp
          */
-        e = ::semantic(e, sc);  // do this before turning on noaccesscheck
+        e = expressionSemantic(e, sc);  // do this before turning on noaccesscheck
 
         sym->size(e->loc); // do semantic of type
 
@@ -8549,7 +7401,7 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int f
         e = new TupleExp(e->loc, e0, exps);
         Scope *sc2 = sc->push();
         sc2->flags = sc->flags | SCOPEnoaccesscheck;
-        e = ::semantic(e, sc2);
+        e = expressionSemantic(e, sc2);
         sc2->pop();
         return e;
     }
@@ -8566,7 +7418,7 @@ L1:
             if (e->op == TOKtype)
                 return Type::getProperty(e->loc, ident, 0);
             e = new DotTypeExp(e->loc, e, sym);
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
         if (ClassDeclaration *cbase = sym->searchBase(ident))
@@ -8577,7 +7429,7 @@ L1:
                 e = new CastExp(e->loc, e, ifbase->type);
             else
                 e = new DotTypeExp(e->loc, e, cbase);
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
 
@@ -8640,7 +7492,7 @@ L1:
              */
             e = e->castTo(sc, tvoidptr->immutableOf()->pointerTo()->pointerTo());
             e = new PtrExp(e->loc, e);
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
 
@@ -8652,14 +7504,14 @@ L1:
             e = e->castTo(sc, tvoidptr->pointerTo());
             e = new AddExp(e->loc, e, new IntegerExp(1));
             e = new PtrExp(e->loc, e);
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
 
         if (ident == Id::outer && sym->vthis)
         {
             if (sym->vthis->semanticRun == PASSinit)
-                sym->vthis->semantic(NULL);
+                dsymbolSemantic(sym->vthis, NULL);
 
             if (ClassDeclaration *cdp = sym->toParent2()->isClassDeclaration())
             {
@@ -8726,9 +7578,9 @@ L1:
             (!v->type->deco && v->inuse))
         {
             if (v->inuse) // Bugzilla 9494
-                e->error("circular reference to %s '%s'", v->kind(), v->toPrettyChars());
+                e->error("circular reference to %s `%s`", v->kind(), v->toPrettyChars());
             else
-                e->error("forward reference to %s '%s'", v->kind(), v->toPrettyChars());
+                e->error("forward reference to %s `%s`", v->kind(), v->toPrettyChars());
             return new ErrorExp();
         }
         if (v->type->ty == Terror)
@@ -8738,19 +7590,19 @@ L1:
         {
             if (v->inuse)
             {
-                e->error("circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
+                e->error("circular initialization of %s `%s`", v->kind(), v->toPrettyChars());
                 return new ErrorExp();
             }
             checkAccess(e->loc, sc, NULL, v);
             Expression *ve = new VarExp(e->loc, v);
-            ve = ::semantic(ve, sc);
+            ve = expressionSemantic(ve, sc);
             return ve;
         }
     }
 
     if (Type *t = s->getType())
     {
-        return ::semantic(new TypeExp(e->loc, t), sc);
+        return expressionSemantic(new TypeExp(e->loc, t), sc);
     }
 
     TemplateMixin *tm = s->isTemplateMixin();
@@ -8768,7 +7620,7 @@ L1:
             e = new TemplateExp(e->loc, td);
         else
             e = new DotTemplateExp(e->loc, e, td);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
 
@@ -8777,7 +7629,7 @@ L1:
     {
         if (!ti->semanticRun)
         {
-            ti->semantic(sc);
+            dsymbolSemantic(ti, sc);
             if (!ti->inst || ti->errors)    // if template failed to expand
                 return new ErrorExp();
         }
@@ -8788,7 +7640,7 @@ L1:
             e = new ScopeExp(e->loc, ti);
         else
             e = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
-        return ::semantic(e, sc);
+        return expressionSemantic(e, sc);
     }
 
     if (s->isImport() || s->isModule() || s->isPackage())
@@ -8821,7 +7673,7 @@ L1:
         if (TupleDeclaration *tup = d->isTupleDeclaration())
         {
             e = new TupleExp(e->loc, tup);
-            e = ::semantic(e, sc);
+            e = expressionSemantic(e, sc);
             return e;
         }
         if (d->needThis() && sc->intypeof != 1)
@@ -8833,7 +7685,7 @@ L1:
             {
                 // This is almost same as getRightThis() in expression.c
                 Expression *e1 = new ThisExp(e->loc);
-                e1 = ::semantic(e1, sc);
+                e1 = expressionSemantic(e1, sc);
             L2:
                 Type *t = e1->type->toBasetype();
                 ClassDeclaration *cd = e->type->isClassHandle();
@@ -8842,7 +7694,7 @@ L1:
                 {
                     e = new DotTypeExp(e1->loc, e1, cd);
                     e = new DotVarExp(e->loc, e, d);
-                    e = ::semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     return e;
                 }
                 if (tcd && tcd->isNested())
@@ -8854,7 +7706,7 @@ L1:
                     e1->type = tcd->vthis->type;
                     e1->type = e1->type->addMod(t->mod);
                     // Do not call checkNestedRef()
-                    //e1 = ::semantic(e1, sc);
+                    //e1 = expressionSemantic(e1, sc);
 
                     // Skip up over nested functions, and get the enclosing
                     // class type.
@@ -8879,17 +7731,17 @@ L1:
                     {   e1->type = s->isClassDeclaration()->type;
                         e1->type = e1->type->addMod(t->mod);
                         if (n > 1)
-                            e1 = ::semantic(e1, sc);
+                            e1 = expressionSemantic(e1, sc);
                     }
                     else
-                        e1 = ::semantic(e1, sc);
+                        e1 = expressionSemantic(e1, sc);
                     goto L2;
                 }
             }
         }
         //printf("e = %s, d = %s\n", e->toChars(), d->toChars());
         if (d->semanticRun == PASSinit)
-            d->semantic(NULL);
+            dsymbolSemantic(d, NULL);
         checkAccess(e->loc, sc, e, d);
         VarExp *ve = new VarExp(e->loc, d);
         if (d->isVarDeclaration() && d->needThis())
@@ -8904,12 +7756,12 @@ L1:
         checkAccess(e->loc, sc, e, d);
         Expression *ve = new VarExp(e->loc, d);
         e = unreal ? ve : new CommaExp(e->loc, e, ve);
-        e = ::semantic(e, sc);
+        e = expressionSemantic(e, sc);
         return e;
     }
 
     e = new DotVarExp(e->loc, e, d);
-    e = ::semantic(e, sc);
+    e = expressionSemantic(e, sc);
     return e;
 }
 
@@ -8946,9 +7798,9 @@ MATCH TypeClass::implicitConvTo(Type *to)
     {
         //printf("TypeClass::implicitConvTo(to = '%s') %s, isbase = %d %d\n", to->toChars(), toChars(), cdto->isBaseInfoComplete(), sym->isBaseInfoComplete());
         if (cdto->semanticRun < PASSsemanticdone && !cdto->isBaseInfoComplete())
-            cdto->semantic(NULL);
+            dsymbolSemantic(cdto, NULL);
         if (sym->semanticRun < PASSsemanticdone && !sym->isBaseInfoComplete())
-            sym->semantic(NULL);
+            dsymbolSemantic(sym, NULL);
         if (cdto->isBaseOf(sym, NULL) && MODimplicitConv(mod, to->mod))
         {
             //printf("'to' is base\n");
@@ -9110,19 +7962,6 @@ Type *TypeTuple::syntaxCopy()
     return t;
 }
 
-Type *TypeTuple::semantic(Loc, Scope *)
-{
-    //printf("TypeTuple::semantic(this = %p)\n", this);
-    //printf("TypeTuple::semantic() %p, %s\n", this, toChars());
-    if (!deco)
-        deco = merge()->deco;
-
-    /* Don't return merge(), because a tuple with one type has the
-     * same deco as that type.
-     */
-    return this;
-}
-
 bool TypeTuple::equals(RootObject *o)
 {
     Type *t = (Type *)o;
@@ -9165,7 +8004,7 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident, int flag)
     }
     else
     {
-        error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
+        error(loc, "no property `%s` for tuple `%s`", ident->toChars(), toChars());
         e = new ErrorExp();
     }
     return e;
@@ -9211,48 +8050,6 @@ Type *TypeSlice::syntaxCopy()
     return t;
 }
 
-Type *TypeSlice::semantic(Loc loc, Scope *sc)
-{
-    //printf("TypeSlice::semantic() %s\n", toChars());
-    Type *tn = next->semantic(loc, sc);
-    //printf("next: %s\n", tn->toChars());
-
-    Type *tbn = tn->toBasetype();
-    if (tbn->ty != Ttuple)
-    {
-        error(loc, "can only slice tuple types, not %s", tbn->toChars());
-        return Type::terror;
-    }
-    TypeTuple *tt = (TypeTuple *)tbn;
-
-    lwr = semanticLength(sc, tbn, lwr);
-    lwr = lwr->ctfeInterpret();
-    uinteger_t i1 = lwr->toUInteger();
-
-    upr = semanticLength(sc, tbn, upr);
-    upr = upr->ctfeInterpret();
-    uinteger_t i2 = upr->toUInteger();
-
-    if (!(i1 <= i2 && i2 <= tt->arguments->length))
-    {
-        error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->length);
-        return Type::terror;
-    }
-
-    next = tn;
-    transitive();
-
-    Parameters *args = new Parameters;
-    args->reserve((size_t)(i2 - i1));
-    for (size_t i = (size_t)i1; i < (size_t)i2; i++)
-    {
-        Parameter *arg = (*tt->arguments)[i];
-        args->push(arg);
-    }
-    Type *t = new TypeTuple(args);
-    return t->semantic(loc, sc);
-}
-
 void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
 {
     next->resolve(loc, sc, pe, pt, ps, intypeid);
@@ -9275,8 +8072,8 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
             sym->parent = sc->scopesym;
             sc = sc->push(sym);
             sc = sc->startCTFE();
-            lwr = ::semantic(lwr, sc);
-            upr = ::semantic(upr, sc);
+            lwr = expressionSemantic(lwr, sc);
+            upr = expressionSemantic(upr, sc);
             sc = sc->endCTFE();
             sc = sc->pop();
 
index 28dba1c250ae46bc8960ed6281ee032bea57282d..083d707f8f30863d522a61f1d80ea9cd953991b7 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -40,6 +40,7 @@ typedef union tree_node type;
 typedef struct TYPE type;
 #endif
 
+Type *typeSemantic(Type *type, const Loc &loc, Scope *sc);
 void semanticTypeInfo(Scope *sc, Type *t);
 MATCH deduceType(RootObject *o, Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wm = NULL, size_t inferStart = 0);
 StorageClass ModToStc(unsigned mod);
@@ -245,7 +246,6 @@ public:
     d_uns64 size();
     virtual d_uns64 size(Loc loc);
     virtual unsigned alignsize();
-    virtual Type *semantic(Loc loc, Scope *sc);
     Type *trySemantic(Loc loc, Scope *sc);
     Type *merge();
     Type *merge2();
@@ -448,7 +448,6 @@ public:
     static TypeVector *create(Type *basetype);
     const char *kind();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
     unsigned alignsize();
     Expression *getProperty(Loc loc, Identifier *ident, int flag);
@@ -486,7 +485,6 @@ public:
     Type *syntaxCopy();
     d_uns64 size(Loc loc);
     unsigned alignsize();
-    Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
     bool isString();
@@ -512,7 +510,6 @@ public:
     Type *syntaxCopy();
     d_uns64 size(Loc loc) /*const*/;
     unsigned alignsize() /*const*/;
-    Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
     bool isString();
@@ -537,7 +534,6 @@ public:
     const char *kind();
     Type *syntaxCopy();
     d_uns64 size(Loc loc);
-    Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
     Expression *defaultInit(Loc loc);
@@ -557,7 +553,6 @@ public:
     static TypePointer *create(Type *t);
     const char *kind();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc) /*const*/;
     MATCH implicitConvTo(Type *to);
     MATCH constConv(Type *to);
@@ -575,7 +570,6 @@ public:
     TypeReference(Type *t);
     const char *kind();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc) /*const*/;
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
     Expression *defaultInit(Loc loc);
@@ -680,7 +674,6 @@ public:
     static TypeFunction *create(Parameters *parameters, Type *treturn, VarArg varargs, LINK linkage, StorageClass stc = 0);
     const char *kind();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     void purityLevel();
     bool hasLazyParameters();
     bool isDstyleVariadic() const;
@@ -709,7 +702,6 @@ public:
     static TypeDelegate *create(Type *t);
     const char *kind();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     Type *addStorageClass(StorageClass stc);
     d_uns64 size(Loc loc) /*const*/;
     unsigned alignsize() /*const*/;
@@ -734,7 +726,6 @@ public:
 
     TypeTraits(const Loc &loc, TraitsExp *exp);
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
     d_uns64 size(Loc loc);
     void accept(Visitor *v) { v->visit(this); }
@@ -774,7 +765,6 @@ public:
     Type *syntaxCopy();
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
     Dsymbol *toDsymbol(Scope *sc);
-    Type *semantic(Loc loc, Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -789,7 +779,6 @@ public:
     const char *kind();
     Type *syntaxCopy();
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
-    Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -805,7 +794,6 @@ public:
     Type *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
-    Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -818,7 +806,6 @@ public:
     Type *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
-    Type *semantic(Loc loc, Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -847,7 +834,6 @@ public:
     d_uns64 size(Loc loc);
     unsigned alignsize();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
     structalign_t alignment();
@@ -878,7 +864,6 @@ public:
     Type *syntaxCopy();
     d_uns64 size(Loc loc);
     unsigned alignsize();
-    Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
     Expression *getProperty(Loc loc, Identifier *ident, int flag);
@@ -917,7 +902,6 @@ public:
     const char *kind();
     d_uns64 size(Loc loc) /*const*/;
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
     ClassDeclaration *isClassHandle();
@@ -948,7 +932,6 @@ public:
     TypeTuple(Type *t1, Type *t2);
     const char *kind();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     bool equals(RootObject *o);
     Expression *getProperty(Loc loc, Identifier *ident, int flag);
     Expression *defaultInit(Loc loc);
@@ -964,7 +947,6 @@ public:
     TypeSlice(Type *next, Expression *lwr, Expression *upr);
     const char *kind();
     Type *syntaxCopy();
-    Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
     void accept(Visitor *v) { v->visit(this); }
 };
index 1372f4804a4b7132cf1415789b790ac7dca09882..12c8b490cfb4936778c2adb0c12481e7c3301a6a 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -83,7 +83,7 @@ public:
 
         if (f->setGC())
         {
-            e->error("array literal in @nogc %s '%s' may cause GC allocation",
+            e->error("array literal in @nogc %s `%s` may cause GC allocation",
                 f->kind(), f->toPrettyChars());
             err = true;
             return;
@@ -98,7 +98,7 @@ public:
 
         if (f->setGC())
         {
-            e->error("associative array literal in @nogc %s '%s' may cause GC allocation",
+            e->error("associative array literal in @nogc %s `%s` may cause GC allocation",
                 f->kind(), f->toPrettyChars());
             err = true;
             return;
@@ -120,12 +120,12 @@ public:
 
         if (f->setGC())
         {
-            e->error("cannot use 'new' in @nogc %s '%s'",
+            e->error("cannot use `new` in @nogc %s `%s`",
                 f->kind(), f->toPrettyChars());
             err = true;
             return;
         }
-        f->printGCUsage(e->loc, "'new' causes GC allocation");
+        f->printGCUsage(e->loc, "`new` causes GC allocation");
     }
 
     void visit(DeleteExp *e)
@@ -159,12 +159,12 @@ public:
 
         if (f->setGC())
         {
-            e->error("cannot use 'delete' in @nogc %s '%s'",
+            e->error("cannot use `delete` in @nogc %s `%s`",
                 f->kind(), f->toPrettyChars());
             err = true;
             return;
         }
-        f->printGCUsage(e->loc, "'delete' requires GC");
+        f->printGCUsage(e->loc, "`delete` requires GC");
     }
 
     void visit(IndexExp* e)
@@ -174,7 +174,7 @@ public:
         {
             if (f->setGC())
             {
-                e->error("indexing an associative array in @nogc %s '%s' may cause GC allocation",
+                e->error("indexing an associative array in @nogc %s `%s` may cause GC allocation",
                     f->kind(), f->toPrettyChars());
                 err = true;
                 return;
@@ -189,12 +189,12 @@ public:
         {
             if (f->setGC())
             {
-                e->error("setting 'length' in @nogc %s '%s' may cause GC allocation",
+                e->error("setting `length` in @nogc %s `%s` may cause GC allocation",
                     f->kind(), f->toPrettyChars());
                 err = true;
                 return;
             }
-            f->printGCUsage(e->loc, "setting 'length' may cause GC allocation");
+            f->printGCUsage(e->loc, "setting `length` may cause GC allocation");
         }
     }
 
@@ -202,7 +202,7 @@ public:
     {
         if (f->setGC())
         {
-            e->error("cannot use operator ~= in @nogc %s '%s'",
+            e->error("cannot use operator ~= in @nogc %s `%s`",
                 f->kind(), f->toPrettyChars());
             err = true;
             return;
@@ -214,7 +214,7 @@ public:
     {
         if (f->setGC())
         {
-            e->error("cannot use operator ~ in @nogc %s '%s'",
+            e->error("cannot use operator ~ in @nogc %s `%s`",
                 f->kind(), f->toPrettyChars());
             err = true;
             return;
index 71d1c6f555233e0d0b68962e86110118bbfe5d5b..95cfb6f0d346fd87fbf4f6ab528e86d777121d00 100644 (file)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright: Copyright (C) 2014-2020 by The D Language Foundation, All Rights Reserved
+// Copyright: Copyright (C) 2014-2021 by The D Language Foundation, All Rights Reserved
 // Authors: Walter Bright, http://www.digitalmars.com
 // License: http://boost.org/LICENSE_1_0.txt
 // Source: https://github.com/D-Programming-Language/dmd/blob/master/src/nspace.c
@@ -86,80 +86,6 @@ void Nspace::setScope(Scope *sc)
     }
 }
 
-void Nspace::semantic(Scope *sc)
-{
-    if (semanticRun != PASSinit)
-        return;
-    if (_scope)
-    {
-        sc = _scope;
-        _scope = NULL;
-    }
-    if (!sc)
-        return;
-
-    semanticRun = PASSsemantic;
-    parent = sc->parent;
-    if (members)
-    {
-        assert(sc);
-        sc = sc->push(this);
-        sc->linkage = LINKcpp;          // note that namespaces imply C++ linkage
-        sc->parent = this;
-
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->importAll(sc);
-        }
-
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->semantic(sc);
-        }
-        sc->pop();
-    }
-    semanticRun = PASSsemanticdone;
-}
-
-void Nspace::semantic2(Scope *sc)
-{
-    if (semanticRun >= PASSsemantic2)
-        return;
-    semanticRun = PASSsemantic2;
-    if (members)
-    {
-        assert(sc);
-        sc = sc->push(this);
-        sc->linkage = LINKcpp;
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->semantic2(sc);
-        }
-        sc->pop();
-    }
-}
-
-void Nspace::semantic3(Scope *sc)
-{
-    if (semanticRun >= PASSsemantic3)
-        return;
-    semanticRun = PASSsemantic3;
-    if (members)
-    {
-        sc = sc->push(this);
-        sc->linkage = LINKcpp;
-        for (size_t i = 0; i < members->length; i++)
-        {
-            Dsymbol *s = (*members)[i];
-            s->semantic3(sc);
-        }
-        sc->pop();
-    }
-}
-
 const char *Nspace::kind() const
 {
     return "namespace";
@@ -174,11 +100,11 @@ Dsymbol *Nspace::search(const Loc &loc, Identifier *ident, int flags)
 {
     //printf("%s::Nspace::search('%s')\n", toChars(), ident->toChars());
     if (_scope && !symtab)
-        semantic(_scope);
+        dsymbolSemantic(this, _scope);
 
     if (!members || !symtab) // opaque or semantic() is not yet called
     {
-        error("is forward referenced when looking for '%s'", ident->toChars());
+        error("is forward referenced when looking for `%s`", ident->toChars());
         return NULL;
     }
 
@@ -225,7 +151,7 @@ void Nspace::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool is
 {
     //printf("Nspace::setFieldOffset() %s\n", toChars());
     if (_scope)                  // if fwd reference
-        semantic(NULL);         // try to resolve it
+        dsymbolSemantic(this, NULL);         // try to resolve it
     if (members)
     {
         for (size_t i = 0; i < members->length; i++)
index ae29b18d787e809b078d1bb066273ff6761bf2f6..71dafb2553d230d8789199727a57f560c01826df 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -25,9 +25,6 @@ class Nspace : public ScopeDsymbol
     Dsymbol *syntaxCopy(Dsymbol *s);
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope *sc);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
     bool oneMember(Dsymbol **ps, Identifier *ident);
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
     int apply(Dsymbol_apply_ft_t fp, void *param);
index b0353a5de7bb6536664ed886d7be86e47f47a0bc..3199a0164ee3f0839e59262ba15b3b01e076a8e8 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2015-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2015-2021 by The D Language Foundation, All Rights Reserved
  * written by Michel Fortin
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 00d76e143e6799949b3bf73c845f94f92ac01131..f3da5a3755f2abf0f30488720f9850b8ff452298 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2015-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2015-2021 by The D Language Foundation, All Rights Reserved
  * written by Michel Fortin
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 66a0d235eee05bbdd384f5ff64c783fa97f6d24e..0aff8b43551788b840ddaa31ba453da7e8aec11f 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -27,9 +27,6 @@ static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart,
 static int inferApplyArgTypesY(TypeFunction *tf, Parameters *parameters, int flags = 0);
 Expression *compare_overload(BinExp *e, Scope *sc, Identifier *id);
 bool MODimplicitConv(MOD modfrom, MOD modto);
-Expression *trySemantic(Expression *e, Scope *sc);
-Expression *binSemanticProp(BinExp *e, Scope *sc);
-Expression *semantic(Expression *e, Scope *sc);
 
 /******************************** Expression **************************/
 
@@ -195,7 +192,7 @@ Objects *opToArg(Scope *sc, TOK op)
         default:                     break;
     }
     Expression *e = new StringExp(Loc(), const_cast<char *>(Token::toChars(op)));
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     Objects *tiargs = new Objects();
     tiargs->push(e);
     return tiargs;
@@ -234,7 +231,7 @@ Expression *op_overload(Expression *e, Scope *sc)
             if (e->e1->op == TOKarray)
             {
                 ArrayExp *ae = (ArrayExp *)e->e1;
-                ae->e1 = semantic(ae->e1, sc);
+                ae->e1 = expressionSemantic(ae->e1, sc);
                 ae->e1 = resolveProperties(sc, ae->e1);
                 Expression *ae1old = ae->e1;
 
@@ -282,7 +279,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                         if (maybeSlice) // op(a[]) might be: a.opSliceUnary!(op)()
                             result = trySemantic(result, sc);
                         else
-                            result = semantic(result, sc);
+                            result = expressionSemantic(result, sc);
                         if (result)
                         {
                             result = Expression::combine(e0, result);
@@ -309,7 +306,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                         Objects *tiargs = opToArg(sc, e->op);
                         result = new DotTemplateInstanceExp(e->loc, ae->e1, Id::opSliceUnary, tiargs);
                         result = new CallExp(e->loc, result, a);
-                        result = semantic(result, sc);
+                        result = expressionSemantic(result, sc);
                         result = Expression::combine(e0, result);
                         return;
                     }
@@ -333,7 +330,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                 ae->lengthVar = NULL;
             }
 
-            e->e1 = semantic(e->e1, sc);
+            e->e1 = expressionSemantic(e->e1, sc);
             e->e1 = resolveProperties(sc, e->e1);
             if (e->e1->op == TOKerror)
             {
@@ -367,7 +364,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     Objects *tiargs = opToArg(sc, e->op);
                     result = new DotTemplateInstanceExp(e->loc, e->e1, fd->ident, tiargs);
                     result = new CallExp(e->loc, result);
-                    result = semantic(result, sc);
+                    result = expressionSemantic(result, sc);
                     return;
                 }
 
@@ -392,7 +389,7 @@ Expression *op_overload(Expression *e, Scope *sc)
         void visit(ArrayExp *ae)
         {
             //printf("ArrayExp::op_overload() (%s)\n", ae->toChars());
-            ae->e1 = semantic(ae->e1, sc);
+            ae->e1 = expressionSemantic(ae->e1, sc);
             ae->e1 = resolveProperties(sc, ae->e1);
             Expression *ae1old = ae->e1;
 
@@ -435,14 +432,14 @@ Expression *op_overload(Expression *e, Scope *sc)
                         if (maybeSlice)
                         {
                             result = new SliceExp(ae->loc, ae->e1, ie);
-                            result = semantic(result, sc);
+                            result = expressionSemantic(result, sc);
                             return;
                         }
                         // Convert to IndexExp
                         if (ae->arguments->length == 1)
                         {
                             result = new IndexExp(ae->loc, ae->e1, (*ae->arguments)[0]);
-                            result = semantic(result, sc);
+                            result = expressionSemantic(result, sc);
                             return;
                         }
                     }
@@ -466,7 +463,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     if (maybeSlice) // a[] might be: a.opSlice()
                         result = trySemantic(result, sc);
                     else
-                        result = semantic(result, sc);
+                        result = expressionSemantic(result, sc);
                     if (result)
                     {
                         result = Expression::combine(e0, result);
@@ -477,7 +474,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                 if (maybeSlice && ae->e1->op == TOKtype)
                 {
                     result = new SliceExp(ae->loc, ae->e1, ie);
-                    result = semantic(result, sc);
+                    result = expressionSemantic(result, sc);
                     result = Expression::combine(e0, result);
                     return;
                 }
@@ -499,7 +496,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     }
                     result = new DotIdExp(ae->loc, ae->e1, Id::slice);
                     result = new CallExp(ae->loc, result, a);
-                    result = semantic(result, sc);
+                    result = expressionSemantic(result, sc);
                     result = Expression::combine(e0, result);
                     return;
                 }
@@ -553,7 +550,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     tiargs->push(e->to);
                     result = new DotTemplateInstanceExp(e->loc, e->e1, fd->ident, tiargs);
                     result = new CallExp(e->loc, result);
-                    result = semantic(result, sc);
+                    result = expressionSemantic(result, sc);
                     return;
                 }
 
@@ -942,7 +939,7 @@ Expression *op_overload(Expression *e, Scope *sc)
             if ((t1->ty == Tclass && e->e2->op == TOKnull) ||
                 (t2->ty == Tclass && e->e1->op == TOKnull))
             {
-                e->error("use '%s' instead of '%s' when comparing with null",
+                e->error("use `%s` instead of `%s` when comparing with null",
                     Token::toChars(e->op == TOKequal ? TOKidentity : TOKnotidentity),
                     Token::toChars(e->op));
                 result = new ErrorExp();
@@ -985,7 +982,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     result = new CallExp(e->loc, result, e1x, e2x);
                     if (e->op == TOKnotequal)
                         result = new NotExp(e->loc, result);
-                    result = semantic(result, sc);
+                    result = expressionSemantic(result, sc);
                     return;
                 }
             }
@@ -996,7 +993,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                 if (result->op == TOKcall && e->op == TOKnotequal)
                 {
                     result = new NotExp(result->loc, result);
-                    result = semantic(result, sc);
+                    result = expressionSemantic(result, sc);
                 }
                 return;
             }
@@ -1015,7 +1012,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                  */
                 TOK op2 = e->op == TOKequal ? TOKidentity : TOKnotidentity;
                 result = new IdentityExp(op2, e->loc, e->e1, e->e2);
-                result = semantic(result, sc);
+                result = expressionSemantic(result, sc);
                 return;
             }
 
@@ -1032,7 +1029,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     // Use bitwise equality.
                     TOK op2 = e->op == TOKequal ? TOKidentity : TOKnotidentity;
                     result = new IdentityExp(op2, e->loc, e->e1, e->e2);
-                    result = semantic(result, sc);
+                    result = expressionSemantic(result, sc);
                     return;
                 }
 
@@ -1058,7 +1055,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     e->att2 = t2;
                 e->e1 = new DotIdExp(e->loc, e->e1, Id::_tupleof);
                 e->e2 = new DotIdExp(e->loc, e->e2, Id::_tupleof);
-                result = semantic(e, sc);
+                result = expressionSemantic(e, sc);
 
                 /* Bugzilla 15292, if the rewrite result is same with the original,
                  * the equality is unresolvable because it has recursive definition.
@@ -1113,7 +1110,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                     assert(result);
                 }
                 result = Expression::combine(Expression::combine(tup1->e0, tup2->e0), result);
-                result = semantic(result, sc);
+                result = expressionSemantic(result, sc);
                 return;
             }
         }
@@ -1135,7 +1132,7 @@ Expression *op_overload(Expression *e, Scope *sc)
             if (e->e1->op == TOKarray)
             {
                 ArrayExp *ae = (ArrayExp *)e->e1;
-                ae->e1 = semantic(ae->e1, sc);
+                ae->e1 = expressionSemantic(ae->e1, sc);
                 ae->e1 = resolveProperties(sc, ae->e1);
                 Expression *ae1old = ae->e1;
 
@@ -1173,7 +1170,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                         if (result->op == TOKerror)
                             return;
 
-                        result = semantic(e->e2, sc);
+                        result = expressionSemantic(e->e2, sc);
                         if (result->op == TOKerror)
                             return;
                         e->e2 = result;
@@ -1189,7 +1186,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                         if (maybeSlice) // (a[] op= e2) might be: a.opSliceOpAssign!(op)(e2)
                             result = trySemantic(result, sc);
                         else
-                            result = semantic(result, sc);
+                            result = expressionSemantic(result, sc);
                         if (result)
                         {
                             result = Expression::combine(e0, result);
@@ -1204,7 +1201,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                         if (result->op == TOKerror)
                             return;
 
-                        result = semantic(e->e2, sc);
+                        result = expressionSemantic(e->e2, sc);
                         if (result->op == TOKerror)
                             return;
                         e->e2 = result;
@@ -1222,7 +1219,7 @@ Expression *op_overload(Expression *e, Scope *sc)
                         Objects *tiargs = opToArg(sc, e->op);
                         result = new DotTemplateInstanceExp(e->loc, ae->e1, Id::opSliceOpAssign, tiargs);
                         result = new CallExp(e->loc, result, a);
-                        result = semantic(result, sc);
+                        result = expressionSemantic(result, sc);
                         result = Expression::combine(e0, result);
                         return;
                     }
@@ -1570,7 +1567,7 @@ Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *ea
         e = new DotIdExp(loc, ethis, d->ident);
     e = new CallExp(loc, e, earg);
 
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     return e;
 }
 
@@ -1611,7 +1608,7 @@ bool inferAggregate(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply)
 
     while (1)
     {
-        aggr = semantic(aggr, sc);
+        aggr = expressionSemantic(aggr, sc);
         aggr = resolveProperties(sc, aggr);
         aggr = aggr->optimize(WANTvalue);
         if (!aggr->type || aggr->op == TOKerror)
@@ -1714,7 +1711,7 @@ bool inferApplyArgTypes(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply)
             Parameter *p = (*fes->parameters)[u];
             if (p->type)
             {
-                p->type = p->type->semantic(fes->loc, sc);
+                p->type = typeSemantic(p->type, fes->loc, sc);
                 p->type = p->type->addStorageClass(p->storageClass);
             }
         }
index 45d94df577d08cc29057c2923474aaf39daa3576..44dedd84038a9829b1c69db9e1d7d93a65d6b4c3 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0
@@ -21,8 +21,6 @@
 #include "ctfe.h"
 #include "errors.h"
 
-Expression *semantic(Expression *e, Scope *sc);
-
 /*************************************
  * If variable has a const initializer,
  * return that initializer.
@@ -36,7 +34,7 @@ Expression *expandVar(int result, VarDeclaration *v)
     if (!v)
         return e;
     if (!v->originalType && v->semanticRun < PASSsemanticdone) // semantic() not yet run
-        v->semantic(NULL);
+        dsymbolSemantic(v, NULL);
 
     if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest)
     {
@@ -97,7 +95,7 @@ Expression *expandVar(int result, VarDeclaration *v)
                     {
                         // const var initialized with non-const expression
                         ei = ei->implicitCastTo(NULL, v->type);
-                        ei = semantic(ei, NULL);
+                        ei = expressionSemantic(ei, NULL);
                     }
                     else
                         goto L1;
index bae3448b90e56c1ff5fe2936e58858fb12cdd400..c050b0504048524d87b117ea5ff916b7b6d85562 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -144,7 +144,7 @@ Dsymbols *Parser::parseModule()
                 }
                 default:
                 {
-                    error("'module' expected instead of %s", token.toChars());
+                    error("`module` expected instead of %s", token.toChars());
                     nextToken();
                     break;
                 }
@@ -195,7 +195,7 @@ Dsymbols *Parser::parseModule()
             md->msg = msg;
 
             if (token.value != TOKsemicolon)
-                error("';' expected following module declaration instead of %s", token.toChars());
+                error("`;` expected following module declaration instead of %s", token.toChars());
             nextToken();
             addComment(mod, comment);
         }
@@ -399,7 +399,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
                 }
                 else
                 {
-                    error("invariant body expected, not '%s'", token.toChars());
+                    error("invariant body expected, not `%s`", token.toChars());
                     goto Lerror;
                 }
                 break;
@@ -458,13 +458,13 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
 
             case TOKcolon:
             case TOKlcurly:
-                error("declaration expected, not '%s'",token.toChars());
+                error("declaration expected, not `%s`",token.toChars());
                 goto Lerror;
 
             case TOKrcurly:
             case TOKeof:
                 if (once)
-                    error("declaration expected, not '%s'", token.toChars());
+                    error("declaration expected, not `%s`", token.toChars());
                 return decldefs;
 
             case TOKstatic:
@@ -749,10 +749,10 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
                 if (pAttrs->protection.kind != Prot::undefined)
                 {
                     if (pAttrs->protection.kind != prot)
-                        error("conflicting protection attribute '%s' and '%s'",
+                        error("conflicting protection attribute `%s` and `%s`",
                             protectionToChars(pAttrs->protection.kind), protectionToChars(prot));
                     else
-                        error("redundant protection attribute '%s'", protectionToChars(prot));
+                        error("redundant protection attribute `%s`", protectionToChars(prot));
                 }
                 pAttrs->protection.kind = prot;
 
@@ -942,7 +942,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
                 continue;
 
             default:
-                error("declaration expected, not '%s'",token.toChars());
+                error("declaration expected, not `%s`",token.toChars());
             Lerror:
                 while (token.value != TOKsemicolon && token.value != TOKeof)
                     nextToken();
@@ -985,9 +985,9 @@ StorageClass Parser::appendStorageClass(StorageClass storageClass, StorageClass
         OutBuffer buf;
         stcToBuffer(&buf, stc);
         if (deprec)
-            deprecation("redundant attribute '%s'", buf.peekChars());
+            deprecation("redundant attribute `%s`", buf.peekChars());
         else
-            error("redundant attribute '%s'", buf.peekChars());
+            error("redundant attribute `%s`", buf.peekChars());
         return storageClass | stc;
     }
 
@@ -997,19 +997,19 @@ StorageClass Parser::appendStorageClass(StorageClass storageClass, StorageClass
     {
         StorageClass u = storageClass & (STCconst | STCimmutable | STCmanifest);
         if (u & (u - 1))
-            error("conflicting attribute '%s'", Token::toChars(token.value));
+            error("conflicting attribute `%s`", Token::toChars(token.value));
     }
     if (stc & (STCgshared | STCshared | STCtls))
     {
         StorageClass u = storageClass & (STCgshared | STCshared | STCtls);
         if (u & (u - 1))
-            error("conflicting attribute '%s'", Token::toChars(token.value));
+            error("conflicting attribute `%s`", Token::toChars(token.value));
     }
     if (stc & (STCsafe | STCsystem | STCtrusted))
     {
         StorageClass u = storageClass & (STCsafe | STCsystem | STCtrusted);
         if (u & (u - 1))
-            error("conflicting attribute '@%s'", token.toChars());
+            error("conflicting attribute `@%s`", token.toChars());
     }
 
     return storageClass;
@@ -1170,7 +1170,7 @@ Dsymbols *Parser::parseBlock(Dsymbol **pLastDecl, PrefixAttributes *pAttrs)
     switch (token.value)
     {
         case TOKsemicolon:
-            error("declaration expected following attribute, not ';'");
+            error("declaration expected following attribute, not `;`");
             nextToken();
             break;
 
@@ -1188,7 +1188,7 @@ Dsymbols *Parser::parseBlock(Dsymbol **pLastDecl, PrefixAttributes *pAttrs)
             if (token.value != TOKrcurly)
             {
                 /* { */
-                error("matching '}' expected, not %s", token.toChars());
+                error("matching `}` expected, not %s", token.toChars());
             }
             else
                 nextToken();
@@ -1439,7 +1439,7 @@ Identifiers *Parser::parseQualifiedIdentifier(const char *entity)
         nextToken();
         if (token.value != TOKidentifier)
         {
-            error("%s expected as dot-separated identifiers, got '%s'",
+            error("%s expected as dot-separated identifiers, got `%s`",
                     entity, token.toChars());
             return NULL;
         }
@@ -1620,9 +1620,9 @@ Dsymbol *Parser::parseCtor(PrefixAttributes *pAttrs)
     else if (StorageClass ss = stc & (STCshared | STCstatic))   // this()
     {
         if (ss == STCstatic)
-            error(loc, "use 'static this()' to declare a static constructor");
+            error(loc, "use `static this()` to declare a static constructor");
         else if (ss == (STCshared | STCstatic))
-            error(loc, "use 'shared static this()' to declare a shared static constructor");
+            error(loc, "use `shared static this()` to declare a shared static constructor");
     }
 
     Expression *constraint = tpl ? parseConstraint() : NULL;
@@ -1674,9 +1674,9 @@ Dsymbol *Parser::parseDtor(PrefixAttributes *pAttrs)
     if (StorageClass ss = stc & (STCshared | STCstatic))
     {
         if (ss == STCstatic)
-            error(loc, "use 'static ~this()' to declare a static destructor");
+            error(loc, "use `static ~this()` to declare a static destructor");
         else if (ss == (STCshared | STCstatic))
-            error(loc, "use 'shared static ~this()' to declare a shared static destructor");
+            error(loc, "use `shared static ~this()` to declare a shared static destructor");
     }
 
     DtorDeclaration *f = new DtorDeclaration(loc, Loc(), stc, Id::dtor);
@@ -1711,7 +1711,7 @@ Dsymbol *Parser::parseStaticCtor(PrefixAttributes *pAttrs)
 
     stc = parsePostfix(stc & ~STC_TYPECTOR, NULL) | stc;
     if (stc & STCshared)
-        error(loc, "use 'shared static this()' to declare a shared static constructor");
+        error(loc, "use `shared static this()` to declare a shared static constructor");
     else if (stc & STCstatic)
         appendStorageClass(stc, STCstatic);     // complaint for the redundancy
     else if (StorageClass modStc = stc & STC_TYPECTOR)
@@ -1749,7 +1749,7 @@ Dsymbol *Parser::parseStaticDtor(PrefixAttributes *pAttrs)
 
     stc = parsePostfix(stc & ~STC_TYPECTOR, &udas) | stc;
     if (stc & STCshared)
-        error(loc, "use 'shared static ~this()' to declare a shared static destructor");
+        error(loc, "use `shared static ~this()` to declare a shared static destructor");
     else if (stc & STCstatic)
         appendStorageClass(stc, STCstatic);     // complaint for the redundancy
     else if (StorageClass modStc = stc & STC_TYPECTOR)
@@ -2856,7 +2856,7 @@ Dsymbol *Parser::parseMixin()
         nextToken();
         if (token.value != TOKidentifier)
         {
-            error("identifier expected following '.' instead of '%s'", token.toChars());
+            error("identifier expected following `.` instead of `%s`", token.toChars());
             break;
         }
         loc = token.loc;
@@ -2874,7 +2874,7 @@ Dsymbol *Parser::parseMixin()
 
     tm = new TemplateMixin(locMixin, id, tqual, tiargs);
     if (token.value != TOKsemicolon)
-        error("';' expected after mixin");
+        error("`;` expected after mixin");
     nextToken();
 
     return tm;
@@ -3144,7 +3144,7 @@ Dsymbols *Parser::parseImport()
         nextToken();
     else
     {
-        error("';' expected");
+        error("`;` expected");
         nextToken();
     }
 
@@ -3373,7 +3373,7 @@ Type *Parser::parseBasicTypeStartingAt(TypeQualified *tid, bool dontLookDotIdent
                 nextToken();
                 if (token.value != TOKidentifier)
                 {
-                    error("identifier expected following '.' instead of '%s'", token.toChars());
+                    error("identifier expected following `.` instead of `%s`", token.toChars());
                     break;
                 }
                 if (maybeArray)
@@ -3602,7 +3602,7 @@ Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident,
             if (pident)
                 *pident = token.ident;
             else
-                error("unexpected identifer '%s' in declarator", token.ident->toChars());
+                error("unexpected identifer `%s` in declarator", token.ident->toChars());
             ts = t;
             nextToken();
             break;
@@ -3635,7 +3635,7 @@ Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident,
              */
             if (isParameters(&peekt))
             {
-                error("function declaration without return type. (Note that constructors are always named 'this')");
+                error("function declaration without return type. (Note that constructors are always named `this`)");
             }
             else
                 error("unexpected ( in declarator");
@@ -4188,7 +4188,7 @@ L2:
             if (init)
             {
                 if (isThis)
-                    error("cannot use syntax 'alias this = %s', use 'alias %s this' instead",
+                    error("cannot use syntax `alias this = %s`, use `alias %s this` instead",
                           init->toChars(), init->toChars());
                 else
                     error("alias cannot have initializer");
@@ -4332,7 +4332,7 @@ L2:
                     continue;
 
                 default:
-                    error("semicolon expected, not '%s'", token.toChars());
+                    error("semicolon expected, not `%s`", token.toChars());
                     break;
             }
         }
@@ -4511,7 +4511,7 @@ Dsymbols *Parser::parseAutoDeclarations(StorageClass storageClass, const utf8_t
                 continue;
 
             default:
-                error("semicolon expected following auto declaration, not '%s'", token.toChars());
+                error("semicolon expected following auto declaration, not `%s`", token.toChars());
                 break;
         }
         break;
@@ -4758,7 +4758,7 @@ Initializer *Parser::parseInitializer()
 
                     case TOKcomma:
                         if (comma == 2)
-                            error("expression expected, not ','");
+                            error("expression expected, not `,`");
                         nextToken();
                         comma = 2;
                         continue;
@@ -4778,7 +4778,7 @@ Initializer *Parser::parseInitializer()
                         is->addInit(NULL, value);
                         comma = 1;
                         continue;
-                        //error("found '%s' instead of field initializer", token.toChars());
+                        //error("found `%s` instead of field initializer", token.toChars());
                         //break;
                 }
                 break;
@@ -4868,7 +4868,7 @@ Initializer *Parser::parseInitializer()
 
                     case TOKcomma:
                         if (comma == 2)
-                            error("expression expected, not ','");
+                            error("expression expected, not `,`");
                         nextToken();
                         comma = 2;
                         continue;
@@ -4878,7 +4878,7 @@ Initializer *Parser::parseInitializer()
                         break;
 
                     case TOKeof:
-                        error("found '%s' instead of array initializer", token.toChars());
+                        error("found `%s` instead of array initializer", token.toChars());
                         break;
                 }
                 break;
@@ -4965,9 +4965,9 @@ void Parser::checkCstyleTypeSyntax(Loc loc, Type *t, int alt, Identifier *ident)
     const char *sp = !ident ? "" : " ";
     const char *s  = !ident ? "" : ident->toChars();
     if (alt & 1)    // contains C-style function pointer syntax
-        error(loc, "instead of C-style syntax, use D-style '%s%s%s'", t->toChars(), sp, s);
+        error(loc, "instead of C-style syntax, use D-style `%s%s%s`", t->toChars(), sp, s);
     else
-        ::warning(loc, "instead of C-style syntax, use D-style syntax '%s%s%s'", t->toChars(), sp, s);
+        ::warning(loc, "instead of C-style syntax, use D-style syntax `%s%s%s`", t->toChars(), sp, s);
 
 }
 
@@ -5408,7 +5408,7 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
 
             nextToken();
             //if (token.value == TOKsemicolon)
-                //error("use '{ }' for an empty statement, not a ';'");
+                //error("use `{ }` for an empty statement, not a `;`");
             Statements *statements = new Statements();
             while (token.value != TOKrcurly && token.value != TOKeof)
             {
@@ -5445,9 +5445,9 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
             if (!(flags & PSsemi_ok))
             {
                 if (flags & PSsemi)
-                    deprecation("use '{ }' for an empty statement, not a ';'");
+                    deprecation("use `{ }` for an empty statement, not a `;`");
                 else
-                    error("use '{ }' for an empty statement, not a ';'");
+                    error("use `{ }` for an empty statement, not a `;`");
             }
             nextToken();
             s = new ExpStatement(loc, (Expression *)NULL);
@@ -5469,7 +5469,7 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
             if (token.value == TOKsemicolon)
                 nextToken();
             else
-                error("terminating ';' required after do-while statement");
+                error("terminating `;` required after do-while statement");
             s = new DoStatement(loc, body, condition, token.loc);
             break;
         }
@@ -6052,7 +6052,7 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
 
                         if (toklist || label)
                         {
-                            error("asm statements must end in ';'");
+                            error("asm statements must end in `;`");
                         }
                         break;
 
@@ -6078,7 +6078,7 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
 
                     case TOKeof:
                         /* { */
-                        error("matching '}' expected, not end of file");
+                        error("matching `}` expected, not end of file");
                         goto Lerror;
                         /* fall through */
 
@@ -6116,7 +6116,7 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
         }
 
         default:
-            error("found '%s' instead of statement", token.toChars());
+            error("found `%s` instead of statement", token.toChars());
             goto Lerror;
 
         Lerror:
@@ -6142,14 +6142,14 @@ void Parser::check(TOK value)
 void Parser::check(Loc loc, TOK value)
 {
     if (token.value != value)
-        error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value));
+        error(loc, "found `%s` when expecting `%s`", token.toChars(), Token::toChars(value));
     nextToken();
 }
 
 void Parser::check(TOK value, const char *string)
 {
     if (token.value != value)
-        error("found '%s' when expecting '%s' following %s",
+        error("found `%s` when expecting `%s` following %s",
             token.toChars(), Token::toChars(value), string);
     nextToken();
 }
@@ -6992,7 +6992,7 @@ Expression *Parser::parsePrimaryExp()
 
         case TOKdollar:
             if (!inBrackets)
-                error("'$' is valid only inside [] of index or slice");
+                error("`$` is valid only inside [] of index or slice");
             e = new DollarExp(loc);
             nextToken();
             break;
@@ -7148,7 +7148,7 @@ Expression *Parser::parsePrimaryExp()
                 {
                     if (token.postfix)
                     {   if (token.postfix != postfix)
-                            error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
+                            error("mismatched string literal postfixes `'%c'` and `'%c'`", postfix, token.postfix);
                         postfix = token.postfix;
                     }
 
@@ -7204,7 +7204,7 @@ Expression *Parser::parsePrimaryExp()
             }
             check(TOKdot, t->toChars());
             if (token.value != TOKidentifier)
-            {   error("found '%s' when expecting identifier following '%s.'", token.toChars(), t->toChars());
+            {   error("found `%s` when expecting identifier following `%s.`", token.toChars(), t->toChars());
                 goto Lerr;
             }
             e = typeDotIdExp(loc, t, token.ident);
@@ -7418,7 +7418,7 @@ Expression *Parser::parsePrimaryExp()
                         e = parseAssignExp();
                     }
                     else if (keys)
-                    {   error("'key:value' expected for associative array literal");
+                    {   error("`key:value` expected for associative array literal");
                         delete keys;
                         keys = NULL;
                     }
@@ -7447,7 +7447,7 @@ Expression *Parser::parsePrimaryExp()
         }
 
         default:
-            error("expression expected, not '%s'", token.toChars());
+            error("expression expected, not `%s`", token.toChars());
         Lerr:
             // Anything for e, as long as it's not NULL
             e = new IntegerExp(loc, 0, Type::tint32);
@@ -7487,7 +7487,7 @@ Expression *Parser::parsePostExp(Expression *e)
                     continue;
                 }
                 else
-                    error("identifier expected following '.', not '%s'", token.toChars());
+                    error("identifier expected following `.`, not `%s`", token.toChars());
                 break;
 
             case TOKplusplus:
index dae7b634db4d82541433b8c158af87ed44cd39cd..82ce32546073346cac005049797dfa71db966948 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index fd76d6da846d7d4aeb0b7c8208f820d94da555be..992a117da2af7e8cad4136cf1657aa1995a756d1 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 2010-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index d08a3f8794f8a2735dfeac3918429d05c634768b..c65b674a7f51da80d365512224de6a18970fd224 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 2010-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index 633414b1530d09e6aa509f7602b5e370ddff4747..f7cb0c75184f2ca7077bce7874e30cbbccbaa315 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 2011-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 195e3beef571d26e5145a812ce8b02f4114b386b..004c43caa541cd93c1c715e61733a62289d14dd1 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 2011-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index ee107393eda3afa28e9632c37df7a8e42d57e308..af7b56f145c6ab1c312ab09a1ab153edeee7b15a 100644 (file)
@@ -21,7 +21,7 @@
  * to recognize them and generate equivalent and faster code.
  *
  * References: $(LINK2 http://blog.regehr.org/archives/1139, Fast Integer Overflow Checks)
- * Copyright: Copyright (C) 2014-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 2014-2021 by The D Language Foundation, All Rights Reserved
  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Authors:   Walter Bright
  * Source:    https://github.com/D-Programming-Language/dmd/blob/master/src/root/checkedint.c
index 66e3b04cac6af63836b1001c20f3358de52236ad..8a7d9c90d9f4b57f520fa8d8111e15f6215ad80e 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2003-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2003-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 4cdf362e598224387ba471898b3d347297da0f40..0a829f3e051edc26535d01f7114fe80bda36914d 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index 5aec84e1239480bb397be74443817fdc30bf5828..9fd176ebcb15be2a331d4c6c60123df535c955f5 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 7fcadc58aa0c7bf5cf2c9f10981e6f072aceb5c3..314b5b512c8bbd385c7088c7e39fdfe04f506af1 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index 348dce2e7fdfeee68b10a74049ce14ce5010d807..51358182b7cb04affe0a982fe360ea82ed85a9c4 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index f0e0213e701d79f970e64b55e270cd639126f883..0c5138b6ddf8f802e65e11b2625c65b5f47e6fd6 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index 6ef515c644145c3ff24f3e19f25e73b89ca548b5..52cd963d7085feb2a669dd7240274cb11778c9ea 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index 452ce30a8f594b48c654fc8923d90da4de8fafad..6a3220062132cdf7154bb8e354e4f453936d4de2 100644 (file)
@@ -2,7 +2,7 @@
  * Compiler implementation of the D programming language
  * http://dlang.org
  *
- * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * Authors:   Martin Nowak, Walter Bright, http://www.digitalmars.com
  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Source:    $(DMDSRC root/_hash.h)
index 3e1532a3a32105a59da77ac07265c008f9c81ee7..d5e3b2b090d48f24e3f0f2c1fa240b0b2ce890c3 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index 81c2e9018059d323bb265a81012f109e1999918d..7fbbfe57db32d57216a861be04a403bec79dfc96 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index da0d305aa5275efd38cb5d1652ca4e3f6b49eae5..186fbb7eb8483e510c3d73deb7f5ee15859a9bc1 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index b35da2530724f9e35a037ee6b15aa54a336e43d6..94651cdd5a49431fe8044534577f0c0062bd624d 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index 09ea44d36302e3742dcb05696a2993207bcf2d9d..768b75d27154c1e14c321597d5bd7583b73c09ca 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 2000-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index fdb8676c2b9c0670463638a8ba9a4bffec37cf18..1f603b8c658eee81bf0e18f1d45f7463938e8926 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index 274245a03077b02793c7a28c602a09b1eb832615..d998d95be7666d9dde4309121986785caaacff05 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index 7cb2dc43de3ff61dd1dd120ced1942b8e137e51d..7fee0d7297b2282e0051c064b33aa340d2c0f695 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index c2351e913c5825a13578d665159c27d4ced63091..3957c112a0782952710abd65c3d6f1c40d7c93f3 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 2010-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index 6d7037509532264f9b48bc560adfe8487f0697b8..bd53fc452c9e7d2825c2335cbb066c9edecabbd6 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 2010-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 2010-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index 15e5a02355920c24d24c136a412196dc2aec0dbf..fe14807791d628a8d45899a05c153052b006d231 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
index 8cbdbd8a91f0dc8c1dff24496638f8c357aa81f5..51304d32c3f041fe6aa13a5783082f67c52d6b61 100644 (file)
@@ -1,5 +1,5 @@
 
-/* Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index 08274af8bd479b841fbccf18e1e1ceb73bc6ba04..7d83dd170ade10f1fdd4ab5c4cbedfd609fe73ac 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 35e38c151ac070f8d4335280596e234d085e8474..ce0892606b8b532a37bd694f93f3d76ae3e23c81 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 7e1b634caca33caf23b6db9506753f8770efbeb4..ea3bf3874e15f0613f9fc4e77f789a853c5de1b4 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
diff --git a/gcc/d/dmd/semantic2.c b/gcc/d/dmd/semantic2.c
new file mode 100644 (file)
index 0000000..7bcf6ce
--- /dev/null
@@ -0,0 +1,410 @@
+
+/* Compiler implementation of the D programming language
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * written by Walter Bright
+ * http://www.digitalmars.com
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "attrib.h"
+#include "declaration.h"
+#include "errors.h"
+#include "import.h"
+#include "init.h"
+#include "module.h"
+#include "nspace.h"
+#include "objc.h"
+#include "scope.h"
+#include "staticassert.h"
+#include "template.h"
+#include "visitor.h"
+
+bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors);
+void udaExpressionEval(Scope *sc, Expressions *exps);
+Objc *objc();
+
+class Semantic2Visitor : public Visitor
+{
+public:
+    Scope *sc;
+
+    Semantic2Visitor(Scope *sc)
+    {
+        this->sc = sc;
+    }
+
+    void visit(Dsymbol *)
+    {
+        // Most Dsymbols have no further semantic analysis needed
+    }
+
+    void visit(StaticAssert *sa)
+    {
+        //printf("StaticAssert::semantic2() %s\n", toChars());
+        ScopeDsymbol *sds = new ScopeDsymbol();
+        sc = sc->push(sds);
+        sc->tinst = NULL;
+        sc->minst = NULL;
+
+        bool errors = false;
+        bool result = evalStaticCondition(sc, sa->exp, sa->exp, errors);
+        sc = sc->pop();
+        if (errors)
+        {
+            errorSupplemental(sa->loc, "while evaluating: static assert(%s)", sa->exp->toChars());
+        }
+        else if (!result)
+        {
+            if (sa->msg)
+            {
+                sc = sc->startCTFE();
+                sa->msg = expressionSemantic(sa->msg, sc);
+                sa->msg = resolveProperties(sc, sa->msg);
+                sc = sc->endCTFE();
+                sa->msg = sa->msg->ctfeInterpret();
+                if (StringExp * se = sa->msg->toStringExp())
+                {
+                    // same with pragma(msg)
+                    se = se->toUTF8(sc);
+                    sa->error("\"%.*s\"", (int)se->len, (char *)se->string);
+                }
+                else
+                    sa->error("%s", sa->msg->toChars());
+            }
+            else
+                sa->error("(%s) is false", sa->exp->toChars());
+            if (sc->tinst)
+                sc->tinst->printInstantiationTrace();
+            if (!global.gag)
+                fatal();
+        }
+    }
+
+    void visit(TemplateInstance *tempinst)
+    {
+        if (tempinst->semanticRun >= PASSsemantic2)
+            return;
+        tempinst->semanticRun = PASSsemantic2;
+        if (!tempinst->errors && tempinst->members)
+        {
+            TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration();
+            assert(tempdecl);
+
+            sc = tempdecl->_scope;
+            assert(sc);
+            sc = sc->push(tempinst->argsym);
+            sc = sc->push(tempinst);
+            sc->tinst = tempinst;
+            sc->minst = tempinst->minst;
+
+            int needGagging = (tempinst->gagged && !global.gag);
+            unsigned int olderrors = global.errors;
+            int oldGaggedErrors = -1;       // dead-store to prevent spurious warning
+            if (needGagging)
+                oldGaggedErrors = global.startGagging();
+
+            for (size_t i = 0; i < tempinst->members->length; i++)
+            {
+                Dsymbol *s = (*tempinst->members)[i];
+                semantic2(s, sc);
+                if (tempinst->gagged && global.errors != olderrors)
+                    break;
+            }
+
+            if (global.errors != olderrors)
+            {
+                if (!tempinst->errors)
+                {
+                    if (!tempdecl->literal)
+                        tempinst->error(tempinst->loc, "error instantiating");
+                    if (tempinst->tinst)
+                        tempinst->tinst->printInstantiationTrace();
+                }
+                tempinst->errors = true;
+            }
+            if (needGagging)
+                global.endGagging(oldGaggedErrors);
+
+            sc = sc->pop();
+            sc->pop();
+        }
+    }
+
+    void visit(TemplateMixin *tmix)
+    {
+        if (tmix->semanticRun >= PASSsemantic2)
+            return;
+        tmix->semanticRun = PASSsemantic2;
+        if (tmix->members)
+        {
+            assert(sc);
+            sc = sc->push(tmix->argsym);
+            sc = sc->push(tmix);
+            for (size_t i = 0; i < tmix->members->length; i++)
+            {
+                Dsymbol *s = (*tmix->members)[i];
+                semantic2(s, sc);
+            }
+            sc = sc->pop();
+            sc->pop();
+        }
+    }
+
+    void visit(VarDeclaration *vd)
+    {
+        if (vd->semanticRun < PASSsemanticdone && vd->inuse)
+            return;
+
+        //printf("VarDeclaration::semantic2('%s')\n", toChars());
+
+        if (vd->_init && !vd->toParent()->isFuncDeclaration())
+        {
+            vd->inuse++;
+            // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof
+            vd->_init = initializerSemantic(vd->_init, sc, vd->type, sc->intypeof == 1 ? INITnointerpret : INITinterpret);
+            vd->inuse--;
+        }
+        if (vd->_init && (vd->storage_class & STCmanifest))
+        {
+            /* Cannot initializer enums with CTFE classreferences and addresses of struct literals.
+             * Scan initializer looking for them. Issue error if found.
+             */
+            if (ExpInitializer *ei = vd->_init->isExpInitializer())
+            {
+                struct EnumInitializer
+                {
+                    static bool arrayHasInvalidEnumInitializer(Expressions *elems)
+                    {
+                        for (size_t i = 0; i < elems->length; i++)
+                        {
+                            Expression *e = (*elems)[i];
+                            if (e && hasInvalidEnumInitializer(e))
+                                return true;
+                        }
+                        return false;
+                    }
+
+                    static bool hasInvalidEnumInitializer(Expression *e)
+                    {
+                        if (e->op == TOKclassreference)
+                            return true;
+                        if (e->op == TOKaddress && ((AddrExp *)e)->e1->op == TOKstructliteral)
+                            return true;
+                        if (e->op == TOKarrayliteral)
+                            return arrayHasInvalidEnumInitializer(((ArrayLiteralExp *)e)->elements);
+                        if (e->op == TOKstructliteral)
+                            return arrayHasInvalidEnumInitializer(((StructLiteralExp *)e)->elements);
+                        if (e->op == TOKassocarrayliteral)
+                        {
+                            AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e;
+                            return arrayHasInvalidEnumInitializer(ae->values) ||
+                                arrayHasInvalidEnumInitializer(ae->keys);
+                        }
+                        return false;
+                    }
+                };
+                if (EnumInitializer::hasInvalidEnumInitializer(ei->exp))
+                    vd->error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead.");
+            }
+        }
+        else if (vd->_init && vd->isThreadlocal())
+        {
+            if ((vd->type->ty == Tclass) && vd->type->isMutable() && !vd->type->isShared())
+            {
+                ExpInitializer *ei = vd->_init->isExpInitializer();
+                if (ei && ei->exp->op == TOKclassreference)
+                    vd->error("is mutable. Only const or immutable class thread local variable are allowed, not %s", vd->type->toChars());
+            }
+            else if (vd->type->ty == Tpointer && vd->type->nextOf()->ty == Tstruct && vd->type->nextOf()->isMutable() && !vd->type->nextOf()->isShared())
+            {
+                ExpInitializer *ei = vd->_init->isExpInitializer();
+                if (ei && ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral)
+                {
+                    vd->error("is a pointer to mutable struct. Only pointers to const, immutable or shared struct thread local variable are allowed, not %s", vd->type->toChars());
+                }
+            }
+        }
+        vd->semanticRun = PASSsemantic2done;
+    }
+
+    void visit(Module *mod)
+    {
+        //printf("Module::semantic2('%s'): parent = %p\n", toChars(), mod->parent);
+        if (mod->semanticRun != PASSsemanticdone)       // semantic() not completed yet - could be recursive call
+            return;
+        mod->semanticRun = PASSsemantic2;
+
+        // Note that modules get their own scope, from scratch.
+        // This is so regardless of where in the syntax a module
+        // gets imported, it is unaffected by context.
+        Scope *sc = Scope::createGlobal(mod);      // create root scope
+        //printf("Module = %p\n", sc.scopesym);
+
+        // Pass 2 semantic routines: do initializers and function bodies
+        for (size_t i = 0; i < mod->members->length; i++)
+        {
+            Dsymbol *s = (*mod->members)[i];
+            semantic2(s, sc);
+        }
+
+        if (mod->userAttribDecl)
+        {
+            semantic2(mod->userAttribDecl, sc);
+        }
+
+        sc = sc->pop();
+        sc->pop();
+        mod->semanticRun = PASSsemantic2done;
+        //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), mod->parent);
+    }
+
+    void visit(FuncDeclaration *fd)
+    {
+        if (fd->semanticRun >= PASSsemantic2done)
+            return;
+        assert(fd->semanticRun <= PASSsemantic2);
+        fd->semanticRun = PASSsemantic2;
+
+        objc()->setSelector(fd, sc);
+        objc()->validateSelector(fd);
+
+        if (fd->parent->isClassDeclaration())
+        {
+            objc()->checkLinkage(fd);
+        }
+        if (!fd->type || fd->type->ty != Tfunction)
+            return;
+        TypeFunction *f = fd->type->toTypeFunction();
+        const size_t nparams = f->parameterList.length();
+        // semantic for parameters' UDAs
+        for (size_t i = 0; i < nparams; i++)
+        {
+            Parameter *param = f->parameterList[i];
+            if (param && param->userAttribDecl)
+                semantic2(param->userAttribDecl, sc);
+        }
+    }
+
+    void visit(Import *i)
+    {
+        //printf("Import::semantic2('%s')\n", toChars());
+        if (i->mod)
+        {
+            semantic2(i->mod, NULL);
+            if (i->mod->needmoduleinfo)
+            {
+                //printf("module5 %s because of %s\n", sc->_module->toChars(), i->mod->toChars());
+                if (sc)
+                    sc->_module->needmoduleinfo = 1;
+            }
+        }
+    }
+
+    void visit(Nspace *ns)
+    {
+        if (ns->semanticRun >= PASSsemantic2)
+            return;
+        ns->semanticRun = PASSsemantic2;
+        if (ns->members)
+        {
+            assert(sc);
+            sc = sc->push(ns);
+            sc->linkage = LINKcpp;
+            for (size_t i = 0; i < ns->members->length; i++)
+            {
+                Dsymbol *s = (*ns->members)[i];
+                semantic2(s, sc);
+            }
+            sc->pop();
+        }
+    }
+
+    void visit(AttribDeclaration *ad)
+    {
+        Dsymbols *d = ad->include(sc);
+
+        if (d)
+        {
+            Scope *sc2 = ad->newScope(sc);
+
+            for (size_t i = 0; i < d->length; i++)
+            {
+                Dsymbol *s = (*d)[i];
+                semantic2(s, sc2);
+            }
+
+            if (sc2 != sc)
+                sc2->pop();
+        }
+    }
+
+    /**
+     * Run the DeprecatedDeclaration's semantic2 phase then its members.
+     *
+     * The message set via a `DeprecatedDeclaration` can be either of:
+     * - a string literal
+     * - an enum
+     * - a static immutable
+     * So we need to call ctfe to resolve it.
+     * Afterward forwards to the members' semantic2.
+     */
+    void visit(DeprecatedDeclaration *dd)
+    {
+        dd->getMessage();
+        visit((AttribDeclaration *)dd);
+    }
+
+    void visit(AlignDeclaration *ad)
+    {
+        ad->getAlignment(sc);
+        visit((AttribDeclaration *)ad);
+    }
+
+    void visit(UserAttributeDeclaration *uad)
+    {
+        if (uad->decl && uad->atts && uad->atts->length && uad->_scope)
+        {
+            uad->_scope = NULL;
+            udaExpressionEval(sc, uad->atts);
+        }
+        visit((AttribDeclaration *)uad);
+    }
+
+    void visit(AggregateDeclaration *ad)
+    {
+        //printf("AggregateDeclaration::semantic2(%s) type = %s, errors = %d\n", toChars(), ad->type->toChars(), ad->errors);
+        if (!ad->members)
+            return;
+
+        if (ad->_scope)
+        {
+            ad->error("has forward references");
+            return;
+        }
+
+        Scope *sc2 = ad->newScope(sc);
+
+        ad->determineSize(ad->loc);
+
+        for (size_t i = 0; i < ad->members->length; i++)
+        {
+            Dsymbol *s = (*ad->members)[i];
+            //printf("\t[%d] %s\n", i, s->toChars());
+            semantic2(s, sc2);
+        }
+
+        sc2->pop();
+    }
+};
+
+/*************************************
+ * Does semantic analysis on initializers and members of aggregates.
+ */
+void semantic2(Dsymbol *dsym, Scope *sc)
+{
+    Semantic2Visitor v(sc);
+    dsym->accept(&v);
+}
diff --git a/gcc/d/dmd/semantic3.c b/gcc/d/dmd/semantic3.c
new file mode 100644 (file)
index 0000000..304eaee
--- /dev/null
@@ -0,0 +1,1421 @@
+
+/* Compiler implementation of the D programming language
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * written by Walter Bright
+ * http://www.digitalmars.com
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "attrib.h"
+#include "declaration.h"
+#include "errors.h"
+#include "id.h"
+#include "init.h"
+#include "module.h"
+#include "nspace.h"
+#include "scope.h"
+#include "statement.h"
+#include "statement_rewrite_walker.h"
+#include "target.h"
+#include "template.h"
+#include "visitor.h"
+
+bool allowsContractWithoutBody(FuncDeclaration *funcdecl);
+int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
+bool checkReturnEscape(Scope *sc, Expression *e, bool gag);
+bool checkReturnEscapeRef(Scope *sc, Expression *e, bool gag);
+TypeIdentifier *getThrowable();
+char *MODtoChars(MOD mod);
+Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
+void allocFieldinit(Scope *sc, size_t dim);
+void freeFieldinit(Scope *sc);
+
+/* Determine if function should add `return 0;`
+ */
+static bool addReturn0(FuncDeclaration *funcdecl)
+{
+    TypeFunction *f = (TypeFunction *)funcdecl->type;
+
+    return f->next->ty == Tvoid &&
+        (funcdecl->isMain() || (global.params.betterC && funcdecl->isCMain()));
+}
+
+/********************************************************
+ * Generate Expression to call the invariant.
+ * Input:
+ *      ad      aggregate with the invariant
+ *      vthis   variable with 'this'
+ * Returns:
+ *      void expression that calls the invariant
+ */
+static Expression *addInvariant(AggregateDeclaration *ad, VarDeclaration *vthis)
+{
+    Expression *e = NULL;
+
+    // Call invariant directly only if it exists
+    FuncDeclaration *inv = ad->inv;
+    ClassDeclaration *cd = ad->isClassDeclaration();
+
+    while (!inv && cd)
+    {
+        cd = cd->baseClass;
+        if (!cd)
+            break;
+        inv = cd->inv;
+    }
+    if (inv)
+    {
+    #if 1
+        // Workaround for bugzilla 13394: For the correct mangling,
+        // run attribute inference on inv if needed.
+        inv->functionSemantic();
+    #endif
+
+        //e = new DsymbolExp(Loc(), inv);
+        //e = new CallExp(Loc(), e);
+        //dsymbolSemantic(e, sc2);
+
+        /* https://issues.dlang.org/show_bug.cgi?id=13113
+         * Currently virtual invariant calls completely
+         * bypass attribute enforcement.
+         * Change the behavior of pre-invariant call by following it.
+         */
+        e = new ThisExp(Loc());
+        e->type = vthis->type;
+        e = new DotVarExp(Loc(), e, inv, false);
+        e->type = inv->type;
+        e = new CallExp(Loc(), e);
+        e->type = Type::tvoid;
+    }
+    return e;
+}
+
+/* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
+ */
+class NrvoWalker : public StatementRewriteWalker
+{
+public:
+    FuncDeclaration *fd;
+    Scope *sc;
+
+    void visit(ReturnStatement *s)
+    {
+        // See if all returns are instead to be replaced with a goto returnLabel;
+        if (fd->returnLabel)
+        {
+            /* Rewrite:
+             *  return exp;
+             * as:
+             *  vresult = exp; goto Lresult;
+             */
+            GotoStatement *gs = new GotoStatement(s->loc, Id::returnLabel);
+            gs->label = fd->returnLabel;
+
+            Statement *s1 = gs;
+            if (s->exp)
+                s1 = new CompoundStatement(s->loc, new ExpStatement(s->loc, s->exp), gs);
+
+            replaceCurrent(s1);
+        }
+    }
+    void visit(TryFinallyStatement *s)
+    {
+        DtorExpStatement *des;
+        if (fd->nrvo_can &&
+            s->finalbody && (des = s->finalbody->isDtorExpStatement()) != NULL &&
+            fd->nrvo_var == des->var)
+        {
+            if (!(global.params.useExceptions && ClassDeclaration::throwable))
+            {
+                /* Don't need to call destructor at all, since it is nrvo
+                 */
+                replaceCurrent(s->_body);
+                s->_body->accept(this);
+                return;
+            }
+
+            /* Normally local variable dtors are called regardless exceptions.
+             * But for nrvo_var, its dtor should be called only when exception is thrown.
+             *
+             * Rewrite:
+             *      try { s->body; } finally { nrvo_var->edtor; }
+             *      // equivalent with:
+             *      //    s->body; scope(exit) nrvo_var->edtor;
+             * as:
+             *      try { s->body; } catch(Throwable __o) { nrvo_var->edtor; throw __o; }
+             *      // equivalent with:
+             *      //    s->body; scope(failure) nrvo_var->edtor;
+             */
+            Statement *sexception = new DtorExpStatement(Loc(), fd->nrvo_var->edtor, fd->nrvo_var);
+            Identifier *id = Identifier::generateId("__o");
+
+            Statement *handler = new PeelStatement(sexception);
+            if (blockExit(sexception, fd, false) & BEfallthru)
+            {
+                ThrowStatement *ts = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id));
+                ts->internalThrow = true;
+                handler = new CompoundStatement(Loc(), handler, ts);
+            }
+
+            Catches *catches = new Catches();
+            Catch *ctch = new Catch(Loc(), getThrowable(), id, handler);
+            ctch->internalCatch = true;
+            catchSemantic(ctch, sc);     // Run semantic to resolve identifier '__o'
+            catches->push(ctch);
+
+            Statement *s2 = new TryCatchStatement(Loc(), s->_body, catches);
+            replaceCurrent(s2);
+            s2->accept(this);
+        }
+        else
+            StatementRewriteWalker::visit(s);
+    }
+};
+
+class Semantic3Visitor : public Visitor
+{
+public:
+    Scope *sc;
+
+    Semantic3Visitor(Scope *sc)
+    {
+        this->sc = sc;
+    }
+
+    void visit(Dsymbol *)
+    {
+        // Most Dsymbols have no further semantic analysis needed
+    }
+
+    void visit(TemplateInstance *tempinst)
+    {
+        //if (tempinst->toChars()[0] == 'D') *(char*)0=0;
+        if (tempinst->semanticRun >= PASSsemantic3)
+            return;
+        tempinst->semanticRun = PASSsemantic3;
+        if (!tempinst->errors && tempinst->members)
+        {
+            TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration();
+            assert(tempdecl);
+
+            sc = tempdecl->_scope;
+            sc = sc->push(tempinst->argsym);
+            sc = sc->push(tempinst);
+            sc->tinst = tempinst;
+            sc->minst = tempinst->minst;
+
+            int needGagging = (tempinst->gagged && !global.gag);
+            unsigned int olderrors = global.errors;
+            int oldGaggedErrors = -1;       // dead-store to prevent spurious warning
+            /* If this is a gagged instantiation, gag errors.
+             * Future optimisation: If the results are actually needed, errors
+             * would already be gagged, so we don't really need to run semantic
+             * on the members.
+             */
+            if (needGagging)
+                oldGaggedErrors = global.startGagging();
+
+            for (size_t i = 0; i < tempinst->members->length; i++)
+            {
+                Dsymbol *s = (*tempinst->members)[i];
+                semantic3(s, sc);
+                if (tempinst->gagged && global.errors != olderrors)
+                    break;
+            }
+
+            if (global.errors != olderrors)
+            {
+                if (!tempinst->errors)
+                {
+                    if (!tempdecl->literal)
+                        tempinst->error(tempinst->loc, "error instantiating");
+                    if (tempinst->tinst)
+                        tempinst->tinst->printInstantiationTrace();
+                }
+                tempinst->errors = true;
+            }
+            if (needGagging)
+                global.endGagging(oldGaggedErrors);
+
+            sc = sc->pop();
+            sc->pop();
+        }
+    }
+
+    void visit(TemplateMixin *tmix)
+    {
+        if (tmix->semanticRun >= PASSsemantic3)
+            return;
+        tmix->semanticRun = PASSsemantic3;
+        if (tmix->members)
+        {
+            sc = sc->push(tmix->argsym);
+            sc = sc->push(tmix);
+            for (size_t i = 0; i < tmix->members->length; i++)
+            {
+                Dsymbol *s = (*tmix->members)[i];
+                semantic3(s, sc);
+            }
+            sc = sc->pop();
+            sc->pop();
+        }
+    }
+
+    void visit(Module *mod)
+    {
+        //printf("Module::semantic3('%s'): parent = %p\n", mod->toChars(), mod->parent);
+        if (mod->semanticRun != PASSsemantic2done)
+            return;
+        mod->semanticRun = PASSsemantic3;
+
+        // Note that modules get their own scope, from scratch.
+        // This is so regardless of where in the syntax a module
+        // gets imported, it is unaffected by context.
+        Scope *sc = Scope::createGlobal(mod);      // create root scope
+        //printf("Module = %p\n", sc.scopesym);
+
+        // Pass 3 semantic routines: do initializers and function bodies
+        for (size_t i = 0; i < mod->members->length; i++)
+        {
+            Dsymbol *s = (*mod->members)[i];
+            //printf("Module %s: %s.semantic3()\n", mod->toChars(), s->toChars());
+            semantic3(s, sc);
+
+            mod->runDeferredSemantic2();
+        }
+
+        if (mod->userAttribDecl)
+        {
+            semantic3(mod->userAttribDecl, sc);
+        }
+
+        sc = sc->pop();
+        sc->pop();
+        mod->semanticRun = PASSsemantic3done;
+    }
+
+    void visit(FuncDeclaration *funcdecl)
+    {
+        VarDeclaration *_arguments = NULL;
+
+        if (!funcdecl->parent)
+        {
+            if (global.errors)
+                return;
+            //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", funcdecl->kind(), funcdecl->toChars(), sc);
+            assert(0);
+        }
+        if (funcdecl->errors || isError(funcdecl->parent))
+        {
+            funcdecl->errors = true;
+            return;
+        }
+        //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", funcdecl->parent->toChars(), funcdecl->toChars(), funcdecl, sc, funcdecl->loc.toChars());
+        //fflush(stdout);
+        //printf("storage class = x%x %x\n", sc->stc, funcdecl->storage_class);
+        //{ static int x; if (++x == 2) *(char*)0=0; }
+        //printf("\tlinkage = %d\n", sc->linkage);
+
+        if (funcdecl->ident == Id::assign && !funcdecl->inuse)
+        {
+            if (funcdecl->storage_class & STCinference)
+            {
+                /* Bugzilla 15044: For generated opAssign function, any errors
+                 * from its body need to be gagged.
+                 */
+                unsigned oldErrors = global.startGagging();
+                funcdecl->inuse++;
+                semantic3(funcdecl, sc);
+                funcdecl->inuse--;
+                if (global.endGagging(oldErrors))   // if errors happened
+                {
+                    // Disable generated opAssign, because some members forbid identity assignment.
+                    funcdecl->storage_class |= STCdisable;
+                    funcdecl->fbody = NULL;   // remove fbody which contains the error
+                    funcdecl->semantic3Errors = false;
+                }
+                return;
+            }
+        }
+
+        //printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract));
+        if (funcdecl->semanticRun >= PASSsemantic3)
+            return;
+        funcdecl->semanticRun = PASSsemantic3;
+        funcdecl->semantic3Errors = false;
+
+        if (!funcdecl->type || funcdecl->type->ty != Tfunction)
+            return;
+        TypeFunction *f = (TypeFunction *)funcdecl->type;
+        if (!funcdecl->inferRetType && f->next->ty == Terror)
+            return;
+
+        if (!funcdecl->fbody && funcdecl->inferRetType && !f->next)
+        {
+            funcdecl->error("has no function body with return type inference");
+            return;
+        }
+
+        unsigned oldErrors = global.errors;
+
+        if (funcdecl->frequires)
+        {
+            for (size_t i = 0; i < funcdecl->foverrides.length; i++)
+            {
+                FuncDeclaration *fdv = funcdecl->foverrides[i];
+
+                if (fdv->fbody && !fdv->frequires)
+                {
+                    funcdecl->error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars());
+                    break;
+                }
+            }
+        }
+
+        // Remember whether we need to generate an 'out' contract.
+        const bool needEnsure = FuncDeclaration::needsFensure(funcdecl);
+
+        if (funcdecl->fbody || funcdecl->frequires || needEnsure)
+        {
+            /* Symbol table into which we place parameters and nested functions,
+             * solely to diagnose name collisions.
+             */
+            funcdecl->localsymtab = new DsymbolTable();
+
+            // Establish function scope
+            ScopeDsymbol *ss = new ScopeDsymbol();
+            // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
+            for (Scope *scx = sc; ; scx = scx->enclosing)
+            {
+                if (scx->scopesym)
+                {
+                    ss->parent = scx->scopesym;
+                    break;
+                }
+            }
+            ss->loc = funcdecl->loc;
+            ss->endlinnum = funcdecl->endloc.linnum;
+            Scope *sc2 = sc->push(ss);
+            sc2->func = funcdecl;
+            sc2->parent = funcdecl;
+            sc2->callSuper = 0;
+            sc2->sbreak = NULL;
+            sc2->scontinue = NULL;
+            sc2->sw = NULL;
+            sc2->fes = funcdecl->fes;
+            sc2->linkage = LINKd;
+            sc2->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCabstract |
+                          STCdeprecated | STCoverride |
+                          STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | STCreturn |
+                          STCproperty | STCnothrow | STCpure | STCsafe | STCtrusted | STCsystem);
+            sc2->protection = Prot(Prot::public_);
+            sc2->explicitProtection = 0;
+            sc2->aligndecl = NULL;
+            if (funcdecl->ident != Id::require && funcdecl->ident != Id::ensure)
+                sc2->flags = sc->flags & ~SCOPEcontract;
+            sc2->flags &= ~SCOPEcompile;
+            sc2->tf = NULL;
+            sc2->os = NULL;
+            sc2->noctor = 0;
+            sc2->userAttribDecl = NULL;
+            if (sc2->intypeof == 1) sc2->intypeof = 2;
+            sc2->fieldinit = NULL;
+            sc2->fieldinit_dim = 0;
+
+            /* Note: When a lambda is defined immediately under aggregate member
+             * scope, it should be contextless due to prevent interior pointers.
+             * e.g.
+             *      // dg points 'this' - it's interior pointer
+             *      class C { int x; void delegate() dg = (){ this.x = 1; }; }
+             *
+             * However, lambdas could be used inside typeof, in order to check
+             * some expressions varidity at compile time. For such case the lambda
+             * body can access aggregate instance members.
+             * e.g.
+             *      class C { int x; static assert(is(typeof({ this.x = 1; }))); }
+             *
+             * To properly accept it, mark these lambdas as member functions.
+             */
+            if (FuncLiteralDeclaration *fld = funcdecl->isFuncLiteralDeclaration())
+            {
+                if (AggregateDeclaration *ad = funcdecl->isMember2())
+                {
+                    if (!sc->intypeof)
+                    {
+                        if (fld->tok == TOKdelegate)
+                            funcdecl->error("cannot be %s members", ad->kind());
+                        else
+                            fld->tok = TOKfunction;
+                    }
+                    else
+                    {
+                        if (fld->tok != TOKfunction)
+                            fld->tok = TOKdelegate;
+                    }
+                }
+            }
+
+            // Declare 'this'
+            AggregateDeclaration *ad = funcdecl->isThis();
+            funcdecl->vthis = funcdecl->declareThis(sc2, ad);
+            //printf("[%s] ad = %p vthis = %p\n", funcdecl->loc.toChars(), ad, funcdecl->vthis);
+            //if (funcdecl->vthis) printf("\tvthis->type = %s\n", funcdecl->vthis->type->toChars());
+
+            // Declare hidden variable _arguments[] and _argptr
+            if (f->parameterList.varargs == VARARGvariadic)
+            {
+                if (f->linkage == LINKd)
+                {
+                    // Variadic arguments depend on Typeinfo being defined
+                    if (!global.params.useTypeInfo || !Type::dtypeinfo || !Type::typeinfotypelist)
+                    {
+                        if (!global.params.useTypeInfo)
+                            funcdecl->error("D-style variadic functions cannot be used with -betterC");
+                        else if (!Type::typeinfotypelist)
+                            funcdecl->error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
+                        else
+                            funcdecl->error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
+                        fatal();
+                    }
+
+                    // Declare _arguments[]
+                    funcdecl->v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
+                    funcdecl->v_arguments->storage_class |= STCtemp | STCparameter;
+                    dsymbolSemantic(funcdecl->v_arguments, sc2);
+                    sc2->insert(funcdecl->v_arguments);
+                    funcdecl->v_arguments->parent = funcdecl;
+
+                    //Type *t = Type::typeinfo->type->constOf()->arrayOf();
+                    Type *t = Type::dtypeinfo->type->arrayOf();
+                    _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
+                    _arguments->storage_class |= STCtemp;
+                    dsymbolSemantic(_arguments, sc2);
+                    sc2->insert(_arguments);
+                    _arguments->parent = funcdecl;
+                }
+                if (f->linkage == LINKd || f->parameterList.length())
+                {
+                    // Declare _argptr
+                    Type *t = target.va_listType(funcdecl->loc, sc);
+                    funcdecl->v_argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
+                    funcdecl->v_argptr->storage_class |= STCtemp;
+                    dsymbolSemantic(funcdecl->v_argptr, sc2);
+                    sc2->insert(funcdecl->v_argptr);
+                    funcdecl->v_argptr->parent = funcdecl;
+                }
+            }
+
+            /* Declare all the function parameters as variables
+             * and install them in parameters[]
+             */
+            size_t nparams = f->parameterList.length();
+            if (nparams)
+            {
+                /* parameters[] has all the tuples removed, as the back end
+                 * doesn't know about tuples
+                 */
+                funcdecl->parameters = new VarDeclarations();
+                funcdecl->parameters->reserve(nparams);
+                for (size_t i = 0; i < nparams; i++)
+                {
+                    Parameter *fparam = f->parameterList[i];
+                    Identifier *id = fparam->ident;
+                    StorageClass stc = 0;
+                    if (!id)
+                    {
+                        /* Generate identifier for un-named parameter,
+                         * because we need it later on.
+                         */
+                        fparam->ident = id = Identifier::generateId("_param_", i);
+                        stc |= STCtemp;
+                    }
+                    Type *vtype = fparam->type;
+                    VarDeclaration *v = new VarDeclaration(funcdecl->loc, vtype, id, NULL);
+                    //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
+                    stc |= STCparameter;
+                    if (f->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
+                        stc |= STCvariadic;
+                    if (funcdecl->flags & FUNCFLAGinferScope && !(fparam->storageClass & STCscope))
+                        stc |= STCmaybescope;
+                    stc |= fparam->storageClass & (STCin | STCout | STCref | STCreturn | STCscope | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
+                    v->storage_class = stc;
+                    dsymbolSemantic(v, sc2);
+                    if (!sc2->insert(v))
+                        funcdecl->error("parameter %s.%s is already defined", funcdecl->toChars(), v->toChars());
+                    else
+                        funcdecl->parameters->push(v);
+                    funcdecl->localsymtab->insert(v);
+                    v->parent = funcdecl;
+                    if (fparam->userAttribDecl)
+                        v->userAttribDecl = fparam->userAttribDecl;
+                }
+            }
+
+            // Declare the tuple symbols and put them in the symbol table,
+            // but not in parameters[].
+            if (f->parameterList.parameters)
+            {
+                for (size_t i = 0; i < f->parameterList.parameters->length; i++)
+                {
+                    Parameter *fparam = (*f->parameterList.parameters)[i];
+
+                    if (!fparam->ident)
+                        continue;                   // never used, so ignore
+                    if (fparam->type->ty == Ttuple)
+                    {
+                        TypeTuple *t = (TypeTuple *)fparam->type;
+                        size_t dim = Parameter::dim(t->arguments);
+                        Objects *exps = new Objects();
+                        exps->setDim(dim);
+                        for (size_t j = 0; j < dim; j++)
+                        {
+                            Parameter *narg = Parameter::getNth(t->arguments, j);
+                            assert(narg->ident);
+                            VarDeclaration *v = sc2->search(Loc(), narg->ident, NULL)->isVarDeclaration();
+                            assert(v);
+                            Expression *e = new VarExp(v->loc, v);
+                            (*exps)[j] = e;
+                        }
+                        assert(fparam->ident);
+                        TupleDeclaration *v = new TupleDeclaration(funcdecl->loc, fparam->ident, exps);
+                        //printf("declaring tuple %s\n", v->toChars());
+                        v->isexp = true;
+                        if (!sc2->insert(v))
+                            funcdecl->error("parameter %s.%s is already defined", funcdecl->toChars(), v->toChars());
+                        funcdecl->localsymtab->insert(v);
+                        v->parent = funcdecl;
+                    }
+                }
+            }
+
+            // Precondition invariant
+            Statement *fpreinv = NULL;
+            if (funcdecl->addPreInvariant())
+            {
+                Expression *e = addInvariant(ad, funcdecl->vthis);
+                if (e)
+                    fpreinv = new ExpStatement(Loc(), e);
+            }
+
+            // Postcondition invariant
+            Statement *fpostinv = NULL;
+            if (funcdecl->addPostInvariant())
+            {
+                Expression *e = addInvariant(ad, funcdecl->vthis);
+                if (e)
+                    fpostinv = new ExpStatement(Loc(), e);
+            }
+
+            // Pre/Postcondition contract
+            if (!funcdecl->fbody)
+                funcdecl->buildEnsureRequire();
+
+            Scope *scout = NULL;
+            if (needEnsure || funcdecl->addPostInvariant())
+            {
+                if ((needEnsure && global.params.useOut == CHECKENABLEon) || fpostinv)
+                {
+                    funcdecl->returnLabel = new LabelDsymbol(Id::returnLabel);
+                }
+
+                // scope of out contract (need for vresult->semantic)
+                ScopeDsymbol *sym = new ScopeDsymbol();
+                sym->parent = sc2->scopesym;
+                sym->loc = funcdecl->loc;
+                sym->endlinnum = funcdecl->endloc.linnum;
+                scout = sc2->push(sym);
+            }
+
+            if (funcdecl->fbody)
+            {
+                ScopeDsymbol *sym = new ScopeDsymbol();
+                sym->parent = sc2->scopesym;
+                sym->loc = funcdecl->loc;
+                sym->endlinnum = funcdecl->endloc.linnum;
+                sc2 = sc2->push(sym);
+
+                AggregateDeclaration *ad2 = funcdecl->isMember2();
+
+                /* If this is a class constructor
+                */
+                if (ad2 && funcdecl->isCtorDeclaration())
+                {
+                    allocFieldinit(sc2, ad2->fields.length);
+                    for (size_t i = 0; i < ad2->fields.length; i++)
+                    {
+                        VarDeclaration *v = ad2->fields[i];
+                        v->ctorinit = 0;
+                    }
+                }
+
+                bool inferRef = (f->isref && (funcdecl->storage_class & STCauto));
+
+                funcdecl->fbody = statementSemantic(funcdecl->fbody, sc2);
+                if (!funcdecl->fbody)
+                    funcdecl->fbody = new CompoundStatement(Loc(), new Statements());
+
+                if (funcdecl->naked)
+                {
+                    fpreinv = NULL;         // can't accommodate with no stack frame
+                    fpostinv = NULL;
+                }
+
+                assert(funcdecl->type == f ||
+                       (funcdecl->type->ty == Tfunction &&
+                        f->purity == PUREimpure &&
+                        ((TypeFunction *)funcdecl->type)->purity >= PUREfwdref));
+                f = (TypeFunction *)funcdecl->type;
+
+                if (funcdecl->inferRetType)
+                {
+                    // If no return type inferred yet, then infer a void
+                    if (!f->next)
+                        f->next = Type::tvoid;
+                    if (f->checkRetType(funcdecl->loc))
+                        funcdecl->fbody = new ErrorStatement();
+                }
+                if (global.params.vcomplex && f->next != NULL)
+                    f->next->checkComplexTransition(funcdecl->loc);
+
+                if (funcdecl->returns && !funcdecl->fbody->isErrorStatement())
+                {
+                    for (size_t i = 0; i < funcdecl->returns->length; )
+                    {
+                        Expression *exp = (*funcdecl->returns)[i]->exp;
+                        if (exp->op == TOKvar && ((VarExp *)exp)->var == funcdecl->vresult)
+                        {
+                            if (addReturn0(funcdecl))
+                                exp->type = Type::tint32;
+                            else
+                                exp->type = f->next;
+                            // Remove `return vresult;` from returns
+                            funcdecl->returns->remove(i);
+                            continue;
+                        }
+                        if (inferRef && f->isref && !exp->type->constConv(f->next))     // Bugzilla 13336
+                            f->isref = false;
+                        i++;
+                    }
+                }
+                if (f->isref)   // Function returns a reference
+                {
+                    if (funcdecl->storage_class & STCauto)
+                        funcdecl->storage_class &= ~STCauto;
+                }
+                if (!target.isReturnOnStack(f, funcdecl->needThis()) || !funcdecl->checkNRVO())
+                    funcdecl->nrvo_can = 0;
+
+                if (funcdecl->fbody->isErrorStatement())
+                    ;
+                else if (funcdecl->isStaticCtorDeclaration())
+                {
+                    /* It's a static constructor. Ensure that all
+                     * ctor consts were initialized.
+                     */
+                    ScopeDsymbol *pd = funcdecl->toParent()->isScopeDsymbol();
+                    for (size_t i = 0; i < pd->members->length; i++)
+                    {
+                        Dsymbol *s = (*pd->members)[i];
+                        s->checkCtorConstInit();
+                    }
+                }
+                else if (ad2 && funcdecl->isCtorDeclaration())
+                {
+                    ClassDeclaration *cd = ad2->isClassDeclaration();
+
+                    // Verify that all the ctorinit fields got initialized
+                    if (!(sc2->callSuper & CSXthis_ctor))
+                    {
+                        for (size_t i = 0; i < ad2->fields.length; i++)
+                        {
+                            VarDeclaration *v = ad2->fields[i];
+                            if (v->isThisDeclaration())
+                                continue;
+                            if (v->ctorinit == 0)
+                            {
+                                /* Current bugs in the flow analysis:
+                                 * 1. union members should not produce error messages even if
+                                 *    not assigned to
+                                 * 2. structs should recognize delegating opAssign calls as well
+                                 *    as delegating calls to other constructors
+                                 */
+                                if (v->isCtorinit() && !v->type->isMutable() && cd)
+                                    funcdecl->error("missing initializer for %s field %s", MODtoChars(v->type->mod), v->toChars());
+                                else if (v->storage_class & STCnodefaultctor)
+                                    error(funcdecl->loc, "field %s must be initialized in constructor", v->toChars());
+                                else if (v->type->needsNested())
+                                    error(funcdecl->loc, "field %s must be initialized in constructor, because it is nested struct", v->toChars());
+                            }
+                            else
+                            {
+                                bool mustInit = (v->storage_class & STCnodefaultctor ||
+                                                 v->type->needsNested());
+                                if (mustInit && !(sc2->fieldinit[i] & CSXthis_ctor))
+                                {
+                                    funcdecl->error("field %s must be initialized but skipped", v->toChars());
+                                }
+                            }
+                        }
+                    }
+                    freeFieldinit(sc2);
+
+                    if (cd &&
+                        !(sc2->callSuper & CSXany_ctor) &&
+                        cd->baseClass && cd->baseClass->ctor)
+                    {
+                        sc2->callSuper = 0;
+
+                        // Insert implicit super() at start of fbody
+                        FuncDeclaration *fd = resolveFuncCall(Loc(), sc2, cd->baseClass->ctor, NULL, funcdecl->vthis->type, NULL, 1);
+                        if (!fd)
+                        {
+                            funcdecl->error("no match for implicit super() call in constructor");
+                        }
+                        else if (fd->storage_class & STCdisable)
+                        {
+                            funcdecl->error("cannot call super() implicitly because it is annotated with @disable");
+                        }
+                        else
+                        {
+                            Expression *e1 = new SuperExp(Loc());
+                            Expression *e = new CallExp(Loc(), e1);
+                            e = expressionSemantic(e, sc2);
+
+                            Statement *s = new ExpStatement(Loc(), e);
+                            funcdecl->fbody = new CompoundStatement(Loc(), s, funcdecl->fbody);
+                        }
+                    }
+                    //printf("callSuper = x%x\n", sc2->callSuper);
+                }
+
+                /* https://issues.dlang.org/show_bug.cgi?id=17502
+                 * Wait until after the return type has been inferred before
+                 * generating the contracts for this function, and merging contracts
+                 * from overrides.
+                 *
+                 * https://issues.dlang.org/show_bug.cgi?id=17893
+                 * However should take care to generate this before inferered
+                 * function attributes are applied, such as 'nothrow'.
+                 *
+                 * This was originally at the end of the first semantic pass, but
+                 * required a fix-up to be done here for the '__result' variable
+                 * type of __ensure() inside auto functions, but this didn't work
+                 * if the out parameter was implicit.
+                 */
+                funcdecl->buildEnsureRequire();
+
+                int blockexit = BEnone;
+                if (!funcdecl->fbody->isErrorStatement())
+                {
+                    // Check for errors related to 'nothrow'.
+                    unsigned int nothrowErrors = global.errors;
+                    blockexit = blockExit(funcdecl->fbody, funcdecl, f->isnothrow);
+                    if (f->isnothrow && (global.errors != nothrowErrors))
+                        error(funcdecl->loc, "nothrow %s `%s` may throw", funcdecl->kind(), funcdecl->toPrettyChars());
+                    if (funcdecl->flags & FUNCFLAGnothrowInprocess)
+                    {
+                        if (funcdecl->type == f) f = (TypeFunction *)f->copy();
+                        f->isnothrow = !(blockexit & BEthrow);
+                    }
+                }
+
+                if (funcdecl->fbody->isErrorStatement())
+                    ;
+                else if (ad2 && funcdecl->isCtorDeclaration())
+                {
+                    /* Append:
+                     *  return this;
+                     * to function body
+                     */
+                    if (blockexit & BEfallthru)
+                    {
+                        Statement *s = new ReturnStatement(funcdecl->loc, NULL);
+                        s = statementSemantic(s, sc2);
+                        funcdecl->fbody = new CompoundStatement(funcdecl->loc, funcdecl->fbody, s);
+                        funcdecl->hasReturnExp |= (funcdecl->hasReturnExp & 1 ? 16 : 1);
+                    }
+                }
+                else if (funcdecl->fes)
+                {
+                    // For foreach(){} body, append a return 0;
+                    if (blockexit & BEfallthru)
+                    {
+                        Expression *e = new IntegerExp(0);
+                        Statement *s = new ReturnStatement(Loc(), e);
+                        funcdecl->fbody = new CompoundStatement(Loc(), funcdecl->fbody, s);
+                        funcdecl->hasReturnExp |= (funcdecl->hasReturnExp & 1 ? 16 : 1);
+                    }
+                    assert(!funcdecl->returnLabel);
+                }
+                else
+                {
+                    const bool inlineAsm = (funcdecl->hasReturnExp & 8) != 0;
+                    if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm)
+                    {
+                        Expression *e;
+                        if (!funcdecl->hasReturnExp)
+                            funcdecl->error("has no return statement, but is expected to return a value of type %s", f->next->toChars());
+                        else
+                            funcdecl->error("no return exp; or assert(0); at end of function");
+                        if (global.params.useAssert == CHECKENABLEon &&
+                            !global.params.useInline)
+                        {
+                            /* Add an assert(0, msg); where the missing return
+                             * should be.
+                             */
+                            e = new AssertExp(funcdecl->endloc,
+                                              new IntegerExp(0),
+                                              new StringExp(funcdecl->loc, const_cast<char *>("missing return expression")));
+                        }
+                        else
+                            e = new HaltExp(funcdecl->endloc);
+                        e = new CommaExp(Loc(), e, f->next->defaultInit());
+                        e = expressionSemantic(e, sc2);
+                        Statement *s = new ExpStatement(Loc(), e);
+                        funcdecl->fbody = new CompoundStatement(Loc(), funcdecl->fbody, s);
+                    }
+                }
+
+                if (funcdecl->returns)
+                {
+                    bool implicit0 = addReturn0(funcdecl);
+                    Type *tret = implicit0 ? Type::tint32 : f->next;
+                    assert(tret->ty != Tvoid);
+                    if (funcdecl->vresult || funcdecl->returnLabel)
+                        funcdecl->buildResultVar(scout ? scout : sc2, tret);
+
+                    /* Cannot move this loop into NrvoWalker, because
+                     * returns[i] may be in the nested delegate for foreach-body.
+                     */
+                    for (size_t i = 0; i < funcdecl->returns->length; i++)
+                    {
+                        ReturnStatement *rs = (*funcdecl->returns)[i];
+                        Expression *exp = rs->exp;
+                        if (exp->op == TOKerror)
+                            continue;
+                        if (tret->ty == Terror)
+                        {
+                            // Bugzilla 13702
+                            exp = checkGC(sc2, exp);
+                            continue;
+                        }
+
+                        if (!exp->implicitConvTo(tret) &&
+                            funcdecl->parametersIntersect(exp->type))
+                        {
+                            if (exp->type->immutableOf()->implicitConvTo(tret))
+                                exp = exp->castTo(sc2, exp->type->immutableOf());
+                            else if (exp->type->wildOf()->implicitConvTo(tret))
+                                exp = exp->castTo(sc2, exp->type->wildOf());
+                        }
+                        exp = exp->implicitCastTo(sc2, tret);
+
+                        if (f->isref)
+                        {
+                            // Function returns a reference
+                            exp = exp->toLvalue(sc2, exp);
+                            checkReturnEscapeRef(sc2, exp, false);
+                        }
+                        else
+                        {
+                            exp = exp->optimize(WANTvalue);
+
+                            /* Bugzilla 10789:
+                             * If NRVO is not possible, all returned lvalues should call their postblits.
+                             */
+                            if (!funcdecl->nrvo_can)
+                                exp = doCopyOrMove(sc2, exp);
+
+                            if (tret->hasPointers())
+                                checkReturnEscape(sc2, exp, false);
+                        }
+
+                        exp = checkGC(sc2, exp);
+
+                        if (funcdecl->vresult)
+                        {
+                            // Create: return vresult = exp;
+                            exp = new BlitExp(rs->loc, funcdecl->vresult, exp);
+                            exp->type = funcdecl->vresult->type;
+
+                            if (rs->caseDim)
+                                exp = Expression::combine(exp, new IntegerExp(rs->caseDim));
+                        }
+                        else if (funcdecl->tintro && !tret->equals(funcdecl->tintro->nextOf()))
+                        {
+                            exp = exp->implicitCastTo(sc2, funcdecl->tintro->nextOf());
+                        }
+                        rs->exp = exp;
+                    }
+                }
+                if (funcdecl->nrvo_var || funcdecl->returnLabel)
+                {
+                    NrvoWalker nw;
+                    nw.fd = funcdecl;
+                    nw.sc = sc2;
+                    nw.visitStmt(funcdecl->fbody);
+                }
+
+                sc2 = sc2->pop();
+            }
+
+            funcdecl->frequire = funcdecl->mergeFrequire(funcdecl->frequire);
+            funcdecl->fensure = funcdecl->mergeFensure(funcdecl->fensure, Id::result);
+
+            Statement *freq = funcdecl->frequire;
+            Statement *fens = funcdecl->fensure;
+
+            /* Do the semantic analysis on the [in] preconditions and
+             * [out] postconditions.
+             */
+            if (freq)
+            {
+                /* frequire is composed of the [in] contracts
+                */
+                ScopeDsymbol *sym = new ScopeDsymbol();
+                sym->parent = sc2->scopesym;
+                sym->loc = funcdecl->loc;
+                sym->endlinnum = funcdecl->endloc.linnum;
+                sc2 = sc2->push(sym);
+                sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire;
+
+                // BUG: need to error if accessing out parameters
+                // BUG: need to disallow returns and throws
+                // BUG: verify that all in and ref parameters are read
+                freq = statementSemantic(freq, sc2);
+                blockExit(freq, funcdecl, false);
+
+                sc2 = sc2->pop();
+
+                if (global.params.useIn == CHECKENABLEoff)
+                    freq = NULL;
+            }
+
+            if (fens)
+            {
+                /* fensure is composed of the [out] contracts
+                */
+                if (f->next->ty == Tvoid && funcdecl->fensures)
+                {
+                    for (size_t i = 0; i < funcdecl->fensures->length; i++)
+                    {
+                        Ensure e = (*funcdecl->fensures)[i];
+                        if (e.id)
+                        {
+                            funcdecl->error(e.ensure->loc, "`void` functions have no result");
+                            //fens = NULL;
+                        }
+                    }
+                }
+
+                sc2 = scout;    //push
+                sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure;
+
+                // BUG: need to disallow returns and throws
+                if (funcdecl->fensure && f->next->ty != Tvoid)
+                    funcdecl->buildResultVar(scout, f->next);
+
+                fens = statementSemantic(fens, sc2);
+                blockExit(fens, funcdecl, false);
+
+                sc2 = sc2->pop();
+
+                if (global.params.useOut == CHECKENABLEoff)
+                    fens = NULL;
+            }
+
+            if (funcdecl->fbody && funcdecl->fbody->isErrorStatement())
+                ;
+            else
+            {
+                Statements *a = new Statements();
+
+                // Merge in initialization of 'out' parameters
+                if (funcdecl->parameters)
+                {
+                    for (size_t i = 0; i < funcdecl->parameters->length; i++)
+                    {
+                        VarDeclaration *v = (*funcdecl->parameters)[i];
+                        if (v->storage_class & STCout)
+                        {
+                            assert(v->_init);
+                            ExpInitializer *ie = v->_init->isExpInitializer();
+                            assert(ie);
+                            if (ie->exp->op == TOKconstruct)
+                                ie->exp->op = TOKassign; // construction occured in parameter processing
+                            a->push(new ExpStatement(Loc(), ie->exp));
+                        }
+                    }
+                }
+
+                if (funcdecl->v_argptr)
+                {
+                    // Handled in FuncDeclaration::toObjFile
+                    funcdecl->v_argptr->_init = new VoidInitializer(funcdecl->loc);
+                }
+
+                if (_arguments)
+                {
+                    /* Advance to elements[] member of TypeInfo_Tuple with:
+                     *  _arguments = v_arguments.elements;
+                     */
+                    Expression *e = new VarExp(Loc(), funcdecl->v_arguments);
+                    e = new DotIdExp(Loc(), e, Id::elements);
+                    e = new ConstructExp(Loc(), _arguments, e);
+                    e = expressionSemantic(e, sc2);
+
+                    _arguments->_init = new ExpInitializer(Loc(), e);
+                    DeclarationExp *de = new DeclarationExp(Loc(), _arguments);
+                    a->push(new ExpStatement(Loc(), de));
+                }
+
+                // Merge contracts together with body into one compound statement
+
+                if (freq || fpreinv)
+                {
+                    if (!freq)
+                        freq = fpreinv;
+                    else if (fpreinv)
+                        freq = new CompoundStatement(Loc(), freq, fpreinv);
+
+                    a->push(freq);
+                }
+
+                if (funcdecl->fbody)
+                    a->push(funcdecl->fbody);
+
+                if (fens || fpostinv)
+                {
+                    if (!fens)
+                        fens = fpostinv;
+                    else if (fpostinv)
+                        fens = new CompoundStatement(Loc(), fpostinv, fens);
+
+                    LabelStatement *ls = new LabelStatement(Loc(), Id::returnLabel, fens);
+                    funcdecl->returnLabel->statement = ls;
+                    a->push(funcdecl->returnLabel->statement);
+
+                    if (f->next->ty != Tvoid && funcdecl->vresult)
+                    {
+                        // Create: return vresult;
+                        Expression *e = new VarExp(Loc(), funcdecl->vresult);
+                        if (funcdecl->tintro)
+                        {
+                            e = e->implicitCastTo(sc, funcdecl->tintro->nextOf());
+                            e = expressionSemantic(e, sc);
+                        }
+                        ReturnStatement *s = new ReturnStatement(Loc(), e);
+                        a->push(s);
+                    }
+                }
+                if (addReturn0(funcdecl))
+                {
+                    // Add a return 0; statement
+                    Statement *s = new ReturnStatement(Loc(), new IntegerExp(0));
+                    a->push(s);
+                }
+
+                Statement *sbody = new CompoundStatement(Loc(), a);
+                /* Append destructor calls for parameters as finally blocks.
+                */
+                if (funcdecl->parameters)
+                {
+                    for (size_t i = 0; i < funcdecl->parameters->length; i++)
+                    {
+                        VarDeclaration *v = (*funcdecl->parameters)[i];
+
+                        if (v->storage_class & (STCref | STCout | STClazy))
+                            continue;
+
+                        if (v->needsScopeDtor())
+                        {
+                            // same with ExpStatement.scopeCode()
+                            Statement *s = new DtorExpStatement(Loc(), v->edtor, v);
+                            v->storage_class |= STCnodtor;
+
+                            s = statementSemantic(s, sc2);
+
+                            bool isnothrow = f->isnothrow & !(funcdecl->flags & FUNCFLAGnothrowInprocess);
+                            int blockexit = blockExit(s, funcdecl, isnothrow);
+                            if (f->isnothrow && isnothrow && blockexit & BEthrow)
+                                error(funcdecl->loc, "nothrow %s `%s` may throw", funcdecl->kind(), funcdecl->toPrettyChars());
+                            if (funcdecl->flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
+                                f->isnothrow = false;
+                            if (blockExit(sbody, funcdecl, f->isnothrow) == BEfallthru)
+                                sbody = new CompoundStatement(Loc(), sbody, s);
+                            else
+                                sbody = new TryFinallyStatement(Loc(), sbody, s);
+                        }
+                    }
+                }
+                // from this point on all possible 'throwers' are checked
+                funcdecl->flags &= ~FUNCFLAGnothrowInprocess;
+
+                if (funcdecl->isSynchronized())
+                {
+                    /* Wrap the entire function body in a synchronized statement
+                    */
+                    ClassDeclaration *cd = funcdecl->isThis() ? funcdecl->isThis()->isClassDeclaration() : funcdecl->parent->isClassDeclaration();
+
+                    if (cd)
+                    {
+                        if (!global.params.is64bit &&
+                            global.params.isWindows &&
+                            !funcdecl->isStatic() && !sbody->usesEH() && !global.params.trace)
+                        {
+                            /* The back end uses the "jmonitor" hack for syncing;
+                             * no need to do the sync at this level.
+                             */
+                        }
+                        else
+                        {
+                            Expression *vsync;
+                            if (funcdecl->isStatic())
+                            {
+                                // The monitor is in the ClassInfo
+                                vsync = new DotIdExp(funcdecl->loc, resolve(funcdecl->loc, sc2, cd, false), Id::classinfo);
+                            }
+                            else
+                            {
+                                // 'this' is the monitor
+                                vsync = new VarExp(funcdecl->loc, funcdecl->vthis);
+                            }
+                            sbody = new PeelStatement(sbody);       // don't redo semantic()
+                            sbody = new SynchronizedStatement(funcdecl->loc, vsync, sbody);
+                            sbody = statementSemantic(sbody, sc2);
+                        }
+                    }
+                    else
+                    {
+                        funcdecl->error("synchronized function %s must be a member of a class", funcdecl->toChars());
+                    }
+                }
+
+                // If declaration has no body, don't set sbody to prevent incorrect codegen.
+                if (funcdecl->fbody || allowsContractWithoutBody(funcdecl))
+                    funcdecl->fbody = sbody;
+            }
+
+            // Fix up forward-referenced gotos
+            if (funcdecl->gotos)
+            {
+                for (size_t i = 0; i < funcdecl->gotos->length; ++i)
+                {
+                    (*funcdecl->gotos)[i]->checkLabel();
+                }
+            }
+
+            if (funcdecl->naked && (funcdecl->fensures || funcdecl->frequires))
+                funcdecl->error("naked assembly functions with contracts are not supported");
+
+            sc2->callSuper = 0;
+            sc2->pop();
+        }
+
+        if (funcdecl->checkClosure())
+        {
+            // We should be setting errors here instead of relying on the global error count.
+            //errors = true;
+        }
+
+        /* If function survived being marked as impure, then it is pure
+        */
+        if (funcdecl->flags & FUNCFLAGpurityInprocess)
+        {
+            funcdecl->flags &= ~FUNCFLAGpurityInprocess;
+            if (funcdecl->type == f)
+                f = (TypeFunction *)f->copy();
+            f->purity = PUREfwdref;
+        }
+
+        if (funcdecl->flags & FUNCFLAGsafetyInprocess)
+        {
+            funcdecl->flags &= ~FUNCFLAGsafetyInprocess;
+            if (funcdecl->type == f)
+                f = (TypeFunction *)f->copy();
+            f->trust = TRUSTsafe;
+        }
+
+        if (funcdecl->flags & FUNCFLAGnogcInprocess)
+        {
+            funcdecl->flags &= ~FUNCFLAGnogcInprocess;
+            if (funcdecl->type == f)
+                f = (TypeFunction *)f->copy();
+            f->isnogc = true;
+        }
+
+        if (funcdecl->flags & FUNCFLAGreturnInprocess)
+        {
+            funcdecl->flags &= ~FUNCFLAGreturnInprocess;
+            if (funcdecl->storage_class & STCreturn)
+            {
+                if (funcdecl->type == f)
+                    f = (TypeFunction *)f->copy();
+                f->isreturn = true;
+            }
+        }
+
+        funcdecl->flags &= ~FUNCFLAGinferScope;
+
+        // Infer STCscope
+        if (funcdecl->parameters)
+        {
+            size_t nfparams = f->parameterList.length();
+            assert(nfparams == funcdecl->parameters->length);
+            for (size_t u = 0; u < funcdecl->parameters->length; u++)
+            {
+                VarDeclaration *v = (*funcdecl->parameters)[u];
+                if (v->storage_class & STCmaybescope)
+                {
+                    //printf("Inferring scope for %s\n", v->toChars());
+                    Parameter *p = f->parameterList[u];
+                    v->storage_class &= ~STCmaybescope;
+                    v->storage_class |= STCscope | STCscopeinferred;
+                    p->storageClass |= STCscope | STCscopeinferred;
+                    assert(!(p->storageClass & STCmaybescope));
+                }
+            }
+        }
+
+        if (funcdecl->vthis && funcdecl->vthis->storage_class & STCmaybescope)
+        {
+            funcdecl->vthis->storage_class &= ~STCmaybescope;
+            funcdecl->vthis->storage_class |= STCscope | STCscopeinferred;
+            f->isscope = true;
+            f->isscopeinferred = true;
+        }
+
+        // reset deco to apply inference result to mangled name
+        if (f != funcdecl->type)
+            f->deco = NULL;
+
+        // Do semantic type AFTER pure/nothrow inference.
+        if (!f->deco && funcdecl->ident != Id::xopEquals && funcdecl->ident != Id::xopCmp)
+        {
+            sc = sc->push();
+            if (funcdecl->isCtorDeclaration()) // Bugzilla #15665
+                sc->flags |= SCOPEctor;
+            sc->stc = 0;
+            sc->linkage = funcdecl->linkage;  // Bugzilla 8496
+            funcdecl->type = typeSemantic(f, funcdecl->loc, sc);
+            sc = sc->pop();
+        }
+
+        /* If this function had instantiated with gagging, error reproduction will be
+         * done by TemplateInstance::semantic.
+         * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
+         */
+        funcdecl->semanticRun = PASSsemantic3done;
+        funcdecl->semantic3Errors = (global.errors != oldErrors) || (funcdecl->fbody && funcdecl->fbody->isErrorStatement());
+        if (funcdecl->type->ty == Terror)
+            funcdecl->errors = true;
+        //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", funcdecl->parent->toChars(), funcdecl->toChars(), sc, funcdecl->loc.toChars());
+        //fflush(stdout);
+    }
+
+    void visit(Nspace *ns)
+    {
+        if (ns->semanticRun >= PASSsemantic3)
+            return;
+        ns->semanticRun = PASSsemantic3;
+        if (ns->members)
+        {
+            sc = sc->push(ns);
+            sc->linkage = LINKcpp;
+            for (size_t i = 0; i < ns->members->length; i++)
+            {
+                Dsymbol *s = (*ns->members)[i];
+                semantic3(s, sc);
+            }
+            sc->pop();
+        }
+    }
+
+    void visit(AttribDeclaration *ad)
+    {
+        Dsymbols *d = ad->include(sc);
+
+        if (d)
+        {
+            Scope *sc2 = ad->newScope(sc);
+
+            for (size_t i = 0; i < d->length; i++)
+            {
+                Dsymbol *s = (*d)[i];
+                semantic3(s, sc2);
+            }
+
+            if (sc2 != sc)
+                sc2->pop();
+        }
+    }
+
+    void visit(AggregateDeclaration *ad)
+    {
+        //printf("AggregateDeclaration::semantic3(%s) type = %s, errors = %d\n", ad->toChars(), ad->type->toChars(), ad->errors);
+        if (!ad->members)
+            return;
+
+        StructDeclaration *sd = ad->isStructDeclaration();
+        if (!sc)    // from runDeferredSemantic3 for TypeInfo generation
+        {
+            assert(sd);
+            sd->semanticTypeInfoMembers();
+            return;
+        }
+
+        Scope *sc2 = ad->newScope(sc);
+
+        for (size_t i = 0; i < ad->members->length; i++)
+        {
+            Dsymbol *s = (*ad->members)[i];
+            semantic3(s, sc2);
+        }
+
+        sc2->pop();
+
+        // don't do it for unused deprecated types
+        // or error types
+        if (!ad->getRTInfo && Type::rtinfo &&
+            (!ad->isDeprecated() || global.params.useDeprecated != DIAGNOSTICerror) &&
+            (ad->type && ad->type->ty != Terror))
+        {
+            // Evaluate: RTinfo!type
+            Objects *tiargs = new Objects();
+            tiargs->push(ad->type);
+            TemplateInstance *ti = new TemplateInstance(ad->loc, Type::rtinfo, tiargs);
+
+            Scope *sc3 = ti->tempdecl->_scope->startCTFE();
+            sc3->tinst = sc->tinst;
+            sc3->minst = sc->minst;
+            if (ad->isDeprecated())
+                sc3->stc |= STCdeprecated;
+
+            dsymbolSemantic(ti, sc3);
+            semantic2(ti, sc3);
+            semantic3(ti, sc3);
+            Expression *e = resolve(Loc(), sc3, ti->toAlias(), false);
+
+            sc3->endCTFE();
+
+            e = e->ctfeInterpret();
+            ad->getRTInfo = e;
+        }
+
+        if (sd)
+            sd->semanticTypeInfoMembers();
+        ad->semanticRun = PASSsemantic3done;
+    }
+};
+
+/*************************************
+ * Does semantic analysis on function bodies.
+ */
+void semantic3(Dsymbol *dsym, Scope *sc)
+{
+    Semantic3Visitor v(sc);
+    dsym->accept(&v);
+}
index efab276d8496fae7807a0f0c2c517b5a355c801a..661bd43134c8ee5c2d44b818ab2fcafe56a3a9db 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -25,7 +25,6 @@
 
 bool walkPostorder(Expression *e, StoppableVisitor *v);
 bool lambdaHasSideEffect(Expression *e);
-Expression *semantic(Expression *e, Scope *sc);
 
 /**************************************************
  * Front-end expression rewriting should create temporary variables for
@@ -425,8 +424,8 @@ Expression *extractSideEffect(Scope *sc, const char *name,
 
     Expression *de = new DeclarationExp(vd->loc, vd);
     Expression *ve = new VarExp(vd->loc, vd);
-    de = semantic(de, sc);
-    ve = semantic(ve, sc);
+    de = expressionSemantic(de, sc);
+    ve = expressionSemantic(ve, sc);
 
     *e0 = Expression::combine(*e0, de);
     return ve;
index 76dfe1d3f06f33d910d4c30110e0d0ab0bc00e5a..2f7b7e13ffcb3a5f41a0565f7b9d3816de4ab5d2 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -30,8 +30,6 @@ bool walkPostorder(Statement *s, StoppableVisitor *v);
 StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
 bool checkEscapeRef(Scope *sc, Expression *e, bool gag);
 VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
-Expression *semantic(Expression *e, Scope *sc);
-StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
 Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion);
 
 Identifier *fixupLabelName(Scope *sc, Identifier *ident)
@@ -470,7 +468,7 @@ Statements *ExpStatement::flatten(Scope *sc)
         Dsymbol *d = ((DeclarationExp *)exp)->declaration;
         if (TemplateMixin *tm = d->isTemplateMixin())
         {
-            Expression *e = semantic(exp, sc);
+            Expression *e = expressionSemantic(exp, sc);
             if (e->op == TOKerror || tm->errors)
             {
                 Statements *a = new Statements();
@@ -1143,12 +1141,12 @@ static bool checkVar(SwitchStatement *s, VarDeclaration *vd)
     }
     else if (vd->ident == Id::withSym)
     {
-        s->deprecation("'switch' skips declaration of 'with' temporary at %s", vd->loc.toChars());
+        s->deprecation("`switch` skips declaration of `with` temporary at %s", vd->loc.toChars());
         return true;
     }
     else
     {
-        s->deprecation("'switch' skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars());
+        s->deprecation("`switch` skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars());
         return true;
     }
 
@@ -1471,7 +1469,7 @@ Statement *ScopeGuardStatement::scopeCode(Scope *sc, Statement **sentry, Stateme
              *  sfinally: if (!x) statement;
              */
             VarDeclaration *v = copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool));
-            v->semantic(sc);
+            dsymbolSemantic(v, sc);
             *sentry = new ExpStatement(loc, v);
 
             Expression *e = new IntegerExp(Loc(), 1, Type::tbool);
@@ -1558,7 +1556,7 @@ bool GotoStatement::checkLabel()
 {
     if (!label->statement)
     {
-        error("label '%s' is undefined", label->toChars());
+        error("label `%s` is undefined", label->toChars());
         return true;
     }
 
index 08eb5fd0fa5121416d6e31ec87b094cd44c567f6..2d8b46c94874d22a298416ba3b7cf94133372ec9 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -23,6 +23,7 @@ struct Scope;
 class Expression;
 class LabelDsymbol;
 class Identifier;
+class Statement;
 class IfStatement;
 class ExpStatement;
 class DefaultStatement;
@@ -38,6 +39,7 @@ class StaticAssert;
 class AsmStatement;
 class GotoStatement;
 class ScopeStatement;
+class Catch;
 class TryCatchStatement;
 class TryFinallyStatement;
 class CaseStatement;
@@ -48,6 +50,11 @@ class StaticForeach;
 // Back end
 struct code;
 
+Statement *statementSemantic(Statement *s, Scope *sc);
+Statement *semanticNoScope(Statement *s, Scope *sc);
+Statement *semanticScope(Statement *s, Scope *sc, Statement *sbreak, Statement *scontinue);
+void catchSemantic(Catch *c, Scope *sc);
+
 bool inferAggregate(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply);
 bool inferApplyArgTypes(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply);
 
diff --git a/gcc/d/dmd/statement_rewrite_walker.h b/gcc/d/dmd/statement_rewrite_walker.h
new file mode 100644 (file)
index 0000000..28a930a
--- /dev/null
@@ -0,0 +1,172 @@
+
+/* Compiler implementation of the D programming language
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * written by Walter Bright
+ * http://www.digitalmars.com
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#include "statement.h"
+#include "visitor.h"
+
+/* A visitor to walk entire statements and provides ability to replace any sub-statements.
+ */
+class StatementRewriteWalker : public Visitor
+{
+    /* Point the currently visited statement.
+     * By using replaceCurrent() method, you can replace AST during walking.
+     */
+    Statement **ps;
+public:
+    void visitStmt(Statement *&s) { ps = &s; s->accept(this); }
+    void replaceCurrent(Statement *s) { *ps = s; }
+
+    void visit(ErrorStatement *) {  }
+    void visit(PeelStatement *s)
+    {
+        if (s->s)
+            visitStmt(s->s);
+    }
+    void visit(ExpStatement *) {  }
+    void visit(DtorExpStatement *) {  }
+    void visit(CompileStatement *) {  }
+    void visit(CompoundStatement *s)
+    {
+        if (s->statements && s->statements->length)
+        {
+            for (size_t i = 0; i < s->statements->length; i++)
+            {
+                if ((*s->statements)[i])
+                    visitStmt((*s->statements)[i]);
+            }
+        }
+    }
+    void visit(CompoundDeclarationStatement *s) { visit((CompoundStatement *)s); }
+    void visit(UnrolledLoopStatement *s)
+    {
+        if (s->statements && s->statements->length)
+        {
+            for (size_t i = 0; i < s->statements->length; i++)
+            {
+                if ((*s->statements)[i])
+                    visitStmt((*s->statements)[i]);
+            }
+        }
+    }
+    void visit(ScopeStatement *s)
+    {
+        if (s->statement)
+            visitStmt(s->statement);
+    }
+    void visit(WhileStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(DoStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(ForStatement *s)
+    {
+        if (s->_init)
+            visitStmt(s->_init);
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(ForeachStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(ForeachRangeStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(IfStatement *s)
+    {
+        if (s->ifbody)
+            visitStmt(s->ifbody);
+        if (s->elsebody)
+            visitStmt(s->elsebody);
+    }
+    void visit(ConditionalStatement *) {  }
+    void visit(PragmaStatement *) {  }
+    void visit(StaticAssertStatement *) {  }
+    void visit(SwitchStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(CaseStatement *s)
+    {
+        if (s->statement)
+            visitStmt(s->statement);
+    }
+    void visit(CaseRangeStatement *s)
+    {
+        if (s->statement)
+            visitStmt(s->statement);
+    }
+    void visit(DefaultStatement *s)
+    {
+        if (s->statement)
+            visitStmt(s->statement);
+    }
+    void visit(GotoDefaultStatement *) {  }
+    void visit(GotoCaseStatement *) {  }
+    void visit(SwitchErrorStatement *) {  }
+    void visit(ReturnStatement *) {  }
+    void visit(BreakStatement *) {  }
+    void visit(ContinueStatement *) {  }
+    void visit(SynchronizedStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(WithStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+    }
+    void visit(TryCatchStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+        if (s->catches && s->catches->length)
+        {
+            for (size_t i = 0; i < s->catches->length; i++)
+            {
+                Catch *c = (*s->catches)[i];
+                if (c && c->handler)
+                    visitStmt(c->handler);
+            }
+        }
+    }
+    void visit(TryFinallyStatement *s)
+    {
+        if (s->_body)
+            visitStmt(s->_body);
+        if (s->finalbody)
+            visitStmt(s->finalbody);
+    }
+    void visit(ScopeGuardStatement *) {  }
+    void visit(ThrowStatement *) {  }
+    void visit(DebugStatement *s)
+    {
+        if (s->statement)
+            visitStmt(s->statement);
+    }
+    void visit(GotoStatement *) {  }
+    void visit(LabelStatement *s)
+    {
+        if (s->statement)
+            visitStmt(s->statement);
+    }
+    void visit(AsmStatement *) {  }
+    void visit(ImportStatement *) {  }
+};
+
index 2fe0d9efeea51f7cdf5356c14fff5989e876c4f4..5579c1ca8938a7f9029469fd7f5e733c5f03738c 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -39,11 +39,6 @@ VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
 Expression *checkAssignmentAsCondition(Expression *e);
 TypeIdentifier *getThrowable();
 
-Expression *semantic(Expression *e, Scope *sc);
-Statement *semantic(Statement *s, Scope *sc);
-void semantic(Catch *c, Scope *sc);
-Statement *semanticNoScope(Statement *s, Scope *sc);
-Statement *semanticScope(Statement *s, Scope *sc, Statement *sbreak, Statement *scontinue);
 int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
 
 class StatementSemanticVisitor : public Visitor
@@ -93,7 +88,7 @@ public:
             if (s->exp->op == TOKcomma)
                 ((CommaExp *)s->exp)->allowCommaExp = true;
 
-            s->exp = semantic(s->exp, sc);
+            s->exp = expressionSemantic(s->exp, sc);
             s->exp = resolveProperties(sc, s->exp);
             s->exp = s->exp->addDtorHook(sc);
             if (checkNonAssignmentArrayOp(s->exp))
@@ -121,7 +116,7 @@ public:
         if (!a)
             return;
         Statement *s = new CompoundStatement(cs->loc, a);
-        result = semantic(s, sc);
+        result = statementSemantic(s, sc);
     }
 
     void visit(CompoundStatement *cs)
@@ -139,7 +134,7 @@ public:
                     cs->statements->insert(i, flt);
                     continue;
                 }
-                s = semantic(s, sc);
+                s = statementSemantic(s, sc);
                 (*cs->statements)[i] = s;
                 if (s)
                 {
@@ -150,12 +145,12 @@ public:
                     (*cs->statements)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally);
                     if (sentry)
                     {
-                        sentry = semantic(sentry, sc);
+                        sentry = statementSemantic(sentry, sc);
                         cs->statements->insert(i, sentry);
                         i++;
                     }
                     if (sexception)
-                        sexception = semantic(sexception, sc);
+                        sexception = statementSemantic(sexception, sc);
                     if (sexception)
                     {
                         if (i + 1 == cs->statements->length && !sfinally)
@@ -197,7 +192,7 @@ public:
                             s = new TryCatchStatement(Loc(), body, catches);
                             if (sfinally)
                                 s = new TryFinallyStatement(Loc(), s, sfinally);
-                            s = semantic(s, sc);
+                            s = statementSemantic(s, sc);
 
                             cs->statements->setDim(i + 1);
                             cs->statements->push(s);
@@ -224,7 +219,7 @@ public:
                             }
                             Statement *body = new CompoundStatement(Loc(), a);
                             s = new TryFinallyStatement(Loc(), body, sfinally);
-                            s = semantic(s, sc);
+                            s = statementSemantic(s, sc);
                             cs->statements->setDim(i + 1);
                             cs->statements->push(s);
                             break;
@@ -290,7 +285,7 @@ public:
             if (s)
             {
                 //printf("[%d]: %s\n", i, s->toChars());
-                s = semantic(s, scd);
+                s = statementSemantic(s, scd);
                 (*uls->statements)[i] = s;
 
                 if (s && !serror)
@@ -318,7 +313,7 @@ public:
                 ss->statement = new CompoundStatement(ss->loc, a);
             }
 
-            ss->statement = semantic(ss->statement, sc);
+            ss->statement = statementSemantic(ss->statement, sc);
             if (ss->statement)
             {
                 if (ss->statement->isErrorStatement())
@@ -338,7 +333,7 @@ public:
                 if (sfinally)
                 {
                     //printf("adding sfinally\n");
-                    sfinally = semantic(sfinally, sc);
+                    sfinally = statementSemantic(sfinally, sc);
                     ss->statement = new CompoundStatement(ss->loc, ss->statement, sfinally);
                 }
             }
@@ -359,7 +354,7 @@ public:
         sc = sc->push(ss->sym);
         sc->sbreak = ss;
         sc->scontinue = ss;
-        ss->statement = semantic(ss->statement, sc);
+        ss->statement = statementSemantic(ss->statement, sc);
         sc = sc->pop();
         result = ss->statement;
     }
@@ -369,7 +364,7 @@ public:
         /* Rewrite as a for(;condition;) loop
          */
         Statement *s = new ForStatement(ws->loc, NULL, ws->condition, NULL, ws->_body, ws->endloc);
-        s = semantic(s, sc);
+        s = statementSemantic(s, sc);
         result = s;
     }
 
@@ -386,7 +381,7 @@ public:
         // check in syntax level
         ds->condition = checkAssignmentAsCondition(ds->condition);
 
-        ds->condition = semantic(ds->condition, sc);
+        ds->condition = expressionSemantic(ds->condition, sc);
         ds->condition = resolveProperties(sc, ds->condition);
         if (checkNonAssignmentArrayOp(ds->condition))
             ds->condition = new ErrorExp();
@@ -432,7 +427,7 @@ public:
             ainit->push(fs);
             Statement *s = new CompoundStatement(fs->loc, ainit);
             s = new ScopeStatement(fs->loc, s, fs->endloc);
-            s = semantic(s, sc);
+            s = statementSemantic(s, sc);
             if (!s->isErrorStatement())
             {
                 if (LabelStatement *ls = checkLabeledLoop(sc, fs))
@@ -458,7 +453,7 @@ public:
             // check in syntax level
             fs->condition = checkAssignmentAsCondition(fs->condition);
 
-            fs->condition = semantic(fs->condition, sc);
+            fs->condition = expressionSemantic(fs->condition, sc);
             fs->condition = resolveProperties(sc, fs->condition);
             if (checkNonAssignmentArrayOp(fs->condition))
                 fs->condition = new ErrorExp();
@@ -470,7 +465,7 @@ public:
         {
             if (fs->increment->op == TOKcomma)
                 ((CommaExp *)fs->increment)->allowCommaExp = true;
-            fs->increment = semantic(fs->increment, sc);
+            fs->increment = expressionSemantic(fs->increment, sc);
             fs->increment = resolveProperties(sc, fs->increment);
             if (checkNonAssignmentArrayOp(fs->increment))
                 fs->increment = new ErrorExp();
@@ -650,7 +645,7 @@ public:
                     p->type = Type::tsize_t;
                 }
             }
-            p->type = p->type->semantic(loc, sc);
+            p->type = typeSemantic(p->type, loc, sc);
             TY keyty = p->type->ty;
             if (keyty != Tint32 && keyty != Tuns32)
             {
@@ -698,7 +693,7 @@ public:
                             0, e->type, ident, e, NULL);
             Identifier *field = Identifier::idPool("tuple");
             Expression *access = new DotIdExp(loc, e, field);
-            access = semantic(access, sc);
+            access = expressionSemantic(access, sc);
             if (!tuple)
                 return false;
             //printf("%s\n", tuple->toChars());
@@ -706,7 +701,7 @@ public:
             {
                 Parameter *cp = (*fs->parameters)[l];
                 Expression *init_ = new IndexExp(loc, access, new IntegerExp(loc, l, Type::tsize_t));
-                init_ = semantic(init_, sc);
+                init_ = expressionSemantic(init_, sc);
                 assert(init_->type);
                 declareVariable(fs, paramtype, te, needExpansion, isStatic, stmts, decls,
                                 p->storageClass, init_->type, cp->ident, init_, NULL);
@@ -782,7 +777,7 @@ public:
         Type *paramtype = (*fs->parameters)[dim-1]->type;
         if (paramtype)
         {
-            paramtype = paramtype->semantic(loc, sc);
+            paramtype = typeSemantic(paramtype, loc, sc);
             if (paramtype->ty == Terror)
                 return false;
         }
@@ -853,7 +848,7 @@ public:
             fs->func = fs->func->fes->func;
 
         VarDeclaration *vinit = NULL;
-        fs->aggr = semantic(fs->aggr, sc);
+        fs->aggr = expressionSemantic(fs->aggr, sc);
         fs->aggr = resolveProperties(sc, fs->aggr);
         fs->aggr = fs->aggr->optimize(WANTvalue);
         if (fs->aggr->op == TOKerror)
@@ -866,7 +861,7 @@ public:
         {
             // Bugzilla 14653: Extend the life of rvalue aggregate till the end of foreach.
             vinit = copyToTemp(STCrvalue, "__aggr", fs->aggr);
-            vinit->semantic(sc);
+            dsymbolSemantic(vinit, sc);
             fs->aggr = new VarExp(fs->aggr->loc, vinit);
         }
 
@@ -946,7 +941,7 @@ public:
             }
             if (vinit)
                 result = new CompoundStatement(loc, new ExpStatement(loc, vinit), result);
-            result = semantic(result, sc);
+            result = statementSemantic(result, sc);
             return;
         }
 
@@ -991,7 +986,7 @@ public:
                     for (size_t i = 0; i < dim; i++)
                     {
                         Parameter *p = (*fs->parameters)[i];
-                        p->type = p->type->semantic(loc, sc2);
+                        p->type = typeSemantic(p->type, loc, sc2);
                         p->type = p->type->addStorageClass(p->storageClass);
                     }
 
@@ -1080,7 +1075,7 @@ public:
                                 IntRange dimrange = getIntRange(ta->dim);
                                 if (!IntRange::fromType(var->type).contains(dimrange))
                                 {
-                                    fs->error("index type '%s' cannot cover index range 0..%llu", p->type->toChars(), ta->dim->toInteger());
+                                    fs->error("index type `%s` cannot cover index range 0..%llu", p->type->toChars(), ta->dim->toInteger());
                                     goto Lerror2;
                                 }
                                 fs->key->range = new IntRange(SignExtendedNumber(0), dimrange.imax);
@@ -1221,7 +1216,7 @@ public:
                     s = new ForStatement(loc, forinit, cond, increment, fs->_body, fs->endloc);
                     if (LabelStatement *ls = checkLabeledLoop(sc, fs))   // Bugzilla 15450: don't use sc2
                         ls->gotoTarget = s;
-                    s = semantic(s, sc2);
+                    s = statementSemantic(s, sc2);
                     break;
                 }
 
@@ -1290,7 +1285,7 @@ public:
                     else
                     {
                         r = copyToTemp(0, "__r", fs->aggr);
-                        r->semantic(sc);
+                        dsymbolSemantic(r, sc);
                         init = new ExpStatement(loc, r);
                         if (vinit)
                             init = new CompoundStatement(loc, new ExpStatement(loc, vinit), init);
@@ -1323,7 +1318,7 @@ public:
                     else
                     {
                         VarDeclaration *vd = copyToTemp(STCref, "__front", einit);
-                        vd->semantic(sc);
+                        dsymbolSemantic(vd, sc);
                         makeargs = new ExpStatement(loc, vd);
 
                         Type *tfront = NULL;
@@ -1383,7 +1378,7 @@ public:
                             Expression *exp = (*exps)[i];
                             if (!p->type)
                                 p->type = exp->type;
-                            p->type = p->type->addStorageClass(p->storageClass)->semantic(loc, sc2);
+                            p->type = typeSemantic(p->type->addStorageClass(p->storageClass), loc, sc2);
                             if (!exp->implicitConvTo(p->type))
                                 goto Lrangeerr;
 
@@ -1400,7 +1395,7 @@ public:
                     s = new ForStatement(loc, init, condition, increment, forbody, fs->endloc);
                     if (LabelStatement *ls = checkLabeledLoop(sc, fs))
                         ls->gotoTarget = s;
-                    s = semantic(s, sc2);
+                    s = statementSemantic(s, sc2);
                     break;
 
                 Lrangeerr:
@@ -1426,7 +1421,7 @@ public:
                         if (fdapply)
                         {
                             assert(fdapply->type && fdapply->type->ty == Tfunction);
-                            tfld = (TypeFunction *)fdapply->type->semantic(loc, sc2);
+                            tfld = (TypeFunction *)typeSemantic(fdapply->type, loc, sc2);
                             goto Lget;
                         }
                         else if (tab->ty == Tdelegate)
@@ -1439,7 +1434,7 @@ public:
                                 Parameter *p = tfld->parameterList[0];
                                 if (p->type && p->type->ty == Tdelegate)
                                 {
-                                    Type *t = p->type->semantic(loc, sc2);
+                                    Type *t = typeSemantic(p->type, loc, sc2);
                                     assert(t->ty == Tdelegate);
                                     tfld = (TypeFunction *)t->nextOf();
                                 }
@@ -1457,7 +1452,7 @@ public:
                         StorageClass stc = STCref;
                         Identifier *id;
 
-                        p->type = p->type->semantic(loc, sc2);
+                        p->type = typeSemantic(p->type, loc, sc2);
                         p->type = p->type->addStorageClass(p->storageClass);
                         if (tfld)
                         {
@@ -1504,7 +1499,7 @@ public:
                     FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, Loc(), tfld, TOKdelegate, fs);
                     fld->fbody = fs->_body;
                     Expression *flde = new FuncExp(loc, fld);
-                    flde = semantic(flde, sc2);
+                    flde = expressionSemantic(flde, sc2);
                     fld->tookAddressOf = 0;
 
                     // Resolve any forward referenced goto's
@@ -1525,7 +1520,7 @@ public:
                     if (vinit)
                     {
                         e = new DeclarationExp(loc, vinit);
-                        e = semantic(e, sc2);
+                        e = expressionSemantic(e, sc2);
                         if (e->op == TOKerror)
                             goto Lerror2;
                     }
@@ -1672,7 +1667,7 @@ public:
                             fs->aggr = ((DelegateExp *)fs->aggr)->e1;
                         }
                         ec = new CallExp(loc, fs->aggr, flde);
-                        ec = semantic(ec, sc2);
+                        ec = expressionSemantic(ec, sc2);
                         if (ec->op == TOKerror)
                             goto Lerror2;
                         if (ec->type != Type::tint32)
@@ -1693,7 +1688,7 @@ public:
                          */
                         ec = new DotIdExp(loc, fs->aggr, sapply->ident);
                         ec = new CallExp(loc, ec, flde);
-                        ec = semantic(ec, sc2);
+                        ec = expressionSemantic(ec, sc2);
                         if (ec->op == TOKerror)
                             goto Lerror2;
                         if (ec->type != Type::tint32)
@@ -1732,7 +1727,7 @@ public:
                         s = new CompoundStatement(loc, a);
                         s = new SwitchStatement(loc, e, s, false);
                     }
-                    s = semantic(s, sc2);
+                    s = statementSemantic(s, sc2);
                     break;
                 }
             case Terror:
@@ -1753,7 +1748,7 @@ public:
     {
         //printf("ForeachRangeStatement::semantic() %p\n", fs);
         Loc loc = fs->loc;
-        fs->lwr = semantic(fs->lwr, sc);
+        fs->lwr = expressionSemantic(fs->lwr, sc);
         fs->lwr = resolveProperties(sc, fs->lwr);
         fs->lwr = fs->lwr->optimize(WANTvalue);
         if (!fs->lwr->type)
@@ -1763,7 +1758,7 @@ public:
             return setError();
         }
 
-        fs->upr = semantic(fs->upr, sc);
+        fs->upr = expressionSemantic(fs->upr, sc);
         fs->upr = resolveProperties(sc, fs->upr);
         fs->upr = fs->upr->optimize(WANTvalue);
         if (!fs->upr->type)
@@ -1774,7 +1769,7 @@ public:
 
         if (fs->prm->type)
         {
-            fs->prm->type = fs->prm->type->semantic(loc, sc);
+            fs->prm->type = typeSemantic(fs->prm->type, loc, sc);
             fs->prm->type = fs->prm->type->addStorageClass(fs->prm->storageClass);
             fs->lwr = fs->lwr->implicitCastTo(sc, fs->prm->type);
 
@@ -1786,7 +1781,7 @@ public:
             {
                 // See if upr-1 fits in prm->type
                 Expression *limit = new MinExp(loc, fs->upr, new IntegerExp(1));
-                limit = semantic(limit, sc);
+                limit = expressionSemantic(limit, sc);
                 limit = limit->optimize(WANTvalue);
                 if (!limit->implicitConvTo(fs->prm->type))
                 {
@@ -1934,7 +1929,7 @@ public:
         ForStatement *s = new ForStatement(loc, forinit, cond, increment, fs->_body, fs->endloc);
         if (LabelStatement *ls = checkLabeledLoop(sc, fs))
             ls->gotoTarget = s;
-        result = semantic(s, sc);
+        result = statementSemantic(s, sc);
     }
 
     void visit(IfStatement *ifs)
@@ -1961,12 +1956,12 @@ public:
             ifs->match = new VarDeclaration(ifs->loc, ifs->prm->type, ifs->prm->ident, ei);
             ifs->match->parent = sc->func;
             ifs->match->storage_class |= ifs->prm->storageClass;
-            ifs->match->semantic(scd);
+            dsymbolSemantic(ifs->match, scd);
 
             DeclarationExp *de = new DeclarationExp(ifs->loc, ifs->match);
             VarExp *ve = new VarExp(ifs->loc, ifs->match);
             ifs->condition = new CommaExp(ifs->loc, de, ve);
-            ifs->condition = semantic(ifs->condition, scd);
+            ifs->condition = expressionSemantic(ifs->condition, scd);
 
             if (ifs->match->edtor)
             {
@@ -1981,7 +1976,7 @@ public:
             if (ifs->condition->op == TOKdotid)
                 ((DotIdExp *)ifs->condition)->noderef = true;
 
-            ifs->condition = semantic(ifs->condition, sc);
+            ifs->condition = expressionSemantic(ifs->condition, sc);
             ifs->condition = resolveProperties(sc, ifs->condition);
             ifs->condition = ifs->condition->addDtorHook(sc);
         }
@@ -2033,17 +2028,17 @@ public:
             {
                 sc = sc->push();
                 sc->flags |= SCOPEdebug;
-                cs->ifbody = semantic(cs->ifbody, sc);
+                cs->ifbody = statementSemantic(cs->ifbody, sc);
                 sc->pop();
             }
             else
-                cs->ifbody = semantic(cs->ifbody, sc);
+                cs->ifbody = statementSemantic(cs->ifbody, sc);
             result = cs->ifbody;
         }
         else
         {
             if (cs->elsebody)
-                cs->elsebody = semantic(cs->elsebody, sc);
+                cs->elsebody = statementSemantic(cs->elsebody, sc);
             result = cs->elsebody;
         }
     }
@@ -2062,7 +2057,7 @@ public:
                     Expression *e = (*ps->args)[i];
 
                     sc = sc->startCTFE();
-                    e = semantic(e, sc);
+                    e = expressionSemantic(e, sc);
                     e = resolveProperties(sc, e);
                     sc = sc->endCTFE();
                     // pragma(msg) is allowed to contain types as well as expressions
@@ -2100,7 +2095,7 @@ public:
                 Expression *e = (*ps->args)[0];
 
                 sc = sc->startCTFE();
-                e = semantic(e, sc);
+                e = expressionSemantic(e, sc);
                 e = resolveProperties(sc, e);
                 sc = sc->endCTFE();
 
@@ -2109,12 +2104,12 @@ public:
                 Dsymbol *sa = getDsymbol(e);
                 if (!sa || !sa->isFuncDeclaration())
                 {
-                    ps->error("function name expected for start address, not '%s'", e->toChars());
+                    ps->error("function name expected for start address, not `%s`", e->toChars());
                     goto Lerror;
                 }
                 if (ps->_body)
                 {
-                    ps->_body = semantic(ps->_body, sc);
+                    ps->_body = statementSemantic(ps->_body, sc);
                     if (ps->_body->isErrorStatement())
                     {
                         result = ps->_body;
@@ -2172,7 +2167,7 @@ public:
                 ps->error("`pragma(%s)` is missing a terminating `;`", ps->ident->toChars());
                 return setError();
             }
-            ps->_body = semantic(ps->_body, sc);
+            ps->_body = statementSemantic(ps->_body, sc);
         }
         result = ps->_body;
         return;
@@ -2183,7 +2178,7 @@ public:
 
     void visit(StaticAssertStatement *s)
     {
-        s->sa->semantic2(sc);
+        semantic2(s->sa, sc);
     }
 
     void visit(SwitchStatement *ss)
@@ -2196,7 +2191,7 @@ public:
             return;
         }
         bool conditionError = false;
-        ss->condition = semantic(ss->condition, sc);
+        ss->condition = expressionSemantic(ss->condition, sc);
         ss->condition = resolveProperties(sc, ss->condition);
 
         Type *att = NULL;
@@ -2234,7 +2229,7 @@ public:
 
             if (ss->condition->op != TOKerror)
             {
-                ss->error("'%s' must be of integral or string type, it is a %s",
+                ss->error("`%s` must be of integral or string type, it is a %s",
                     ss->condition->toChars(), ss->condition->type->toChars());
                 conditionError = true;
                 break;
@@ -2257,7 +2252,7 @@ public:
 
         ss->cases = new CaseStatements();
         sc->noctor++;       // BUG: should use Scope::mergeCallSuper() for each case instead
-        ss->_body = semantic(ss->_body, sc);
+        ss->_body = statementSemantic(ss->_body, sc);
         sc->noctor--;
 
         if (conditionError || (ss->_body && ss->_body->isErrorStatement()))
@@ -2337,7 +2332,7 @@ public:
             ss->hasNoDefault = 1;
 
             if (!ss->isFinal && (!ss->_body || !ss->_body->isErrorStatement()))
-                ss->error("switch statement without a default; use 'final switch' or add 'default: assert(0);' or add 'default: break;'");
+                ss->error("switch statement without a default; use `final switch` or add `default: assert(0);` or add `default: break;`");
 
             // Generate runtime error if the default is hit
             Statements *a = new Statements();
@@ -2389,7 +2384,7 @@ public:
 
         //printf("CaseStatement::semantic() %s\n", cs->toChars());
         sc = sc->startCTFE();
-        cs->exp = semantic(cs->exp, sc);
+        cs->exp = expressionSemantic(cs->exp, sc);
         cs->exp = resolveProperties(sc, cs->exp);
         sc = sc->endCTFE();
         if (sw)
@@ -2502,7 +2497,7 @@ public:
             cs->error("case not in switch statement");
             errors = true;
         }
-        cs->statement = semantic(cs->statement, sc);
+        cs->statement = statementSemantic(cs->statement, sc);
         if (cs->statement->isErrorStatement())
         {
             result = cs->statement;
@@ -2533,14 +2528,14 @@ public:
         }
 
         sc = sc->startCTFE();
-        crs->first = semantic(crs->first, sc);
+        crs->first = expressionSemantic(crs->first, sc);
         crs->first = resolveProperties(sc, crs->first);
         sc = sc->endCTFE();
         crs->first = crs->first->implicitCastTo(sc, sw->condition->type);
         crs->first = crs->first->ctfeInterpret();
 
         sc = sc->startCTFE();
-        crs->last = semantic(crs->last, sc);
+        crs->last = expressionSemantic(crs->last, sc);
         crs->last = resolveProperties(sc, crs->last);
         sc = sc->endCTFE();
         crs->last = crs->last->implicitCastTo(sc, sw->condition->type);
@@ -2549,7 +2544,7 @@ public:
         if (crs->first->op == TOKerror || crs->last->op == TOKerror || errors)
         {
             if (crs->statement)
-                semantic(crs->statement, sc);
+                statementSemantic(crs->statement, sc);
             return setError();
         }
 
@@ -2597,7 +2592,7 @@ public:
             statements->push(cs);
         }
         Statement *s = new CompoundStatement(crs->loc, statements);
-        s = semantic(s, sc);
+        s = statementSemantic(s, sc);
         result = s;
     }
 
@@ -2630,7 +2625,7 @@ public:
             ds->error("default not in switch statement");
             errors = true;
         }
-        ds->statement = semantic(ds->statement, sc);
+        ds->statement = statementSemantic(ds->statement, sc);
         if (errors || ds->statement->isErrorStatement())
             return setError();
 
@@ -2664,7 +2659,7 @@ public:
 
         if (gcs->exp)
         {
-            gcs->exp = semantic(gcs->exp, sc);
+            gcs->exp = expressionSemantic(gcs->exp, sc);
             gcs->exp = gcs->exp->implicitCastTo(sc, sc->sw->condition->type);
             gcs->exp = gcs->exp->optimize(WANTvalue);
             if (gcs->exp->op == TOKerror)
@@ -2757,7 +2752,7 @@ public:
                 rs->exp = inferType(rs->exp, tret);
             else if (fld && fld->treq)
                 rs->exp = inferType(rs->exp, fld->treq->nextOf()->nextOf());
-            rs->exp = semantic(rs->exp, sc);
+            rs->exp = expressionSemantic(rs->exp, sc);
 
             // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
             if (rs->exp->op == TOKtype)
@@ -2793,7 +2788,7 @@ public:
                     errors = true;
 
                     rs->exp = new CastExp(rs->loc, rs->exp, Type::tvoid);
-                    rs->exp = semantic(rs->exp, sc);
+                    rs->exp = expressionSemantic(rs->exp, sc);
                 }
 
                 /* Replace:
@@ -3021,7 +3016,7 @@ public:
                     Statement *s = ls->statement;
 
                     if (!s || !s->hasBreak())
-                        bs->error("label '%s' has no break", bs->ident->toChars());
+                        bs->error("label `%s` has no break", bs->ident->toChars());
                     else if (ls->tf != sc->tf)
                         bs->error("cannot break out of finally block");
                     else
@@ -3033,7 +3028,7 @@ public:
                     return setError();
                 }
             }
-            bs->error("enclosing label '%s' for break not found", bs->ident->toChars());
+            bs->error("enclosing label `%s` for break not found", bs->ident->toChars());
             return setError();
         }
         else if (!sc->sbreak)
@@ -3108,7 +3103,7 @@ public:
                     Statement *s = ls->statement;
 
                     if (!s || !s->hasContinue())
-                        cs->error("label '%s' has no continue", cs->ident->toChars());
+                        cs->error("label `%s` has no continue", cs->ident->toChars());
                     else if (ls->tf != sc->tf)
                         cs->error("cannot continue out of finally block");
                     else
@@ -3119,7 +3114,7 @@ public:
                     return setError();
                 }
             }
-            cs->error("enclosing label '%s' for continue not found", cs->ident->toChars());
+            cs->error("enclosing label `%s` for continue not found", cs->ident->toChars());
             return setError();
         }
         else if (!sc->scontinue)
@@ -3149,7 +3144,7 @@ public:
     {
         if (ss->exp)
         {
-            ss->exp = semantic(ss->exp, sc);
+            ss->exp = expressionSemantic(ss->exp, sc);
             ss->exp = resolveProperties(sc, ss->exp);
             ss->exp = ss->exp->optimize(WANTvalue);
             ss->exp = checkGC(sc, ss->exp);
@@ -3158,7 +3153,7 @@ public:
             ClassDeclaration *cd = ss->exp->type->isClassHandle();
             if (!cd)
             {
-                ss->error("can only synchronize on class objects, not '%s'", ss->exp->type->toChars());
+                ss->error("can only synchronize on class objects, not `%s`", ss->exp->type->toChars());
                 return setError();
             }
             else if (cd->isInterfaceDeclaration())
@@ -3173,11 +3168,11 @@ public:
                 }
 
                 Type *t = ClassDeclaration::object->type;
-                t = t->semantic(Loc(), sc)->toBasetype();
+                t = typeSemantic(t, Loc(), sc)->toBasetype();
                 assert(t->ty == Tclass);
 
                 ss->exp = new CastExp(ss->loc, ss->exp, t);
-                ss->exp = semantic(ss->exp, sc);
+                ss->exp = expressionSemantic(ss->exp, sc);
             }
 
             /* Rewrite as:
@@ -3186,7 +3181,7 @@ public:
              *  try { body } finally { _d_monitorexit(tmp); }
              */
             VarDeclaration *tmp = copyToTemp(0, "__sync", ss->exp);
-            tmp->semantic(sc);
+            dsymbolSemantic(tmp, sc);
 
             Statements *cs = new Statements();
             cs->push(new ExpStatement(ss->loc, tmp));
@@ -3207,7 +3202,7 @@ public:
             cs->push(s);
 
             s = new CompoundStatement(ss->loc, cs);
-            result = semantic(s, sc);
+            result = statementSemantic(s, sc);
             return;
         }
         else
@@ -3230,7 +3225,7 @@ public:
              * Backend optimizer could remove this unused variable.
              */
             VarDeclaration *v = new VarDeclaration(ss->loc, Type::tvoidptr, Identifier::generateId("__sync"), NULL);
-            v->semantic(sc);
+            dsymbolSemantic(v, sc);
             cs->push(new ExpStatement(ss->loc, v));
 
             Parameters* args = new Parameters;
@@ -3238,13 +3233,13 @@ public:
 
             FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter, STCnothrow);
             Expression *e = new AddrExp(ss->loc, tmpExp);
-            e = semantic(e, sc);
+            e = expressionSemantic(e, sc);
             e = new CallExp(ss->loc, new VarExp(ss->loc, fdenter, false), e);
             e->type = Type::tvoid;                  // do not run semantic on e
             cs->push(new ExpStatement(ss->loc, e));
 
             FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit, STCnothrow);
-            e = semantic(tmpExp, sc);
+            e = expressionSemantic(tmpExp, sc);
             e = new CallExp(ss->loc, new VarExp(ss->loc, fdexit, false), e);
             e->type = Type::tvoid;                  // do not run semantic on e
             Statement *s = new ExpStatement(ss->loc, e);
@@ -3252,12 +3247,12 @@ public:
             cs->push(s);
 
             s = new CompoundStatement(ss->loc, cs);
-            result = semantic(s, sc);
+            result = statementSemantic(s, sc);
             return;
         }
     Lbody:
         if (ss->_body)
-            ss->_body = semantic(ss->_body, sc);
+            ss->_body = statementSemantic(ss->_body, sc);
         if (ss->_body && ss->_body->isErrorStatement())
         {
             result = ss->_body;
@@ -3272,7 +3267,7 @@ public:
         Initializer *init;
 
         //printf("WithStatement::semantic()\n");
-        ws->exp = semantic(ws->exp, sc);
+        ws->exp = expressionSemantic(ws->exp, sc);
         ws->exp = resolveProperties(sc, ws->exp);
         ws->exp = ws->exp->optimize(WANTvalue);
         ws->exp = checkGC(sc, ws->exp);
@@ -3304,7 +3299,7 @@ public:
             if (t->ty == Tpointer)
             {
                 ws->exp = new PtrExp(ws->loc, ws->exp);
-                ws->exp = semantic(ws->exp, sc);
+                ws->exp = expressionSemantic(ws->exp, sc);
                 t = ws->exp->type->toBasetype();
             }
 
@@ -3314,7 +3309,7 @@ public:
             {
                 init = new ExpInitializer(ws->loc, ws->exp);
                 ws->wthis = new VarDeclaration(ws->loc, ws->exp->type, Id::withSym, init);
-                ws->wthis->semantic(sc);
+                dsymbolSemantic(ws->wthis, sc);
 
                 sym = new WithScopeSymbol(ws);
                 sym->parent = sc->scopesym;
@@ -3334,17 +3329,17 @@ public:
                      * }
                      */
                     VarDeclaration *tmp = copyToTemp(0, "__withtmp", ws->exp);
-                    tmp->semantic(sc);
+                    dsymbolSemantic(tmp, 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);
-                    result = semantic(ss, sc);
+                    result = statementSemantic(ss, sc);
                     return;
                 }
                 Expression *e = ws->exp->addressOf();
                 init = new ExpInitializer(ws->loc, e);
                 ws->wthis = new VarDeclaration(ws->loc, e->type, Id::withSym, init);
-                ws->wthis->semantic(sc);
+                dsymbolSemantic(ws->wthis, sc);
                 sym = new WithScopeSymbol(ws);
                 // Need to set the scope to make use of resolveAliasThis
                 sym->setScope(sc);
@@ -3353,7 +3348,7 @@ public:
             }
             else
             {
-                ws->error("with expressions must be aggregate types or pointers to them, not '%s'", olde->type->toChars());
+                ws->error("with expressions must be aggregate types or pointers to them, not `%s`", olde->type->toChars());
                 return setError();
             }
         }
@@ -3363,7 +3358,7 @@ public:
             sym->_scope = sc;
             sc = sc->push(sym);
             sc->insert(sym);
-            ws->_body = semantic(ws->_body, sc);
+            ws->_body = statementSemantic(ws->_body, sc);
             sc->pop();
             if (ws->_body && ws->_body->isErrorStatement())
             {
@@ -3402,7 +3397,7 @@ public:
         for (size_t i = 0; i < tcs->catches->length; i++)
         {
             Catch *c = (*tcs->catches)[i];
-            semantic(c, sc);
+            catchSemantic(c, sc);
             if (c->errors)
             {
                 catchErrors = true;
@@ -3478,7 +3473,7 @@ public:
     void visit(TryFinallyStatement *tfs)
     {
         //printf("TryFinallyStatement::semantic()\n");
-        tfs->_body = semantic(tfs->_body, sc);
+        tfs->_body = statementSemantic(tfs->_body, sc);
         sc = sc->push();
         sc->tf = tfs;
         sc->sbreak = NULL;
@@ -3572,7 +3567,7 @@ public:
         FuncDeclaration *fd = sc->parent->isFuncDeclaration();
         fd->hasReturnExp |= 2;
 
-        ts->exp = semantic(ts->exp, sc);
+        ts->exp = expressionSemantic(ts->exp, sc);
         ts->exp = resolveProperties(sc, ts->exp);
         ts->exp = checkGC(sc, ts->exp);
         if (ts->exp->op == TOKerror)
@@ -3596,7 +3591,7 @@ public:
         {
             sc = sc->push();
             sc->flags |= SCOPEdebug;
-            ds->statement = semantic(ds->statement, sc);
+            ds->statement = statementSemantic(ds->statement, sc);
             sc->pop();
         }
         result = ds->statement;
@@ -3653,7 +3648,7 @@ public:
         LabelDsymbol *ls2 = fd->searchLabel(ls->ident);
         if (ls2->statement)
         {
-            ls->error("label '%s' already defined", ls2->toChars());
+            ls->error("label `%s` already defined", ls2->toChars());
             return setError();
         }
         else
@@ -3670,7 +3665,7 @@ public:
         }
         sc->slabel = ls;
         if (ls->statement)
-            ls->statement = semantic(ls->statement, sc);
+            ls->statement = statementSemantic(ls->statement, sc);
         sc->pop();
 
         result = ls;
@@ -3690,18 +3685,18 @@ public:
         for (size_t i = 0; i < cas->statements->length; i++)
         {
             Statement *s = (*cas->statements)[i];
-            (*cas->statements)[i] = s ? semantic(s, sc) : NULL;
+            (*cas->statements)[i] = s ? statementSemantic(s, sc) : NULL;
         }
 
         assert(sc->func);
         // use setImpure/setGC when the deprecation cycle is over
         PURE purity;
         if (!(cas->stc & STCpure) && (purity = sc->func->isPureBypassingInference()) != PUREimpure && purity != PUREfwdref)
-            cas->deprecation("asm statement is assumed to be impure - mark it with 'pure' if it is not");
+            cas->deprecation("asm statement is assumed to be impure - mark it with `pure` if it is not");
         if (!(cas->stc & STCnogc) && sc->func->isNogcBypassingInference())
-            cas->deprecation("asm statement is assumed to use the GC - mark it with '@nogc' if it does not");
+            cas->deprecation("asm statement is assumed to use the GC - mark it with `@nogc` if it does not");
         if (!(cas->stc & (STCtrusted|STCsafe)) && sc->func->setUnsafe())
-            cas->error("asm statement is assumed to be @system - mark it with '@trusted' if it is not");
+            cas->error("asm statement is assumed to be @system - mark it with `@trusted` if it is not");
 
         sc->pop();
         result = cas;
@@ -3727,7 +3722,7 @@ public:
                 s->aliasdecls.push(ad);
             }
 
-            s->semantic(sc);
+            dsymbolSemantic(s, sc);
             // https://issues.dlang.org/show_bug.cgi?id=19942
             // If the module that's being imported doesn't exist, don't add it to the symbol table
             // for the current scope.
@@ -3746,14 +3741,14 @@ public:
     }
 };
 
-Statement *semantic(Statement *s, Scope *sc)
+Statement *statementSemantic(Statement *s, Scope *sc)
 {
     StatementSemanticVisitor v = StatementSemanticVisitor(sc);
     s->accept(&v);
     return v.result;
 }
 
-void semantic(Catch *c, Scope *sc)
+void catchSemantic(Catch *c, Scope *sc)
 {
     //printf("Catch::semantic(%s)\n", ident->toChars());
 
@@ -3786,7 +3781,7 @@ void semantic(Catch *c, Scope *sc)
         // reference .object.Throwable
         c->type = getThrowable();
     }
-    c->type = c->type->semantic(c->loc, sc);
+    c->type = typeSemantic(c->type, c->loc, sc);
     if (c->type == Type::terror)
         c->errors = true;
     else
@@ -3794,7 +3789,7 @@ void semantic(Catch *c, Scope *sc)
         ClassDeclaration *cd = c->type->toBasetype()->isClassHandle();
         if (!cd)
         {
-            error(c->loc, "can only catch class objects, not '%s'", c->type->toChars());
+            error(c->loc, "can only catch class objects, not `%s`", c->type->toChars());
             c->errors = true;
         }
         else if (cd->isCPPclass())
@@ -3812,24 +3807,24 @@ void semantic(Catch *c, Scope *sc)
         }
         else if (cd != ClassDeclaration::throwable && !ClassDeclaration::throwable->isBaseOf(cd, NULL))
         {
-            error(c->loc, "can only catch class objects derived from Throwable, not '%s'", c->type->toChars());
+            error(c->loc, "can only catch class objects derived from Throwable, not `%s`", c->type->toChars());
             c->errors = true;
         }
         else if (sc->func && !sc->intypeof && !c->internalCatch &&
                  cd != ClassDeclaration::exception && !ClassDeclaration::exception->isBaseOf(cd, NULL) &&
                  sc->func->setUnsafe())
         {
-            error(c->loc, "can only catch class objects derived from Exception in @safe code, not '%s'", c->type->toChars());
+            error(c->loc, "can only catch class objects derived from Exception in @safe code, not `%s`", c->type->toChars());
             c->errors = true;
         }
 
         if (c->ident)
         {
             c->var = new VarDeclaration(c->loc, c->type, c->ident, NULL);
-            c->var->semantic(sc);
+            dsymbolSemantic(c->var, sc);
             sc->insert(c->var);
         }
-        c->handler = semantic(c->handler, sc);
+        c->handler = statementSemantic(c->handler, sc);
         if (c->handler && c->handler->isErrorStatement())
             c->errors = true;
     }
@@ -3843,7 +3838,7 @@ Statement *semanticNoScope(Statement *s, Scope *sc)
     {
         s = new CompoundStatement(s->loc, s); // so scopeCode() gets called
     }
-    s = semantic(s, sc);
+    s = statementSemantic(s, sc);
     return s;
 }
 
index 57181cd67c14890062eaf6b3e25b589c427f8b7f..c2d0f5b65c280ac68368be33ec2871bff9f5c024 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -19,7 +19,6 @@
 #include "template.h"
 #include "declaration.h"
 
-Expression *semantic(Expression *e, Scope *sc);
 bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors);
 
 /********************************* AttribDeclaration ****************************/
@@ -43,52 +42,6 @@ void StaticAssert::addMember(Scope *, ScopeDsymbol *)
     // we didn't add anything
 }
 
-void StaticAssert::semantic(Scope *)
-{
-}
-
-void StaticAssert::semantic2(Scope *sc)
-{
-    //printf("StaticAssert::semantic2() %s\n", toChars());
-    ScopeDsymbol *sds = new ScopeDsymbol();
-    sc = sc->push(sds);
-    sc->tinst = NULL;
-    sc->minst = NULL;
-
-    bool errors = false;
-    bool result = evalStaticCondition(sc, exp, exp, errors);
-    sc = sc->pop();
-    if (errors)
-    {
-        errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
-    }
-    else if (!result)
-    {
-        if (msg)
-        {
-            sc = sc->startCTFE();
-            msg = ::semantic(msg, sc);
-            msg = resolveProperties(sc, msg);
-            sc = sc->endCTFE();
-            msg = msg->ctfeInterpret();
-            if (StringExp * se = msg->toStringExp())
-            {
-                // same with pragma(msg)
-                se = se->toUTF8(sc);
-                error("\"%.*s\"", (int)se->len, (char *)se->string);
-            }
-            else
-                error("%s", msg->toChars());
-        }
-        else
-            error("(%s) is false", exp->toChars());
-        if (sc->tinst)
-            sc->tinst->printInstantiationTrace();
-        if (!global.gag)
-              fatal();
-    }
-}
-
 bool StaticAssert::oneMember(Dsymbol **ps, Identifier *)
 {
     //printf("StaticAssert::oneMember())\n");
index 44913226da87f32ec6a71d3588926e94dae1c02e..6d43cb73a0d233330ded8947d180c1598c386614 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -24,8 +24,6 @@ public:
 
     Dsymbol *syntaxCopy(Dsymbol *s);
     void addMember(Scope *sc, ScopeDsymbol *sds);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
     bool oneMember(Dsymbol **ps, Identifier *ident);
     const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
index 48a60d34fb1b91841522d426eef968e8cff22cb9..ef0a35ff38211e4eb424e243566c13e85a25ae50 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -13,8 +13,6 @@
 #include "mtype.h"
 #include "scope.h"
 
-Expression *semantic(Expression *e, Scope *sc);
-
 /********************************************
  * Semantically analyze and then evaluate a static condition at compile time.
  * This is special because short circuit operators &&, || and ?: at the top
@@ -64,7 +62,7 @@ bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors
     sc = sc->startCTFE();
     sc->flags |= SCOPEcondition;
 
-    e = semantic(e, sc);
+    e = expressionSemantic(e, sc);
     e = resolveProperties(sc, e);
 
     sc = sc->endCTFE();
index 5a2dd4d913369b8a2989492090fea0b933746101..a91880fd0fc86d87a343c1144f9ddc4b166fb4e4 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2013-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2013-2021 by The D Language Foundation, All Rights Reserved
  * written by Iain Buclaw
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 0a5bc798d6b1e37d28147a7dd8c103a35acf83d0..dac1e85b433ac06f9f818619d8d95f4e0b207f97 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -35,6 +35,10 @@ class Parameter;
 enum MATCH;
 enum PASS;
 
+bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters);
+RootObject *aliasParameterSemantic(Loc loc, Scope *sc, RootObject *o, TemplateParameters *parameters);
+void templateInstanceSemantic(TemplateInstance *tempinst, Scope *sc, Expressions *fargs);
+
 class Tuple : public RootObject
 {
 public:
@@ -80,7 +84,6 @@ public:
     TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
         Expression *constraint, Dsymbols *decldefs, bool ismixin = false, bool literal = false);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc);
     bool overloadInsert(Dsymbol *s);
     bool hasStaticCtorOrDtor();
     const char *kind() const;
@@ -145,7 +148,6 @@ public:
 
     virtual TemplateParameter *syntaxCopy() = 0;
     virtual bool declareParameter(Scope *sc) = 0;
-    virtual bool semantic(Scope *sc, TemplateParameters *parameters) = 0;
     virtual void print(RootObject *oarg, RootObject *oded) = 0;
     virtual RootObject *specialization() = 0;
     virtual RootObject *defaultArg(Loc instLoc, Scope *sc) = 0;
@@ -179,7 +181,6 @@ public:
     TemplateTypeParameter *isTemplateTypeParameter();
     TemplateParameter *syntaxCopy();
     bool declareParameter(Scope *sc);
-    bool semantic(Scope *sc, TemplateParameters *parameters);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
     RootObject *defaultArg(Loc instLoc, Scope *sc);
@@ -220,7 +221,6 @@ public:
     TemplateValueParameter *isTemplateValueParameter();
     TemplateParameter *syntaxCopy();
     bool declareParameter(Scope *sc);
-    bool semantic(Scope *sc, TemplateParameters *parameters);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
     RootObject *defaultArg(Loc instLoc, Scope *sc);
@@ -248,7 +248,6 @@ public:
     TemplateAliasParameter *isTemplateAliasParameter();
     TemplateParameter *syntaxCopy();
     bool declareParameter(Scope *sc);
-    bool semantic(Scope *sc, TemplateParameters *parameters);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
     RootObject *defaultArg(Loc instLoc, Scope *sc);
@@ -269,7 +268,6 @@ public:
     TemplateTupleParameter *isTemplateTupleParameter();
     TemplateParameter *syntaxCopy();
     bool declareParameter(Scope *sc);
-    bool semantic(Scope *sc, TemplateParameters *parameters);
     void print(RootObject *oarg, RootObject *oded);
     RootObject *specialization();
     RootObject *defaultArg(Loc instLoc, Scope *sc);
@@ -326,10 +324,6 @@ public:
     TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
     static Objects *arraySyntaxCopy(Objects *objs);
     Dsymbol *syntaxCopy(Dsymbol *);
-    void semantic(Scope *sc, Expressions *fargs);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
     Dsymbol *toAlias();                 // resolve real symbol
     const char *kind() const;
     bool oneMember(Dsymbol **ps, Identifier *ident);
@@ -368,9 +362,6 @@ public:
 
     TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs);
     Dsymbol *syntaxCopy(Dsymbol *s);
-    void semantic(Scope *sc);
-    void semantic2(Scope *sc);
-    void semantic3(Scope *sc);
     const char *kind() const;
     bool oneMember(Dsymbol **ps, Identifier *ident);
     int apply(Dsymbol_apply_ft_t fp, void *param);
diff --git a/gcc/d/dmd/templateparamsem.c b/gcc/d/dmd/templateparamsem.c
new file mode 100644 (file)
index 0000000..11cd52e
--- /dev/null
@@ -0,0 +1,116 @@
+
+/* Compiler implementation of the D programming language
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * written by Walter Bright
+ * http://www.digitalmars.com
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#include "template.h"
+#include "mtype.h"
+#include "scope.h"
+#include "visitor.h"
+
+bool reliesOnTident(Type *t, TemplateParameters *tparams = NULL, size_t iStart = 0);
+
+class TemplateParameterSemanticVisitor : public Visitor
+{
+public:
+    Scope *sc;
+    TemplateParameters *parameters;
+    bool result;
+
+    TemplateParameterSemanticVisitor(Scope *sc, TemplateParameters *parameters)
+    {
+        this->sc = sc;
+        this->parameters = parameters;
+       this->result = false;
+    }
+
+    void visit(TemplateTypeParameter *ttp)
+    {
+        //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
+        if (ttp->specType && !reliesOnTident(ttp->specType, parameters))
+        {
+            ttp->specType = typeSemantic(ttp->specType, ttp->loc, sc);
+        }
+        result = !(ttp->specType && isError(ttp->specType));
+    }
+
+    void visit(TemplateValueParameter *tvp)
+    {
+        tvp->valType = typeSemantic(tvp->valType, tvp->loc, sc);
+
+        result = !isError(tvp->valType);
+    }
+
+    void visit(TemplateAliasParameter *tap)
+    {
+        if (tap->specType && !reliesOnTident(tap->specType, parameters))
+        {
+            tap->specType = typeSemantic(tap->specType, tap->loc, sc);
+        }
+        tap->specAlias = aliasParameterSemantic(tap->loc, sc, tap->specAlias, parameters);
+        result = !(tap->specType  && isError(tap->specType)) &&
+            !(tap->specAlias && isError(tap->specAlias));
+    }
+
+    void visit(TemplateTupleParameter *)
+    {
+        result = true;
+    }
+};
+
+/************************************************
+ * Performs semantic on TemplateParameter AST nodes.
+ *
+ * Params:
+ *      tp = element of `parameters` to be semantically analyzed
+ *      sc = context
+ *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
+ * Returns:
+ *      `true` if no errors
+ */
+bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters)
+{
+    TemplateParameterSemanticVisitor v(sc, parameters);
+    tp->accept(&v);
+    return v.result;
+}
+
+/***********************************************
+ * Support function for performing semantic analysis on `TemplateAliasParameter`.
+ *
+ * Params:
+ *      loc = location (for error messages)
+ *      sc = context
+ *      o = object to run semantic() on, the `TemplateAliasParameter`s `specAlias` or `defaultAlias`
+ *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
+ * Returns:
+ *      object resulting from running `semantic` on `o`
+ */
+RootObject *aliasParameterSemantic(Loc loc, Scope *sc, RootObject *o, TemplateParameters *parameters)
+{
+    if (o)
+    {
+        Expression *ea = isExpression(o);
+        Type *ta = isType(o);
+        if (ta && (!parameters || !reliesOnTident(ta, parameters)))
+        {
+            Dsymbol *s = ta->toDsymbol(sc);
+            if (s)
+                o = s;
+            else
+                o = typeSemantic(ta, loc, sc);
+        }
+        else if (ea)
+        {
+            sc = sc->startCTFE();
+            ea = expressionSemantic(ea, sc);
+            sc = sc->endCTFE();
+            o = ea->ctfeInterpret();
+        }
+    }
+    return o;
+}
index 9db1e33c1da7f08ea60d9f63b4d15f913560c6f1..eb06beed9b64ba09637ba2cc16ea7dea2f376b8e 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 82dcaa2dfdec3d6c7d7fab3873ab326303f53dee..f79d8419c900d3bc3097c11d615099e66178a640 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 70f7f2cb582ec51a9e16b260fc3f534c7b66464e..b7c612c2af2868d72ee81c1ca308b543cabe8a4d 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -39,8 +39,6 @@ int ScopeDsymbol_foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx,
 void freeFieldinit(Scope *sc);
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
 Package *resolveIsPackage(Dsymbol *sym);
-Expression *trySemantic(Expression *e, Scope *sc);
-Expression *semantic(Expression *e, Scope *sc);
 Expression *typeToExpression(Type *t);
 
 
@@ -803,7 +801,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             return f->isNested() ? True(e) : False(e);
         }
 
-        e->error("aggregate or function expected instead of '%s'", o->toChars());
+        e->error("aggregate or function expected instead of `%s`", o->toChars());
         return new ErrorExp();
     }
     else if (e->ident == Id::isDisabled)
@@ -925,7 +923,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         }
 
         StringExp *se = new StringExp(e->loc, const_cast<char *>(id->toChars()));
-        return semantic(se, sc);
+        return expressionSemantic(se, sc);
     }
     else if (e->ident == Id::getProtection || e->ident == Id::getVisibility)
     {
@@ -948,12 +946,12 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             return new ErrorExp();
         }
         if (s->semanticRun == PASSinit)
-            s->semantic(NULL);
+            dsymbolSemantic(s, NULL);
 
         const char *protName = protectionToChars(s->prot().kind);   // TODO: How about package(names)
         assert(protName);
         StringExp *se = new StringExp(e->loc, const_cast<char *>(protName));
-        return semantic(se, sc);
+        return expressionSemantic(se, sc);
     }
     else if (e->ident == Id::parent)
     {
@@ -982,7 +980,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
                 if (td->overroot)       // if not start of overloaded list of TemplateDeclaration's
                     td = td->overroot;  // then get the start
                 Expression *ex = new TemplateExp(e->loc, td, f);
-                ex = semantic(ex, sc);
+                ex = expressionSemantic(ex, sc);
                 return ex;
             }
 
@@ -990,7 +988,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             {
                 // Directly translate to VarExp instead of FuncExp
                 Expression *ex = new VarExp(e->loc, fld, true);
-                return semantic(ex, sc);
+                return expressionSemantic(ex, sc);
             }
         }
 
@@ -1013,7 +1011,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             return new ErrorExp();
         }
 
-        ex = semantic(ex, sc);
+        ex = expressionSemantic(ex, sc);
         RootObject *oc = (*e->args)[1];
         Dsymbol *symc = getDsymbol(oc);
         if (!symc)
@@ -1031,7 +1029,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         else
             assert(0);
 
-        ex = semantic(ex, sc);
+        ex = expressionSemantic(ex, sc);
         return ex;
     }
     else if (e->ident == Id::hasMember ||
@@ -1120,7 +1118,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             if (ex->op == TOKdotid)
                 // Prevent semantic() from replacing Symbol with its initializer
                 ((DotIdExp *)ex)->wantsym = true;
-            ex = semantic(ex, scx);
+            ex = expressionSemantic(ex, scx);
             scx->pop();
             return ex;
         }
@@ -1130,7 +1128,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         {
             unsigned errors = global.errors;
             Expression *eorig = ex;
-            ex = semantic(ex, scx);
+            ex = expressionSemantic(ex, scx);
             if (errors < global.errors)
                 e->error("%s cannot be resolved", eorig->toChars());
             //ex->print();
@@ -1193,7 +1191,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
                 overloadApply(f, &p, &fptraits);
 
             ex = new TupleExp(e->loc, exps);
-            ex = semantic(ex, scx);
+            ex = expressionSemantic(ex, scx);
             scx->pop();
             return ex;
         }
@@ -1243,7 +1241,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         if (ad->aliasthis)
             exps->push(new StringExp(e->loc, const_cast<char *>(ad->aliasthis->ident->toChars())));
         Expression *ex = new TupleExp(e->loc, exps);
-        ex = semantic(ex, sc);
+        ex = expressionSemantic(ex, sc);
         return ex;
     }
     else if (e->ident == Id::getAttributes)
@@ -1283,7 +1281,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
 
         Expressions *exps = udad ? udad->getAttributes() : new Expressions();
         TupleExp *tup = new TupleExp(e->loc, exps);
-        return semantic(tup, sc);
+        return expressionSemantic(tup, sc);
     }
     else if (e->ident == Id::getFunctionAttributes)
     {
@@ -1308,7 +1306,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         tf->attributesApply(&pa, &PushAttributes::fp, TRUSTformatSystem);
 
         TupleExp *tup = new TupleExp(e->loc, mods);
-        return semantic(tup, sc);
+        return expressionSemantic(tup, sc);
     }
     else if (e->ident == Id::isReturnOnStack)
     {
@@ -1375,7 +1373,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
                 assert(0);
         }
         StringExp *se = new StringExp(e->loc, const_cast<char*>(style));
-        return semantic(se, sc);
+        return expressionSemantic(se, sc);
     }
     else if (e->ident == Id::getParameterStorageClasses)
     {
@@ -1464,7 +1462,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             exps->push(new StringExp(e->loc, const_cast<char *>("scope")));
 
         TupleExp *tup = new TupleExp(e->loc, exps);
-        return semantic(tup, sc);
+        return expressionSemantic(tup, sc);
     }
     else if (e->ident == Id::getLinkage)
     {
@@ -1512,7 +1510,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         }
         const char *linkage = linkageToChars(link);
         StringExp *se = new StringExp(e->loc, const_cast<char *>(linkage));
-        return semantic(se, sc);
+        return expressionSemantic(se, sc);
     }
     else if (e->ident == Id::allMembers ||
              e->ident == Id::derivedMembers)
@@ -1620,7 +1618,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         if (cd && e->ident == Id::allMembers)
         {
             if (cd->semanticRun < PASSsemanticdone)
-                cd->semantic(NULL);    // Bugzilla 13668: Try to resolve forward reference
+                dsymbolSemantic(cd, NULL);    // Bugzilla 13668: Try to resolve forward reference
 
             struct PushBaseMembers
             {
@@ -1654,7 +1652,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
          *   [ __traits(allMembers, ...) ]
          */
         Expression *ex = new TupleExp(e->loc, exps);
-        ex = semantic(ex, sc);
+        ex = expressionSemantic(ex, sc);
         return ex;
     }
     else if (e->ident == Id::compiles)
@@ -1683,7 +1681,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
                 t->resolve(e->loc, sc2, &ex, &t, &s);
                 if (t)
                 {
-                    t->semantic(e->loc, sc2);
+                    typeSemantic(t, e->loc, sc2);
                     if (t->ty == Terror)
                         err = true;
                 }
@@ -1692,7 +1690,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             }
             if (ex)
             {
-                ex = semantic(ex, sc2);
+                ex = expressionSemantic(ex, sc2);
                 ex = resolvePropertiesOnly(sc2, ex);
                 ex = ex->optimize(WANTvalue);
                 if (sc2->func && sc2->func->type->ty == Tfunction)
@@ -1795,7 +1793,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             collectUnitTests(sds->members, uniqueUnitTests, exps);
         }
         TupleExp *te= new TupleExp(e->loc, exps);
-        return semantic(te, sc);
+        return expressionSemantic(te, sc);
     }
     else if (e->ident == Id::getVirtualIndex)
     {
@@ -1856,7 +1854,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             e->error("`getTargetInfo` key `\"%s\"` not supported by this implementation", se->toPtr());
             return new ErrorExp();
         }
-        return semantic(r, sc);
+        return expressionSemantic(r, sc);
     }
     else if (e->ident == Id::getLocation)
     {
@@ -1886,13 +1884,13 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         (*exps)[1] = new IntegerExp(e->loc, s->loc.linnum, Type::tint32);
         (*exps)[2] = new IntegerExp(e->loc, s->loc.charnum, Type::tint32);
         TupleExp *tup = new TupleExp(e->loc, exps);
-        return semantic(tup, sc);
+        return expressionSemantic(tup, sc);
     }
 
     if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars))
-        e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub);
+        e->error("unrecognized trait `%s`, did you mean `%s`?", e->ident->toChars(), sub);
     else
-        e->error("unrecognized trait '%s'", e->ident->toChars());
+        e->error("unrecognized trait `%s`", e->ident->toChars());
     return new ErrorExp();
 
     e->error("wrong number of arguments %d", (int)dim);
index 2933e983b019caf458d3b7a56c8d4993c94c6194..496cfe3a8559bfb0ea5c634dc249501ae5436372 100644 (file)
@@ -1,18 +1,31 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
  */
 
+#include "root/dsystem.h"
+#include "root/checkedint.h"
+
 #include "mtype.h"
+#include "aggregate.h"
+#include "enum.h"
+#include "errors.h"
 #include "expression.h"
+#include "hdrgen.h"
+#include "id.h"
+#include "init.h"
+#include "scope.h"
+#include "target.h"
 #include "template.h"
+#include "visitor.h"
 
 Expression *typeToExpression(Type *t);
 Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
+char *MODtoChars(MOD mod);
 
 class TypeToExpressionVisitor : public Visitor
 {
@@ -121,3 +134,1260 @@ Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i)
     }
     return e;
 }
+
+/**************************
+ * This evaluates exp while setting length to be the number
+ * of elements in the tuple t.
+ */
+static Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
+{
+    if (t->ty == Ttuple)
+    {
+        ScopeDsymbol *sym = new ArrayScopeSymbol(sc, (TypeTuple *)t);
+        sym->parent = sc->scopesym;
+        sc = sc->push(sym);
+
+        sc = sc->startCTFE();
+        exp = expressionSemantic(exp, sc);
+        sc = sc->endCTFE();
+
+        sc->pop();
+    }
+    else
+    {
+        sc = sc->startCTFE();
+        exp = expressionSemantic(exp, sc);
+        sc = sc->endCTFE();
+    }
+
+    return exp;
+}
+
+static Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
+{
+    ScopeDsymbol *sym = new ArrayScopeSymbol(sc, s);
+    sym->parent = sc->scopesym;
+    sc = sc->push(sym);
+
+    sc = sc->startCTFE();
+    exp = expressionSemantic(exp, sc);
+    sc = sc->endCTFE();
+
+    sc->pop();
+    return exp;
+}
+
+/******************************************
+ * Perform semantic analysis on a type.
+ * Params:
+ *      type = Type AST node
+ *      loc = the location of the type
+ *      sc = context
+ * Returns:
+ *      `Type` with completed semantic analysis, `Terror` if errors
+ *      were encountered
+ */
+Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
+{
+    class TypeSemanticVisitor : public Visitor
+    {
+    public:
+        Loc loc;
+        Scope *sc;
+        Type *result;
+
+        TypeSemanticVisitor(const Loc &loc, Scope *sc)
+        {
+            this->loc = loc;
+            this->sc = sc;
+            this->result = NULL;
+        }
+
+    private:
+        void error()
+        {
+            result = Type::terror;
+        }
+
+    public:
+        void visit(Type *t)
+        {
+            if (t->ty == Tint128 || t->ty == Tuns128)
+            {
+                ::error(loc, "cent and ucent types not implemented");
+                return error();
+            }
+
+            result = t->merge();
+        }
+
+        void visit(TypeVector *mtype)
+        {
+            unsigned int errors = global.errors;
+            mtype->basetype = typeSemantic(mtype->basetype, loc, sc);
+            if (errors != global.errors)
+                return error();
+            mtype->basetype = mtype->basetype->toBasetype()->mutableOf();
+            if (mtype->basetype->ty != Tsarray)
+            {
+                ::error(loc, "T in __vector(T) must be a static array, not %s", mtype->basetype->toChars());
+                return error();
+            }
+            TypeSArray *t = (TypeSArray *)mtype->basetype;
+            int sz = (int)t->size(loc);
+            switch (target.isVectorTypeSupported(sz, t->nextOf()))
+            {
+            case 0: // valid
+                break;
+            case 1: // no support at all
+                ::error(loc, "SIMD vector types not supported on this platform");
+                return error();
+            case 2: // invalid base type
+                ::error(loc, "vector type %s is not supported on this platform", mtype->toChars());
+                return error();
+            case 3: // invalid size
+                ::error(loc, "%d byte vector type %s is not supported on this platform", sz, mtype->toChars());
+                return error();
+            default:
+                assert(0);
+            }
+            result = mtype->merge();
+        }
+
+        void visit(TypeSArray *mtype)
+        {
+            //printf("TypeSArray::semantic() %s\n", mtype->toChars());
+
+            Type *t;
+            Expression *e;
+            Dsymbol *s;
+            mtype->next->resolve(loc, sc, &e, &t, &s);
+
+            if (mtype->dim && s && s->isTupleDeclaration())
+            {
+                TupleDeclaration *sd = s->isTupleDeclaration();
+
+                mtype->dim = semanticLength(sc, sd, mtype->dim);
+                mtype->dim = mtype->dim->ctfeInterpret();
+                if(mtype->dim->op == TOKerror)
+                    return error();
+
+                uinteger_t d = mtype->dim->toUInteger();
+                if (d >= sd->objects->length)
+                {
+                    ::error(loc, "tuple index %llu exceeds %llu", (unsigned long long)d, (unsigned long long)sd->objects->length);
+                    return error();
+                }
+
+                RootObject *o = (*sd->objects)[(size_t)d];
+                if (o->dyncast() != DYNCAST_TYPE)
+                {
+                    ::error(loc, "%s is not a type", mtype->toChars());
+                    return error();
+                }
+                result = ((Type *)o)->addMod(mtype->mod);
+                return;
+            }
+
+            if (t && t->ty == Terror)
+                return error();
+
+            Type *tn = typeSemantic(mtype->next, loc, sc);
+            if (tn->ty == Terror)
+                return error();
+
+            Type *tbn = tn->toBasetype();
+            if (mtype->dim)
+            {
+                unsigned int errors = global.errors;
+                mtype->dim = semanticLength(sc, tbn, mtype->dim);
+                if (errors != global.errors)
+                    return error();
+
+                mtype->dim = mtype->dim->optimize(WANTvalue);
+                mtype->dim = mtype->dim->ctfeInterpret();
+                if (mtype->dim->op == TOKerror)
+                    return error();
+                errors = global.errors;
+                dinteger_t d1 = mtype->dim->toInteger();
+                if (errors != global.errors)
+                    return error();
+
+                mtype->dim = mtype->dim->implicitCastTo(sc, Type::tsize_t);
+                mtype->dim = mtype->dim->optimize(WANTvalue);
+                if (mtype->dim->op == TOKerror)
+                    return error();
+                errors = global.errors;
+                dinteger_t d2 = mtype->dim->toInteger();
+                if (errors != global.errors)
+                    return error();
+
+                if (mtype->dim->op == TOKerror)
+                    return error();
+
+                if (d1 != d2)
+                {
+                Loverflow:
+                    ::error(loc, "%s size %llu * %llu exceeds 0x%llx size limit for static array",
+                          mtype->toChars(), (unsigned long long)tbn->size(loc), (unsigned long long)d1, target.maxStaticDataSize);
+                    return error();
+                }
+
+                Type *tbx = tbn->baseElemOf();
+                if ((tbx->ty == Tstruct && !((TypeStruct *)tbx)->sym->members) ||
+                    (tbx->ty == Tenum && !((TypeEnum *)tbx)->sym->members))
+                {
+                    /* To avoid meaningless error message, skip the total size limit check
+                     * when the bottom of element type is opaque.
+                     */
+                }
+                else if (tbn->isTypeBasic() ||
+                         tbn->ty == Tpointer ||
+                         tbn->ty == Tarray ||
+                         tbn->ty == Tsarray ||
+                         tbn->ty == Taarray ||
+                         (tbn->ty == Tstruct && (((TypeStruct *)tbn)->sym->sizeok == SIZEOKdone)) ||
+                         tbn->ty == Tclass)
+                {
+                    /* Only do this for types that don't need to have semantic()
+                     * run on them for the size, since they may be forward referenced.
+                     */
+                    bool overflow = false;
+                    if (mulu(tbn->size(loc), d2, overflow) >= target.maxStaticDataSize || overflow)
+                        goto Loverflow;
+                }
+            }
+            switch (tbn->ty)
+            {
+                case Ttuple:
+                {
+                    // Index the tuple to get the type
+                    assert(mtype->dim);
+                    TypeTuple *tt = (TypeTuple *)tbn;
+                    uinteger_t d = mtype->dim->toUInteger();
+                    if (d >= tt->arguments->length)
+                    {
+                        ::error(loc, "tuple index %llu exceeds %llu", (unsigned long long)d, (unsigned long long)tt->arguments->length);
+                        return error();
+                    }
+                    Type *telem = (*tt->arguments)[(size_t)d]->type;
+                    result = telem->addMod(mtype->mod);
+                    return;
+                }
+                case Tfunction:
+                case Tnone:
+                    ::error(loc, "cannot have array of %s", tbn->toChars());
+                    return error();
+                default:
+                    break;
+            }
+            if (tbn->isscope())
+            {
+                ::error(loc, "cannot have array of scope %s", tbn->toChars());
+                return error();
+            }
+
+            /* Ensure things like const(immutable(T)[3]) become immutable(T[3])
+             * and const(T)[3] become const(T[3])
+             */
+            mtype->next = tn;
+            mtype->transitive();
+            result = mtype->addMod(tn->mod)->merge();
+        }
+
+        void visit(TypeDArray *mtype)
+        {
+            Type *tn = typeSemantic(mtype->next, loc,sc);
+            Type *tbn = tn->toBasetype();
+            switch (tbn->ty)
+            {
+                case Ttuple:
+                    result = tbn;
+                    return;
+                case Tfunction:
+                case Tnone:
+                    ::error(loc, "cannot have array of %s", tbn->toChars());
+                    return error();
+                case Terror:
+                    return error();
+                default:
+                    break;
+            }
+            if (tn->isscope())
+            {
+                ::error(loc, "cannot have array of scope %s", tn->toChars());
+                return error();
+            }
+            mtype->next = tn;
+            mtype->transitive();
+            result = mtype->merge();
+        }
+
+        void visit(TypeAArray *mtype)
+        {
+            //printf("TypeAArray::semantic() %s index->ty = %d\n", mtype->toChars(), mtype->index->ty);
+            if (mtype->deco)
+            {
+                result = mtype;
+                return;
+            }
+
+            mtype->loc = loc;
+            mtype->sc = sc;
+            if (sc)
+                sc->setNoFree();
+
+            // Deal with the case where we thought the index was a type, but
+            // in reality it was an expression.
+            if (mtype->index->ty == Tident || mtype->index->ty == Tinstance || mtype->index->ty == Tsarray ||
+                mtype->index->ty == Ttypeof || mtype->index->ty == Treturn)
+            {
+                Expression *e;
+                Type *t;
+                Dsymbol *s;
+
+                mtype->index->resolve(loc, sc, &e, &t, &s);
+                if (e)
+                {
+                    // It was an expression -
+                    // Rewrite as a static array
+                    TypeSArray *tsa = new TypeSArray(mtype->next, e);
+                    result = typeSemantic(tsa, loc, sc);
+                    return;
+                }
+                else if (t)
+                    mtype->index = typeSemantic(t, loc, sc);
+                else
+                {
+                    mtype->index->error(loc, "index is not a type or an expression");
+                    return error();
+                }
+            }
+            else
+                mtype->index = typeSemantic(mtype->index, loc,sc);
+            mtype->index = mtype->index->merge2();
+
+            if (mtype->index->nextOf() && !mtype->index->nextOf()->isImmutable())
+            {
+                mtype->index = mtype->index->constOf()->mutableOf();
+            }
+
+            switch (mtype->index->toBasetype()->ty)
+            {
+                case Tfunction:
+                case Tvoid:
+                case Tnone:
+                case Ttuple:
+                    ::error(loc, "cannot have associative array key of %s", mtype->index->toBasetype()->toChars());
+                    /* fall through */
+                case Terror:
+                    return error();
+                default:
+                    break;
+            }
+            Type *tbase = mtype->index->baseElemOf();
+            while (tbase->ty == Tarray)
+                tbase = tbase->nextOf()->baseElemOf();
+            if (tbase->ty == Tstruct)
+            {
+                /* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up.
+                 */
+                StructDeclaration *sd = ((TypeStruct *)tbase)->sym;
+                if (sd->semanticRun < PASSsemanticdone)
+                    dsymbolSemantic(sd, NULL);
+
+                // duplicate a part of StructDeclaration::semanticTypeInfoMembers
+                //printf("AA = %s, key: xeq = %p, xerreq = %p xhash = %p\n", mtype->toChars(), sd->xeq, sd->xerreq, sd->xhash);
+                if (sd->xeq &&
+                    sd->xeq->_scope &&
+                    sd->xeq->semanticRun < PASSsemantic3done)
+                {
+                    unsigned errors = global.startGagging();
+                    semantic3(sd->xeq, sd->xeq->_scope);
+                    if (global.endGagging(errors))
+                        sd->xeq = sd->xerreq;
+                }
+
+                const char *s = (mtype->index->toBasetype()->ty != Tstruct) ? "bottom of " : "";
+                if (!sd->xeq)
+                {
+                    // If sd->xhash != NULL:
+                    //   sd or its fields have user-defined toHash.
+                    //   AA assumes that its result is consistent with bitwise equality.
+                    // else:
+                    //   bitwise equality & hashing
+                }
+                else if (sd->xeq == sd->xerreq)
+                {
+                    if (search_function(sd, Id::eq))
+                    {
+                        ::error(loc, "%sAA key type %s does not have `bool opEquals(ref const %s) const`",
+                                s, sd->toChars(), sd->toChars());
+                    }
+                    else
+                    {
+                        ::error(loc, "%sAA key type %s does not support const equality",
+                                s, sd->toChars());
+                    }
+                    return error();
+                }
+                else if (!sd->xhash)
+                {
+                    if (search_function(sd, Id::eq))
+                    {
+                        ::error(loc, "%sAA key type %s should have `size_t toHash() const nothrow @safe` if opEquals defined",
+                                s, sd->toChars());
+                    }
+                    else
+                    {
+                        ::error(loc, "%sAA key type %s supports const equality but doesn't support const hashing",
+                                s, sd->toChars());
+                    }
+                    return error();
+                }
+                else
+                {
+                    // defined equality & hashing
+                    assert(sd->xeq && sd->xhash);
+
+                    /* xeq and xhash may be implicitly defined by compiler. For example:
+                     *   struct S { int[] arr; }
+                     * With 'arr' field equality and hashing, compiler will implicitly
+                     * generate functions for xopEquals and xtoHash in TypeInfo_Struct.
+                     */
+                }
+            }
+            else if (tbase->ty == Tclass && !((TypeClass *)tbase)->sym->isInterfaceDeclaration())
+            {
+                ClassDeclaration *cd = ((TypeClass *)tbase)->sym;
+                if (cd->semanticRun < PASSsemanticdone)
+                    dsymbolSemantic(cd, NULL);
+
+                if (!ClassDeclaration::object)
+                {
+                    ::error(Loc(), "missing or corrupt object.d");
+                    fatal();
+                }
+
+                static FuncDeclaration *feq   = NULL;
+                static FuncDeclaration *fcmp  = NULL;
+                static FuncDeclaration *fhash = NULL;
+                if (!feq)   feq   = search_function(ClassDeclaration::object, Id::eq)->isFuncDeclaration();
+                if (!fcmp)  fcmp  = search_function(ClassDeclaration::object, Id::cmp)->isFuncDeclaration();
+                if (!fhash) fhash = search_function(ClassDeclaration::object, Id::tohash)->isFuncDeclaration();
+                assert(fcmp && feq && fhash);
+
+                if (feq->vtblIndex < (int)cd->vtbl.length && cd->vtbl[feq ->vtblIndex] == feq)
+                {
+                    if (fcmp->vtblIndex < (int)cd->vtbl.length && cd->vtbl[fcmp->vtblIndex] != fcmp)
+                    {
+                        const char *s = (mtype->index->toBasetype()->ty != Tclass) ? "bottom of " : "";
+                        ::error(loc, "%sAA key type %s now requires equality rather than comparison",
+                            s, cd->toChars());
+                        errorSupplemental(loc, "Please override Object.opEquals and toHash.");
+                    }
+                }
+            }
+            mtype->next = typeSemantic(mtype->next, loc,sc)->merge2();
+            mtype->transitive();
+
+            switch (mtype->next->toBasetype()->ty)
+            {
+                case Tfunction:
+                case Tvoid:
+                case Tnone:
+                case Ttuple:
+                    ::error(loc, "cannot have associative array of %s", mtype->next->toChars());
+                    /* fall through */
+                case Terror:
+                    return error();
+            }
+            if (mtype->next->isscope())
+            {
+                ::error(loc, "cannot have array of scope %s", mtype->next->toChars());
+                return error();
+            }
+            result = mtype->merge();
+        }
+
+        void visit(TypePointer *mtype)
+        {
+            //printf("TypePointer::semantic() %s\n", mtype->toChars());
+            if (mtype->deco)
+            {
+                result = mtype;
+                return;
+            }
+            Type *n = typeSemantic(mtype->next, loc, sc);
+            switch (n->toBasetype()->ty)
+            {
+                case Ttuple:
+                    ::error(loc, "cannot have pointer to %s", n->toChars());
+                    /* fall through */
+                case Terror:
+                    return error();
+                default:
+                    break;
+            }
+            if (n != mtype->next)
+            {
+                mtype->deco = NULL;
+            }
+            mtype->next = n;
+            if (mtype->next->ty != Tfunction)
+            {
+                mtype->transitive();
+                result = mtype->merge();
+                return;
+            }
+            mtype->deco = mtype->merge()->deco;
+            /* Don't return merge(), because arg identifiers and default args
+             * can be different
+             * even though the types match
+             */
+            result = mtype;
+        }
+
+        void visit(TypeReference *mtype)
+        {
+            //printf("TypeReference::semantic()\n");
+            Type *n = typeSemantic(mtype->next, loc, sc);
+            if (n != mtype->next)
+                mtype->deco = NULL;
+            mtype->next = n;
+            mtype->transitive();
+            result = mtype->merge();
+        }
+
+
+        void visit(TypeFunction *mtype)
+        {
+            if (mtype->deco)                   // if semantic() already run
+            {
+                //printf("already done\n");
+                result = mtype;
+                return;
+            }
+            //printf("TypeFunction::semantic() this = %p\n", this);
+            //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", mtype->toChars(), sc->stc, mtype->fargs);
+
+            bool errors = false;
+
+            if (mtype->inuse > global.recursionLimit)
+            {
+                mtype->inuse = 0;
+                ::error(loc, "recursive type");
+                return error();
+            }
+
+            /* 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.
+             */
+            TypeFunction *tf = mtype->copy()->toTypeFunction();
+            if (mtype->parameterList.parameters)
+            {
+                tf->parameterList.parameters = mtype->parameterList.parameters->copy();
+                for (size_t i = 0; i < mtype->parameterList.parameters->length; i++)
+                {
+                    void *pp = mem.xmalloc(sizeof(Parameter));
+                    Parameter *p = (Parameter *)memcpy(pp, (void *)(*mtype->parameterList.parameters)[i],
+                                                       sizeof(Parameter));
+                    (*tf->parameterList.parameters)[i] = p;
+                }
+            }
+
+            if (sc->stc & STCpure)
+                tf->purity = PUREfwdref;
+            if (sc->stc & STCnothrow)
+                tf->isnothrow = true;
+            if (sc->stc & STCnogc)
+                tf->isnogc = true;
+            if (sc->stc & STCref)
+                tf->isref = true;
+            if (sc->stc & STCreturn)
+                tf->isreturn = true;
+            if (sc->stc & STCscope)
+                tf->isscope = true;
+            if (sc->stc & STCscopeinferred)
+                tf->isscopeinferred = true;
+            //if ((sc->stc & (STCreturn | STCref)) == STCreturn)
+            //    tf->isscope = true; // return by itself means 'return scope'
+
+            if (tf->trust == TRUSTdefault)
+            {
+                if (sc->stc & STCsafe)
+                    tf->trust = TRUSTsafe;
+                if (sc->stc & STCsystem)
+                    tf->trust = TRUSTsystem;
+                if (sc->stc & STCtrusted)
+                    tf->trust = TRUSTtrusted;
+            }
+
+            if (sc->stc & STCproperty)
+                tf->isproperty = true;
+
+            tf->linkage = sc->linkage;
+            bool wildreturn = false;
+            if (tf->next)
+            {
+                sc = sc->push();
+                sc->stc &= ~(STC_TYPECTOR | STC_FUNCATTR);
+                tf->next = typeSemantic(tf->next, loc, sc);
+                sc = sc->pop();
+                errors |= tf->checkRetType(loc);
+                if (tf->next->isscope() && !(sc->flags & SCOPEctor))
+                {
+                    ::error(loc, "functions cannot return scope %s", tf->next->toChars());
+                    errors = true;
+                }
+                if (tf->next->hasWild())
+                    wildreturn = true;
+
+                if (tf->isreturn && !tf->isref && !tf->next->hasPointers())
+                {
+                    ::error(loc, "function type `%s` has `return` but does not return any indirections", tf->toChars());
+                }
+            }
+
+            unsigned char wildparams = 0;
+            if (tf->parameterList.parameters)
+            {
+                /* Create a scope for evaluating the default arguments for the parameters
+                 */
+                Scope *argsc = sc->push();
+                argsc->stc = 0;                 // don't inherit storage class
+                argsc->protection = Prot(Prot::public_);
+                argsc->func = NULL;
+
+                size_t dim = tf->parameterList.length();
+                for (size_t i = 0; i < dim; i++)
+                {
+                    Parameter *fparam = tf->parameterList[i];
+                    mtype->inuse++;
+                    fparam->type = typeSemantic(fparam->type, loc, argsc);
+                    mtype->inuse--;
+
+                    if (fparam->type->ty == Terror)
+                    {
+                        errors = true;
+                        continue;
+                    }
+
+                    fparam->type = fparam->type->addStorageClass(fparam->storageClass);
+
+                    if (fparam->storageClass & (STCauto | STCalias | STCstatic))
+                    {
+                        if (!fparam->type)
+                            continue;
+                    }
+
+                    Type *t = fparam->type->toBasetype();
+
+                    if (t->ty == Tfunction)
+                    {
+                        ::error(loc, "cannot have parameter of function type %s", fparam->type->toChars());
+                        errors = true;
+                    }
+                    else if (!(fparam->storageClass & (STCref | STCout)) &&
+                             (t->ty == Tstruct || t->ty == Tsarray || t->ty == Tenum))
+                    {
+                        Type *tb2 = t->baseElemOf();
+                        if ((tb2->ty == Tstruct && !((TypeStruct *)tb2)->sym->members) ||
+                            (tb2->ty == Tenum && !((TypeEnum *)tb2)->sym->memtype))
+                        {
+                            ::error(loc, "cannot have parameter of opaque type %s by value", fparam->type->toChars());
+                            errors = true;
+                        }
+                    }
+                    else if (!(fparam->storageClass & STClazy) && t->ty == Tvoid)
+                    {
+                        ::error(loc, "cannot have parameter of type %s", fparam->type->toChars());
+                        errors = true;
+                    }
+
+                    if ((fparam->storageClass & (STCref | STCwild)) == (STCref | STCwild))
+                    {
+                        // 'ref inout' implies 'return'
+                        fparam->storageClass |= STCreturn;
+                    }
+
+                    if (fparam->storageClass & STCreturn)
+                    {
+                        if (fparam->storageClass & (STCref | STCout))
+                        {
+                            // Disabled for the moment awaiting improvement to allow return by ref
+                            // to be transformed into return by scope.
+                            if (0 && !tf->isref)
+                            {
+                                StorageClass stc = fparam->storageClass & (STCref | STCout);
+                                ::error(loc, "parameter %s is `return %s` but function does not return by ref",
+                                    fparam->ident ? fparam->ident->toChars() : "",
+                                    stcToChars(stc));
+                                errors = true;
+                            }
+                        }
+                        else
+                        {
+                            fparam->storageClass |= STCscope;        // 'return' implies 'scope'
+                            if (tf->isref)
+                            {
+                            }
+                            else if (!tf->isref && tf->next && !tf->next->hasPointers())
+                            {
+                                ::error(loc, "parameter %s is `return` but function does not return any indirections",
+                                    fparam->ident ? fparam->ident->toChars() : "");
+                                errors = true;
+                            }
+                        }
+                    }
+
+                    if (fparam->storageClass & (STCref | STClazy))
+                    {
+                    }
+                    else if (fparam->storageClass & STCout)
+                    {
+                        if (unsigned char m = fparam->type->mod & (MODimmutable | MODconst | MODwild))
+                        {
+                            ::error(loc, "cannot have %s out parameter of type %s", MODtoChars(m), t->toChars());
+                            errors = true;
+                        }
+                        else
+                        {
+                            Type *tv = t;
+                            while (tv->ty == Tsarray)
+                                tv = tv->nextOf()->toBasetype();
+                            if (tv->ty == Tstruct && ((TypeStruct *)tv)->sym->noDefaultCtor)
+                            {
+                                ::error(loc, "cannot have out parameter of type %s because the default construction is disabled",
+                                    fparam->type->toChars());
+                                errors = true;
+                            }
+                        }
+                    }
+
+                    if (fparam->storageClass & STCscope && !fparam->type->hasPointers() && fparam->type->ty != Ttuple)
+                    {
+                        fparam->storageClass &= ~STCscope;
+                        if (!(fparam->storageClass & STCref))
+                            fparam->storageClass &= ~STCreturn;
+                    }
+
+                    if (t->hasWild())
+                    {
+                        wildparams |= 1;
+                        //if (tf->next && !wildreturn)
+                        //    ::error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with `ref`)");
+                    }
+
+                    if (fparam->defaultArg)
+                    {
+                        Expression *e = fparam->defaultArg;
+                        if (fparam->storageClass & (STCref | STCout))
+                        {
+                            e = expressionSemantic(e, argsc);
+                            e = resolveProperties(argsc, e);
+                        }
+                        else
+                        {
+                            e = inferType(e, fparam->type);
+                            Initializer *iz = new ExpInitializer(e->loc, e);
+                            iz = initializerSemantic(iz, argsc, fparam->type, INITnointerpret);
+                            e = initializerToExpression(iz);
+                        }
+                        if (e->op == TOKfunction)               // see Bugzilla 4820
+                        {
+                            FuncExp *fe = (FuncExp *)e;
+                            // Replace function literal with a function symbol,
+                            // since default arg expression must be copied when used
+                            // and copying the literal itself is wrong.
+                            e = new VarExp(e->loc, fe->fd, false);
+                            e = new AddrExp(e->loc, e);
+                            e = expressionSemantic(e, argsc);
+                        }
+                        e = e->implicitCastTo(argsc, fparam->type);
+
+                        // default arg must be an lvalue
+                        if (fparam->storageClass & (STCout | STCref))
+                            e = e->toLvalue(argsc, e);
+
+                        fparam->defaultArg = e;
+                        if (e->op == TOKerror)
+                            errors = true;
+                    }
+
+                    /* If fparam after semantic() turns out to be a tuple, the number of parameters may
+                     * change.
+                     */
+                    if (t->ty == Ttuple)
+                    {
+                        /* TypeFunction::parameter also is used as the storage of
+                         * Parameter objects for FuncDeclaration. So we should copy
+                         * the elements of TypeTuple::arguments to avoid unintended
+                         * sharing of Parameter object among other functions.
+                         */
+                        TypeTuple *tt = (TypeTuple *)t;
+                        if (tt->arguments && tt->arguments->length)
+                        {
+                            /* Propagate additional storage class from tuple parameters to their
+                             * element-parameters.
+                             * Make a copy, as original may be referenced elsewhere.
+                             */
+                            size_t tdim = tt->arguments->length;
+                            Parameters *newparams = new Parameters();
+                            newparams->setDim(tdim);
+                            for (size_t j = 0; j < tdim; j++)
+                            {
+                                Parameter *narg = (*tt->arguments)[j];
+
+                                // Bugzilla 12744: If the storage classes of narg
+                                // conflict with the ones in fparam, it's ignored.
+                                StorageClass stc  = fparam->storageClass | narg->storageClass;
+                                StorageClass stc1 = fparam->storageClass & (STCref | STCout | STClazy);
+                                StorageClass stc2 =   narg->storageClass & (STCref | STCout | STClazy);
+                                if (stc1 && stc2 && stc1 != stc2)
+                                {
+                                    OutBuffer buf1;  stcToBuffer(&buf1, stc1 | ((stc1 & STCref) ? (fparam->storageClass & STCauto) : 0));
+                                    OutBuffer buf2;  stcToBuffer(&buf2, stc2);
+
+                                    ::error(loc, "incompatible parameter storage classes `%s` and `%s`",
+                                              buf1.peekChars(), buf2.peekChars());
+                                    errors = true;
+                                    stc = stc1 | (stc & ~(STCref | STCout | STClazy));
+                                }
+
+                                (*newparams)[j] = new Parameter(
+                                        stc, narg->type, narg->ident, narg->defaultArg, narg->userAttribDecl);
+                            }
+                            fparam->type = new TypeTuple(newparams);
+                        }
+                        fparam->storageClass = 0;
+
+                        /* Reset number of parameters, and back up one to do this fparam again,
+                         * now that it is a tuple
+                         */
+                        dim = tf->parameterList.length();
+                        i--;
+                        continue;
+                    }
+
+                    /* Resolve "auto ref" storage class to be either ref or value,
+                     * based on the argument matching the parameter
+                     */
+                    if (fparam->storageClass & STCauto)
+                    {
+                        if (mtype->fargs && i < mtype->fargs->length && (fparam->storageClass & STCref))
+                        {
+                            Expression *farg = (*mtype->fargs)[i];
+                            if (farg->isLvalue())
+                                ;                               // ref parameter
+                            else
+                                fparam->storageClass &= ~STCref;        // value parameter
+                            fparam->storageClass &= ~STCauto;    // Bugzilla 14656
+                            fparam->storageClass |= STCautoref;
+                        }
+                        else
+                        {
+                            ::error(loc, "`auto` can only be used as part of `auto ref` for template function parameters");
+                            errors = true;
+                        }
+                    }
+
+                    // Remove redundant storage classes for type, they are already applied
+                    fparam->storageClass &= ~(STC_TYPECTOR | STCin);
+                }
+                argsc->pop();
+            }
+            if (tf->isWild())
+                wildparams |= 2;
+
+            if (wildreturn && !wildparams)
+            {
+                ::error(loc, "inout on return means inout must be on a parameter as well for %s", mtype->toChars());
+                errors = true;
+            }
+            tf->iswild = wildparams;
+
+            if (tf->isproperty && (tf->parameterList.varargs != VARARGnone || tf->parameterList.length() > 2))
+            {
+                ::error(loc, "properties can only have zero, one, or two parameter");
+                errors = true;
+            }
+
+            if (tf->parameterList.varargs == VARARGvariadic && tf->linkage != LINKd && tf->parameterList.length() == 0)
+            {
+                ::error(loc, "variadic functions with non-D linkage must have at least one parameter");
+                errors = true;
+            }
+
+            if (errors)
+                return error();
+
+            if (tf->next)
+                tf->deco = tf->merge()->deco;
+
+            /* Don't return merge(), because arg identifiers and default args
+             * can be different
+             * even though the types match
+             */
+            result = tf;
+        }
+
+        void visit(TypeDelegate *mtype)
+        {
+            //printf("TypeDelegate::semantic() %s\n", mtype->toChars());
+            if (mtype->deco)                   // if semantic() already run
+            {
+                //printf("already done\n");
+                result = mtype;
+                return;
+            }
+            mtype->next = typeSemantic(mtype->next, loc,sc);
+            if (mtype->next->ty != Tfunction)
+                return error();
+
+            /* In order to deal with Bugzilla 4028, perhaps default arguments should
+             * be removed from next before the merge.
+             */
+
+            /* Don't return merge(), because arg identifiers and default args
+             * can be different
+             * even though the types match
+             */
+            mtype->deco = mtype->merge()->deco;
+            result = mtype;
+        }
+
+        void visit(TypeTraits *mtype)
+        {
+            if (mtype->ty == Terror)
+            {
+                result = mtype;
+                return;
+            }
+
+            const int inAlias = (sc->flags & SCOPEalias) != 0;
+            if (mtype->exp->ident != Id::allMembers &&
+                mtype->exp->ident != Id::derivedMembers &&
+                mtype->exp->ident != Id::getMember &&
+                mtype->exp->ident != Id::parent &&
+                mtype->exp->ident != Id::child &&
+                mtype->exp->ident != Id::getOverloads &&
+                mtype->exp->ident != Id::getVirtualFunctions &&
+                mtype->exp->ident != Id::getVirtualMethods &&
+                mtype->exp->ident != Id::getAttributes &&
+                mtype->exp->ident != Id::getUnitTests &&
+                mtype->exp->ident != Id::getAliasThis)
+            {
+                static const char *ctxt[2] = {"as type", "in alias"};
+                ::error(loc, "trait `%s` is either invalid or not supported %s",
+                        mtype->exp->ident->toChars(), ctxt[inAlias]);
+                mtype->ty = Terror;
+                result = mtype;
+                return;
+            }
+
+            if (Expression *e = semanticTraits(mtype->exp, sc))
+            {
+                switch (e->op)
+                {
+                case TOKdotvar:
+                    mtype->sym = ((DotVarExp *)e)->var;
+                    break;
+                case TOKvar:
+                    mtype->sym = ((VarExp *)e)->var;
+                    break;
+                case TOKfunction:
+                {
+                    FuncExp *fe = (FuncExp *)e;
+                    if (fe->td)
+                        mtype->sym = fe->td;
+                    else
+                        mtype->sym = fe->fd;
+                    break;
+                }
+                case TOKdottd:
+                    mtype->sym = ((DotTemplateExp*)e)->td;
+                    break;
+                case TOKdsymbol:
+                    mtype->sym = ((DsymbolExp *)e)->s;
+                    break;
+                case TOKtemplate:
+                    mtype->sym = ((TemplateExp *)e)->td;
+                    break;
+                case TOKscope:
+                    mtype->sym = ((ScopeExp *)e)->sds;
+                    break;
+                case TOKtuple:
+                {
+                    TupleExp *te = e->toTupleExp();
+                    Objects *elems = new Objects;
+                    elems->setDim(te->exps->length);
+                    for (size_t i = 0; i < elems->length; i++)
+                    {
+                        Expression *src = (*te->exps)[i];
+                        switch (src->op)
+                        {
+                        case TOKtype:
+                            (*elems)[i] = ((TypeExp *)src)->type;
+                            break;
+                        case TOKdottype:
+                            (*elems)[i] = ((DotTypeExp *)src)->type;
+                            break;
+                        case TOKoverloadset:
+                            (*elems)[i] = ((OverExp *)src)->type;
+                            break;
+                        default:
+                            if (Dsymbol *sym = isDsymbol(src))
+                                (*elems)[i] = sym;
+                            else
+                                (*elems)[i] = src;
+                        }
+                    }
+                    TupleDeclaration *td = new TupleDeclaration(e->loc,
+                        Identifier::generateId("__aliastup"), elems);
+                    mtype->sym = td;
+                    break;
+                }
+                case TOKdottype:
+                    result = isType(((DotTypeExp *)e)->sym);
+                    break;
+                case TOKtype:
+                    result = ((TypeExp *)e)->type;
+                    break;
+                case TOKoverloadset:
+                    result = ((OverExp *)e)->type;
+                    break;
+                default:
+                    break;
+                }
+            }
+
+            if (result)
+                result = result->addMod(mtype->mod);
+            if (!inAlias && !result)
+            {
+                if (!global.errors)
+                    ::error(loc, "`%s` does not give a valid type", mtype->toChars());
+                return error();
+            }
+        }
+
+        void visit(TypeIdentifier *mtype)
+        {
+            Type *t;
+            Expression *e;
+            Dsymbol *s;
+
+            //printf("TypeIdentifier::semantic(%s)\n", mtype->toChars());
+            mtype->resolve(loc, sc, &e, &t, &s);
+            if (t)
+            {
+                //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
+                t = t->addMod(mtype->mod);
+            }
+            else
+            {
+                if (s)
+                {
+                    s->error(loc, "is used as a type");
+                    //halt();
+                }
+                else
+                    ::error(loc, "%s is used as a type", mtype->toChars());
+                return error();
+            }
+            //t->print();
+            result = t;
+        }
+
+        void visit(TypeInstance *mtype)
+        {
+            Type *t;
+            Expression *e;
+            Dsymbol *s;
+
+            //printf("TypeInstance::semantic(%p, %s)\n", this, mtype->toChars());
+            {
+                unsigned errors = global.errors;
+                mtype->resolve(loc, sc, &e, &t, &s);
+                // if we had an error evaluating the symbol, suppress further errors
+                if (!t && errors != global.errors)
+                    return error();
+            }
+
+            if (!t)
+            {
+                if (!e && s && s->errors)
+                {
+                    // if there was an error evaluating the symbol, it might actually
+                    // be a type. Avoid misleading error messages.
+                    ::error(loc, "%s had previous errors", mtype->toChars());
+                }
+                else
+                    ::error(loc, "%s is used as a type", mtype->toChars());
+                return error();
+            }
+            result = t;
+        }
+
+        void visit(TypeTypeof *mtype)
+        {
+            //printf("TypeTypeof::semantic() %s\n", mtype->toChars());
+
+            Expression *e;
+            Type *t;
+            Dsymbol *s;
+            mtype->resolve(loc, sc, &e, &t, &s);
+            if (s && (t = s->getType()) != NULL)
+                t = t->addMod(mtype->mod);
+            if (!t)
+            {
+                ::error(loc, "%s is used as a type", mtype->toChars());
+                return error();
+            }
+            result = t;
+        }
+
+        void visit(TypeReturn *mtype)
+        {
+            //printf("TypeReturn::semantic() %s\n", mtype->toChars());
+
+            Expression *e;
+            Type *t;
+            Dsymbol *s;
+            mtype->resolve(loc, sc, &e, &t, &s);
+            if (s && (t = s->getType()) != NULL)
+                t = t->addMod(mtype->mod);
+            if (!t)
+            {
+                ::error(loc, "%s is used as a type", mtype->toChars());
+                return error();
+            }
+            result = t;
+        }
+
+        void visit(TypeEnum *mtype)
+        {
+            //printf("TypeEnum::semantic() %s\n", mtype->toChars());
+            result = mtype->deco ? mtype : mtype->merge();
+        }
+
+        void visit(TypeStruct *mtype)
+        {
+            //printf("TypeStruct::semantic('%s')\n", mtype->sym->toChars());
+            if (mtype->deco)
+            {
+                if (sc && sc->cppmangle != CPPMANGLEdefault)
+                {
+                    if (mtype->cppmangle == CPPMANGLEdefault)
+                        mtype->cppmangle = sc->cppmangle;
+                    else
+                        assert(mtype->cppmangle == sc->cppmangle);
+                }
+                result = mtype;
+                return;
+            }
+
+            /* Don't semantic for sym because it should be deferred until
+             * sizeof needed or its members accessed.
+             */
+            // instead, parent should be set correctly
+            assert(mtype->sym->parent);
+
+            if (mtype->sym->type->ty == Terror)
+                return error();
+            if (sc)
+                mtype->cppmangle = sc->cppmangle;
+            result = mtype->merge();
+        }
+
+        void visit(TypeClass *mtype)
+        {
+            //printf("TypeClass::semantic(%s)\n", mtype->sym->toChars());
+            if (mtype->deco)
+            {
+                if (sc && sc->cppmangle != CPPMANGLEdefault)
+                {
+                    if (mtype->cppmangle == CPPMANGLEdefault)
+                        mtype->cppmangle = sc->cppmangle;
+                    else
+                        assert(mtype->cppmangle == sc->cppmangle);
+                }
+                result = mtype;
+                return;
+            }
+
+            /* Don't semantic for sym because it should be deferred until
+             * sizeof needed or its members accessed.
+             */
+            // instead, parent should be set correctly
+            assert(mtype->sym->parent);
+
+            if (mtype->sym->type->ty == Terror)
+                return error();
+            if (sc)
+                mtype->cppmangle = sc->cppmangle;
+            result = mtype->merge();
+        }
+
+        void visit(TypeTuple *mtype)
+        {
+            //printf("TypeTuple::semantic(this = %p)\n", this);
+            //printf("TypeTuple::semantic() %p, %s\n", this, mtype->toChars());
+            if (!mtype->deco)
+                mtype->deco = mtype->merge()->deco;
+
+            /* Don't return merge(), because a tuple with one type has the
+             * same deco as that type.
+             */
+            result = mtype;
+        }
+
+        void visit(TypeSlice *mtype)
+        {
+            //printf("TypeSlice::semantic() %s\n", mtype->toChars());
+            Type *tn = typeSemantic(mtype->next, loc, sc);
+            //printf("next: %s\n", tn->toChars());
+
+            Type *tbn = tn->toBasetype();
+            if (tbn->ty != Ttuple)
+            {
+                ::error(loc, "can only slice tuple types, not %s", tbn->toChars());
+                return error();
+            }
+            TypeTuple *tt = (TypeTuple *)tbn;
+
+            mtype->lwr = semanticLength(sc, tbn, mtype->lwr);
+            mtype->lwr = mtype->lwr->ctfeInterpret();
+            uinteger_t i1 = mtype->lwr->toUInteger();
+
+            mtype->upr = semanticLength(sc, tbn, mtype->upr);
+            mtype->upr = mtype->upr->ctfeInterpret();
+            uinteger_t i2 = mtype->upr->toUInteger();
+
+            if (!(i1 <= i2 && i2 <= tt->arguments->length))
+            {
+                ::error(loc, "slice `[%llu..%llu]` is out of range of [0..%llu]",
+                    (unsigned long long)i1, (unsigned long long)i2, (unsigned long long)tt->arguments->length);
+                return error();
+            }
+
+            mtype->next = tn;
+            mtype->transitive();
+
+            Parameters *args = new Parameters;
+            args->reserve((size_t)(i2 - i1));
+            for (size_t i = (size_t)i1; i < (size_t)i2; i++)
+            {
+                Parameter *arg = (*tt->arguments)[i];
+                args->push(arg);
+            }
+            Type *t = new TypeTuple(args);
+            result = typeSemantic(t, loc, sc);
+        }
+    };
+    TypeSemanticVisitor v(loc, sc);
+    type->accept(&v);
+    return v.result;
+}
index c497f961315045374d218d0094062fa98188220b..f6b543590f2165602fa3c892010f768f83f2d8bb 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2003-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2003-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 52a731f0bf8ed09ea16767406f57daed2c369244..b3782afe78b0fc9f4d518376f024c2c1b025c883 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2003-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2003-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 73de2e409b2cfbc36bb09b3b10d3a72f68975c27..c9e632234efdf7c5dbb49072c0ce7fa0fc264e8c 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
index 36c9ef73ed165eaa6c99ef75c5a90d7a959900b1..9e7fd5ea75d1cbfbfe142c6fb66ba7df02370578 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -23,7 +23,6 @@ public:
 
     const char *toChars();
     void addMember(Scope *sc, ScopeDsymbol *sds);
-    void semantic(Scope *sc);
     const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -39,7 +38,6 @@ public:
 
     const char *toChars();
     void addMember(Scope *sc, ScopeDsymbol *sds);
-    void semantic(Scope *sc);
     const char *kind() const;
     void accept(Visitor *v) { v->visit(this); }
 };
index 5f2bf2cccb4b1118e9532b12c794af1699237138..a274e6f083e916faac2a875bb2ef76228831bfd1 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 2013-2020 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 2013-2021 by The D Language Foundation, All Rights Reserved
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
  * http://www.boost.org/LICENSE_1_0.txt
index ec8539deb45402e3b06fc99f2b008230e25e1f71..698e7669884bfd87ee426b5a713b1521c645f7ba 100644 (file)
@@ -210,7 +210,7 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
   ClassDeclaration *tinfo = ClassDeclaration::create (loc, ident, NULL, NULL,
                                                      true);
   tinfo->parent = object_module;
-  tinfo->semantic (object_module->_scope);
+  dsymbolSemantic (tinfo, object_module->_scope);
   tinfo->baseClass = base;
   /* This is a compiler generated class, and shouldn't be mistaken for being
      the type declared in the runtime library.  */