Exemple #1
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;
}
Exemple #2
0
Expression *semanticTraits(TraitsExp *e, Scope *sc)
{
#if LOGSEMANTIC
    printf("TraitsExp::semantic() %s\n", e->toChars());
#endif
    if (e->ident != Id::compiles && e->ident != Id::isSame &&
        e->ident != Id::identifier && e->ident != Id::getProtection)
    {
        if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 1))
            return new ErrorExp();
    }
    size_t dim = e->args ? e->args->dim : 0;

    if (e->ident == Id::isArithmetic)
    {
        return isTypeX(e, &isTypeArithmetic);
    }
    else if (e->ident == Id::isFloating)
    {
        return isTypeX(e, &isTypeFloating);
    }
    else if (e->ident == Id::isIntegral)
    {
        return isTypeX(e, &isTypeIntegral);
    }
    else if (e->ident == Id::isScalar)
    {
        return isTypeX(e, &isTypeScalar);
    }
    else if (e->ident == Id::isUnsigned)
    {
        return isTypeX(e, &isTypeUnsigned);
    }
    else if (e->ident == Id::isAssociativeArray)
    {
        return isTypeX(e, &isTypeAssociativeArray);
    }
    else if (e->ident == Id::isStaticArray)
    {
        return isTypeX(e, &isTypeStaticArray);
    }
    else if (e->ident == Id::isAbstractClass)
    {
        return isTypeX(e, &isTypeAbstractClass);
    }
    else if (e->ident == Id::isFinalClass)
    {
        return isTypeX(e, &isTypeFinalClass);
    }
    else if (e->ident == Id::isPOD)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Type *t = isType(o);
        StructDeclaration *sd;
        if (!t)
        {
            e->error("type expected as second argument of __traits %s instead of %s", e->ident->toChars(), o->toChars());
            goto Lfalse;
        }
        Type *tb = t->baseElemOf();
        if (tb->ty == Tstruct
            && ((sd = (StructDeclaration *)(((TypeStruct *)tb)->sym)) != NULL))
        {
            if (sd->isPOD())
                goto Ltrue;
            else
                goto Lfalse;
        }
        goto Ltrue;
    }
    else if (e->ident == Id::isNested)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        AggregateDeclaration *a;
        FuncDeclaration *f;

        if (!s) { }
        else if ((a = s->isAggregateDeclaration()) != NULL)
        {
            if (a->isNested())
                goto Ltrue;
            else
                goto Lfalse;
        }
        else if ((f = s->isFuncDeclaration()) != NULL)
        {
            if (f->isNested())
                goto Ltrue;
            else
                goto Lfalse;
        }

        e->error("aggregate or function expected instead of '%s'", o->toChars());
        goto Lfalse;
    }
    else if (e->ident == Id::isAbstractFunction)
    {
        return isFuncX(e, &isFuncAbstractFunction);
    }
    else if (e->ident == Id::isVirtualFunction)
    {
        return isFuncX(e, &isFuncVirtualFunction);
    }
    else if (e->ident == Id::isVirtualMethod)
    {
        return isFuncX(e, &isFuncVirtualMethod);
    }
    else if (e->ident == Id::isFinalFunction)
    {
        return isFuncX(e, &isFuncFinalFunction);
    }
    else if (e->ident == Id::isOverrideFunction)
    {
        return isFuncX(e, &isFuncOverrideFunction);
    }
    else if (e->ident == Id::isStaticFunction)
    {
        return isFuncX(e, &isFuncStaticFunction);
    }
    else if (e->ident == Id::isRef)
    {
        return isDeclX(e, &isDeclRef);
    }
    else if (e->ident == Id::isOut)
    {
        return isDeclX(e, &isDeclOut);
    }
    else if (e->ident == Id::isLazy)
    {
        return isDeclX(e, &isDeclLazy);
    }
    else if (e->ident == Id::identifier)
    {
        // Get identifier for symbol as a string literal
        /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
         * a symbol should not be folded to a constant.
         * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
         */
        if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 2))
            return new ErrorExp();

        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Parameter *po = isParameter(o);
        Identifier *id;
        if (po)
        {
            id = po->ident;
            assert(id);
        }
        else
        {
            Dsymbol *s = getDsymbol(o);
            if (!s || !s->ident)
            {
                e->error("argument %s has no identifier", o->toChars());
                goto Lfalse;
            }
            id = s->ident;
        }
        StringExp *se = new StringExp(e->loc, id->toChars());
        return se->semantic(sc);
    }
    else if (e->ident == Id::getProtection)
    {
        if (dim != 1)
            goto Ldimerror;

        Scope *sc2 = sc->push();
        sc2->flags = sc->flags | SCOPEnoaccesscheck;
        bool ok = TemplateInstance::semanticTiargs(e->loc, sc2, e->args, 1);
        sc2->pop();

        if (!ok)
            return new ErrorExp();

        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (!s)
        {
            if (!isError(o))
                e->error("argument %s has no protection", o->toChars());
            goto Lfalse;
        }
        if (s->scope)
            s->semantic(s->scope);

        const char *protName = protectionToChars(s->prot());
        assert(protName);
        StringExp *se = new StringExp(e->loc, (char *) protName);
        return se->semantic(sc);
    }
    else if (e->ident == Id::parent)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (s)
        {
            if (FuncDeclaration *fd = s->isFuncDeclaration())   // Bugzilla 8943
                s = fd->toAliasFunc();
            if (!s->isImport())  // Bugzilla 8922
                s = s->toParent();
        }
        if (!s || s->isImport())
        {
            e->error("argument %s has no parent", o->toChars());
            goto Lfalse;
        }

        if (FuncDeclaration *f = s->isFuncDeclaration())
        {
            if (TemplateDeclaration *td = getFuncTemplateDecl(f))
            {
                if (td->overroot)       // if not start of overloaded list of TemplateDeclaration's
                    td = td->overroot;  // then get the start
                Expression *ex = new TemplateExp(e->loc, td, f);
                ex = ex->semantic(sc);
                return ex;
            }

            if (FuncLiteralDeclaration *fld = f->isFuncLiteralDeclaration())
            {
                // Directly translate to VarExp instead of FuncExp
                Expression *ex = new VarExp(e->loc, fld, 1);
                return ex->semantic(sc);
            }
        }

        return (new DsymbolExp(e->loc, s))->semantic(sc);
    }
    else if (e->ident == Id::hasMember ||
             e->ident == Id::getMember ||
             e->ident == Id::getOverloads ||
             e->ident == Id::getVirtualMethods ||
             e->ident == Id::getVirtualFunctions)
    {
        if (dim != 2)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Expression *ex = isExpression((*e->args)[1]);
        if (!ex)
        {
            e->error("expression expected as second argument of __traits %s", e->ident->toChars());
            goto Lfalse;
        }
        ex = ex->ctfeInterpret();
        StringExp *se = ex->toStringExp();
        if (!se || se->length() == 0)
        {
            e->error("string expected as second argument of __traits %s instead of %s", e->ident->toChars(), ex->toChars());
            goto Lfalse;
        }
        se = se->toUTF8(sc);
        if (se->sz != 1)
        {
            e->error("string must be chars");
            goto Lfalse;
        }
        Identifier *id = Lexer::idPool((char *)se->string);

        /* Prefer dsymbol, because it might need some runtime contexts.
         */
        Dsymbol *sym = getDsymbol(o);
        if (sym)
        {
            ex = new DsymbolExp(e->loc, sym);
            ex = new DotIdExp(e->loc, ex, id);
        }
        else if (Type *t = isType(o))
            ex = typeDotIdExp(e->loc, t, id);
        else if (Expression *ex2 = isExpression(o))
            ex = new DotIdExp(e->loc, ex2, id);
        else
        {
            e->error("invalid first argument");
            goto Lfalse;
        }

        if (e->ident == Id::hasMember)
        {
            if (sym)
            {
                Dsymbol *sm = sym->search(e->loc, id);
                if (sm)
                    goto Ltrue;
            }

            /* Take any errors as meaning it wasn't found
             */
            Scope *sc2 = sc->push();
            ex = ex->trySemantic(sc2);
            sc2->pop();
            if (!ex)
                goto Lfalse;
            else
                goto Ltrue;
        }
        else if (e->ident == Id::getMember)
        {
            ex = ex->semantic(sc);
            return ex;
        }
        else if (e->ident == Id::getVirtualFunctions ||
                 e->ident == Id::getVirtualMethods ||
                 e->ident == Id::getOverloads)
        {
            unsigned errors = global.errors;
            Expression *eorig = ex;
            ex = ex->semantic(sc);
            if (errors < global.errors)
                e->error("%s cannot be resolved", eorig->toChars());

            /* Create tuple of functions of ex
             */
            //ex->print();
            Expressions *exps = new Expressions();
            FuncDeclaration *f;
            if (ex->op == TOKvar)
            {
                VarExp *ve = (VarExp *)ex;
                f = ve->var->isFuncDeclaration();
                ex = NULL;
            }
            else if (ex->op == TOKdotvar)
            {
                DotVarExp *dve = (DotVarExp *)ex;
                f = dve->var->isFuncDeclaration();
                if (dve->e1->op == TOKdottype || dve->e1->op == TOKthis)
                    ex = NULL;
                else
                    ex = dve->e1;
            }
            else
                f = NULL;
            Ptrait p;
            p.exps = exps;
            p.e1 = ex;
            p.ident = e->ident;
            overloadApply(f, &p, &fptraits);

            TupleExp *tup = new TupleExp(e->loc, exps);
            return tup->semantic(sc);
        }
        else
            assert(0);
    }
    else if (e->ident == Id::classInstanceSize)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        ClassDeclaration *cd;
        if (!s || (cd = s->isClassDeclaration()) == NULL)
        {
            e->error("first argument is not a class");
            goto Lfalse;
        }
        if (cd->sizeok == SIZEOKnone)
        {
            if (cd->scope)
                cd->semantic(cd->scope);
        }
        if (cd->sizeok != SIZEOKdone)
        {
            e->error("%s %s is forward referenced", cd->kind(), cd->toChars());
            goto Lfalse;
        }
        return new IntegerExp(e->loc, cd->structsize, Type::tsize_t);
    }
    else if (e->ident == Id::getAliasThis)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        AggregateDeclaration *ad;
        if (!s || (ad = s->isAggregateDeclaration()) == NULL)
        {
            e->error("argument is not an aggregate type");
            goto Lfalse;
        }

        Expressions *exps = new Expressions();
        if (ad->aliasthis)
            exps->push(new StringExp(e->loc, ad->aliasthis->ident->toChars()));

        Expression *ex = new TupleExp(e->loc, exps);
        ex = ex->semantic(sc);
        return ex;
    }
    else if (e->ident == Id::getAttributes)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (!s)
        {
        #if 0
            Expression *x = isExpression(o);
            Type *t = isType(o);
            if (x) printf("e = %s %s\n", Token::toChars(x->op), x->toChars());
            if (t) printf("t = %d %s\n", t->ty, t->toChars());
        #endif
            e->error("first argument is not a symbol");
            goto Lfalse;
        }
        //printf("getAttributes %s, attrs = %p, scope = %p\n", s->toChars(), s->userAttribDecl, s->scope);
        UserAttributeDeclaration *udad = s->userAttribDecl;
        TupleExp *tup = new TupleExp(e->loc, udad ? udad->getAttributes() : new Expressions());
        return tup->semantic(sc);
    }
    else if (e->ident == Id::getFunctionAttributes)
    {
        /// extract all function attributes as a tuple (const/shared/inout/pure/nothrow/etc) except UDAs.

        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        Type *t = isType(o);
        TypeFunction *tf = NULL;

        if (s)
        {
            if (FuncDeclaration *f = s->isFuncDeclaration())
                t = f->type;
            else if (VarDeclaration *v = s->isVarDeclaration())
                t = v->type;
        }
        if (t)
        {
            if (t->ty == Tfunction)
                tf = (TypeFunction *)t;
            else if (t->ty == Tdelegate)
                tf = (TypeFunction *)t->nextOf();
            else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction)
                tf = (TypeFunction *)t->nextOf();
        }
        if (!tf)
        {
            e->error("first argument is not a function");
            goto Lfalse;
        }

        Expressions *mods = new Expressions();

        PushAttributes pa;
        pa.mods = mods;

        tf->modifiersApply(&pa, &PushAttributes::fp);
        tf->attributesApply(&pa, &PushAttributes::fp, TRUSTformatSystem);

        TupleExp *tup = new TupleExp(e->loc, mods);
        return tup->semantic(sc);
    }
    else if (e->ident == Id::allMembers || e->ident == Id::derivedMembers)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        ScopeDsymbol *sds;
        if (!s)
        {
            e->error("argument has no members");
            goto Lfalse;
        }
        Import *import;
        if ((import = s->isImport()) != NULL)
        {
            // Bugzilla 9692
            sds = import->mod;
        }
        else if ((sds = s->isScopeDsymbol()) == NULL)
        {
            e->error("%s %s has no members", s->kind(), s->toChars());
            goto Lfalse;
        }

        // use a struct as local function
        struct PushIdentsDg
        {
            static int dg(void *ctx, size_t n, Dsymbol *sm)
            {
                if (!sm)
                    return 1;
                //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
                if (sm->ident)
                {
                    if (sm->ident != Id::ctor &&
                        sm->ident != Id::dtor &&
                        sm->ident != Id::_postblit &&
                        memcmp(sm->ident->string, "__", 2) == 0)
                    {
                        return 0;
                    }

                    //printf("\t%s\n", sm->ident->toChars());
                    Identifiers *idents = (Identifiers *)ctx;

                    /* Skip if already present in idents[]
                     */
                    for (size_t j = 0; j < idents->dim; j++)
                    {   Identifier *id = (*idents)[j];
                        if (id == sm->ident)
                            return 0;
#ifdef DEBUG
                        // Avoid using strcmp in the first place due to the performance impact in an O(N^2) loop.
                        assert(strcmp(id->toChars(), sm->ident->toChars()) != 0);
#endif
                    }

                    idents->push(sm->ident);
                }
                else
                {
                    EnumDeclaration *ed = sm->isEnumDeclaration();
                    if (ed)
                    {
                        ScopeDsymbol::foreach(NULL, ed->members, &PushIdentsDg::dg, (Identifiers *)ctx);
                    }
                }
                return 0;
            }
        };

        Identifiers *idents = new Identifiers;

        ScopeDsymbol::foreach(sc, sds->members, &PushIdentsDg::dg, idents);

        ClassDeclaration *cd = sds->isClassDeclaration();
        if (cd && e->ident == Id::allMembers)
        {
            struct PushBaseMembers
            {
                static void dg(ClassDeclaration *cd, Identifiers *idents)
                {
                    for (size_t i = 0; i < cd->baseclasses->dim; i++)
                    {
                        ClassDeclaration *cb = (*cd->baseclasses)[i]->base;
                        ScopeDsymbol::foreach(NULL, cb->members, &PushIdentsDg::dg, idents);
                        if (cb->baseclasses->dim)
                            dg(cb, idents);
                    }
                }
            };
            PushBaseMembers::dg(cd, idents);
        }

        // Turn Identifiers into StringExps reusing the allocated array
        assert(sizeof(Expressions) == sizeof(Identifiers));
        Expressions *exps = (Expressions *)idents;
        for (size_t i = 0; i < idents->dim; i++)
        {
            Identifier *id = (*idents)[i];
            StringExp *se = new StringExp(e->loc, id->toChars());
            (*exps)[i] = se;
        }

        /* Making this a tuple is more flexible, as it can be statically unrolled.
         * To make an array literal, enclose __traits in [ ]:
         *   [ __traits(allMembers, ...) ]
         */
        Expression *ex = new TupleExp(e->loc, exps);
        ex = ex->semantic(sc);
        return ex;
    }
    else if (e->ident == Id::compiles)
    {
        /* Determine if all the objects - types, expressions, or symbols -
         * compile without error
         */
        if (!dim)
            goto Lfalse;

        for (size_t i = 0; i < dim; i++)
        {
            unsigned errors = global.startGagging();
            unsigned oldspec = global.speculativeGag;
            global.speculativeGag = global.gag;
            Scope *sc2 = sc->push();
            sc2->speculative = true;
            sc2->flags = sc->flags & ~SCOPEctfe | SCOPEcompile;
            bool err = false;

            RootObject *o = (*e->args)[i];
            Type *t = isType(o);
            Expression *ex = t ? t->toExpression() : isExpression(o);
            if (!ex && t)
            {
                Dsymbol *s;
                t->resolve(e->loc, sc2, &ex, &t, &s);
                if (t)
                {
                    t->semantic(e->loc, sc2);
                    if (t->ty == Terror)
                        err = true;
                }
                else if (s && s->errors)
                    err = true;
            }
            if (ex)
            {
                ex = ex->semantic(sc2);
                ex = resolvePropertiesOnly(sc2, ex);
                ex = ex->optimize(WANTvalue);
                if (sc2->func && sc2->func->type->ty == Tfunction)
                {
                    TypeFunction *tf = (TypeFunction *)sc2->func->type;
                    canThrow(ex, sc2->func, tf->isnothrow);
                }
                ex = checkGC(sc2, ex);
                if (ex->op == TOKerror)
                    err = true;
            }

            sc2->pop();
            global.speculativeGag = oldspec;
            if (global.endGagging(errors) || err)
            {
                goto Lfalse;
            }
        }
        goto Ltrue;
    }
    else if (e->ident == Id::isSame)
    {
        /* Determine if two symbols are the same
         */
        if (dim != 2)
            goto Ldimerror;
        if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 0))
            return new ErrorExp();
        RootObject *o1 = (*e->args)[0];
        RootObject *o2 = (*e->args)[1];
        Dsymbol *s1 = getDsymbol(o1);
        Dsymbol *s2 = getDsymbol(o2);

        //printf("isSame: %s, %s\n", o1->toChars(), o2->toChars());
