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/include/clang/Analysis/PathSensitive/BasicValueFactory.h b/include/clang/Analysis/PathSensitive/BasicValueFactory.h
index 351e326..9462ed5 100644
--- a/include/clang/Analysis/PathSensitive/BasicValueFactory.h
+++ b/include/clang/Analysis/PathSensitive/BasicValueFactory.h
@@ -27,22 +27,26 @@
 
 namespace clang {
   
+class RVal;
+  
 class BasicValueFactory {
   typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
           APSIntSetTy;
 
   typedef llvm::FoldingSet<SymIntConstraint>
           SymIntCSetTy;
+  
 
   ASTContext& Ctx;
   llvm::BumpPtrAllocator& BPAlloc;
 
   APSIntSetTy   APSIntSet;
   SymIntCSetTy  SymIntCSet;
+  void*         PersistentRVals;
 
 public:
   BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc) 
-  : Ctx(ctx), BPAlloc(Alloc) {}
+  : Ctx(ctx), BPAlloc(Alloc), PersistentRVals(0) {}
 
   ~BasicValueFactory();
 
@@ -66,6 +70,9 @@
   const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op,
                                      const llvm::APSInt& V1,
                                      const llvm::APSInt& V2);
+  
+  const std::pair<RVal, unsigned>&
+  getPersistentSizedRVal(const RVal& V, unsigned Bits);
 };
 
 } // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/RValues.h b/include/clang/Analysis/PathSensitive/RValues.h
index dd99a2e..45a5452 100644
--- a/include/clang/Analysis/PathSensitive/RValues.h
+++ b/include/clang/Analysis/PathSensitive/RValues.h
@@ -163,7 +163,8 @@
 
 namespace nonlval {
   
-enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind };
+enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind,
+            LValAsIntegerKind };
 
 class SymbolVal : public NonLVal {
 public:
@@ -230,6 +231,40 @@
   }
 };
   
+class LValAsInteger : public NonLVal {
+  LValAsInteger(const std::pair<RVal, unsigned>& data) :
+    NonLVal(LValAsIntegerKind, &data) {}
+  
+public:
+    
+  LVal getLVal() const {
+    return cast<LVal>(((std::pair<RVal, unsigned>*) Data)->first);
+  }
+  
+  const LVal& getPersistentLVal() const {
+    return cast<LVal>(((std::pair<RVal, unsigned>*) Data)->first);
+  }    
+  
+  unsigned getNumBits() const {
+    return ((std::pair<RVal, unsigned>*) Data)->second;
+  }
+  
+  // Implement isa<T> support.
+  static inline bool classof(const RVal* V) {
+    return V->getBaseKind() == NonLValKind &&
+           V->getSubKind() == LValAsIntegerKind;
+  }
+  
+  static inline bool classof(const NonLVal* V) {
+    return V->getSubKind() == LValAsIntegerKind;
+  }
+  
+  static inline LValAsInteger Make(BasicValueFactory& Vals, LVal V,
+                                   unsigned Bits) {    
+    return LValAsInteger(Vals.getPersistentSizedRVal(V, Bits));
+  }
+};
+  
 } // end namespace clang::nonlval
 
 //==------------------------------------------------------------------------==//
diff --git a/lib/Analysis/BasicValueFactory.cpp b/lib/Analysis/BasicValueFactory.cpp
index 88b360d..22fb2d1 100644
--- a/lib/Analysis/BasicValueFactory.cpp
+++ b/lib/Analysis/BasicValueFactory.cpp
@@ -14,15 +14,32 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Analysis/PathSensitive/BasicValueFactory.h"
+#include "clang/Analysis/PathSensitive/RValues.h"
 
 using namespace clang;
 
