]> granicus.if.org Git - clang/commitdiff
[analyzer] Use SymExprs to represent '<loc> - <loc>' and '<loc> == <loc>'.
authorJordan Rose <jordan_rose@apple.com>
Sat, 23 Mar 2013 01:21:05 +0000 (01:21 +0000)
committerJordan Rose <jordan_rose@apple.com>
Sat, 23 Mar 2013 01:21:05 +0000 (01:21 +0000)
We just treat this as opaque symbols, but even that allows us to handle
simple cases where the same condition is tested twice. This is very common
in the STL, which means that any project using the STL gets spurious errors.

Part of <rdar://problem/13239003>.

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

lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
test/Analysis/ptr-arith.c

index 3e50c3300032fa1ae48e4e05f05cada180400470..c6c96b5ddb6670c8937fe08741fb582f1062909e 100644 (file)
@@ -508,22 +508,21 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
           // Otherwise, make a SymIntExpr out of the expression.
           return MakeSymIntVal(symIntExpr, op, *RHSValue, resultTy);
         }
+      }
 
-
-      } else if (isa<SymbolData>(Sym)) {
-        // Does the symbol simplify to a constant?  If so, "fold" the constant
-        // by setting 'lhs' to a ConcreteInt and try again.
-        if (const llvm::APSInt *Constant = state->getConstraintManager()
-                                                  .getSymVal(state, Sym)) {
-          lhs = nonloc::ConcreteInt(*Constant);
-          continue;
-        }
-
-        // Is the RHS a constant?
-        if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
-          return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
+      // Does the symbolic expression simplify to a constant?
+      // If so, "fold" the constant by setting 'lhs' to a ConcreteInt
+      // and try again.
+      ConstraintManager &CMgr = state->getConstraintManager();
+      if (const llvm::APSInt *Constant = CMgr.getSymVal(state, Sym)) {
+        lhs = nonloc::ConcreteInt(*Constant);
+        continue;
       }
 
+      // Is the RHS a constant?
+      if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
+        return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
+
       // Give up -- this is not a symbolic expression we can handle.
       return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
     }
@@ -682,11 +681,11 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
       // regions, though.
       return UnknownVal();
 
-    const MemSpaceRegion *LeftMS = LeftMR->getMemorySpace();
-    const MemSpaceRegion *RightMS = RightMR->getMemorySpace();
-    const MemSpaceRegion *UnknownMS = MemMgr.getUnknownRegion();
     const MemRegion *LeftBase = LeftMR->getBaseRegion();
     const MemRegion *RightBase = RightMR->getBaseRegion();
+    const MemSpaceRegion *LeftMS = LeftBase->getMemorySpace();
+    const MemSpaceRegion *RightMS = RightBase->getMemorySpace();
+    const MemSpaceRegion *UnknownMS = MemMgr.getUnknownRegion();
 
     // If the two regions are from different known memory spaces they cannot be
     // equal. Also, assume that no symbolic region (whose memory space is
@@ -789,7 +788,6 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
       }
 
       // If we get here, we have no way of comparing the ElementRegions.
-      return UnknownVal();
     }
 
     // See if both regions are fields of the same structure.
@@ -842,6 +840,13 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
       llvm_unreachable("Fields not found in parent record's definition");
     }
 
+    // At this point we're not going to get a good answer, but we can try
+    // conjuring an expression instead.
+    SymbolRef LHSSym = lhs.getAsLocSymbol();
+    SymbolRef RHSSym = rhs.getAsLocSymbol();
+    if (LHSSym && RHSSym)
+      return makeNonLoc(LHSSym, op, RHSSym, resultTy);
+
     // If we get here, we have no way of comparing the regions.
     return UnknownVal();
   }
index 9294c1832bdfacd9a7732c9b9e3b1a7266906b82..7f2582dc24ca7fde1dbe4bda4b04714858c9324c 100644 (file)
@@ -167,3 +167,15 @@ void PR7527 (int *p) {
   if (((int) p) & 1) // not crash
     return;
 }
+
+void use_symbols(int *lhs, int *rhs) {
+  clang_analyzer_eval(lhs < rhs); // expected-warning{{UNKNOWN}}
+  if (lhs < rhs)
+    return;
+  clang_analyzer_eval(lhs < rhs); // expected-warning{{FALSE}}
+
+  clang_analyzer_eval(lhs - rhs); // expected-warning{{UNKNOWN}}
+  if ((lhs - rhs) != 5)
+    return;
+  clang_analyzer_eval((lhs - rhs) == 5); // expected-warning{{TRUE}}
+}