#if 0
        printf("o1: %p\n", o1);
        printf("o2: %p\n", o2);
        if (!s1)
        {
            Expression *ea = isExpression(o1);
            if (ea)
                printf("%s\n", ea->toChars());
            Type *ta = isType(o1);
            if (ta)
                printf("%s\n", ta->toChars());
            goto Lfalse;
        }
        else
            printf("%s %s\n", s1->kind(), s1->toChars());
#endif
        if (!s1 && !s2)
        {
            Expression *ea1 = isExpression(o1);
            Expression *ea2 = isExpression(o2);
            if (ea1 && ea2)
            {
                if (ea1->equals(ea2))
                    goto Ltrue;
            }
        }

        if (!s1 || !s2)
            goto Lfalse;

        s1 = s1->toAlias();
        s2 = s2->toAlias();

        if (s1->isFuncAliasDeclaration())
            s1 = ((FuncAliasDeclaration *)s1)->toAliasFunc();
        if (s2->isFuncAliasDeclaration())
            s2 = ((FuncAliasDeclaration *)s2)->toAliasFunc();

        if (s1 == s2)
            goto Ltrue;
        else
            goto Lfalse;
    }
    else if (e->ident == Id::getUnitTests)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (!s)
        {
            e->error("argument %s to __traits(getUnitTests) must be a module or aggregate", o->toChars());
            goto Lfalse;
        }

        Import *imp = s->isImport();
        if (imp)  // Bugzilla 10990
            s = imp->mod;

        ScopeDsymbol* scope = s->isScopeDsymbol();

        if (!scope)
        {
            e->error("argument %s to __traits(getUnitTests) must be a module or aggregate, not a %s", s->toChars(), s->kind());
            goto Lfalse;
        }

        Expressions* unitTests = new Expressions();
        Dsymbols* symbols = scope->members;

        if (global.params.useUnitTests && symbols)
        {
            // Should actually be a set
            AA* uniqueUnitTests = NULL;
            collectUnitTests(symbols, uniqueUnitTests, unitTests);
        }

        TupleExp *tup = new TupleExp(e->loc, unitTests);
        return tup->semantic(sc);
    }
    else if(e->ident == Id::getVirtualIndex)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        FuncDeclaration *fd;
        if (!s || (fd = s->isFuncDeclaration()) == NULL)
        {
            e->error("first argument to __traits(getVirtualIndex) must be a function");
            goto Lfalse;
        }
        fd = fd->toAliasFunc(); // Neccessary to support multiple overloads.
        return new IntegerExp(e->loc, fd->vtblIndex, Type::tptrdiff_t);
    }
    else
    {
        if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars))
            e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub);
        else
            e->error("unrecognized trait '%s'", e->ident->toChars());

        goto Lfalse;
    }

    return NULL;

Ldimerror:
    e->error("wrong number of arguments %d", (int)dim);
    goto Lfalse;


Lfalse:
    return new IntegerExp(e->loc, 0, Type::tbool);

