diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-06-14 02:17:33 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-06-14 02:17:33 +0000 |
commit | 5bc86103767c2abcbfdd6518e0ccbbbb6aa59e0f (patch) | |
tree | c77202b1e6e5c6c69e5c72bf85a62295f01e7d2c /lib/AST/ExprConstant.cpp | |
parent | 1b63e4f732dbc73d90abf886b4d21f8e3a165f6d (diff) |
PR4351: Add constant evaluation for constructs like "foo == NULL", where
foo has a constant address.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73321 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index ff00bc24b3..4815ae5c3b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -62,6 +62,13 @@ static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info); // Misc utilities //===----------------------------------------------------------------------===// +static bool EvalPointerValueAsBool(APValue& Value, bool& Result) { + // FIXME: Is this accurate for all kinds of bases? If not, what would + // the check look like? + Result = Value.getLValueBase() || Value.getLValueOffset(); + return true; +} + static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) { if (E->getType()->isIntegralType()) { APSInt IntResult; @@ -79,10 +86,7 @@ static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) { APValue PointerResult; if (!EvaluatePointer(E, PointerResult, Info)) return false; - // FIXME: Is this accurate for all kinds of bases? If not, what would - // the check look like? - Result = PointerResult.getLValueBase() || PointerResult.getLValueOffset(); - return true; + return EvalPointerValueAsBool(PointerResult, Result); } else if (E->getType()->isAnyComplexType()) { APValue ComplexResult; if (!EvaluateComplex(E, ComplexResult, Info)) @@ -937,10 +941,27 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (!EvaluatePointer(E->getRHS(), RHSValue, Info)) return false; - // Reject any bases; this is conservative, but good enough for - // common uses - if (LHSValue.getLValueBase() || RHSValue.getLValueBase()) - return false; + // Reject any bases from the normal codepath; we special-case comparisons + // to null. + if (LHSValue.getLValueBase()) { + if (!E->isEqualityOp()) + return false; + if (RHSValue.getLValueBase() || RHSValue.getLValueOffset()) + return false; + bool bres; + if (!EvalPointerValueAsBool(LHSValue, bres)) + return false; + return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E); + } else if (RHSValue.getLValueBase()) { + if (!E->isEqualityOp()) + return false; + if (LHSValue.getLValueBase() || LHSValue.getLValueOffset()) + return false; + bool bres; + if (!EvalPointerValueAsBool(RHSValue, bres)) + return false; + return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E); + } if (E->getOpcode() == BinaryOperator::Sub) { const QualType Type = E->getLHS()->getType(); |