File indexing completed on 2026-05-10 08:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
0023 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
0024
0025 #include "clang/AST/ASTContext.h"
0026 #include "clang/AST/Stmt.h"
0027 #include "clang/ASTMatchers/ASTMatchFinder.h"
0028 #include "clang/ASTMatchers/ASTMatchers.h"
0029 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
0030 #include "llvm/ADT/StringRef.h"
0031 #include <functional>
0032 #include <string>
0033 #include <type_traits>
0034 #include <utility>
0035 #include <vector>
0036
0037 namespace clang {
0038 namespace dataflow {
0039
0040
0041 template <typename LatticeT> struct TransferState {
0042 TransferState(LatticeT &Lattice, Environment &Env)
0043 : Lattice(Lattice), Env(Env) {}
0044
0045
0046 LatticeT &Lattice;
0047 Environment &Env;
0048 };
0049
0050
0051
0052
0053
0054
0055 template <typename LatticeT> struct TransferStateForDiagnostics {
0056 TransferStateForDiagnostics(const LatticeT &Lattice, const Environment &Env)
0057 : Lattice(Lattice), Env(Env) {}
0058
0059
0060 const LatticeT &Lattice;
0061 const Environment &Env;
0062 };
0063
0064 template <typename T>
0065 using MatchSwitchMatcher = ast_matchers::internal::Matcher<T>;
0066
0067 template <typename T, typename State, typename Result = void>
0068 using MatchSwitchAction = std::function<Result(
0069 const T *, const ast_matchers::MatchFinder::MatchResult &, State &)>;
0070
0071 template <typename BaseT, typename State, typename Result = void>
0072 using ASTMatchSwitch =
0073 std::function<Result(const BaseT &, ASTContext &, State &)>;
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 template <typename BaseT, typename State, typename Result = void>
0096 class ASTMatchSwitchBuilder {
0097 public:
0098
0099
0100
0101
0102
0103
0104 template <typename NodeT>
0105 ASTMatchSwitchBuilder &&CaseOf(MatchSwitchMatcher<BaseT> M,
0106 MatchSwitchAction<NodeT, State, Result> A) && {
0107 static_assert(std::is_base_of<BaseT, NodeT>::value,
0108 "NodeT must be derived from BaseT.");
0109 Matchers.push_back(std::move(M));
0110 Actions.push_back(
0111 [A = std::move(A)](const BaseT *Node,
0112 const ast_matchers::MatchFinder::MatchResult &R,
0113 State &S) { return A(cast<NodeT>(Node), R, S); });
0114 return std::move(*this);
0115 }
0116
0117 ASTMatchSwitch<BaseT, State, Result> Build() && {
0118 return [Matcher = BuildMatcher(), Actions = std::move(Actions)](
0119 const BaseT &Node, ASTContext &Context, State &S) -> Result {
0120 auto Results = ast_matchers::matchDynamic(Matcher, Node, Context);
0121 if (Results.empty()) {
0122 return Result();
0123 }
0124
0125
0126 for (const auto &Element : Results[0].getMap()) {
0127 llvm::StringRef ID(Element.first);
0128 size_t Index = 0;
0129 if (ID.consume_front("Tag") && !ID.getAsInteger(10, Index) &&
0130 Index < Actions.size()) {
0131 return Actions[Index](
0132 &Node,
0133 ast_matchers::MatchFinder::MatchResult(Results[0], &Context), S);
0134 }
0135 }
0136 return Result();
0137 };
0138 }
0139
0140 private:
0141 ast_matchers::internal::DynTypedMatcher BuildMatcher() {
0142 using ast_matchers::anything;
0143 using ast_matchers::stmt;
0144 using ast_matchers::unless;
0145 using ast_matchers::internal::DynTypedMatcher;
0146 if (Matchers.empty())
0147 return stmt(unless(anything()));
0148 for (int I = 0, N = Matchers.size(); I < N; ++I) {
0149 std::string Tag = ("Tag" + llvm::Twine(I)).str();
0150
0151 Matchers[I].setAllowBind(true);
0152 auto M = *Matchers[I].tryBind(Tag);
0153
0154
0155
0156
0157
0158 Matchers[I] =
0159 !M.getTraversalKind() ? M.withTraversalKind(TK_AsIs) : std::move(M);
0160 }
0161
0162
0163 return DynTypedMatcher::constructVariadic(
0164 DynTypedMatcher::VO_AnyOf, ASTNodeKind::getFromNodeKind<BaseT>(),
0165 std::move(Matchers));
0166 }
0167
0168 std::vector<ast_matchers::internal::DynTypedMatcher> Matchers;
0169 std::vector<MatchSwitchAction<BaseT, State, Result>> Actions;
0170 };
0171
0172 }
0173 }
0174 #endif