]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix symbolication for unknown unary increment/decrement results.
authorArtem Dergachev <artem.dergachev@gmail.com>
Tue, 28 Mar 2017 15:57:12 +0000 (15:57 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Tue, 28 Mar 2017 15:57:12 +0000 (15:57 +0000)
If the value is known, but we cannot increment it, conjure a symbol to
represent the result of the operation based on the operator expression,
not on the sub-expression.

In particular, no longer crash on comparing a result of a LocAsInteger increment
to a constant integer.

rdar://problem/31067356

Differential Revision: https://reviews.llvm.org/D31289

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

lib/StaticAnalyzer/Core/ExprEngineC.cpp
lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
test/Analysis/casts.c

index ea4ff916c85a07510103264c5db58043b633e770..8f720a2067b153ce489669c273296295a207cecf 100644 (file)
@@ -1054,7 +1054,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
     // Conjure a new symbol if necessary to recover precision.
     if (Result.isUnknown()){
       DefinedOrUnknownSVal SymVal =
-        svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+        svalBuilder.conjureSymbolVal(nullptr, U, LCtx,
                                      currBldrCtx->blockCount());
       Result = SymVal;
 
index 28b43dd566d5cb6d39a3aa32a5fac2b48a5a84e3..359841660bf4bbb36e14859bcea820a549389fed 100644 (file)
@@ -362,6 +362,9 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
                              resultTy);
         case nonloc::ConcreteIntKind: {
           // Transform the integer into a location and compare.
+          // FIXME: This only makes sense for comparisons. If we want to, say,
+          // add 1 to a LocAsInteger, we'd better unpack the Loc and add to it,
+          // then pack it back into a LocAsInteger.
           llvm::APSInt i = rhs.castAs<nonloc::ConcreteInt>().getValue();
           BasicVals.getAPSIntType(Context.VoidPtrTy).apply(i);
           return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
@@ -942,6 +945,8 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
     rhs = convertToArrayIndex(rhs).castAs<NonLoc>();
     SVal index = UnknownVal();
     const MemRegion *superR = nullptr;
+    // We need to know the type of the pointer in order to add an integer to it.
+    // Depending on the type, different amount of bytes is added.
     QualType elementType;
 
     if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
@@ -955,6 +960,10 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
       assert(op == BO_Add || op == BO_Sub);
       index = (op == BO_Add) ? rhs : evalMinus(rhs);
       superR = region;
+      // TODO: Is this actually reliable? Maybe improving our MemRegion
+      // hierarchy to provide typed regions for all non-void pointers would be
+      // better. For instance, we cannot extend this towards LocAsInteger
+      // operations, where result type of the expression is integer.
       if (resultTy->isAnyPointerType())
         elementType = resultTy->getPointeeType();
     }
index 92082fec2b13ec1902b4228c23cd67441c56f30a..3ba12e4318de168e6a60feed069a9936839ea451 100644 (file)
@@ -118,3 +118,8 @@ void castsToBool() {
   extern float globalFloat;
   clang_analyzer_eval(globalFloat); // expected-warning{{UNKNOWN}}
 }
+
+void locAsIntegerCasts(void *p) {
+  int x = (int) p;
+  clang_analyzer_eval(++x < 10); // no-crash // expected-warning{{UNKNOWN}}
+}