Пример #1
0
SEXP attribute_hidden do_subset2_dflt(SEXP call, SEXP op, SEXP args, SEXP rho)
{
    SEXP ans, dims, dimnames, indx, subs, x;
    int i, ndims, nsubs;
    int drop = 1, pok, exact = -1;
    int named_x;
    R_xlen_t offset = 0;

    PROTECT(args);
    ExtractDropArg(args, &drop);
    /* Is partial matching ok?  When the exact arg is NA, a warning is
       issued if partial matching occurs.
     */
    exact = ExtractExactArg(args);
    if (exact == -1)
	pok = exact;
    else
	pok = !exact;

    x = CAR(args);

    /* This code was intended for compatibility with S, */
    /* but in fact S does not do this.	Will anyone notice? */

    if (x == R_NilValue) {
	UNPROTECT(1); /* args */
	return x;
    }

    /* Get the subscripting and dimensioning information */
    /* and check that any array subscripting is compatible. */

    subs = CDR(args);
    if(0 == (nsubs = length(subs)))
	errorcall(call, _("no index specified"));
    dims = getAttrib(x, R_DimSymbol);
    ndims = length(dims);
    if(nsubs > 1 && nsubs != ndims)
	errorcall(call, _("incorrect number of subscripts"));

    /* code to allow classes to extend environment */
    if(TYPEOF(x) == S4SXP) {
        x = R_getS4DataSlot(x, ANYSXP);
	if(x == R_NilValue)
	  errorcall(call, _("this S4 class is not subsettable"));
    }
    PROTECT(x);

    /* split out ENVSXP for now */
    if( TYPEOF(x) == ENVSXP ) {
	if( nsubs != 1 || !isString(CAR(subs)) || length(CAR(subs)) != 1 )
	    errorcall(call, _("wrong arguments for subsetting an environment"));
	ans = findVarInFrame(x, installTrChar(STRING_ELT(CAR(subs), 0)));
	if( TYPEOF(ans) == PROMSXP ) {
	    PROTECT(ans);
	    ans = eval(ans, R_GlobalEnv);
	    UNPROTECT(1); /* ans */
	} else SET_NAMED(ans, 2);

	UNPROTECT(2); /* args, x */
	if(ans == R_UnboundValue)
	    return(R_NilValue);
	if (NAMED(ans))
	    SET_NAMED(ans, 2);
	return ans;
    }

    /* back to the regular program */
    if (!(isVector(x) || isList(x) || isLanguage(x)))
	errorcall(call, R_MSG_ob_nonsub, type2char(TYPEOF(x)));

    named_x = NAMED(x);  /* x may change below; save this now.  See PR#13411 */

    if(nsubs == 1) { /* vector indexing */
	SEXP thesub = CAR(subs);
	int len = length(thesub);

	if (len > 1) {
#ifdef SWITCH_TO_REFCNT
	    if (IS_GETTER_CALL(call)) {
		/* this is (most likely) a getter call in a complex
		   assighment so we duplicate as needed. The original
		   x should have been duplicated if it might be
		   shared */
		if (MAYBE_SHARED(x))
		    error("getter call used outside of a complex assignment.");
		x = vectorIndex(x, thesub, 0, len-1, pok, call, TRUE);
	    }
	    else
		x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE);
#else
	    x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE);
#endif
	    named_x = NAMED(x);
	    UNPROTECT(1); /* x */
	    PROTECT(x);
	}

	SEXP xnames = PROTECT(getAttrib(x, R_NamesSymbol));
	offset = get1index(thesub, xnames,
			   xlength(x), pok, len > 1 ? len-1 : -1, call);
	UNPROTECT(1); /* xnames */
	if (offset < 0 || offset >= xlength(x)) {
	    /* a bold attempt to get the same behaviour for $ and [[ */
	    if (offset < 0 && (isNewList(x) ||
			       isExpression(x) ||
			       isList(x) ||
			       isLanguage(x))) {
		UNPROTECT(2); /* args, x */
		return R_NilValue;
	    }
	    else errorcall(call, R_MSG_subs_o_b);
	}
    } else { /* matrix indexing */
	/* Here we use the fact that: */
	/* CAR(R_NilValue) = R_NilValue */
	/* CDR(R_NilValue) = R_NilValue */

	int ndn; /* Number of dimnames. Unlikely to be anything but
		    0 or nsubs, but just in case... */

	PROTECT(indx = allocVector(INTSXP, nsubs));
	dimnames = getAttrib(x, R_DimNamesSymbol);
	ndn = length(dimnames);
	for (i = 0; i < nsubs; i++) {
	    INTEGER(indx)[i] = (int)
		get1index(CAR(subs),
			  (i < ndn) ? VECTOR_ELT(dimnames, i) : R_NilValue,
			  INTEGER(indx)[i], pok, -1, call);
	    subs = CDR(subs);
	    if (INTEGER(indx)[i] < 0 ||
		INTEGER(indx)[i] >= INTEGER(dims)[i])
		errorcall(call, R_MSG_subs_o_b);
	}
	offset = 0;
	for (i = (nsubs - 1); i > 0; i--)
	    offset = (offset + INTEGER(indx)[i]) * INTEGER(dims)[i - 1];
	offset += INTEGER(indx)[0];
	UNPROTECT(1); /* indx */
    }

    if(isPairList(x)) {
#ifdef LONG_VECTOR_SUPPORT
	if (offset > R_SHORT_LEN_MAX)
	    error("invalid subscript for pairlist");
#endif
	ans = CAR(nthcdr(x, (int) offset));
	if (named_x > NAMED(ans))
	    SET_NAMED(ans, named_x);
    } else if(isVectorList(x)) {
	/* did unconditional duplication before 2.4.0 */
	ans = VECTOR_ELT(x, offset);
	if (named_x > NAMED(ans))
	    SET_NAMED(ans, named_x);
    } else {
	ans = allocVector(TYPEOF(x), 1);
	switch (TYPEOF(x)) {
	case LGLSXP:
	case INTSXP:
	    INTEGER(ans)[0] = INTEGER(x)[offset];
	    break;
	case REALSXP:
	    REAL(ans)[0] = REAL(x)[offset];
	    break;
	case CPLXSXP:
	    COMPLEX(ans)[0] = COMPLEX(x)[offset];
	    break;
	case STRSXP:
	    SET_STRING_ELT(ans, 0, STRING_ELT(x, offset));
	    break;
	case RAWSXP:
	    RAW(ans)[0] = RAW(x)[offset];
	    break;
	default:
	    UNIMPLEMENTED_TYPE("do_subset2", x);
	}
    }
    UNPROTECT(2); /* args, x */
    return ans;
}
Пример #2
0
// push negation as far down as possible, use demorgan's laws
//	~(A && B) identical to (~A || ~B), and
//	~(A || B) identical to (~A && ~B)
//
int
Semantic::demorgans()
{
	// check if atomic or an expression
	if (!isExpression())
		return(OK);

	// remove multiple NOTs, 
	//	use ~~A <--> A and
	//	use ~~~A <--> ~A rules.
	//
	if (removeExtraNots() != OK)
		return(NOTOK);

	// check if atomic or an expression. this second check
	// is required since it is possible that when all extra
	// negations are removed, only an Atomic is left.
	//
	if (!isExpression())
		return(OK);

	// check if we have a negated expression
	Expression *pe = (Expression *)prep;
	if (pe->type != Expression::Negation)
	{
		// not a negated expression, check left and right
		if (pe->left != NULL && pe->left->demorgans() != OK)
			return(NOTOK);
		if (pe->right != NULL && pe->right->demorgans() != OK)
			return(NOTOK);
		return(OK);
	}

	// we have a negation, check if rhs is atomic or an expression.
	Semantic *prs = pe->right;
	if (!(prs->isExpression()))
	{
		// what is negated is NOT an expression, just return.
		return(OK);
	}

	// check if expression is an AND or OR
	Expression *pre = (Expression *)prs->prep;
	if (pre->type != Expression::Or && pre->type != Expression::And)
	{
		// not a AND or OR expression, check left and right
		if (pre->left != NULL && pre->left->demorgans() != OK)
			return(NOTOK);
		if (pre->right != NULL && pre->right->demorgans() != OK)
			return(NOTOK);
		return(OK);
	}

	// we have a negated AND or OR expression, apply demorgans laws.
	Semantic *prels = pre->left;
	Semantic *prers = pre->right;

	// create new negation records
	Semantic *pnegls = new Semantic(Expression::Negation, NULL, prels);
	MustBeTrue(pnegls != NULL);
	Semantic *pnegrs = new Semantic(Expression::Negation, NULL, prers);
	MustBeTrue(pnegrs != NULL);

	// write over negation record with the new record info
	pe->left = pnegls;
	pe->right = pnegrs;
	switch (pre->type)
	{
	case Expression::Or:
		pe->type = Expression::And;
		break;
	case Expression::And:
		pe->type = Expression::Or;
		break;
	default:
		MustBeTrue(0);
		break;
	}

	// delete old right semantic record
	pre->left = NULL;
	pre->right = NULL;
	delete prs;

	// check left and right sides
	if (pe->left != NULL && pe->left->demorgans() != OK)
		return(NOTOK);
	if (pe->right != NULL && pe->right->demorgans() != OK)
		return(NOTOK);

	// all done
	return(OK);
}
Пример #3
0
/* Calculate the bounding rectangle for a string.
 * x and y assumed to be in INCHES.
 */
