StmtToBlockMap.h (2926B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef StmtToBlockMap_h__ 6 #define StmtToBlockMap_h__ 7 8 #include "Utils.h" 9 10 // This method is copied from clang-tidy's ExprSequence.cpp. 11 // 12 // Returns the Stmt nodes that are parents of 'S', skipping any potential 13 // intermediate non-Stmt nodes. 14 // 15 // In almost all cases, this function returns a single parent or no parents at 16 // all. 17 inline SmallVector<const Stmt *, 1> getParentStmts(const Stmt *S, 18 ASTContext *Context) { 19 SmallVector<const Stmt *, 1> Result; 20 21 auto Parents = Context->getParents(*S); 22 23 SmallVector<clang::DynTypedNode, 1> NodesToProcess(Parents.begin(), 24 Parents.end()); 25 26 while (!NodesToProcess.empty()) { 27 clang::DynTypedNode Node = NodesToProcess.back(); 28 NodesToProcess.pop_back(); 29 30 if (const auto *S = Node.get<Stmt>()) { 31 Result.push_back(S); 32 } else { 33 Parents = Context->getParents(Node); 34 NodesToProcess.append(Parents.begin(), Parents.end()); 35 } 36 } 37 38 return Result; 39 } 40 41 // This class is a modified version of the class from clang-tidy's 42 // ExprSequence.cpp 43 // 44 // Maps `Stmt`s to the `CFGBlock` that contains them. Some `Stmt`s may be 45 // contained in more than one `CFGBlock`; in this case, they are mapped to the 46 // innermost block (i.e. the one that is furthest from the root of the tree). 47 // An optional outparameter provides the index into the block where the `Stmt` 48 // was found. 49 class StmtToBlockMap { 50 public: 51 // Initializes the map for the given `CFG`. 52 StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext) 53 : Context(TheContext) { 54 for (const auto *B : *TheCFG) { 55 for (size_t I = 0; I < B->size(); ++I) { 56 if (auto S = (*B)[I].getAs<CFGStmt>()) { 57 Map[S->getStmt()] = std::make_pair(B, I); 58 } 59 } 60 } 61 } 62 63 // Returns the block that S is contained in. Some `Stmt`s may be contained 64 // in more than one `CFGBlock`; in this case, this function returns the 65 // innermost block (i.e. the one that is furthest from the root of the tree). 66 // 67 // The optional outparameter `Index` is set to the index into the block where 68 // the `Stmt` was found. 69 const CFGBlock *blockContainingStmt(const Stmt *S, 70 size_t *Index = nullptr) const { 71 while (!Map.count(S)) { 72 SmallVector<const Stmt *, 1> Parents = getParentStmts(S, Context); 73 if (Parents.empty()) 74 return nullptr; 75 S = Parents[0]; 76 } 77 78 const auto &E = Map.lookup(S); 79 if (Index) 80 *Index = E.second; 81 return E.first; 82 } 83 84 private: 85 ASTContext *Context; 86 87 llvm::DenseMap<const Stmt *, std::pair<const CFGBlock *, size_t>> Map; 88 }; 89 90 #endif // StmtToBlockMap_h__