void AggregateDeclaration::semantic3(Scope *sc) { #if IN_LLVM if (!global.inExtraInliningSemantic) availableExternally = false; #endif //printf("AggregateDeclaration::semantic3(%s)\n", toChars()); if (members) { sc = sc->push(this); sc->parent = this; for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; s->semantic3(sc); } if (StructDeclaration *sd = isStructDeclaration()) { //if (sd->xeq != NULL) printf("sd = %s xeq @ [%s]\n", sd->toChars(), sd->loc.toChars()); //assert(sd->xeq == NULL); if (sd->xeq == NULL) sd->xeq = sd->buildXopEquals(sc); } sc = sc->pop(); if (!getRTInfo && Type::rtinfo && (!isDeprecated() || global.params.useDeprecated) && // don't do it for unused deprecated types (type && type->ty != Terror)) // or error types { // Evaluate: gcinfo!type Objects *tiargs = new Objects(); tiargs->push(type); TemplateInstance *ti = new TemplateInstance(loc, Type::rtinfo, tiargs); ti->semantic(sc); ti->semantic2(sc); ti->semantic3(sc); Dsymbol *s = ti->toAlias(); Expression *e = new DsymbolExp(Loc(), s, 0); e = e->ctfeSemantic(ti->tempdecl->scope); e = e->ctfeInterpret(); getRTInfo = e; } } }
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { size_t length; const unsigned amax = 0x80000000; bool errors = false; //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); if (sem) // if semantic() already run return this; sem = 1; type = t; Initializer *aa = NULL; t = t->toBasetype(); switch (t->ty) { case Tpointer: case Tsarray: case Tarray: break; case Tvector: t = ((TypeVector *)t)->basetype; break; case Taarray: // was actually an associative array literal aa = new ExpInitializer(loc, toAssocArrayLiteral()); return aa->semantic(sc, t, needInterpret); default: error(loc, "cannot use array to initialize %s", type->toChars()); goto Lerr; } length = 0; for (size_t i = 0; i < index.dim; i++) { Expression *idx = index[i]; if (idx) { idx = idx->ctfeSemantic(sc); idx = idx->ctfeInterpret(); index[i] = idx; length = idx->toInteger(); if (idx->op == TOKerror) errors = true; } Initializer *val = value[i]; ExpInitializer *ei = val->isExpInitializer(); if (ei && !idx) ei->expandTuples = 1; val = val->semantic(sc, t->nextOf(), needInterpret); if (val->isErrorInitializer()) errors = true; ei = val->isExpInitializer(); // found a tuple, expand it if (ei && ei->exp->op == TOKtuple) { TupleExp *te = (TupleExp *)ei->exp; index.remove(i); value.remove(i); for (size_t j = 0; j < te->exps->dim; ++j) { Expression *e = (*te->exps)[j]; index.insert(i + j, (Expression *)NULL); value.insert(i + j, new ExpInitializer(e->loc, e)); } i--; continue; } else { value[i] = val; } length++; if (length == 0) { error(loc, "array dimension overflow"); goto Lerr; } if (length > dim) dim = length; } if (t->ty == Tsarray) { dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { error(loc, "array initializer has %u elements, but array length is %lld", dim, edim); goto Lerr; } } if (errors) goto Lerr; if ((uinteger_t) dim * t->nextOf()->size() >= amax) { error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size())); goto Lerr; } return this; Lerr: return new ErrorInitializer(); }
void EnumDeclaration::semantic(Scope *sc) { Type *t; Scope *sce; //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars()); //printf("EnumDeclaration::semantic() %s\n", toChars()); if (!members && !memtype) // enum ident; return; if (!memtype && !isAnonymous()) { // Set memtype if we can to reduce fwd reference errors memtype = Type::tint32; // case 1) enum ident { ... } } if (symtab) // if already done { if (isdone || !scope) return; // semantic() already completed } else symtab = new DsymbolTable(); Scope *scx = NULL; if (scope) { sc = scope; scx = scope; // save so we don't make redundant copies scope = NULL; } unsigned dprogress_save = Module::dprogress; if (sc->stc & STCdeprecated) isdeprecated = true; userAttributes = sc->userAttributes; parent = sc->parent; protection = sc->protection; /* The separate, and distinct, cases are: * 1. enum { ... } * 2. enum : memtype { ... } * 3. enum ident { ... } * 4. enum ident : memtype { ... } */ if (memtype) { memtype = memtype->semantic(loc, sc); /* Check to see if memtype is forward referenced */ if (memtype->ty == Tenum) { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc); if (!sym->memtype || !sym->members || !sym->symtab || sym->scope) { // memtype is forward referenced, so try again later scope = scx ? scx : new Scope(*sc); scope->setNoFree(); scope->module->addDeferredSemantic(this); Module::dprogress = dprogress_save; //printf("\tdeferring %s\n", toChars()); return; } } if (memtype->ty == Tvoid) { error("base type must not be void"); memtype = Type::terror; } #if 0 // Decided to abandon this restriction for D 2.0 if (!memtype->isintegral()) { error("base type must be of integral type, not %s", memtype->toChars()); memtype = Type::tint32; } #endif } isdone = 1; if (!members) // enum ident : memtype; return; Module::dprogress++; type = type->semantic(loc, sc); if (isAnonymous()) sce = sc; else { sce = sc->push(this); sce->parent = this; } if (members->dim == 0) error("enum %s must have at least one member", toChars()); ScopeDsymbol *scopesym; if (isAnonymous()) { /* Anonymous enum members get added to enclosing scope. */ for (Scope *sct = sce; sct; sct = sct->enclosing) { if (sct->scopesym) { scopesym = sct->scopesym; if (!sct->scopesym->symtab) sct->scopesym->symtab = new DsymbolTable(); break; } } } else scopesym = this; int first = 1; Expression *elast = NULL; for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); Expression *e; Expression *emax = NULL; if (!em) /* The e->semantic(sce) can insert other symbols, such as * template instances and function literals. */ continue; //printf(" Enum member '%s'\n",em->toChars()); if (em->type) em->type = em->type->semantic(em->loc, sce); e = em->value; if (e) { assert(e->dyncast() == DYNCAST_EXPRESSION); e = e->ctfeSemantic(sce); e = e->ctfeInterpret(); if (memtype) { e = e->implicitCastTo(sce, memtype); e = e->ctfeInterpret(); if (!isAnonymous()) e = e->castTo(sce, type); t = memtype; } else if (em->type) { e = e->implicitCastTo(sce, em->type); e = e->ctfeInterpret(); assert(isAnonymous()); t = e->type; } else t = e->type; } else if (first) { if (memtype) t = memtype; else if (em->type) t = em->type; else t = Type::tint32; e = new IntegerExp(em->loc, 0, Type::tint32); e = e->implicitCastTo(sce, t); e = e->ctfeInterpret(); if (!isAnonymous()) e = e->castTo(sce, type); } else if (memtype && memtype == Type::terror) { e = new ErrorExp(); minval = e; maxval = e; defaultval = e; } else { // Lazily evaluate enum.max if (!emax) { emax = t->getProperty(Loc(), Id::max, 0); emax = emax->ctfeSemantic(sce); emax = emax->ctfeInterpret(); } // Set value to (elast + 1). // But first check that (elast != t.max) assert(elast); e = new EqualExp(TOKequal, em->loc, elast, emax); e = e->ctfeSemantic(sce); e = e->ctfeInterpret(); if (e->toInteger()) error("overflow of enum value %s", elast->toChars()); // Now set e to (elast + 1) e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32)); e = e->ctfeSemantic(sce); e = e->castTo(sce, elast->type); e = e->ctfeInterpret(); if (t->isfloating()) { // Check that e != elast (not always true for floats) Expression *etest = new EqualExp(TOKequal, em->loc, e, elast); etest = etest->ctfeSemantic(sce); etest = etest->ctfeInterpret(); if (etest->toInteger()) error("enum member %s has inexact value, due to loss of precision", em->toChars()); } } elast = e; em->value = e; // Add to symbol table only after evaluating 'value' if (isAnonymous() && !sc->func) { // already inserted to enclosing scope in addMember assert(em->ed); } else { em->ed = this; em->addMember(sc, scopesym, 1); } /* Compute .min, .max and .default values. * If enum doesn't have a name, we can never identify the enum type, * so there is no purpose for a .min, .max or .default */ if (!isAnonymous() && memtype != Type::terror) { if (first) { defaultval = e; minval = e; maxval = e; } else { Expression *ec; /* In order to work successfully with UDTs, * build expressions to do the comparisons, * and let the semantic analyzer and constant * folder give us the result. */ // Compute if(e < minval) ec = new CmpExp(TOKlt, em->loc, e, minval); ec = ec->ctfeSemantic(sce); ec = ec->ctfeInterpret(); if (ec->toInteger()) minval = e; ec = new CmpExp(TOKgt, em->loc, e, maxval); ec = ec->ctfeSemantic(sce); ec = ec->ctfeInterpret(); if (ec->toInteger()) maxval = e; } } first = 0; } //printf("defaultval = %lld\n", defaultval); //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars()); if (sc != sce) sce->pop(); //members->print(); }