zcov: / lib/Checker/ExplodedGraph.cpp


Files: 1 Branches Taken: 67.7% 65 / 96
Generated: 2010-02-10 01:31 Branches Executed: 87.5% 84 / 96
Line Coverage: 91.5% 108 / 118


Programs: 1 Runs 2897


       1                 : //=-- ExplodedGraph.cpp - Local, Path-Sens. "Exploded Graph" -*- C++ -*------=//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : //  This file defines the template classes ExplodedNode and ExplodedGraph,
      11                 : //  which represent a path-sensitive, intra-procedural "exploded graph."
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "clang/Checker/PathSensitive/ExplodedGraph.h"
      16                 : #include "clang/Checker/PathSensitive/GRState.h"
      17                 : #include "clang/AST/Stmt.h"
      18                 : #include "llvm/ADT/DenseSet.h"
      19                 : #include "llvm/ADT/DenseMap.h"
      20                 : #include "llvm/ADT/SmallVector.h"
      21                 : #include <vector>
      22                 : 
      23                 : using namespace clang;
      24                 : 
      25                 : //===----------------------------------------------------------------------===//
      26                 : // Node auditing.
      27                 : //===----------------------------------------------------------------------===//
      28                 : 
      29                 : // An out of line virtual method to provide a home for the class vtable.
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
      30                0: ExplodedNode::Auditor::~Auditor() {}
      31                 : 
      32                 : #ifndef NDEBUG
      33                 : static ExplodedNode::Auditor* NodeAuditor = 0;
      34                 : #endif
      35                 : 
      36             2138: void ExplodedNode::SetAuditor(ExplodedNode::Auditor* A) {
      37                 : #ifndef NDEBUG
      38             2138:   NodeAuditor = A;
      39                 : #endif
      40             2138: }
      41                 : 
      42                 : //===----------------------------------------------------------------------===//
      43                 : // ExplodedNode.
      44                 : //===----------------------------------------------------------------------===//
      45                 : 
      46              884: static inline BumpVector<ExplodedNode*>& getVector(void* P) {
      47              884:   return *reinterpret_cast<BumpVector<ExplodedNode*>*>(P);
      48                 : }
      49                 : 
      50            72311: void ExplodedNode::addPredecessor(ExplodedNode* V, ExplodedGraph &G) {
                        0: branch 1 not taken
                    72311: branch 2 taken
      51            72311:   assert (!V->isSink());
      52            72311:   Preds.addNode(V, G);
      53            72311:   V->Succs.addNode(this, G);
      54                 : #ifndef NDEBUG
                        0: branch 0 not taken
                    72311: branch 1 taken
      55            72311:   if (NodeAuditor) NodeAuditor->AddEdge(V, this);
      56                 : #endif
      57            72311: }
      58                 : 
      59           144622: void ExplodedNode::NodeGroup::addNode(ExplodedNode* N, ExplodedGraph &G) {
                        0: branch 0 not taken
                   144622: branch 1 taken
      60           144622:   assert((reinterpret_cast<uintptr_t>(N) & Mask) == 0x0);
                        0: branch 1 not taken
                   144622: branch 2 taken
      61           144622:   assert(!getFlag());
      62                 : 
                   144502: branch 1 taken
                      120: branch 2 taken
      63           144622:   if (getKind() == Size1) {
                     1705: branch 1 taken
                   142797: branch 2 taken
      64           144502:     if (ExplodedNode* NOld = getNode()) {
      65             1705:       BumpVectorContext &Ctx = G.getNodeAllocator();
      66                 :       BumpVector<ExplodedNode*> *V = 
      67             1705:         G.getAllocator().Allocate<BumpVector<ExplodedNode*> >();
                     1705: branch 1 taken
                        0: branch 2 not taken
      68             1705:       new (V) BumpVector<ExplodedNode*>(Ctx, 4);
      69                 :       
                        0: branch 0 not taken
                     1705: branch 1 taken
      70             1705:       assert((reinterpret_cast<uintptr_t>(V) & Mask) == 0x0);
      71             1705:       V->push_back(NOld, Ctx);
      72             1705:       V->push_back(N, Ctx);
      73             1705:       P = reinterpret_cast<uintptr_t>(V) | SizeOther;
                        0: branch 1 not taken
                     1705: branch 2 taken
      74             1705:       assert(getPtr() == (void*) V);
                        0: branch 1 not taken
                     1705: branch 2 taken
      75             1705:       assert(getKind() == SizeOther);
      76                 :     }
      77                 :     else {
      78           142797:       P = reinterpret_cast<uintptr_t>(N);
                        0: branch 1 not taken
                   142797: branch 2 taken
      79           142797:       assert(getKind() == Size1);
      80                 :     }
      81                 :   }
      82                 :   else {
                        0: branch 1 not taken
                      120: branch 2 taken
      83              120:     assert(getKind() == SizeOther);
      84              120:     getVector(getPtr()).push_back(N, G.getNodeAllocator());
      85                 :   }
      86           144622: }
      87                 : 
      88                0: unsigned ExplodedNode::NodeGroup::size() const {
                        0: branch 1 not taken
                        0: branch 2 not taken
      89                0:   if (getFlag())
      90                0:     return 0;
      91                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
      92                0:   if (getKind() == Size1)
                        0: branch 1 not taken
                        0: branch 2 not taken
      93                0:     return getNode() ? 1 : 0;
      94                 :   else
      95                0:     return getVector(getPtr()).size();
      96                 : }
      97                 : 
      98            55152: ExplodedNode **ExplodedNode::NodeGroup::begin() const {
                      359: branch 1 taken
                    54793: branch 2 taken
      99            55152:   if (getFlag())
     100              359:     return NULL;
     101                 : 
                    54411: branch 1 taken
                      382: branch 2 taken
     102            54793:   if (getKind() == Size1)
                    53707: branch 1 taken
                      704: branch 2 taken
     103            54411:     return (ExplodedNode**) (getPtr() ? &P : NULL);
     104                 :   else
     105              382:     return const_cast<ExplodedNode**>(&*(getVector(getPtr()).begin()));
     106                 : }
     107                 : 
     108            43288: ExplodedNode** ExplodedNode::NodeGroup::end() const {
                      359: branch 1 taken
                    42929: branch 2 taken
     109            43288:   if (getFlag())
     110              359:     return NULL;
     111                 : 
                    42547: branch 1 taken
                      382: branch 2 taken
     112            42929:   if (getKind() == Size1)
                    41843: branch 1 taken
                      704: branch 2 taken
     113            42547:     return (ExplodedNode**) (getPtr() ? &P+1 : NULL);
     114                 :   else {
     115                 :     // Dereferencing end() is undefined behaviour. The vector is not empty, so
     116                 :     // we can dereference the last elem and then add 1 to the result.
     117              382:     return const_cast<ExplodedNode**>(getVector(getPtr()).end());
     118                 :   }
     119                 : }
     120                 : 
     121                 : ExplodedNode *ExplodedGraph::getNode(const ProgramPoint& L,
     122            75579:                                      const GRState* State, bool* IsNew) {
     123                 :   // Profile 'State' to determine if we already have an existing node.
     124            75579:   llvm::FoldingSetNodeID profile;
     125            75579:   void* InsertPos = 0;
     126                 : 
     127            75579:   NodeTy::Profile(profile, L, State);
     128            75579:   NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
     129                 : 
                    75379: branch 0 taken
                      200: branch 1 taken
     130            75579:   if (!V) {
     131                 :     // Allocate a new node.
     132            75379:     V = (NodeTy*) getAllocator().Allocate<NodeTy>();
                    75379: branch 1 taken
                        0: branch 2 not taken
     133            75379:     new (V) NodeTy(L, State);
     134                 : 
     135                 :     // Insert the node into the node set and return it.
     136            75379:     Nodes.InsertNode(V, InsertPos);
     137                 : 
     138            75379:     ++NumNodes;
     139                 : 
                    58145: branch 0 taken
                    17234: branch 1 taken
     140            75379:     if (IsNew) *IsNew = true;
     141                 :   }
     142                 :   else
                      200: branch 0 taken
                        0: branch 1 not taken
     143              200:     if (IsNew) *IsNew = false;
     144                 : 
     145            75579:   return V;
     146                 : }
     147                 : 
     148                 : std::pair<ExplodedGraph*, InterExplodedGraphMap*>
     149                 : ExplodedGraph::Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
     150              580:                llvm::DenseMap<const void*, const void*> *InverseMap) const {
     151                 : 
                        0: branch 0 not taken
                      580: branch 1 taken
     152              580:   if (NBeg == NEnd)
     153                 :     return std::make_pair((ExplodedGraph*) 0,
     154                0:                           (InterExplodedGraphMap*) 0);
     155                 : 
                        0: branch 0 not taken
                      580: branch 1 taken
     156              580:   assert (NBeg < NEnd);
     157                 : 
     158              580:   llvm::OwningPtr<InterExplodedGraphMap> M(new InterExplodedGraphMap());
     159                 : 
     160              580:   ExplodedGraph* G = TrimInternal(NBeg, NEnd, M.get(), InverseMap);
     161                 : 
     162              580:   return std::make_pair(static_cast<ExplodedGraph*>(G), M.take());
     163                 : }
     164                 : 
     165                 : ExplodedGraph*
     166                 : ExplodedGraph::TrimInternal(const ExplodedNode* const* BeginSources,
     167                 :                             const ExplodedNode* const* EndSources,
     168                 :                             InterExplodedGraphMap* M,
     169              580:                    llvm::DenseMap<const void*, const void*> *InverseMap) const {
     170                 : 
     171                 :   typedef llvm::DenseSet<const ExplodedNode*> Pass1Ty;
     172              580:   Pass1Ty Pass1;
     173                 : 
     174                 :   typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> Pass2Ty;
     175              580:   Pass2Ty& Pass2 = M->M;
     176                 : 
     177              580:   llvm::SmallVector<const ExplodedNode*, 10> WL1, WL2;
     178                 : 
     179                 :   // ===- Pass 1 (reverse DFS) -===
                      584: branch 0 taken
                      580: branch 1 taken
     180             1164:   for (const ExplodedNode* const* I = BeginSources; I != EndSources; ++I) {
                        0: branch 0 not taken
                      584: branch 1 taken
     181              584:     assert(*I);
     182              584:     WL1.push_back(*I);
     183                 :   }
     184                 : 
     185                 :   // Process the first worklist until it is empty.  Because it is a std::list
     186                 :   // it acts like a FIFO queue.
                     8841: branch 1 taken
                      580: branch 2 taken
     187            10001:   while (!WL1.empty()) {
     188             8841:     const ExplodedNode *N = WL1.back();
     189             8841:     WL1.pop_back();
     190                 : 
     191                 :     // Have we already visited this node?  If so, continue to the next one.
                       34: branch 1 taken
                     8807: branch 2 taken
     192             8841:     if (Pass1.count(N))
     193               34:       continue;
     194                 : 
     195                 :     // Otherwise, mark this node as visited.
     196             8807:     Pass1.insert(N);
     197                 : 
     198                 :     // If this is a root enqueue it to the second worklist.
                      580: branch 1 taken
                     8227: branch 2 taken
     199             8807:     if (N->Preds.empty()) {
     200              580:       WL2.push_back(N);
     201              580:       continue;
     202                 :     }
     203                 : 
     204                 :     // Visit our predecessors and enqueue them.
                     8257: branch 2 taken
                     8227: branch 3 taken
     205            16484:     for (ExplodedNode** I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I)
     206             8257:       WL1.push_back(*I);
     207                 :   }
     208                 : 
     209                 :   // We didn't hit a root? Return with a null pointer for the new graph.
                        0: branch 1 not taken
                      580: branch 2 taken
     210              580:   if (WL2.empty())
     211                0:     return 0;
     212                 : 
     213                 :   // Create an empty graph.
     214              580:   ExplodedGraph* G = MakeEmptyGraph();
     215                 : 
     216                 :   // ===- Pass 2 (forward DFS to construct the new graph) -===
                     8807: branch 1 taken
                      580: branch 2 taken
     217             9967:   while (!WL2.empty()) {
     218             8807:     const ExplodedNode* N = WL2.back();
     219             8807:     WL2.pop_back();
     220                 : 
     221                 :     // Skip this node if we have already processed it.
                        0: branch 4 not taken
                     8807: branch 5 taken
     222             8807:     if (Pass2.find(N) != Pass2.end())
     223                0:       continue;
     224                 : 
     225                 :     // Create the corresponding node in the new graph and record the mapping
     226                 :     // from the old node to the new node.
     227             8807:     ExplodedNode* NewN = G->getNode(N->getLocation(), N->State, NULL);
     228             8807:     Pass2[N] = NewN;
     229                 : 
     230                 :     // Also record the reverse mapping from the new node to the old node.
                     8807: branch 0 taken
                        0: branch 1 not taken
     231             8807:     if (InverseMap) (*InverseMap)[NewN] = N;
     232                 : 
     233                 :     // If this node is a root, designate it as such in the graph.
                      580: branch 1 taken
                     8227: branch 2 taken
     234             8807:     if (N->Preds.empty())
     235              580:       G->addRoot(NewN);
     236                 : 
     237                 :     // In the case that some of the intended predecessors of NewN have already
     238                 :     // been created, we should hook them up as predecessors.
     239                 : 
     240                 :     // Walk through the predecessors of 'N' and hook up their corresponding
     241                 :     // nodes in the new graph (if any) to the freshly created node.
                     8257: branch 2 taken
                     8807: branch 3 taken
     242            17064:     for (ExplodedNode **I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I) {
     243             8257:       Pass2Ty::iterator PI = Pass2.find(*I);
                       30: branch 3 taken
                     8227: branch 4 taken
     244             8257:       if (PI == Pass2.end())
     245               30:         continue;
     246                 : 
     247             8227:       NewN->addPredecessor(PI->second, *G);
     248                 :     }
     249                 : 
     250                 :     // In the case that some of the intended successors of NewN have already
     251                 :     // been created, we should hook them up as successors.  Otherwise, enqueue
     252                 :     // the new nodes from the original graph that should have nodes created
     253                 :     // in the new graph.
                     8550: branch 2 taken
                     8807: branch 3 taken
     254            17357:     for (ExplodedNode **I=N->Succs.begin(), **E=N->Succs.end(); I!=E; ++I) {
     255             8550:       Pass2Ty::iterator PI = Pass2.find(*I);
                       30: branch 3 taken
                     8520: branch 4 taken
     256             8550:       if (PI != Pass2.end()) {
     257               30:         PI->second->addPredecessor(NewN, *G);
     258               30:         continue;
     259                 :       }
     260                 : 
     261                 :       // Enqueue nodes to the worklist that were marked during pass 1.
                     8227: branch 1 taken
                      293: branch 2 taken
     262             8520:       if (Pass1.count(*I))
     263             8227:         WL2.push_back(*I);
     264                 :     }
     265                 : 
     266                 :     // Finally, explictly mark all nodes without any successors as sinks.
                      359: branch 1 taken
                     8448: branch 2 taken
     267             8807:     if (N->isSink())
     268              359:       NewN->markAsSink();
     269                 :   }
     270                 : 
     271              580:   return G;
     272                 : }
     273                 : 
     274                 : ExplodedNode*
     275              584: InterExplodedGraphMap::getMappedNode(const ExplodedNode* N) const {
     276                 :   llvm::DenseMap<const ExplodedNode*, ExplodedNode*>::const_iterator I =
     277              584:     M.find(N);
     278                 : 
                        0: branch 2 not taken
                      584: branch 3 taken
     279              584:   return I == M.end() ? 0 : I->second;
     280                 : }
     281                 : 

Generated: 2010-02-10 01:31 by zcov