diff options
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()); |