aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-03-09 21:14:01 +0000
committerAnna Zaks <ganna@apple.com>2012-03-09 21:14:01 +0000
commit3fd5f370a28552976c52e76c3035d79012d78dda (patch)
tree1f1c1ba1daec04eca122fb4ad6a44689b9221868 /lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
parenta5d531f67de0cfeb56b843da15146f3b4cd75bd9 (diff)
[analyzer] Add support for NoRedundancy inlining mode.
We do not reanalyze a function, which has already been analyzed as an inlined callee. As per PRELIMINARY testing, this gives over 50% run time reduction on some benchmarks without decreasing of the number of bugs found. Turning the mode on by default. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152440 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp')
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp70
1 files changed, 42 insertions, 28 deletions
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index e126657eb9..51761fb151 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -48,6 +48,7 @@ using llvm::SmallPtrSet;
static ExplodedNode::Auditor* CreateUbiViz();
+STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
STATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level).");
//===----------------------------------------------------------------------===//
@@ -189,7 +190,9 @@ public:
void HandleDeclContextDecl(ASTContext &C, Decl *D);
void HandleDeclContextDeclFunction(ASTContext &C, Decl *D);
- void HandleCode(Decl *D);
+ void HandleCode(Decl *D, SetOfDecls *VisitedCallees = 0);
+ void RunPathSensitiveChecks(Decl *D, SetOfDecls *VisitedCallees);
+ void ActionExprEngine(Decl *D, bool ObjCGCEnabled, SetOfDecls *VisitedCallees);
};
} // end anonymous namespace
@@ -219,15 +222,18 @@ void AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
// Find the top level nodes - children of root + the unreachable (parentless)
// nodes.
- llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
+ llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
CallGraphNode *Entry = CG.getRoot();
for (CallGraphNode::iterator I = Entry->begin(),
- E = Entry->end(); I != E; ++I)
+ E = Entry->end(); I != E; ++I) {
TopLevelFunctions.push_back(*I);
-
+ NumFunctionTopLevel++;
+ }
for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
- TE = CG.parentless_end(); TI != TE; ++TI)
+ TE = CG.parentless_end(); TI != TE; ++TI) {
TopLevelFunctions.push_back(*TI);
+ NumFunctionTopLevel++;
+ }
// TODO: Sort TopLevelFunctions.
@@ -241,12 +247,20 @@ void AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
DFI = llvm::df_ext_begin(*TI, Visited),
E = llvm::df_ext_end(*TI, Visited);
DFI != E; ++DFI) {
+ SetOfDecls VisitedCallees;
Decl *D = (*DFI)->getDecl();
assert(D);
- HandleCode(D);
+ HandleCode(D, (Mgr->InliningMode == All ? 0 : &VisitedCallees));
+
+ // Add the visited callees to the global visited set.
+ for (SetOfDecls::const_iterator I = VisitedCallees.begin(),
+ E = VisitedCallees.end(); I != E; ++I) {
+ CallGraphNode *VN = CG.getNode(*I);
+ if (VN)
+ Visited.insert(VN);
+ }
}
}
-
}
void AnalysisConsumer::HandleDeclContextDecl(ASTContext &C, Decl *D) {
@@ -284,6 +298,9 @@ void AnalysisConsumer::HandleDeclContextDeclFunction(ASTContext &C, Decl *D) {
case Decl::CXXMethod:
case Decl::Function: {
FunctionDecl *FD = cast<FunctionDecl>(D);
+ IdentifierInfo *II = FD->getIdentifier();
+ if (II && II->getName().startswith("__inline"))
+ break;
// We skip function template definitions, as their semantics is
// only determined when they are instantiated.
if (FD->isThisDeclarationADefinition() &&
@@ -350,9 +367,6 @@ static void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
FindBlocks(DC, WL);
}
-static void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
- Decl *D);
-
static std::string getFunctionName(const Decl *D) {
if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
return ID->getSelector().getAsString();
@@ -365,7 +379,7 @@ static std::string getFunctionName(const Decl *D) {
return "";
}
-void AnalysisConsumer::HandleCode(Decl *D) {
+void AnalysisConsumer::HandleCode(Decl *D, SetOfDecls *VisitedCallees) {
if (!Opts.AnalyzeSpecificFunction.empty() &&
getFunctionName(D) != Opts.AnalyzeSpecificFunction)
return;
@@ -400,7 +414,7 @@ void AnalysisConsumer::HandleCode(Decl *D) {
if ((*WI)->hasBody()) {
checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
if (checkerMgr->hasPathSensitiveCheckers())
- RunPathSensitiveChecks(*this, *Mgr, *WI);
+ RunPathSensitiveChecks(*WI, VisitedCallees);
}
NumFunctionsAnalyzed++;
}
@@ -409,52 +423,52 @@ void AnalysisConsumer::HandleCode(Decl *D) {
// Path-sensitive checking.
//===----------------------------------------------------------------------===//
-static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager &mgr,
- Decl *D, bool ObjCGCEnabled) {
+void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
+ SetOfDecls *VisitedCallees) {
// Construct the analysis engine. First check if the CFG is valid.
// FIXME: Inter-procedural analysis will need to handle invalid CFGs.
- if (!mgr.getCFG(D))
+ if (!Mgr->getCFG(D))
return;
- ExprEngine Eng(mgr, ObjCGCEnabled);
+
+ ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees);
// Set the graph auditor.
OwningPtr<ExplodedNode::Auditor> Auditor;
- if (mgr.shouldVisualizeUbigraph()) {
+ if (Mgr->shouldVisualizeUbigraph()) {
Auditor.reset(CreateUbiViz());
ExplodedNode::SetAuditor(Auditor.get());
}
// Execute the worklist algorithm.
- Eng.ExecuteWorkList(mgr.getAnalysisDeclContextManager().getStackFrame(D, 0),
- mgr.getMaxNodes());
+ Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D, 0),
+ Mgr->getMaxNodes());
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.
ExplodedNode::SetAuditor(0);
// Visualize the exploded graph.
- if (mgr.shouldVisualizeGraphviz())
- Eng.ViewGraph(mgr.shouldTrimGraph());
+ if (Mgr->shouldVisualizeGraphviz())
+ Eng.ViewGraph(Mgr->shouldTrimGraph());
// Display warnings.
Eng.getBugReporter().FlushReports();
}
-static void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
- Decl *D) {
+void AnalysisConsumer::RunPathSensitiveChecks(Decl *D, SetOfDecls *Visited) {
- switch (mgr.getLangOptions().getGC()) {
+ switch (Mgr->getLangOptions().getGC()) {
case LangOptions::NonGC:
- ActionExprEngine(C, mgr, D, false);
+ ActionExprEngine(D, false, Visited);
break;
case LangOptions::GCOnly:
- ActionExprEngine(C, mgr, D, true);
+ ActionExprEngine(D, true, Visited);
break;
case LangOptions::HybridGC:
- ActionExprEngine(C, mgr, D, false);
- ActionExprEngine(C, mgr, D, true);
+ ActionExprEngine(D, false, Visited);
+ ActionExprEngine(D, true, Visited);
break;
}
}