diff options
Diffstat (limited to 'clang')
5 files changed, 46 insertions, 5 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index be4c649133d..f8f7e25d8bb 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -32,6 +32,31 @@ namespace ento { typedef llvm::SmallPtrSet<const Decl*,24> SetOfDecls; +class FunctionSummariesTy { + struct FunctionSummary { + /// True if this function has reached a max block count while inlined from + /// at least one call site. + bool MayReachMaxBlockCount; + FunctionSummary() : MayReachMaxBlockCount(false) {} + }; + + typedef llvm::DenseMap<const Decl*, FunctionSummary> MapTy; + MapTy Map; + +public: + void markReachedMaxBlockCount(const Decl* D) { + Map[D].MayReachMaxBlockCount = true; + } + + bool hasReachedMaxBlockCount(const Decl* D) { + MapTy::const_iterator I = Map.find(D); + if (I != Map.end()) + return I->second.MayReachMaxBlockCount; + return false; + } + +}; + class AnalysisManager : public BugReporterData { virtual void anchor(); AnalysisDeclContextManager AnaCtxMgr; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index c0c6ef3fb46..f4d2e6027b5 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -90,8 +90,13 @@ class ExprEngine : public SubEngine { /// destructor is called before the rest of the ExprEngine is destroyed. GRBugReporter BR; + /// The information about functions shared by the whole translation unit. + /// (This data is owned by AnalysisConsumer.) + FunctionSummariesTy *FunctionSummaries; + public: - ExprEngine(AnalysisManager &mgr, bool gcEnabled, SetOfDecls *VisitedCallees); + ExprEngine(AnalysisManager &mgr, bool gcEnabled, SetOfDecls *VisitedCallees, + FunctionSummariesTy *FS); ~ExprEngine(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index fc2a756eb39..4789f354e49 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -67,7 +67,8 @@ static inline Selector GetNullarySelector(const char* name, ASTContext &Ctx) { //===----------------------------------------------------------------------===// ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled, - SetOfDecls *VisitedCallees) + SetOfDecls *VisitedCallees, + FunctionSummariesTy *FS) : AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()), Engine(*this, VisitedCallees), @@ -81,7 +82,7 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled, currentStmt(NULL), currentStmtIdx(0), currentBuilderContext(0), NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), RaiseSel(GetNullarySelector("raise", getContext())), - ObjCGCEnabled(gcEnabled), BR(mgr, *this) { + ObjCGCEnabled(gcEnabled), BR(mgr, *this), FunctionSummaries(FS) { if (mgr.shouldEagerlyTrimExplodedGraph()) { // Enable eager node reclaimation when constructing the ExplodedGraph. @@ -1046,9 +1047,12 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, // Check if we stopped at the top level function or not. // Root node should have the location context of the top most function. const LocationContext *CalleeLC = pred->getLocation().getLocationContext(); + const LocationContext *CalleeSF = CalleeLC->getCurrentStackFrame(); const LocationContext *RootLC = (*G.roots_begin())->getLocation().getLocationContext(); - if (RootLC->getCurrentStackFrame() != CalleeLC->getCurrentStackFrame()) { + if (RootLC->getCurrentStackFrame() != CalleeSF) { + FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl()); + // Re-run the call evaluation without inlining it, by storing the // no-inlining policy in the state and enqueuing the new work item on // the list. Replay should almost never fail. Use the stats to catch it diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 1746b5c529e..fead0862fa8 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -137,6 +137,9 @@ bool ExprEngine::shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred) { == AMgr.InlineMaxStackDepth) return false; + if (FunctionSummaries->hasReachedMaxBlockCount(FD)) + return false; + if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize) return false; diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index b1d2f31df0e..3b9deda2bac 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -104,6 +104,10 @@ public: /// Time the analyzes time of each translation unit. static llvm::Timer* TUTotalTimer; + /// The information about analyzed functions shared throughout the + /// translation unit. + FunctionSummariesTy FunctionSummaries; + AnalysisConsumer(const Preprocessor& pp, const std::string& outdir, const AnalyzerOptions& opts, @@ -449,7 +453,7 @@ void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled, if (!Mgr->getCFG(D)) return; - ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees); + ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries); // Set the graph auditor. OwningPtr<ExplodedNode::Auditor> Auditor; |