aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-10-16 21:26:27 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-10-16 21:26:27 +0000
commit1e12c59e8f9bb76c23628c4e0d0a1dfced0b1fa0 (patch)
tree921669eca776599266b3e7f8e2564564e5cdc25d /lib/AST/ExprConstant.cpp
parent20cdbeb8f36576f469db195b4140c293c7281718 (diff)
Split apart the state accumulated during constant expression evaluation and the
end result. Use this split to propagate state information and diagnostics through more of constant expression evaluation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142159 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp99
1 files changed, 53 insertions, 46 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index df75bc8a73..3c21dc4472 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -46,8 +46,8 @@ namespace {
struct EvalInfo {
const ASTContext &Ctx;
- /// EvalResult - Contains information about the evaluation.
- Expr::EvalResult &EvalResult;
+ /// EvalStatus - Contains information about the evaluation.
+ Expr::EvalStatus &EvalStatus;
typedef llvm::DenseMap<const OpaqueValueExpr*, APValue> MapTy;
MapTy OpaqueValues;
@@ -57,8 +57,8 @@ namespace {
return &i->second;
}
- EvalInfo(const ASTContext &ctx, Expr::EvalResult &evalresult)
- : Ctx(ctx), EvalResult(evalresult) {}
+ EvalInfo(const ASTContext &C, Expr::EvalStatus &S)
+ : Ctx(C), EvalStatus(S) {}
const LangOptions &getLangOpts() { return Ctx.getLangOptions(); }
};
@@ -121,7 +121,7 @@ namespace {
};
}
-static bool Evaluate(EvalInfo &info, const Expr *E);
+static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E);
static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info);
static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info);
static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
@@ -264,10 +264,10 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType,
namespace {
class HasSideEffect
: public ConstStmtVisitor<HasSideEffect, bool> {
- EvalInfo &Info;
+ const ASTContext &Ctx;
public:
- HasSideEffect(EvalInfo &info) : Info(info) {}
+ HasSideEffect(const ASTContext &C) : Ctx(C) {}
// Unhandled nodes conservatively default to having side effects.
bool VisitStmt(const Stmt *S) {
@@ -279,17 +279,17 @@ public:
return Visit(E->getResultExpr());
}
bool VisitDeclRefExpr(const DeclRefExpr *E) {
- if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ if (Ctx.getCanonicalType(E->getType()).isVolatileQualified())
return true;
return false;
}
bool VisitObjCIvarRefExpr(const ObjCIvarRefExpr *E) {
- if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ if (Ctx.getCanonicalType(E->getType()).isVolatileQualified())
return true;
return false;
}
bool VisitBlockDeclRefExpr (const BlockDeclRefExpr *E) {
- if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ if (Ctx.getCanonicalType(E->getType()).isVolatileQualified())
return true;
return false;
}
@@ -310,7 +310,7 @@ public:
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E)
{ return Visit(E->getLHS()) || Visit(E->getRHS()); }
bool VisitChooseExpr(const ChooseExpr *E)
- { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+ { return Visit(E->getChosenSubExpr(Ctx)); }
bool VisitCastExpr(const CastExpr *E) { return Visit(E->getSubExpr()); }
bool VisitBinAssign(const BinaryOperator *E) { return true; }
bool VisitCompoundAssignOperator(const BinaryOperator *E) { return true; }
@@ -321,7 +321,7 @@ public:
bool VisitUnaryPreDec(const UnaryOperator *E) { return true; }
bool VisitUnaryPostDec(const UnaryOperator *E) { return true; }
bool VisitUnaryDeref(const UnaryOperator *E) {
- if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ if (Ctx.getCanonicalType(E->getType()).isVolatileQualified())
return true;
return Visit(E->getSubExpr());
}
@@ -349,16 +349,17 @@ public:
: info(info), opaqueValue(opaqueValue) {
// If evaluation fails, fail immediately.
- if (!Evaluate(info, value)) {
+ if (!Evaluate(info.OpaqueValues[opaqueValue], info, value)) {
this->opaqueValue = 0;
return;
}
- info.OpaqueValues[opaqueValue] = info.EvalResult.Val;
}
bool hasError() const { return opaqueValue == 0; }
~OpaqueValueEvaluation() {
+ // FIXME: This will not work for recursive constexpr functions using opaque
+ // values. Restore the former value.
if (opaqueValue) info.OpaqueValues.erase(opaqueValue);
}
};
@@ -967,8 +968,9 @@ VectorExprEvaluator::GetZeroVector(QualType T) {
}
APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
- if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
- Info.EvalResult.HasSideEffects = true;
+ APValue Scratch;
+ if (!Evaluate(Scratch, Info, E->getSubExpr()))
+ Info.EvalStatus.HasSideEffects = true;
return GetZeroVector(E->getType());
}
@@ -1020,10 +1022,10 @@ public:
bool Error(SourceLocation L, diag::kind D, const Expr *E) {
// Take the first error.
- if (Info.EvalResult.Diag == 0) {
- Info.EvalResult.DiagLoc = L;
- Info.EvalResult.Diag = D;
- Info.EvalResult.DiagExpr = E;
+ if (Info.EvalStatus.Diag == 0) {
+ Info.EvalStatus.DiagLoc = L;
+ Info.EvalStatus.Diag = D;
+ Info.EvalStatus.DiagExpr = E;
}
return false;
}
@@ -1058,7 +1060,7 @@ public:
bool VisitMemberExpr(const MemberExpr *E) {
if (CheckReferencedDecl(E, E->getMemberDecl())) {
// Conservatively assume a MemberExpr will have side-effects
- Info.EvalResult.HasSideEffects = true;
+ Info.EvalStatus.HasSideEffects = true;
return true;
}
@@ -1172,6 +1174,8 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
VD->setEvaluatingValue();
Expr::EvalResult EResult;
+ // FIXME: Produce a diagnostic if the initializer isn't a constant
+ // expression.
if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects &&
EResult.Val.isInt()) {
// Cache the evaluated value in the variable declaration.
@@ -1350,8 +1354,9 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// If we can't evaluate the LHS, it might have side effects;
// conservatively mark it.
- if (!E->getLHS()->isEvaluatable(Info.Ctx))
- Info.EvalResult.HasSideEffects = true;
+ APValue Scratch;
+ if (!Evaluate(Scratch, Info, E->getLHS()))
+ Info.EvalStatus.HasSideEffects = true;
return true;
}
@@ -1381,7 +1386,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
!rhsResult == (E->getOpcode() == BO_LAnd)) {
// Since we weren't able to evaluate the left hand side, it
// must have had side effects.
- Info.EvalResult.HasSideEffects = true;
+ Info.EvalStatus.HasSideEffects = true;
return Success(rhsResult, E);
}
@@ -1943,8 +1948,9 @@ bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
return Success(LV.getComplexIntImag(), E);
}
- if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
- Info.EvalResult.HasSideEffects = true;
+ APValue Scratch;
+ if (!Evaluate(Scratch, Info, E->getSubExpr()))
+ Info.EvalStatus.HasSideEffects = true;
return Success(0, E);
}
@@ -2145,8 +2151,9 @@ bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
return true;
}
- if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
- Info.EvalResult.HasSideEffects = true;
+ APValue Scratch;
+ if (!Evaluate(Scratch, Info, E->getSubExpr()))
+ Info.EvalStatus.HasSideEffects = true;
const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType());
Result = llvm::APFloat::getZero(Sem);
return true;
@@ -2176,8 +2183,9 @@ bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// If we can't evaluate the LHS, it might have side effects;
// conservatively mark it.
- if (!E->getLHS()->isEvaluatable(Info.Ctx))
- Info.EvalResult.HasSideEffects = true;
+ APValue Scratch;
+ if (!Evaluate(Scratch, Info, E->getLHS()))
+ Info.EvalStatus.HasSideEffects = true;
return true;
}
@@ -2460,8 +2468,9 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// If we can't evaluate the LHS, it might have side effects;
// conservatively mark it.
- if (!E->getLHS()->isEvaluatable(Info.Ctx))
- Info.EvalResult.HasSideEffects = true;
+ APValue Scratch;
+ if (!Evaluate(Scratch, Info, E->getLHS()))
+ Info.EvalStatus.HasSideEffects = true;
return true;
}
@@ -2616,15 +2625,15 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
// Top level Expr::Evaluate method.
//===----------------------------------------------------------------------===//
-static bool Evaluate(EvalInfo &Info, const Expr *E) {
+static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
if (E->getType()->isVectorType()) {
- if (!EvaluateVector(E, Info.EvalResult.Val, Info))
+ if (!EvaluateVector(E, Result, Info))
return false;
} else if (E->getType()->isIntegralOrEnumerationType()) {
- if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(E))
+ if (!IntExprEvaluator(Info, Result).Visit(E))
return false;
- if (Info.EvalResult.Val.isLValue() &&
- !IsGlobalLValue(Info.EvalResult.Val.getLValueBase()))
+ if (Result.isLValue() &&
+ !IsGlobalLValue(Result.getLValueBase()))
return false;
} else if (E->getType()->hasPointerRepresentation()) {
LValue LV;
@@ -2632,18 +2641,18 @@ static bool Evaluate(EvalInfo &Info, const Expr *E) {
return false;
if (!IsGlobalLValue(LV.Base))
return false;
- LV.moveInto(Info.EvalResult.Val);
+ LV.moveInto(Result);
} else if (E->getType()->isRealFloatingType()) {
llvm::APFloat F(0.0);
if (!EvaluateFloat(E, F, Info))
return false;
- Info.EvalResult.Val = APValue(F);
+ Result = APValue(F);
} else if (E->getType()->isAnyComplexType()) {
ComplexValue C;
if (!EvaluateComplex(E, C, Info))
return false;
- C.moveInto(Info.EvalResult.Val);
+ C.moveInto(Result);
} else
return false;
@@ -2656,19 +2665,19 @@ static bool Evaluate(EvalInfo &Info, const Expr *E) {
/// in Result.
bool Expr::Evaluate(EvalResult &Result, const ASTContext &Ctx) const {
EvalInfo Info(Ctx, Result);
- return ::Evaluate(Info, this);
+ return ::Evaluate(Result.Val, Info, this);
}
bool Expr::EvaluateAsBooleanCondition(bool &Result,
const ASTContext &Ctx) const {
- EvalResult Scratch;
+ EvalStatus Scratch;
EvalInfo Info(Ctx, Scratch);
return HandleConversionToBool(this, Result, Info);
}
bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const {
- EvalResult Scratch;
+ EvalStatus Scratch;
EvalInfo Info(Ctx, Scratch);
return EvaluateInteger(this, Result, Info) && !Scratch.HasSideEffects;
@@ -2707,9 +2716,7 @@ bool Expr::isEvaluatable(const ASTContext &Ctx) const {
}
bool Expr::HasSideEffects(const ASTContext &Ctx) const {
- Expr::EvalResult Result;
- EvalInfo Info(Ctx, Result);
- return HasSideEffect(Info).Visit(this);
+ return HasSideEffect(Ctx).Visit(this);
}
APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const {