[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

Anna Zaks ganna at apple.com
Thu Dec 20 17:48:18 PST 2012


Thanks.

Anna.
On Dec 20, 2012, at 5:30 PM, Rafael Espindola wrote:

> 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
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list