From 3b4c3ea2fb4de1126e1f07744e0e0bb480bed6ad Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Sat, 23 Mar 2013 01:21:05 +0000 Subject: [PATCH] [analyzer] Use SymExprs to represent ' - ' and ' == '. 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 . llvm-svn: 177800 --- .../StaticAnalyzer/Core/SimpleSValBuilder.cpp | 41 +++++++++++-------- clang/test/Analysis/ptr-arith.c | 12 ++++++ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 3e50c3300032..c6c96b5ddb66 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/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(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/clang/test/Analysis/ptr-arith.c b/clang/test/Analysis/ptr-arith.c index 9294c1832bdf..7f2582dc24ca 100644 --- a/clang/test/Analysis/ptr-arith.c +++ b/clang/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}} +}