From: Iain Buclaw Date: Tue, 9 Feb 2021 14:40:06 +0000 (+0100) Subject: d: Merge upstream dmd 7132b3537 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a3b38b7781622babb5ca68c621367770a65012fa;p=gcc.git d: Merge upstream dmd 7132b3537 Splits out all semantic passes for Dsymbol, Type, and TemplateParameter nodes into Visitors in separate files, and the copyright years of all sources have been updated. Reviewed-on: https://github.com/dlang/dmd/pull/12190 gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 7132b3537. * Make-lang.in (D_FRONTEND_OBJS): Add d/dsymbolsem.o, d/semantic2.o, d/semantic3.o, and d/templateparamsem.o. * d-compiler.cc (Compiler::genCmain): Update calls to semantic entrypoint functions. * d-lang.cc (d_parse_file): Likewise. * typeinfo.cc (make_frontend_typeinfo): Likewise. --- diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in index 2b3c936a3fa..b0fce06e507 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 3907d010684..512ef4bab3e 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 0fd207da7f3..1a51c5e4b7c 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 89397c836e2..690fe407278 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 63f46c60f63..11b26c5dc5c 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 6cfc76d8c6c..4935e6a1f5d 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 9da64d042eb..458416f4950 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 816a4ee8f79..15905e41710 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 6f3301ed1df..8a727ae66d1 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 20cdb6fd184..52d596bb871 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 627464a635f..0ecccf170bd 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 09519af0e99..5576dd74e0d 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 5445b9e5968..56b8ce816be 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 a20e96bc929..74364176128 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 4705862e025..44e3cc13bd3 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 33d61edbcc8..5d180f54367 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 73c4a660368..eb09076b2d2 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 7f9006ce851..e7ef5a4ccf7 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 c36c4ec53cf..7f174606422 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 2ea3d408155..6f112ad909c 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 17398c1ef78..593a98d10b4 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 38e6191698d..8cfeac54e20 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 3f571fcb14b..a0e0b5fb993 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 1eab264f5ce..359739e24a0 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 ee38033ac82..1d669e595e5 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 1fc9d936bbd..61e28fe8d13 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 7481f910e11..c7dbbbea5d3 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 d20f6636445..a9394dcce7f 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 6a3ec9e7d5c..81b563f4b0f 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 3aec39372c1..b3019aae4b8 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 d15d94a3157..ca1d3bb771c 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 4b969d4dd60..0d93ed80e58 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 f868790f9e7..5e71f3b24a1 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 cefd3b037aa..91cbe50713c 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 4a9a118ebba..303ae617874 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 95c263fc425..a2b01f534eb 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 92783b89ab3..5d2da1ccdb9 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 c06ffe6c3a0..6d13ab1c121 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 72dc0893af5..65e6734b035 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 8829367dab4..40c67ceb084 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 293484cae60..89c55576a55 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 6555f12e7b4..1ddfe06e6a1 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 00000000000..5d5c9fca769 --- /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 316f105b9e3..b868e9ad388 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 f88fca561c5..269d92466cd 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 50067637b13..cac901d1a6e 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 6d389ed76e0..ae5ea214a73 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 165da693ca0..a92ae2abbc4 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 b3fccd9ef46..cd0382b0a22 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 3314d0c096c..c90392d16a2 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(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(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(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(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 15a4d8770c6..f0ae2805df4 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 7cebd9a3023..7cccd956966 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(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(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 2f1d648bf35..7a216a97941 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,2019 +183,166 @@ static bool allowsContractWithoutBody(FuncDeclaration *funcdecl) return true; } -// Do the semantic analysis on the external interface to the function. - -void FuncDeclaration::semantic(Scope *sc) +/**************************************************** + * Determine whether an 'out' contract is declared inside + * the given function or any of its overrides. + * Params: + * fd = the function to search + * Returns: + * true found an 'out' contract + * false didn't find one + */ +bool FuncDeclaration::needsFensure(FuncDeclaration *fd) { - TypeFunction *f; - AggregateDeclaration *ad; - InterfaceDeclaration *id; - - if (semanticRun != PASSinit && isFuncLiteralDeclaration()) - { - /* Member functions that have return types that are - * forward references can have semantic() run more than - * once on them. - * See test\interface2.d, test20 - */ - return; - } - - if (semanticRun >= PASSsemanticdone) - return; - assert(semanticRun <= PASSsemantic); - semanticRun = PASSsemantic; - - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - if (!sc || errors) - return; - - parent = sc->parent; - Dsymbol *parent = toParent(); - - foverrides.setDim(0); // reset in case semantic() is being retried for this function - - storage_class |= sc->stc & ~STCref; - ad = isThis(); - // Don't nest structs b/c of generated methods which should not access the outer scopes. - // https://issues.dlang.org/show_bug.cgi?id=16627 - if (ad && !generated) - { - storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized); - ad->makeNested(); - } - if (sc->func) - storage_class |= sc->func->storage_class & STCdisable; - // Remove prefix storage classes silently. - if ((storage_class & STC_TYPECTOR) && !(ad || isNested())) - storage_class &= ~STC_TYPECTOR; - - //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal()); - - FuncLiteralDeclaration *fld = isFuncLiteralDeclaration(); - if (fld && fld->treq) - { - Type *treq = fld->treq; - assert(treq->nextOf()->ty == Tfunction); - if (treq->ty == Tdelegate) - fld->tok = TOKdelegate; - else if (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction) - fld->tok = TOKfunction; - else - assert(0); - linkage = treq->nextOf()->toTypeFunction()->linkage; - } - else - linkage = sc->linkage; - inlining = sc->inlining; - protection = sc->protection; - userAttribDecl = sc->userAttribDecl; - - if (!originalType) - originalType = type->syntaxCopy(); - if (type->ty != Tfunction) - { - if (type->ty != Terror) - { - error("%s must be a function instead of %s", toChars(), type->toChars()); - type = Type::terror; - } - errors = true; - return; - } - if (!type->deco) - { - sc = sc->push(); - sc->stc |= storage_class & (STCdisable | STCdeprecated); // forward to function type - TypeFunction *tf = type->toTypeFunction(); - - if (sc->func) - { - /* If the nesting parent is pure without inference, - * then this function defaults to pure too. - * - * auto foo() pure { - * auto bar() {} // become a weak purity funciton - * class C { // nested class - * auto baz() {} // become a weak purity funciton - * } - * - * static auto boo() {} // typed as impure - * // Even though, boo cannot call any impure functions. - * // See also Expression::checkPurity(). - * } - */ - if (tf->purity == PUREimpure && (isNested() || isThis())) - { - FuncDeclaration *fd = NULL; - for (Dsymbol *p = toParent2(); p; p = p->toParent2()) - { - if (AggregateDeclaration *adx = p->isAggregateDeclaration()) - { - if (adx->isNested()) - continue; - break; - } - if ((fd = p->isFuncDeclaration()) != NULL) - break; - } - - /* If the parent's purity is inferred, then this function's purity needs - * to be inferred first. - */ - if (fd && fd->isPureBypassingInference() >= PUREweak && - !isInstantiated()) - { - tf->purity = PUREfwdref; // default to pure - } - } - } - - if (tf->isref) sc->stc |= STCref; - if (tf->isscope) sc->stc |= STCscope; - if (tf->isnothrow) sc->stc |= STCnothrow; - if (tf->isnogc) sc->stc |= STCnogc; - if (tf->isproperty) sc->stc |= STCproperty; - if (tf->purity == PUREfwdref) sc->stc |= STCpure; - if (tf->trust != TRUSTdefault) - sc->stc &= ~(STCsafe | STCsystem | STCtrusted); - if (tf->trust == TRUSTsafe) sc->stc |= STCsafe; - if (tf->trust == TRUSTsystem) sc->stc |= STCsystem; - if (tf->trust == TRUSTtrusted) sc->stc |= STCtrusted; - - if (isCtorDeclaration()) - { - sc->flags |= SCOPEctor; - - Type *tret = ad->handleType(); - assert(tret); - tret = tret->addStorageClass(storage_class | sc->stc); - tret = tret->addMod(type->mod); - tf->next = tret; - - if (ad->isStructDeclaration()) - sc->stc |= STCref; - } - - // 'return' on a non-static class member function implies 'scope' as well - if (ad && ad->isClassDeclaration() && (tf->isreturn || sc->stc & STCreturn) && !(sc->stc & STCstatic)) - sc->stc |= STCscope; - - // If 'this' has no pointers, remove 'scope' as it has no meaning - if (sc->stc & STCscope && ad && ad->isStructDeclaration() && !ad->type->hasPointers()) - { - sc->stc &= ~STCscope; - tf->isscope = false; - } - - sc->linkage = linkage; - - if (!tf->isNaked() && !(isThis() || isNested())) - { - OutBuffer buf; - MODtoBuffer(&buf, tf->mod); - error("without 'this' cannot be %s", buf.peekChars()); - tf->mod = 0; // remove qualifiers - } - - /* Apply const, immutable, wild and shared storage class - * to the function type. Do this before type semantic. - */ - StorageClass stc = storage_class; - if (type->isImmutable()) - stc |= STCimmutable; - if (type->isConst()) - stc |= STCconst; - if (type->isShared() || storage_class & STCsynchronized) - stc |= STCshared; - if (type->isWild()) - stc |= STCwild; - switch (stc & STC_TYPECTOR) - { - case STCimmutable: - case STCimmutable | STCconst: - case STCimmutable | STCwild: - case STCimmutable | STCwild | STCconst: - case STCimmutable | STCshared: - case STCimmutable | STCshared | STCconst: - case STCimmutable | STCshared | STCwild: - case STCimmutable | STCshared | STCwild | STCconst: - // Don't use immutableOf(), as that will do a merge() - type = type->makeImmutable(); - break; - - case STCconst: - type = type->makeConst(); - break; - - case STCwild: - type = type->makeWild(); - break; - - case STCwild | STCconst: - type = type->makeWildConst(); - break; - - case STCshared: - type = type->makeShared(); - break; - - case STCshared | STCconst: - type = type->makeSharedConst(); - break; - - case STCshared | STCwild: - type = type->makeSharedWild(); - break; - - case STCshared | STCwild | STCconst: - type = type->makeSharedWildConst(); - break; - - case 0: - break; - - default: - assert(0); - } + if (fd->fensures) + return true; - type = type->semantic(loc, sc); - sc = sc->pop(); - } - if (type->ty != Tfunction) - { - if (type->ty != Terror) - { - error("%s must be a function instead of %s", toChars(), type->toChars()); - type = Type::terror; - } - errors = true; - return; - } - else + for (size_t i = 0; i < fd->foverrides.length; i++) { - // Merge back function attributes into 'originalType'. - // It's used for mangling, ddoc, and json output. - TypeFunction *tfo = originalType->toTypeFunction(); - TypeFunction *tfx = type->toTypeFunction(); - tfo->mod = tfx->mod; - tfo->isscope = tfx->isscope; - tfo->isscopeinferred = tfx->isscopeinferred; - tfo->isref = tfx->isref; - tfo->isnothrow = tfx->isnothrow; - tfo->isnogc = tfx->isnogc; - tfo->isproperty = tfx->isproperty; - tfo->purity = tfx->purity; - tfo->trust = tfx->trust; - - storage_class &= ~(STC_TYPECTOR | STC_FUNCATTR); - } - - f = (TypeFunction *)type; + FuncDeclaration *fdv = fd->foverrides[i]; - if ((storage_class & STCauto) && !f->isref && !inferRetType) - error("storage class 'auto' has no effect if return type is not inferred"); - /* Functions can only be 'scope' if they have a 'this' - */ - if (f->isscope && !isNested() && !ad) - { - error("functions cannot be scope"); - } + if (fdv->fensure) + return true; - if (f->isreturn && !needThis() && !isNested()) - { - /* Non-static nested functions have a hidden 'this' pointer to which - * the 'return' applies - */ - error("static member has no 'this' to which 'return' can apply"); + if (needsFensure(fdv)) + return true; } + return false; +} - if (isAbstract() && !isVirtual()) - { - const char *sfunc; - if (isStatic()) - sfunc = "static"; - else if (protection.kind == Prot::private_ || protection.kind == Prot::package_) - sfunc = protectionToChars(protection.kind); - else - sfunc = "non-virtual"; - error("%s functions cannot be abstract", sfunc); - } +/**************************************************** + * Check whether result variable can be built. + * Returns: + * `true` if the function has a return type that + * is different from `void`. + */ +static bool canBuildResultVar(FuncDeclaration *fd) +{ + TypeFunction *f = (TypeFunction *)fd->type; + return f && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid; +} - if (isOverride() && !isVirtual()) - { - Prot::Kind kind = prot().kind; - if ((kind == Prot::private_ || kind == Prot::package_) && isMember()) - error("%s method is not virtual and cannot override", protectionToChars(kind)); - else - error("cannot override a non-virtual function"); - } - - if (isAbstract() && isFinalFunc()) - error("cannot be both final and abstract"); - - id = parent->isInterfaceDeclaration(); - if (id) - { - storage_class |= STCabstract; - - if (isCtorDeclaration() || - isPostBlitDeclaration() || - isDtorDeclaration() || - isInvariantDeclaration() || - isNewDeclaration() || isDelete()) - error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface %s", id->toChars()); - if (fbody && isVirtual()) - error("function body only allowed in final functions in interface %s", id->toChars()); - } - - if (UnionDeclaration *ud = parent->isUnionDeclaration()) - { - if (isPostBlitDeclaration() || - isDtorDeclaration() || - isInvariantDeclaration()) - error("destructors, postblits and invariants are not allowed in union %s", ud->toChars()); - } - - if (parent->isStructDeclaration()) - { - if (isCtorDeclaration()) - { - goto Ldone; - } - } - - if (ClassDeclaration *cd = parent->isClassDeclaration()) - { - if (isCtorDeclaration()) - { - goto Ldone; - } - - if (storage_class & STCabstract) - cd->isabstract = ABSyes; - - // if static function, do not put in vtbl[] - if (!isVirtual()) - { - //printf("\tnot virtual\n"); - goto Ldone; - } - // Suppress further errors if the return type is an error - if (type->nextOf() == Type::terror) - goto Ldone; - - bool may_override = false; - for (size_t i = 0; i < cd->baseclasses->length; i++) - { - BaseClass *b = (*cd->baseclasses)[i]; - ClassDeclaration *cbd = b->type->toBasetype()->isClassHandle(); - if (!cbd) - continue; - for (size_t j = 0; j < cbd->vtbl.length; j++) - { - FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration(); - if (!f2 || f2->ident != ident) - continue; - if (cbd->parent && cbd->parent->isTemplateInstance()) - { - if (!f2->functionSemantic()) - goto Ldone; - } - may_override = true; - } - } - if (may_override && type->nextOf() == NULL) - { - /* If same name function exists in base class but 'this' is auto return, - * cannot find index of base class's vtbl[] to override. - */ - error("return type inference is not supported if may override base class function"); - } - - /* Find index of existing function in base class's vtbl[] to override - * (the index will be the same as in cd's current vtbl[]) - */ - int vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.length) - : -1; - - bool doesoverride = false; - switch (vi) - { - case -1: - Lintro: - /* Didn't find one, so - * This is an 'introducing' function which gets a new - * slot in the vtbl[]. - */ - - // Verify this doesn't override previous final function - if (cd->baseClass) - { - Dsymbol *s = cd->baseClass->search(loc, ident); - if (s) - { - FuncDeclaration *f2 = s->isFuncDeclaration(); - if (f2) - { - f2 = f2->overloadExactMatch(type); - if (f2 && f2->isFinalFunc() && f2->prot().kind != Prot::private_) - error("cannot override final function %s", f2->toPrettyChars()); - } - } - } - - /* These quirky conditions mimic what VC++ appears to do - */ - if (global.params.mscoff && cd->isCPPclass() && - cd->baseClass && cd->baseClass->vtbl.length) - { - /* if overriding an interface function, then this is not - * introducing and don't put it in the class vtbl[] - */ - interfaceVirtual = overrideInterface(); - if (interfaceVirtual) - { - //printf("\tinterface function %s\n", toChars()); - cd->vtblFinal.push(this); - goto Linterfaces; - } - } - - if (isFinalFunc()) - { - // Don't check here, as it may override an interface function - //if (isOverride()) - //error("is marked as override, but does not override any function"); - cd->vtblFinal.push(this); - } - else - { - //printf("\tintroducing function %s\n", toChars()); - introducing = 1; - if (cd->isCPPclass() && target.cpp.reverseOverloads) - { - // with dmc, overloaded functions are grouped and in reverse order - vtblIndex = (int)cd->vtbl.length; - for (int i = 0; i < (int)cd->vtbl.length; i++) - { - if (cd->vtbl[i]->ident == ident && cd->vtbl[i]->parent == parent) - { - vtblIndex = (int)i; - break; - } - } - // shift all existing functions back - for (int i = (int)cd->vtbl.length; i > vtblIndex; i--) - { - FuncDeclaration *fd = cd->vtbl[i-1]->isFuncDeclaration(); - assert(fd); - fd->vtblIndex++; - } - cd->vtbl.insert(vtblIndex, this); - } - else - { - // Append to end of vtbl[] - vi = (int)cd->vtbl.length; - cd->vtbl.push(this); - vtblIndex = vi; - } - } - break; - - case -2: - // can't determine because of forward references - errors = true; - return; - - default: - { - FuncDeclaration *fdv = cd->baseClass->vtbl[vi]->isFuncDeclaration(); - FuncDeclaration *fdc = cd->vtbl[vi]->isFuncDeclaration(); - // This function is covariant with fdv - - if (fdc == this) - { - doesoverride = true; - break; - } - - if (fdc->toParent() == parent) - { - //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n", - // vi, this, this->toChars(), this->type->toChars(), this->loc.toChars(), - // fdc, fdc ->toChars(), fdc ->type->toChars(), fdc ->loc.toChars(), - // fdv, fdv ->toChars(), fdv ->type->toChars(), fdv ->loc.toChars()); - - // fdc overrides fdv exactly, then this introduces new function. - if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod) - goto Lintro; - } - - // This function overrides fdv - if (fdv->isFinalFunc()) - error("cannot override final function %s", fdv->toPrettyChars()); - - if (!isOverride()) - { - if (fdv->isFuture()) - { - ::deprecation(loc, "@__future base class method %s is being overridden by %s; rename the latter", - fdv->toPrettyChars(), toPrettyChars()); - // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[] - goto Lintro; - } - else - { - int vi2 = findVtblIndex(&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.length, false); - if (vi2 < 0) - // https://issues.dlang.org/show_bug.cgi?id=17349 - ::deprecation(loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute", - fdv->toPrettyChars(), toPrettyChars()); - else - ::error(loc, "implicitly overriding base class method %s with %s deprecated; add 'override' attribute", - fdv->toPrettyChars(), toPrettyChars()); - } - } - - doesoverride = true; - if (fdc->toParent() == parent) - { - // If both are mixins, or both are not, then error. - // If either is not, the one that is not overrides the other. - bool thismixin = this->parent->isClassDeclaration() != NULL; - bool fdcmixin = fdc->parent->isClassDeclaration() != NULL; - if (thismixin == fdcmixin) - { - error("multiple overrides of same function"); - } - else if (!thismixin) // fdc overrides fdv - { - // this doesn't override any function - break; - } - } - cd->vtbl[vi] = this; - vtblIndex = vi; - - /* Remember which functions this overrides - */ - foverrides.push(fdv); - - /* This works by whenever this function is called, - * it actually returns tintro, which gets dynamically - * cast to type. But we know that tintro is a base - * of type, so we could optimize it by not doing a - * dynamic cast, but just subtracting the isBaseOf() - * offset if the value is != null. - */ - - if (fdv->tintro) - tintro = fdv->tintro; - else if (!type->equals(fdv->type)) - { - /* Only need to have a tintro if the vptr - * offsets differ - */ - int offset; - if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset)) - { - tintro = fdv->type; - } - } - break; - } - } - - /* Go through all the interface bases. - * If this function is covariant with any members of those interface - * functions, set the tintro. - */ - Linterfaces: - for (size_t i = 0; i < cd->interfaces.length; i++) - { - BaseClass *b = cd->interfaces.ptr[i]; - vi = findVtblIndex((Dsymbols *)&b->sym->vtbl, (int)b->sym->vtbl.length); - switch (vi) - { - case -1: - break; - - case -2: - // can't determine because of forward references - errors = true; - return; - - default: - { - FuncDeclaration *fdv = (FuncDeclaration *)b->sym->vtbl[vi]; - Type *ti = NULL; - - /* Remember which functions this overrides - */ - foverrides.push(fdv); - - /* Should we really require 'override' when implementing - * an interface function? - */ - //if (!isOverride()) - //warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); - - if (fdv->tintro) - ti = fdv->tintro; - else if (!type->equals(fdv->type)) - { - /* Only need to have a tintro if the vptr - * offsets differ - */ - int offset; - if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset)) - { - ti = fdv->type; - } - } - if (ti) - { - if (tintro) - { - if (!tintro->nextOf()->equals(ti->nextOf()) && - !tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) && - !ti->nextOf()->isBaseOf(tintro->nextOf(), NULL)) - { - error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars()); - } - } - tintro = ti; - } - goto L2; - } - } - } - - if (!doesoverride && isOverride() && (type->nextOf() || !may_override)) - { - BaseClass *bc = NULL; - Dsymbol *s = NULL; - for (size_t i = 0; i < cd->baseclasses->length; i++) - { - bc = (*cd->baseclasses)[i]; - s = bc->sym->search_correct(ident); - if (s) break; - } - - if (s) - error("does not override any function, did you mean to override '%s%s'?", - bc->sym->isCPPclass() ? "extern (C++) " : "", s->toPrettyChars()); - else - error("does not override any function"); - } - - L2: ; - - /* Go through all the interface bases. - * Disallow overriding any final functions in the interface(s). - */ - for (size_t i = 0; i < cd->interfaces.length; i++) - { - BaseClass *b = cd->interfaces.ptr[i]; - if (b->sym) - { - Dsymbol *s = search_function(b->sym, ident); - if (s) - { - FuncDeclaration *f2 = s->isFuncDeclaration(); - if (f2) - { - f2 = f2->overloadExactMatch(type); - if (f2 && f2->isFinalFunc() && f2->prot().kind != Prot::private_) - error("cannot override final function %s.%s", b->sym->toChars(), f2->toPrettyChars()); - } - } - } - } - - if (isOverride()) - { - if (storage_class & STCdisable) - deprecation("overridden functions cannot be annotated @disable"); - if (isDeprecated()) - deprecation("deprecated functions cannot be annotated @disable"); - } - } - else if (isOverride() && !parent->isTemplateInstance()) - error("override only applies to class member functions"); - - // Reflect this->type to f because it could be changed by findVtblIndex - f = type->toTypeFunction(); - -Ldone: - /* Contracts can only appear without a body when they are virtual interface functions - */ - if (!fbody && !allowsContractWithoutBody(this)) - error("in and out contracts can only appear without a body when they are virtual interface functions or abstract"); - - /* Do not allow template instances to add virtual functions - * to a class. - */ - if (isVirtual()) - { - TemplateInstance *ti = parent->isTemplateInstance(); - if (ti) - { - // Take care of nested templates - while (1) - { - TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); - if (!ti2) - break; - ti = ti2; - } - - // If it's a member template - ClassDeclaration *cd = ti->tempdecl->isClassMember(); - if (cd) - { - error("cannot use template to add virtual function to class '%s'", cd->toChars()); - } - } - } - - if (isMain()) - checkDmain(); // Check main() parameters and return type - - /* Purity and safety can be inferred for some functions by examining - * the function body. - */ - if (canInferAttributes(this, sc)) - initInferAttributes(this); - - Module::dprogress++; - semanticRun = PASSsemanticdone; - - /* Save scope for possible later use (if we need the - * function internals) - */ - _scope = sc->copy(); - _scope->setNoFree(); - - static bool printedMain = false; // semantic might run more than once - if (global.params.verbose && !printedMain) - { - const char *type = isMain() ? "main" : isWinMain() ? "winmain" : isDllMain() ? "dllmain" : (const char *)NULL; - Module *mod = sc->_module; - - if (type && mod) - { - printedMain = true; - const char *name = mod->srcfile->toChars(); - const char *path = FileName::searchPath(global.path, name, true); - message("entry %-10s\t%s", type, path ? path : name); - } - } - - if (fbody && isMain() && sc->_module->isRoot()) - Compiler::genCmain(sc); - - assert(type->ty != Terror || errors); - - // semantic for parameters' UDAs - const size_t nparams = f->parameterList.length(); - for (size_t i = 0; i < nparams; i++) - { - Parameter *param = f->parameterList[i]; - if (param && param->userAttribDecl) - param->userAttribDecl->semantic(sc); - } -} - -void FuncDeclaration::semantic2(Scope *sc) -{ - if (semanticRun >= PASSsemantic2done) - return; - assert(semanticRun <= PASSsemantic2); - semanticRun = PASSsemantic2; - - objc()->setSelector(this, sc); - objc()->validateSelector(this); - - if (parent->isClassDeclaration()) - { - objc()->checkLinkage(this); - } - if (!type || type->ty != Tfunction) - return; - TypeFunction *f = type->toTypeFunction(); - const size_t nparams = f->parameterList.length(); - // semantic for parameters' UDAs - for (size_t i = 0; i < nparams; i++) - { - Parameter *param = f->parameterList[i]; - if (param && param->userAttribDecl) - param->userAttribDecl->semantic2(sc); - } -} - -/**************************************************** - * Determine whether an 'out' contract is declared inside - * the given function or any of its overrides. - * Params: - * fd = the function to search - * Returns: - * true found an 'out' contract - * false didn't find one - */ -static bool needsFensure(FuncDeclaration *fd) -{ - if (fd->fensures) - return true; - - for (size_t i = 0; i < fd->foverrides.length; i++) - { - FuncDeclaration *fdv = fd->foverrides[i]; - - if (fdv->fensure) - return true; - - if (needsFensure(fdv)) - return true; - } - return false; -} - -/**************************************************** - * Check whether result variable can be built. - * Returns: - * `true` if the function has a return type that - * is different from `void`. - */ -static bool canBuildResultVar(FuncDeclaration *fd) -{ - TypeFunction *f = (TypeFunction *)fd->type; - return f && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid; -} - -/**************************************************** - * Rewrite contracts as statements. - * Params: - * fdx = the function to rewrite contracts for - */ -static void buildEnsureRequire(FuncDeclaration *fdx) -{ - if (fdx->frequires) +/**************************************************** + * Rewrite contracts as statements. + */ +void FuncDeclaration::buildEnsureRequire() +{ + if (frequires) { /* in { statements1... } * in { statements2... } * ... * becomes: - * in { { statements1... } { statements2... } ... } - */ - assert(fdx->frequires->length); - Loc loc = (*fdx->frequires)[0]->loc; - Statements *s = new Statements; - for (size_t i = 0; i < fdx->frequires->length; i++) - { - Statement *r = (*fdx->frequires)[i]; - s->push(new ScopeStatement(r->loc, r, r->loc)); - } - fdx->frequire = new CompoundStatement(loc, s); - } - - if (fdx->fensures) - { - /* out(id1) { statements1... } - * out(id2) { statements2... } - * ... - * becomes: - * out(__result) { { ref id1 = __result; { statements1... } } - * { ref id2 = __result; { statements2... } } ... } - */ - assert(fdx->fensures->length); - Loc loc = (*fdx->fensures)[0].ensure->loc; - Statements *s = new Statements; - for (size_t i = 0; i < fdx->fensures->length; i++) - { - Ensure r = (*fdx->fensures)[i]; - if (r.id && canBuildResultVar(fdx)) - { - Loc rloc = r.ensure->loc; - IdentifierExp *resultId = new IdentifierExp(rloc, Id::result); - ExpInitializer *init = new ExpInitializer(rloc, resultId); - StorageClass stc = STCref | STCtemp | STCresult; - VarDeclaration *decl = new VarDeclaration(rloc, NULL, r.id, init); - decl->storage_class = stc; - ExpStatement *sdecl = new ExpStatement(rloc, decl); - s->push(new ScopeStatement(rloc, new CompoundStatement(rloc, sdecl, r.ensure), rloc)); - } - else - { - s->push(r.ensure); - } - } - fdx->fensure = new CompoundStatement(loc, s); - } - - if (!fdx->isVirtual()) - return; - - /* Rewrite contracts as nested functions, then call them. Doing it as nested - * functions means that overriding functions can call them. - */ - TypeFunction *f = (TypeFunction *)fdx->type; - - if (fdx->frequire) - { - /* in { ... } - * becomes: - * void __require() { ... } - * __require(); - */ - Loc loc = fdx->frequire->loc; - TypeFunction *tf = new TypeFunction(ParameterList(), Type::tvoid, LINKd); - tf->isnothrow = f->isnothrow; - tf->isnogc = f->isnogc; - tf->purity = f->purity; - tf->trust = f->trust; - FuncDeclaration *fd = new FuncDeclaration(loc, loc, - Id::require, STCundefined, tf); - fd->fbody = fdx->frequire; - Statement *s1 = new ExpStatement(loc, fd); - Expression *e = new CallExp(loc, new VarExp(loc, fd, false), (Expressions *)NULL); - Statement *s2 = new ExpStatement(loc, e); - fdx->frequire = new CompoundStatement(loc, s1, s2); - fdx->fdrequire = fd; - } - - if (fdx->fensure) - { - /* out (result) { ... } - * becomes: - * void __ensure(ref tret result) { ... } - * __ensure(result); - */ - Loc loc = fdx->fensure->loc; - Parameters *fparams = new Parameters(); - Parameter *p = NULL; - if (canBuildResultVar(fdx)) - { - p = new Parameter(STCref | STCconst, f->nextOf(), Id::result, NULL, NULL); - fparams->push(p); - } - TypeFunction *tf = new TypeFunction(ParameterList(fparams), Type::tvoid, LINKd); - tf->isnothrow = f->isnothrow; - tf->isnogc = f->isnogc; - tf->purity = f->purity; - tf->trust = f->trust; - FuncDeclaration *fd = new FuncDeclaration(loc, loc, - Id::ensure, STCundefined, tf); - fd->fbody = fdx->fensure; - Statement *s1 = new ExpStatement(loc, fd); - Expression *eresult = NULL; - if (canBuildResultVar(fdx)) - eresult = new IdentifierExp(loc, Id::result); - Expression *e = new CallExp(loc, new VarExp(loc, fd, false), eresult); - Statement *s2 = new ExpStatement(loc, e); - fdx->fensure = new CompoundStatement(loc, s1, s2); - fdx->fdensure = fd; - } -} - -/* Determine if function should add `return 0;` - */ -static bool addReturn0(FuncDeclaration *funcdecl) -{ - TypeFunction *f = (TypeFunction *)funcdecl->type; - - return f->next->ty == Tvoid && - (funcdecl->isMain() || (global.params.betterC && funcdecl->isCMain())); -} - -// Do the semantic analysis on the internals of the function. - -void FuncDeclaration::semantic3(Scope *sc) -{ - VarDeclaration *_arguments = NULL; - - if (!parent) - { - if (global.errors) - return; - //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); - assert(0); - } - if (errors || isError(parent)) - { - errors = true; - return; - } - //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars()); - //fflush(stdout); - //printf("storage class = x%x %x\n", sc->stc, storage_class); - //{ static int x; if (++x == 2) *(char*)0=0; } - //printf("\tlinkage = %d\n", sc->linkage); - - if (ident == Id::assign && !inuse) - { - if (storage_class & STCinference) - { - /* Bugzilla 15044: For generated opAssign function, any errors - * from its body need to be gagged. - */ - unsigned oldErrors = global.startGagging(); - ++inuse; - semantic3(sc); - --inuse; - if (global.endGagging(oldErrors)) // if errors happened - { - // Disable generated opAssign, because some members forbid identity assignment. - storage_class |= STCdisable; - fbody = NULL; // remove fbody which contains the error - semantic3Errors = false; - } - return; - } - } - - //printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract)); - if (semanticRun >= PASSsemantic3) - return; - semanticRun = PASSsemantic3; - semantic3Errors = false; - - if (!type || type->ty != Tfunction) - return; - TypeFunction *f = (TypeFunction *)type; - if (!inferRetType && f->next->ty == Terror) - return; - - if (!fbody && inferRetType && !f->next) - { - error("has no function body with return type inference"); - return; - } - - unsigned oldErrors = global.errors; - - if (frequires) - { - for (size_t i = 0; i < foverrides.length; i++) - { - FuncDeclaration *fdv = foverrides[i]; - - if (fdv->fbody && !fdv->frequires) - { - error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars()); - break; - } - } - } - - // Remember whether we need to generate an 'out' contract. - const bool needEnsure = needsFensure(this); - - if (fbody || frequires || needEnsure) - { - /* Symbol table into which we place parameters and nested functions, - * solely to diagnose name collisions. - */ - localsymtab = new DsymbolTable(); - - // Establish function scope - ScopeDsymbol *ss = new ScopeDsymbol(); - // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes - for (Scope *scx = sc; ; scx = scx->enclosing) - { - if (scx->scopesym) - { - ss->parent = scx->scopesym; - break; - } - } - ss->loc = loc; - ss->endlinnum = endloc.linnum; - Scope *sc2 = sc->push(ss); - sc2->func = this; - sc2->parent = this; - sc2->callSuper = 0; - sc2->sbreak = NULL; - sc2->scontinue = NULL; - sc2->sw = NULL; - sc2->fes = fes; - sc2->linkage = LINKd; - sc2->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCabstract | - STCdeprecated | STCoverride | - STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | STCreturn | - STCproperty | STCnothrow | STCpure | STCsafe | STCtrusted | STCsystem); - sc2->protection = Prot(Prot::public_); - sc2->explicitProtection = 0; - sc2->aligndecl = NULL; - if (this->ident != Id::require && this->ident != Id::ensure) - sc2->flags = sc->flags & ~SCOPEcontract; - sc2->flags &= ~SCOPEcompile; - sc2->tf = NULL; - sc2->os = NULL; - sc2->noctor = 0; - sc2->userAttribDecl = NULL; - if (sc2->intypeof == 1) sc2->intypeof = 2; - sc2->fieldinit = NULL; - sc2->fieldinit_dim = 0; - - /* Note: When a lambda is defined immediately under aggregate member - * scope, it should be contextless due to prevent interior pointers. - * e.g. - * // dg points 'this' - it's interior pointer - * class C { int x; void delegate() dg = (){ this.x = 1; }; } - * - * However, lambdas could be used inside typeof, in order to check - * some expressions varidity at compile time. For such case the lambda - * body can access aggregate instance members. - * e.g. - * class C { int x; static assert(is(typeof({ this.x = 1; }))); } - * - * To properly accept it, mark these lambdas as member functions. - */ - if (FuncLiteralDeclaration *fld = isFuncLiteralDeclaration()) - { - if (AggregateDeclaration *ad = isMember2()) - { - if (!sc->intypeof) - { - if (fld->tok == TOKdelegate) - error("cannot be %s members", ad->kind()); - else - fld->tok = TOKfunction; - } - else - { - if (fld->tok != TOKfunction) - fld->tok = TOKdelegate; - } - } - } - - // Declare 'this' - AggregateDeclaration *ad = isThis(); - vthis = declareThis(sc2, ad); - //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis); - //if (vthis) printf("\tvthis->type = %s\n", vthis->type->toChars()); - - // Declare hidden variable _arguments[] and _argptr - if (f->parameterList.varargs == VARARGvariadic) - { - if (f->linkage == LINKd) - { - // Variadic arguments depend on Typeinfo being defined - if (!global.params.useTypeInfo || !Type::dtypeinfo || !Type::typeinfotypelist) - { - if (!global.params.useTypeInfo) - error("D-style variadic functions cannot be used with -betterC"); - else if (!Type::typeinfotypelist) - error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions"); - else - error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions"); - fatal(); - } - - // Declare _arguments[] - v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); - v_arguments->storage_class |= STCtemp | STCparameter; - v_arguments->semantic(sc2); - sc2->insert(v_arguments); - v_arguments->parent = this; - - //Type *t = Type::typeinfo->type->constOf()->arrayOf(); - Type *t = Type::dtypeinfo->type->arrayOf(); - _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL); - _arguments->storage_class |= STCtemp; - _arguments->semantic(sc2); - sc2->insert(_arguments); - _arguments->parent = this; - } - if (f->linkage == LINKd || f->parameterList.length()) - { - // Declare _argptr - Type *t = target.va_listType(loc, sc); - v_argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL); - v_argptr->storage_class |= STCtemp; - v_argptr->semantic(sc2); - sc2->insert(v_argptr); - v_argptr->parent = this; - } - } - - /* Declare all the function parameters as variables - * and install them in parameters[] - */ - size_t nparams = f->parameterList.length(); - if (nparams) - { - /* parameters[] has all the tuples removed, as the back end - * doesn't know about tuples - */ - parameters = new VarDeclarations(); - parameters->reserve(nparams); - for (size_t i = 0; i < nparams; i++) - { - Parameter *fparam = f->parameterList[i]; - Identifier *id = fparam->ident; - StorageClass stc = 0; - if (!id) - { - /* Generate identifier for un-named parameter, - * because we need it later on. - */ - fparam->ident = id = Identifier::generateId("_param_", i); - stc |= STCtemp; - } - Type *vtype = fparam->type; - VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL); - //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); - stc |= STCparameter; - if (f->parameterList.varargs == VARARGtypesafe && i + 1 == nparams) - stc |= STCvariadic; - if (flags & FUNCFLAGinferScope && !(fparam->storageClass & STCscope)) - stc |= STCmaybescope; - stc |= fparam->storageClass & (STCin | STCout | STCref | STCreturn | STCscope | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); - v->storage_class = stc; - v->semantic(sc2); - if (!sc2->insert(v)) - error("parameter %s.%s is already defined", toChars(), v->toChars()); - else - parameters->push(v); - localsymtab->insert(v); - v->parent = this; - if (fparam->userAttribDecl) - v->userAttribDecl = fparam->userAttribDecl; - } - } - - // Declare the tuple symbols and put them in the symbol table, - // but not in parameters[]. - if (f->parameterList.parameters) - { - for (size_t i = 0; i < f->parameterList.parameters->length; i++) - { - Parameter *fparam = (*f->parameterList.parameters)[i]; - - if (!fparam->ident) - continue; // never used, so ignore - if (fparam->type->ty == Ttuple) - { - TypeTuple *t = (TypeTuple *)fparam->type; - size_t dim = Parameter::dim(t->arguments); - Objects *exps = new Objects(); - exps->setDim(dim); - for (size_t j = 0; j < dim; j++) - { - Parameter *narg = Parameter::getNth(t->arguments, j); - assert(narg->ident); - VarDeclaration *v = sc2->search(Loc(), narg->ident, NULL)->isVarDeclaration(); - assert(v); - Expression *e = new VarExp(v->loc, v); - (*exps)[j] = e; - } - assert(fparam->ident); - TupleDeclaration *v = new TupleDeclaration(loc, fparam->ident, exps); - //printf("declaring tuple %s\n", v->toChars()); - v->isexp = true; - if (!sc2->insert(v)) - error("parameter %s.%s is already defined", toChars(), v->toChars()); - localsymtab->insert(v); - v->parent = this; - } - } - } - - // Precondition invariant - Statement *fpreinv = NULL; - if (addPreInvariant()) - { - Expression *e = addInvariant(ad, vthis); - if (e) - fpreinv = new ExpStatement(Loc(), e); - } - - // Postcondition invariant - Statement *fpostinv = NULL; - if (addPostInvariant()) - { - Expression *e = addInvariant(ad, vthis); - if (e) - fpostinv = new ExpStatement(Loc(), e); - } - - // Pre/Postcondition contract - if (!fbody) - buildEnsureRequire(this); - - Scope *scout = NULL; - if (needEnsure || addPostInvariant()) - { - if ((needEnsure && global.params.useOut == CHECKENABLEon) || fpostinv) - { - returnLabel = new LabelDsymbol(Id::returnLabel); - } - - // scope of out contract (need for vresult->semantic) - ScopeDsymbol *sym = new ScopeDsymbol(); - sym->parent = sc2->scopesym; - sym->loc = loc; - sym->endlinnum = endloc.linnum; - scout = sc2->push(sym); - } - - if (fbody) - { - ScopeDsymbol *sym = new ScopeDsymbol(); - sym->parent = sc2->scopesym; - sym->loc = loc; - sym->endlinnum = endloc.linnum; - sc2 = sc2->push(sym); - - AggregateDeclaration *ad2 = isMember2(); - - /* If this is a class constructor - */ - if (ad2 && isCtorDeclaration()) - { - allocFieldinit(sc2, ad2->fields.length); - for (size_t i = 0; i < ad2->fields.length; i++) - { - VarDeclaration *v = ad2->fields[i]; - v->ctorinit = 0; - } - } - - bool inferRef = (f->isref && (storage_class & STCauto)); - - fbody = ::semantic(fbody, sc2); - if (!fbody) - fbody = new CompoundStatement(Loc(), new Statements()); - - if (naked) - { - fpreinv = NULL; // can't accommodate with no stack frame - fpostinv = NULL; - } - - assert(type == f || - (type->ty == Tfunction && - f->purity == PUREimpure && - ((TypeFunction *)type)->purity >= PUREfwdref)); - f = (TypeFunction *)type; - - if (inferRetType) - { - // If no return type inferred yet, then infer a void - if (!f->next) - f->next = Type::tvoid; - if (f->checkRetType(loc)) - fbody = new ErrorStatement(); - } - if (global.params.vcomplex && f->next != NULL) - f->next->checkComplexTransition(loc); - - if (returns && !fbody->isErrorStatement()) - { - for (size_t i = 0; i < returns->length; ) - { - Expression *exp = (*returns)[i]->exp; - if (exp->op == TOKvar && ((VarExp *)exp)->var == vresult) - { - if (addReturn0(this)) - exp->type = Type::tint32; - else - exp->type = f->next; - // Remove `return vresult;` from returns - returns->remove(i); - continue; - } - if (inferRef && f->isref && !exp->type->constConv(f->next)) // Bugzilla 13336 - f->isref = false; - i++; - } - } - if (f->isref) // Function returns a reference - { - if (storage_class & STCauto) - storage_class &= ~STCauto; - } - if (!target.isReturnOnStack(f, needThis()) || !checkNRVO()) - nrvo_can = 0; - - if (fbody->isErrorStatement()) - ; - else if (isStaticCtorDeclaration()) - { - /* It's a static constructor. Ensure that all - * ctor consts were initialized. - */ - ScopeDsymbol *pd = toParent()->isScopeDsymbol(); - for (size_t i = 0; i < pd->members->length; i++) - { - Dsymbol *s = (*pd->members)[i]; - s->checkCtorConstInit(); - } - } - else if (ad2 && isCtorDeclaration()) - { - ClassDeclaration *cd = ad2->isClassDeclaration(); - - // Verify that all the ctorinit fields got initialized - if (!(sc2->callSuper & CSXthis_ctor)) - { - for (size_t i = 0; i < ad2->fields.length; i++) - { - VarDeclaration *v = ad2->fields[i]; - if (v->isThisDeclaration()) - continue; - if (v->ctorinit == 0) - { - /* Current bugs in the flow analysis: - * 1. union members should not produce error messages even if - * not assigned to - * 2. structs should recognize delegating opAssign calls as well - * as delegating calls to other constructors - */ - if (v->isCtorinit() && !v->type->isMutable() && cd) - error("missing initializer for %s field %s", MODtoChars(v->type->mod), v->toChars()); - else if (v->storage_class & STCnodefaultctor) - ::error(loc, "field %s must be initialized in constructor", v->toChars()); - else if (v->type->needsNested()) - ::error(loc, "field %s must be initialized in constructor, because it is nested struct", v->toChars()); - } - else - { - bool mustInit = (v->storage_class & STCnodefaultctor || - v->type->needsNested()); - if (mustInit && !(sc2->fieldinit[i] & CSXthis_ctor)) - { - error("field %s must be initialized but skipped", v->toChars()); - } - } - } - } - freeFieldinit(sc2); - - if (cd && - !(sc2->callSuper & CSXany_ctor) && - cd->baseClass && cd->baseClass->ctor) - { - sc2->callSuper = 0; - - // Insert implicit super() at start of fbody - FuncDeclaration *fd = resolveFuncCall(Loc(), sc2, cd->baseClass->ctor, NULL, vthis->type, NULL, 1); - if (!fd) - { - error("no match for implicit super() call in constructor"); - } - else if (fd->storage_class & STCdisable) - { - error("cannot call super() implicitly because it is annotated with @disable"); - } - else - { - Expression *e1 = new SuperExp(Loc()); - Expression *e = new CallExp(Loc(), e1); - e = ::semantic(e, sc2); - - Statement *s = new ExpStatement(Loc(), e); - fbody = new CompoundStatement(Loc(), s, fbody); - } - } - //printf("callSuper = x%x\n", sc2->callSuper); - } - - /* https://issues.dlang.org/show_bug.cgi?id=17502 - * Wait until after the return type has been inferred before - * generating the contracts for this function, and merging contracts - * from overrides. - * - * https://issues.dlang.org/show_bug.cgi?id=17893 - * However should take care to generate this before inferered - * function attributes are applied, such as 'nothrow'. - * - * This was originally at the end of the first semantic pass, but - * required a fix-up to be done here for the '__result' variable - * type of __ensure() inside auto functions, but this didn't work - * if the out parameter was implicit. - */ - buildEnsureRequire(this); - - int blockexit = BEnone; - if (!fbody->isErrorStatement()) - { - // Check for errors related to 'nothrow'. - unsigned int nothrowErrors = global.errors; - blockexit = blockExit(fbody, this, f->isnothrow); - if (f->isnothrow && (global.errors != nothrowErrors)) - ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars()); - if (flags & FUNCFLAGnothrowInprocess) - { - if (type == f) f = (TypeFunction *)f->copy(); - f->isnothrow = !(blockexit & BEthrow); - } - } - - if (fbody->isErrorStatement()) - ; - else if (ad2 && isCtorDeclaration()) - { - /* Append: - * return this; - * to function body - */ - if (blockexit & BEfallthru) - { - Statement *s = new ReturnStatement(loc, NULL); - s = ::semantic(s, sc2); - fbody = new CompoundStatement(loc, fbody, s); - hasReturnExp |= (hasReturnExp & 1 ? 16 : 1); - } - } - else if (fes) - { - // For foreach(){} body, append a return 0; - if (blockexit & BEfallthru) - { - Expression *e = new IntegerExp(0); - Statement *s = new ReturnStatement(Loc(), e); - fbody = new CompoundStatement(Loc(), fbody, s); - hasReturnExp |= (hasReturnExp & 1 ? 16 : 1); - } - assert(!returnLabel); - } - else - { - const bool inlineAsm = (hasReturnExp & 8) != 0; - if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm) - { - Expression *e; - if (!hasReturnExp) - error("has no return statement, but is expected to return a value of type %s", f->next->toChars()); - else - error("no return exp; or assert(0); at end of function"); - if (global.params.useAssert == CHECKENABLEon && - !global.params.useInline) - { - /* Add an assert(0, msg); where the missing return - * should be. - */ - e = new AssertExp( - endloc, - new IntegerExp(0), - new StringExp(loc, const_cast("missing return expression")) - ); - } - else - e = new HaltExp(endloc); - e = new CommaExp(Loc(), e, f->next->defaultInit()); - e = ::semantic(e, sc2); - Statement *s = new ExpStatement(Loc(), e); - fbody = new CompoundStatement(Loc(), fbody, s); - } - } - - if (returns) - { - bool implicit0 = addReturn0(this); - Type *tret = implicit0 ? Type::tint32 : f->next; - assert(tret->ty != Tvoid); - if (vresult || returnLabel) - buildResultVar(scout ? scout : sc2, tret); - - /* Cannot move this loop into NrvoWalker, because - * returns[i] may be in the nested delegate for foreach-body. - */ - for (size_t i = 0; i < returns->length; i++) - { - ReturnStatement *rs = (*returns)[i]; - Expression *exp = rs->exp; - if (exp->op == TOKerror) - continue; - if (tret->ty == Terror) - { - // Bugzilla 13702 - exp = checkGC(sc2, exp); - continue; - } - - if (!exp->implicitConvTo(tret) && - parametersIntersect(exp->type)) - { - if (exp->type->immutableOf()->implicitConvTo(tret)) - exp = exp->castTo(sc2, exp->type->immutableOf()); - else if (exp->type->wildOf()->implicitConvTo(tret)) - exp = exp->castTo(sc2, exp->type->wildOf()); - } - exp = exp->implicitCastTo(sc2, tret); - - if (f->isref) - { - // Function returns a reference - exp = exp->toLvalue(sc2, exp); - checkReturnEscapeRef(sc2, exp, false); - } - else - { - exp = exp->optimize(WANTvalue); - - /* Bugzilla 10789: - * If NRVO is not possible, all returned lvalues should call their postblits. - */ - if (!nrvo_can) - exp = doCopyOrMove(sc2, exp); - - if (tret->hasPointers()) - checkReturnEscape(sc2, exp, false); - } - - exp = checkGC(sc2, exp); - - if (vresult) - { - // Create: return vresult = exp; - exp = new BlitExp(rs->loc, vresult, exp); - exp->type = vresult->type; - - if (rs->caseDim) - exp = Expression::combine(exp, new IntegerExp(rs->caseDim)); - } - else if (tintro && !tret->equals(tintro->nextOf())) - { - exp = exp->implicitCastTo(sc2, tintro->nextOf()); - } - rs->exp = exp; - } - } - if (nrvo_var || returnLabel) - { - NrvoWalker nw; - nw.fd = this; - nw.sc = sc2; - nw.visitStmt(fbody); - } - - sc2 = sc2->pop(); - } - - frequire = mergeFrequire(frequire); - fensure = mergeFensure(fensure, Id::result); - - Statement *freq = frequire; - Statement *fens = fensure; - - /* Do the semantic analysis on the [in] preconditions and - * [out] postconditions. - */ - if (freq) - { - /* frequire is composed of the [in] contracts - */ - ScopeDsymbol *sym = new ScopeDsymbol(); - sym->parent = sc2->scopesym; - sym->loc = loc; - sym->endlinnum = endloc.linnum; - sc2 = sc2->push(sym); - sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire; - - // BUG: need to error if accessing out parameters - // BUG: need to disallow returns and throws - // BUG: verify that all in and ref parameters are read - freq = ::semantic(freq, sc2); - blockExit(freq, this, false); - - sc2 = sc2->pop(); - - if (global.params.useIn == CHECKENABLEoff) - freq = NULL; - } - - if (fens) - { - /* fensure is composed of the [out] contracts - */ - if (f->next->ty == Tvoid && fensures) - { - for (size_t i = 0; i < fensures->length; i++) - { - Ensure e = (*fensures)[i]; - if (e.id) - { - error(e.ensure->loc, "`void` functions have no result"); - //fens = NULL; - } - } - } - - sc2 = scout; //push - sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure; - - // BUG: need to disallow returns and throws - if (fensure && f->next->ty != Tvoid) - buildResultVar(scout, f->next); - - fens = ::semantic(fens, sc2); - blockExit(fens, this, false); - - sc2 = sc2->pop(); - - if (global.params.useOut == CHECKENABLEoff) - fens = NULL; - } - - if (fbody && fbody->isErrorStatement()) - ; - else - { - Statements *a = new Statements(); - - // Merge in initialization of 'out' parameters - if (parameters) - { - for (size_t i = 0; i < parameters->length; i++) - { - VarDeclaration *v = (*parameters)[i]; - if (v->storage_class & STCout) - { - assert(v->_init); - ExpInitializer *ie = v->_init->isExpInitializer(); - assert(ie); - if (ie->exp->op == TOKconstruct) - ie->exp->op = TOKassign; // construction occured in parameter processing - a->push(new ExpStatement(Loc(), ie->exp)); - } - } - } - - if (v_argptr) - { - // Handled in FuncDeclaration::toObjFile - v_argptr->_init = new VoidInitializer(loc); - } - - if (_arguments) - { - /* Advance to elements[] member of TypeInfo_Tuple with: - * _arguments = v_arguments.elements; - */ - Expression *e = new VarExp(Loc(), v_arguments); - e = new DotIdExp(Loc(), e, Id::elements); - e = new ConstructExp(Loc(), _arguments, e); - e = ::semantic(e, sc2); - - _arguments->_init = new ExpInitializer(Loc(), e); - DeclarationExp *de = new DeclarationExp(Loc(), _arguments); - a->push(new ExpStatement(Loc(), de)); - } - - // Merge contracts together with body into one compound statement - - if (freq || fpreinv) - { - if (!freq) - freq = fpreinv; - else if (fpreinv) - freq = new CompoundStatement(Loc(), freq, fpreinv); - - a->push(freq); - } - - if (fbody) - a->push(fbody); - - if (fens || fpostinv) - { - if (!fens) - fens = fpostinv; - else if (fpostinv) - fens = new CompoundStatement(Loc(), fpostinv, fens); - - LabelStatement *ls = new LabelStatement(Loc(), Id::returnLabel, fens); - returnLabel->statement = ls; - a->push(returnLabel->statement); - - if (f->next->ty != Tvoid && vresult) - { - // Create: return vresult; - Expression *e = new VarExp(Loc(), vresult); - if (tintro) - { - e = e->implicitCastTo(sc, tintro->nextOf()); - e = ::semantic(e, sc); - } - ReturnStatement *s = new ReturnStatement(Loc(), e); - a->push(s); - } - } - if (addReturn0(this)) - { - // Add a return 0; statement - Statement *s = new ReturnStatement(Loc(), new IntegerExp(0)); - a->push(s); - } - - Statement *sbody = new CompoundStatement(Loc(), a); - /* Append destructor calls for parameters as finally blocks. - */ - if (parameters) - { - for (size_t i = 0; i < parameters->length; i++) - { - VarDeclaration *v = (*parameters)[i]; - - if (v->storage_class & (STCref | STCout | STClazy)) - continue; - - if (v->needsScopeDtor()) - { - // same with ExpStatement.scopeCode() - Statement *s = new DtorExpStatement(Loc(), v->edtor, v); - v->storage_class |= STCnodtor; - - s = ::semantic(s, sc2); - - bool isnothrow = f->isnothrow & !(flags & FUNCFLAGnothrowInprocess); - int blockexit = blockExit(s, this, isnothrow); - if (f->isnothrow && isnothrow && blockexit & BEthrow) - ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars()); - if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow) - f->isnothrow = false; - if (blockExit(sbody, this, f->isnothrow) == BEfallthru) - sbody = new CompoundStatement(Loc(), sbody, s); - else - sbody = new TryFinallyStatement(Loc(), sbody, s); - } - } - } - // from this point on all possible 'throwers' are checked - flags &= ~FUNCFLAGnothrowInprocess; - - if (isSynchronized()) - { - /* Wrap the entire function body in a synchronized statement - */ - ClassDeclaration *cd = isThis() ? isThis()->isClassDeclaration() : parent->isClassDeclaration(); - - if (cd) - { - if (!global.params.is64bit && - global.params.isWindows && - !isStatic() && !sbody->usesEH() && !global.params.trace) - { - /* The back end uses the "jmonitor" hack for syncing; - * no need to do the sync at this level. - */ - } - else - { - Expression *vsync; - if (isStatic()) - { - // The monitor is in the ClassInfo - vsync = new DotIdExp(loc, resolve(loc, sc2, cd, false), Id::classinfo); - } - else - { - // 'this' is the monitor - vsync = new VarExp(loc, vthis); - } - sbody = new PeelStatement(sbody); // don't redo semantic() - sbody = new SynchronizedStatement(loc, vsync, sbody); - sbody = ::semantic(sbody, sc2); - } - } - else - { - error("synchronized function %s must be a member of a class", toChars()); - } - } - - // If declaration has no body, don't set sbody to prevent incorrect codegen. - if (fbody || allowsContractWithoutBody(this)) - fbody = sbody; - } - - // Fix up forward-referenced gotos - if (gotos) - { - for (size_t i = 0; i < gotos->length; ++i) - { - (*gotos)[i]->checkLabel(); - } - } - - if (naked && (fensures || frequires)) - error("naked assembly functions with contracts are not supported"); - - sc2->callSuper = 0; - sc2->pop(); - } - - if (checkClosure()) - { - // We should be setting errors here instead of relying on the global error count. - //errors = true; - } - - /* If function survived being marked as impure, then it is pure - */ - if (flags & FUNCFLAGpurityInprocess) - { - flags &= ~FUNCFLAGpurityInprocess; - if (type == f) - f = (TypeFunction *)f->copy(); - f->purity = PUREfwdref; - } - - if (flags & FUNCFLAGsafetyInprocess) - { - flags &= ~FUNCFLAGsafetyInprocess; - if (type == f) - f = (TypeFunction *)f->copy(); - f->trust = TRUSTsafe; - } - - if (flags & FUNCFLAGnogcInprocess) - { - flags &= ~FUNCFLAGnogcInprocess; - if (type == f) - f = (TypeFunction *)f->copy(); - f->isnogc = true; - } - - if (flags & FUNCFLAGreturnInprocess) - { - flags &= ~FUNCFLAGreturnInprocess; - if (storage_class & STCreturn) + * in { { statements1... } { statements2... } ... } + */ + assert(frequires->length); + Loc loc = (*frequires)[0]->loc; + Statements *s = new Statements; + for (size_t i = 0; i < frequires->length; i++) { - if (type == f) - f = (TypeFunction *)f->copy(); - f->isreturn = true; + Statement *r = (*frequires)[i]; + s->push(new ScopeStatement(r->loc, r, r->loc)); } + frequire = new CompoundStatement(loc, s); } - flags &= ~FUNCFLAGinferScope; - - // Infer STCscope - if (parameters) + if (fensures) { - size_t nfparams = f->parameterList.length(); - assert(nfparams == parameters->length); - for (size_t u = 0; u < parameters->length; u++) + /* out(id1) { statements1... } + * out(id2) { statements2... } + * ... + * becomes: + * out(__result) { { ref id1 = __result; { statements1... } } + * { ref id2 = __result; { statements2... } } ... } + */ + assert(fensures->length); + Loc loc = (*fensures)[0].ensure->loc; + Statements *s = new Statements; + for (size_t i = 0; i < fensures->length; i++) { - VarDeclaration *v = (*parameters)[u]; - if (v->storage_class & STCmaybescope) + Ensure r = (*fensures)[i]; + if (r.id && canBuildResultVar(this)) + { + Loc rloc = r.ensure->loc; + IdentifierExp *resultId = new IdentifierExp(rloc, Id::result); + ExpInitializer *init = new ExpInitializer(rloc, resultId); + StorageClass stc = STCref | STCtemp | STCresult; + VarDeclaration *decl = new VarDeclaration(rloc, NULL, r.id, init); + decl->storage_class = stc; + ExpStatement *sdecl = new ExpStatement(rloc, decl); + s->push(new ScopeStatement(rloc, new CompoundStatement(rloc, sdecl, r.ensure), rloc)); + } + else { - //printf("Inferring scope for %s\n", v->toChars()); - Parameter *p = f->parameterList[u]; - v->storage_class &= ~STCmaybescope; - v->storage_class |= STCscope | STCscopeinferred; - p->storageClass |= STCscope | STCscopeinferred; - assert(!(p->storageClass & STCmaybescope)); + s->push(r.ensure); } } + fensure = new CompoundStatement(loc, s); } - if (vthis && vthis->storage_class & STCmaybescope) - { - vthis->storage_class &= ~STCmaybescope; - vthis->storage_class |= STCscope | STCscopeinferred; - f->isscope = true; - f->isscopeinferred = true; - } + if (!isVirtual()) + return; - // reset deco to apply inference result to mangled name - if (f != type) - f->deco = NULL; + /* Rewrite contracts as nested functions, then call them. Doing it as nested + * functions means that overriding functions can call them. + */ + TypeFunction *f = (TypeFunction *)type; - // Do semantic type AFTER pure/nothrow inference. - if (!f->deco && ident != Id::xopEquals && ident != Id::xopCmp) + if (frequire) { - sc = sc->push(); - if (isCtorDeclaration()) // Bugzilla #15665 - sc->flags |= SCOPEctor; - sc->stc = 0; - sc->linkage = linkage; // Bugzilla 8496 - type = f->semantic(loc, sc); - sc = sc->pop(); + /* in { ... } + * becomes: + * void __require() { ... } + * __require(); + */ + Loc loc = frequire->loc; + TypeFunction *tf = new TypeFunction(ParameterList(), Type::tvoid, LINKd); + tf->isnothrow = f->isnothrow; + tf->isnogc = f->isnogc; + tf->purity = f->purity; + tf->trust = f->trust; + FuncDeclaration *fd = new FuncDeclaration(loc, loc, + Id::require, STCundefined, tf); + fd->fbody = frequire; + Statement *s1 = new ExpStatement(loc, fd); + Expression *e = new CallExp(loc, new VarExp(loc, fd, false), (Expressions *)NULL); + Statement *s2 = new ExpStatement(loc, e); + frequire = new CompoundStatement(loc, s1, s2); + fdrequire = fd; } - /* If this function had instantiated with gagging, error reproduction will be - * done by TemplateInstance::semantic. - * Otherwise, error gagging should be temporarily ungagged by functionSemantic3. - */ - semanticRun = PASSsemantic3done; - semantic3Errors = (global.errors != oldErrors) || (fbody && fbody->isErrorStatement()); - if (type->ty == Terror) - errors = true; - //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); - //fflush(stdout); + if (fensure) + { + /* out (result) { ... } + * becomes: + * void __ensure(ref tret result) { ... } + * __ensure(result); + */ + Loc loc = fensure->loc; + Parameters *fparams = new Parameters(); + Parameter *p = NULL; + if (canBuildResultVar(this)) + { + p = new Parameter(STCref | STCconst, f->nextOf(), Id::result, NULL, NULL); + fparams->push(p); + } + TypeFunction *tf = new TypeFunction(ParameterList(fparams), Type::tvoid, LINKd); + tf->isnothrow = f->isnothrow; + tf->isnogc = f->isnogc; + tf->purity = f->purity; + tf->trust = f->trust; + FuncDeclaration *fd = new FuncDeclaration(loc, loc, + Id::ensure, STCundefined, tf); + fd->fbody = fensure; + Statement *s1 = new ExpStatement(loc, fd); + Expression *eresult = NULL; + if (canBuildResultVar(this)) + eresult = new IdentifierExp(loc, Id::result); + Expression *e = new CallExp(loc, new VarExp(loc, fd, false), eresult); + Statement *s2 = new ExpStatement(loc, e); + fensure = new CompoundStatement(loc, s1, s2); + fdensure = fd; + } } /**************************************************** @@ -2531,7 +362,7 @@ bool FuncDeclaration::functionSemantic() unsigned oldgag = global.gag; if (global.gag && !spec) global.gag = 0; - semantic(_scope); + dsymbolSemantic(this, _scope); global.gag = oldgag; if (spec && global.errors != olderrs) spec->errors = (global.errors - olderrs != 0); @@ -2586,7 +417,7 @@ bool FuncDeclaration::functionSemantic3() unsigned oldgag = global.gag; if (global.gag && !spec) global.gag = 0; - semantic3(_scope); + semantic3(this, _scope); global.gag = oldgag; // If it is a speculatively-instantiated template, and errors occur, @@ -2615,7 +446,7 @@ bool FuncDeclaration::checkForwardRef(Loc loc) if (!type->deco) { bool inSemantic3 = (inferRetType && semanticRun >= PASSsemantic3); - ::error(loc, "forward reference to %s'%s'", + ::error(loc, "forward reference to %s`%s`", (inSemantic3 ? "inferred return type of function " : ""), toChars()); return true; @@ -2655,7 +486,7 @@ VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope)) v->storage_class |= STCmaybescope; - v->semantic(sc); + dsymbolSemantic(v, sc); if (!sc->insert(v)) assert(0); v->parent = this; @@ -2681,7 +512,7 @@ VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope)) v->storage_class |= STCmaybescope; - v->semantic(sc); + dsymbolSemantic(v, sc); if (!sc->insert(v)) assert(0); v->parent = this; @@ -2756,7 +587,7 @@ void FuncDeclaration::buildResultVar(Scope *sc, Type *tret) vresult->storage_class |= STCref; vresult->type = tret; - vresult->semantic(sc); + dsymbolSemantic(vresult, sc); if (!sc->insert(vresult)) error("out result %s is already defined", vresult->toChars()); @@ -2816,7 +647,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf) assert(fdv->_scope); Scope *sc = fdv->_scope->push(); sc->stc &= ~STCoverride; - fdv->semantic3(sc); + semantic3(fdv, sc); sc->pop(); } @@ -2874,7 +705,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Identifier *oid) assert(fdv->_scope); Scope *sc = fdv->_scope->push(); sc->stc &= ~STCoverride; - fdv->semantic3(sc); + semantic3(fdv, sc); sc->pop(); } @@ -3706,7 +1537,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, } else if (od) { - ::error(loc, "none of the overloads of '%s' are callable using argument types !(%s)%s", + ::error(loc, "none of the overloads of `%s` are callable using argument types !(%s)%s", od->ident->toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); } else @@ -3721,7 +1552,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod); MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod); if (hasOverloads) - ::error(loc, "none of the overloads of '%s' are callable using a %sobject, candidates are:", + ::error(loc, "none of the overloads of `%s` are callable using a %sobject, candidates are:", fd->ident->toChars(), thisBuf.peekChars()); else ::error(loc, "%smethod %s is not callable using a %sobject", @@ -3731,7 +1562,7 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, { //printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco); if (hasOverloads) - ::error(loc, "none of the overloads of '%s' are callable using argument types %s, candidates are:", + ::error(loc, "none of the overloads of `%s` are callable using argument types %s, candidates are:", fd->ident->toChars(), fargsBuf.peekChars()); else fd->error(loc, "%s%s is not callable using argument types %s", @@ -4296,56 +2127,6 @@ bool FuncDeclaration::addPostInvariant() !naked); } -/******************************************************** - * Generate Expression to call the invariant. - * Input: - * ad aggregate with the invariant - * vthis variable with 'this' - * Returns: - * void expression that calls the invariant - */ -Expression *addInvariant(AggregateDeclaration *ad, VarDeclaration *vthis) -{ - Expression *e = NULL; - - // Call invariant directly only if it exists - FuncDeclaration *inv = ad->inv; - ClassDeclaration *cd = ad->isClassDeclaration(); - - while (!inv && cd) - { - cd = cd->baseClass; - if (!cd) - break; - inv = cd->inv; - } - if (inv) - { - #if 1 - // Workaround for bugzilla 13394: For the correct mangling, - // run attribute inference on inv if needed. - inv->functionSemantic(); - #endif - - //e = new DsymbolExp(Loc(), inv); - //e = new CallExp(Loc(), e); - //e = e->semantic(sc2); - - /* https://issues.dlang.org/show_bug.cgi?id=13113 - * Currently virtual invariant calls completely - * bypass attribute enforcement. - * Change the behavior of pre-invariant call by following it. - */ - e = new ThisExp(Loc()); - e->type = vthis->type; - e = new DotVarExp(Loc(), e, inv, false); - e->type = inv->type; - e = new CallExp(Loc(), e); - e->type = Type::tvoid; - } - return e; -} - /********************************** * Generate a FuncDeclaration for a runtime library function. */ @@ -4987,87 +2768,6 @@ Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(f); } -void CtorDeclaration::semantic(Scope *sc) -{ - //printf("CtorDeclaration::semantic() %s\n", toChars()); - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = toParent2(); - AggregateDeclaration *ad = p->isAggregateDeclaration(); - if (!ad) - { - ::error(loc, "constructor can only be a member of aggregate, not %s %s", - p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - - sc = sc->push(); - sc->stc &= ~STCstatic; // not a static constructor - sc->flags |= SCOPEctor; - - FuncDeclaration::semantic(sc); - - sc->pop(); - - if (errors) - return; - - TypeFunction *tf = type->toTypeFunction(); - - /* See if it's the default constructor - * But, template constructor should not become a default constructor. - */ - if (ad && (!parent->isTemplateInstance() || parent->isTemplateMixin())) - { - const size_t dim = tf->parameterList.length(); - - if (StructDeclaration *sd = ad->isStructDeclaration()) - { - if (dim == 0 && tf->parameterList.varargs == VARARGnone) // empty default ctor w/o any varargs - { - if (fbody || !(storage_class & STCdisable) || dim) - { - error("default constructor for structs only allowed " - "with @disable, no body, and no parameters"); - storage_class |= STCdisable; - fbody = NULL; - } - sd->noDefaultCtor = true; - } - else if (dim == 0 && tf->parameterList.varargs) // allow varargs only ctor - { - } - else if (dim && tf->parameterList[0]->defaultArg) - { - // if the first parameter has a default argument, then the rest does as well - if (storage_class & STCdisable) - { - deprecation("@disable'd constructor cannot have default " - "arguments for all parameters."); - deprecationSupplemental(loc, "Use @disable this(); if you want to disable default initialization."); - } - else - deprecation("all parameters have default arguments, " - "but structs cannot have default constructors."); - } - - } - else if (dim == 0 && tf->parameterList.varargs == VARARGnone) - { - ad->defaultCtor = this; - } - } -} - const char *CtorDeclaration::kind() const { return "constructor"; @@ -5108,44 +2808,6 @@ Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(dd); } -void PostBlitDeclaration::semantic(Scope *sc) -{ - //printf("PostBlitDeclaration::semantic() %s\n", toChars()); - //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor); - //printf("stc = x%llx\n", sc->stc); - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = toParent2(); - StructDeclaration *ad = p->isStructDeclaration(); - if (!ad) - { - ::error(loc, "postblit can only be a member of struct/union, not %s %s", - p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - if (ident == Id::postblit && semanticRun < PASSsemantic) - ad->postblits.push(this); - if (!type) - type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class); - - sc = sc->push(); - sc->stc &= ~STCstatic; // not static - sc->linkage = LINKd; - - FuncDeclaration::semantic(sc); - - sc->pop(); -} - bool PostBlitDeclaration::overloadInsert(Dsymbol *) { return false; // cannot overload postblits @@ -5185,44 +2847,6 @@ Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(dd); } -void DtorDeclaration::semantic(Scope *sc) -{ - //printf("DtorDeclaration::semantic() %s\n", toChars()); - //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor); - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = toParent2(); - AggregateDeclaration *ad = p->isAggregateDeclaration(); - if (!ad) - { - ::error(loc, "destructor can only be a member of aggregate, not %s %s", - p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - if (ident == Id::dtor && semanticRun < PASSsemantic) - ad->dtors.push(this); - if (!type) - type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class); - - sc = sc->push(); - sc->stc &= ~STCstatic; // not a static destructor - if (sc->linkage != LINKcpp) - sc->linkage = LINKd; - - FuncDeclaration::semantic(sc); - - sc->pop(); -} - bool DtorDeclaration::overloadInsert(Dsymbol *) { return false; // cannot overload destructors @@ -5275,71 +2899,6 @@ Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(scd); } -void StaticCtorDeclaration::semantic(Scope *sc) -{ - //printf("StaticCtorDeclaration::semantic()\n"); - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = parent->pastMixin(); - if (!p->isScopeDsymbol()) - { - const char *s = (isSharedStaticCtorDeclaration() ? "shared " : ""); - ::error(loc, "%sstatic constructor can only be member of module/aggregate/template, not %s %s", - s, p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - if (!type) - type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class); - - /* If the static ctor appears within a template instantiation, - * it could get called multiple times by the module constructors - * for different modules. Thus, protect it with a gate. - */ - if (isInstantiated() && semanticRun < PASSsemantic) - { - /* Add this prefix to the function: - * static int gate; - * if (++gate != 1) return; - * Note that this is not thread safe; should not have threads - * during static construction. - */ - VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL); - v->storage_class = STCtemp | (isSharedStaticCtorDeclaration() ? STCstatic : STCtls); - Statements *sa = new Statements(); - Statement *s = new ExpStatement(Loc(), v); - sa->push(s); - Expression *e = new IdentifierExp(Loc(), v->ident); - e = new AddAssignExp(Loc(), e, new IntegerExp(1)); - e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(1)); - s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc()); - sa->push(s); - if (fbody) - sa->push(fbody); - fbody = new CompoundStatement(Loc(), sa); - } - - FuncDeclaration::semantic(sc); - - // We're going to need ModuleInfo - Module *m = getModule(); - if (!m) - m = sc->_module; - if (m) - { - m->needmoduleinfo = 1; - //printf("module1 %s needs moduleinfo\n", m->toChars()); - } -} - AggregateDeclaration *StaticCtorDeclaration::isThis() { return NULL; @@ -5402,72 +2961,6 @@ Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(sdd); } -void StaticDtorDeclaration::semantic(Scope *sc) -{ - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = parent->pastMixin(); - if (!p->isScopeDsymbol()) - { - const char *s = (isSharedStaticDtorDeclaration() ? "shared " : ""); - ::error(loc, "%sstatic destructor can only be member of module/aggregate/template, not %s %s", - s, p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - if (!type) - type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class); - - /* If the static ctor appears within a template instantiation, - * it could get called multiple times by the module constructors - * for different modules. Thus, protect it with a gate. - */ - if (isInstantiated() && semanticRun < PASSsemantic) - { - /* Add this prefix to the function: - * static int gate; - * if (--gate != 0) return; - * Increment gate during constructor execution. - * Note that this is not thread safe; should not have threads - * during static destruction. - */ - VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL); - v->storage_class = STCtemp | (isSharedStaticDtorDeclaration() ? STCstatic : STCtls); - Statements *sa = new Statements(); - Statement *s = new ExpStatement(Loc(), v); - sa->push(s); - Expression *e = new IdentifierExp(Loc(), v->ident); - e = new AddAssignExp(Loc(), e, new IntegerExp(-1)); - e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(0)); - s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc()); - sa->push(s); - if (fbody) - sa->push(fbody); - fbody = new CompoundStatement(Loc(), sa); - vgate = v; - } - - FuncDeclaration::semantic(sc); - - // We're going to need ModuleInfo - Module *m = getModule(); - if (!m) - m = sc->_module; - if (m) - { - m->needmoduleinfo = 1; - //printf("module2 %s needs moduleinfo\n", m->toChars()); - } -} - AggregateDeclaration *StaticDtorDeclaration::isThis() { return NULL; @@ -5523,46 +3016,6 @@ Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(id); } -void InvariantDeclaration::semantic(Scope *sc) -{ - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = parent->pastMixin(); - AggregateDeclaration *ad = p->isAggregateDeclaration(); - if (!ad) - { - ::error(loc, "invariant can only be a member of aggregate, not %s %s", - p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - if (ident != Id::classInvariant && - semanticRun < PASSsemantic && - !ad->isUnionDeclaration() // users are on their own with union fields - ) - ad->invs.push(this); - if (!type) - type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class); - - sc = sc->push(); - sc->stc &= ~STCstatic; // not a static invariant - sc->stc |= STCconst; // invariant() is always const - sc->flags = (sc->flags & ~SCOPEcontract) | SCOPEinvariant; - sc->linkage = LINKd; - - FuncDeclaration::semantic(sc); - - sc->pop(); -} - bool InvariantDeclaration::isVirtual() { return false; @@ -5605,40 +3058,6 @@ Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(utd); } -void UnitTestDeclaration::semantic(Scope *sc) -{ - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - protection = sc->protection; - - parent = sc->parent; - Dsymbol *p = parent->pastMixin(); - if (!p->isScopeDsymbol()) - { - ::error(loc, "unittest can only be a member of module/aggregate/template, not %s %s", - p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - - if (global.params.useUnitTests) - { - if (!type) - type = new TypeFunction(ParameterList(), Type::tvoid, LINKd, storage_class); - Scope *sc2 = sc->push(); - sc2->linkage = LINKd; - FuncDeclaration::semantic(sc2); - sc2->pop(); - } -} - AggregateDeclaration *UnitTestDeclaration::isThis() { return NULL; @@ -5676,49 +3095,6 @@ Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(f); } -void NewDeclaration::semantic(Scope *sc) -{ - //printf("NewDeclaration::semantic()\n"); - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = parent->pastMixin(); - if (!p->isAggregateDeclaration()) - { - ::error(loc, "allocator can only be a member of aggregate, not %s %s", - p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - Type *tret = Type::tvoid->pointerTo(); - if (!type) - type = new TypeFunction(ParameterList(parameters, varargs), tret, LINKd, storage_class); - - type = type->semantic(loc, sc); - - // Check that there is at least one argument of type size_t - TypeFunction *tf = type->toTypeFunction(); - if (tf->parameterList.length() < 1) - { - error("at least one argument of type size_t expected"); - } - else - { - Parameter *fparam = tf->parameterList[0]; - if (!fparam->type->equals(Type::tsize_t)) - error("first argument must be type size_t, not %s", fparam->type->toChars()); - } - - FuncDeclaration::semantic(sc); -} - const char *NewDeclaration::kind() const { return "allocator"; @@ -5755,48 +3131,6 @@ Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s) return FuncDeclaration::syntaxCopy(f); } -void DeleteDeclaration::semantic(Scope *sc) -{ - //printf("DeleteDeclaration::semantic()\n"); - if (semanticRun >= PASSsemanticdone) - return; - if (_scope) - { - sc = _scope; - _scope = NULL; - } - - parent = sc->parent; - Dsymbol *p = parent->pastMixin(); - if (!p->isAggregateDeclaration()) - { - ::error(loc, "deallocator can only be a member of aggregate, not %s %s", - p->kind(), p->toChars()); - type = Type::terror; - errors = true; - return; - } - if (!type) - type = new TypeFunction(ParameterList(parameters), Type::tvoid, LINKd, storage_class); - - type = type->semantic(loc, sc); - - // Check that there is only one argument of type void* - TypeFunction *tf = type->toTypeFunction(); - if (tf->parameterList.length() != 1) - { - error("one argument of type void* expected"); - } - else - { - Parameter *fparam = tf->parameterList[0]; - if (!fparam->type->equals(Type::tvoid->pointerTo())) - error("one argument of type void* expected, not %s", fparam->type->toChars()); - } - - FuncDeclaration::semantic(sc); -} - const char *DeleteDeclaration::kind() const { return "deallocator"; diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index 6e65d86eb5a..d9d59d685ca 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 a351930ce45..a11c9c353d9 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 1bad506bb28..d464d4aa618 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 459a3a622bc..fc58a3c4462 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 5cc9025a7b3..e3940a8adbf 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 1bd453fc53c..197d288e532 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 c611bf1dc35..278ce9b8a76 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 322a293cf09..59faa993b9b 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 c221cd203dc..d7c27eaa771 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 d08e374add2..239cb073332 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 d1739313c11..e49ad15c2d3 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 28b4187b2e6..d18e0549aac 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 6f98fdb4946..4ba18d6a474 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 9381da46b29..c7d1dfe0deb 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 788b37b18a4..36af8dac9ee 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 58ec5b9b434..fd6153205c9 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 802de81c4c2..832e559a875 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 2dbcc0c0f90..d680001000f 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 db989b0b528..3ea932c036e 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 555b6c65b84..b36e7f7bdaf 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 26710b4771b..80ec36e00e6 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 c60f4a73440..544f77b8b0b 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 ddccd6c7d99..9b9c278c8a7 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 4968ec7e1b5..03078b5e833 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 cc8eb226019..c1071b2f278 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(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(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 28dba1c250a..083d707f8f3 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 1372f4804a4..12c8b490cfb 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 71d1c6f5552..95cfb6f0d34 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 ae29b18d787..71dafb2553d 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 b0353a5de7b..3199a0164ee 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 00d76e143e6..f3da5a3755f 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 66a0d235eee..0aff8b43551 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(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 45d94df577d..44dedd84038 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 bae3448b90e..c050b050404 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 dae7b634db4..82ce3254607 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 fd76d6da846..992a117da2a 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 d08a3f8794f..c65b674a7f5 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 633414b1530..f7cb0c75184 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 195e3beef57..004c43caa54 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 ee107393eda..af7b56f145c 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 66e3b04cac6..8a7d9c90d9f 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 4cdf362e598..0a829f3e051 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 5aec84e1239..9fd176ebcb1 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 7fcadc58aa0..314b5b512c8 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 348dce2e7fd..51358182b7c 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 f0e0213e701..0c5138b6ddf 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 6ef515c6441..52cd963d708 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 452ce30a8f5..6a322006213 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 3e1532a3a32..d5e3b2b090d 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 81c2e901805..7fbbfe57db3 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 da0d305aa52..186fbb7eb84 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 b35da253072..94651cdd5a4 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 09ea44d3630..768b75d2715 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 fdb8676c2b9..1f603b8c658 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 274245a0307..d998d95be76 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 7cb2dc43de3..7fee0d7297b 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 c2351e913c5..3957c112a07 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 6d703750953..bd53fc452c9 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 15e5a023559..fe14807791d 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 8cbdbd8a91f..51304d32c3f 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 08274af8bd4..7d83dd170ad 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 35e38c151ac..ce0892606b8 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 7e1b634caca..ea3bf3874e1 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 00000000000..7bcf6ce4f33 --- /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 00000000000..304eaeeb119 --- /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("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 efab276d849..661bd43134c 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 76dfe1d3f06..2f7b7e13ffc 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 08eb5fd0fa5..2d8b46c9487 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 00000000000..28a930a28bc --- /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 2fe0d9efeea..5579c1ca893 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 57181cd67c1..c2d0f5b65c2 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 44913226da8..6d43cb73a0d 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 48a60d34fb1..ef0a35ff382 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 5a2dd4d9133..a91880fd0fc 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 0a5bc798d6b..dac1e85b433 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 00000000000..11cd52e351b --- /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 9db1e33c1da..eb06beed9b6 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 82dcaa2dfde..f79d8419c90 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 70f7f2cb582..b7c612c2af2 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(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(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(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(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("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(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 2933e983b01..496cfe3a855 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 c497f961315..f6b543590f2 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 52a731f0bf8..b3782afe78b 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 73de2e409b2..c9e632234ef 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 36c9ef73ed1..9e7fd5ea75d 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 5f2bf2cccb4..a274e6f083e 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 ec8539deb45..698e7669884 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. */