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
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index ff00bc2..4815ae5 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -62,6 +62,13 @@
// 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 @@
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 @@
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();
diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c
index 971986b..72db14c 100644
--- a/test/Sema/const-eval.c
+++ b/test/Sema/const-eval.c
@@ -66,3 +66,5 @@
EVAL_EXPR(31, (int*)0 == (int*)0 ? 1 : -1)
EVAL_EXPR(32, (int*)0 != (int*)0 ? -1 : 1)
EVAL_EXPR(33, (void*)0 - (void*)0 == 0 ? 1 : -1)
+void foo(void) {}
+EVAL_EXPR(34, (foo == (void *)0) ? -1 : 1)