void textRect(double x, double y, SEXP text, int i,
	      const pGEcontext gc,
	      double xadj, double yadj,
	      double rot, pGEDevDesc dd, LRect *r)
{
    /* NOTE that we must work in inches for the angles to be correct
     */
    LLocation bl, br, tr, tl;
    LLocation tbl, tbr, ttr, ttl;
    LTransform thisLocation, thisRotation, thisJustification;
    LTransform tempTransform, transform;
    double w, h;
    if (isExpression(text)) {
	SEXP expr = VECTOR_ELT(text, i % LENGTH(text));
	w = fromDeviceWidth(GEExpressionWidth(expr, gc, dd),
			    GE_INCHES, dd);
	h = fromDeviceHeight(GEExpressionHeight(expr, gc, dd),
			     GE_INCHES, dd);
    } else {
	const char* string = CHAR(STRING_ELT(text, i % LENGTH(text)));
	w = fromDeviceWidth(GEStrWidth(string,
				       (gc->fontface == 5) ? CE_SYMBOL :
				       getCharCE(STRING_ELT(text, i % LENGTH(text))),
				       gc, dd),
			    GE_INCHES, dd);
	h = fromDeviceHeight(GEStrHeight(string,
					 (gc->fontface == 5) ? CE_SYMBOL :
					 getCharCE(STRING_ELT(text, i % LENGTH(text))),
					 gc, dd),
			     GE_INCHES, dd);
    }
    location(0, 0, bl);
    location(w, 0, br);
    location(w, h, tr);
    location(0, h, tl);
    translation(-xadj*w, -yadj*h, thisJustification);
    translation(x, y, thisLocation);
    if (rot != 0)
	rotation(rot, thisRotation);
    else
	identity(thisRotation);
    /* Position relative to origin of rotation THEN rotate.
     */
    multiply(thisJustification, thisRotation, tempTransform);
    /* Translate to (x, y)
     */
    multiply(tempTransform, thisLocation, transform);
    trans(bl, transform, tbl);
    trans(br, transform, tbr);
    trans(tr, transform, ttr);
    trans(tl, transform, ttl);
    rect(locationX(tbl), locationX(tbr), locationX(ttr), locationX(ttl),
	 locationY(tbl), locationY(tbr), locationY(ttr), locationY(ttl),
	 r);
    /* For debugging, the following prints out an R statement to draw the
     * bounding box
     */
    /*
    Rprintf("\ngrid.lines(c(%f, %f, %f, %f, %f), c(%f, %f, %f, %f, %f), default.units=\"inches\")\n",
	locationX(tbl), locationX(tbr), locationX(ttr), locationX(ttl),
	 locationX(tbl),
	 locationY(tbl), locationY(tbr), locationY(ttr), locationY(ttl),
	 locationY(tbl)
	 );
    */
}
Пример #4
0
// remove existential quantifier by using skolem functions. all skolem
// functions must be unique. remember that the skolem function is dependent
// on any universal variables that are in scope.
//
int
Semantic::skolemize(List<Symbol> &localscope)
{
	// check if expression or predicate
	if (isExpression())
	{
		// get expression
		Expression *pe = (Expression *)prep;

		// what type is it
		if (pe->type == Expression::Universal)
		{
			// store universal variable
			localscope.insertAtEnd(Symbol(pe->name, 
				Symbol::UniversalVariable));

			// follow right leg, left leg is null
			MustBeTrue(pe->left == NULL && pe->right != NULL);
			if (pe->right->skolemize(localscope) != OK)
				return(NOTOK);

			// remove universal variable
			Symbol tmp;
			localscope.removeAtEnd(tmp);
		}
		else if (pe->type == Expression::Existential)
		{
			// store existential variable
			String uname = uniqueName(String("_SK"));
			localscope.insertAtEnd(Symbol(pe->name, uname,
				Symbol::ExistentialVariable));

			// follow right leg, left leg is null
			MustBeTrue(pe->left == NULL && pe->right != NULL);
			if (pe->right->skolemize(localscope) != OK)
				return(NOTOK);

			// remove existential variable
			Symbol tmp;
			localscope.removeAtEnd(tmp);
		}
		else
		{
			// follow down other expression operators
			if (pe->left != NULL && 
			    pe->left->skolemize(localscope) != OK)
				return(NOTOK);
			if (pe->right != NULL && 
			    pe->right->skolemize(localscope) != OK)
				return(NOTOK);
		}
		
	}
	else if (isPredicate())
	{
		// get predicate
		Predicate *pp = (Predicate *)prep;

		// check for functions
		if (pp->type == Predicate::Function)
		{
			// cycle thru arguments
			ListIterator<Semantic * > pargsIter(*pp->pargs);
			for ( ; !pargsIter.done(); pargsIter++)
			{
				Semantic *parg = pargsIter();
				if (parg != NULL && 
				    parg->skolemize(localscope) != OK)
					return(NOTOK);
			}
		}
	}
	else if (isArgument())
	{
		// check type of argument
		Argument *pa = (Argument *)prep;
		switch (pa->type)
		{
		case Argument::Variable:
		{
			// check if an existential variable
			Symbol qvarsym(pa->name);
			if(localscope.retrieve(qvarsym) != OK)
				break;
			if (qvarsym.getType() != Symbol::ExistentialVariable)
				break;

			// we have an existential variable
			String skolemName(qvarsym.getUniqueName());

			// need to replace this variable with a 
			// skolem function which is dependent on all
			// universal variables in scope at this time.
			//
			List<Semantic * > *pargs = new List<Semantic * >;
			MustBeTrue(pargs != NULL);
			ListIterator<Symbol> scopeIter(localscope);
			int nargs;
			for (nargs = 0; !scopeIter.done(); scopeIter++)
			{
				// get symbol
				Symbol uvar = scopeIter();

				// check if we found the current 
				// symbol. this marks the end of 
				// dependent variables for the 
				// skolem function. all other
				// existential variables are skipped.
				//
				if (uvar.getType() == 
					Symbol::ExistentialVariable)
				{
					if (uvar == Symbol(pa->name))
						break;
					else
						continue;
				}

				// we have a universal variable in
				// scope
				//
				Semantic *parg = new Semantic(
					Argument::Variable, uvar.getName());
				MustBeTrue(parg != NULL);
				pargs->insertAtEnd(parg);
				nargs++;
			}
			if (nargs == 0)
			{
				// skolem constant
				pa->type = Argument::Constant;
				pa->name = skolemName;
				pa->pargs = NULL;
				pa->argnum = 0;

				// delete unused argument list
				delete pargs;
			}
			else
			{
				// skolem function
				pa->type = Argument::Function;
				pa->name = skolemName;
				pa->pargs = pargs;
				pa->argnum = nargs;
			}
			break;
		}

		case Argument::Function:
		{
			// we have a function, scan its arguments
			ListIterator<Semantic *> pargsIter(*pa->pargs);
			for ( ; !pargsIter.done(); pargsIter++)
			{
				Semantic *parg = pargsIter();
				if (parg != NULL && 
				    parg->skolemize(localscope) != OK)
					return(NOTOK);
			}
			break;
		}
		}
	}
	else
	{
		MustBeTrue(0);
	}

	// all done
	return(OK);
}
Пример #5
0
int
Semantic::skolemize()
{
	// check if expression or predicate
	// if it's a predicate, there is nothing to do
	// since we are at the beginning of the expression,
	// and quantifiers are expressions.
	//
	if (!isExpression())
		return(OK);

	// list of variables in scope
	List<Symbol> localscope;

	// get expression
	Expression *pe = (Expression *)prep;

	// what type is it
	if (pe->type == Expression::Universal)
	{
		// store universal variable
		localscope.insertAtEnd(Symbol(pe->name, 
			Symbol::UniversalVariable));

		// follow right leg, left leg is null
		MustBeTrue(pe->left == NULL && pe->right != NULL);
		if (pe->right->skolemize(localscope) != OK)
			return(NOTOK);

		// remove universal variable
		Symbol tmp;
		localscope.removeAtEnd(tmp);
	}
	else if (pe->type == Expression::Existential)
	{
		// store existential variable
		String uname = uniqueName(String("_SK"));
		localscope.insertAtEnd(Symbol(pe->name, uname,
			Symbol::ExistentialVariable));

		// follow right leg, left leg is null
		MustBeTrue(pe->left == NULL && pe->right != NULL);
		if (pe->right->skolemize(localscope) != OK)
			return(NOTOK);

		// remove existential variable
		Symbol tmp(pe->name);
		localscope.removeAtEnd(tmp);
	}
	else
	{
		// follow down other expression operators
		if (pe->left != NULL && pe->left->skolemize(localscope) != OK)
			return(NOTOK);
		if (pe->right != NULL && pe->right->skolemize(localscope) != OK)
			return(NOTOK);
	}

	// scan one more time to remove existential records
	return(removeExistentials());
}
Пример #6
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);
        PROT protection = s->prot();

        const char *protName = Pprotectionnames[protection];

        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->userAttributes, s->userAttributesScope);
        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);
                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);
}
Пример #7
0
// rename all variable names to unique names.
int
Semantic::renameVariables(List<Symbol> &localscope)
{
	// check of predicate or expression
	if (isExpression())
	{
		// get expression record
		Expression *pe = (Expression *)prep;

		// check if we have quantifier
		int popscope = 0;
		if (pe->type == Expression::Universal)
		{
			// we have a quantifier, rename variable
			popscope = 1;
			String uname = uniqueName(String("_Q"));
			localscope.insertAtFront(
				Symbol(pe->name, uname, 
				Symbol::UniversalVariable));

			// change name in semantic record
			pe->name = uname;
		}
		else if (pe->type == Expression::Existential)
		{
			// we have a quantifier, rename variable
			popscope = 1;
			String uname = uniqueName(String("_Q"));
			localscope.insertAtFront(
				Symbol(pe->name, uname, 
				Symbol::ExistentialVariable));

			// change name in semantic record
			pe->name = uname;
		}

		// follow left and right branches
		if (pe->left != NULL && 
		    pe->left->renameVariables(localscope) != OK) 
			return(NOTOK);
		if (pe->right != NULL && 
		    pe->right->renameVariables(localscope) != OK)
			return(NOTOK);

		// pop scope variable if required
		if (popscope)
		{
			Symbol tmp;
			MustBeTrue(localscope.removeAtFront(tmp) == OK);
		}
	}
	else if (isPredicate())
	{
		// get predicate record
		Predicate *pp = (Predicate *)prep;

		// check if a function
		if (pp->type == Predicate::Function)
		{
			// we have a function, scan argument list
			ListIterator<Semantic *> pargsIter(*pp->pargs);
			for ( ; !pargsIter.done(); pargsIter++)
			{
				Semantic *parg = pargsIter();
				if (parg != NULL && 
				    parg->renameVariables(localscope) != OK)
					return(NOTOK);
			}
		}
	}
	else if (isArgument())
	{
		// check if a variable, function or anything else
		Argument *pa = (Argument *)prep;
		if (pa->type == Argument::Variable)
		{
			// find variable in scope
			Symbol usym(pa->name);
			if (localscope.retrieve(usym) == OK)
			{
				pa->name = usym.getUniqueName();
				MustBeTrue(pa->name != String(""));
			}
		}
		else if (pa->type == Argument::Function)
		{
			// we have a function, scan argument list
			ListIterator<Semantic *> pargsIter(*pa->pargs);
			for ( ; !pargsIter.done(); pargsIter++)
			{
				Semantic *parg = pargsIter();
				if (parg != NULL && 
				    parg->renameVariables(localscope) != OK)
					return(NOTOK);
			}
		}
	}
	else
	{
		MustBeTrue(0);
	}

	// all done
	return(OK);
}
Пример #8
0
// Logic:
// - If it is a number then just add it to the actions vector (but adding two
// times a number is not allowed as "3 4 6 =" is not a correct syntax. "3 + 6 =" would be correct.)
// - If it is an expression-operation (like "3+4-") then do the operation with the operation before that
// ("3+4" in the example) and add it to "left expression" (m_leftExpression).
// - If it is a term-operation (like 3+4x) add the left number (3) to m_leftExpression and
// the right handside number (4) of the expression operation to m_leftTerm.
// - "=" and "None" as an operation means that a totally new calculation started from there,
// meaning that the first number after them are just assigned to "left expression" (m_leftExpression).
// After "=" and "None" the first temporary results (untill the next expression operator)
// go to m_leftTerm and m_leftExpression remains zero.
// return value: Returns true if input was valid otherwise false
bool Calculator::addInput(const Action& input)
{
    const Calculator::Action lastInput = getLastInput();

    if (input.actionType == ActionType::Number)
    {
        // adding a number after a number would be an error -> that entry is ignored
        if (lastInput.actionType != ActionType::Number)
            m_actions.push_back(input);
    }
    else if (isOperation(input.actionType))
    {
        if (lastInput.actionType == ActionType::Number)
        {
            ActionType lastOperation = getLastOperation();
            switch (lastOperation)
            {
            case ActionType::Plus:
                if (isExpression(input.actionType) || input.actionType == ActionType::Equals)
                {
                    // "3 + 4 -", "3 + 4 ="
                    m_leftExpression.add(lastInput.value);
                    m_leftTerm.reset();
                }
                else if (isTerm(input.actionType))
                {
                    // "3 + 4 x",
                    m_leftTerm.set(lastInput.value);
                }
                break;
            case ActionType::Minus:
                if (isExpression(input.actionType) || input.actionType == ActionType::Equals)
                {
                    // "3 - 4 -", "3 - 4 ="
                    m_leftExpression.add(-lastInput.value);
                    m_leftTerm.reset();
                }
                else if (isTerm(input.actionType))
                {
                    // "3 - 4 x",
                    m_leftTerm.set(-lastInput.value);
                }
                break;
            case ActionType::Multiply:
                if (isExpression(input.actionType) || input.actionType == ActionType::Equals)
                {
                    // "3 x 4 +", "3 x 4 ="
                    m_leftExpression.add(m_leftTerm.getValue() * lastInput.value);
                    m_leftTerm.reset();
                }
                else if (isTerm(input.actionType)) // "3 x 4 x"
                    m_leftTerm.multiplyBy(lastInput.value);
                break;
            case ActionType::Divide:
                if (isExpression(input.actionType) || input.actionType == ActionType::Equals)
                {
                    if (lastInput.value == 0.0)
                    {
                        CalculatorException divByZeroException("Error: Cannot Divide By Zero",
                                                               CalculatorException::ExceptionType::DividedByZero);
                        throw divByZeroException;
                    }
                    else
                    {
                        // "3 / 4 +", "3 / 4 ="
                        m_leftExpression.add(m_leftTerm.getValue() / lastInput.value);
                        m_leftTerm.reset();
                    }
                }
                else if (isTerm(input.actionType)) // "3 / 4 x"
                    m_leftTerm.multiplyBy(1.0 / lastInput.value);
                break;
            case ActionType::Equals: // "=" is the start of a new beginnning, see (h: *)
                if (isTerm(input.actionType))
                {
                    // "= 3 x "
                    m_leftExpression.reset();
                    m_leftTerm.set(lastInput.value);
                }
                else if (isExpression(input.actionType))
                {
                    // "= 3 + "
                    m_leftExpression.set(lastInput.value);
                    m_leftTerm.reset();
                }
                break;
            case ActionType::None: // "None" is the start of a new beginnning, see (h: *)
                if (isTerm(input.actionType))
                {
                    // "3 x "
                    m_leftExpression.reset();
                    m_leftTerm.set(lastInput.value);
                }
                else if (isExpression(input.actionType))
                {
                    // "3 + "
                    m_leftExpression.set(lastInput.value);
                    m_leftTerm.reset();
                }
                break;
            }
            m_actions.push_back(input);
            return true;
        }
    }
    return false;
}
Пример #9
0
QString QgsFieldExpressionWidget::asExpression() const
{
  return isExpression() ? currentText() : QgsExpression::quotedColumnRef( currentText() );
}
/*配列範囲外参照と未定義処理の検証式の生成*/
void writeArrayCheck(CSTLString *output, ARRAY_OFFSET_LISTIterator aoff_list_i, int undefined_control_check, int array_unbound_check){
	int array_offset_level;

	int offset_level_counter;

	OFFSET_LISTIterator off_list_i;
	//オフセットレベルの取得
	array_offset_level = OFFSET_LIST_size(ARRAY_OFFSET_LIST_data(aoff_list_i)->offset_list);

	//オフセットレベルが0を超える場合(すなわち、オフセット情報が存在する場合)
	if(array_offset_level > 0){

	//配列の形を保持する情報(処理中で使用される)
		CSTLString *array_string = CSTLString_new();
		CSTLString *basis_location_content = CSTLString_new();
		CSTLString_assign(array_string, "");
		CSTLString_assign(basis_location_content, "");

		//オフセット情報を参照する
		for(offset_level_counter = 1, off_list_i = OFFSET_LIST_begin(ARRAY_OFFSET_LIST_data(aoff_list_i)->offset_list);
			off_list_i != OFFSET_LIST_end(ARRAY_OFFSET_LIST_data(aoff_list_i)->offset_list);
			offset_level_counter++, off_list_i = OFFSET_LIST_next(off_list_i)){
				int is_expression_flag = isExpression(*OFFSET_LIST_data(off_list_i));
				CSTLString *statement = CSTLString_new();

				//未定義処理チェックフラグが成り立っている場合、
				//レベルごとの未定義処理の検証式を生成する。未定義処理の検証式の形式は以下の通りである。
				//if(defined_階層_変数名 == 0 && max_size_階層_変数名 == 0){
				//	printf("#ファイル名#:行数: detected undefine pointer access in variable 変数名);
				//	assert(0);
				//	リターン式;
				//}
				if(undefined_control_check){

					CSTLString_printf(statement,0,"if(*defined_%d_%s%s == 0 && *malloc_flag_%d_%s%s == 0){\n",
								 offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string),
								 offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string)
							);

					CSTLString_printf(statement,1,"printf(\"#%s#:%d: detected undefine pointer access in variable %s\");\n ",getFileName(), ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->line, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name));

					CSTLString_printf(statement, 1, "assert(0);\n");

					//リターン命令の返却型に応じる変更(もし、void型であれば、「return;」にする)
					if(CSTLString_compare_with_char(ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->return_type, "void") == 0){
						CSTLString_printf(statement, 1, "return;\n");
					}else{
						CSTLString_printf(statement, 1, "return 1;\n");
					}

					CSTLString_printf(statement, 1, "}\n");

				}

				//配列範囲外チェックフラグが成り立っていた場合、
				//レベルごとの配列範囲外参照の検証式を生成する。配列範囲外参照の式の形式は以下の通りである
				//if(0 > 式 + 基本位置 || 式 + 基本位置 < 対象変数の配列長){
				//	printf("#ファイル名#:行数: detected unbound access in variable 変数名 basis_location = %d 式 = %d\n", basis_location, 式);
				//	assert(0);
				//	リターン式;
				//}
				if(array_unbound_check){
					CSTLString_printf(statement,1,"if(0 > %s + basis_location_%d_%s%s){\n",
								 *OFFSET_LIST_data(off_list_i), offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string));
					/*
					CSTLString_printf(statement,1,"printf(\"#%s#:%d:detected unbound access in variable %s ",getFileName(), ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->line, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name));

					//basis_locationの内容も出力する
					CSTLString_printf(statement,1," basis_location = %%d ");

					//もし、オフセットの内容が式であれば、式=値という形で出力する
					if(is_expression_flag == 1){
						CSTLString_printf(statement,1,"(%s = %%d)\\n\"", *OFFSET_LIST_data(off_list_i));
						//basis_locationの内容を含めた引数の内容を入れる
						CSTLString_printf(statement,1,", basis_location_%d_%s%s, %s",offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string) , *OFFSET_LIST_data(off_list_i));
					}

					//そうでなければ、値という形で出力する
					else{
						CSTLString_printf(statement,1,"(%s)\\n\"", *OFFSET_LIST_data(off_list_i));
						//basis_locationの内容の引数の内容を入れる
						CSTLString_printf(statement,1,", basis_location_%d_%s%s", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string));
					}
					CSTLString_printf(statement, 1, ");\n");
					*/
					//エラーのXMLを出力
					CSTLString_printf(statement,1,"printf(\"<error type = #dquot#Lower Unbound#dquot# variable=#dquot#%s#dquot#>\");\n",(char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name));
					if(is_expression_flag == 1){
						CSTLString_printf(statement,1,"printf(\"<expression text=#dquot#%s#dquot# value=#dquot#%%d#dquot#></expression>\",%s);\n", *OFFSET_LIST_data(off_list_i), *OFFSET_LIST_data(off_list_i));
					}else{
						CSTLString_printf(statement,1,"printf(\"<expression value=#dquot#%%d#dquot#></expression>\",%s);\n",*OFFSET_LIST_data(off_list_i));
					}
					CSTLString_printf(statement,1,"printf(\"<basic_location value=#dquot#%%d#dquot#></basic_location>\", basis_location_%d_%s%s);\n", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string));
					CSTLString_printf(statement,1,"printf(\"</error>\");\n");
					CSTLString_printf(statement,1,"printf(\"</source>\");\n");

					CSTLString_printf(statement, 1, "assert(0);\n");

					//リターン命令の返却型に応じる変更(もし、void型であれば、「return;」にする)
					if(CSTLString_compare_with_char(ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->return_type, "void") == 0){
						CSTLString_printf(statement, 1, "return;\n");
					}else{
						CSTLString_printf(statement, 1, "return 1;\n");
					}

					CSTLString_printf(statement, 1, "}\n");
					CSTLString_printf(statement, 1, "if(%s + basis_location_%d_%s%s >= *max_size_%d_%s%s){",
							*OFFSET_LIST_data(off_list_i), offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string),
							offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string));
					//エラーのXMLを出力
					outputErrorXml(statement, aoff_list_i, off_list_i, offset_level_counter, array_string);
