]> granicus.if.org Git - clang/commitdiff
PR4351: Add constant evaluation for constructs like "foo == NULL", where
authorEli Friedman <eli.friedman@gmail.com>
Sun, 14 Jun 2009 02:17:33 +0000 (02:17 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sun, 14 Jun 2009 02:17:33 +0000 (02:17 +0000)
foo has a constant address.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73321 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
test/Sema/const-eval.c

index ff00bc24b391658e1d1b918b794e4e9d0c085162..4815ae5c3b94390f73519ec5403314c3459f03c0 100644 (file)
@@ -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();
index 971986b2d3af3af9e51e61b6794f853987b66cc8..72db14c82053e257e39713205941785b2fa8e2c9 100644 (file)
@@ -66,3 +66,5 @@ EVAL_EXPR(30, (int)(_Complex float)((1<<30)-1) == (1<<30) ? 1 : -1)
 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)