Beispiel #1
0
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;
        }
    }
}
Beispiel #2
0
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();
}
Beispiel #3
0
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();
}