Ltrue:
    return new IntegerExp(e->loc, 1, Type::tbool);
}
Exemple #3
0
  void Output::operator()(Ruleset* r)
  {
    Selector* s     = r->selector();
    Block*    b     = r->block();
    bool      decls = false;

    // Filter out rulesets that aren't printable (process its children though)
    if (!Util::isPrintable(r, output_style())) {
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        if (dynamic_cast<Has_Block*>(stm)) {
          if (typeid(*stm) != typeid(Declaration)) {
            stm->perform(this);
          }
        }
      }
      return;
    }

    if (b->has_non_hoistable()) {
      decls = true;
      if (output_style() == NESTED) indentation += r->tabs();
      if (opt.source_comments) {
        std::stringstream ss;
        append_indentation();
        ss << "/* line " << r->pstate().line + 1 << ", " << r->pstate().path << " */";
        append_string(ss.str());
        append_optional_linefeed();
      }
      s->perform(this);
      append_scope_opener(b);
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        bool bPrintExpression = true;
        // Check print conditions
        if (typeid(*stm) == typeid(Declaration)) {
          Declaration* dec = static_cast<Declaration*>(stm);
          if (dec->value()->concrete_type() == Expression::STRING) {
            String_Constant* valConst = static_cast<String_Constant*>(dec->value());
            std::string val(valConst->value());
            if (auto qstr = dynamic_cast<String_Quoted*>(valConst)) {
              if (!qstr->quote_mark() && val.empty()) {
                bPrintExpression = false;
              }
            }
          }
          else if (dec->value()->concrete_type() == Expression::LIST) {
            List* list = static_cast<List*>(dec->value());
            bool all_invisible = true;
            for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
              Expression* item = (*list)[list_i];
              if (!item->is_invisible()) all_invisible = false;
            }
            if (all_invisible) bPrintExpression = false;
          }
        }
        // Print if OK
        if (!stm->is_hoistable() && bPrintExpression) {
          stm->perform(this);
        }
      }
      if (output_style() == NESTED) indentation -= r->tabs();
      append_scope_closer(b);
    }

    if (b->has_hoistable()) {
      if (decls) ++indentation;
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        if (stm->is_hoistable()) {
          stm->perform(this);
        }
      }
      if (decls) --indentation;
    }
  }
