aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd/declaration.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d/dmd/declaration.c')
-rw-r--r--gcc/d/dmd/declaration.c1046
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());