Despite me asking Jordan to do r162313, revert it. We can provide
authorTed Kremenek <kremenek@apple.com>
Wed, 22 Aug 2012 19:58:20 +0000 (19:58 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 22 Aug 2012 19:58:20 +0000 (19:58 +0000)
another way to whitelist these special cases.  This is an intermediate patch.

llvm-svn: 162386

clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
clang/test/Analysis/reference.cpp

index 550404a..2b883cf 100644 (file)
@@ -380,7 +380,17 @@ RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) {
   // given symbol type.
   BasicValueFactory &BV = getBasicVals();
   QualType T = sym->getType(BV.getContext());
-  return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
+
+  RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
+
+  // Special case: references are known to be non-zero.
+  if (T->isReferenceType()) {
+    APSIntType IntType = BV.getAPSIntType(T);
+    Result = Result.Intersect(BV, F, ++IntType.getZeroValue(),
+                                     --IntType.getZeroValue());
+  }
+
+  return Result;
 }
 
 //===------------------------------------------------------------------------===
index 0f675cd..5568f1c 100644 (file)
@@ -84,9 +84,14 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
     const SubRegion *SubR = dyn_cast<SubRegion>(R);
 
     while (SubR) {
-      if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR))
-        return assumeAuxForSymbol(state, SymR->getSymbol(), Assumption);
-
+      // FIXME: now we only find the first symbolic region.
+      if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
+        const llvm::APSInt &zero = getBasicVals().getZeroWithPtrWidth();
+        if (Assumption)
+          return assumeSymNE(state, SymR->getSymbol(), zero, zero);
+        else
+          return assumeSymEQ(state, SymR->getSymbol(), zero, zero);
+      }
       SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
     }
 
@@ -133,13 +138,10 @@ SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
   BasicValueFactory &BVF = getBasicVals();
   QualType T = Sym->getType(BVF.getContext());
 
-  // Don't do anything if this isn't a type we can constrain.
-  if (!(T->isIntegralOrEnumerationType() || Loc::isLocType(T)))
+  // None of the constraint solvers currently support non-integer types.
+  if (!T->isIntegerType())
     return State;
 
-  if (T->isReferenceType())
-    return Assumption ? State : NULL;
-
   const llvm::APSInt &zero = BVF.getValue(0, T);
   if (Assumption)
     return assumeSymNE(State, Sym, zero, zero);
@@ -159,6 +161,8 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
     return assumeAuxForSymbol(state, sym, Assumption);
   }
 
+  BasicValueFactory &BasicVals = getBasicVals();
+
   switch (Cond.getSubKind()) {
   default:
     llvm_unreachable("'Assume' not implemented for this NonLoc");
@@ -181,9 +185,12 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
 
       BinaryOperator::Opcode op = SE->getOpcode();
       // Implicitly compare non-comparison expressions to 0.
-      if (!BinaryOperator::isComparisonOp(op))
-        return assumeAuxForSymbol(state, SE, Assumption);
-
+      if (!BinaryOperator::isComparisonOp(op)) {
+        QualType T = SE->getType(BasicVals.getContext());
+        const llvm::APSInt &zero = BasicVals.getValue(0, T);
+        op = (Assumption ? BO_NE : BO_EQ);
+        return assumeSymRel(state, SE, op, zero);
+      }
       // From here on out, op is the real comparison we'll be testing.
       if (!Assumption)
         op = NegateComparison(op);
@@ -231,25 +238,8 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
   BasicValueFactory &BVF = getBasicVals();
   ASTContext &Ctx = BVF.getContext();
 
-  // Special case for references, which cannot be null.
-  QualType Ty = LHS->getType(Ctx);
-  if (Ty->isReferenceType() && Int == 0) {
-    switch (op) {
-    case BO_EQ:
-    case BO_LE:
-    case BO_LT:
-      return NULL;
-    case BO_NE:
-    case BO_GT:
-    case BO_GE:
-      return state;
-    default:
-      llvm_unreachable("We should only be handling comparisons here.");
-    }
-  }
-
   // Get the type used for calculating wraparound.
-  APSIntType WraparoundType = BVF.getAPSIntType(Ty);
+  APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType(Ctx));
 
   // We only handle simple comparisons of the form "$sym == constant"
   // or "($sym+constant1) == constant2".
index f6200c5..657795f 100644 (file)
@@ -118,9 +118,6 @@ void testReferenceAddress(int &x) {
 
   extern S *getS();
   clang_analyzer_eval(&getS()->x != 0); // expected-warning{{TRUE}}
-
-  // This actually takes a different path, because it's not a BinaryOperator.
-  clang_analyzer_eval(&getS()->x); // expected-warning{{TRUE}}
 }