Exemple #4
0
Fichier : enum.c Projet : eco/dmd
Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
{
    //printf("EnumDeclaration::getMaxValue()\n");
    bool first = true;

    Expression **pval = (id == Id::max) ? &maxval : &minval;

    if (inuse)
    {
        error(loc, "recursive definition of .%s property", id->toChars());
        goto Lerrors;
    }
    if (*pval)
        goto Ldone;

    if (scope)
        semantic(scope);
    if (errors)
        goto Lerrors;
    if (semanticRun == PASSinit || !members)
    {
        error("is forward referenced looking for .%s", id->toChars());
        goto Lerrors;
    }
    if (!(memtype && memtype->isintegral()))
    {
        error(loc, "has no .%s property because base type %s is not an integral type",
                id->toChars(),
                memtype ? memtype->toChars() : "");
        goto Lerrors;
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = (*members)[i]->isEnumMember();
        if (!em)
            continue;
        if (em->errors)
            goto Lerrors;

        Expression *e = em->value;
        if (first)
        {
            *pval = e;
            first = false;
        }
        else
        {
            /* 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 > maxval)
             *      maxval = e;
             */
            Expression *ec = new CmpExp(id == Id::max ? TOKgt : TOKlt, em->loc, e, *pval);
            inuse++;
            ec = ec->semantic(em->scope);
            inuse--;
            ec = ec->ctfeInterpret();
            if (ec->toInteger())
                *pval = e;
        }
    }
Ldone:
  {
    Expression *e = *pval;
    if (e->op != TOKerror)
    {
        e = e->copy();
        e->loc = loc;
    }
    return e;
  }

Lerrors:
    *pval = new ErrorExp();
    return *pval;
}
Exemple #5
0
ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
                                              Expression &expr,
                                              bool generate_debug_info) :
    ExpressionParser (exe_scope, expr, generate_debug_info),
    m_compiler (),
    m_code_generator (),
    m_pp_callbacks(nullptr)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    // We can't compile expressions without a target.  So if the exe_scope is null or doesn't have a target,
    // then we just need to get out of here.  I'll lldb_assert and not make any of the compiler objects since
    // I can't return errors directly from the constructor.  Further calls will check if the compiler was made and
    // bag out if it wasn't.
    
    if (!exe_scope)
    {
        lldb_assert(exe_scope, "Can't make an expression parser with a null scope.", __FUNCTION__, __FILE__, __LINE__);
        return;
    }
    
    lldb::TargetSP target_sp;
    target_sp = exe_scope->CalculateTarget();
    if (!target_sp)
    {
        lldb_assert(exe_scope, "Can't make an expression parser with a null target.", __FUNCTION__, __FILE__, __LINE__);
        return;
    }
    
    // 1. Create a new compiler instance.
    m_compiler.reset(new CompilerInstance());
    lldb::LanguageType frame_lang = expr.Language(); // defaults to lldb::eLanguageTypeUnknown
    bool overridden_target_opts = false;
    lldb_private::LanguageRuntime *lang_rt = nullptr;

    std::string abi;
    ArchSpec target_arch;
    target_arch = target_sp->GetArchitecture();

    const auto target_machine = target_arch.GetMachine();

    // If the expression is being evaluated in the context of an existing
    // stack frame, we introspect to see if the language runtime is available.
    
    lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame();
    lldb::ProcessSP process_sp = exe_scope->CalculateProcess();
    
    // Make sure the user hasn't provided a preferred execution language
    // with `expression --language X -- ...`
    if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown)
        frame_lang = frame_sp->GetLanguage();

    if (process_sp && frame_lang != lldb::eLanguageTypeUnknown)
    {
        lang_rt = process_sp->GetLanguageRuntime(frame_lang);
        if (log)
            log->Printf("Frame has language of type %s", Language::GetNameForLanguageType(frame_lang));
    }

    // 2. Configure the compiler with a set of default options that are appropriate
    // for most situations.
    if (target_arch.IsValid())
    {
        std::string triple = target_arch.GetTriple().str();
        m_compiler->getTargetOpts().Triple = triple;
        if (log)
            log->Printf("Using %s as the target triple", m_compiler->getTargetOpts().Triple.c_str());
    }
    else
    {
        // If we get here we don't have a valid target and just have to guess.
        // Sometimes this will be ok to just use the host target triple (when we evaluate say "2+3", but other
        // expressions like breakpoint conditions and other things that _are_ target specific really shouldn't just be
        // using the host triple. In such a case the language runtime should expose an overridden options set (3),
        // below.
        m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
        if (log)
            log->Printf("Using default target triple of %s", m_compiler->getTargetOpts().Triple.c_str());
    }
    // Now add some special fixes for known architectures:
    // Any arm32 iOS environment, but not on arm64
    if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
        m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
        m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
    {
        m_compiler->getTargetOpts().ABI = "apcs-gnu";
    }
    // Supported subsets of x86
    if (target_machine == llvm::Triple::x86 ||
        target_machine == llvm::Triple::x86_64)
    {
        m_compiler->getTargetOpts().Features.push_back("+sse");
        m_compiler->getTargetOpts().Features.push_back("+sse2");
    }

    // Set the target CPU to generate code for.
    // This will be empty for any CPU that doesn't really need to make a special CPU string.
    m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU();

    // Set the target ABI
    abi = GetClangTargetABI(target_arch);
    if (!abi.empty())
        m_compiler->getTargetOpts().ABI = abi;

    // 3. Now allow the runtime to provide custom configuration options for the target.
    // In this case, a specialized language runtime is available and we can query it for extra options.
    // For 99% of use cases, this will not be needed and should be provided when basic platform detection is not enough.
    if (lang_rt)
        overridden_target_opts = lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts());

    if (overridden_target_opts)
        if (log)
        {
            log->Debug("Using overridden target options for the expression evaluation");

            auto opts = m_compiler->getTargetOpts();
            log->Debug("Triple: '%s'", opts.Triple.c_str());
            log->Debug("CPU: '%s'", opts.CPU.c_str());
            log->Debug("FPMath: '%s'", opts.FPMath.c_str());
            log->Debug("ABI: '%s'", opts.ABI.c_str());
            log->Debug("LinkerVersion: '%s'", opts.LinkerVersion.c_str());
            StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten");
            StringList::LogDump(log, opts.Features, "Features");
            StringList::LogDump(log, opts.Reciprocals, "Reciprocals");
        }

    // 4. Create and install the target on the compiler.
    m_compiler->createDiagnostics();
    auto target_info = TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts);
    if (log)
    {
        log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign());
        log->Printf("Target datalayout string: '%s'", target_info->getDataLayout().getStringRepresentation().c_str());
        log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str());
        log->Printf("Target vector alignment: %d", target_info->getMaxVectorAlign());
    }
    m_compiler->setTarget(target_info);

    assert (m_compiler->hasTarget());

    // 5. Set language options.
    lldb::LanguageType language = expr.Language();

    switch (language)
    {
    case lldb::eLanguageTypeC:
    case lldb::eLanguageTypeC89:
    case lldb::eLanguageTypeC99:
    case lldb::eLanguageTypeC11:
        // FIXME: the following language option is a temporary workaround,
        // to "ask for C, get C++."
        // For now, the expression parser must use C++ anytime the
        // language is a C family language, because the expression parser
        // uses features of C++ to capture values.
        m_compiler->getLangOpts().CPlusPlus = true;
        break;
    case lldb::eLanguageTypeObjC:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        // FIXME: the following language option is a temporary workaround,
        // to "ask for ObjC, get ObjC++" (see comment above).
        m_compiler->getLangOpts().CPlusPlus = true;
        break;
    case lldb::eLanguageTypeC_plus_plus:
    case lldb::eLanguageTypeC_plus_plus_11:
    case lldb::eLanguageTypeC_plus_plus_14:
        m_compiler->getLangOpts().CPlusPlus11 = true;
        m_compiler->getHeaderSearchOpts().UseLibcxx = true;
        LLVM_FALLTHROUGH;
    case lldb::eLanguageTypeC_plus_plus_03:
        m_compiler->getLangOpts().CPlusPlus = true;
        // FIXME: the following language option is a temporary workaround,
        // to "ask for C++, get ObjC++".  Apple hopes to remove this requirement
        // on non-Apple platforms, but for now it is needed.
        m_compiler->getLangOpts().ObjC1 = true;
        break;
    case lldb::eLanguageTypeObjC_plus_plus:
    case lldb::eLanguageTypeUnknown:
    default:
        m_compiler->getLangOpts().ObjC1 = true;
        m_compiler->getLangOpts().ObjC2 = true;
        m_compiler->getLangOpts().CPlusPlus = true;
        m_compiler->getLangOpts().CPlusPlus11 = true;
        m_compiler->getHeaderSearchOpts().UseLibcxx = true;
        break;
    }

    m_compiler->getLangOpts().Bool = true;
    m_compiler->getLangOpts().WChar = true;
    m_compiler->getLangOpts().Blocks = true;
    m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
    if (expr.DesiredResultType() == Expression::eResultTypeId)
        m_compiler->getLangOpts().DebuggerCastResultToId = true;

    m_compiler->getLangOpts().CharIsSigned =
            ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault();

    // Spell checking is a nice feature, but it ends up completing a
    // lot of types that we didn't strictly speaking need to complete.
    // As a result, we spend a long time parsing and importing debug
    // information.
    m_compiler->getLangOpts().SpellChecking = false;

    if (process_sp && m_compiler->getLangOpts().ObjC1)
    {
        if (process_sp->GetObjCLanguageRuntime())
        {
            if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2)
                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
            else
                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7));

            if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing())
                m_compiler->getLangOpts().DebuggerObjCLiteral = true;
        }
    }

    m_compiler->getLangOpts().ThreadsafeStatics = false;
    m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
    m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name

    // Set CodeGen options
    m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
    m_compiler->getCodeGenOpts().InstrumentFunctions = false;
    m_compiler->getCodeGenOpts().DisableFPElim = true;
    m_compiler->getCodeGenOpts().OmitLeafFramePointer = false;
    if (generate_debug_info)
        m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
    else
        m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);

    // Disable some warnings.
    m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
        "unused-value", clang::diag::Severity::Ignored, SourceLocation());
    m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
        "odr", clang::diag::Severity::Ignored, SourceLocation());

    // Inform the target of the language options
    //
    // FIXME: We shouldn't need to do this, the target should be immutable once
    // created. This complexity should be lifted elsewhere.
    m_compiler->getTarget().adjust(m_compiler->getLangOpts());

    // 6. Set up the diagnostic buffer for reporting errors

    m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter);

    // 7. Set up the source management objects inside the compiler

    clang::FileSystemOptions file_system_options;
    m_file_manager.reset(new clang::FileManager(file_system_options));

    if (!m_compiler->hasSourceManager())
        m_compiler->createSourceManager(*m_file_manager.get());

    m_compiler->createFileManager();
    m_compiler->createPreprocessor(TU_Complete);
    
    if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor())
    {
        ClangPersistentVariables *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
        std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars));
        m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get());
        m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
    }
        
    // 8. Most of this we get from the CompilerInstance, but we
    // also want to give the context an ExternalASTSource.
    m_selector_table.reset(new SelectorTable());
    m_builtin_context.reset(new Builtin::Context());

    std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
                                                                  m_compiler->getSourceManager(),
                                                                  m_compiler->getPreprocessor().getIdentifierTable(),
                                                                  *m_selector_table.get(),
                                                                  *m_builtin_context.get()));
    
    ast_context->InitBuiltinTypes(m_compiler->getTarget());

    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
    ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();

    if (decl_map)
    {
        llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
        decl_map->InstallASTContext(ast_context.get());
        ast_context->setExternalSource(ast_source);
    }

    m_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str()));
    m_ast_context->setASTContext(ast_context.get());
    m_compiler->setASTContext(ast_context.release());

    std::string module_name("$__lldb_module");

    m_llvm_context.reset(new LLVMContext());
    m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
                                             module_name,
                                             m_compiler->getHeaderSearchOpts(),
                                             m_compiler->getPreprocessorOpts(),
                                             m_compiler->getCodeGenOpts(),
                                             *m_llvm_context));
}
Exemple #6
0
Expression *createTypeInfoArray(Scope *sc, Expression *exps[], size_t dim)
{
#if 1
    /*
     * Pass a reference to the TypeInfo_Tuple corresponding to the types of the
     * arguments. Source compatibility is maintained by computing _arguments[]
     * at the start of the called function by offseting into the TypeInfo_Tuple
     * reference.
     */
    Parameters *args = Parameters_create();
    args->setDim(dim);
    for (size_t i = 0; i < dim; i++)
    {   Parameter *arg = Parameter::create(STCin, exps[i]->type, NULL, NULL);
        (*args)[i] = arg;
    }
    TypeTuple *tup = TypeTuple::create(args);
    Expression *e = tup->getTypeInfo(sc);
    e = e->optimize(WANTvalue);
    assert(e->op == TOKsymoff);         // should be SymOffExp

    return e;
#else
    /* Improvements:
     * 1) create an array literal instead,
     * as it would eliminate the extra dereference of loading the
     * static variable.
     */

    ArrayInitializer *ai = new ArrayInitializer(0);
    VarDeclaration *v;
    Type *t;
    Expression *e;
    OutBuffer buf;
    Identifier *id;
    char *name;

    // Generate identifier for _arguments[]
    buf.writestring("_arguments_");
    for (int i = 0; i < dim; i++)
    {   t = exps[i]->type;
        t->toDecoBuffer(&buf);
    }
    buf.writeByte(0);
    id = Lexer::idPool((char *)buf.data);

    Module *m = sc->module;
    Dsymbol *s = m->symtab->lookup(id);

    if (s && s->parent == m)
    {   // Use existing one
        v = s->isVarDeclaration();
        assert(v);
    }
    else
    {   // Generate new one

        for (int i = 0; i < dim; i++)
        {   t = exps[i]->type;
            e = t->getTypeInfo(sc);
            ai->addInit(new IntegerExp(i), new ExpInitializer(Loc(), e));
        }

        t = Type::typeinfo->type->arrayOf();
        ai->type = t;
        v = new VarDeclaration(0, t, id, ai);
        v->storage_class |= STCtemp;
        m->members->push(v);
        m->symtabInsert(v);
        sc = sc->push();
        sc->linkage = LINKc;
        sc->stc = STCstatic | STCcomdat;
        ai->semantic(sc, t);
        v->semantic(sc);
        v->parent = m;
        sc = sc->pop();
    }
    e = VarExp::create(Loc(), v);
    e = e->semantic(sc);
    return e;
#endif
}
FunctionInvocation *
FunctionInvocation::make_random_binary(CGContext &cg_context, const Type* type)
{
	DEPTH_GUARD_BY_TYPE_RETURN(dtFunctionInvocationRandomBinary, NULL);
	if (rnd_flipcoin(10) && Type::has_pointer_type()) {
		ERROR_GUARD(NULL);
		return make_random_binary_ptr_comparison(cg_context);
	}

	eBinaryOps op;
	do {
		op = (eBinaryOps)(rnd_upto(MAX_BINARY_OP, BINARY_OPS_PROB_FILTER));
	} while (type->is_float() && !BinaryOpWorksForFloat(op));
	ERROR_GUARD(NULL);
	assert(type);
	SafeOpFlags *flags = SafeOpFlags::make_random_binary(type, NULL, NULL, sOpBinary, op);
	assert(flags);
	ERROR_GUARD(NULL);
	FunctionInvocationBinary *fi = FunctionInvocationBinary::CreateFunctionInvocationBinary(cg_context, op, flags);

	Effect lhs_eff_accum;
	CGContext lhs_cg_context(cg_context, cg_context.get_effect_context(), &lhs_eff_accum);

	// Generate an expression with the correct type required by safe math operands
	const Type* lhs_type = flags->get_lhs_type();
	const Type* rhs_type = flags->get_rhs_type();
	assert(lhs_type && rhs_type);
	if (!BinaryOpWorksForFloat(op)) {
		assert(!lhs_type->is_float() && "lhs_type is float!");
		assert(!rhs_type->is_float() && "rhs_type is float!");
	}

	Expression *lhs = Expression::make_random(lhs_cg_context, lhs_type);
	ERROR_GUARD_AND_DEL1(NULL, fi);
	Expression *rhs = 0;

	cg_context.merge_param_context(lhs_cg_context, true);
	FactMgr* fm = get_fact_mgr(&cg_context);
	vector<const Fact*> facts_copy = fm->global_facts;

#if 0
	if (lhs->term_type == eVariable) {
		lhs_eff_accum.read_deref_volatile((ExpressionVariable*)lhs);
	}
#endif

	// If we are guaranteed that the LHS will be evaluated before the RHS,
	// or if the LHS is pure (not merely side-effect-free),
	// then we can generate the RHS under the original effect context.
	if (IsOrderedStandardFunc(op)) { // || lhs_eff_accum.is_pure()) { TODO: need more thoughts on the purity issue.
		rhs = Expression::make_random(cg_context, rhs_type);
	}
	else {
		// Otherwise, the RHS must be generated under the combined effect
		// of the original effect and the LHS effect.
		Effect rhs_eff_context(cg_context.get_effect_context());
		rhs_eff_context.add_effect(lhs_eff_accum, true);
		Effect rhs_eff_accum;

		CGContext rhs_cg_context(cg_context, rhs_eff_context, &rhs_eff_accum);
		if (op == eLShift || op == eRShift) {
			eTermType tt = MAX_TERM_TYPES;
			bool not_constant = rnd_flipcoin(ShiftByNonConstantProb);
			// avoid shifting negative or too much
			if (!not_constant) {
				rhs = Constant::make_random_upto(lhs_type->SizeInBytes() * 8);
			} else {
				rhs = Expression::make_random(rhs_cg_context, rhs_type, NULL, false, true, tt);
			}
		}
		else {
			rhs = Expression::make_random(rhs_cg_context, rhs_type);
			// avoid divide by zero or possible zero (reached by pointer comparison)
			if ((op == eMod || op == eDiv) && (rhs->equals(0) || rhs->is_0_or_1()) &&
				!lhs_type->is_float() && !rhs_type->is_float()) {
				VectorFilter f;
				f.add(eMod).add(eDiv).add(eLShift).add(eRShift);
				op = (eBinaryOps)(rnd_upto(MAX_BINARY_OP, &f));
				fi->set_operation(op);
			}
		}
		cg_context.merge_param_context(rhs_cg_context, true);
	}

	ERROR_GUARD_AND_DEL2(NULL, fi, lhs);
	if (!BinaryOpWorksForFloat(op)) {
		assert(!lhs->get_type().is_float() && "lhs is of float!");
		assert(!rhs->get_type().is_float() && "rhs is of float!");
	}

	if (CompatibleChecker::compatible_check(lhs, rhs)) {
		Error::set_error(COMPATIBLE_CHECK_ERROR);
		delete lhs;
		delete rhs;
		delete fi;
		return NULL;
	}

	// ordered operators such as "||" or "&&" may skip the 2nd parameter
	if (IsOrderedStandardFunc(op)) {
		fm->makeup_new_var_facts(facts_copy, fm->global_facts);
		merge_facts(fm->global_facts, facts_copy);
	}
	// TODO: fix `rhs' for eLShift and eRShift and ...
	// Currently, the "fix" is handled in `FunctionInvocationBinary::Output'.
	fi->param_value.push_back(lhs);
	fi->param_value.push_back(rhs);
	return fi;
}
TEST(Expression_Builder, can_build_digit_multiply) {
	ExpressionBuilder builder("2*3", NULL);
	Expression* expression = builder.Build();
	ASSERT_EQ(2*3, expression->Calculate());
}
TEST(Expression_Builder, can_build_digit_divide) {
	ExpressionBuilder builder("3/2", NULL);
	Expression* expression = builder.Build();
	ASSERT_EQ(3.0/2.0, expression->Calculate());
}
bool DataReference::gather_info_data_expr_rec(Expression expr,
        Symbol &base_sym,
        Source &size,
        Source &addr,
        Type &type,
        bool enclosing_is_array,
        bool & pointer_member_access,
        std::stringstream& warnlog)
{
    if (expr.is_id_expression()
            || expr.is_this_variable()
            || expr.is_accessed_member())
    {
        Symbol sym(NULL);

        if (expr.is_this_variable())
        {
            sym = expr.get_this_symbol();
        }
        else
        {
            sym = expr.get_id_expression().get_computed_symbol();
        }

        if (!sym.is_valid())
        {
            warnlog << expr.get_ast().get_locus() << ": warning: unknown symbol in data-reference '" << expr.prettyprint() << "'"
                    << std::endl;
            return false;
        }

        if (!sym.is_variable())
        {
            warnlog << expr.get_ast().get_locus() << ": warning: symbol in data-reference '" << expr.prettyprint() << "' "
                    << "is not a variable" << std::endl;
            return false;
        }

        base_sym = sym;
        Source this_accessor;
        if(expr.is_id_expression() && sym.is_member() && !sym.is_static())
        {
            this_accessor << "this->";
        }

        type = sym.get_type();

        if (type.is_reference())
            type = type.references_to();

        if (type.is_array()
                || enclosing_is_array)
        {
            addr << this_accessor << sym.get_qualified_name();
        }
        else
        {
            addr << "&" << this_accessor << sym.get_qualified_name();
        }
        size = safe_expression_size(type, expr.get_scope());

        return true;
    }
    else if (expr.is_array_subscript())
    {
        Source arr_size, arr_addr;
        Type arr_type(NULL);
        bool b = gather_info_data_expr_rec(expr.get_subscripted_expression(),
                                           base_sym,
                                           arr_size,
                                           arr_addr,
                                           arr_type,
                                           /* enclosing_is_array */ true,
                                           pointer_member_access,
                                           warnlog);
        if (!b)
        {
            return false;
        }

        if (arr_type.is_array())
        {
            type = arr_type.array_element();
        }
        else if (arr_type.is_pointer())
        {
            type = arr_type.points_to();
        }
        else
        {
            warnlog << expr.get_ast().get_locus()
                    << ": warning: array subscript in data-reference '"
                    << expr.prettyprint()
                    << "' is not a variable" << std::endl;
            return false;
        }

        size = safe_expression_size(type, expr.get_scope());
        addr = arr_addr << "[" << expr.get_subscript_expression() << "]";
        if (!enclosing_is_array)
        {
            addr = "&(" + addr.get_source() + ")";
        }

        return true;
    }
    else if (expr.is_array_section_range()
             || expr.is_array_section_size())
    {
        ObjectList<Expression> range_set;

        Expression current_expr = expr;
        while (current_expr.is_array_section_range()
                || current_expr.is_array_section_size())
        {
            range_set.append(current_expr);
            current_expr = current_expr.array_section_item();
        }

        // Now check that everything makes sense.
        // - We allow a pointer or an array at the first dimension
        // - Every other dimension must be an array
        Type current_type = current_expr.get_type();
        for (ObjectList<Expression>::iterator it = range_set.begin();
                it != range_set.end();
                it++)
        {
            if (current_type.is_reference())
                current_type = current_type.references_to();

            if (!(current_type.is_array()
                    || (current_type.is_pointer()
                        && it == range_set.begin())))
            {
                // Not valid
                if (!current_type.is_array()
                        && !current_type.is_pointer())
                {
                    warnlog << expr.get_ast().get_locus()
                            << ": warning: array section in data-reference '"
                            << expr.prettyprint()
                            << "' is not a pointer or array type" << std::endl;
                }
                else if (current_type.is_pointer())
                {
                    warnlog << expr.get_ast().get_locus()
                            << ": warning: array section in data-reference '"
                            << expr.prettyprint()
                            << "' is a pointer type but it is not the first section" << std::endl;
                }
                return false;
            }

            if (current_type.is_array())
            {
                current_type = current_type.array_element();
            }
            else
            {
                current_type = current_type.points_to();
            }
        }

        Source arr_size, arr_addr;
        Type arr_type(NULL);
        bool b = gather_info_data_expr_rec(current_expr,
                                           base_sym,
                                           arr_size,
                                           arr_addr,
                                           arr_type,
                                           /* enclosing_is_array */ true,
                                           pointer_member_access,
                                           warnlog);
        if (!b)
            return false;

        // Now rebuild the type
        Type rebuilt_type = current_type;
        for (ObjectList<Expression>::iterator it = range_set.begin();
                it != range_set.end();
                it++)
        {
            Expression& section(*it);

            Source upper_bound;
            if (section.is_array_section_size())
            {
                upper_bound
                        << "((" << section.array_section_lower() << ") + (" << section.array_section_upper() << ") - 1)"
                        ;
            }
            else if (section.is_array_section_range())
            {
                upper_bound
                        << section.array_section_upper()
                        ;
            }

            AST_t upper_bound_tree = upper_bound.parse_expression(section.get_ast(),
                                     section.get_scope_link());
            rebuilt_type = rebuilt_type.get_array_to(section.array_section_lower().get_ast(), upper_bound_tree, section.get_scope());

            arr_addr << "[" << section.array_section_lower() << "]"
                     ;
        }

        addr = arr_addr;
        type = rebuilt_type;
        if (!enclosing_is_array)
        {
            addr = "&(" + addr.get_source() + ")";
        }
        size = safe_expression_size(type, expr.get_scope());
        return true;
    }
    else if (expr.is_unary_operation())
    {
        if (expr.get_operation_kind() == Expression::REFERENCE)
        {
            Expression ref_expr = expr.get_unary_operand();
            if (ref_expr.is_unary_operation()
                    && ref_expr.get_operation_kind() == Expression::DERREFERENCE)
            {
                // Case &(*a)
                return gather_info_data_expr_rec(ref_expr.get_unary_operand(),
                                                 base_sym,
                                                 size,
                                                 addr,
                                                 type,
                                                 enclosing_is_array,
                                                 pointer_member_access,
                                                 warnlog);
            }
            else if (ref_expr.is_array_subscript())
            {
                // Case &(a[0])
                return gather_info_data_expr_rec(ref_expr.get_subscripted_expression(),
                                                 base_sym,
                                                 size,
                                                 addr,
                                                 type,
                                                 enclosing_is_array,
                                                 pointer_member_access,
                                                 warnlog);
            }
            else if (ref_expr.is_array_section_range()
                     || ref_expr.is_array_section_size())
            {
                // Case &(a[0:4])
                // Case &(a[0;5])
                return gather_info_data_expr_rec(ref_expr.array_section_item(),
                                                 base_sym,
                                                 size,
                                                 addr,
                                                 type,
                                                 enclosing_is_array,
                                                 pointer_member_access,
                                                 warnlog);
            }
        }
        else if (expr.get_operation_kind() == Expression::DERREFERENCE)
        {
            Expression ref_expr = expr.get_unary_operand();
            if (ref_expr.is_unary_operation()
                    && ref_expr.get_operation_kind() == Expression::REFERENCE)
            {
                // Case *(&a)
                return gather_info_data_expr_rec(ref_expr.get_unary_operand(),
                                                 base_sym,
                                                 size,
                                                 addr,
                                                 type,
                                                 enclosing_is_array,
                                                 pointer_member_access,
                                                 warnlog);
            }
            else
            {
                // Case *a
                Source ptr_size, ptr_addr;
                bool b = gather_info_data_expr_rec(ref_expr,
                                                   base_sym,
                                                   ptr_size,
                                                   ptr_addr,
                                                   type,
                                                   enclosing_is_array,
                                                   pointer_member_access,
                                                   warnlog);

                if (!b)
                    return false;

                if (type.is_pointer())
                {
                    type = type.points_to();
                }
                else if (type.is_array())
                {
                    type = type.array_element();
                }

                size = safe_expression_size(type, expr.get_scope());
                addr = "(" + ref_expr.prettyprint() + ")";

                return true;
            }
        }

        warnlog << expr.get_ast().get_locus()
                << ": warning: expression '"
                << expr.prettyprint()
                << "' is not a valid data-reference" << std::endl;
        return false;
    }
    else if (expr.is_shaping_expression())
    {
        Expression shaped_expr = expr.shaped_expression();

        Source arr_size, arr_addr;

        bool b = gather_info_data_expr_rec(shaped_expr, base_sym,
                                           arr_size, arr_addr,
                                           type, /* enclosing_is_array */ true,
                                           pointer_member_access, warnlog);

        if (!b)
            return false;

        CXX_LANGUAGE()
        {
            if (type.is_reference())
            {
                type = type.references_to();
            }
        }

        // Array to pointer
        if (type.is_array())
        {
            type = type.array_element().get_pointer_to();
        }

        if (!type.is_pointer())
        {
            warnlog << expr.get_ast().get_locus()
                    << ": warning: in data reference '"
                    << expr.prettyprint()
                    << "' shaped expression does not have pointer type" << std::endl;
            return false;
        }

        type = type.points_to();

        ObjectList<Expression> shape_list = expr.shape_list();
        for (ObjectList<Expression>::reverse_iterator it = shape_list.rbegin();
                it != shape_list.rend();
                it++)
        {
            type = type.get_array_to(it->get_ast(), it->get_scope());
        }
        size = safe_expression_size(type, expr.get_scope());

        Type cast_type = type.array_element().get_pointer_to();

        addr << "((" << cast_type.get_declaration(expr.get_scope(), "") << ")" << arr_addr << ")";

        return true;
    }
Exemple #11
0
 inline std::string SqlTranslator::BuildQuery() {
   m_query.clear();
   m_expression->Apply(*this);
   return m_query;
 }
DataReference::DataReference(Expression expr)
    : Expression(expr.get_ast(), expr.get_scope_link()),
      _valid(), _base_symbol(NULL), _type(NULL), _size(), _addr()
{
    _valid = gather_info_data_expr(*this, _base_symbol, _size, _addr, _type, _warnlog);
}
Exemple #13
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement

    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
    if (ident == Id::msg)
    {
        if (args)
        {
            for (size_t i = 0; i < args->dim; i++)
            {
                Expression *e = args->tdata()[i];

                e = e->semantic(sc);
                e = e->optimize(WANTvalue | WANTinterpret);
                StringExp *se = e->toString();
                if (se)
                {
                    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
                }
                else
                    fprintf(stdmsg, "%s", e->toChars());
            }
            fprintf(stdmsg, "\n");
        }
        goto Lnodecl;
    }
    else if (ident == Id::lib)
    {
        if (!args || args->dim != 1)
            error("string expected for library name");
        else
        {
            Expression *e = args->tdata()[0];

            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->tdata()[0] = e;
            if (e->op == TOKerror)
                goto Lnodecl;
            StringExp *se = e->toString();
            if (!se)
                error("string expected for library name, not '%s'", e->toChars());
            else if (global.params.verbose)
            {
                char *name = (char *)mem.malloc(se->len + 1);
                memcpy(name, se->string, se->len);
                name[se->len] = 0;
                printf("library   %s\n", name);
                mem.free(name);
            }
        }
        goto Lnodecl;
    }
#if IN_GCC
    else if (ident == Id::GNU_asm)
    {
        if (! args || args->dim != 2)
            error("identifier and string expected for asm name");
        else
        {
            Expression *e;
            Declaration *d = NULL;
            StringExp *s = NULL;

            e = args->tdata()[0];
            e = e->semantic(sc);
            if (e->op == TOKvar)
            {
                d = ((VarExp *)e)->var;
                if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
                    d = NULL;
            }
            if (!d)
                error("first argument of GNU_asm must be a function or variable declaration");

            e = args->tdata()[1];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            e = e->toString();
            if (e && ((StringExp *)e)->sz == 1)
                s = ((StringExp *)e);
            else
                error("second argument of GNU_asm must be a char string");

            if (d && s)
                d->c_ident = Lexer::idPool((char*) s->string);
        }
        goto Lnodecl;
    }
#endif
#if DMDV2
    else if (ident == Id::startaddress)
    {
        if (!args || args->dim != 1)
            error("function name expected for start address");
        else
        {
            Expression *e = args->tdata()[0];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->tdata()[0] = e;
            Dsymbol *sa = getDsymbol(e);
            if (!sa || !sa->isFuncDeclaration())
                error("function name expected for start address, not '%s'", e->toChars());
        }
        goto Lnodecl;
    }
#endif
#if TARGET_NET
    else if (ident == Lexer::idPool("assembly"))
    {
    }
#endif // TARGET_NET
    else if (global.params.ignoreUnsupportedPragmas)
    {
        if (global.params.verbose)
        {
            /* Print unrecognized pragmas
             */
            printf("pragma    %s", ident->toChars());
            if (args)
            {
                for (size_t i = 0; i < args->dim; i++)
                {
                    Expression *e = args->tdata()[i];
                    e = e->semantic(sc);
                    e = e->optimize(WANTvalue | WANTinterpret);
                    if (i == 0)
                        printf(" (");
                    else
                        printf(",");
                    printf("%s", e->toChars());
                }
                if (args->dim)
                    printf(")");
            }
            printf("\n");
        }
        goto Lnodecl;
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

    if (decl)
    {
        for (unsigned i = 0; i < decl->dim; i++)
        {
            Dsymbol *s = decl->tdata()[i];

            s->semantic(sc);
        }
    }
    return;

Lnodecl:
    if (decl)
        error("pragma is missing closing ';'");
}
Exemple #14
0
ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
	if (frame.Sandboxed)
		BOOST_THROW_EXCEPTION(ScriptError("Includes are not allowed in sandbox mode.", m_DebugInfo));

	Expression *expr;
	String name, path, pattern;

	switch (m_Type) {
		case IncludeRegular:
			{
				ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
				CHECK_RESULT(pathres);
				path = pathres.GetValue();
			}

			expr = ConfigCompiler::HandleInclude(m_RelativeBase, path, m_SearchIncludes, m_Zone, m_Package, m_DebugInfo);
			break;

		case IncludeRecursive:
			{
				ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
				CHECK_RESULT(pathres);
				path = pathres.GetValue();
			}

			{
				ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
				CHECK_RESULT(patternres);
				pattern = patternres.GetValue();
			}

			expr = ConfigCompiler::HandleIncludeRecursive(m_RelativeBase, path, pattern, m_Zone, m_Package, m_DebugInfo);
			break;

		case IncludeZones:
			{
				ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
				CHECK_RESULT(nameres);
				name = nameres.GetValue();
			}

			{
				ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
				CHECK_RESULT(pathres);
				path = pathres.GetValue();
			}

			{
				ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
				CHECK_RESULT(patternres);
				pattern = patternres.GetValue();
			}

			expr = ConfigCompiler::HandleIncludeZones(m_RelativeBase, name, path, pattern, m_Package, m_DebugInfo);
			break;
	}

	ExpressionResult res(Empty);

	try {
		res = expr->Evaluate(frame, dhint);
	} catch (const std::exception&) {
		delete expr;
		throw;
	}

	delete expr;

	return res;
}
static void dismantle_multi_dim_array_expression(
		SuifEnv *env,
		MultiDimArrayExpression *exp,
		TypeBuilder *type_builder,
		suif_hash_map<MultiDimArrayType *,Type *> &type_map) 
{
    Expression *ref_exp = exp->get_array_address();

    Type *typ = ref_exp->get_result_type();
    if (is_kind_of<PointerType>(typ))
	typ = to<PointerType>(typ)->get_reference_type();
    if (is_kind_of<ReferenceType>(typ))
        typ = to<ReferenceType>(typ)->get_reference_type();

    if (is_kind_of<QualifiedType>(typ))
        typ = to<QualifiedType>(typ)->get_base_type();

    simple_stack<Expression *> lows;
    int dims;
    Type *rep_type;

    if (is_kind_of<MultiDimArrayType>(typ)) {
    	MultiDimArrayType *mdatyp= to<MultiDimArrayType>(typ);
	suif_hash_map<MultiDimArrayType *,Type *>::iterator iter =
		type_map.find(mdatyp);
	kernel_assert_message(iter != type_map.end(),
		("Error - type not converted"));
	rep_type = (*iter).second;
    	dims = exp->get_index_count();
    	for (int i = dims - 1;i >=0 ; i--) {
	    lows.push(mdatyp->get_lower_bound(i));
	    }
	}
    else {
	// this arm should never be taken, so assert
	kernel_assert_message(false,("This code should not have been accessed"));
	rep_type = typ;
        dims = 0;
	while (is_kind_of<ArrayType>(typ)) {
	    ArrayType *atype = to<ArrayType>(typ);
	    dims ++;
	    lows.push(atype->get_lower_bound());
	    typ = to<QualifiedType>(atype->get_element_type())->get_base_type();
	    }
	}

    exp->replace(ref_exp,0);
    ref_exp->set_parent(0);
    int index_count = exp->get_index_count();
    for (int i = 0;i < index_count;i ++) {
	Type *ref_type = rep_type;
	for (int j = 0;j <= i;j ++) {
	    ref_type = type_builder->unqualify_type(ref_type);
	    ref_type = to<ArrayType>(ref_type)->get_element_type();
	    }
	ref_type = type_builder->unqualify_type(ref_type);
	ref_type = type_builder->get_pointer_type(ref_type);
	Expression *index = exp->get_index(index_count - i - 1);



	// process nested multi dim arra expressions
        for (Iter<MultiDimArrayExpression> iter =
                object_iterator<MultiDimArrayExpression>(index);
         iter.is_valid();
         iter.next()) {
        MultiDimArrayExpression *mexpr = &iter.current();
        dismantle_multi_dim_array_expression(env,mexpr,type_builder,type_map);
        }
	
	exp->replace(index,0);
	index->set_parent(0);
        ref_exp = create_array_reference_expression(
		env,to<DataType>(ref_type),ref_exp,
		index);
	}
    exp->get_parent()->replace(exp,ref_exp);
}
TEST(Expression_Builder, can_build_digit)
{
	ExpressionBuilder builder("1", NULL);
	Expression* expression = builder.Build();
	ASSERT_EQ(1,expression->Calculate());
}
Exemple #17
0
Expression *createTypeInfoArray(Scope *sc, Expression *exps[], unsigned dim)
{
#if 1
    /* Get the corresponding TypeInfo_Tuple and
     * point at its elements[].
     */

    /* Create the TypeTuple corresponding to the types of args[]
     */
    Parameters *args = new Parameters;
    args->setDim(dim);
    for (size_t i = 0; i < dim; i++)
    {   Parameter *arg = new Parameter(STCin, exps[i]->type, NULL, NULL);
        args->tdata()[i] = arg;
    }
    TypeTuple *tup = new TypeTuple(args);
    Expression *e = tup->getTypeInfo(sc);
    e = e->optimize(WANTvalue);
    assert(e->op == TOKsymoff);         // should be SymOffExp

#if BREAKABI
    /*
     * Should just pass a reference to TypeInfo_Tuple instead,
     * but that would require existing code to be recompiled.
     * Source compatibility can be maintained by computing _arguments[]
     * at the start of the called function by offseting into the
     * TypeInfo_Tuple reference.
     */

#else
    // Advance to elements[] member of TypeInfo_Tuple
    SymOffExp *se = (SymOffExp *)e;
    se->offset += PTRSIZE + PTRSIZE;

    // Set type to TypeInfo[]*
    se->type = Type::typeinfo->type->arrayOf()->pointerTo();

    // Indirect to get the _arguments[] value
    e = new PtrExp(0, se);
    e->type = se->type->next;
#endif
    return e;
#else
    /* Improvements:
     * 1) create an array literal instead,
     * as it would eliminate the extra dereference of loading the
     * static variable.
     */

    ArrayInitializer *ai = new ArrayInitializer(0);
    VarDeclaration *v;
    Type *t;
    Expression *e;
    OutBuffer buf;
    Identifier *id;
    char *name;

    // Generate identifier for _arguments[]
    buf.writestring("_arguments_");
    for (int i = 0; i < dim; i++)
    {   t = exps[i]->type;
        t->toDecoBuffer(&buf);
    }
    buf.writeByte(0);
    id = Lexer::idPool((char *)buf.data);

    Module *m = sc->module;
    Dsymbol *s = m->symtab->lookup(id);

    if (s && s->parent == m)
    {   // Use existing one
        v = s->isVarDeclaration();
        assert(v);
    }
    else
    {   // Generate new one

        for (int i = 0; i < dim; i++)
        {   t = exps[i]->type;
            e = t->getTypeInfo(sc);
            ai->addInit(new IntegerExp(i), new ExpInitializer(0, e));
        }

        t = Type::typeinfo->type->arrayOf();
        ai->type = t;
        v = new VarDeclaration(0, t, id, ai);
        m->members->push(v);
        m->symtabInsert(v);
        sc = sc->push();
        sc->linkage = LINKc;
        sc->stc = STCstatic | STCcomdat;
        ai->semantic(sc, t);
        v->semantic(sc);
        v->parent = m;
        sc = sc->pop();
    }
    e = new VarExp(0, v);
    e = e->semantic(sc);
    return e;
#endif
}
TEST(Expression_Builder, can_build_expression_whith_bracket) {
	ExpressionBuilder builder("(1+2)*3", NULL);
	Expression* expression = builder.Build();
	ASSERT_EQ( (1+2)*3, expression->Calculate());
}
Exemple #19
0
    void source_name(Dsymbol *s)
    {
        char *name = s->ident->toChars();
        TemplateInstance *ti = s->isTemplateInstance();
        if (ti)
        {
            if (!substitute(ti->tempdecl))
            {
                store(ti->tempdecl);
                name = ti->name->toChars();
                buf.printf("%d%s", strlen(name), name);
            }
            buf.writeByte('I');
            bool is_var_arg = false;
            for (size_t i = 0; i < ti->tiargs->dim; i++)
            {
                RootObject *o = (RootObject *)(*ti->tiargs)[i];

                TemplateParameter *tp = NULL;
                TemplateValueParameter *tv = NULL;
                TemplateTupleParameter *tt = NULL;
                if (!is_var_arg)
                {
                    TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration();
                    tp = (*td->parameters)[i];
                    tv = tp->isTemplateValueParameter();
                    tt = tp->isTemplateTupleParameter();
                }
                /*
                 *           <template-arg> ::= <type>            # type or template
                 *                          ::= <expr-primary>   # simple expressions
                 */

                if (tt)
                {
                    buf.writeByte('I');
                    is_var_arg = true;
                    tp = NULL;
                }

                if (tv)
                {
                    // <expr-primary> ::= L <type> <value number> E                   # integer literal
                    if (tv->valType->isintegral())
                    {
                        Expression* e = isExpression(o);
                        assert(e);
                        buf.writeByte('L');
                        tv->valType->accept(this);
                        if (tv->valType->isunsigned())
                        {
                            buf.printf("%llu", e->toUInteger());
                        }
                        else
                        {
                            dinteger_t val = e->toInteger();
                            if (val < 0)
                            {
                                val = -val;
                                buf.writeByte('n');
                            }
                            buf.printf("%lld", val);
                        }
                        buf.writeByte('E');
                    }
                    else
                    {
                        s->error("ICE: C++ %s template value parameter is not supported", tv->valType->toChars());
                        assert(0);
                    }
                }
                else if (!tp || tp->isTemplateTypeParameter())
                {
                    Type *t = isType(o);
                    assert(t);
                    t->accept(this);
                }
                else if (tp->isTemplateAliasParameter())
                {
                    Dsymbol* d = isDsymbol(o);
                    Expression* e = isExpression(o);
                    if (!d && !e)
                    {
                        s->error("ICE: %s is unsupported parameter for C++ template: (%s)", o->toChars());
                        assert(0);
                    }
                    if (d && d->isFuncDeclaration())
                    {
                        bool is_nested = d->toParent() && !d->toParent()->isModule() && ((TypeFunction *)d->isFuncDeclaration()->type)->linkage == LINKcpp;
                        if (is_nested) buf.writeByte('X');
                        buf.writeByte('L');
                        mangle_function(d->isFuncDeclaration());
                        buf.writeByte('E');
                        if (is_nested) buf.writeByte('E');
                    }
                    else if (e && e->op == TOKvar && ((VarExp*)e)->var->isVarDeclaration())
                    {
                        VarDeclaration *vd = ((VarExp*)e)->var->isVarDeclaration();
                        buf.writeByte('L');
                        mangle_variable(vd, true);
                        buf.writeByte('E');
                    }
                    else if (d && d->isTemplateDeclaration() && d->isTemplateDeclaration()->onemember)
                    {
                        if (!substitute(d))
                        {
                            cpp_mangle_name(d);
                            store(d);
                        }
                    }
                    else
                    {
                        s->error("ICE: %s is unsupported parameter for C++ template", o->toChars());
                        assert(0);
                    }

                }
                else
                {
                    s->error("ICE: C++ templates support only integral value , type parameters, alias templates and alias function parameters");
                    assert(0);
                }
            }
            if (is_var_arg)
            {
                buf.writeByte('E');
            }
            buf.writeByte('E');
            return;
        }
        else
        {
            buf.printf("%d%s", strlen(name), name);
        }
    }
