xref: /minix3/external/bsd/llvm/dist/clang/lib/Analysis/CFGStmtMap.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc //  This file defines the CFGStmtMap class, which defines a mapping from
11f4a2713aSLionel Sambuc //  Stmt* to CFGBlock*
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "llvm/ADT/DenseMap.h"
16f4a2713aSLionel Sambuc #include "clang/AST/ParentMap.h"
17f4a2713aSLionel Sambuc #include "clang/Analysis/CFG.h"
18f4a2713aSLionel Sambuc #include "clang/Analysis/CFGStmtMap.h"
19f4a2713aSLionel Sambuc 
20f4a2713aSLionel Sambuc using namespace clang;
21f4a2713aSLionel Sambuc 
22f4a2713aSLionel Sambuc typedef llvm::DenseMap<const Stmt*, CFGBlock*> SMap;
AsMap(void * m)23f4a2713aSLionel Sambuc static SMap *AsMap(void *m) { return (SMap*) m; }
24f4a2713aSLionel Sambuc 
~CFGStmtMap()25f4a2713aSLionel Sambuc CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
26f4a2713aSLionel Sambuc 
getBlock(Stmt * S)27f4a2713aSLionel Sambuc CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
28f4a2713aSLionel Sambuc   SMap *SM = AsMap(M);
29f4a2713aSLionel Sambuc   Stmt *X = S;
30f4a2713aSLionel Sambuc 
31f4a2713aSLionel Sambuc   // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
32f4a2713aSLionel Sambuc   // is in the map.
33f4a2713aSLionel Sambuc   while (X) {
34f4a2713aSLionel Sambuc     SMap::iterator I = SM->find(X);
35f4a2713aSLionel Sambuc     if (I != SM->end()) {
36f4a2713aSLionel Sambuc       CFGBlock *B = I->second;
37f4a2713aSLionel Sambuc       // Memoize this lookup.
38f4a2713aSLionel Sambuc       if (X != S)
39f4a2713aSLionel Sambuc         (*SM)[X] = B;
40f4a2713aSLionel Sambuc       return B;
41f4a2713aSLionel Sambuc     }
42f4a2713aSLionel Sambuc 
43f4a2713aSLionel Sambuc     X = PM->getParentIgnoreParens(X);
44f4a2713aSLionel Sambuc   }
45f4a2713aSLionel Sambuc 
46*0a6a1f1dSLionel Sambuc   return nullptr;
47f4a2713aSLionel Sambuc }
48f4a2713aSLionel Sambuc 
Accumulate(SMap & SM,CFGBlock * B)49f4a2713aSLionel Sambuc static void Accumulate(SMap &SM, CFGBlock *B) {
50f4a2713aSLionel Sambuc   // First walk the block-level expressions.
51f4a2713aSLionel Sambuc   for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
52f4a2713aSLionel Sambuc     const CFGElement &CE = *I;
53f4a2713aSLionel Sambuc     Optional<CFGStmt> CS = CE.getAs<CFGStmt>();
54f4a2713aSLionel Sambuc     if (!CS)
55f4a2713aSLionel Sambuc       continue;
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc     CFGBlock *&Entry = SM[CS->getStmt()];
58f4a2713aSLionel Sambuc     // If 'Entry' is already initialized (e.g., a terminator was already),
59f4a2713aSLionel Sambuc     // skip.
60f4a2713aSLionel Sambuc     if (Entry)
61f4a2713aSLionel Sambuc       continue;
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc     Entry = B;
64f4a2713aSLionel Sambuc 
65f4a2713aSLionel Sambuc   }
66f4a2713aSLionel Sambuc 
67f4a2713aSLionel Sambuc   // Look at the label of the block.
68f4a2713aSLionel Sambuc   if (Stmt *Label = B->getLabel())
69f4a2713aSLionel Sambuc     SM[Label] = B;
70f4a2713aSLionel Sambuc 
71f4a2713aSLionel Sambuc   // Finally, look at the terminator.  If the terminator was already added
72f4a2713aSLionel Sambuc   // because it is a block-level expression in another block, overwrite
73f4a2713aSLionel Sambuc   // that mapping.
74f4a2713aSLionel Sambuc   if (Stmt *Term = B->getTerminator())
75f4a2713aSLionel Sambuc     SM[Term] = B;
76f4a2713aSLionel Sambuc }
77f4a2713aSLionel Sambuc 
Build(CFG * C,ParentMap * PM)78f4a2713aSLionel Sambuc CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
79f4a2713aSLionel Sambuc   if (!C || !PM)
80*0a6a1f1dSLionel Sambuc     return nullptr;
81f4a2713aSLionel Sambuc 
82f4a2713aSLionel Sambuc   SMap *SM = new SMap();
83f4a2713aSLionel Sambuc 
84f4a2713aSLionel Sambuc   // Walk all blocks, accumulating the block-level expressions, labels,
85f4a2713aSLionel Sambuc   // and terminators.
86f4a2713aSLionel Sambuc   for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
87f4a2713aSLionel Sambuc     Accumulate(*SM, *I);
88f4a2713aSLionel Sambuc 
89f4a2713aSLionel Sambuc   return new CFGStmtMap(PM, SM);
90f4a2713aSLionel Sambuc }
91f4a2713aSLionel Sambuc 
92