예제 #1
0
파일: init.c 프로젝트: kryptonX/dmd
Expression *ArrayInitializer::toExpression()
{   Expressions *elements;

    //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
    //static int i; if (++i == 2) halt();

    size_t edim;
    Type *t = NULL;
    if (type)
    {
        if (type == Type::terror)
            return new ErrorExp();

        t = type->toBasetype();
        switch (t->ty)
        {
           case Tsarray:
               edim = ((TypeSArray *)t)->dim->toInteger();
               break;

           case Tpointer:
           case Tarray:
               edim = dim;
               break;

           default:
               assert(0);
        }
    }
    else
    {
        edim = value.dim;
        for (size_t i = 0, j = 0; i < value.dim; i++, j++)
        {
            if (index.tdata()[i])
                j = index.tdata()[i]->toInteger();
            if (j >= edim)
                edim = j + 1;
        }
    }

    elements = new Expressions();
    elements->setDim(edim);
    elements->zero();
    for (size_t i = 0, j = 0; i < value.dim; i++, j++)
    {
        if (index.tdata()[i])
            j = (index.tdata()[i])->toInteger();
        assert(j < edim);
        Initializer *iz = value.tdata()[i];
        if (!iz)
            goto Lno;
        Expression *ex = iz->toExpression();
        if (!ex)
        {
            goto Lno;
        }
        elements->tdata()[j] = ex;
    }

    /* Fill in any missing elements with the default initializer
     */
    {
    Expression *init = NULL;
    for (size_t i = 0; i < edim; i++)
    {
        if (!elements->tdata()[i])
        {
            if (!type)
                goto Lno;
            if (!init)
                init = ((TypeNext *)t)->next->defaultInit();
            elements->tdata()[i] = init;
        }
    }

    Expression *e = new ArrayLiteralExp(loc, elements);
    e->type = type;
    return e;
    }

Lno:
    return NULL;
}
예제 #2
0
파일: init.c 프로젝트: kryptonX/dmd
/***************************************
 * This works by transforming a struct initializer into
 * a struct literal. In the future, the two should be the
 * same thing.
 */