TEST(Expression_Builder, can_expression_whith_unary_minus) {
	ExpressionBuilder builder("-3*2", NULL);
	Expression* expression = builder.Build();
	ASSERT_EQ(-3*2, expression->Calculate());
}
FunctionInvocation *
FunctionInvocation::make_random_binary_ptr_comparison(CGContext &cg_context)
{
	eBinaryOps op = rnd_flipcoin(50) ? eCmpEq : eCmpNe;
	ERROR_GUARD(NULL);
	SafeOpFlags *flags = SafeOpFlags::make_random_binary(get_int_type(), NULL, NULL, sOpBinary, op);
	ERROR_GUARD(NULL);

	FunctionInvocation *fi = FunctionInvocationBinary::CreateFunctionInvocationBinary(cg_context, op, flags);
	const Type* type = Type::choose_random_pointer_type();
	ERROR_GUARD_AND_DEL1(NULL, fi);

	Effect lhs_eff_accum;
	CGContext lhs_cg_context(cg_context, cg_context.get_effect_context(), &lhs_eff_accum);
	lhs_cg_context.flags |= NO_DANGLING_PTR;
	Expression *lhs = Expression::make_random(lhs_cg_context, type, 0, true);
	ERROR_GUARD_AND_DEL1(NULL, fi);
	cg_context.merge_param_context(lhs_cg_context, true);

	// now focus on RHS ...
	enum eTermType tt = MAX_TERM_TYPES;
	// if LHS is const, there is no need for RHS to be const as well
	if (lhs->term_type == eConstant) {
		tt = eVariable;
	}
	Expression *rhs = 0;

	// If we are guaranteed that the LHS will be evaluated before the RHS,
	// or if the LHS is pure (not merely side-effect-free),
	// then we can generate the RHS under the original effect context.
	if (IsOrderedStandardFunc(op)) { //  lhs_eff_accum.is_pure())  JYTODO: purity needs to be redefined
		// although we don't need care about other side effect, we do
		// need to pass in NO_DANGLING_PTR flag
		unsigned int old_flag = cg_context.flags;
		cg_context.flags |= NO_DANGLING_PTR;
		rhs = Expression::make_random(cg_context, type, 0, true, false, tt);
		cg_context.flags = old_flag;
	} else {
		// Otherwise, the RHS must be generated under the combined effect
		// of the original effect and the LHS effect.
		Effect rhs_eff_context(cg_context.get_effect_context());
		rhs_eff_context.add_effect(lhs_eff_accum);
		Effect rhs_eff_accum;

		CGContext rhs_cg_context(cg_context, rhs_eff_context, &rhs_eff_accum);
		rhs_cg_context.flags |= NO_DANGLING_PTR;
		rhs = Expression::make_random(rhs_cg_context, type, 0, true, false, tt);
		cg_context.merge_param_context(rhs_cg_context, true);
	}
	ERROR_GUARD_AND_DEL2(NULL, fi, lhs);

	// typecast, if needed.
	rhs->check_and_set_cast(&lhs->get_type());

	// TODO: fix `rhs' for eLShift and eRShift and ...
	// Currently, the "fix" is handled in `FunctionInvocationBinary::Output'.
	fi->param_value.push_back(lhs);
	fi->param_value.push_back(rhs);
	fi->ptr_cmp = true;

	// bookkeeping for pointers
	Bookkeeper::record_pointer_comparisons(lhs, rhs);
	return fi;
}
TEST(Expression_Builder, can_expression_whith_unary_minus_and_whith_bracket) {
	ExpressionBuilder builder("4*(-3)", NULL);
	Expression* expression = builder.Build();
	ASSERT_EQ(4*(-3), expression->Calculate());
}
Exemple #23
0
Fichier : enum.c Projet : eco/dmd
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 && !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;
}
TEST(Expression_Builder, can_expression_whith_variable) {
	ExpressionBuilder builder("a*(1+2)", new ConsoleStub(2)); // à = 2;
	Expression* expression = builder.Build();
	ASSERT_EQ(2*(1 + 2), expression->Calculate());
}
Exemple #25
0
static BlockScopeRawPtr originalScope(StaticClassName *scn) {
  Expression *e = dynamic_cast<Expression*>(scn);
  if (e) return e->getOriginalScope();
  return dynamic_cast<Statement*>(scn)->getScope();
}
Walker::ApplyStatus NonConstDimExpressionWalker::operator () (SuifObject *x) {
    if (_rev_map.find(x) != _rev_map.end())
	return Walker::Continue;
    ArrayExpressionProxy exp(to<Expression>(x));        
    Expression *ref_exp = exp.get_array_address();

    ArrayTypeProxy type(exp.get_array_type());
    if (!type.has_non_const_bounds())
        return Walker::Continue;

    DataType *element_type = type.get_element_type();
    IInteger bit_size = element_type->get_bit_size();

    int dims = exp.get_dimension_count();
    int type_dims = type.get_dimension_count();

    Expression *index = 0;
    Expression *offset = 0;
    int missing_dims = type_dims - dims; // the more nested dims are the missing ones
    for (int i = type_dims-1;i >=0;i--) {
	// This code uses an iterative approach which is not good in general
	// as it serialises everything in the generated code
	Expression *low = type.get_lower_bound(i);
	Expression *next_index;
	if (i < missing_dims) {
	    next_index = low;
	    }
	else {
	    next_index = exp.get_index(i-missing_dims);
	    }
	if (!index) {
	    index = next_index;
	    offset = low;
	    }
	else {
            Expression *high = type.get_upper_bound(i);

            Expression *elements = build_dyadic_expression(k_add,
                                build_dyadic_expression(k_subtract,
                                                        high,
                                                        low),
                                create_int_constant(get_env(),
                                                    low->get_result_type(),
                                                    1));
	    index = build_dyadic_expression(k_add,
					    next_index,
					    build_dyadic_expression(k_multiply,
								    elements,
								    index));
            offset = build_dyadic_expression(k_add,
                                            low,
                                            build_dyadic_expression(k_multiply,
                                                                    elements,
                                                                    offset));
	    }
	}

    index = build_dyadic_expression(k_subtract,index,offset);
    ref_exp = create_array_reference_expression(	
					get_env(),
					type.get_element_type(),
					to<Expression>(ref_exp->deep_clone()),
					index);

    // next line is done automatically
    // x->get_parent()->replace(x,ref_exp); 
    _rev_map.enter_value(ref_exp,x);
    set_address(ref_exp);
    return Walker::Replaced;
}
void
ParallelCoordinatesViewerEnginePluginInfo::InitializePlotAtts(
    AttributeSubject *atts, const avtPlotMetaData &plot)
{
    // If we had scalar names, we can just copy the default atts
    // and return.
    if (defaultAtts->GetScalarAxisNames().size() != 0)
    {
        // One helpful thing we can do: make sure the user set the
        // visual axis names.  They really should have, but since
        // we can blindly copy them from the scalar axis names in
        // this case, no harm doing it for them.
        if (defaultAtts->GetVisualAxisNames().size() == 0)
            defaultAtts->SetVisualAxisNames(defaultAtts->GetScalarAxisNames());

        *(ParallelCoordinatesAttributes*)atts = *defaultAtts;

        return;
    }

    // Otherwise,  we must be an array variable; try to get
    // some names for its components....
    const avtDatabaseMetaData *md = plot.GetMetaData();
    const std::string &var = plot.GetVariableName();
    const avtArrayMetaData *array = md->GetArray(var);
    stringVector subNames;
    if (array)
    {
        subNames = array->compNames;
    }
    else
    {
        Expression *exp =
            ParsingExprList::GetExpression(plot.GetVariableName());
        if (exp == NULL || exp->GetType() != Expression::ArrayMeshVar)
        {
            debug3 << "ParallelCoordinatesAttributes::InitializePlotAtts: "
                   << "variable wasn't an array database variable, an "
                   << "array expression, or a list of scalars.  This can "
                   << "happen if the user attempts to create this plot "
                   << "without the use off a wizard, e.g. in the case of "
                   << "the cli.  Assuming this is the case and continuing "
                   << "without error.\n";
            return;
        }
        // If we have any problems walking the expression tree, just return;
        // the worst case scenario if we don't populate the visual axis
        // name list is that the GUI window is temporarily blank.
        ExprNode *root = ParsingExprList::GetExpressionTree(exp);
        if (root->GetTypeName() != "Function")
            return;
        FunctionExpr *fn = dynamic_cast<FunctionExpr*>(root);
        if (fn->GetName() != "array_compose" &&
            fn->GetName() != "array_compose_with_bins")
            return;
        ArgsExpr *argsExpr = fn->GetArgsExpr();
        std::vector<ArgExpr*> *args = argsExpr ? argsExpr->GetArgs() : NULL;
        if (!args)
            return;
        for (size_t i=0; i<args->size(); i++)
        {
            ExprNode *arg = (ExprNode*)((*args)[i]->GetExpr());
            if (arg->GetTypeName() == "List")
                break;
            subNames.push_back(arg->GetPos().GetText(exp->GetDefinition()));
        }
    }

    doubleVector extMin(subNames.size(), -1e+37);
    doubleVector extMax(subNames.size(), +1e+37);

    // Set up the default attributes to contain these values, so
    // if the user hits reset, the axis names are retained.
    defaultAtts->SetVisualAxisNames(subNames);
    defaultAtts->SetExtentMinima(extMin);
    defaultAtts->SetExtentMaxima(extMax);
    *(ParallelCoordinatesAttributes*)atts = *defaultAtts;
}
/**
    Convert ArrayReferenceExpression \a top_array to a 
    MultiDimArrayExpression.
*/
void OneDimArrayConverter::
convert_array_expr2multi_array_expr(ArrayReferenceExpression* top_array){
    Expression* expr = top_array;
    unsigned int i = 0;

    suif_vector<Expression*> lower_bounds;
    suif_vector<Expression*> upper_bounds;
    list<Expression*> indices;
    IInteger bit_size, bit_alignment;
    suif_vector<ArrayReferenceExpression *> exprs;

    do{
        ArrayReferenceExpression* are = to<ArrayReferenceExpression>(expr);
        expr = are->get_base_array_address();
        exprs.push_back(are);
	} while(is_kind_of<ArrayReferenceExpression>(expr));

    // collect bounds and indeces
    for (unsigned int exp_ind = 0; exp_ind < exprs.size();exp_ind++)
    {
        ArrayReferenceExpression* are = exprs[exp_ind];
        DataType* type = are->get_base_array_address()->get_result_type();
        ArrayType* array_type;

		if(is_kind_of<ArrayType>(type)){
			array_type = to<ArrayType>(type);
		}else{
			array_type = to<ArrayType>(
				unwrap_ptr_ref_type(type)->get_base_type());
		}
        
        bit_size = array_type->get_element_type()->
                get_base_type()->get_bit_size();
        bit_alignment = array_type->get_element_type()->
                get_base_type()->get_bit_alignment();

        // What happens to ArrayType?? Does it become garbage?
        suif_assert(array_type->get_lower_bound());
        suif_assert(array_type->get_upper_bound());

        // clone bounds and add to the lists
        lower_bounds.push_back(array_type->get_lower_bound());
        upper_bounds.push_back(array_type->get_upper_bound());
        // save the index
        Expression* index = are->get_index();
        remove_suif_object(index); index->set_parent(NULL);
        indices.push_back(index);

        suif_assert(upper_bounds[i]);
        suif_assert(lower_bounds[i]);
        suif_assert(indices[i]);

        i++;
	}

    // Build the offset for the expression. We have to traverse upwards to do this
    Expression *top_expr_base = exprs[exprs.size()-1]->get_base_array_address();
    
	DataType* top_expr_base_type = top_expr_base->get_result_type();
	ArrayType* top_array_type;
	if(is_kind_of<ArrayType>(top_expr_base_type)){
		top_array_type = to<ArrayType>(top_expr_base_type);
	}else{
		top_array_type = to<ArrayType>(tb->unqualify_data_type(unwrap_ptr_ref_type(
			top_expr_base_type)));
	}
    
	Expression* inc    = create_int_constant(suif_env, 1);
    Expression* offset = create_int_constant(suif_env, 0);
    suif_vector<Expression *> elements;

    for (unsigned int ind = 0;ind < lower_bounds.size(); ind ++)
    {
        Expression *lower = lower_bounds[ind];
        Expression *upper = upper_bounds[ind];

        offset = 
            build_dyadic_expression(k_add, 
                offset,
                build_dyadic_expression(
                    k_multiply, 
                    deep_suif_clone(inc),
                    deep_suif_clone(lower)));
        
        Expression *element =
                    build_dyadic_expression(k_add, 
                        build_dyadic_expression(k_subtract,
                            deep_suif_clone(upper), 
                            deep_suif_clone(lower)),
                        create_int_constant(suif_env,1));

        inc = build_dyadic_expression(k_multiply, 
            inc, 
            deep_suif_clone(element));

	    elements.push_back(element);
    }
    // Now, inc and offset are ready

    // retrieve the multi-type
    MultiDimArrayType* multi_type;
	suif_map<ArrayType*, MultiDimArrayType*>::iterator type_iter =
	    type_map->find(top_array_type);
#ifdef CONVERT_TYPES
    suif_assert_message((type_iter != type_map->end()),
        ("Array type never translated"));
#else
    if(type_iter == type_map->end()){
        multi_type = array_type2multi_array_type(top_array_type);
    }else
#endif //CONVERT_TYPES
    multi_type = (*type_iter).second;

    remove_suif_object(top_expr_base);

    // add a convert to the necessary type
    top_expr_base = create_unary_expression(suif_env, 
            tb->get_pointer_type(multi_type), 
            k_convert, top_expr_base);
    //top_expr_base->print_to_default();

    // construct the expression to be returned 
    MultiDimArrayExpression* mae =
        create_multi_dim_array_expression(suif_env,
            top_array->get_result_type(), 
            top_expr_base, 
            offset);

    // now when we have the expression, set the indices
    for (list<Expression*>::iterator ind_iter = indices.begin();
        ind_iter!=indices.end(); ind_iter++)
    {
        Expression* index = *ind_iter;
        //printf("%p \t", index);index->print_to_default();
        mae->append_index(index);
    }

    for (suif_vector<Expression *>::iterator eiter = elements.begin();
        eiter != elements.end(); eiter ++)
    {
        Expression* element = *eiter;
        mae->append_element(element);
    }

    replace_expression(top_array, mae);
}
 void ParamMapFixup::Do(const Expression& Exp)
 {
     ParamMapFixup Fixup;
     Exp->Accept(&Fixup);
     return;
 }
