diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-16 21:26:27 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-16 21:26:27 +0000 |
commit | 1e12c59e8f9bb76c23628c4e0d0a1dfced0b1fa0 (patch) | |
tree | 921669eca776599266b3e7f8e2564564e5cdc25d /lib/AST/ExprConstant.cpp | |
parent | 20cdbeb8f36576f469db195b4140c293c7281718 (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.cpp | 99 |
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 { |