NoQ updated this revision to Diff 148681. NoQ added a comment. Optimize `simplifySVal()` instead of reducing the threshold.
I'll address the memoization separately. https://reviews.llvm.org/D47155 Files: include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp test/Analysis/hangs.c Index: test/Analysis/hangs.c =================================================================== --- /dev/null +++ test/Analysis/hangs.c @@ -0,0 +1,30 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker core -verify %s + +// expected-no-diagnostics + +// Stuff that used to hang. + +int g(); + +int f(int y) { + return y + g(); +} + +int produce_a_very_large_symbol(int x) { + return f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f( + f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(x)))))))))))))))))))))))))))))))); +} + +void produce_an_exponentially_exploding_symbol(int x, int y) { + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); +} Index: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp =================================================================== --- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -1222,6 +1222,10 @@ ProgramStateRef State; SValBuilder &SVB; + static bool isUnchanged(SymbolRef Sym, SVal Val) { + return Sym == Val.getAsSymbol(); + } + public: Simplifier(ProgramStateRef State) : State(State), SVB(State->getStateManager().getSValBuilder()) {} @@ -1231,15 +1235,16 @@ SVB.getKnownValue(State, nonloc::SymbolVal(S))) return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I) : (SVal)SVB.makeIntVal(*I); - return Loc::isLocType(S->getType()) ? (SVal)SVB.makeLoc(S) - : nonloc::SymbolVal(S); + return SVB.makeSymbolVal(S); } // TODO: Support SymbolCast. Support IntSymExpr when/if we actually // start producing them. SVal VisitSymIntExpr(const SymIntExpr *S) { SVal LHS = Visit(S->getLHS()); + if (isUnchanged(S->getLHS(), LHS)) + return SVB.makeSymbolVal(S); SVal RHS; // By looking at the APSInt in the right-hand side of S, we cannot // figure out if it should be treated as a Loc or as a NonLoc. @@ -1264,6 +1269,8 @@ SVal VisitSymSymExpr(const SymSymExpr *S) { SVal LHS = Visit(S->getLHS()); SVal RHS = Visit(S->getRHS()); + if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS)) + return SVB.makeSymbolVal(S); return SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()); } Index: include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -367,6 +367,15 @@ return loc::ConcreteInt(BasicVals.getValue(integer)); } + /// Make an SVal that represents the given symbol. This follows the convention + /// of representing Loc-type symbols (symbolic pointers and references) + /// as Loc values wrapping the symbol rather than as plain symbol values. + SVal makeSymbolVal(SymbolRef Sym) { + if (Loc::isLocType(Sym->getType())) + return makeLoc(Sym); + return nonloc::SymbolVal(Sym); + } + /// Return a memory region for the 'this' object reference. loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC);
Index: test/Analysis/hangs.c =================================================================== --- /dev/null +++ test/Analysis/hangs.c @@ -0,0 +1,30 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker core -verify %s + +// expected-no-diagnostics + +// Stuff that used to hang. + +int g(); + +int f(int y) { + return y + g(); +} + +int produce_a_very_large_symbol(int x) { + return f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f( + f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(x)))))))))))))))))))))))))))))))); +} + +void produce_an_exponentially_exploding_symbol(int x, int y) { + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); + x += y; y += x + g(); +} Index: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp =================================================================== --- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -1222,6 +1222,10 @@ ProgramStateRef State; SValBuilder &SVB; + static bool isUnchanged(SymbolRef Sym, SVal Val) { + return Sym == Val.getAsSymbol(); + } + public: Simplifier(ProgramStateRef State) : State(State), SVB(State->getStateManager().getSValBuilder()) {} @@ -1231,15 +1235,16 @@ SVB.getKnownValue(State, nonloc::SymbolVal(S))) return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I) : (SVal)SVB.makeIntVal(*I); - return Loc::isLocType(S->getType()) ? (SVal)SVB.makeLoc(S) - : nonloc::SymbolVal(S); + return SVB.makeSymbolVal(S); } // TODO: Support SymbolCast. Support IntSymExpr when/if we actually // start producing them. SVal VisitSymIntExpr(const SymIntExpr *S) { SVal LHS = Visit(S->getLHS()); + if (isUnchanged(S->getLHS(), LHS)) + return SVB.makeSymbolVal(S); SVal RHS; // By looking at the APSInt in the right-hand side of S, we cannot // figure out if it should be treated as a Loc or as a NonLoc. @@ -1264,6 +1269,8 @@ SVal VisitSymSymExpr(const SymSymExpr *S) { SVal LHS = Visit(S->getLHS()); SVal RHS = Visit(S->getRHS()); + if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS)) + return SVB.makeSymbolVal(S); return SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()); } Index: include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -367,6 +367,15 @@ return loc::ConcreteInt(BasicVals.getValue(integer)); } + /// Make an SVal that represents the given symbol. This follows the convention + /// of representing Loc-type symbols (symbolic pointers and references) + /// as Loc values wrapping the symbol rather than as plain symbol values. + SVal makeSymbolVal(SymbolRef Sym) { + if (Loc::isLocType(Sym->getType())) + return makeLoc(Sym); + return nonloc::SymbolVal(Sym); + } + /// Return a memory region for the 'this' object reference. loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits