Example #1
0
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
    );
}
Example #2
0
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));
}
Example #3
0
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();
}
Example #4
0
File: enum.c Project: Geod24/dnet
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();
}
Example #5
0
File: enum.c Project: Arpit007/dmd
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;
}
Example #6
0
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));
}
Example #7
0
File: enum.c Project: andralex/dmd
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;
}
Example #8
0
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());
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
File: enum.c Project: Geod24/dnet
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();
}
Example #13
0
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();
}
Example #14
0
bool operator==(const EnumMember& lhs, const EnumMember& rhs)
{
    return (lhs.name() == rhs.name() && lhs.declaringType() == rhs.declaringType() && lhs.type() == rhs.type());
}