aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
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 {