[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