1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Provides a way to construct an ASTConsumer that runs given matchers
// over the AST and invokes a given callback on every match.
//
// The general idea is to construct a matcher expression that describes a
// subtree match on the AST. Next, a callback that is executed every time the
// expression matches is registered, and the matcher is run over the AST of
// some code. Matched subexpressions can be bound to string IDs and easily
// be accessed from the registered callback. The callback can than use the
// AST nodes that the subexpressions matched on to output information about
// the match or construct changes that can be applied to the code.
//
// Example:
// class HandleMatch : public MatchFinder::MatchCallback {
// public:
// virtual void Run(const MatchFinder::MatchResult &Result) {
// const CXXRecordDecl *Class =
// Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
// ...
// }
// };
//
// int main(int argc, char **argv) {
// ClangTool Tool(argc, argv);
// MatchFinder finder;
// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
// new HandleMatch);
// return Tool.Run(newFrontendActionFactory(&finder));
// }
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
#include "clang/ASTMatchers/ASTMatchers.h"
namespace clang {
namespace ast_matchers {
/// \brief A class to allow finding matches over the Clang AST.
///
/// After creation, you can add multiple matchers to the MatchFinder via
/// calls to addMatcher(...).
///
/// Once all matchers are added, newASTConsumer() returns an ASTConsumer
/// that will trigger the callbacks specified via addMatcher(...) when a match
/// is found.
///
/// See ASTMatchers.h for more information about how to create matchers.
///
/// Not intended to be subclassed.
class MatchFinder {
public:
/// \brief Contains all information for a given match.
///
/// Every time a match is found, the MatchFinder will invoke the registered
/// MatchCallback with a MatchResult containing information about the match.
struct MatchResult {
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
/// \brief Contains the nodes bound on the current match.
///
/// This allows user code to easily extract matched AST nodes.
const BoundNodes Nodes;
/// \brief Utilities for interpreting the matched AST structures.
/// @{
clang::ASTContext * const Context;
clang::SourceManager * const SourceManager;
/// @}
};
/// \brief Called when the Match registered for it was successfully found
/// in the AST.
class MatchCallback {
public:
virtual ~MatchCallback();
/// \brief Called on every match by the \c MatchFinder.
virtual void run(const MatchResult &Result) = 0;
/// \brief Called at the start of each translation unit.
///
/// Optionally override to do per translation unit tasks.
virtual void onStartOfTranslationUnit() {}
};
/// \brief Called when parsing is finished. Intended for testing only.
class ParsingDoneTestCallback {
public:
virtual ~ParsingDoneTestCallback();
virtual void run() = 0;
};
MatchFinder();
~MatchFinder();
/// \brief Adds a matcher to execute when running over the AST.
///
/// Calls 'Action' with the BoundNodes on every match.
/// Adding more than one 'NodeMatch' allows finding different matches in a
/// single pass over the AST.
///
/// Does not take ownership of 'Action'.
/// @{
void addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const TypeMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action);
/// @}
/// \brief Creates a clang ASTConsumer that finds all matches.
clang::ASTConsumer *newASTConsumer();
/// \brief Finds all matches on the given \c Node.
///
/// @{
void findAll(const Decl &Node, ASTContext &Context);
void findAll(const Stmt &Node, ASTContext &Context);
/// @}
/// \brief Registers a callback to notify the end of parsing.
///
/// The provided closure is called after parsing is done, before the AST is
/// traversed. Useful for benchmarking.
/// Each call to FindAll(...) will call the closure once.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
private:
/// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
/// when it matches.
std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> >
MatcherCallbackPairs;
/// \brief Called when parsing is done.
ParsingDoneTestCallback *ParsingDone;
};
} // end namespace ast_matchers
} // end namespace clang
#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
|