]> granicus.if.org Git - clang/commitdiff
[analyzer] Push "references are non-null" knowledge up to the common parent.
authorJordan Rose <jordan_rose@apple.com>
Tue, 21 Aug 2012 20:52:19 +0000 (20:52 +0000)
committerJordan Rose <jordan_rose@apple.com>
Tue, 21 Aug 2012 20:52:19 +0000 (20:52 +0000)
This reduces duplication across the Basic and Range constraint managers, and
keeps their internals free of dealing with the semantics of C++. It's still
a little unfortunate that the constraint manager is dealing with this at all,
but this is pretty much the only place to put it so that it will apply to all
symbolic values, even when embedded in larger expressions.

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

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

index fb6d4be09da4289309d901e1dd9eac3b7ad993c2..9a3c5d1922497c0a3247637ef982795c1b319e52 100644 (file)
@@ -363,11 +363,6 @@ const llvm::APSInt* BasicConstraintManager::getSymVal(ProgramStateRef state,
 bool BasicConstraintManager::isNotEqual(ProgramStateRef state,
                                         SymbolRef sym,
                                         const llvm::APSInt& V) const {
-  // Special case: references are known to be non-zero.
-  if (sym->getType(getBasicVals().getContext())->isReferenceType())
-    if (V == 0)
-      return true;
-
   // Retrieve the NE-set associated with the given symbol.
   const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
 
index 2b883cf9b9beb8896142dc254c75d9925ae20929..550404a51075b30ba72c75cff0b2c98b4fdfc038 100644 (file)
@@ -380,17 +380,7 @@ RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) {
   // given symbol type.
   BasicValueFactory &BV = getBasicVals();
   QualType T = sym->getType(BV.getContext());
-
-  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;
+  return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
 }
 
 //===------------------------------------------------------------------------===
index 5568f1ca555d10fab7abf4760f46e1d7474fc780..0f675cdba7ad36c52bbc676a2417181c4ac5a549 100644 (file)
@@ -84,14 +84,9 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
     const SubRegion *SubR = dyn_cast<SubRegion>(R);
 
     while (SubR) {
-      // 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);
-      }
+      if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR))
+        return assumeAuxForSymbol(state, SymR->getSymbol(), Assumption);
+
       SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
     }
 
@@ -138,10 +133,13 @@ SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
   BasicValueFactory &BVF = getBasicVals();
   QualType T = Sym->getType(BVF.getContext());
 
-  // None of the constraint solvers currently support non-integer types.
-  if (!T->isIntegerType())
+  // Don't do anything if this isn't a type we can constrain.
+  if (!(T->isIntegralOrEnumerationType() || Loc::isLocType(T)))
     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);
@@ -161,8 +159,6 @@ 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");
@@ -185,12 +181,9 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
 
       BinaryOperator::Opcode op = SE->getOpcode();
       // Implicitly compare non-comparison expressions to 0.
-      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);
-      }
+      if (!BinaryOperator::isComparisonOp(op))
+        return assumeAuxForSymbol(state, SE, Assumption);
+
       // From here on out, op is the real comparison we'll be testing.
       if (!Assumption)
         op = NegateComparison(op);
@@ -238,8 +231,25 @@ 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(LHS->getType(Ctx));
+  APSIntType WraparoundType = BVF.getAPSIntType(Ty);
 
   // We only handle simple comparisons of the form "$sym == constant"
   // or "($sym+constant1) == constant2".
index d901bfee8a066ceb15116c7dfeef8055ff9b0fb2..f9a7e664d8f4714868ce2b975dee82eaeffc5236 100644 (file)
@@ -119,6 +119,9 @@ 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}}
 }