diff options
139 files changed, 9937 insertions, 9782 deletions
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in index 2b3c936..b0fce06 100644 --- a/gcc/d/Make-lang.in +++ b/gcc/d/Make-lang.in @@ -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 \ diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc index 3907d01..512ef4b 100644 --- a/gcc/d/d-compiler.cc +++ b/gcc/d/d-compiler.cc @@ -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); } diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 0fd207d..1a51c5e 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -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 (); diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 89397c8..690fe40 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -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. diff --git a/gcc/d/dmd/access.c b/gcc/d/dmd/access.c index 63f46c6..11b26c5 100644 --- a/gcc/d/dmd/access.c +++ b/gcc/d/dmd/access.c @@ -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. diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index 6cfc76d..4935e6a 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -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; diff --git a/gcc/d/dmd/aliasthis.c b/gcc/d/dmd/aliasthis.c index 9da64d0..458416f 100644 --- a/gcc/d/dmd/aliasthis.c +++ b/gcc/d/dmd/aliasthis.c @@ -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. @@ -18,10 +18,9 @@ #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"; diff --git a/gcc/d/dmd/aliasthis.h b/gcc/d/dmd/aliasthis.h index 816a4ee..15905e4 100644 --- a/gcc/d/dmd/aliasthis.h +++ b/gcc/d/dmd/aliasthis.h @@ -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); } diff --git a/gcc/d/dmd/apply.c b/gcc/d/dmd/apply.c index 6f3301e..8a727ae 100644 --- a/gcc/d/dmd/apply.c +++ b/gcc/d/dmd/apply.c @@ -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/arrayop.c b/gcc/d/dmd/arrayop.c index 20cdb6f..52d596b 100644 --- a/gcc/d/dmd/arrayop.c +++ b/gcc/d/dmd/arrayop.c @@ -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) diff --git a/gcc/d/dmd/arraytypes.h b/gcc/d/dmd/arraytypes.h index 627464a..0ecccf1 100644 --- a/gcc/d/dmd/arraytypes.h +++ b/gcc/d/dmd/arraytypes.h @@ -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. diff --git a/gcc/d/dmd/ast_node.h b/gcc/d/dmd/ast_node.h index 09519af..5576dd7 100644 --- a/gcc/d/dmd/ast_node.h +++ b/gcc/d/dmd/ast_node.h @@ -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/attrib.c b/gcc/d/dmd/attrib.c index 5445b9e..56b8ce8 100644 --- a/gcc/d/dmd/attrib.c +++ b/gcc/d/dmd/attrib.c @@ -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; diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h index a20e96b..7436417 100644 --- a/gcc/d/dmd/attrib.h +++ b/gcc/d/dmd/attrib.h @@ -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; diff --git a/gcc/d/dmd/blockexit.c b/gcc/d/dmd/blockexit.c index 4705862..44e3cc1 100644 --- a/gcc/d/dmd/blockexit.c +++ b/gcc/d/dmd/blockexit.c @@ -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; diff --git a/gcc/d/dmd/canthrow.c b/gcc/d/dmd/canthrow.c index 33d61ed..5d180f5 100644 --- a/gcc/d/dmd/canthrow.c +++ b/gcc/d/dmd/canthrow.c @@ -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; diff --git a/gcc/d/dmd/clone.c b/gcc/d/dmd/clone.c index 73c4a66..eb09076 100644 --- a/gcc/d/dmd/clone.c +++ b/gcc/d/dmd/clone.c @@ -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; } } diff --git a/gcc/d/dmd/compiler.h b/gcc/d/dmd/compiler.h index 7f9006c..e7ef5a4 100644 --- a/gcc/d/dmd/compiler.h +++ b/gcc/d/dmd/compiler.h @@ -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/complex_t.h b/gcc/d/dmd/complex_t.h index c36c4ec..7f17460 100644 --- a/gcc/d/dmd/complex_t.h +++ b/gcc/d/dmd/complex_t.h @@ -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/cond.c b/gcc/d/dmd/cond.c index 2ea3d40..6f112ad 100644 --- a/gcc/d/dmd/cond.c +++ b/gcc/d/dmd/cond.c @@ -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) diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h index 17398c1..593a98d 100644 --- a/gcc/d/dmd/cond.h +++ b/gcc/d/dmd/cond.h @@ -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/constfold.c b/gcc/d/dmd/constfold.c index 38e6191..8cfeac5 100644 --- a/gcc/d/dmd/constfold.c +++ b/gcc/d/dmd/constfold.c @@ -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/cppmangle.c b/gcc/d/dmd/cppmangle.c index 3f571fc..a0e0b5f 100644 --- a/gcc/d/dmd/cppmangle.c +++ b/gcc/d/dmd/cppmangle.c @@ -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/ctfe.h b/gcc/d/dmd/ctfe.h index 1eab264..359739e 100644 --- a/gcc/d/dmd/ctfe.h +++ b/gcc/d/dmd/ctfe.h @@ -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/ctfeexpr.c b/gcc/d/dmd/ctfeexpr.c index ee38033..1d669e5 100644 --- a/gcc/d/dmd/ctfeexpr.c +++ b/gcc/d/dmd/ctfeexpr.c @@ -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/dcast.c b/gcc/d/dmd/dcast.c index 1fc9d93..61e28fe 100644 --- a/gcc/d/dmd/dcast.c +++ b/gcc/d/dmd/dcast.c @@ -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)) { diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c index 7481f91..c7dbbbe 100644 --- a/gcc/d/dmd/dclass.c +++ b/gcc/d/dmd/dclass.c @@ -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; } diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c index d20f663..a9394dc 100644 --- a/gcc/d/dmd/declaration.c +++ b/gcc/d/dmd/declaration.c @@ -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,10 +29,6 @@ #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()); diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index 6a3ec9e..81b563f 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -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(); diff --git a/gcc/d/dmd/delegatize.c b/gcc/d/dmd/delegatize.c index 3aec393..b3019aa 100644 --- a/gcc/d/dmd/delegatize.c +++ b/gcc/d/dmd/delegatize.c @@ -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; } diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c index d15d94a..ca1d3bb 100644 --- a/gcc/d/dmd/denum.c +++ b/gcc/d/dmd/denum.c @@ -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); } diff --git a/gcc/d/dmd/dimport.c b/gcc/d/dmd/dimport.c index 4b969d4..0d93ed8 100644 --- a/gcc/d/dmd/dimport.c +++ b/gcc/d/dmd/dimport.c @@ -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 diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c index f868790..5e71f3b 100644 --- a/gcc/d/dmd/dinterpret.c +++ b/gcc/d/dmd/dinterpret.c @@ -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(); } diff --git a/gcc/d/dmd/dmacro.c b/gcc/d/dmd/dmacro.c index cefd3b0..91cbe50 100644 --- a/gcc/d/dmd/dmacro.c +++ b/gcc/d/dmd/dmacro.c @@ -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/dmangle.c b/gcc/d/dmd/dmangle.c index 4a9a118..303ae61 100644 --- a/gcc/d/dmd/dmangle.c +++ b/gcc/d/dmd/dmangle.c @@ -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/dmodule.c b/gcc/d/dmd/dmodule.c index 95c263f..a2b01f5 100644 --- a/gcc/d/dmd/dmodule.c +++ b/gcc/d/dmd/dmodule.c @@ -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 diff --git a/gcc/d/dmd/doc.c b/gcc/d/dmd/doc.c index 92783b8..5d2da1c 100644 --- a/gcc/d/dmd/doc.c +++ b/gcc/d/dmd/doc.c @@ -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 { diff --git a/gcc/d/dmd/doc.h b/gcc/d/dmd/doc.h index c06ffe6..6d13ab1 100644 --- a/gcc/d/dmd/doc.h +++ b/gcc/d/dmd/doc.h @@ -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/dscope.c b/gcc/d/dmd/dscope.c index 72dc089..65e6734 100644 --- a/gcc/d/dmd/dscope.c +++ b/gcc/d/dmd/dscope.c @@ -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; } diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c index 8829367..40c67ce 100644 --- a/gcc/d/dmd/dstruct.c +++ b/gcc/d/dmd/dstruct.c @@ -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; } diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c index 293484c..89c5557 100644 --- a/gcc/d/dmd/dsymbol.c +++ b/gcc/d/dmd/dsymbol.c @@ -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; diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index 6555f12..1ddfe06 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -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 index 0000000..5d5c9fc --- /dev/null +++ b/gcc/d/dmd/dsymbolsem.c @@ -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); +} diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c index 316f105..b868e9a 100644 --- a/gcc/d/dmd/dtemplate.c +++ b/gcc/d/dmd/dtemplate.c @@ -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++) diff --git a/gcc/d/dmd/dversion.c b/gcc/d/dmd/dversion.c index f88fca5..269d924 100644 --- a/gcc/d/dmd/dversion.c +++ b/gcc/d/dmd/dversion.c @@ -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"; diff --git a/gcc/d/dmd/entity.c b/gcc/d/dmd/entity.c index 5006763..cac901d 100644 --- a/gcc/d/dmd/entity.c +++ b/gcc/d/dmd/entity.c @@ -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/enum.h b/gcc/d/dmd/enum.h index 6d389ed..ae5ea21 100644 --- a/gcc/d/dmd/enum.h +++ b/gcc/d/dmd/enum.h @@ -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; } diff --git a/gcc/d/dmd/errors.h b/gcc/d/dmd/errors.h index 165da69..a92ae2a 100644 --- a/gcc/d/dmd/errors.h +++ b/gcc/d/dmd/errors.h @@ -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/escape.c b/gcc/d/dmd/escape.c index b3fccd9..cd0382b 100644 --- a/gcc/d/dmd/escape.c +++ b/gcc/d/dmd/escape.c @@ -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/expression.c b/gcc/d/dmd/expression.c index 3314d0c..c90392d 100644 --- a/gcc/d/dmd/expression.c +++ b/gcc/d/dmd/expression.c @@ -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(); diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index 15a4d87..f0ae280 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -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); diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c index 7cebd9a..7cccd95 100644 --- a/gcc/d/dmd/expressionsem.c +++ b/gcc/d/dmd/expressionsem.c @@ -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: diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c index 2f1d648..7a216a9 100644 --- a/gcc/d/dmd/func.c +++ b/gcc/d/dmd/func.c @@ -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,275 +22,20 @@ #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,824 +183,6 @@ static bool allowsContractWithoutBody(FuncDeclaration *funcdecl) return true; } -// Do the semantic analysis on the external interface to the function. - -void FuncDeclaration::semantic(Scope *sc) -{ - 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); - } - - 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 - { - // 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; - - 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 (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 (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); - } - - 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. @@ -1326,7 +192,7 @@ void FuncDeclaration::semantic2(Scope *sc) * true found an 'out' contract * false didn't find one */ -static bool needsFensure(FuncDeclaration *fd) +bool FuncDeclaration::needsFensure(FuncDeclaration *fd) { if (fd->fensures) return true; @@ -1358,12 +224,10 @@ static bool canBuildResultVar(FuncDeclaration *fd) /**************************************************** * Rewrite contracts as statements. - * Params: - * fdx = the function to rewrite contracts for */ -static void buildEnsureRequire(FuncDeclaration *fdx) +void FuncDeclaration::buildEnsureRequire() { - if (fdx->frequires) + if (frequires) { /* in { statements1... } * in { statements2... } @@ -1371,18 +235,18 @@ static void buildEnsureRequire(FuncDeclaration *fdx) * becomes: * in { { statements1... } { statements2... } ... } */ - assert(fdx->frequires->length); - Loc loc = (*fdx->frequires)[0]->loc; + assert(frequires->length); + Loc loc = (*frequires)[0]->loc; Statements *s = new Statements; - for (size_t i = 0; i < fdx->frequires->length; i++) + for (size_t i = 0; i < frequires->length; i++) { - Statement *r = (*fdx->frequires)[i]; + Statement *r = (*frequires)[i]; s->push(new ScopeStatement(r->loc, r, r->loc)); } - fdx->frequire = new CompoundStatement(loc, s); + frequire = new CompoundStatement(loc, s); } - if (fdx->fensures) + if (fensures) { /* out(id1) { statements1... } * out(id2) { statements2... } @@ -1391,13 +255,13 @@ static void buildEnsureRequire(FuncDeclaration *fdx) * out(__result) { { ref id1 = __result; { statements1... } } * { ref id2 = __result; { statements2... } } ... } */ - assert(fdx->fensures->length); - Loc loc = (*fdx->fensures)[0].ensure->loc; + assert(fensures->length); + Loc loc = (*fensures)[0].ensure->loc; Statements *s = new Statements; - for (size_t i = 0; i < fdx->fensures->length; i++) + for (size_t i = 0; i < fensures->length; i++) { - Ensure r = (*fdx->fensures)[i]; - if (r.id && canBuildResultVar(fdx)) + Ensure r = (*fensures)[i]; + if (r.id && canBuildResultVar(this)) { Loc rloc = r.ensure->loc; IdentifierExp *resultId = new IdentifierExp(rloc, Id::result); @@ -1413,25 +277,25 @@ static void buildEnsureRequire(FuncDeclaration *fdx) s->push(r.ensure); } } - fdx->fensure = new CompoundStatement(loc, s); + fensure = new CompoundStatement(loc, s); } - if (!fdx->isVirtual()) + if (!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; + TypeFunction *f = (TypeFunction *)type; - if (fdx->frequire) + if (frequire) { /* in { ... } * becomes: * void __require() { ... } * __require(); */ - Loc loc = fdx->frequire->loc; + Loc loc = frequire->loc; TypeFunction *tf = new TypeFunction(ParameterList(), Type::tvoid, LINKd); tf->isnothrow = f->isnothrow; tf->isnogc = f->isnogc; @@ -1439,25 +303,25 @@ static void buildEnsureRequire(FuncDeclaration *fdx) tf->trust = f->trust; FuncDeclaration *fd = new FuncDeclaration(loc, loc, Id::require, STCundefined, tf); - fd->fbody = fdx->frequire; + 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); - fdx->frequire = new CompoundStatement(loc, s1, s2); - fdx->fdrequire = fd; + frequire = new CompoundStatement(loc, s1, s2); + fdrequire = fd; } - if (fdx->fensure) + if (fensure) { /* out (result) { ... } * becomes: * void __ensure(ref tret result) { ... } * __ensure(result); */ - Loc loc = fdx->fensure->loc; + Loc loc = fensure->loc; Parameters *fparams = new Parameters(); Parameter *p = NULL; - if (canBuildResultVar(fdx)) + if (canBuildResultVar(this)) { p = new Parameter(STCref | STCconst, f->nextOf(), Id::result, NULL, NULL); fparams->push(p); @@ -1469,1051 +333,18 @@ static void buildEnsureRequire(FuncDeclaration *fdx) tf->trust = f->trust; FuncDeclaration *fd = new FuncDeclaration(loc, loc, Id::ensure, STCundefined, tf); - fd->fbody = fdx->fensure; + fd->fbody = fensure; Statement *s1 = new ExpStatement(loc, fd); Expression *eresult = NULL; - if (canBuildResultVar(fdx)) + 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); - fdx->fensure = new CompoundStatement(loc, s1, s2); - fdx->fdensure = fd; + fensure = new CompoundStatement(loc, s1, s2); + 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) - { - if (type == f) - f = (TypeFunction *)f->copy(); - f->isreturn = true; - } - } - - flags &= ~FUNCFLAGinferScope; - - // Infer STCscope - if (parameters) - { - size_t nfparams = f->parameterList.length(); - assert(nfparams == parameters->length); - for (size_t u = 0; u < parameters->length; u++) - { - VarDeclaration *v = (*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 (vthis && vthis->storage_class & STCmaybescope) - { - vthis->storage_class &= ~STCmaybescope; - vthis->storage_class |= STCscope | STCscopeinferred; - f->isscope = true; - f->isscopeinferred = true; - } - - // reset deco to apply inference result to mangled name - if (f != type) - f->deco = NULL; - - // Do semantic type AFTER pure/nothrow inference. - if (!f->deco && ident != Id::xopEquals && ident != Id::xopCmp) - { - 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(); - } - - /* 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); -} - /**************************************************** * Resolve forward reference of function signature - * parameter types, return type, and attributes. @@ -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"; diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index 6e65d86..d9d59d6 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -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/hdrgen.c b/gcc/d/dmd/hdrgen.c index a351930..a11c9c3 100644 --- a/gcc/d/dmd/hdrgen.c +++ b/gcc/d/dmd/hdrgen.c @@ -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. diff --git a/gcc/d/dmd/hdrgen.h b/gcc/d/dmd/hdrgen.h index 1bad506..d464d4a 100644 --- a/gcc/d/dmd/hdrgen.h +++ b/gcc/d/dmd/hdrgen.h @@ -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. diff --git a/gcc/d/dmd/iasm.c b/gcc/d/dmd/iasm.c index 459a3a6..fc58a3c 100644 --- a/gcc/d/dmd/iasm.c +++ b/gcc/d/dmd/iasm.c @@ -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. diff --git a/gcc/d/dmd/iasmgcc.c b/gcc/d/dmd/iasmgcc.c index 5cc9025..e3940a8 100644 --- a/gcc/d/dmd/iasmgcc.c +++ b/gcc/d/dmd/iasmgcc.c @@ -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. @@ -12,14 +12,12 @@ */ #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); } } diff --git a/gcc/d/dmd/identifier.c b/gcc/d/dmd/identifier.c index 1bd453f..197d288 100644 --- a/gcc/d/dmd/identifier.c +++ b/gcc/d/dmd/identifier.c @@ -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/identifier.h b/gcc/d/dmd/identifier.h index c611bf1..278ce9b 100644 --- a/gcc/d/dmd/identifier.h +++ b/gcc/d/dmd/identifier.h @@ -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/idgen.c b/gcc/d/dmd/idgen.c index 322a293..59faa99 100644 --- a/gcc/d/dmd/idgen.c +++ b/gcc/d/dmd/idgen.c @@ -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/impcnvgen.c b/gcc/d/dmd/impcnvgen.c index c221cd2..d7c27ea 100644 --- a/gcc/d/dmd/impcnvgen.c +++ b/gcc/d/dmd/impcnvgen.c @@ -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/imphint.c b/gcc/d/dmd/imphint.c index d08e374..239cb07 100644 --- a/gcc/d/dmd/imphint.c +++ b/gcc/d/dmd/imphint.c @@ -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. diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h index d173931..e49ad15 100644 --- a/gcc/d/dmd/import.h +++ b/gcc/d/dmd/import.h @@ -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); diff --git a/gcc/d/dmd/init.c b/gcc/d/dmd/init.c index 28b4187..d18e054 100644 --- a/gcc/d/dmd/init.c +++ b/gcc/d/dmd/init.c @@ -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) diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h index 6f98fdb..4ba18d6 100644 --- a/gcc/d/dmd/init.h +++ b/gcc/d/dmd/init.h @@ -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: diff --git a/gcc/d/dmd/initsem.c b/gcc/d/dmd/initsem.c index 9381da4..c7d1dfe 100644 --- a/gcc/d/dmd/initsem.c +++ b/gcc/d/dmd/initsem.c @@ -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; diff --git a/gcc/d/dmd/intrange.c b/gcc/d/dmd/intrange.c index 788b37b..36af8da 100644 --- a/gcc/d/dmd/intrange.c +++ b/gcc/d/dmd/intrange.c @@ -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. diff --git a/gcc/d/dmd/intrange.h b/gcc/d/dmd/intrange.h index 58ec5b9..fd61532 100644 --- a/gcc/d/dmd/intrange.h +++ b/gcc/d/dmd/intrange.h @@ -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. diff --git a/gcc/d/dmd/json.c b/gcc/d/dmd/json.c index 802de81..832e559 100644 --- a/gcc/d/dmd/json.c +++ b/gcc/d/dmd/json.c @@ -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/json.h b/gcc/d/dmd/json.h index 2dbcc0c..d680001 100644 --- a/gcc/d/dmd/json.h +++ b/gcc/d/dmd/json.h @@ -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/lexer.c b/gcc/d/dmd/lexer.c index db989b0..3ea932c 100644 --- a/gcc/d/dmd/lexer.c +++ b/gcc/d/dmd/lexer.c @@ -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; } diff --git a/gcc/d/dmd/lexer.h b/gcc/d/dmd/lexer.h index 555b6c6..b36e7f7 100644 --- a/gcc/d/dmd/lexer.h +++ b/gcc/d/dmd/lexer.h @@ -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/macro.h b/gcc/d/dmd/macro.h index 26710b4..80ec36e 100644 --- a/gcc/d/dmd/macro.h +++ b/gcc/d/dmd/macro.h @@ -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/mangle.h b/gcc/d/dmd/mangle.h index c60f4a7..544f77b 100644 --- a/gcc/d/dmd/mangle.h +++ b/gcc/d/dmd/mangle.h @@ -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/mars.h b/gcc/d/dmd/mars.h index ddccd6c..9b9c278 100644 --- a/gcc/d/dmd/mars.h +++ b/gcc/d/dmd/mars.h @@ -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/module.h b/gcc/d/dmd/module.h index 4968ec7..03078b5e 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -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); diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c index cc8eb22..c1071b2 100644 --- a/gcc/d/dmd/mtype.c +++ b/gcc/d/dmd/mtype.c @@ -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(); diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 28dba1c..083d707 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -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); } }; diff --git a/gcc/d/dmd/nogc.c b/gcc/d/dmd/nogc.c index 1372f48..12c8b49 100644 --- a/gcc/d/dmd/nogc.c +++ b/gcc/d/dmd/nogc.c @@ -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; diff --git a/gcc/d/dmd/nspace.c b/gcc/d/dmd/nspace.c index 71d1c6f..95cfb6f 100644 --- a/gcc/d/dmd/nspace.c +++ b/gcc/d/dmd/nspace.c @@ -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++) diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h index ae29b18..71dafb2 100644 --- a/gcc/d/dmd/nspace.h +++ b/gcc/d/dmd/nspace.h @@ -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); diff --git a/gcc/d/dmd/objc.c b/gcc/d/dmd/objc.c index b0353a5..3199a01 100644 --- a/gcc/d/dmd/objc.c +++ b/gcc/d/dmd/objc.c @@ -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. diff --git a/gcc/d/dmd/objc.h b/gcc/d/dmd/objc.h index 00d76e1..f3da5a3 100644 --- a/gcc/d/dmd/objc.h +++ b/gcc/d/dmd/objc.h @@ -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. diff --git a/gcc/d/dmd/opover.c b/gcc/d/dmd/opover.c index 66a0d23..0aff8b4 100644 --- a/gcc/d/dmd/opover.c +++ b/gcc/d/dmd/opover.c @@ -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); } } diff --git a/gcc/d/dmd/optimize.c b/gcc/d/dmd/optimize.c index 45d94df..44dedd8 100644 --- a/gcc/d/dmd/optimize.c +++ b/gcc/d/dmd/optimize.c @@ -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; diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c index bae3448..c050b05 100644 --- a/gcc/d/dmd/parse.c +++ b/gcc/d/dmd/parse.c @@ -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: diff --git a/gcc/d/dmd/parse.h b/gcc/d/dmd/parse.h index dae7b63..82ce325 100644 --- a/gcc/d/dmd/parse.h +++ b/gcc/d/dmd/parse.h @@ -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/root/aav.c b/gcc/d/dmd/root/aav.c index fd76d6d..992a117 100644 --- a/gcc/d/dmd/root/aav.c +++ b/gcc/d/dmd/root/aav.c @@ -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) diff --git a/gcc/d/dmd/root/aav.h b/gcc/d/dmd/root/aav.h index d08a3f87..c65b674 100644 --- a/gcc/d/dmd/root/aav.h +++ b/gcc/d/dmd/root/aav.h @@ -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) diff --git a/gcc/d/dmd/root/array.h b/gcc/d/dmd/root/array.h index 633414b..f7cb0c7 100644 --- a/gcc/d/dmd/root/array.h +++ b/gcc/d/dmd/root/array.h @@ -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. diff --git a/gcc/d/dmd/root/bitarray.h b/gcc/d/dmd/root/bitarray.h index 195e3be..004c43c 100644 --- a/gcc/d/dmd/root/bitarray.h +++ b/gcc/d/dmd/root/bitarray.h @@ -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. diff --git a/gcc/d/dmd/root/checkedint.c b/gcc/d/dmd/root/checkedint.c index ee10739..af7b56f 100644 --- a/gcc/d/dmd/root/checkedint.c +++ b/gcc/d/dmd/root/checkedint.c @@ -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 diff --git a/gcc/d/dmd/root/checkedint.h b/gcc/d/dmd/root/checkedint.h index 66e3b04..8a7d9c9 100644 --- a/gcc/d/dmd/root/checkedint.h +++ b/gcc/d/dmd/root/checkedint.h @@ -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. diff --git a/gcc/d/dmd/root/ctfloat.h b/gcc/d/dmd/root/ctfloat.h index 4cdf362..0a829f3 100644 --- a/gcc/d/dmd/root/ctfloat.h +++ b/gcc/d/dmd/root/ctfloat.h @@ -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 diff --git a/gcc/d/dmd/root/dcompat.h b/gcc/d/dmd/root/dcompat.h index 5aec84e..9fd176e 100644 --- a/gcc/d/dmd/root/dcompat.h +++ b/gcc/d/dmd/root/dcompat.h @@ -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. diff --git a/gcc/d/dmd/root/file.c b/gcc/d/dmd/root/file.c index 7fcadc5..314b5b5 100644 --- a/gcc/d/dmd/root/file.c +++ b/gcc/d/dmd/root/file.c @@ -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) diff --git a/gcc/d/dmd/root/file.h b/gcc/d/dmd/root/file.h index 348dce2..5135818 100644 --- a/gcc/d/dmd/root/file.h +++ b/gcc/d/dmd/root/file.h @@ -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 diff --git a/gcc/d/dmd/root/filename.c b/gcc/d/dmd/root/filename.c index f0e0213..0c5138b 100644 --- a/gcc/d/dmd/root/filename.c +++ b/gcc/d/dmd/root/filename.c @@ -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) diff --git a/gcc/d/dmd/root/filename.h b/gcc/d/dmd/root/filename.h index 6ef515c..52cd963 100644 --- a/gcc/d/dmd/root/filename.h +++ b/gcc/d/dmd/root/filename.h @@ -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 diff --git a/gcc/d/dmd/root/hash.h b/gcc/d/dmd/root/hash.h index 452ce30..6a32200 100644 --- a/gcc/d/dmd/root/hash.h +++ b/gcc/d/dmd/root/hash.h @@ -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) diff --git a/gcc/d/dmd/root/object.h b/gcc/d/dmd/root/object.h index 3e1532a..d5e3b2b 100644 --- a/gcc/d/dmd/root/object.h +++ b/gcc/d/dmd/root/object.h @@ -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) diff --git a/gcc/d/dmd/root/outbuffer.c b/gcc/d/dmd/root/outbuffer.c index 81c2e90..7fbbfe5 100644 --- a/gcc/d/dmd/root/outbuffer.c +++ b/gcc/d/dmd/root/outbuffer.c @@ -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) diff --git a/gcc/d/dmd/root/outbuffer.h b/gcc/d/dmd/root/outbuffer.h index da0d305..186fbb7 100644 --- a/gcc/d/dmd/root/outbuffer.h +++ b/gcc/d/dmd/root/outbuffer.h @@ -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 diff --git a/gcc/d/dmd/root/port.h b/gcc/d/dmd/root/port.h index b35da25..94651cd 100644 --- a/gcc/d/dmd/root/port.h +++ b/gcc/d/dmd/root/port.h @@ -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 diff --git a/gcc/d/dmd/root/rmem.c b/gcc/d/dmd/root/rmem.c index 09ea44d..768b75d 100644 --- a/gcc/d/dmd/root/rmem.c +++ b/gcc/d/dmd/root/rmem.c @@ -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) diff --git a/gcc/d/dmd/root/rmem.h b/gcc/d/dmd/root/rmem.h index fdb8676..1f603b8 100644 --- a/gcc/d/dmd/root/rmem.h +++ b/gcc/d/dmd/root/rmem.h @@ -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 diff --git a/gcc/d/dmd/root/root.h b/gcc/d/dmd/root/root.h index 274245a..d998d95 100644 --- a/gcc/d/dmd/root/root.h +++ b/gcc/d/dmd/root/root.h @@ -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 diff --git a/gcc/d/dmd/root/rootobject.c b/gcc/d/dmd/root/rootobject.c index 7cb2dc4..7fee0d7 100644 --- a/gcc/d/dmd/root/rootobject.c +++ b/gcc/d/dmd/root/rootobject.c @@ -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) diff --git a/gcc/d/dmd/root/speller.c b/gcc/d/dmd/root/speller.c index c2351e9..3957c11 100644 --- a/gcc/d/dmd/root/speller.c +++ b/gcc/d/dmd/root/speller.c @@ -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) diff --git a/gcc/d/dmd/root/speller.h b/gcc/d/dmd/root/speller.h index 6d70375..bd53fc4 100644 --- a/gcc/d/dmd/root/speller.h +++ b/gcc/d/dmd/root/speller.h @@ -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) diff --git a/gcc/d/dmd/root/stringtable.c b/gcc/d/dmd/root/stringtable.c index 15e5a02..fe14807 100644 --- a/gcc/d/dmd/root/stringtable.c +++ b/gcc/d/dmd/root/stringtable.c @@ -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) diff --git a/gcc/d/dmd/root/stringtable.h b/gcc/d/dmd/root/stringtable.h index 8cbdbd8..51304d3 100644 --- a/gcc/d/dmd/root/stringtable.h +++ b/gcc/d/dmd/root/stringtable.h @@ -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 diff --git a/gcc/d/dmd/safe.c b/gcc/d/dmd/safe.c index 08274af..7d83dd1 100644 --- a/gcc/d/dmd/safe.c +++ b/gcc/d/dmd/safe.c @@ -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/sapply.c b/gcc/d/dmd/sapply.c index 35e38c1..ce08926 100644 --- a/gcc/d/dmd/sapply.c +++ b/gcc/d/dmd/sapply.c @@ -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/scope.h b/gcc/d/dmd/scope.h index 7e1b634..ea3bf38 100644 --- a/gcc/d/dmd/scope.h +++ b/gcc/d/dmd/scope.h @@ -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 index 0000000..7bcf6ce --- /dev/null +++ b/gcc/d/dmd/semantic2.c @@ -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 index 0000000..304eaee --- /dev/null +++ b/gcc/d/dmd/semantic3.c @@ -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); +} diff --git a/gcc/d/dmd/sideeffect.c b/gcc/d/dmd/sideeffect.c index efab276..661bd43 100644 --- a/gcc/d/dmd/sideeffect.c +++ b/gcc/d/dmd/sideeffect.c @@ -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; diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c index 76dfe1d..2f7b7e1 100644 --- a/gcc/d/dmd/statement.c +++ b/gcc/d/dmd/statement.c @@ -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; } diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h index 08eb5fd..2d8b46c 100644 --- a/gcc/d/dmd/statement.h +++ b/gcc/d/dmd/statement.h @@ -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 index 0000000..28a930a --- /dev/null +++ b/gcc/d/dmd/statement_rewrite_walker.h @@ -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 *) { } +}; + diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c index 2fe0d9e..5579c1c 100644 --- a/gcc/d/dmd/statementsem.c +++ b/gcc/d/dmd/statementsem.c @@ -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; } diff --git a/gcc/d/dmd/staticassert.c b/gcc/d/dmd/staticassert.c index 57181cd..c2d0f5b 100644 --- a/gcc/d/dmd/staticassert.c +++ b/gcc/d/dmd/staticassert.c @@ -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"); diff --git a/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h index 4491322..6d43cb7 100644 --- a/gcc/d/dmd/staticassert.h +++ b/gcc/d/dmd/staticassert.h @@ -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); } diff --git a/gcc/d/dmd/staticcond.c b/gcc/d/dmd/staticcond.c index 48a60d3..ef0a35f 100644 --- a/gcc/d/dmd/staticcond.c +++ b/gcc/d/dmd/staticcond.c @@ -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(); diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h index 5a2dd4d..a91880f 100644 --- a/gcc/d/dmd/target.h +++ b/gcc/d/dmd/target.h @@ -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. diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h index 0a5bc79..dac1e85 100644 --- a/gcc/d/dmd/template.h +++ b/gcc/d/dmd/template.h @@ -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 index 0000000..11cd52e --- /dev/null +++ b/gcc/d/dmd/templateparamsem.c @@ -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; +} diff --git a/gcc/d/dmd/tokens.c b/gcc/d/dmd/tokens.c index 9db1e33..eb06bee 100644 --- a/gcc/d/dmd/tokens.c +++ b/gcc/d/dmd/tokens.c @@ -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/tokens.h b/gcc/d/dmd/tokens.h index 82dcaa2..f79d841 100644 --- a/gcc/d/dmd/tokens.h +++ b/gcc/d/dmd/tokens.h @@ -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/traits.c b/gcc/d/dmd/traits.c index 70f7f2c..b7c612c 100644 --- a/gcc/d/dmd/traits.c +++ b/gcc/d/dmd/traits.c @@ -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); diff --git a/gcc/d/dmd/typesem.c b/gcc/d/dmd/typesem.c index 2933e98..496cfe3 100644 --- a/gcc/d/dmd/typesem.c +++ b/gcc/d/dmd/typesem.c @@ -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; +} diff --git a/gcc/d/dmd/utf.c b/gcc/d/dmd/utf.c index c497f96..f6b5435 100644 --- a/gcc/d/dmd/utf.c +++ b/gcc/d/dmd/utf.c @@ -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. diff --git a/gcc/d/dmd/utf.h b/gcc/d/dmd/utf.h index 52a731f..b3782af 100644 --- a/gcc/d/dmd/utf.h +++ b/gcc/d/dmd/utf.h @@ -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. diff --git a/gcc/d/dmd/utils.c b/gcc/d/dmd/utils.c index 73de2e4..c9e6322 100644 --- a/gcc/d/dmd/utils.c +++ b/gcc/d/dmd/utils.c @@ -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/version.h b/gcc/d/dmd/version.h index 36c9ef7..9e7fd5e 100644 --- a/gcc/d/dmd/version.h +++ b/gcc/d/dmd/version.h @@ -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); } }; diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h index 5f2bf2c..a274e6f 100644 --- a/gcc/d/dmd/visitor.h +++ b/gcc/d/dmd/visitor.h @@ -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 diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc index ec8539d..698e766 100644 --- a/gcc/d/typeinfo.cc +++ b/gcc/d/typeinfo.cc @@ -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. */ |