diff options
-rw-r--r-- | lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 39 | ||||
-rw-r--r-- | test/Analysis/ptr-arith.c | 12 |
2 files changed, 34 insertions, 17 deletions
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 3e50c33000..c6c96b5ddb 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -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(); } diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c index 9294c1832b..7f2582dc24 100644 --- a/test/Analysis/ptr-arith.c +++ b/test/Analysis/ptr-arith.c @@ -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}} +} |