Implement FIXME in GRExprEngine::VisitUnaryOperator() to handle implicit conversions caused by the '!' operator.  This required adding some logic to GRSimpleVals to reason about nonloc::LocAsInteger SVals.  This code appears to work fine, but it should eventually be cleaned up.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59335 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp
index 4deef68..783bccc 100644
--- a/lib/Analysis/GRSimpleVals.cpp
+++ b/lib/Analysis/GRSimpleVals.cpp
@@ -69,20 +69,21 @@
   //   can be introduced by the frontend for corner cases, e.g
   //   casting from va_list* to __builtin_va_list&.
   //
+  assert (!X.isUnknownOrUndef());
+  
   if (Loc::IsLocType(T) || T->isReferenceType())
     return X;
   
   assert (T->isIntegerType());
-  
-  if (!isa<loc::ConcreteInt>(X))
-    return UnknownVal();
-  
   BasicValueFactory& BasicVals = Eng.getBasicVals();
+  unsigned BitWidth = Eng.getContext().getTypeSize(T);
+
+  if (!isa<loc::ConcreteInt>(X))
+    return nonloc::LocAsInteger::Make(BasicVals, X, BitWidth);
   
   llvm::APSInt V = cast<loc::ConcreteInt>(X).getValue();
   V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T));
-  V.extOrTrunc(Eng.getContext().getTypeSize(T));
-
+  V.extOrTrunc(BitWidth);
   return nonloc::ConcreteInt(BasicVals.getValue(V));
 }
 
@@ -123,11 +124,11 @@
   (unsigned char) BinaryOperator::EQ   /* NE => EQ */
 };
 
-SVal GRSimpleVals::DetermEvalBinOpNN(GRStateManager& StateMgr,
+SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
                                      BinaryOperator::Opcode Op,
                                      NonLoc L, NonLoc R)  {
 
-  BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+  BasicValueFactory& BasicVals = Eng.getBasicVals();
   unsigned subkind = L.getSubKind();
   
   while (1) {
@@ -136,6 +137,37 @@
       default:
         return UnknownVal();
         
+      case nonloc::LocAsIntegerKind: {
+        Loc LL = cast<nonloc::LocAsInteger>(L).getLoc();        
+        
+        switch (R.getSubKind()) {
+          case nonloc::LocAsIntegerKind:
+            return EvalBinOp(Eng, Op, LL,
+                             cast<nonloc::LocAsInteger>(R).getLoc());
+            
+          case nonloc::ConcreteIntKind: {
+            // Transform the integer into a location and compare.
+            ASTContext& Ctx = Eng.getContext();
+            llvm::APSInt V = cast<nonloc::ConcreteInt>(R).getValue();
+            V.setIsUnsigned(true);
+            V.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy));
+            return EvalBinOp(Eng, Op, LL,
+                             loc::ConcreteInt(BasicVals.getValue(V)));
+          }
+          
+          default: 
+            switch (Op) {
+              case BinaryOperator::EQ:
+                return NonLoc::MakeIntTruthVal(BasicVals, false);
+              case BinaryOperator::NE:
+                return NonLoc::MakeIntTruthVal(BasicVals, true);
+              default:
+                // This case also handles pointer arithmetic.
+                return UnknownVal();
+            }
+        }
+      }
+        
       case nonloc::SymIntConstraintValKind: {
         
         // Logical not?