]> granicus.if.org Git - clang/commitdiff
* API change: we need to pass GRState to GRExprEngine::EvalBinOp() because
authorZhongxing Xu <xuzhongxing@gmail.com>
Wed, 20 May 2009 09:00:16 +0000 (09:00 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Wed, 20 May 2009 09:00:16 +0000 (09:00 +0000)
  RegionStore needs to know the type of alloca region.
* RegionStoreManager::EvalBinOp() now converts the alloca region to its first
  element region, as what is done to symbolic region.

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

include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Analysis/PathSensitive/GRTransferFuncs.h
include/clang/Analysis/PathSensitive/Store.h
lib/Analysis/GRExprEngine.cpp
lib/Analysis/GRSimpleVals.cpp
lib/Analysis/GRSimpleVals.h
lib/Analysis/RegionStore.cpp
test/Analysis/array-struct.c

index d9556a08ac497013493e04cc36e82fe89c7f4905..2068b1beaa1349135e327cb99fc120f0d535a48d 100644 (file)
@@ -693,7 +693,8 @@ public:
   void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex,
                  BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T);  
   
-  SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, QualType T);
+  SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op, SVal L,SVal R,
+                 QualType T);
   
 protected:
   
index bee139f96816975a60407ec684df265e9175d5d3..0f353d07004f3e5c980ad91d071a252f34fdd21e 100644 (file)
@@ -67,8 +67,8 @@ public:
   
   // Pointer arithmetic.
   
-  virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
-                         Loc L, NonLoc R) = 0;
+  virtual SVal EvalBinOp(GRExprEngine& Engine, const GRState *state,
+                         BinaryOperator::Opcode Op, Loc L, NonLoc R) = 0;
   
   // Calls.
   
index adcb2f76e0f36c4a93fb72aa16ea66d4a97e847d..1f081f4eb0d0b8de18909b5919249e00cc6c722e 100644 (file)
@@ -137,7 +137,8 @@ public:
                                 QualType CastToTy);
 
   /// EvalBinOp - Perform pointer arithmetic.
-  virtual SVal EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) {
+  virtual SVal EvalBinOp(const GRState *state, 
+                         BinaryOperator::Opcode Op, Loc L, NonLoc R) {
     return UnknownVal();
   }
   
index bc6a36c747c9883f57f48d66622c662078ef84dd..e8c5be51d6ac3e24e78cbf3a5f7512014cd51a3c 100644 (file)
@@ -177,7 +177,7 @@ const GRState* GRExprEngine::getInitialState() {
       if (T->isIntegerType())
         if (const MemRegion *R = StateMgr.getRegion(PD)) {
           SVal V = GetSVal(state, loc::MemRegionVal(R));
-          SVal Constraint = EvalBinOp(BinaryOperator::GT, V,
+          SVal Constraint = EvalBinOp(state, BinaryOperator::GT, V,
                                       ValMgr.makeZeroVal(T),
                                       getContext().IntTy);          
           bool isFeasible = false;          
@@ -841,7 +841,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
         
     do {
       nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));      
-      SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal,
+      SVal Res = EvalBinOp(DefaultSt, BinaryOperator::EQ, CondV, CaseVal,
                            getContext().IntTy);
       
       // Now "assume" that the case matches.      
@@ -1333,7 +1333,8 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst,
     SVal oldValueVal = StateMgr.GetSVal(stateLoad, oldValueExpr);
         
     // Perform the comparison.
-    SVal Cmp = Engine.EvalBinOp(BinaryOperator::EQ, theValueVal, oldValueVal,
+    SVal Cmp = Engine.EvalBinOp(stateLoad,
+                                BinaryOperator::EQ, theValueVal, oldValueVal,
                                 Engine.getContext().IntTy);
     bool isFeasible = false;
     const GRState *stateEqual = StateMgr.Assume(stateLoad, Cmp, true,
@@ -2622,7 +2623,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
             
             if (isa<Loc>(V)) {
               Loc X = Loc::MakeNull(getBasicVals());
-              SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X,
+              SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast<Loc>(V), X,
                                       U->getType());
               state = BindExpr(state, U, Result);
             }
@@ -2679,7 +2680,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
       BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
                                                      : BinaryOperator::Sub;
 
-      SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U), U->getType());    
+      SVal Result = EvalBinOp(state, Op, V2, MakeConstantVal(1U, U), 
+                              U->getType());    
       
       // Conjure a new symbol if necessary to recover precision.
       if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
@@ -2690,7 +2692,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
         // non-nullness.  Check if the original value was non-null, and if so propagate
         // that constraint.        
         if (Loc::IsLocType(U->getType())) {
-          SVal Constraint = EvalBinOp(BinaryOperator::EQ, V2,
+          SVal Constraint = EvalBinOp(state, BinaryOperator::EQ, V2,
                                       ValMgr.makeZeroVal(U->getType()),
                                       getContext().IntTy);          
           
@@ -2699,7 +2701,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
           if (!isFeasible) {
             // It isn't feasible for the original value to be null.
             // Propagate this constraint.
-            Constraint = EvalBinOp(BinaryOperator::EQ, Result,
+            Constraint = EvalBinOp(state, BinaryOperator::EQ, Result,
                                    ValMgr.makeZeroVal(U->getType()),
                                    getContext().IntTy);
             
@@ -2965,7 +2967,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           // Process non-assignements except commas or short-circuited
           // logical expressions (LAnd and LOr).
           
-          SVal Result = EvalBinOp(Op, LeftV, RightV, B->getType());
+          SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType());
           
           if (Result.isUnknown()) {
             if (OldSt != state) {
@@ -3079,7 +3081,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
         }
       
         // Compute the result of the operation.      
-        SVal Result = EvalCast(EvalBinOp(Op, V, RightV, CTy), B->getType());
+        SVal Result = EvalCast(EvalBinOp(state, Op, V, RightV, CTy), 
+                               B->getType());
           
         if (Result.isUndef()) {
           // The operands were not undefined, but the result is undefined.
@@ -3147,8 +3150,8 @@ void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* state,
   if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R, T);
 }
 
-SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R,
-                             QualType T) {
+SVal GRExprEngine::EvalBinOp(const GRState* state, BinaryOperator::Opcode Op, 
+                             SVal L, SVal R, QualType T) {
   
   if (L.isUndef() || R.isUndef())
     return UndefinedVal();
@@ -3160,7 +3163,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R,
     if (isa<Loc>(R))
       return getTF().EvalBinOp(*this, Op, cast<Loc>(L), cast<Loc>(R));
     else
-      return getTF().EvalBinOp(*this, Op, cast<Loc>(L), cast<NonLoc>(R));
+      return getTF().EvalBinOp(*this, state, Op, cast<Loc>(L), cast<NonLoc>(R));
   }
   
   if (isa<Loc>(R)) {
@@ -3170,8 +3173,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R,
     assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub);
     
     // Commute the operands.
-    return getTF().EvalBinOp(*this, Op, cast<Loc>(R),
-                             cast<NonLoc>(L));
+    return getTF().EvalBinOp(*this, state, Op, cast<Loc>(R), cast<NonLoc>(L));
   }
   else
     return getTF().DetermEvalBinOpNN(*this, Op, cast<NonLoc>(L),
index 17e3c381dcf5b3ce254524641a25ba5cd059f161..e1c4848f45599de5462f6b3ae6fa75123442c850 100644 (file)
@@ -257,8 +257,8 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
   }
 }
 
-SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
-                             Loc L, NonLoc R) {
+SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, const GRState *state, 
+                             BinaryOperator::Opcode Op, Loc L, NonLoc R) {
   
   // Special case: 'R' is an integer that has the same width as a pointer and
   // we are using the integer location in a comparison.  Normally this cannot be
@@ -280,7 +280,7 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
   }
   
   // Delegate pointer arithmetic to store manager.
-  return Eng.getStoreManager().EvalBinOp(Op, L, R);
+  return Eng.getStoreManager().EvalBinOp(state, Op, L, R);
 }
 
 // Equality operators for Locs.  
index 1258cbc1bf487962537710b8a0247065aa78e5c3..6ef49dcdd22ee11c07ed48a97d94e5b613b94100 100644 (file)
@@ -53,8 +53,8 @@ public:
   
   // Pointer arithmetic.
   
-  virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
-                         Loc L, NonLoc R);  
+  virtual SVal EvalBinOp(GRExprEngine& Engine, const GRState *state,
+                         BinaryOperator::Opcode Op, Loc L, NonLoc R);  
   
   // Calls.
   
