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 | 725810a2bb76e63d6a8c0529941008f0b5e70c3f (patch) | |
| tree | 6854763294a18272b6580f51e60f12ae26126153 /clang/lib/AST/ExprConstant.cpp | |
| parent | 053a7358d611482980af56cd7677a6ae5fcc4f28 (diff) | |
| download | bcm5719-llvm-725810a2bb76e63d6a8c0529941008f0b5e70c3f.tar.gz bcm5719-llvm-725810a2bb76e63d6a8c0529941008f0b5e70c3f.zip | |
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.
llvm-svn: 142159
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 99 | 
1 files changed, 53 insertions, 46 deletions
| diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index df75bc8a735..3c21dc4472a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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 { | 

