llvm::DIType ldc::DIBuilder::CreateEnumType(Type *type) { llvm::Type *T = DtoType(type); assert(type->ty == Tenum && "only enums allowed for debug info in dwarfEnumType"); TypeEnum *te = static_cast<TypeEnum *>(type); llvm::SmallVector<llvm::Value *, 8> subscripts; for (ArrayIter<Dsymbol> it(te->sym->members); it.more(); it.next()) { EnumMember *em = it->isEnumMember(); llvm::StringRef Name(em->toChars()); uint64_t Val = em->value->toInteger(); llvm::Value *Subscript = DBuilder.createEnumerator(Name, Val); subscripts.push_back(Subscript); } llvm::StringRef Name = te->toChars(); unsigned LineNumber = te->sym->loc.linnum; llvm::DIFile File = CreateFile(te->sym->loc); return DBuilder.createEnumerationType( llvm::DICompileUnit(GetCU()), Name, File, LineNumber, getTypeBitSize(T), // size (bits) getABITypeAlign(T)*8, // align (bits) DBuilder.getOrCreateArray(subscripts) // subscripts #if LDC_LLVM_VER >= 302 , CreateTypeDescription(te->sym->memtype, NULL) #endif ); }
ldc::DIType ldc::DIBuilder::CreateEnumType(Type *type) { llvm::Type *T = DtoType(type); assert(type->ty == Tenum && "only enums allowed for debug info in dwarfEnumType"); TypeEnum *te = static_cast<TypeEnum *>(type); #if LDC_LLVM_VER >= 306 llvm::SmallVector<llvm::Metadata *, 8> subscripts; #else llvm::SmallVector<llvm::Value *, 8> subscripts; #endif for (auto m : *te->sym->members) { EnumMember *em = m->isEnumMember(); llvm::StringRef Name(em->toChars()); uint64_t Val = em->value->toInteger(); auto Subscript = DBuilder.createEnumerator(Name, Val); subscripts.push_back(Subscript); } llvm::StringRef Name = te->toChars(); unsigned LineNumber = te->sym->loc.linnum; ldc::DIFile File(CreateFile(te->sym->loc)); return DBuilder.createEnumerationType( GetCU(), Name, File, LineNumber, getTypeBitSize(T), // size (bits) getABITypeAlign(T) * 8, // align (bits) DBuilder.getOrCreateArray(subscripts), // subscripts CreateTypeDescription(te->sym->memtype, false)); }
void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("enum "); if (ident) { buf->writestring(ident->toChars()); buf->writeByte(' '); } if (memtype) { buf->writestring(": "); memtype->toCBuffer(buf, NULL, hgs); } if (!members) { buf->writeByte(';'); buf->writenl(); return; } buf->writenl(); buf->writeByte('{'); buf->writenl(); buf->level++; for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); if (!em) continue; em->toCBuffer(buf, hgs); buf->writeByte(','); buf->writenl(); } buf->level--; buf->writeByte('}'); buf->writenl(); }
void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { int i; buf->writestring("enum "); if (ident) { buf->writestring(ident->toChars()); buf->writeByte(' '); } if (memtype) { buf->writestring(": "); memtype->toCBuffer(buf, NULL, hgs); } if (!members) { buf->writeByte(';'); buf->writenl(); return; } buf->writenl(); buf->writeByte('{'); buf->writenl(); for (i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); if (!em) continue; //buf->writestring(" "); em->toCBuffer(buf, hgs); buf->writeByte(','); buf->writenl(); } buf->writeByte('}'); buf->writenl(); }
void EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sds) { #if 0 printf("EnumDeclaration::addMember() %s\n", toChars()); for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); printf(" member %s\n", em->toChars()); } #endif /* Anonymous enum members get added to enclosing scope. */ ScopeDsymbol *scopesym = isAnonymous() ? sds : this; if (!isAnonymous()) { ScopeDsymbol::addMember(sc, sds); if (!symtab) symtab = new DsymbolTable(); } if (members) { for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); em->ed = this; //printf("add %s to scope %s\n", em->toChars(), scopesym->toChars()); em->addMember(sc, scopesym); } } added = true; }
ldc::DIType ldc::DIBuilder::CreateEnumType(Type *type) { assert(type->ty == Tenum); llvm::Type *T = DtoType(type); TypeEnum *te = static_cast<TypeEnum *>(type); llvm::SmallVector<LLMetadata *, 8> subscripts; for (auto m : *te->sym->members) { EnumMember *em = m->isEnumMember(); llvm::StringRef Name(em->toChars()); uint64_t Val = em->value()->toInteger(); auto Subscript = DBuilder.createEnumerator(Name, Val); subscripts.push_back(Subscript); } llvm::StringRef Name = te->toChars(); unsigned LineNumber = te->sym->loc.linnum; ldc::DIFile File(CreateFile(te->sym)); return DBuilder.createEnumerationType( GetCU(), Name, File, LineNumber, getTypeAllocSize(T) * 8, // size (bits) getABITypeAlign(T) * 8, // align (bits) DBuilder.getOrCreateArray(subscripts), // subscripts CreateTypeDescription(te->sym->memtype, false)); }
int EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { if (!isAnonymous()) return ScopeDsymbol::addMember(sc, sd, memnum); /* Anonymous enum members get added to enclosing scope. */ for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); em->ed = this; //printf("add %s\n", em->toChars()); em->addMember(sc, sd, 1); } return 1; }
void EnumDeclaration::semantic(Scope *sc) { //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars()); //printf("EnumDeclaration::semantic() %p %s\n", this, toChars()); if (semanticRun >= PASSsemanticdone) return; // semantic() already completed if (semanticRun == PASSsemantic) { assert(memtype); ::error(loc, "circular reference to enum base type %s", memtype->toChars()); errors = true; semanticRun = PASSsemanticdone; return; } unsigned dprogress_save = Module::dprogress; Scope *scx = NULL; if (scope) { sc = scope; scx = scope; // save so we don't make redundant copies scope = NULL; } parent = sc->parent; type = type->semantic(loc, sc); protection = sc->protection; if (sc->stc & STCdeprecated) isdeprecated = true; userAttribDecl = sc->userAttribDecl; semanticRun = PASSsemantic; if (!members && !memtype) // enum ident; { semanticRun = PASSsemanticdone; return; } if (!symtab) symtab = new DsymbolTable(); /* The separate, and distinct, cases are: * 1. enum { ... } * 2. enum : memtype { ... } * 3. enum ident { ... } * 4. enum ident : memtype { ... } * 5. enum ident : memtype; * 6. enum ident; */ if (memtype) { memtype = memtype->semantic(loc, sc); /* Check to see if memtype is forward referenced */ if (memtype->ty == Tenum) { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc); if (!sym->memtype || !sym->members || !sym->symtab || sym->scope) { // memtype is forward referenced, so try again later scope = scx ? scx : sc->copy(); scope->setNoFree(); scope->module->addDeferredSemantic(this); Module::dprogress = dprogress_save; //printf("\tdeferring %s\n", toChars()); semanticRun = PASSinit; return; } } if (memtype->ty == Tvoid) { error("base type must not be void"); memtype = Type::terror; } if (memtype->ty == Terror) { errors = true; if (members) { for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; s->errors = true; // poison all the members } } semanticRun = PASSsemanticdone; return; } } semanticRun = PASSsemanticdone; if (!members) // enum ident : memtype; return; if (members->dim == 0) { error("enum %s must have at least one member", toChars()); errors = true; return; } Module::dprogress++; Scope *sce; if (isAnonymous()) sce = sc; else { sce = sc->push(this); sce->parent = this; } sce = sce->startCTFE(); sce->setNoFree(); // needed for getMaxMinValue() /* Each enum member gets the sce scope */ for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); if (em) em->scope = sce; } if (!added) { /* addMember() is not called when the EnumDeclaration appears as a function statement, * so we have to do what addMember() does and install the enum members in the right symbol * table */ ScopeDsymbol *scopesym = NULL; if (isAnonymous()) { /* Anonymous enum members get added to enclosing scope. */ for (Scope *sct = sce; 1; sct = sct->enclosing) { assert(sct); if (sct->scopesym) { scopesym = sct->scopesym; if (!sct->scopesym->symtab) sct->scopesym->symtab = new DsymbolTable(); break; } } } else { // Otherwise enum members are in the EnumDeclaration's symbol table scopesym = this; } for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); if (em) { em->ed = this; em->addMember(sc, scopesym, 1); } } } for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); if (em) em->semantic(em->scope); } //printf("defaultval = %lld\n", defaultval); //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars()); //printf("members = %s\n", members->toChars()); }
void EnumMember::semantic(Scope *sc) { //printf("EnumMember::semantic() %s\n", toChars()); if (errors || semanticRun >= PASSsemanticdone) return; if (semanticRun == PASSsemantic) { error("circular reference to enum member"); Lerrors: errors = true; semanticRun = PASSsemanticdone; return; } assert(ed); ed->semantic(sc); if (ed->errors) goto Lerrors; if (errors || semanticRun >= PASSsemanticdone) return; semanticRun = PASSsemantic; if (scope) sc = scope; // The first enum member is special bool first = (this == (*ed->members)[0]); if (type) { type = type->semantic(loc, sc); assert(value); // "type id;" is not a valid enum member declaration } if (value) { Expression *e = value; assert(e->dyncast() == DYNCAST_EXPRESSION); e = e->semantic(sc); e = resolveProperties(sc, e); e = e->ctfeInterpret(); if (e->op == TOKerror) goto Lerrors; if (first && !ed->memtype && !ed->isAnonymous()) { ed->memtype = e->type; if (ed->memtype->ty == Terror) { ed->errors = true; goto Lerrors; } if (ed->memtype->ty != Terror) { /* Bugzilla 11746: All of named enum members should have same type * with the first member. If the following members were referenced * during the first member semantic, their types should be unified. */ for (size_t i = 0; i < ed->members->dim; i++) { EnumMember *em = (*ed->members)[i]->isEnumMember(); if (!em || em == this || em->semanticRun < PASSsemanticdone || em->type) continue; //printf("[%d] em = %s, em->semanticRun = %d\n", i, toChars(), em->semanticRun); Expression *e = em->value; e = e->implicitCastTo(sc, ed->memtype); e = e->ctfeInterpret(); e = e->castTo(sc, ed->type); if (e->op == TOKerror) ed->errors = true; em->value = e; } if (ed->errors) { ed->memtype = Type::terror; goto Lerrors; } } } if (ed->memtype && !type) { e = e->implicitCastTo(sc, ed->memtype); e = e->ctfeInterpret(); // save origValue for better json output origValue = e; if (!ed->isAnonymous()) e = e->castTo(sc, ed->type); } else if (type) { e = e->implicitCastTo(sc, type); e = e->ctfeInterpret(); assert(ed->isAnonymous()); // save origValue for better json output origValue = e; } value = e; } else if (first) { Type *t; if (ed->memtype) t = ed->memtype; else { t = Type::tint32; if (!ed->isAnonymous()) ed->memtype = t; } Expression *e = new IntegerExp(loc, 0, Type::tint32); e = e->implicitCastTo(sc, t); e = e->ctfeInterpret(); // save origValue for better json output origValue = e; if (!ed->isAnonymous()) e = e->castTo(sc, ed->type); value = e; } else { /* Find the previous enum member, * and set this to be the previous value + 1 */ EnumMember *emprev = NULL; for (size_t i = 0; i < ed->members->dim; i++) { EnumMember *em = (*ed->members)[i]->isEnumMember(); if (em) { if (em == this) break; emprev = em; } } assert(emprev); if (emprev->semanticRun < PASSsemanticdone) // if forward reference emprev->semantic(emprev->scope); // resolve it if (emprev->errors) goto Lerrors; Expression *eprev = emprev->value; Type *tprev = eprev->type->equals(ed->type) ? ed->memtype : eprev->type; Expression *emax = tprev->getProperty(ed->loc, Id::max, 0); emax = emax->semantic(sc); emax = emax->ctfeInterpret(); // Set value to (eprev + 1). // But first check that (eprev != emax) assert(eprev); Expression *e = new EqualExp(TOKequal, loc, eprev, emax); e = e->semantic(sc); e = e->ctfeInterpret(); if (e->toInteger()) { error("initialization with (%s.%s + 1) causes overflow for type '%s'", emprev->ed->toChars(), emprev->toChars(), ed->type->toBasetype()->toChars()); goto Lerrors; } // Now set e to (eprev + 1) e = new AddExp(loc, eprev, new IntegerExp(loc, 1, Type::tint32)); e = e->semantic(sc); e = e->castTo(sc, eprev->type); e = e->ctfeInterpret(); // save origValue (without cast) for better json output if (e->op != TOKerror) // avoid duplicate diagnostics { assert(emprev->origValue); origValue = new AddExp(loc, emprev->origValue, new IntegerExp(loc, 1, Type::tint32)); origValue = origValue->semantic(sc); origValue = origValue->ctfeInterpret(); } if (e->op == TOKerror) goto Lerrors; if (e->type->isfloating()) { // Check that e != eprev (not always true for floats) Expression *etest = new EqualExp(TOKequal, loc, e, eprev); etest = etest->semantic(sc); etest = etest->ctfeInterpret(); if (etest->toInteger()) { error("has inexact value, due to loss of precision"); goto Lerrors; } } value = e; } assert(origValue); semanticRun = PASSsemanticdone; }
unsigned cv4_Denum(EnumDeclaration *e) { debtyp_t *d,*dt; unsigned nfields,fnamelen; unsigned len; unsigned property; unsigned attribute; int i; const char *id; idx_t typidx; //dbg_printf("cv4_Denum(%s)\n", e->toChars()); property = 0; if (!e->members || !e->memtype) property |= 0x80; // enum is forward referenced id = e->toPrettyChars(); len = 10; d = debtyp_alloc(len + cv_stringbytes(id)); TOWORD(d->data,LF_ENUM); TOWORD(d->data + 4,e->memtype ? cv4_typidx(e->memtype->toCtype()) : 0); TOWORD(d->data + 8,property); len += cv_namestring(d->data + len,id); d->length = 0; // so cv_debtyp() will allocate new typidx = cv_debtyp(d); d->length = len; // restore length // Compute the number of fields, and the length of the fieldlist record nfields = 0; fnamelen = 2; if (e->members) { for (i = 0; i < e->members->dim; i++) { EnumMember *sf = ((Dsymbol *)e->members->data[i])->isEnumMember(); dinteger_t value; if (sf) { value = sf->value->toInteger(); unsigned fnamelen1 = fnamelen; fnamelen += 4 + cv4_numericbytes(value) + cv_stringbytes(sf->toPrettyChars()); /* Optlink dies on longer ones, so just truncate */ if (fnamelen > 0xB000) // 0xB000 found by trial and error { fnamelen = fnamelen1; // back up break; // and skip the rest } nfields++; } } } TOWORD(d->data + 2,nfields); // If forward reference, then field list is 0 if (!e->members) { TOWORD(d->data + 6,0); return typidx; } // Generate fieldlist type record dt = debtyp_alloc(fnamelen); TOWORD(dt->data,LF_FIELDLIST); // And fill it in int j = 2; int fieldi = 0; for (i = 0; i < e->members->dim; i++) { EnumMember *sf = ((Dsymbol *)e->members->data[i])->isEnumMember(); dinteger_t value; if (sf) { fieldi++; if (fieldi > nfields) break; // chop off the rest value = sf->value->toInteger(); TOWORD(dt->data + j,LF_ENUMERATE); attribute = 0; TOWORD(dt->data + j + 2,attribute); cv4_storenumeric(dt->data + j + 4,value); j += 4 + cv4_numericbytes(value); j += cv_namestring(dt->data + j, sf->toPrettyChars()); // If enum is not a member of a class, output enum members as constants // if (!isclassmember(s)) // { // cv4_outsym(sf); // } } } assert(j == fnamelen); TOWORD(d->data + 6,cv_debtyp(dt)); // cv4_outsym(s); return typidx; }
unsigned cv4_Denum(EnumDeclaration *e) { //dbg_printf("cv4_Denum(%s)\n", e->toChars()); unsigned property = 0; if (!e->members || !e->memtype || !e->memtype->isintegral()) property |= 0x80; // enum is forward referenced or non-integer // Compute the number of fields, and the length of the fieldlist record unsigned nfields = 0; unsigned fnamelen = 2; if (!property) { for (size_t i = 0; i < e->members->dim; i++) { EnumMember *sf = (*e->members)[i]->isEnumMember(); if (sf) { dinteger_t value = sf->value->toInteger(); unsigned fnamelen1 = fnamelen; // store only member's simple name fnamelen += 4 + cv4_numericbytes(value) + cv_stringbytes(sf->toChars()); if (config.fulltypes != CV8) { /* Optlink dies on longer ones, so just truncate */ if (fnamelen > 0xB000) // 0xB000 found by trial and error { fnamelen = fnamelen1; // back up break; // and skip the rest } } nfields++; } } } const char *id = e->toPrettyChars(); unsigned len; debtyp_t *d; unsigned memtype = e->memtype ? cv4_typidx(e->memtype->toCtype()) : 0; switch (config.fulltypes) { case CV8: len = 14; d = debtyp_alloc(len + cv_stringbytes(id)); TOWORD(d->data,LF_ENUM_V3); TOLONG(d->data + 6,memtype); TOWORD(d->data + 4,property); len += cv_namestring(d->data + len,id); break; case CV4: len = 10; d = debtyp_alloc(len + cv_stringbytes(id)); TOWORD(d->data,LF_ENUM); TOWORD(d->data + 4,memtype); TOWORD(d->data + 8,property); len += cv_namestring(d->data + len,id); break; default: assert(0); } unsigned length_save = d->length; d->length = 0; // so cv_debtyp() will allocate new idx_t typidx = cv_debtyp(d); d->length = length_save; // restore length TOWORD(d->data + 2,nfields); unsigned fieldlist = 0; if (!property) // if forward reference, then fieldlist is 0 { // Generate fieldlist type record debtyp_t *dt = debtyp_alloc(fnamelen); TOWORD(dt->data,(config.fulltypes == CV8) ? LF_FIELDLIST_V2 : LF_FIELDLIST); // And fill it in unsigned j = 2; unsigned fieldi = 0; for (size_t i = 0; i < e->members->dim; i++) { EnumMember *sf = (*e->members)[i]->isEnumMember(); if (sf) { fieldi++; if (fieldi > nfields) break; // chop off the rest dinteger_t value = sf->value->toInteger(); TOWORD(dt->data + j,(config.fulltypes == CV8) ? LF_ENUMERATE_V3 : LF_ENUMERATE); unsigned attribute = 0; TOWORD(dt->data + j + 2,attribute); cv4_storenumeric(dt->data + j + 4,value); j += 4 + cv4_numericbytes(value); // store only member's simple name j += cv_namestring(dt->data + j, sf->toChars()); // If enum is not a member of a class, output enum members as constants // if (!isclassmember(s)) // { // cv4_outsym(sf); // } } } assert(j == fnamelen); fieldlist = cv_debtyp(dt); } if (config.fulltypes == CV8) TOLONG(d->data + 10,fieldlist); else TOWORD(d->data + 6,fieldlist); // cv4_outsym(s); return typidx; }
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) // 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 (!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; } if (sc->stc & STCdeprecated) isdeprecated = 1; parent = sc->parent; /* 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); printf("\tdeferring %s\n", toChars()); return; } } #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 } 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()); int first = 1; Expression *elast = NULL; for (int i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); Expression *e; 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->semantic(sce); e = e->optimize(WANTvalue | WANTinterpret); if (memtype) { e = e->implicitCastTo(sce, memtype); e = e->optimize(WANTvalue | WANTinterpret); if (!isAnonymous()) e = e->castTo(sce, type); t = memtype; } else if (em->type) { e = e->implicitCastTo(sce, em->type); e = e->optimize(WANTvalue | WANTinterpret); 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->optimize(WANTvalue | WANTinterpret); if (!isAnonymous()) e = e->castTo(sce, type); } else { // Set value to (elast + 1). // But first check that (elast != t.max) assert(elast); e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max)); e = e->semantic(sce); e = e->optimize(WANTvalue | WANTinterpret); 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->semantic(sce); e = e->castTo(sce, elast->type); e = e->optimize(WANTvalue | WANTinterpret); } elast = e; em->value = e; // Add to symbol table only after evaluating 'value' if (isAnonymous()) { /* Anonymous enum members get added to enclosing scope. */ for (Scope *scx = sce; scx; scx = scx->enclosing) { if (scx->scopesym) { if (!scx->scopesym->symtab) scx->scopesym->symtab = new DsymbolTable(); em->addMember(sce, scx->scopesym, 1); break; } } } else em->addMember(sc, this, 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()) { 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->semantic(sce); ec = ec->optimize(WANTvalue | WANTinterpret); if (ec->toInteger()) minval = e; ec = new CmpExp(TOKgt, em->loc, e, maxval); ec = ec->semantic(sce); ec = ec->optimize(WANTvalue | WANTinterpret); 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(); }
void EnumDeclaration::semantic(Scope *sc) { uinteger_t number; Type *t; Scope *sce; //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars()); if (!memtype) memtype = Type::tint32; 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 = 1; parent = sc->scopesym; 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) { error("base enum %s is forward referenced", sym->toChars()); memtype = Type::tint32; } } if (!memtype->isintegral()) { error("base type must be of integral type, not %s", memtype->toChars()); memtype = Type::tint32; } isdone = 1; Module::dprogress++; t = isAnonymous() ? memtype : type; symtab = new DsymbolTable(); sce = sc->push(this); sce->parent = this; number = 0; if (!members) // enum ident; return; if (members->dim == 0) error("enum %s must have at least one member", toChars()); int first = 1; for (size_t i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); Expression *e; 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()); e = em->value; if (e) { assert(e->dyncast() == DYNCAST_EXPRESSION); e = e->semantic(sce); e = e->optimize(WANTvalue); // Need to copy it because we're going to change the type e = e->copy(); e = e->implicitCastTo(sc, memtype); e = e->optimize(WANTvalue); number = e->toInteger(); e->type = t; } else { // Default is the previous number plus 1 // Check for overflow if (!first) { switch (t->toBasetype()->ty) { case Tbool: if (number == 2) goto Loverflow; break; case Tint8: if (number == 128) goto Loverflow; break; case Tchar: case Tuns8: if (number == 256) goto Loverflow; break; case Tint16: if (number == 0x8000) goto Loverflow; break; case Twchar: case Tuns16: if (number == 0x10000) goto Loverflow; break; case Tint32: if (number == 0x80000000) goto Loverflow; break; case Tdchar: case Tuns32: if (number == 0x100000000LL) goto Loverflow; break; case Tint64: if (number == 0x8000000000000000LL) goto Loverflow; break; case Tuns64: if (number == 0) goto Loverflow; break; Loverflow: error("overflow of enum value"); break; default: assert(0); } } e = new IntegerExp(em->loc, number, t); } em->value = e; // Add to symbol table only after evaluating 'value' if (isAnonymous()) { //sce->enclosing->insert(em); for (Scope *sct = sce->enclosing; sct; sct = sct->enclosing) { if (sct->scopesym) { if (!sct->scopesym->symtab) sct->scopesym->symtab = new DsymbolTable(); em->addMember(sce, sct->scopesym, 1); break; } } } else em->addMember(sc, this, 1); if (first) { first = 0; defaultval = number; minval = number; maxval = number; } else if (memtype->isunsigned()) { if (number < minval) minval = number; if (number > maxval) maxval = number; } else { if ((sinteger_t)number < (sinteger_t)minval) minval = number; if ((sinteger_t)number > (sinteger_t)maxval) maxval = number; } number++; } //printf("defaultval = %lld\n", defaultval); sce->pop(); //members->print(); }
bool operator==(const EnumMember& lhs, const EnumMember& rhs) { return (lhs.name() == rhs.name() && lhs.declaringType() == rhs.declaringType() && lhs.type() == rhs.type()); }