/*					CSTLString_printf(statement,1,"printf(\"<error type = #dquot#Upper Unbound#dquot# variable=#dquot#%s#dquot#>\");\n",(char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name));
					if(is_expression_flag == 1){
						CSTLString_printf(statement,1,"printf(\"<expression text=#dquot#%s#dquot# value=#dquot#%%d#dquot#></expression>\",%s);\n", *OFFSET_LIST_data(off_list_i), *OFFSET_LIST_data(off_list_i));
					}else{
						CSTLString_printf(statement,1,"printf(\"<expression value=#dquot#%%d#dquot#></expression>\",%s);\n",*OFFSET_LIST_data(off_list_i));
					}
					CSTLString_printf(statement,1,"printf(\"<basic_location value=#dquot#%%d#dquot#></basic_location>\", basis_location_%d_%s%s);\n", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string));
					CSTLString_printf(statement,1,"printf(\"</error>\");\n");
					CSTLString_printf(statement,1,"printf(\"</source>\");\n");*/

					CSTLString_printf(statement, 1, "assert(0);\n");

					//リターン命令の返却型に応じる変更(もし、void型であれば、「return;」にする)
					if(CSTLString_compare_with_char(ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->return_type, "void") == 0){
						CSTLString_printf(statement, 1, "return;\n");
					}else{
						CSTLString_printf(statement, 1, "return 1;\n");
					}

					CSTLString_printf(statement, 1, "}\n");
				}
				CSTLString_printf(output, 1, "%s", (char*)CSTLString_c_str(statement));

				//次のレベルのための配列を生成する。
				CSTLString_printf(basis_location_content, 0, "basis_location_%d_%s%s", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string));
				CSTLString_printf(array_string, 1," [ %s + %s ]", *OFFSET_LIST_data(off_list_i), (char*)CSTLString_c_str(basis_location_content));
				CSTLString_delete(statement);
		}

		CSTLString_delete(array_string);
		CSTLString_delete(basis_location_content);

	}

}
Пример #11
0
shared_ptr<Object> Context::getProperty(const string& expression) {
	assert (isExpression(expression));

	return impl->evaluateObject(expression);
}
Пример #12
0
Expression *TraitsExp::semantic(Scope *sc)
{
#if LOGSEMANTIC
    printf("TraitsExp::semantic() %s\n", toChars());
#endif
    if (ident != Id::compiles && ident != Id::isSame)
	TemplateInstance::semanticTiargs(loc, sc, args, 1);
    size_t dim = args ? args->dim : 0;
    Object *o;
    FuncDeclaration *f;

#define ISTYPE(cond) \
	for (size_t i = 0; i < dim; i++)	\
	{   Type *t = getType((Object *)args->data[i]);	\
	    if (!t)				\
		goto Lfalse;			\
	    if (!(cond))			\
		goto Lfalse;			\
	}					\
	if (!dim)				\
	    goto Lfalse;			\
	goto Ltrue;

#define ISDSYMBOL(cond) \
	for (size_t i = 0; i < dim; i++)	\
	{   Dsymbol *s = getDsymbol((Object *)args->data[i]);	\
	    if (!s)				\
		goto Lfalse;			\
	    if (!(cond))			\
		goto Lfalse;			\
	}					\
	if (!dim)				\
	    goto Lfalse;			\
	goto Ltrue;



    if (ident == Id::isArithmetic)
    {
	ISTYPE(t->isintegral() || t->isfloating())
    }
    else if (ident == Id::isFloating)
    {
	ISTYPE(t->isfloating())
    }
    else if (ident == Id::isIntegral)
    {
	ISTYPE(t->isintegral())
    }
    else if (ident == Id::isScalar)
    {
	ISTYPE(t->isscalar())
    }
    else if (ident == Id::isUnsigned)
    {
	ISTYPE(t->isunsigned())
    }
    else if (ident == Id::isAssociativeArray)
    {
	ISTYPE(t->toBasetype()->ty == Taarray)
    }
    else if (ident == Id::isStaticArray)
    {
	ISTYPE(t->toBasetype()->ty == Tsarray)
    }
    else if (ident == Id::isAbstractClass)
    {
	ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
    }
    else if (ident == Id::isFinalClass)
    {
	ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
    }
    else if (ident == Id::isAbstractFunction)
    {
	ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
    }
    else if (ident == Id::isVirtualFunction)
    {
	ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
    }
    else if (ident == Id::isFinalFunction)
    {
	ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
    }
    else if (ident == Id::hasMember ||
	     ident == Id::getMember ||
	     ident == Id::getVirtualFunctions)
    {
	if (dim != 2)
	    goto Ldimerror;
	Object *o = (Object *)args->data[0];
	Expression *e = isExpression((Object *)args->data[1]);
	if (!e)
	{   // error("expression expected as second argument of __traits %s", ident->toChars());
	    goto Lfalse;
	}
	e = e->optimize(WANTvalue | WANTinterpret);
	if (e->op != TOKstring)
	{   // error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars());
	    goto Lfalse;
	}
	StringExp *se = (StringExp *)e;
	se = se->toUTF8(sc);
	if (se->sz != 1)
	{   // error("string must be chars");
	    goto Lfalse;
	}
	Identifier *id = Lexer::idPool((char *)se->string);

	Type *t = isType(o);
	e = isExpression(o);
	Dsymbol *s = isDsymbol(o);
	if (t)
	    e = new TypeDotIdExp(loc, t, id);
	else if (e)
	    e = new DotIdExp(loc, e, id);
	else if (s)
	{   e = new DsymbolExp(loc, s);
	    e = new DotIdExp(loc, e, id);
	}
	else
	{   // error("invalid first argument");
	    goto Lfalse;
	}

	if (ident == Id::hasMember)
	{   /* Take any errors as meaning it wasn't found
	     */
	    unsigned errors = global.errors;
	    global.gag++;
	    e = e->semantic(sc);
	    global.gag--;
	    if (errors != global.errors)
	    {	if (global.gag == 0)
		    global.errors = errors;
		goto Lfalse;
	    }
	    else
		goto Ltrue;
	}
	else if (ident == Id::getMember)
	{
	    e = e->semantic(sc);
	    return e;
	}
	else if (ident == Id::getVirtualFunctions)
	{
	    unsigned errors = global.errors;
	    Expression *ex = e;
	    e = e->semantic(sc);
	    /* if (errors < global.errors)
		error("%s cannot be resolved", ex->toChars()); */

	    /* Create tuple of virtual function overloads of e
	     */
	    //e->dump(0);
	    Expressions *exps = new Expressions();
	    FuncDeclaration *f;
	    if (e->op == TOKvar)
	    {	VarExp *ve = (VarExp *)e;
		f = ve->var->isFuncDeclaration();
	    }
	    else if (e->op == TOKdotvar)
	    {	DotVarExp *dve = (DotVarExp *)e;
		f = dve->var->isFuncDeclaration();
	    }
	    else
		f = NULL;
	    Pvirtuals p;
	    p.exps = exps;
	    p.e1 = e;
	    overloadApply(f, fpvirtuals, &p);

	    TupleExp *tup = new TupleExp(loc, exps);
	    return tup->semantic(sc);
	}
	else
	    assert(0);
    }
    else if (ident == Id::classInstanceSize)
    {
	if (dim != 1)
	    goto Ldimerror;
	Object *o = (Object *)args->data[0];
	Dsymbol *s = getDsymbol(o);
	ClassDeclaration *cd;
	if (!s || (cd = s->isClassDeclaration()) == NULL)
	{
	    // error("first argument is not a class");
	    goto Lfalse;
	}
	return new IntegerExp(loc, cd->structsize, Type::tsize_t);
    }
    else if (ident == Id::allMembers || ident == Id::derivedMembers)
    {
	if (dim != 1)
	    goto Ldimerror;
	Object *o = (Object *)args->data[0];
	Dsymbol *s = getDsymbol(o);
	ScopeDsymbol *sd;
	if (!s)
	{
	    // error("argument has no members");
	    goto Lfalse;
	}
	if ((sd = s->isScopeDsymbol()) == NULL)
	{
	    // error("%s %s has no members", s->kind(), s->toChars());
	    goto Lfalse;
	}
	Expressions *exps = new Expressions;
	while (1)
	{   size_t dim = ScopeDsymbol::dim(sd->members);
	    for (size_t i = 0; i < dim; i++)
	    {
		Dsymbol *sm = ScopeDsymbol::getNth(sd->members, i);
		//printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
		if (sm->ident)
		{
		    //printf("\t%s\n", sm->ident->toChars());
		    char *str = sm->ident->toChars();

		    /* Skip if already present in exps[]
		     */
		    for (size_t j = 0; j < exps->dim; j++)
		    {   StringExp *se2 = (StringExp *)exps->data[j];
			if (strcmp(str, (char *)se2->string) == 0)
			    goto Lnext;
		    }

		    StringExp *se = new StringExp(loc, str);
		    exps->push(se);
		}
	    Lnext:
		;
	    }
	    ClassDeclaration *cd = sd->isClassDeclaration();
	    if (cd && cd->baseClass && ident == Id::allMembers)
		sd = cd->baseClass;	// do again with base class
	    else
		break;
	}
	Expression *e = new ArrayLiteralExp(loc, exps);
	e = e->semantic(sc);
	return e;
    }
    else if (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++)
	{   Object *o = (Object *)args->data[i];
	    Type *t;
	    Expression *e;
	    Dsymbol *s;

	    unsigned errors = global.errors;
	    global.gag++;

	    t = isType(o);
	    if (t)
	    {	t->resolve(loc, sc, &e, &t, &s);
		if (t)
		    t->semantic(loc, sc);
		else if (e)
		    e->semantic(sc);
	    }
	    else
	    {	e = isExpression(o);
		if (e)
		    e->semantic(sc);
	    }

	    global.gag--;
	    if (errors != global.errors)
	    {   if (global.gag == 0)
		    global.errors = errors;
		goto Lfalse;
	    }
	}
	goto Ltrue;
    }
    else if (ident == Id::isSame)
    {	/* Determine if two symbols are the same
	 */
	if (dim != 2)
	    goto Ldimerror;
	TemplateInstance::semanticTiargs(loc, sc, args, 0);
	Object *o1 = (Object *)args->data[0];
	Object *o2 = (Object *)args->data[1];
	Dsymbol *s1 = getDsymbol(o1);
	Dsymbol *s2 = getDsymbol(o2);

#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 && ea1->equals(ea2))
		goto Ltrue;
	}

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

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

	if (s1 == s2)
	    goto Ltrue;
	else
	    goto Lfalse;
    }
    else
    {	// error("unrecognized trait %s", ident->toChars());
	goto Lfalse;
    }

    return NULL;

