Beispiel #1
0
Datei: cast.c Projekt: smunix/ldc
Expression *Expression::integralPromotions(Scope *sc)
{
    Expression *e = this;

    //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
    switch (type->toBasetype()->ty)
    {
        case Tvoid:
            error("void has no value");
            return new ErrorExp();

        case Tint8:
        case Tuns8:
        case Tint16:
        case Tuns16:
        case Tbit:
        case Tbool:
        case Tchar:
        case Twchar:
            e = e->castTo(sc, Type::tint32);
            break;

        case Tdchar:
            e = e->castTo(sc, Type::tuns32);
            break;
    }
    return e;
}
Beispiel #2
0
Datei: cast.c Projekt: smunix/ldc
Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
{
    if (type == t)
        return this;
    AssocArrayLiteralExp *e = this;
    Type *typeb = type->toBasetype();
    Type *tb = t->toBasetype();
    if (tb->ty == Taarray && typeb->ty == Taarray &&
        tb->nextOf()->toBasetype()->ty != Tvoid)
    {
        e = (AssocArrayLiteralExp *)copy();
        e->keys = (Expressions *)keys->copy();
        e->values = (Expressions *)values->copy();
        assert(keys->dim == values->dim);
        for (size_t i = 0; i < keys->dim; i++)
        {   Expression *ex = (Expression *)values->data[i];
            ex = ex->castTo(sc, tb->nextOf());
            e->values->data[i] = (void *)ex;

            ex = (Expression *)keys->data[i];
            ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
            e->keys->data[i] = (void *)ex;
        }
        e->type = t;
        return e;
    }
L1:
    return e->Expression::castTo(sc, t);
}
Beispiel #3
0
Datei: cast.c Projekt: smunix/ldc
Expression *TupleExp::castTo(Scope *sc, Type *t)
{   TupleExp *e = (TupleExp *)copy();
    e->exps = (Expressions *)exps->copy();
    for (size_t i = 0; i < e->exps->dim; i++)
    {   Expression *ex = (Expression *)e->exps->data[i];
        ex = ex->castTo(sc, t);
        e->exps->data[i] = (void *)ex;
    }
    return e;
}
Beispiel #4
0
Datei: cast.c Projekt: smunix/ldc
Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
{
#if 0
    printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n",
        toChars(), type->toChars(), t->toChars());
#endif
    if (type == t)
        return this;
    ArrayLiteralExp *e = this;
    Type *typeb = type->toBasetype();
    Type *tb = t->toBasetype();
    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
        (typeb->ty == Tarray || typeb->ty == Tsarray) &&
        // Not trying to convert non-void[] to void[]
        !(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid))
    {
        if (tb->ty == Tsarray)
        {   TypeSArray *tsa = (TypeSArray *)tb;
            if (elements->dim != tsa->dim->toInteger())
                goto L1;
        }

        e = (ArrayLiteralExp *)copy();
        e->elements = (Expressions *)elements->copy();
        for (int i = 0; i < elements->dim; i++)
        {   Expression *ex = (Expression *)elements->data[i];
            ex = ex->castTo(sc, tb->nextOf());
            e->elements->data[i] = (void *)ex;
        }
        e->type = t;
        return e;
    }
    if (tb->ty == Tpointer && typeb->ty == Tsarray)
    {
        e = (ArrayLiteralExp *)copy();
        e->type = typeb->nextOf()->pointerTo();
    }
