[cfe-commits] r170829 - in /cfe/trunk: include/clang/Analysis/CallGraph.h lib/Analysis/CallGraph.cpp lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp test/Analysis/debug-CallGraph.c
Rafael Espindola
rafael.espindola at gmail.com
Thu Dec 20 17:30:23 PST 2012
Author: rafael
Date: Thu Dec 20 19:30:23 2012
New Revision: 170829
URL: http://llvm.org/viewvc/llvm-project?rev=170829&view=rev
Log:
Revert r170826. The output of
./bin/clang -cc1 -internal-isystem /home/espindola/llvm/build/lib/clang/3.3/include/ -analyze -analyzer-checker=debug.DumpCallGraph /home/espindola/llvm/clang/test/Analysis/debug-CallGraph.c -fblocks
changes in each run.
Modified:
cfe/trunk/include/clang/Analysis/CallGraph.h
cfe/trunk/lib/Analysis/CallGraph.cpp
cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
cfe/trunk/test/Analysis/debug-CallGraph.c
Modified: cfe/trunk/include/clang/Analysis/CallGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CallGraph.h?rev=170829&r1=170828&r2=170829&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/CallGraph.h (original)
+++ cfe/trunk/include/clang/Analysis/CallGraph.h Thu Dec 20 19:30:23 2012
@@ -39,9 +39,15 @@
/// FunctionMap owns all CallGraphNodes.
FunctionMapTy FunctionMap;
- /// This is a virtual root node that has edges to all the functions.
+ /// This is a virtual root node that has edges to all the global functions -
+ /// 'main' or functions accessible from other translation units.
CallGraphNode *Root;
+ /// The list of nodes that have no parent. These are unreachable from Root.
+ /// Declarations can get to this list due to impressions in the graph, for
+ /// example, we do not track functions whose addresses were taken.
+ llvm::SetVector<CallGraphNode *> ParentlessNodes;
+
public:
CallGraph();
~CallGraph();
@@ -85,6 +91,12 @@
/// failing to add a call edge due to the analysis imprecision.
typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
+ nodes_iterator parentless_begin() { return ParentlessNodes.begin(); }
+ nodes_iterator parentless_end() { return ParentlessNodes.end(); }
+ const_nodes_iterator
+ parentless_begin() const { return ParentlessNodes.begin(); }
+ const_nodes_iterator
+ parentless_end() const { return ParentlessNodes.end(); }
void print(raw_ostream &os) const;
void dump() const;
@@ -158,6 +170,7 @@
void addCallee(CallGraphNode *N, CallGraph *CG) {
CalledFunctions.push_back(N);
+ CG->ParentlessNodes.remove(N);
}
Decl *getDecl() const { return FD; }
Modified: cfe/trunk/lib/Analysis/CallGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CallGraph.cpp?rev=170829&r1=170828&r2=170829&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CallGraph.cpp (original)
+++ cfe/trunk/lib/Analysis/CallGraph.cpp Thu Dec 20 19:30:23 2012
@@ -141,8 +141,14 @@
void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
assert(D);
+ // Do nothing if the node already exists.
+ if (FunctionMap.find(D) != FunctionMap.end())
+ return;
+
// Allocate a new node, mark it as root, and process it's calls.
CallGraphNode *Node = getOrInsertNode(D);
+ if (IsGlobal)
+ Root->addCallee(Node, this);
// Process all the calls by this function as well.
CGBuilder builder(this, Node);
@@ -162,9 +168,9 @@
return Node;
Node = new CallGraphNode(F);
- // Make Root node a parent of all functions to make sure all are reachable.
+ // If not root, add to the parentless list.
if (F != 0)
- Root->addCallee(Node, this);
+ ParentlessNodes.insert(Node);
return Node;
}
Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=170829&r1=170828&r2=170829&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Thu Dec 20 19:30:23 2012
@@ -39,7 +39,6 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Timer.h"
@@ -418,34 +417,61 @@
}
void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
- // Build the Call Graph by adding all the top level declarations to the graph.
+ // Otherwise, use the Callgraph to derive the order.
+ // Build the Call Graph.
+ CallGraph CG;
+
+ // Add all the top level declarations to the graph.
// Note: CallGraph can trigger deserialization of more items from a pch
// (though HandleInterestingDecl); triggering additions to LocalTUDecls.
// We rely on random access to add the initially processed Decls to CG.
- CallGraph CG;
for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
CG.addToCallGraph(LocalTUDecls[i]);
}
- // Walk over all of the call graph nodes in topological order, so that we
- // analyze parents before the children. Skip the functions inlined into
- // the previously processed functions. Use external Visited set to identify
- // inlined functions. The topological order allows the "do not reanalyze
- // previously inlined function" performance heuristic to be triggered more
- // often.
+ // Find the top level nodes - children of root + the unreachable (parentless)
+ // nodes.
+ llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
+ for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
+ TE = CG.parentless_end(); TI != TE; ++TI) {
+ TopLevelFunctions.push_back(*TI);
+ NumFunctionTopLevel++;
+ }
+ CallGraphNode *Entry = CG.getRoot();
+ for (CallGraphNode::iterator I = Entry->begin(),
+ E = Entry->end(); I != E; ++I) {
+ TopLevelFunctions.push_back(*I);
+ NumFunctionTopLevel++;
+ }
+
+ // Make sure the nodes are sorted in order reverse of their definition in the
+ // translation unit. This step is very important for performance. It ensures
+ // that we analyze the root functions before the externally available
+ // subroutines.
+ std::deque<CallGraphNode*> BFSQueue;
+ for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
+ TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
+ TI != TE; ++TI)
+ BFSQueue.push_back(*TI);
+
+ // BFS over all of the functions, while skipping the ones inlined into
+ // the previously processed functions. Use external Visited set, which is
+ // also modified when we inline a function.
SetOfConstDecls Visited;
SetOfConstDecls VisitedAsTopLevel;
- llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
- for (llvm::ReversePostOrderTraversal<clang::CallGraph*>::rpo_iterator
- I = RPOT.begin(); I != RPOT.end(); ++I) {
- NumFunctionTopLevel++;
+ while(!BFSQueue.empty()) {
+ CallGraphNode *N = BFSQueue.front();
+ BFSQueue.pop_front();
+
+ // Push the children into the queue.
+ for (CallGraphNode::const_iterator CI = N->begin(),
+ CE = N->end(); CI != CE; ++CI) {
+ if (!shouldSkipFunction((*CI)->getDecl(), Visited, VisitedAsTopLevel))
+ BFSQueue.push_back(*CI);
+ }
- CallGraphNode *N = *I;
Decl *D = N->getDecl();
-
- // Skip the abstract root node.
- if (!D)
- continue;
+ assert(D);
// Skip the functions which have been processed already or previously
// inlined.
Modified: cfe/trunk/test/Analysis/debug-CallGraph.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/debug-CallGraph.c?rev=170829&r1=170828&r2=170829&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/debug-CallGraph.c (original)
+++ cfe/trunk/test/Analysis/debug-CallGraph.c Thu Dec 20 19:30:23 2012
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCallGraph %s -fblocks 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCallGraph %s 2>&1 | FileCheck %s
static void mmm(int y) {
if (y != 0)
y++;
- y = y/y;
+ y = y/0;
}
static int foo(int x, int y) {
@@ -17,17 +17,5 @@
foo(1,2);
}
-void bbb(int y) {
- int x = (y > 2);
- ^ {
- foo(x, y);
- }();
-}
-
// CHECK:--- Call graph Dump ---
-// CHECK: Function: < root > calls: mmm foo aaa < > bbb
-// CHECK: Function: bbb calls: < >
-// CHECK: Function: mmm calls:
-// CHECK: Function: aaa calls: foo
-// CHECK: Function: foo calls: mmm
-// CHECK: Function: < > calls: foo
+// CHECK: Function: < root > calls: aaa
More information about the cfe-commits
mailing list