+typedef std::pair<RVal, unsigned> SizedRVal;
+
+namespace llvm {
+template<> struct FoldingSetTrait<SizedRVal> {
+  static inline void Profile(const SizedRVal& X, llvm::FoldingSetNodeID& ID) {
+    X.first.Profile(ID);
+    ID.AddInteger(X.second);
+  }
+};
+}
+
+typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SizedRVal> >
+  PersistentRValsTy;
+
 BasicValueFactory::~BasicValueFactory() {
   // Note that the dstor for the contents of APSIntSet will never be called,
   // so we iterate over the set and invoke the dstor for each APSInt.  This
   // frees an aux. memory allocated to represent very large constants.
   for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
     I->getValue().~APSInt();
+  
+  delete (PersistentRValsTy*) PersistentRVals;  
 }
 
 const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
@@ -165,3 +182,29 @@
       return &getValue( V1 ^ V2 );
   }
 }
+
+
+const std::pair<RVal, unsigned>&
+BasicValueFactory::getPersistentSizedRVal(const RVal& V, unsigned Bits) {
+  
+  // Lazily create the folding set.
+  if (!PersistentRVals) PersistentRVals = new PersistentRValsTy();
+    
+  llvm::FoldingSetNodeID ID;
+  void* InsertPos;
+  V.Profile(ID);
+  ID.AddInteger(Bits);
+  
+  PersistentRValsTy& Map = *((PersistentRValsTy*) PersistentRVals);
+  
+  typedef llvm::FoldingSetNodeWrapper<SizedRVal> FoldNodeTy;
+  FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
+  
+  if (!P) {  
+    P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
+    new (P) FoldNodeTy(std::make_pair(V, Bits));
+    Map.InsertNode(P, InsertPos);
+  }
+
+  return *P;
+}
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);
+    }
   }
 }
 
diff --git a/lib/Analysis/RValues.cpp b/lib/Analysis/RValues.cpp
index 2e44e70..86f5ac9 100644
--- a/lib/Analysis/RValues.cpp
+++ b/lib/Analysis/RValues.cpp
@@ -35,6 +35,10 @@
     
     return (symbol_iterator) &C.getSymbol();
   }
+  else if (isa<nonlval::LValAsInteger>(this)) {
+    const nonlval::LValAsInteger& V = cast<nonlval::LValAsInteger>(*this);
+    return  V.getPersistentLVal().symbol_begin();
+  }
   
   return NULL;
 }
@@ -345,7 +349,14 @@
         Out << 'U';
       
       break;
-    }  
+    }
+    
+    case nonlval::LValAsIntegerKind: {
+      const nonlval::LValAsInteger& C = *cast<nonlval::LValAsInteger>(this);
+      C.getLVal().print(Out);
+      Out << " [as " << C.getNumBits() << " bit integer]";
+      break;
+    }
       
     default:
       assert (false && "Pretty-printed not implemented for this NonLVal.");
diff --git a/lib/Analysis/ValueState.cpp b/lib/Analysis/ValueState.cpp
index c0ed7aa..bba2e06 100644
--- a/lib/Analysis/ValueState.cpp
+++ b/lib/Analysis/ValueState.cpp
@@ -277,12 +277,7 @@
           return UnknownVal();
           
         QualType ST = C->getSubExpr()->getType();
-        
-        if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
-          E = C->getSubExpr();
-          continue;
-        }
-        
+
         break;
       }
         
@@ -294,11 +289,6 @@
         if (CT->isVoidType())
           return UnknownVal();
         
-        if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
-          E = C->getSubExpr();
-          continue;
-        }
-        
         break;
       }
         
diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c
index b78c93a..6d954fd 100644
--- a/test/Analysis/null-deref-ps.c
+++ b/test/Analysis/null-deref-ps.c
@@ -1,5 +1,7 @@
 // RUN: clang -checker-simple -verify %s
 
+#include<stdint.h>
+
 void f1(int *p) {  
   if (p) *p = 1;
   else *p = 0; // expected-warning{{ereference}}
@@ -27,3 +29,13 @@
   return x[i+1]; // expected-warning{{Dereference of null pointer.}}
 }
 
+int f4(int *p) {
+  
+  uintptr_t x = p;
+  
+  if (x)
+    return 1;
+    
+  int *q = (int*) x;
+  return *q; // expected-warning{{Dereference of null pointer.}}
+}
\ No newline at end of file