L1:
    return e->Expression::castTo(sc, t);
}
Beispiel #5
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;
}
Beispiel #6
0
Expression *expandVar(int result, VarDeclaration *v)
{
    //printf("expandVar(result = %d, v = %s)\n", result, v ? v->toChars() : "null");
    Expression *e = NULL;
    if (v && (v->isConst() || v->isInvariant() || v->storage_class & STCmanifest))
    {
	Type *tb = v->type->toBasetype();
	if (result & WANTinterpret ||
	    v->storage_class & STCmanifest ||
	    (tb->ty != Tsarray && tb->ty != Tstruct)
	   )
	{
	    if (v->init)
	    {
		if (v->inuse)
		    goto L1;
		Expression *ei = v->init->toExpression();
		if (!ei)
		    goto L1;
		if (ei->op == TOKconstruct || ei->op == TOKblit)
		{   AssignExp *ae = (AssignExp *)ei;
		    ei = ae->e2;
		    if (ei->isConst() != 1 && ei->op != TOKstring)
			goto L1;
		    if (ei->type != v->type)
			goto L1;
		}
		if (v->scope)
		{
		    v->inuse++;
		    e = ei->syntaxCopy();
		    e = e->semantic(v->scope);
		    e = e->implicitCastTo(v->scope, v->type);
		    v->scope = NULL;
		    v->inuse--;
		}
		else if (!ei->type)
		{
		    goto L1;
		}
		else
		    // Should remove the copy() operation by
		    // making all mods to expressions copy-on-write
		    e = ei->copy();
	    }
	    else
	    {
#if 1
		goto L1;
#else
		// BUG: what if const is initialized in constructor?
		e = v->type->defaultInit();
		e->loc = e1->loc;
#endif
	    }
	    if (e->type != v->type)
	    {
		e = e->castTo(NULL, v->type);
	    }
	    e = e->optimize(result);
	}
    }
L1:
    //if (e) printf("\te = %s, e->type = %s\n", e->toChars(), e->type->toChars());
    return e;
}
Beispiel #7
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)		// 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();
}
Beispiel #8
0
Expression *expandVar(int result, VarDeclaration *v)
{
    //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v->toChars() : "null");

    Expression *e = NULL;
    if (!v)
        return e;
    if (!v->originalType && v->scope)   // semantic() not yet run
        v->semantic (v->scope);

    if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest)
    {
        if (!v->type)
        {
            //error("ICE");
            return e;
        }
        Type *tb = v->type->toBasetype();
        if (result & WANTinterpret ||
            v->storage_class & STCmanifest ||
            v->type->toBasetype()->isscalar() ||
            ((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct))
           )
        {
            if (v->init)
            {
                if (v->inuse)
                {   if (v->storage_class & STCmanifest)
                        v->error("recursive initialization of constant");
                    goto L1;
                }
                Expression *ei = v->init->toExpression();
                if (!ei)
                {   if (v->storage_class & STCmanifest)
                        v->error("enum cannot be initialized with %s", v->init->toChars());
                    goto L1;
                }
                if (ei->op == TOKconstruct || ei->op == TOKblit)
                {   AssignExp *ae = (AssignExp *)ei;
                    ei = ae->e2;
                    if (result & WANTinterpret)
                    {
                        v->inuse++;
                        ei = ei->optimize(result);
                        v->inuse--;
                    }
                    else if (ei->isConst() != 1 && ei->op != TOKstring)
                        goto L1;

                    if (ei->type == v->type)
                    {   // const variable initialized with const expression
                    }
                    else if (ei->implicitConvTo(v->type) >= MATCHconst)
                    {   // const var initialized with non-const expression
                        ei = ei->implicitCastTo(0, v->type);
                        ei = ei->semantic(0);
                    }
                    else
                        goto L1;
                }
                if (v->scope)
                {
                    v->inuse++;
                    e = ei->syntaxCopy();
                    e = e->semantic(v->scope);
                    e = e->implicitCastTo(v->scope, v->type);
                    // enabling this line causes test22 in test suite to fail
                    //ei->type = e->type;
                    v->scope = NULL;
                    v->inuse--;
                }
                else if (!ei->type)
                {
                    goto L1;
                }
                else
                    // Should remove the copy() operation by
                    // making all mods to expressions copy-on-write
                    e = ei->copy();
            }
            else
            {
#if 1
                goto L1;
#else
                // BUG: what if const is initialized in constructor?
                e = v->type->defaultInit();
                e->loc = e1->loc;
#endif
            }
            if (e->type != v->type)
            {
                e = e->castTo(NULL, v->type);
            }
            v->inuse++;
            e = e->optimize(result);
            v->inuse--;
        }
    }
L1:
    //if (e) printf("\te = %p, %s, e->type = %d, %s\n", e, e->toChars(), e->type->ty, e->type->toChars());
    return e;
}
Beispiel #9
0
Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
{
#if 0
    printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n",
        toChars(), type->toChars(), t->toChars());
#endif
    if (type == t)
        return this;
    ArrayLiteralExp *e = this;
    Type *typeb = type->toBasetype();
    Type *tb = t->toBasetype();
    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
        (typeb->ty == Tarray || typeb->ty == Tsarray) &&
        // Not trying to convert non-void[] to void[]
        !(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid))
    {
        if (tb->ty == Tsarray)
        {   TypeSArray *tsa = (TypeSArray *)tb;
            if (elements->dim != tsa->dim->toInteger())
                goto L1;
        }

        e = (ArrayLiteralExp *)copy();
        e->elements = (Expressions *)elements->copy();
        for (size_t i = 0; i < elements->dim; i++)
        {   Expression *ex = (*elements)[i];
            ex = ex->castTo(sc, tb->nextOf());
            (*e->elements)[i] = ex;
        }
        e->type = t;
        return e;
    }
    if (tb->ty == Tpointer && typeb->ty == Tsarray)
    {
        e = (ArrayLiteralExp *)copy();
        e->type = typeb->nextOf()->pointerTo();
    }
#if DMDV2
    else if (tb->ty == Tvector &&
        (typeb->ty == Tarray || typeb->ty == Tsarray))
    {
        // Convert array literal to vector type
        TypeVector *tv = (TypeVector *)tb;
        TypeSArray *tbase = (TypeSArray *)tv->basetype;
        assert(tbase->ty == Tsarray);
        if (elements->dim != tbase->dim->toInteger())
            goto L1;

        e = (ArrayLiteralExp *)copy();
        e->elements = (Expressions *)elements->copy();
        Type *telement = tv->elementType();
        for (size_t i = 0; i < elements->dim; i++)
        {   Expression *ex = (*elements)[i];
            ex = ex->castTo(sc, telement);
            (*e->elements)[i] = ex;
        }
        Expression *ev = new VectorExp(loc, e, tb);
        ev = ev->semantic(sc);
        return ev;
    }
#endif
L1:
    return e->Expression::castTo(sc, t);
}