diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 1bece7fade4c..506debe0a0f0 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -80,10 +80,6 @@ private: /// usually because it could not reason about something. BlocksAborted blocksAborted; - /// The functions which have been analyzed through inlining. This is owned by - /// AnalysisConsumer. It can be null. - SetOfConstDecls *AnalyzedCallees; - /// The information about functions shared by the whole translation unit. /// (This data is owned by AnalysisConsumer.) FunctionSummariesTy *FunctionSummaries; @@ -108,12 +104,11 @@ private: public: /// Construct a CoreEngine object to analyze the provided CFG. - CoreEngine(SubEngine& subengine, SetOfConstDecls *VisitedCallees, + CoreEngine(SubEngine& subengine, FunctionSummariesTy *FS) : SubEng(subengine), G(new ExplodedGraph()), WList(WorkList::makeDFS()), BCounterFactory(G->getAllocator()), - AnalyzedCallees(VisitedCallees), FunctionSummaries(FS){} /// getGraph - Returns the exploded graph. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index f85670a576d7..ab155819382f 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -90,9 +90,13 @@ class ExprEngine : public SubEngine { /// destructor is called before the rest of the ExprEngine is destroyed. GRBugReporter BR; + /// The functions which have been analyzed through inlining. This is owned by + /// AnalysisConsumer. It can be null. + SetOfConstDecls *VisitedCallees; + public: ExprEngine(AnalysisManager &mgr, bool gcEnabled, - SetOfConstDecls *VisitedCallees, + SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS); ~ExprEngine(); diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 1f137424d450..8b7eeef470c8 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -243,11 +243,6 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc, case ProgramPoint::CallEnterKind: { CallEnter CEnter = cast(Loc); - if (AnalyzedCallees) - if (const CallExpr* CE = - dyn_cast_or_null(CEnter.getCallExpr())) - if (const Decl *CD = CE->getCalleeDecl()) - AnalyzedCallees->insert(CD); SubEng.processCallEnter(CEnter, Pred); break; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 15f47c39ae54..4225c67dc704 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -55,11 +55,11 @@ STATISTIC(NumTimesRetriedWithoutInlining, //===----------------------------------------------------------------------===// ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled, - SetOfConstDecls *VisitedCallees, + SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS) : AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()), - Engine(*this, VisitedCallees, FS), + Engine(*this, FS), G(Engine.getGraph()), StateMgr(getContext(), mgr.getStoreManagerCreator(), mgr.getConstraintManagerCreator(), G.getAllocator(), @@ -70,7 +70,8 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled, currStmt(NULL), currStmtIdx(0), currBldrCtx(0), NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), RaiseSel(GetNullarySelector("raise", getContext())), - ObjCGCEnabled(gcEnabled), BR(mgr, *this) + ObjCGCEnabled(gcEnabled), BR(mgr, *this), + VisitedCallees(VisitedCalleesIn) { if (mgr.options.eagerlyTrimExplodedGraph) { // Enable eager node reclaimation when constructing the ExplodedGraph. diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 70350ce0c1c5..4313e727c51f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -465,6 +465,10 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, NumInlinedCalls++; + // Mark the decl as visited. + if (VisitedCallees) + VisitedCallees->insert(D); + return true; } diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index a10a36481d14..bd643bab0374 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -348,6 +348,22 @@ void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) { } } +static bool shouldSkipFunction(CallGraphNode *N, + SmallPtrSet Visited) { + // We want to re-analyse the functions as top level in several cases: + // - The 'init' methods should be reanalyzed because + // ObjCNonNilReturnValueChecker assumes that '[super init]' never returns + // 'nil' and unless we analyze the 'init' functions as top level, we will not + // catch errors within defensive code. + // - We want to reanalyze all ObjC methods as top level to report Retain + // Count naming convention errors more aggressively. + if (isa(N->getDecl())) + return false; + + // Otherwise, if we visited the function before, do not reanalyze it. + return Visited.count(N); +} + void AnalysisConsumer::HandleDeclsGallGraph(const unsigned LocalTUDeclsSize) { // Otherwise, use the Callgraph to derive the order. // Build the Call Graph. @@ -397,13 +413,13 @@ void AnalysisConsumer::HandleDeclsGallGraph(const unsigned LocalTUDeclsSize) { // Push the children into the queue. for (CallGraphNode::const_iterator CI = N->begin(), CE = N->end(); CI != CE; ++CI) { - if (!Visited.count(*CI)) + if (!shouldSkipFunction(*CI, Visited)) BFSQueue.push_back(*CI); } // Skip the functions which have been processed already or previously // inlined. - if (Visited.count(N)) + if (shouldSkipFunction(N, Visited)) continue; // Analyze the function.