r177468 - [analyzer] Break cycles (optionally) when trimming an ExplodedGraph.

Jordan Rose jordan_rose at apple.com
Tue Mar 19 17:35:31 PDT 2013


Author: jrose
Date: Tue Mar 19 19:35:31 2013
New Revision: 177468

URL: http://llvm.org/viewvc/llvm-project?rev=177468&view=rev
Log:
[analyzer] Break cycles (optionally) when trimming an ExplodedGraph.

Having a trimmed graph with no cycles (a DAG) is much more convenient for
trying to find shortest paths, which is exactly what BugReporter needs to do.

Part of the performance work for <rdar://problem/13433687>.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h?rev=177468&r1=177467&r2=177468&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h Tue Mar 19 19:35:31 2013
@@ -363,12 +363,16 @@ public:
   ///
   /// \param Nodes The nodes which must appear in the final graph. Presumably
   ///              these are end-of-path nodes (i.e. they have no successors).
+  /// \param BreakCycles Whether or not the trimmed graph should make an effort
+  ///                    to eliminate cycles. Note that this may result in some
+  ///                    unnecessary nodes being included in the final graph
+  ///                    (i.e. nodes that would have only appeared in a cycle).
   /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in
   ///                        the returned graph.
   /// \param[out] InverseMap An optional map from nodes in the returned graph to
   ///                        nodes in this graph.
   /// \returns The trimmed graph
-  ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes,
+  ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes, bool BreakCycles = false,
                       InterExplodedGraphMap *ForwardMap = 0,
                       InterExplodedGraphMap *InverseMap = 0) const;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=177468&r1=177467&r2=177468&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Tue Mar 19 19:35:31 2013
@@ -1895,7 +1895,8 @@ public:
                ArrayRef<const ExplodedNode *> Nodes) {
     // The trimmed graph is created in the body of the constructor to ensure
     // that the DenseMaps have been initialized already.
-    G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap));
+    G.reset(OriginalGraph->trim(Nodes, /*BreakCycles=*/true,
+                                &ForwardMap, &InverseMap));
   }
 
   void createBestReportGraph(ArrayRef<const ExplodedNode *> Nodes,

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp?rev=177468&r1=177467&r2=177468&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp Tue Mar 19 19:35:31 2013
@@ -331,8 +331,22 @@ ExplodedNode *ExplodedGraph::getNode(con
   return V;
 }
 
+static bool isDescendent(const ExplodedNode *Parent, const ExplodedNode *Child){
+  SmallVector<const ExplodedNode *, 16> WL;
+  WL.push_back(Parent);
+
+  while (!WL.empty()) {
+    const ExplodedNode *N = WL.pop_back_val();
+    if (N == Child)
+      return true;
+    WL.append(N->succ_begin(), N->succ_end());
+  }
+
+  return false;
+}
+
 ExplodedGraph *
-ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
+ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks, bool BreakCycles,
                     InterExplodedGraphMap *ForwardMap,
                     InterExplodedGraphMap *InverseMap) const{
 
@@ -429,7 +443,8 @@ ExplodedGraph::trim(ArrayRef<const NodeT
          I != E; ++I) {
       Pass2Ty::iterator PI = Pass2.find(*I);
       if (PI != Pass2.end()) {
-        const_cast<ExplodedNode *>(PI->second)->addPredecessor(NewN, *G);
+        if (!BreakCycles || !isDescendent(PI->second, NewN))
+          const_cast<ExplodedNode *>(PI->second)->addPredecessor(NewN, *G);
         continue;
       }
 





More information about the cfe-commits mailing list