index e1d875b8f9fe95c41257539aa8b3c9561f5aa401..be34bd57b85424fa3b45f2a431bb2bb9c1f259ea 100644 (file)
@@ -214,7 +214,7 @@ public:
   CastResult CastRegion(const GRState* state, const MemRegion* R,
                         QualType CastToTy);
 
-  SVal EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R);
+  SVal EvalBinOp(const GRState *state,BinaryOperator::Opcode Op,Loc L,NonLoc R);
 
   /// The high level logic for this method is this:
   /// Retrieve (L)
@@ -636,15 +636,17 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
   return 0;
 }
 
-SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) {
+SVal RegionStoreManager::EvalBinOp(const GRState *state, 
+                                   BinaryOperator::Opcode Op, Loc L, NonLoc R) {
   // Assume the base location is MemRegionVal.
   if (!isa<loc::MemRegionVal>(L))
     return UnknownVal();
 
   const MemRegion* MR = cast<loc::MemRegionVal>(L).getRegion();
   const ElementRegion *ER = 0;
-  // If the operand is a symbolic region, we convert it to the first element
-  // region implicitly.
+
+  // If the operand is a symbolic or alloca region, create the first element
+  // region on it.
   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) {
     // Get symbol's type. It should be a pointer type.
     SymbolRef Sym = SR->getSymbol();
@@ -653,7 +655,18 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) {
 
     SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
     ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR);
-  } else
+  } 
+  else if (const AllocaRegion *AR = dyn_cast<AllocaRegion>(MR)) {
+    // Get the alloca region's current cast type.
+    GRStateRef StRef(state, StateMgr);
+
+    GRStateTrait<RegionCasts>::lookup_type T = StRef.get<RegionCasts>(AR);
+    assert(T && "alloca region has no type.");
+    QualType EleTy = cast<PointerType>(T->getTypePtr())->getPointeeType();
+    SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
+    ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR);
+  } 
+  else
     ER = cast<ElementRegion>(MR);
 
   SVal Idx = ER->getIndex();
index 318f92f907ee7eecb007ebcaa6caa38a0cd09e3e..17c0d46cd999a3fead9739c00471ccb050b02765 100644 (file)
@@ -63,6 +63,7 @@ void f6() {
   char *p;
   p = __builtin_alloca(10); 
   p[1] = 'a';
+  p += 2;
 }
 
 struct s2;