Permalink
Browse files

Merge pull request #652 from yebblies/issue6169

Issue 6169 - [CTFE] pure functions cannot compute constants using functions not marked as pure
  • Loading branch information...
2 parents 515ff95 + 42d1af1 commit 15a57832d0a9ed18eb619c58261db6c2eedc663e @donc donc committed May 4, 2013
View
@@ -971,7 +971,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
Expression *e = (*args)[i];
- e = e->semantic(sc);
+ e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
if (e->op != TOKerror && e->op != TOKtype)
e = e->ctfeInterpret();
@@ -999,7 +999,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
Expression *e = (*args)[0];
- e = e->semantic(sc);
+ e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
@@ -1027,7 +1027,7 @@ void PragmaDeclaration::semantic(Scope *sc)
else
{
Expression *e = (*args)[0];
- e = e->semantic(sc);
+ e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
@@ -1050,7 +1050,7 @@ void PragmaDeclaration::semantic(Scope *sc)
for (size_t i = 0; i < args->dim; i++)
{
Expression *e = (*args)[i];
- e = e->semantic(sc);
+ e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
if (i == 0)
@@ -1428,7 +1428,7 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
void CompileDeclaration::compileIt(Scope *sc)
{
//printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
- exp = exp->semantic(sc);
+ exp = exp->ctfeSemantic(sc);
exp = resolveProperties(sc, exp);
exp = exp->ctfeInterpret();
StringExp *se = exp->toString();
View
@@ -259,7 +259,7 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
sc = sc->push(sc->scopesym);
sc->sd = s; // s gets any addMember()
sc->flags |= SCOPEstaticif;
- Expression *e = exp->semantic(sc);
+ Expression *e = exp->ctfeSemantic(sc);
e = resolveProperties(sc, e);
sc->pop();
if (!e->type->checkBoolean())
View
@@ -851,6 +851,11 @@ void VarDeclaration::semantic(Scope *sc)
if (!type)
{ inuse++;
+ // Infering the type requires running semantic,
+ // so mark the scope as ctfe if required
+ if (storage_class & (STCmanifest | STCstatic))
+ sc->needctfe++;
+
//printf("inferring type for %s with init %s\n", toChars(), init->toChars());
ArrayInitializer *ai = init->isArrayInitializer();
if (ai)
@@ -872,6 +877,8 @@ void VarDeclaration::semantic(Scope *sc)
else
type = init->inferType(sc);
+ if (storage_class & (STCmanifest | STCstatic))
+ sc->needctfe--;
// type = type->semantic(loc, sc);
inuse--;
@@ -1585,7 +1592,10 @@ void VarDeclaration::semantic(Scope *sc)
{
Expression *exp;
exp = ei->exp->syntaxCopy();
- exp = exp->semantic(sc);
+ if (isDataseg() || (storage_class & STCmanifest))
+ exp = exp->ctfeSemantic(sc);
+ else
+ exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
Type *tb = type->toBasetype();
Type *ti = exp->type->toBasetype();
View
@@ -252,7 +252,7 @@ void EnumDeclaration::semantic(Scope *sc)
if (e)
{
assert(e->dyncast() == DYNCAST_EXPRESSION);
- e = e->semantic(sce);
+ e = e->ctfeSemantic(sce);
e = e->ctfeInterpret();
if (memtype)
{
@@ -299,30 +299,30 @@ void EnumDeclaration::semantic(Scope *sc)
if (!emax)
{
emax = t->getProperty(0, Id::max, 0);
- emax = emax->semantic(sce);
+ emax = emax->ctfeSemantic(sce);
emax = emax->ctfeInterpret();
}
// Set value to (elast + 1).
// But first check that (elast != t.max)
assert(elast);
e = new EqualExp(TOKequal, em->loc, elast, emax);
- e = e->semantic(sce);
+ e = e->ctfeSemantic(sce);
e = e->ctfeInterpret();
if (e->toInteger())
error("overflow of enum value %s", elast->toChars());
// Now set e to (elast + 1)
e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
- e = e->semantic(sce);
+ e = e->ctfeSemantic(sce);
e = e->castTo(sce, elast->type);
e = e->ctfeInterpret();
if (t->isfloating())
{
// Check that e != elast (not always true for floats)
Expression *etest = new EqualExp(TOKequal, em->loc, e, elast);
- etest = etest->semantic(sce);
+ etest = etest->ctfeSemantic(sce);
etest = etest->ctfeInterpret();
if (etest->toInteger())
error("enum member %s has inexact value, due to loss of precision", em->toChars());
@@ -361,13 +361,13 @@ void EnumDeclaration::semantic(Scope *sc)
// Compute if(e < minval)
ec = new CmpExp(TOKlt, em->loc, e, minval);
- ec = ec->semantic(sce);
+ ec = ec->ctfeSemantic(sce);
ec = ec->ctfeInterpret();
if (ec->toInteger())
minval = e;
ec = new CmpExp(TOKgt, em->loc, e, maxval);
- ec = ec->semantic(sce);
+ ec = ec->ctfeSemantic(sce);
ec = ec->ctfeInterpret();
if (ec->toInteger())
maxval = e;
View
@@ -1552,6 +1552,29 @@ Expression *Expression::trySemantic(Scope *sc)
return e;
}
+/**********************************
+ * Shortcut to run semantic with purity and
+ * safety checking disabled for the immediate
+ * expressions
+ */
+
+Expression *Expression::ctfeSemantic(Scope *sc)
+{
+ if (sc)
+ {
+ assert(sc->needctfe >= 0);
+ sc->needctfe++;
+ Expression *e = semantic(sc);
+ sc->needctfe--;
+ assert(sc->needctfe >= 0);
+ return e;
+ }
+ else
+ {
+ return semantic(sc);
+ }
+}
+
void Expression::print()
{
fprintf(stdmsg, "%s\n", toChars());
@@ -1891,7 +1914,8 @@ void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
// If the caller has a pure parent, then either the called func must be pure,
// OR, they must have the same pure parent.
if (/*outerfunc->isPure() &&*/ // comment out because we deduce purity now
- !f->isPure() && calledparent != outerfunc)
+ !f->isPure() && calledparent != outerfunc &&
+ !sc->needctfe)
{
if (outerfunc->setImpure())
error("pure function '%s' cannot call impure function '%s'",
@@ -1992,6 +2016,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis)
void Expression::checkSafety(Scope *sc, FuncDeclaration *f)
{
if (sc->func && !sc->intypeof &&
+ !(sc->needctfe) &&
!f->isSafe() && !f->isTrusted())
{
if (sc->func->setUnsafe())
@@ -4983,7 +5008,10 @@ Expression *NewAnonClassExp::semantic(Scope *sc)
#endif
Expression *d = new DeclarationExp(loc, cd);
+ int needctfe = sc->needctfe;
+ sc->needctfe = 0;
d = d->semantic(sc);
+ sc->needctfe = needctfe;
Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
@@ -5407,6 +5435,11 @@ Expression *FuncExp::semantic(Scope *sc)
printf("FuncExp::semantic(%s)\n", toChars());
if (fd->treq) printf(" treq = %s\n", fd->treq->toChars());
#endif
+ Expression *e = this;
+
+ int needctfe = sc->needctfe;
+ sc->needctfe = 0;
+
if (!type || type == Type::tvoid)
{
/* fd->treq might be incomplete type,
@@ -5436,10 +5469,9 @@ Expression *FuncExp::semantic(Scope *sc)
td->semantic(sc);
type = Type::tvoid; // temporary type
- if (!fd->treq) // defer type determination
- return this;
-
- return inferType(fd->treq);
+ if (fd->treq) // defer type determination
+ e = inferType(fd->treq);
+ goto Ldone;
}
unsigned olderrors = global.errors;
@@ -5494,7 +5526,9 @@ Expression *FuncExp::semantic(Scope *sc)
}
fd->tookAddressOf++;
}
- return this;
+Ldone:
+ sc->needctfe = needctfe;
+ return e;
}
// used from CallExp::semantic()
@@ -6578,7 +6612,7 @@ Expression *CompileExp::semantic(Scope *sc)
#if LOGSEMANTIC
printf("CompileExp::semantic('%s')\n", toChars());
#endif
- UnaExp::semantic(sc);
+ e1 = e1->ctfeSemantic(sc);
e1 = resolveProperties(sc, e1);
if (e1->op == TOKerror)
return e1;
@@ -6631,7 +6665,7 @@ Expression *FileExp::semantic(Scope *sc)
#if LOGSEMANTIC
printf("FileExp::semantic('%s')\n", toChars());
#endif
- UnaExp::semantic(sc);
+ e1 = e1->ctfeSemantic(sc);
e1 = resolveProperties(sc, e1);
e1 = e1->ctfeInterpret();
if (e1->op != TOKstring)
@@ -8386,12 +8420,12 @@ Expression *CallExp::semantic(Scope *sc)
return new ErrorExp();
}
- if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug))
+ if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug) && !sc->needctfe)
{
if (sc->func->setImpure())
error("pure function '%s' cannot call impure %s '%s'", sc->func->toPrettyChars(), p, e1->toChars());
}
- if (sc->func && tf->trust <= TRUSTsystem)
+ if (sc->func && tf->trust <= TRUSTsystem && !sc->needctfe)
{
if (sc->func->setUnsafe())
error("safe function '%s' cannot call system %s '%s'", sc->func->toPrettyChars(), p, e1->toChars());
@@ -9572,14 +9606,22 @@ Expression *SliceExp::semantic(Scope *sc)
}
if (lwr)
- { lwr = lwr->semantic(sc2);
+ {
+ if (t->ty == Ttuple)
+ lwr = lwr->ctfeSemantic(sc2);
+ else
+ lwr = lwr->semantic(sc2);
lwr = resolveProperties(sc2, lwr);
lwr = lwr->implicitCastTo(sc2, Type::tsize_t);
if (lwr->type == Type::terror)
goto Lerr;
}
if (upr)
- { upr = upr->semantic(sc2);
+ {
+ if (t->ty == Ttuple)
+ upr = upr->ctfeSemantic(sc2);
+ else
+ upr = upr->semantic(sc2);
upr = resolveProperties(sc2, upr);
upr = upr->implicitCastTo(sc2, Type::tsize_t);
if (upr->type == Type::terror)
@@ -10053,7 +10095,10 @@ Expression *IndexExp::semantic(Scope *sc)
sc = sc->push(sym);
}
- e2 = e2->semantic(sc);
+ if (t1->ty == Ttuple)
+ e2 = e2->ctfeSemantic(sc);
+ else
+ e2 = e2->semantic(sc);
e2 = resolveProperties(sc, e2);
if (e2->type == Type::terror)
goto Lerr;
View
@@ -114,6 +114,7 @@ struct Expression : Object
virtual int apply(apply_fp_t fp, void *param);
virtual Expression *semantic(Scope *sc);
Expression *trySemantic(Scope *sc);
+ Expression *ctfeSemantic(Scope *sc);
int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression()
View
@@ -3671,7 +3671,7 @@ STATIC code *asm_db_parse(OP *pop)
case TOKidentifier:
{ Expression *e = new IdentifierExp(asmstate.loc, asmtok->ident);
- e = e->semantic(asmstate.sc);
+ e = e->ctfeSemantic(asmstate.sc);
e = e->ctfeInterpret();
if (e->op == TOKint64)
{ dt.ul = e->toInteger();
@@ -3747,7 +3747,7 @@ int asm_getnum()
Expression *e;
e = new IdentifierExp(asmstate.loc, asmtok->ident);
- e = e->semantic(asmstate.sc);
+ e = e->ctfeSemantic(asmstate.sc);
e = e->ctfeInterpret();
i = e->toInteger();
v = (int) i;
@@ -4458,7 +4458,7 @@ STATIC OPND *asm_primary_exp()
break;
}
}
- e = e->semantic(asmstate.sc);
+ e = e->ctfeSemantic(asmstate.sc);
e = e->ctfeInterpret();
if (e->isConst())
{
View
@@ -558,7 +558,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
{
Expression *idx = index[i];
if (idx)
- { idx = idx->semantic(sc);
+ { idx = idx->ctfeSemantic(sc);
idx = idx->ctfeInterpret();
index[i] = idx;
length = idx->toInteger();
@@ -942,7 +942,10 @@ bool arrayHasNonConstPointers(Expressions *elems)
Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
- exp = exp->semantic(sc);
+ if (needInterpret)
+ exp = exp->ctfeSemantic(sc);
+ else
+ exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
if (exp->op == TOKerror)
return this;
Oops, something went wrong.

0 comments on commit 15a5783

Please sign in to comment.