Source code

Revision control

Other Tools

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
ASTContext::DynTypedNodeList Parents = Context->getParents(*S);
22
23
SmallVector<ast_type_traits::DynTypedNode, 1> NodesToProcess(Parents.begin(),
24
Parents.end());
25
26
while (!NodesToProcess.empty()) {
27
ast_type_traits::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 (Optional<CFGStmt> 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__