diff options
author | Abramo Bagnara <abramo.bagnara@gmail.com> | 2011-07-02 13:13:53 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo.bagnara@gmail.com> | 2011-07-02 13:13:53 +0000 |
commit | 973c4fc0b0a88f9cea273b16f2082788a6e57d74 (patch) | |
tree | abbeeb70ea45d20ebb072bd9470fcff71a2dbd25 /lib/AST/ExprConstant.cpp | |
parent | 25af091c5548f85e38dee5c8bfc1748efc06f88c (diff) |
Rewritten fix in r134139 to conform evaluation result to original evaluation context.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134320 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 1be23fc990..df33f7afc3 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -955,21 +955,17 @@ public: IntExprEvaluator(EvalInfo &info, APValue &result) : ExprEvaluatorBaseTy(info), Result(result) {} - bool Success(const llvm::APSInt &SI, QualType Ty) { - assert(Ty->isIntegralOrEnumerationType() && + bool Success(const llvm::APSInt &SI, const Expr *E) { + assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); - assert(SI.isSigned() == Ty->isSignedIntegerOrEnumerationType() && + assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() && "Invalid evaluation result."); - assert(SI.getBitWidth() == Info.Ctx.getIntWidth(Ty) && + assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(SI); return true; } - bool Success(const llvm::APSInt &SI, const Expr *E) { - return Success(SI, E->getType()); - } - bool Success(const llvm::APInt &I, const Expr *E) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); @@ -1111,9 +1107,23 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { // Enums are integer constant exprs. if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { - // Note: provide the type of ECD (rather than that of E), - // so that signedness/width will match the ECD init value. - return Success(ECD->getInitVal(), ECD->getType()); + // Check for signedness/width mismatches between E type and ECD value. + bool SameSign = (ECD->getInitVal().isSigned() + == E->getType()->isSignedIntegerOrEnumerationType()); + bool SameWidth = (ECD->getInitVal().getBitWidth() + == Info.Ctx.getIntWidth(E->getType())); + if (SameSign && SameWidth) + return Success(ECD->getInitVal(), E); + else { + // Get rid of mismatch (otherwise Success assertions will fail) + // by computing a new value matching the type of E. + llvm::APSInt Val = ECD->getInitVal(); + if (!SameSign) + Val.setIsSigned(!ECD->getInitVal().isSigned()); + if (!SameWidth) + Val = Val.extOrTrunc(Info.Ctx.getIntWidth(E->getType())); + return Success(Val, E); + } } // In C++, const, non-volatile integers initialized with ICEs are ICEs. |