diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-02-09 15:40:06 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-02-13 12:50:45 +0100 |
commit | a3b38b7781622babb5ca68c621367770a65012fa (patch) | |
tree | 32ba65cb98047efa6ed8f86b327903ce647c008f /gcc/d/dmd/declaration.c | |
parent | 0f3a743b688f4845e1798eed9b2e2284e891da11 (diff) | |
download | gcc-a3b38b7781622babb5ca68c621367770a65012fa.zip gcc-a3b38b7781622babb5ca68c621367770a65012fa.tar.gz gcc-a3b38b7781622babb5ca68c621367770a65012fa.tar.bz2 |
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.
Diffstat (limited to 'gcc/d/dmd/declaration.c')
-rw-r--r-- | gcc/d/dmd/declaration.c | 1046 |
1 files changed, 8 insertions, 1038 deletions
diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c index d20f663..a9394dc 100644 --- a/gcc/d/dmd/declaration.c +++ b/gcc/d/dmd/declaration.c @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved * written by Walter Bright * http://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. @@ -29,10 +29,6 @@ #include "hdrgen.h" bool checkNestedRef(Dsymbol *s, Dsymbol *p); -VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e); -Expression *semantic(Expression *e, Scope *sc); -Initializer *inferType(Initializer *init, Scope *sc); -Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret); /************************************ * Check to see the aggregate type is nested and its context pointer is @@ -81,10 +77,6 @@ Declaration::Declaration(Identifier *id) mangleOverride = NULL; } -void Declaration::semantic(Scope *) -{ -} - const char *Declaration::kind() const { return "declaration"; @@ -139,7 +131,7 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *, Expression *e1, int fla if (scx->func == parent && (scx->flags & SCOPEcontract)) { const char *s = isParameter() && parent->ident != Id::ensure ? "parameter" : "result"; - if (!flag) error(loc, "cannot modify %s '%s' in contract", s, toChars()); + if (!flag) error(loc, "cannot modify %s `%s` in contract", s, toChars()); return 2; // do not report type related errors } } @@ -291,7 +283,7 @@ Type *TupleDeclaration::getType() tupletype = new TypeTuple(args); if (hasdeco) - return tupletype->semantic(Loc(), NULL); + return typeSemantic(tupletype, Loc(), NULL); } return tupletype; @@ -380,173 +372,6 @@ Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s) return sa; } -void AliasDeclaration::semantic(Scope *sc) -{ - if (semanticRun >= PASSsemanticdone) - return; - assert(semanticRun <= PASSsemantic); - - storage_class |= sc->stc & STCdeprecated; - protection = sc->protection; - userAttribDecl = sc->userAttribDecl; - - if (!sc->func && inNonRoot()) - return; - - aliasSemantic(sc); -} - -void AliasDeclaration::aliasSemantic(Scope *sc) -{ - //printf("AliasDeclaration::semantic() %s\n", toChars()); - - // as AliasDeclaration::semantic, in case we're called first. - // see https://issues.dlang.org/show_bug.cgi?id=21001 - storage_class |= sc->stc & STCdeprecated; - protection = sc->protection; - userAttribDecl = sc->userAttribDecl; - - // TypeTraits needs to know if it's located in an AliasDeclaration - sc->flags |= SCOPEalias; - - if (aliassym) - { - FuncDeclaration *fd = aliassym->isFuncLiteralDeclaration(); - TemplateDeclaration *td = aliassym->isTemplateDeclaration(); - if (fd || (td && td->literal)) - { - if (fd && fd->semanticRun >= PASSsemanticdone) - { - sc->flags &= ~SCOPEalias; - return; - } - - Expression *e = new FuncExp(loc, aliassym); - e = ::semantic(e, sc); - if (e->op == TOKfunction) - { - FuncExp *fe = (FuncExp *)e; - aliassym = fe->td ? (Dsymbol *)fe->td : fe->fd; - } - else - { - aliassym = NULL; - type = Type::terror; - } - sc->flags &= ~SCOPEalias; - return; - } - - if (aliassym->isTemplateInstance()) - aliassym->semantic(sc); - sc->flags &= ~SCOPEalias; - return; - } - inuse = 1; - - // Given: - // alias foo.bar.abc def; - // it is not knowable from the syntax whether this is an alias - // for a type or an alias for a symbol. It is up to the semantic() - // pass to distinguish. - // If it is a type, then type is set and getType() will return that - // type. If it is a symbol, then aliassym is set and type is NULL - - // toAlias() will return aliasssym. - - unsigned int errors = global.errors; - Type *oldtype = type; - - // Ungag errors when not instantiated DeclDefs scope alias - Ungag ungag(global.gag); - //printf("%s parent = %s, gag = %d, instantiated = %d\n", toChars(), parent, global.gag, isInstantiated()); - if (parent && global.gag && !isInstantiated() && !toParent2()->isFuncDeclaration()) - { - //printf("%s type = %s\n", toPrettyChars(), type->toChars()); - global.gag = 0; - } - - /* This section is needed because Type::resolve() will: - * const x = 3; - * alias y = x; - * try to convert identifier x to 3. - */ - Dsymbol *s = type->toDsymbol(sc); - if (errors != global.errors) - { - s = NULL; - type = Type::terror; - } - if (s && s == this) - { - error("cannot resolve"); - s = NULL; - type = Type::terror; - } - if (!s || !s->isEnumMember()) - { - Type *t; - Expression *e; - Scope *sc2 = sc; - if (storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable)) - { - // For 'ref' to be attached to function types, and picked - // up by Type::resolve(), it has to go into sc. - sc2 = sc->push(); - sc2->stc |= storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCshared | STCdisable); - } - type = type->addSTC(storage_class); - type->resolve(loc, sc2, &e, &t, &s); - if (sc2 != sc) - sc2->pop(); - - if (e) // Try to convert Expression to Dsymbol - { - s = getDsymbol(e); - if (!s) - { - if (e->op != TOKerror) - error("cannot alias an expression %s", e->toChars()); - t = Type::terror; - } - } - type = t; - } - if (s == this) - { - assert(global.errors); - type = Type::terror; - s = NULL; - } - if (!s) // it's a type alias - { - //printf("alias %s resolved to type %s\n", toChars(), type->toChars()); - type = type->semantic(loc, sc); - aliassym = NULL; - } - else // it's a symbolic alias - { - //printf("alias %s resolved to %s %s\n", toChars(), s->kind(), s->toChars()); - type = NULL; - aliassym = s; - } - if (global.gag && errors != global.errors) - { - type = oldtype; - aliassym = NULL; - } - inuse = 0; - semanticRun = PASSsemanticdone; - - if (Dsymbol *sx = overnext) - { - overnext = NULL; - - if (!overloadInsert(sx)) - ScopeDsymbol::multiplyDefined(Loc(), sx, this); - } - sc->flags &= ~SCOPEalias; -} - bool AliasDeclaration::overloadInsert(Dsymbol *s) { //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n", @@ -684,7 +509,7 @@ Dsymbol *AliasDeclaration::toAlias() } else { - Type *t = type->semantic(loc, _scope); + Type *t = typeSemantic(type, loc, _scope); if (t->ty == Terror) goto Lerr; if (global.errors != olderrors) @@ -723,11 +548,11 @@ Dsymbol *AliasDeclaration::toAlias() /* If this is an internal alias for selective/renamed import, * load the module first. */ - _import->semantic(NULL); + dsymbolSemantic(_import, NULL); } if (_scope) { - aliasSemantic(_scope); + aliasSemantic(this, _scope); } } @@ -783,10 +608,6 @@ const char *OverDeclaration::kind() const return "overload alias"; // todo } -void OverDeclaration::semantic(Scope *) -{ -} - bool OverDeclaration::equals(RootObject *o) { if (this == o) @@ -922,852 +743,6 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) return v; } - -void VarDeclaration::semantic(Scope *sc) -{ -// if (semanticRun > PASSinit) -// return; -// semanticRun = PASSsemantic; - - if (semanticRun >= PASSsemanticdone) - return; - - Scope *scx = NULL; - if (_scope) - { - sc = _scope; - scx = sc; - _scope = NULL; - } - - if (!sc) - return; - - semanticRun = PASSsemantic; - - /* Pick up storage classes from context, but except synchronized, - * override, abstract, and final. - */ - storage_class |= (sc->stc & ~(STCsynchronized | STCoverride | STCabstract | STCfinal)); - if (storage_class & STCextern && _init) - error("extern symbols cannot have initializers"); - - userAttribDecl = sc->userAttribDecl; - - AggregateDeclaration *ad = isThis(); - if (ad) - storage_class |= ad->storage_class & STC_TYPECTOR; - - /* If auto type inference, do the inference - */ - int inferred = 0; - if (!type) - { - inuse++; - - // Infering the type requires running semantic, - // so mark the scope as ctfe if required - bool needctfe = (storage_class & (STCmanifest | STCstatic)) != 0; - if (needctfe) sc = sc->startCTFE(); - - //printf("inferring type for %s with init %s\n", toChars(), _init->toChars()); - _init = inferType(_init, sc); - type = initializerToExpression(_init)->type; - - if (needctfe) sc = sc->endCTFE(); - - inuse--; - inferred = 1; - - /* This is a kludge to support the existing syntax for RAII - * declarations. - */ - storage_class &= ~STCauto; - originalType = type->syntaxCopy(); - } - else - { - if (!originalType) - originalType = type->syntaxCopy(); - - /* Prefix function attributes of variable declaration can affect - * its type: - * pure nothrow void function() fp; - * static assert(is(typeof(fp) == void function() pure nothrow)); - */ - Scope *sc2 = sc->push(); - sc2->stc |= (storage_class & STC_FUNCATTR); - inuse++; - type = type->semantic(loc, sc2); - inuse--; - sc2->pop(); - } - //printf(" semantic type = %s\n", type ? type->toChars() : "null"); - if (type->ty == Terror) - errors = true; - - type->checkDeprecated(loc, sc); - linkage = sc->linkage; - this->parent = sc->parent; - //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); - protection = sc->protection; - - /* If scope's alignment is the default, use the type's alignment, - * otherwise the scope overrrides. - */ - alignment = sc->alignment(); - if (alignment == STRUCTALIGN_DEFAULT) - alignment = type->alignment(); // use type's alignment - - //printf("sc->stc = %x\n", sc->stc); - //printf("storage_class = x%x\n", storage_class); - - if (global.params.vcomplex) - type->checkComplexTransition(loc); - - // Calculate type size + safety checks - if (sc->func && !sc->intypeof) - { - if ((storage_class & STCgshared) && !isMember()) - { - if (sc->func->setUnsafe()) - error("__gshared not allowed in safe functions; use shared"); - } - } - - Dsymbol *parent = toParent(); - - Type *tb = type->toBasetype(); - Type *tbn = tb->baseElemOf(); - if (tb->ty == Tvoid && !(storage_class & STClazy)) - { - if (inferred) - { - error("type %s is inferred from initializer %s, and variables cannot be of type void", - type->toChars(), _init->toChars()); - } - else - error("variables cannot be of type void"); - type = Type::terror; - tb = type; - } - if (tb->ty == Tfunction) - { - error("cannot be declared to be a function"); - type = Type::terror; - tb = type; - } - if (tb->ty == Tstruct) - { - TypeStruct *ts = (TypeStruct *)tb; - if (!ts->sym->members) - { - error("no definition of struct %s", ts->toChars()); - } - } - if ((storage_class & STCauto) && !inferred) - error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?"); - - if (tb->ty == Ttuple) - { - /* Instead, declare variables for each of the tuple elements - * and add those. - */ - TypeTuple *tt = (TypeTuple *)tb; - size_t nelems = Parameter::dim(tt->arguments); - Expression *ie = (_init && !_init->isVoidInitializer()) ? initializerToExpression(_init) : NULL; - if (ie) - ie = ::semantic(ie, sc); - - if (nelems > 0 && ie) - { - Expressions *iexps = new Expressions(); - iexps->push(ie); - - Expressions *exps = new Expressions(); - - for (size_t pos = 0; pos < iexps->length; pos++) - { - Lexpand1: - Expression *e = (*iexps)[pos]; - Parameter *arg = Parameter::getNth(tt->arguments, pos); - arg->type = arg->type->semantic(loc, sc); - //printf("[%d] iexps->length = %d, ", pos, iexps->length); - //printf("e = (%s %s, %s), ", Token::tochars[e->op], e->toChars(), e->type->toChars()); - //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars()); - - if (e != ie) - { - if (iexps->length > nelems) - goto Lnomatch; - if (e->type->implicitConvTo(arg->type)) - continue; - } - - if (e->op == TOKtuple) - { - TupleExp *te = (TupleExp *)e; - if (iexps->length - 1 + te->exps->length > nelems) - goto Lnomatch; - - iexps->remove(pos); - iexps->insert(pos, te->exps); - (*iexps)[pos] = Expression::combine(te->e0, (*iexps)[pos]); - goto Lexpand1; - } - else if (isAliasThisTuple(e)) - { - VarDeclaration *v = copyToTemp(0, "__tup", e); - v->semantic(sc); - VarExp *ve = new VarExp(loc, v); - ve->type = e->type; - - exps->setDim(1); - (*exps)[0] = ve; - expandAliasThisTuples(exps, 0); - - for (size_t u = 0; u < exps->length ; u++) - { - Lexpand2: - Expression *ee = (*exps)[u]; - arg = Parameter::getNth(tt->arguments, pos + u); - arg->type = arg->type->semantic(loc, sc); - //printf("[%d+%d] exps->length = %d, ", pos, u, exps->length); - //printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars()); - //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars()); - - size_t iexps_dim = iexps->length - 1 + exps->length; - if (iexps_dim > nelems) - goto Lnomatch; - if (ee->type->implicitConvTo(arg->type)) - continue; - - if (expandAliasThisTuples(exps, u) != -1) - goto Lexpand2; - } - - if ((*exps)[0] != ve) - { - Expression *e0 = (*exps)[0]; - (*exps)[0] = new CommaExp(loc, new DeclarationExp(loc, v), e0); - (*exps)[0]->type = e0->type; - - iexps->remove(pos); - iexps->insert(pos, exps); - goto Lexpand1; - } - } - } - if (iexps->length < nelems) - goto Lnomatch; - - ie = new TupleExp(_init->loc, iexps); - } -Lnomatch: - - if (ie && ie->op == TOKtuple) - { - TupleExp *te = (TupleExp *)ie; - size_t tedim = te->exps->length; - if (tedim != nelems) - { - ::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems); - for (size_t u = tedim; u < nelems; u++) // fill dummy expression - te->exps->push(new ErrorExp()); - } - } - - Objects *exps = new Objects(); - exps->setDim(nelems); - for (size_t i = 0; i < nelems; i++) - { - Parameter *arg = Parameter::getNth(tt->arguments, i); - - OutBuffer buf; - buf.printf("__%s_field_%llu", ident->toChars(), (ulonglong)i); - const char *name = buf.extractChars(); - Identifier *id = Identifier::idPool(name); - - Initializer *ti; - if (ie) - { - Expression *einit = ie; - if (ie->op == TOKtuple) - { - TupleExp *te = (TupleExp *)ie; - einit = (*te->exps)[i]; - if (i == 0) - einit = Expression::combine(te->e0, einit); - } - ti = new ExpInitializer(einit->loc, einit); - } - else - ti = _init ? _init->syntaxCopy() : NULL; - - VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti); - v->storage_class |= STCtemp | storage_class; - if (arg->storageClass & STCparameter) - v->storage_class |= arg->storageClass; - //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); - v->semantic(sc); - - if (sc->scopesym) - { - //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); - if (sc->scopesym->members) - sc->scopesym->members->push(v); - } - - Expression *e = new DsymbolExp(loc, v); - (*exps)[i] = e; - } - TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); - v2->parent = this->parent; - v2->isexp = true; - aliassym = v2; - semanticRun = PASSsemanticdone; - return; - } - - /* Storage class can modify the type - */ - type = type->addStorageClass(storage_class); - - /* Adjust storage class to reflect type - */ - if (type->isConst()) - { - storage_class |= STCconst; - if (type->isShared()) - storage_class |= STCshared; - } - else if (type->isImmutable()) - storage_class |= STCimmutable; - else if (type->isShared()) - storage_class |= STCshared; - else if (type->isWild()) - storage_class |= STCwild; - - if (StorageClass stc = storage_class & (STCsynchronized | STCoverride | STCabstract | STCfinal)) - { - if (stc == STCfinal) - error("cannot be final, perhaps you meant const?"); - else - { - OutBuffer buf; - stcToBuffer(&buf, stc); - error("cannot be %s", buf.peekChars()); - } - storage_class &= ~stc; // strip off - } - - if (storage_class & STCscope) - { - StorageClass stc = storage_class & (STCstatic | STCextern | STCmanifest | STCtls | STCgshared); - if (stc) - { - OutBuffer buf; - stcToBuffer(&buf, stc); - error("cannot be 'scope' and '%s'", buf.peekChars()); - } - else if (isMember()) - { - error("field cannot be 'scope'"); - } - else if (!type->hasPointers()) - { - storage_class &= ~STCscope; // silently ignore; may occur in generic code - } - } - - if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe)) - { - } - else - { - AggregateDeclaration *aad = parent->isAggregateDeclaration(); - if (aad) - { - if (global.params.vfield && - storage_class & (STCconst | STCimmutable) && _init && !_init->isVoidInitializer()) - { - const char *s = (storage_class & STCimmutable) ? "immutable" : "const"; - message(loc, "`%s.%s` is `%s` field", ad->toPrettyChars(), toChars(), s); - } - storage_class |= STCfield; - if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor) - { - if (!isThisDeclaration() && !_init) - aad->noDefaultCtor = true; - } - } - - InterfaceDeclaration *id = parent->isInterfaceDeclaration(); - if (id) - { - error("field not allowed in interface"); - } - else if (aad && aad->sizeok == SIZEOKdone) - { - error("cannot be further field because it will change the determined %s size", aad->toChars()); - } - - /* Templates cannot add fields to aggregates - */ - TemplateInstance *ti = parent->isTemplateInstance(); - if (ti) - { - // Take care of nested templates - while (1) - { - TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); - if (!ti2) - break; - ti = ti2; - } - - // If it's a member template - AggregateDeclaration *ad2 = ti->tempdecl->isMember(); - if (ad2 && storage_class != STCundefined) - { - error("cannot use template to add field to aggregate '%s'", ad2->toChars()); - } - } - } - - if ((storage_class & (STCref | STCparameter | STCforeach | STCtemp | STCresult)) == STCref && ident != Id::This) - { - error("only parameters or foreach declarations can be ref"); - } - - if (type->hasWild()) - { - if (storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield) || - isDataseg() - ) - { - error("only parameters or stack based variables can be inout"); - } - FuncDeclaration *func = sc->func; - if (func) - { - if (func->fes) - func = func->fes->func; - bool isWild = false; - for (FuncDeclaration *fd = func; fd; fd = fd->toParent2()->isFuncDeclaration()) - { - if (((TypeFunction *)fd->type)->iswild) - { - isWild = true; - break; - } - } - if (!isWild) - { - error("inout variables can only be declared inside inout functions"); - } - } - } - - if (!(storage_class & (STCctfe | STCref | STCresult)) && tbn->ty == Tstruct && - ((TypeStruct *)tbn)->sym->noDefaultCtor) - { - if (!_init) - { - if (isField()) - { - /* For fields, we'll check the constructor later to make sure it is initialized - */ - storage_class |= STCnodefaultctor; - } - else if (storage_class & STCparameter) - ; - else - error("default construction is disabled for type %s", type->toChars()); - } - } - - FuncDeclaration *fd = parent->isFuncDeclaration(); - if (type->isscope() && !(storage_class & STCnodtor)) - { - if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd) - { - error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope"); - } - - if (!(storage_class & STCscope)) - { - if (!(storage_class & STCparameter) && ident != Id::withSym) - error("reference to scope class must be scope"); - } - } - - // Calculate type size + safety checks - if (sc->func && !sc->intypeof) - { - if (_init && _init->isVoidInitializer() && type->hasPointers()) // get type size - { - if (sc->func->setUnsafe()) - error("void initializers for pointers not allowed in safe functions"); - } - else if (!_init && - !(storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield | STCparameter)) && - type->hasVoidInitPointers()) - { - if (sc->func->setUnsafe()) - error("void initializers for pointers not allowed in safe functions"); - } - } - - if (!_init && !fd) - { - // If not mutable, initializable by constructor only - storage_class |= STCctorinit; - } - - if (_init) - storage_class |= STCinit; // remember we had an explicit initializer - else if (storage_class & STCmanifest) - error("manifest constants must have initializers"); - - bool isBlit = false; - d_uns64 sz = 0; - if (!_init && !sc->inunion && !(storage_class & (STCstatic | STCgshared | STCextern)) && fd && - (!(storage_class & (STCfield | STCin | STCforeach | STCparameter | STCresult)) - || (storage_class & STCout)) && - (sz = type->size()) != 0) - { - // Provide a default initializer - //printf("Providing default initializer for '%s'\n", toChars()); - if (sz == SIZE_INVALID && type->ty != Terror) - error("size of type %s is invalid", type->toChars()); - - Type *tv = type; - while (tv->ty == Tsarray) // Don't skip Tenum - tv = tv->nextOf(); - if (tv->needsNested()) - { - /* Nested struct requires valid enclosing frame pointer. - * In StructLiteralExp::toElem(), it's calculated. - */ - assert(tv->toBasetype()->ty == Tstruct); - checkFrameAccess(loc, sc, ((TypeStruct *)tbn)->sym); - - Expression *e = tv->defaultInitLiteral(loc); - e = new BlitExp(loc, new VarExp(loc, this), e); - e = ::semantic(e, sc); - _init = new ExpInitializer(loc, e); - goto Ldtor; - } - if (tv->ty == Tstruct && ((TypeStruct *)tv)->sym->zeroInit == 1) - { - /* If a struct is all zeros, as a special case - * set it's initializer to the integer 0. - * In AssignExp::toElem(), we check for this and issue - * a memset() to initialize the struct. - * Must do same check in interpreter. - */ - Expression *e = new IntegerExp(loc, 0, Type::tint32); - e = new BlitExp(loc, new VarExp(loc, this), e); - e->type = type; // don't type check this, it would fail - _init = new ExpInitializer(loc, e); - goto Ldtor; - } - if (type->baseElemOf()->ty == Tvoid) - { - error("%s does not have a default initializer", type->toChars()); - } - else if (Expression *e = type->defaultInit(loc)) - { - _init = new ExpInitializer(loc, e); - } - // Default initializer is always a blit - isBlit = true; - } - - if (_init) - { - sc = sc->push(); - sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCnogc | STCref | STCdisable); - - ExpInitializer *ei = _init->isExpInitializer(); - if (ei) // Bugzilla 13424: Preset the required type to fail in FuncLiteralDeclaration::semantic3 - ei->exp = inferType(ei->exp, type); - - // If inside function, there is no semantic3() call - if (sc->func || sc->intypeof == 1) - { - // If local variable, use AssignExp to handle all the various - // possibilities. - if (fd && - !(storage_class & (STCmanifest | STCstatic | STCtls | STCgshared | STCextern)) && - !_init->isVoidInitializer()) - { - //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); - if (!ei) - { - ArrayInitializer *ai = _init->isArrayInitializer(); - Expression *e; - if (ai && tb->ty == Taarray) - e = ai->toAssocArrayLiteral(); - else - e = initializerToExpression(_init); - if (!e) - { - // Run semantic, but don't need to interpret - _init = ::semantic(_init, sc, type, INITnointerpret); - e = initializerToExpression(_init); - if (!e) - { - error("is not a static and cannot have static initializer"); - e = new ErrorExp(); - } - } - ei = new ExpInitializer(_init->loc, e); - _init = ei; - } - - Expression *exp = ei->exp; - Expression *e1 = new VarExp(loc, this); - if (isBlit) - exp = new BlitExp(loc, e1, exp); - else - exp = new ConstructExp(loc, e1, exp); - canassign++; - exp = ::semantic(exp, sc); - canassign--; - exp = exp->optimize(WANTvalue); - - if (exp->op == TOKerror) - { - _init = new ErrorInitializer(); - ei = NULL; - } - else - ei->exp = exp; - - if (ei && isScope()) - { - Expression *ex = ei->exp; - while (ex->op == TOKcomma) - ex = ((CommaExp *)ex)->e2; - if (ex->op == TOKblit || ex->op == TOKconstruct) - ex = ((AssignExp *)ex)->e2; - if (ex->op == TOKnew) - { - // See if initializer is a NewExp that can be allocated on the stack - NewExp *ne = (NewExp *)ex; - if (type->toBasetype()->ty == Tclass) - { - if (ne->newargs && ne->newargs->length > 1) - { - mynew = true; - } - else - { - ne->onstack = true; - onstack = true; - } - } - } - else if (ex->op == TOKfunction) - { - // or a delegate that doesn't escape a reference to the function - FuncDeclaration *f = ((FuncExp *)ex)->fd; - f->tookAddressOf--; - } - } - } - else - { - // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof - _init = ::semantic(_init, sc, type, sc->intypeof == 1 ? INITnointerpret : INITinterpret); - } - } - else if (parent->isAggregateDeclaration()) - { - _scope = scx ? scx : sc->copy(); - _scope->setNoFree(); - } - else if (storage_class & (STCconst | STCimmutable | STCmanifest) || - type->isConst() || type->isImmutable()) - { - /* Because we may need the results of a const declaration in a - * subsequent type, such as an array dimension, before semantic2() - * gets ordinarily run, try to run semantic2() now. - * Ignore failure. - */ - - if (!inferred) - { - unsigned errors = global.errors; - inuse++; - if (ei) - { - Expression *exp = ei->exp->syntaxCopy(); - - bool needctfe = isDataseg() || (storage_class & STCmanifest); - if (needctfe) sc = sc->startCTFE(); - exp = ::semantic(exp, sc); - exp = resolveProperties(sc, exp); - if (needctfe) sc = sc->endCTFE(); - - Type *tb2 = type->toBasetype(); - Type *ti = exp->type->toBasetype(); - - /* The problem is the following code: - * struct CopyTest { - * double x; - * this(double a) { x = a * 10.0;} - * this(this) { x += 2.0; } - * } - * const CopyTest z = CopyTest(5.3); // ok - * const CopyTest w = z; // not ok, postblit not run - * static assert(w.x == 55.0); - * because the postblit doesn't get run on the initialization of w. - */ - if (ti->ty == Tstruct) - { - StructDeclaration *sd = ((TypeStruct *)ti)->sym; - /* Look to see if initializer involves a copy constructor - * (which implies a postblit) - */ - // there is a copy constructor - // and exp is the same struct - if (sd->postblit && - tb2->toDsymbol(NULL) == sd) - { - // The only allowable initializer is a (non-copy) constructor - if (exp->isLvalue()) - error("of type struct %s uses this(this), which is not allowed in static initialization", tb2->toChars()); - } - } - ei->exp = exp; - } - _init = ::semantic(_init, sc, type, INITinterpret); - inuse--; - if (global.errors > errors) - { - _init = new ErrorInitializer(); - type = Type::terror; - } - } - else - { - _scope = scx ? scx : sc->copy(); - _scope->setNoFree(); - } - } - sc = sc->pop(); - } - -Ldtor: - /* Build code to execute destruction, if necessary - */ - edtor = callScopeDtor(sc); - if (edtor) - { - if (sc->func && storage_class & (STCstatic | STCgshared)) - edtor = ::semantic(edtor, sc->_module->_scope); - else - edtor = ::semantic(edtor, sc); - -#if 0 // currently disabled because of std.stdio.stdin, stdout and stderr - if (isDataseg() && !(storage_class & STCextern)) - error("static storage variables cannot have destructors"); -#endif - } - - semanticRun = PASSsemanticdone; - - if (type->toBasetype()->ty == Terror) - errors = true; - - if (sc->scopesym && !sc->scopesym->isAggregateDeclaration()) - { - for (ScopeDsymbol *sym = sc->scopesym; sym && endlinnum == 0; - sym = sym->parent ? sym->parent->isScopeDsymbol() : NULL) - endlinnum = sym->endlinnum; - } -} - -void VarDeclaration::semantic2(Scope *sc) -{ - if (semanticRun < PASSsemanticdone && inuse) - return; - - //printf("VarDeclaration::semantic2('%s')\n", toChars()); - - if (_init && !toParent()->isFuncDeclaration()) - { - inuse++; - // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof - _init = ::semantic(_init, sc, type, sc->intypeof == 1 ? INITnointerpret : INITinterpret); - inuse--; - } - if (_init && storage_class & STCmanifest) - { - /* Cannot initializer enums with CTFE classreferences and addresses of struct literals. - * Scan initializer looking for them. Issue error if found. - */ - if (ExpInitializer *ei = _init->isExpInitializer()) - { - struct EnumInitializer - { - static bool arrayHasInvalidEnumInitializer(Expressions *elems) - { - for (size_t i = 0; i < elems->length; i++) - { - Expression *e = (*elems)[i]; - if (e && hasInvalidEnumInitializer(e)) - return true; - } - return false; - } - - static bool hasInvalidEnumInitializer(Expression *e) - { - if (e->op == TOKclassreference) - return true; - if (e->op == TOKaddress && ((AddrExp *)e)->e1->op == TOKstructliteral) - return true; - if (e->op == TOKarrayliteral) - return arrayHasInvalidEnumInitializer(((ArrayLiteralExp *)e)->elements); - if (e->op == TOKstructliteral) - return arrayHasInvalidEnumInitializer(((StructLiteralExp *)e)->elements); - if (e->op == TOKassocarrayliteral) - { - AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e; - return arrayHasInvalidEnumInitializer(ae->values) || - arrayHasInvalidEnumInitializer(ae->keys); - } - return false; - } - }; - if (EnumInitializer::hasInvalidEnumInitializer(ei->exp)) - error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead."); - } - } - else if (_init && isThreadlocal()) - { - if ((type->ty == Tclass) && type->isMutable() && !type->isShared()) - { - ExpInitializer *ei = _init->isExpInitializer(); - if (ei && ei->exp->op == TOKclassreference) - error("is mutable. Only const or immutable class thread local variable are allowed, not %s", type->toChars()); - } - else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct && type->nextOf()->isMutable() &&!type->nextOf()->isShared()) - { - ExpInitializer *ei = _init->isExpInitializer(); - if (ei && ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral) - { - error("is a pointer to mutable struct. Only pointers to const, immutable or shared struct thread local variable are allowed, not %s", type->toChars()); - } - } - } - semanticRun = PASSsemantic2done; -} - void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) { //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad->toChars(), toChars()); @@ -1863,7 +838,7 @@ Dsymbol *VarDeclaration::toAlias() { //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); if ((!type || !type->deco) && _scope) - semantic(_scope); + dsymbolSemantic(this, _scope); assert(this != aliassym); Dsymbol *s = aliassym ? aliassym->toAlias() : this; @@ -2035,7 +1010,7 @@ Expression *VarDeclaration::getConstInitializer(bool needFullType) if (_scope) { inuse++; - _init = ::semantic(_init, _scope, type, INITinterpret); + _init = initializerSemantic(_init, _scope, type, INITinterpret); _scope = NULL; inuse--; } @@ -2300,11 +1275,6 @@ Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *) return NULL; } -void TypeInfoDeclaration::semantic(Scope *) -{ - assert(linkage == LINKc); -} - const char *TypeInfoDeclaration::toChars() { //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo->toChars()); |