Lnottype:
    // error("%s is not a type", o->toChars());
    goto Lfalse;

Ldimerror:
    // error("wrong number of arguments %d", dim);
    goto Lfalse;


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

Ltrue:
    return new IntegerExp(loc, 1, Type::tbool);
}
Пример #13
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);
        }
    }
Пример #14
0
LLFunction* DtoInlineIRFunction(FuncDeclaration* fdecl)
{
    const char* mangled_name = mangleExact(fdecl);
    TemplateInstance* tinst = fdecl->parent->isTemplateInstance();
    assert(tinst);

    Objects& objs = tinst->tdtypes;
    assert(objs.dim == 3);

    Expression* a0 = isExpression(objs[0]);
    assert(a0);
    StringExp* strexp = a0->toStringExp();
    assert(strexp);
    assert(strexp->sz == 1);
    std::string code(static_cast<char*>(strexp->string), strexp->len);

    Type* ret = isType(objs[1]);
    assert(ret);

    Tuple* a2 = isTuple(objs[2]);
    assert(a2);
    Objects& arg_types = a2->objects;

    std::string str;
    llvm::raw_string_ostream stream(str);
    stream << "define " << *DtoType(ret) << " @" << mangled_name << "(";

    for(size_t i = 0; ;)
    {
        Type* ty = isType(arg_types[i]);
        //assert(ty);
        if(!ty)
        {
            error(tinst->loc,
                "All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types");
            fatal();
        }
        stream << *DtoType(ty);

        i++;
        if(i >= arg_types.dim)
            break;

        stream << ", ";
    }

    if(ret->ty == Tvoid)
        code.append("\nret void");

    stream << ")\n{\n" << code <<  "\n}";

    llvm::SMDiagnostic err;

#if LDC_LLVM_VER >= 306
    std::unique_ptr<llvm::Module> m = llvm::parseAssemblyString(
        stream.str().c_str(), err, gIR->context());
#elif LDC_LLVM_VER >= 303
    llvm::Module* m = llvm::ParseAssemblyString(
        stream.str().c_str(), NULL, err, gIR->context());
#else
    llvm::ParseAssemblyString(
        stream.str().c_str(), gIR->module, err, gIR->context());
#endif

    std::string errstr = err.getMessage();
    if(errstr != "")
        error(tinst->loc,
            "can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s",
#if LDC_LLVM_VER >= 303
            err.getLineContents().str().c_str(),
#else
            err.getLineContents().c_str(),
#endif
            (std::string(err.getColumnNo(), ' ') + '^').c_str(),
            errstr.c_str(), stream.str().c_str());

#if LDC_LLVM_VER >= 306
    llvm::Linker(gIR->module).linkInModule(m.get());
#else
#if LDC_LLVM_VER >= 303
    std::string errstr2 = "";
#if LDC_LLVM_VER >= 306
    llvm::Linker(gIR->module).linkInModule(m.get(), &errstr2);
#else
    llvm::Linker(gIR->module).linkInModule(m, &errstr2);
#endif
    if(errstr2 != "")
        error(tinst->loc,
            "Error when linking in llvm inline ir: %s", errstr2.c_str());
#endif
#endif

    LLFunction* fun = gIR->module->getFunction(mangled_name);
    fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
    fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline));
    return fun;
}