Exemple #30
0
Expression *AddrExp::optimize(int result)
{   Expression *e;

    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());

    /* Rewrite &(a,b) as (a,&b)
     */
    if (e1->op == TOKcomma)
    {	CommaExp *ce = (CommaExp *)e1;
	AddrExp *ae = new AddrExp(loc, ce->e2);
	ae->type = type;
	e = new CommaExp(ce->loc, ce->e1, ae);
	e->type = type;
	return e->optimize(result);
    }

    if (e1->op == TOKvar)
    {	VarExp *ve = (VarExp *)e1;
	if (ve->var->storage_class & STCmanifest)
	    e1 = e1->optimize(result);
    }
    else
	e1 = e1->optimize(result);

    // Convert &*ex to ex
    if (e1->op == TOKstar)
    {	Expression *ex;

	ex = ((PtrExp *)e1)->e1;
	if (type->equals(ex->type))
	    e = ex;
	else
	{
	    e = ex->copy();
	    e->type = type;
	}
	return e;
    }
    if (e1->op == TOKvar)
    {	VarExp *ve = (VarExp *)e1;
	if (!ve->var->isOut() && !ve->var->isRef() &&
	    !ve->var->isImportedSymbol())
	{
	    SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads);
	    se->type = type;
	    return se;
	}
    }
    if (e1->op == TOKindex)
    {	// Convert &array[n] to &array+n
	IndexExp *ae = (IndexExp *)e1;

	if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
	{
	    integer_t index = ae->e2->toInteger();
	    VarExp *ve = (VarExp *)ae->e1;
	    if (ve->type->ty == Tsarray
		&& !ve->var->isImportedSymbol())
	    {
		TypeSArray *ts = (TypeSArray *)ve->type;
		integer_t dim = ts->dim->toInteger();
		if (index < 0 || index >= dim)
		    error("array index %jd is out of bounds [0..%jd]", index, dim);
		e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
		e->type = type;
		return e;
	    }
	}
    }
    return this;
}