Added "nonlval::LValAsInteger" to represent abstract LVals casted to integers, allowing us to track lvals when they are casted back to pointers.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50108 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 4c77b64..bdb7429 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1102,10 +1102,8 @@
   else
     Visit(Ex, Pred, S1);
   
-  // Check for redundant casts or casting to "void"
-  if (T->isVoidType() ||
-      Ex->getType() == T || 
-      (T->isPointerType() && Ex->getType()->isFunctionType())) {
+  // Check for casting to "void".
+  if (T->isVoidType()) {
     
     for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1)
       Dst.Add(*I1);
@@ -1113,11 +1111,54 @@
     return;
   }
   
+  // FIXME: The rest of this should probably just go into EvalCall, and
+  //   let the transfer function object be responsible for constructing
+  //   nodes.
+  
+  QualType ExTy = Ex->getType();
+  
   for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
     NodeTy* N = *I1;
     ValueState* St = GetState(N);
-    
     RVal V = T->isReferenceType() ? GetLVal(St, Ex) : GetRVal(St, Ex);
+
+    // Unknown?
+    
+    if (V.isUnknown()) {
+      Dst.Add(N);
+      continue;
+    }
+    
+    // Undefined?
+    
+    if (V.isUndef()) {
+      MakeNode(Dst, CastE, N, SetRVal(St, CastE, V));
+      continue;
+    }
+  
+    // Check for casts from pointers to integers.
+    if (T->isIntegerType() && ExTy->isPointerType()) {
+      unsigned bits = getContext().getTypeSize(ExTy);
+    
+      // FIXME: Determine if the number of bits of the target type is 
+      // equal or exceeds the number of bits to store the pointer value.
+      // If not, flag an error.
+      
+      V = nonlval::LValAsInteger::Make(BasicVals, cast<LVal>(V), bits);
+      MakeNode(Dst, CastE, N, SetRVal(St, CastE, V));
+      continue;
+    }
+    
+    // Check for casts from integers to pointers.
+    if (T->isPointerType() && ExTy->isIntegerType())
+      if (nonlval::LValAsInteger *LV = dyn_cast<nonlval::LValAsInteger>(&V)) {
+        // Just unpackage the lval and return it.
+        V = LV->getLVal();
+        MakeNode(Dst, CastE, N, SetRVal(St, CastE, V));
+        continue;
+      }
+    
+    // All other cases.
     
     MakeNode(Dst, CastE, N, SetRVal(St, CastE, EvalCast(V, CastE->getType())));
   }
@@ -2024,6 +2065,11 @@
       isFeasible = b ? Assumption : !Assumption;      
       return St;
     }
+      
+    case nonlval::LValAsIntegerKind: {
+      return AssumeAux(St, cast<nonlval::LValAsInteger>(Cond).getLVal(),
+                       Assumption, isFeasible);
+    }
   }
 }