summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/StmtToBlockMap.h
diff options
context:
space:
mode:
Diffstat (limited to 'build/clang-plugin/StmtToBlockMap.h')
-rw-r--r--build/clang-plugin/StmtToBlockMap.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/build/clang-plugin/StmtToBlockMap.h b/build/clang-plugin/StmtToBlockMap.h
new file mode 100644
index 0000000000..f499cb91ec
--- /dev/null
+++ b/build/clang-plugin/StmtToBlockMap.h
@@ -0,0 +1,90 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef StmtToBlockMap_h__
+#define StmtToBlockMap_h__
+
+#include "Utils.h"
+
+// This method is copied from clang-tidy's ExprSequence.cpp.
+//
+// Returns the Stmt nodes that are parents of 'S', skipping any potential
+// intermediate non-Stmt nodes.
+//
+// In almost all cases, this function returns a single parent or no parents at
+// all.
+inline SmallVector<const Stmt *, 1> getParentStmts(const Stmt *S,
+ ASTContext *Context) {
+ SmallVector<const Stmt *, 1> Result;
+
+ auto Parents = Context->getParents(*S);
+
+ SmallVector<clang::DynTypedNode, 1> NodesToProcess(Parents.begin(),
+ Parents.end());
+
+ while (!NodesToProcess.empty()) {
+ clang::DynTypedNode Node = NodesToProcess.back();
+ NodesToProcess.pop_back();
+
+ if (const auto *S = Node.get<Stmt>()) {
+ Result.push_back(S);
+ } else {
+ Parents = Context->getParents(Node);
+ NodesToProcess.append(Parents.begin(), Parents.end());
+ }
+ }
+
+ return Result;
+}
+
+// This class is a modified version of the class from clang-tidy's
+// ExprSequence.cpp
+//
+// Maps `Stmt`s to the `CFGBlock` that contains them. Some `Stmt`s may be
+// contained in more than one `CFGBlock`; in this case, they are mapped to the
+// innermost block (i.e. the one that is furthest from the root of the tree).
+// An optional outparameter provides the index into the block where the `Stmt`
+// was found.
+class StmtToBlockMap {
+public:
+ // Initializes the map for the given `CFG`.
+ StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext)
+ : Context(TheContext) {
+ for (const auto *B : *TheCFG) {
+ for (size_t I = 0; I < B->size(); ++I) {
+ if (Optional<CFGStmt> S = (*B)[I].getAs<CFGStmt>()) {
+ Map[S->getStmt()] = std::make_pair(B, I);
+ }
+ }
+ }
+ }
+
+ // Returns the block that S is contained in. Some `Stmt`s may be contained
+ // in more than one `CFGBlock`; in this case, this function returns the
+ // innermost block (i.e. the one that is furthest from the root of the tree).
+ //
+ // The optional outparameter `Index` is set to the index into the block where
+ // the `Stmt` was found.
+ const CFGBlock *blockContainingStmt(const Stmt *S,
+ size_t *Index = nullptr) const {
+ while (!Map.count(S)) {
+ SmallVector<const Stmt *, 1> Parents = getParentStmts(S, Context);
+ if (Parents.empty())
+ return nullptr;
+ S = Parents[0];
+ }
+
+ const auto &E = Map.lookup(S);
+ if (Index)
+ *Index = E.second;
+ return E.first;
+ }
+
+private:
+ ASTContext *Context;
+
+ llvm::DenseMap<const Stmt *, std::pair<const CFGBlock *, size_t>> Map;
+};
+
+#endif // StmtToBlockMap_h__