]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/7249327> by allowing silent conversions between signed and unsign...
authorTed Kremenek <kremenek@apple.com>
Fri, 25 Sep 2009 00:18:15 +0000 (00:18 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 25 Sep 2009 00:18:15 +0000 (00:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82737 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/BasicValueFactory.h
lib/Analysis/SimpleConstraintManager.cpp
lib/Analysis/SimpleSValuator.cpp
test/Analysis/misc-ps-region-store.m

index 69cd9db77cb9dea5a301d1ed256d1470f357b7f0..12f0ce2d50b7cb90b7b91ff31f439bc33713ce5a 100644 (file)
@@ -92,16 +92,25 @@ public:
 
   /// Convert - Create a new persistent APSInt with the same value as 'From'
   ///  but with the bitwidth and signedness of 'To'.
-  const llvm::APSIntConvert(const llvm::APSInt& To,
+  const llvm::APSInt &Convert(const llvm::APSInt& To,
                               const llvm::APSInt& From) {
 
     if (To.isUnsigned() == From.isUnsigned() &&
         To.getBitWidth() == From.getBitWidth())
       return From;
 
-    return getValue(From.getSExtValue(),
-                    To.getBitWidth(),
-                    To.isUnsigned());
+    return getValue(From.getSExtValue(), To.getBitWidth(), To.isUnsigned());
+  }
+  
+  const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
+    assert(T->isIntegerType() || Loc::IsLocType(T));
+    unsigned bitwidth = Ctx.getTypeSize(T);
+    bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
+    
+    if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth())
+      return From;
+    
+    return getValue(From.getSExtValue(), bitwidth, isUnsigned);
   }
 
   const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
index e4ad85aa8369be91c75b58e0fd705e4a35be893b..015db76080dfbe3091f14aa007406cf251e6885e 100644 (file)
@@ -162,8 +162,19 @@ const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
 
   case nonloc::SymExprValKind: {
     nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
-    if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression()))
-      return AssumeSymInt(state, Assumption, SE);
+    if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression())){
+      // FIXME: This is a hack.  It silently converts the RHS integer to be
+      // of the same type as on the left side.  This should be removed once
+      // we support truncation/extension of symbolic values.      
+      GRStateManager &StateMgr = state->getStateManager();
+      ASTContext &Ctx = StateMgr.getContext();
+      QualType LHSType = SE->getLHS()->getType(Ctx);
+      BasicValueFactory &BasicVals = StateMgr.getBasicVals();
+      const llvm::APSInt &RHS = BasicVals.Convert(LHSType, SE->getRHS());
+      SymIntExpr SENew(SE->getLHS(), SE->getOpcode(), RHS, SE->getType(Ctx));
+
+      return AssumeSymInt(state, Assumption, &SENew);
+    }
 
     // For all other symbolic expressions, over-approximate and consider
     // the constraint feasible.
index 6d944da45b0951d9fce56778e2c9f8119eb65960..52a591927dfe2045059736d903a245f0dd683fee 100644 (file)
@@ -68,6 +68,15 @@ SVal SimpleSValuator::EvalCastNL(NonLoc val, QualType castTy) {
     QualType T = Ctx.getCanonicalType(se->getType(Ctx));
     if (T == Ctx.getCanonicalType(castTy))
       return val;
+    
+    // FIXME: Remove this hack when we support symbolic truncation/extension.
+    // HACK: If both castTy and T are integers, ignore the cast.  This is
+    // not a permanent solution.  Eventually we want to precisely handle
+    // extension/truncation of symbolic integers.  This prevents us from losing
+    // precision when we assign 'x = y' and 'y' is symbolic and x and y are
+    // different integer types.
+    if (T->isIntegerType() && castTy->isIntegerType())
+      return val;
 
     return UnknownVal();
   }
index c5be02c821f93f00eb2c4b223ebc3afe6741888b..dd1e6455f0a5eb70cc80d41285c782368dbdb442 100644 (file)
@@ -207,3 +207,33 @@ void rdar_7249340(ptr_rdar_7249340 x) {
   *p = 0xDEADBEEF; // no-warning
 }
 
+// <rdar://problem/7249327> - This test case tests both value tracking of
+// array values and that we handle symbolic values that are casted
+// between different integer types.  Note the assignment 'n = *a++'; here
+// 'n' is and 'int' and '*a' is 'unsigned'.  Previously we got a false positive
+// at 'x += *b++' (undefined value) because we got a false path.
+int rdar_7249327_aux(void);
+
+void rdar_7249327(unsigned int A[2*32]) {
+  int B[2*32];
+  int *b;
+  unsigned int *a;
+  int x = 0;
+  
+  int n;
+  
+  a = A;
+  b = B;
+  
+  n = *a++;
+  if (n)
+    *b++ = rdar_7249327_aux();
+
+  a = A;
+  b = B;
+  
+  n = *a++;
+  if (n)
+    x += *b++; // no-warning
+}
+