Expression *StructInitializer::toExpression()
{   Expression *e;
    size_t offset;

    //printf("StructInitializer::toExpression() %s\n", toChars());
    if (!ad)                            // if fwd referenced
    {
        return NULL;
    }
    StructDeclaration *sd = ad->isStructDeclaration();
    if (!sd)
        return NULL;
    Expressions *elements = new Expressions();
    size_t nfields = ad->fields.dim;
#if DMDV2
    if (sd->isnested)
       nfields--;
#endif
    elements->setDim(nfields);
    for (size_t i = 0; i < elements->dim; i++)
    {
        elements->tdata()[i] = NULL;
    }
    unsigned fieldi = 0;
    for (size_t i = 0; i < value.dim; i++)
    {
        Identifier *id = field.tdata()[i];
        if (id)
        {
            Dsymbol * s = ad->search(loc, id, 0);
            if (!s)
            {
                error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
                goto Lno;
            }
            s = s->toAlias();

            // Find out which field index it is
            for (fieldi = 0; 1; fieldi++)
            {
                if (fieldi >= nfields)
                {
                    s->error("is not a per-instance initializable field");
                    goto Lno;
                }
                if (s == ad->fields.tdata()[fieldi])
                    break;
            }
        }
        else if (fieldi >= nfields)
        {   error(loc, "too many initializers for '%s'", ad->toChars());
            goto Lno;
        }
        Initializer *iz = value.tdata()[i];
        if (!iz)
            goto Lno;
        Expression *ex = iz->toExpression();
        if (!ex)
            goto Lno;
        if (elements->tdata()[fieldi])
        {   error(loc, "duplicate initializer for field '%s'",
                ad->fields.tdata()[fieldi]->toChars());
            goto Lno;
        }
        elements->tdata()[fieldi] = ex;
        ++fieldi;
    }
    // Now, fill in any missing elements with default initializers.
    // We also need to validate any anonymous unions
    offset = 0;
    for (size_t i = 0; i < elements->dim; )
    {
        VarDeclaration * vd = ad->fields.tdata()[i]->isVarDeclaration();

        //printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset);
        if (vd->offset < offset)
        {
            // Only the first field of a union can have an initializer
            if (elements->tdata()[i])
                goto Lno;
        }
        else
        {
            if (!elements->tdata()[i])
                // Default initialize
                elements->tdata()[i] = vd->type->defaultInit();
        }
        offset = vd->offset + vd->type->size();
        i++;
#if 0
        int unionSize = ad->numFieldsInUnion(i);
        if (unionSize == 1)
        {   // Not a union -- default initialize if missing
            if (!elements->tdata()[i])
                elements->tdata()[i] = vd->type->defaultInit();
        }
        else
        {   // anonymous union -- check for errors
            int found = -1; // index of the first field with an initializer
            for (int j = i; j < i + unionSize; ++j)
            {
                if (!elements->tdata()[j])
                    continue;
                if (found >= 0)
                {
                    VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration();
                    VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration();
                    error(loc, "%s cannot have initializers for fields %s and %s in same union",
                        ad->toChars(),
                        v1->toChars(), v->toChars());
                    goto Lno;
                }
                found = j;
            }
            if (found == -1)
            {
                error(loc, "no initializer for union that contains field %s",
                    vd->toChars());
                goto Lno;
            }
        }
        i += unionSize;
#endif
    }
    e = new StructLiteralExp(loc, sd, elements);
    e->type = sd->type;
    return e;

Lno:
    delete elements;
    return NULL;
}
예제 #3
0
파일: todt.c 프로젝트: s-ludwig/GDC
dt_t *ArrayInitializer::toDtBit()
{
#if DMDV1
    unsigned size;
    unsigned length;
    unsigned tadim;
    dt_t *d;
    dt_t **pdtend;
    Type *tb = type->toBasetype();

    //printf("ArrayInitializer::toDtBit('%s')\n", toChars());

    Bits databits;
    Bits initbits;

    if (tb->ty == Tsarray)
    {
        /* The 'dim' for ArrayInitializer is only the maximum dimension
         * seen in the initializer, not the type. So, for static arrays,
         * use instead the dimension of the type in order
         * to get the whole thing.
         */
        dinteger_t value = ((TypeSArray*)tb)->dim->toInteger();
        tadim = value;
        assert(tadim == value);  // truncation overflow should already be checked
        databits.resize(tadim);
        initbits.resize(tadim);
    }
    else
    {
        databits.resize(dim);
        initbits.resize(dim);
    }

    /* The default initializer may be something other than zero.
     */
    if (tb->nextOf()->defaultInit()->toInteger())
       databits.set();

    size = sizeof(databits[0]);

    length = 0;
    for (size_t i = 0; i < index.dim; i++)
    {   Expression *idx;
        Initializer *val;
        Expression *eval;

        idx = index[i];
        if (idx)
        {   dinteger_t value;
            value = idx->toInteger();
            length = value;
            if (length != value)
            {   error(loc, "index overflow %llu", value);
                length = 0;
            }
        }
        assert(length < dim);

        val = value[i];
        eval = val->toExpression();
        if (initbits.test(length))
            error(loc, "duplicate initializations for index %d", length);
        initbits.set(length);
        if (eval->toInteger())          // any non-zero value is boolean 'true'
            databits.set(length);
        else
            databits.clear(length);     // boolean 'false'
        length++;
    }

    d = NULL;
#ifdef IN_GCC
    pdtend = dtnbits(&d, databits.allocdim * size, (char *)databits.data, sizeof(databits.tdata()[0]));
#else
    pdtend = dtnbytes(&d, databits.allocdim * size, (char *)databits.data);
#endif
    switch (tb->ty)
    {
        case Tsarray:
        {
            if (dim > tadim)
            {
                error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
            }
            else
            {
                tadim = (tadim + 31) / 32;
                if (databits.allocdim < tadim)
                    pdtend = dtnzeros(pdtend, size * (tadim - databits.allocdim));      // pad out end of array
            }
            break;
        }

        case Tpointer:
        case Tarray:
            // Create symbol, and then refer to it
            Symbol *s;
            s = static_sym();
            s->Sdt = d;
            outdata(s);

            d = NULL;
            if (tb->ty == Tarray)
                dtsize_t(&d, dim);
            dtxoff(&d, s, 0, TYnptr);
            break;

        default:
            assert(0);
    }
    return d;
#else
    return NULL;
#endif
}
예제 #4
0
파일: init.c 프로젝트: monarchdodra/dmd
Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
    t = t->toBasetype();
    if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct)
        t = t->nextOf()->toBasetype();
    if (t->ty == Tstruct)
    {
        StructDeclaration *sd = ((TypeStruct *)t)->sym;
        if (sd->ctor)
        {
            error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
                sd->kind(), sd->toChars(), sd->toChars());
            return new ErrorInitializer();
        }
        sd->size(loc);
        if (sd->sizeok != SIZEOKdone)
            return new ErrorInitializer();
        size_t nfields = sd->fields.dim - sd->isNested();

        //expandTuples for non-identity arguments?

        Expressions *elements = new Expressions();
        elements->setDim(nfields);
        for (size_t i = 0; i < elements->dim; i++)
            (*elements)[i] = NULL;

        // Run semantic for explicitly given initializers
        // TODO: this part is slightly different from StructLiteralExp::semantic.
        bool errors = false;
        for (size_t fieldi = 0, i = 0; i < field.dim; i++)
        {
            if (Identifier *id = field[i])
            {
                Dsymbol *s = sd->search(loc, id);
                if (!s)
                {
                    s = sd->search_correct(id);
                    if (s)
                        error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
                              id->toChars(), sd->toChars(), s->kind(), s->toChars());
                    else
                        error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
                    return new ErrorInitializer();
                }
                s = s->toAlias();

                // Find out which field index it is
                for (fieldi = 0; 1; fieldi++)
                {
                    if (fieldi >= nfields)
                    {
                        error(loc, "%s.%s is not a per-instance initializable field",
                            sd->toChars(), s->toChars());
                        return new ErrorInitializer();
                    }
                    if (s == sd->fields[fieldi])
                        break;
                }
            }
            else if (fieldi >= nfields)
            {
                error(loc, "too many initializers for %s", sd->toChars());
                return new ErrorInitializer();
            }

            VarDeclaration *vd = sd->fields[fieldi];
            if ((*elements)[fieldi])
            {
                error(loc, "duplicate initializer for field '%s'", vd->toChars());
                errors = true;
                continue;
            }
            for (size_t j = 0; j < nfields; j++)
            {
                VarDeclaration *v2 = sd->fields[j];
                bool overlap = (vd->offset < v2->offset + v2->type->size() &&
                                v2->offset < vd->offset + vd->type->size());
                if (overlap && (*elements)[j])
                {
                    error(loc, "overlapping initialization for field %s and %s",
                        v2->toChars(), vd->toChars());
                    errors = true;
                    continue;
                }
            }

            assert(sc);
            Initializer *iz = value[i];
            iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret);
            Expression *ex = iz->toExpression();
            if (ex->op == TOKerror)
            {
                errors = true;
                continue;
            }
            value[i] = iz;
            (*elements)[fieldi] = ex;
            ++fieldi;
        }
        if (errors)
            return new ErrorInitializer();

        StructLiteralExp *sle = new StructLiteralExp(loc, sd, elements, t);
        if (!sd->fill(loc, elements, false))
            return new ErrorInitializer();
        sle->type = t;

        ExpInitializer *ie = new ExpInitializer(loc, sle);
        return ie->semantic(sc, t, needInterpret);
    }
    else if ((t->ty == Tdelegate || t->ty == Tpointer && t->nextOf()->ty == Tfunction) && value.dim == 0)
    {
        TOK tok = (t->ty == Tdelegate) ? TOKdelegate : TOKfunction;
        /* Rewrite as empty delegate literal { }
         */
        Parameters *arguments = new Parameters;
        Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
        FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, tok, NULL);
        fd->fbody = new CompoundStatement(loc, new Statements());
        fd->endloc = loc;
        Expression *e = new FuncExp(loc, fd);
        ExpInitializer *ie = new ExpInitializer(loc, e);
        return ie->semantic(sc, t, needInterpret);
    }

    error(loc, "a struct is not a valid initializer for a %s", t->toChars());
    return new ErrorInitializer();
}
예제 #5
0
파일: init.c 프로젝트: niceDreamer/dmd
Expression *StructInitializer::fill(Scope *sc, Type *t, NeedInterpret needInterpret)
{
    //printf("StructInitializer::fill(sc = %p, '%s')\n", sc, toChars());
    assert(t->ty == Tstruct);
    StructDeclaration *sd = ((TypeStruct *)t)->sym;
    sd->size(loc);
    if (sd->sizeok != SIZEOKdone)
        return new ErrorExp();
    size_t nfields = sd->fields.dim - sd->isNested();

    Expressions *elements = new Expressions();
    elements->setDim(nfields);
    for (size_t i = 0; i < elements->dim; i++)
        (*elements)[i] = NULL;

    // Run semantic for explicitly given initializers
    bool errors = false;
    for (size_t fieldi = 0, i = 0; i < field.dim; i++)
    {
        if (Identifier *id = field[i])
        {
            Dsymbol *s = sd->search(loc, id, 0);
            if (!s)
            {
                s = sd->search_correct(id);
                if (s)
                    error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
                          id->toChars(), sd->toChars(), s->kind(), s->toChars());
                else
                    error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
                return new ErrorExp();
            }
            s = s->toAlias();

            // Find out which field index it is
            for (fieldi = 0; 1; fieldi++)
            {
                if (fieldi >= nfields)
                {
                    error(loc, "%s.%s is not a per-instance initializable field",
                        sd->toChars(), s->toChars());
                    return new ErrorExp();
                }
                if (s == sd->fields[fieldi])
                    break;
            }
        }
        else if (fieldi >= nfields)
        {
            error(loc, "too many initializers for %s", sd->toChars());
            return new ErrorExp();
        }

        VarDeclaration *vd = sd->fields[fieldi];
        if ((*elements)[fieldi])
        {
            error(loc, "duplicate initializer for field '%s'", vd->toChars());
            errors = true;
            continue;
        }
        for (size_t j = 0; j < nfields; j++)
        {
            VarDeclaration *v2 = sd->fields[j];
            bool overlap = (vd->offset < v2->offset + v2->type->size() &&
                            v2->offset < vd->offset + vd->type->size());
            if (overlap && (*elements)[j])
            {
                error(loc, "overlapping initialization for field %s and %s",
                    v2->toChars(), vd->toChars());
                errors = true;
                continue;
            }
        }

        assert(sc);
        Initializer *iz = value[i];
        iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret);
        Expression *ex = iz->toExpression();
        if (ex->op == TOKerror)
        {
            errors = true;
            continue;
        }
        value[i] = iz;
        (*elements)[fieldi] = ex;
        ++fieldi;
    }
    if (errors)
        return new ErrorExp();

    // Fill in missing any elements with default initializers
    for (size_t i = 0; i < elements->dim; i++)
    {
        if ((*elements)[i])
            continue;
        VarDeclaration *vd = sd->fields[i];
        VarDeclaration *vx = vd;
        if (vd->init && vd->init->isVoidInitializer())
            vx = NULL;
        // Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
        size_t fieldi = i;
        for (size_t j = 0; j < nfields; j++)
        {
            if (i == j)
                continue;
            VarDeclaration *v2 = sd->fields[j];
            if (v2->init && v2->init->isVoidInitializer())
                continue;

            bool overlap = (vd->offset < v2->offset + v2->type->size() &&
                            v2->offset < vd->offset + vd->type->size());
            if (!overlap)
                continue;

            if ((*elements)[j])
            {
                vx = NULL;
                break;
            }

    #if 1
            /* Prefer first found non-void-initialized field
             * union U { int a; int b = 2; }
             * U u;    // Error: overlapping initialization for field a and b
             */
            if (!vx)
                vx = v2, fieldi = j;
            else if (v2->init)
            {
                error(loc, "overlapping initialization for field %s and %s",
                    v2->toChars(), vd->toChars());
            }
    #else   // fix Bugzilla 1432
            /* Prefer explicitly initialized field
             * union U { int a; int b = 2; }
             * U u;    // OK (u.b == 2)
             */
            if (!vx || !vx->init && v2->init)
                vx = v2, fieldi = j;
            else if (vx->init && v2->init)
            {
                error(loc, "overlapping default initialization for field %s and %s",
                    v2->toChars(), vd->toChars());
            }
            else
                assert(vx->init || !vx->init && !v2->init);
    #endif
        }
        if (vx)
        {
            if (vx->init)
            {
                assert(!vx->init->isVoidInitializer());
                if (vx->scope)
                {
                    // Do deferred semantic analysis
                    Initializer *i2 = vx->init->syntaxCopy();
                    i2 = i2->semantic(vx->scope, vx->type, INITinterpret);
                    (*elements)[fieldi] = i2->toExpression();
                    if (!global.gag)
                    {
                        vx->scope = NULL;
                        vx->init = i2;  // save result
                    }
                }
                else
                    (*elements)[fieldi] = vx->init->toExpression();
            }
            else
                (*elements)[fieldi] = vx->type->defaultInit();
        }
    }

    for (size_t i = 0; i < elements->dim; i++)
    {
        Expression *e = (*elements)[i];
        if (e && e->op == TOKerror)
            return e;
    }

    Expression *e = new StructLiteralExp(loc, sd, elements, t);
    if (sc)
        e = e->semantic(sc);
    else
        e->type = sd->type; // from glue layer
    return e;
}