1f4a2713aSLionel Sambuc //===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file defines the RecursiveASTVisitor interface, which recursively
11f4a2713aSLionel Sambuc // traverses the entire AST.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
15f4a2713aSLionel Sambuc #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
16f4a2713aSLionel Sambuc
17*0a6a1f1dSLionel Sambuc #include "clang/AST/Attr.h"
18f4a2713aSLionel Sambuc #include "clang/AST/Decl.h"
19f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
20f4a2713aSLionel Sambuc #include "clang/AST/DeclFriend.h"
21f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h"
22f4a2713aSLionel Sambuc #include "clang/AST/DeclOpenMP.h"
23f4a2713aSLionel Sambuc #include "clang/AST/DeclTemplate.h"
24f4a2713aSLionel Sambuc #include "clang/AST/Expr.h"
25f4a2713aSLionel Sambuc #include "clang/AST/ExprCXX.h"
26f4a2713aSLionel Sambuc #include "clang/AST/ExprObjC.h"
27f4a2713aSLionel Sambuc #include "clang/AST/NestedNameSpecifier.h"
28f4a2713aSLionel Sambuc #include "clang/AST/Stmt.h"
29f4a2713aSLionel Sambuc #include "clang/AST/StmtCXX.h"
30f4a2713aSLionel Sambuc #include "clang/AST/StmtObjC.h"
31f4a2713aSLionel Sambuc #include "clang/AST/StmtOpenMP.h"
32f4a2713aSLionel Sambuc #include "clang/AST/TemplateBase.h"
33f4a2713aSLionel Sambuc #include "clang/AST/TemplateName.h"
34f4a2713aSLionel Sambuc #include "clang/AST/Type.h"
35f4a2713aSLionel Sambuc #include "clang/AST/TypeLoc.h"
36f4a2713aSLionel Sambuc
37f4a2713aSLionel Sambuc // The following three macros are used for meta programming. The code
38f4a2713aSLionel Sambuc // using them is responsible for defining macro OPERATOR().
39f4a2713aSLionel Sambuc
40f4a2713aSLionel Sambuc // All unary operators.
41f4a2713aSLionel Sambuc #define UNARYOP_LIST() \
42*0a6a1f1dSLionel Sambuc OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \
43*0a6a1f1dSLionel Sambuc OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \
44*0a6a1f1dSLionel Sambuc OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \
45f4a2713aSLionel Sambuc OPERATOR(Extension)
46f4a2713aSLionel Sambuc
47f4a2713aSLionel Sambuc // All binary operators (excluding compound assign operators).
48f4a2713aSLionel Sambuc #define BINOP_LIST() \
49*0a6a1f1dSLionel Sambuc OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \
50*0a6a1f1dSLionel Sambuc OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \
51*0a6a1f1dSLionel Sambuc OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \
52*0a6a1f1dSLionel Sambuc OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \
53*0a6a1f1dSLionel Sambuc OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma)
54f4a2713aSLionel Sambuc
55f4a2713aSLionel Sambuc // All compound assign operators.
56f4a2713aSLionel Sambuc #define CAO_LIST() \
57f4a2713aSLionel Sambuc OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \
58f4a2713aSLionel Sambuc OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
59f4a2713aSLionel Sambuc
60f4a2713aSLionel Sambuc namespace clang {
61f4a2713aSLionel Sambuc
62f4a2713aSLionel Sambuc // A helper macro to implement short-circuiting when recursing. It
63f4a2713aSLionel Sambuc // invokes CALL_EXPR, which must be a method call, on the derived
64f4a2713aSLionel Sambuc // object (s.t. a user of RecursiveASTVisitor can override the method
65f4a2713aSLionel Sambuc // in CALL_EXPR).
66f4a2713aSLionel Sambuc #define TRY_TO(CALL_EXPR) \
67*0a6a1f1dSLionel Sambuc do { \
68*0a6a1f1dSLionel Sambuc if (!getDerived().CALL_EXPR) \
69*0a6a1f1dSLionel Sambuc return false; \
70*0a6a1f1dSLionel Sambuc } while (0)
71f4a2713aSLionel Sambuc
72f4a2713aSLionel Sambuc /// \brief A class that does preorder depth-first traversal on the
73f4a2713aSLionel Sambuc /// entire Clang AST and visits each node.
74f4a2713aSLionel Sambuc ///
75f4a2713aSLionel Sambuc /// This class performs three distinct tasks:
76f4a2713aSLionel Sambuc /// 1. traverse the AST (i.e. go to each node);
77f4a2713aSLionel Sambuc /// 2. at a given node, walk up the class hierarchy, starting from
78f4a2713aSLionel Sambuc /// the node's dynamic type, until the top-most class (e.g. Stmt,
79f4a2713aSLionel Sambuc /// Decl, or Type) is reached.
80f4a2713aSLionel Sambuc /// 3. given a (node, class) combination, where 'class' is some base
81f4a2713aSLionel Sambuc /// class of the dynamic type of 'node', call a user-overridable
82f4a2713aSLionel Sambuc /// function to actually visit the node.
83f4a2713aSLionel Sambuc ///
84f4a2713aSLionel Sambuc /// These tasks are done by three groups of methods, respectively:
85f4a2713aSLionel Sambuc /// 1. TraverseDecl(Decl *x) does task #1. It is the entry point
86f4a2713aSLionel Sambuc /// for traversing an AST rooted at x. This method simply
87f4a2713aSLionel Sambuc /// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo
88f4a2713aSLionel Sambuc /// is the dynamic type of *x, which calls WalkUpFromFoo(x) and
89f4a2713aSLionel Sambuc /// then recursively visits the child nodes of x.
90f4a2713aSLionel Sambuc /// TraverseStmt(Stmt *x) and TraverseType(QualType x) work
91f4a2713aSLionel Sambuc /// similarly.
92f4a2713aSLionel Sambuc /// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit
93f4a2713aSLionel Sambuc /// any child node of x. Instead, it first calls WalkUpFromBar(x)
94f4a2713aSLionel Sambuc /// where Bar is the direct parent class of Foo (unless Foo has
95f4a2713aSLionel Sambuc /// no parent), and then calls VisitFoo(x) (see the next list item).
96f4a2713aSLionel Sambuc /// 3. VisitFoo(Foo *x) does task #3.
97f4a2713aSLionel Sambuc ///
98f4a2713aSLionel Sambuc /// These three method groups are tiered (Traverse* > WalkUpFrom* >
99f4a2713aSLionel Sambuc /// Visit*). A method (e.g. Traverse*) may call methods from the same
100f4a2713aSLionel Sambuc /// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*).
101f4a2713aSLionel Sambuc /// It may not call methods from a higher tier.
102f4a2713aSLionel Sambuc ///
103f4a2713aSLionel Sambuc /// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar
104f4a2713aSLionel Sambuc /// is Foo's super class) before calling VisitFoo(), the result is
105f4a2713aSLionel Sambuc /// that the Visit*() methods for a given node are called in the
106f4a2713aSLionel Sambuc /// top-down order (e.g. for a node of type NamespaceDecl, the order will
107f4a2713aSLionel Sambuc /// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()).
108f4a2713aSLionel Sambuc ///
109f4a2713aSLionel Sambuc /// This scheme guarantees that all Visit*() calls for the same AST
110f4a2713aSLionel Sambuc /// node are grouped together. In other words, Visit*() methods for
111f4a2713aSLionel Sambuc /// different nodes are never interleaved.
112f4a2713aSLionel Sambuc ///
113f4a2713aSLionel Sambuc /// Clients of this visitor should subclass the visitor (providing
114f4a2713aSLionel Sambuc /// themselves as the template argument, using the curiously recurring
115f4a2713aSLionel Sambuc /// template pattern) and override any of the Traverse*, WalkUpFrom*,
116f4a2713aSLionel Sambuc /// and Visit* methods for declarations, types, statements,
117f4a2713aSLionel Sambuc /// expressions, or other AST nodes where the visitor should customize
118f4a2713aSLionel Sambuc /// behavior. Most users only need to override Visit*. Advanced
119f4a2713aSLionel Sambuc /// users may override Traverse* and WalkUpFrom* to implement custom
120f4a2713aSLionel Sambuc /// traversal strategies. Returning false from one of these overridden
121f4a2713aSLionel Sambuc /// functions will abort the entire traversal.
122f4a2713aSLionel Sambuc ///
123f4a2713aSLionel Sambuc /// By default, this visitor tries to visit every part of the explicit
124f4a2713aSLionel Sambuc /// source code exactly once. The default policy towards templates
125f4a2713aSLionel Sambuc /// is to descend into the 'pattern' class or function body, not any
126f4a2713aSLionel Sambuc /// explicit or implicit instantiations. Explicit specializations
127f4a2713aSLionel Sambuc /// are still visited, and the patterns of partial specializations
128f4a2713aSLionel Sambuc /// are visited separately. This behavior can be changed by
129f4a2713aSLionel Sambuc /// overriding shouldVisitTemplateInstantiations() in the derived class
130f4a2713aSLionel Sambuc /// to return true, in which case all known implicit and explicit
131f4a2713aSLionel Sambuc /// instantiations will be visited at the same time as the pattern
132f4a2713aSLionel Sambuc /// from which they were produced.
133*0a6a1f1dSLionel Sambuc template <typename Derived> class RecursiveASTVisitor {
134f4a2713aSLionel Sambuc public:
135f4a2713aSLionel Sambuc /// \brief Return a reference to the derived class.
getDerived()136f4a2713aSLionel Sambuc Derived &getDerived() { return *static_cast<Derived *>(this); }
137f4a2713aSLionel Sambuc
138f4a2713aSLionel Sambuc /// \brief Return whether this visitor should recurse into
139f4a2713aSLionel Sambuc /// template instantiations.
shouldVisitTemplateInstantiations()140f4a2713aSLionel Sambuc bool shouldVisitTemplateInstantiations() const { return false; }
141f4a2713aSLionel Sambuc
142f4a2713aSLionel Sambuc /// \brief Return whether this visitor should recurse into the types of
143f4a2713aSLionel Sambuc /// TypeLocs.
shouldWalkTypesOfTypeLocs()144f4a2713aSLionel Sambuc bool shouldWalkTypesOfTypeLocs() const { return true; }
145f4a2713aSLionel Sambuc
146f4a2713aSLionel Sambuc /// \brief Return whether this visitor should recurse into implicit
147f4a2713aSLionel Sambuc /// code, e.g., implicit constructors and destructors.
shouldVisitImplicitCode()148f4a2713aSLionel Sambuc bool shouldVisitImplicitCode() const { return false; }
149f4a2713aSLionel Sambuc
150f4a2713aSLionel Sambuc /// \brief Return whether \param S should be traversed using data recursion
151f4a2713aSLionel Sambuc /// to avoid a stack overflow with extreme cases.
shouldUseDataRecursionFor(Stmt * S)152f4a2713aSLionel Sambuc bool shouldUseDataRecursionFor(Stmt *S) const {
153f4a2713aSLionel Sambuc return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) ||
154f4a2713aSLionel Sambuc isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S);
155f4a2713aSLionel Sambuc }
156f4a2713aSLionel Sambuc
157f4a2713aSLionel Sambuc /// \brief Recursively visit a statement or expression, by
158f4a2713aSLionel Sambuc /// dispatching to Traverse*() based on the argument's dynamic type.
159f4a2713aSLionel Sambuc ///
160f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true
161f4a2713aSLionel Sambuc /// otherwise (including when the argument is NULL).
162f4a2713aSLionel Sambuc bool TraverseStmt(Stmt *S);
163f4a2713aSLionel Sambuc
164f4a2713aSLionel Sambuc /// \brief Recursively visit a type, by dispatching to
165f4a2713aSLionel Sambuc /// Traverse*Type() based on the argument's getTypeClass() property.
166f4a2713aSLionel Sambuc ///
167f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true
168f4a2713aSLionel Sambuc /// otherwise (including when the argument is a Null type).
169f4a2713aSLionel Sambuc bool TraverseType(QualType T);
170f4a2713aSLionel Sambuc
171f4a2713aSLionel Sambuc /// \brief Recursively visit a type with location, by dispatching to
172f4a2713aSLionel Sambuc /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
173f4a2713aSLionel Sambuc ///
174f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true
175f4a2713aSLionel Sambuc /// otherwise (including when the argument is a Null type location).
176f4a2713aSLionel Sambuc bool TraverseTypeLoc(TypeLoc TL);
177f4a2713aSLionel Sambuc
178*0a6a1f1dSLionel Sambuc /// \brief Recursively visit an attribute, by dispatching to
179*0a6a1f1dSLionel Sambuc /// Traverse*Attr() based on the argument's dynamic type.
180*0a6a1f1dSLionel Sambuc ///
181*0a6a1f1dSLionel Sambuc /// \returns false if the visitation was terminated early, true
182*0a6a1f1dSLionel Sambuc /// otherwise (including when the argument is a Null type location).
183*0a6a1f1dSLionel Sambuc bool TraverseAttr(Attr *At);
184*0a6a1f1dSLionel Sambuc
185f4a2713aSLionel Sambuc /// \brief Recursively visit a declaration, by dispatching to
186f4a2713aSLionel Sambuc /// Traverse*Decl() based on the argument's dynamic type.
187f4a2713aSLionel Sambuc ///
188f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true
189f4a2713aSLionel Sambuc /// otherwise (including when the argument is NULL).
190f4a2713aSLionel Sambuc bool TraverseDecl(Decl *D);
191f4a2713aSLionel Sambuc
192f4a2713aSLionel Sambuc /// \brief Recursively visit a C++ nested-name-specifier.
193f4a2713aSLionel Sambuc ///
194f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
195f4a2713aSLionel Sambuc bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
196f4a2713aSLionel Sambuc
197f4a2713aSLionel Sambuc /// \brief Recursively visit a C++ nested-name-specifier with location
198f4a2713aSLionel Sambuc /// information.
199f4a2713aSLionel Sambuc ///
200f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
201f4a2713aSLionel Sambuc bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
202f4a2713aSLionel Sambuc
203f4a2713aSLionel Sambuc /// \brief Recursively visit a name with its location information.
204f4a2713aSLionel Sambuc ///
205f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
206f4a2713aSLionel Sambuc bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
207f4a2713aSLionel Sambuc
208f4a2713aSLionel Sambuc /// \brief Recursively visit a template name and dispatch to the
209f4a2713aSLionel Sambuc /// appropriate method.
210f4a2713aSLionel Sambuc ///
211f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
212f4a2713aSLionel Sambuc bool TraverseTemplateName(TemplateName Template);
213f4a2713aSLionel Sambuc
214f4a2713aSLionel Sambuc /// \brief Recursively visit a template argument and dispatch to the
215f4a2713aSLionel Sambuc /// appropriate method for the argument type.
216f4a2713aSLionel Sambuc ///
217f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
218f4a2713aSLionel Sambuc // FIXME: migrate callers to TemplateArgumentLoc instead.
219f4a2713aSLionel Sambuc bool TraverseTemplateArgument(const TemplateArgument &Arg);
220f4a2713aSLionel Sambuc
221f4a2713aSLionel Sambuc /// \brief Recursively visit a template argument location and dispatch to the
222f4a2713aSLionel Sambuc /// appropriate method for the argument type.
223f4a2713aSLionel Sambuc ///
224f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
225f4a2713aSLionel Sambuc bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
226f4a2713aSLionel Sambuc
227f4a2713aSLionel Sambuc /// \brief Recursively visit a set of template arguments.
228f4a2713aSLionel Sambuc /// This can be overridden by a subclass, but it's not expected that
229f4a2713aSLionel Sambuc /// will be needed -- this visitor always dispatches to another.
230f4a2713aSLionel Sambuc ///
231f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
232f4a2713aSLionel Sambuc // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
233f4a2713aSLionel Sambuc bool TraverseTemplateArguments(const TemplateArgument *Args,
234f4a2713aSLionel Sambuc unsigned NumArgs);
235f4a2713aSLionel Sambuc
236f4a2713aSLionel Sambuc /// \brief Recursively visit a constructor initializer. This
237f4a2713aSLionel Sambuc /// automatically dispatches to another visitor for the initializer
238f4a2713aSLionel Sambuc /// expression, but not for the name of the initializer, so may
239f4a2713aSLionel Sambuc /// be overridden for clients that need access to the name.
240f4a2713aSLionel Sambuc ///
241f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
242f4a2713aSLionel Sambuc bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
243f4a2713aSLionel Sambuc
244f4a2713aSLionel Sambuc /// \brief Recursively visit a lambda capture.
245f4a2713aSLionel Sambuc ///
246f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
247*0a6a1f1dSLionel Sambuc bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C);
248f4a2713aSLionel Sambuc
249f4a2713aSLionel Sambuc /// \brief Recursively visit the body of a lambda expression.
250f4a2713aSLionel Sambuc ///
251f4a2713aSLionel Sambuc /// This provides a hook for visitors that need more context when visiting
252f4a2713aSLionel Sambuc /// \c LE->getBody().
253f4a2713aSLionel Sambuc ///
254f4a2713aSLionel Sambuc /// \returns false if the visitation was terminated early, true otherwise.
255f4a2713aSLionel Sambuc bool TraverseLambdaBody(LambdaExpr *LE);
256f4a2713aSLionel Sambuc
257*0a6a1f1dSLionel Sambuc // ---- Methods on Attrs ----
258*0a6a1f1dSLionel Sambuc
259*0a6a1f1dSLionel Sambuc // \brief Visit an attribute.
VisitAttr(Attr * A)260*0a6a1f1dSLionel Sambuc bool VisitAttr(Attr *A) { return true; }
261*0a6a1f1dSLionel Sambuc
262*0a6a1f1dSLionel Sambuc // Declare Traverse* and empty Visit* for all Attr classes.
263*0a6a1f1dSLionel Sambuc #define ATTR_VISITOR_DECLS_ONLY
264*0a6a1f1dSLionel Sambuc #include "clang/AST/AttrVisitor.inc"
265*0a6a1f1dSLionel Sambuc #undef ATTR_VISITOR_DECLS_ONLY
266*0a6a1f1dSLionel Sambuc
267f4a2713aSLionel Sambuc // ---- Methods on Stmts ----
268f4a2713aSLionel Sambuc
269f4a2713aSLionel Sambuc // Declare Traverse*() for all concrete Stmt classes.
270f4a2713aSLionel Sambuc #define ABSTRACT_STMT(STMT)
271*0a6a1f1dSLionel Sambuc #define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
272f4a2713aSLionel Sambuc #include "clang/AST/StmtNodes.inc"
273f4a2713aSLionel Sambuc // The above header #undefs ABSTRACT_STMT and STMT upon exit.
274f4a2713aSLionel Sambuc
275f4a2713aSLionel Sambuc // Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
WalkUpFromStmt(Stmt * S)276f4a2713aSLionel Sambuc bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
VisitStmt(Stmt * S)277f4a2713aSLionel Sambuc bool VisitStmt(Stmt *S) { return true; }
278f4a2713aSLionel Sambuc #define STMT(CLASS, PARENT) \
279f4a2713aSLionel Sambuc bool WalkUpFrom##CLASS(CLASS *S) { \
280f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##PARENT(S)); \
281f4a2713aSLionel Sambuc TRY_TO(Visit##CLASS(S)); \
282f4a2713aSLionel Sambuc return true; \
283f4a2713aSLionel Sambuc } \
284f4a2713aSLionel Sambuc bool Visit##CLASS(CLASS *S) { return true; }
285f4a2713aSLionel Sambuc #include "clang/AST/StmtNodes.inc"
286f4a2713aSLionel Sambuc
287f4a2713aSLionel Sambuc // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
288f4a2713aSLionel Sambuc // operator methods. Unary operators are not classes in themselves
289f4a2713aSLionel Sambuc // (they're all opcodes in UnaryOperator) but do have visitors.
290f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
291f4a2713aSLionel Sambuc bool TraverseUnary##NAME(UnaryOperator *S) { \
292f4a2713aSLionel Sambuc TRY_TO(WalkUpFromUnary##NAME(S)); \
293f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getSubExpr())); \
294f4a2713aSLionel Sambuc return true; \
295f4a2713aSLionel Sambuc } \
296f4a2713aSLionel Sambuc bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
297f4a2713aSLionel Sambuc TRY_TO(WalkUpFromUnaryOperator(S)); \
298f4a2713aSLionel Sambuc TRY_TO(VisitUnary##NAME(S)); \
299f4a2713aSLionel Sambuc return true; \
300f4a2713aSLionel Sambuc } \
301f4a2713aSLionel Sambuc bool VisitUnary##NAME(UnaryOperator *S) { return true; }
302f4a2713aSLionel Sambuc
303f4a2713aSLionel Sambuc UNARYOP_LIST()
304f4a2713aSLionel Sambuc #undef OPERATOR
305f4a2713aSLionel Sambuc
306f4a2713aSLionel Sambuc // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
307f4a2713aSLionel Sambuc // operator methods. Binary operators are not classes in themselves
308f4a2713aSLionel Sambuc // (they're all opcodes in BinaryOperator) but do have visitors.
309f4a2713aSLionel Sambuc #define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
310f4a2713aSLionel Sambuc bool TraverseBin##NAME(BINOP_TYPE *S) { \
311f4a2713aSLionel Sambuc TRY_TO(WalkUpFromBin##NAME(S)); \
312f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getLHS())); \
313f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getRHS())); \
314f4a2713aSLionel Sambuc return true; \
315f4a2713aSLionel Sambuc } \
316f4a2713aSLionel Sambuc bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
317f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
318f4a2713aSLionel Sambuc TRY_TO(VisitBin##NAME(S)); \
319f4a2713aSLionel Sambuc return true; \
320f4a2713aSLionel Sambuc } \
321f4a2713aSLionel Sambuc bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
322f4a2713aSLionel Sambuc
323f4a2713aSLionel Sambuc #define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
BINOP_LIST()324f4a2713aSLionel Sambuc BINOP_LIST()
325f4a2713aSLionel Sambuc #undef OPERATOR
326f4a2713aSLionel Sambuc
327f4a2713aSLionel Sambuc // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound
328f4a2713aSLionel Sambuc // assignment methods. Compound assignment operators are not
329f4a2713aSLionel Sambuc // classes in themselves (they're all opcodes in
330f4a2713aSLionel Sambuc // CompoundAssignOperator) but do have visitors.
331f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
332f4a2713aSLionel Sambuc GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator)
333f4a2713aSLionel Sambuc
334f4a2713aSLionel Sambuc CAO_LIST()
335f4a2713aSLionel Sambuc #undef OPERATOR
336f4a2713aSLionel Sambuc #undef GENERAL_BINOP_FALLBACK
337f4a2713aSLionel Sambuc
338f4a2713aSLionel Sambuc // ---- Methods on Types ----
339f4a2713aSLionel Sambuc // FIXME: revamp to take TypeLoc's rather than Types.
340f4a2713aSLionel Sambuc
341f4a2713aSLionel Sambuc // Declare Traverse*() for all concrete Type classes.
342f4a2713aSLionel Sambuc #define ABSTRACT_TYPE(CLASS, BASE)
343*0a6a1f1dSLionel Sambuc #define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T);
344f4a2713aSLionel Sambuc #include "clang/AST/TypeNodes.def"
345f4a2713aSLionel Sambuc // The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
346f4a2713aSLionel Sambuc
347f4a2713aSLionel Sambuc // Define WalkUpFrom*() and empty Visit*() for all Type classes.
348f4a2713aSLionel Sambuc bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); }
VisitType(Type * T)349f4a2713aSLionel Sambuc bool VisitType(Type *T) { return true; }
350f4a2713aSLionel Sambuc #define TYPE(CLASS, BASE) \
351f4a2713aSLionel Sambuc bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \
352f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##BASE(T)); \
353f4a2713aSLionel Sambuc TRY_TO(Visit##CLASS##Type(T)); \
354f4a2713aSLionel Sambuc return true; \
355f4a2713aSLionel Sambuc } \
356f4a2713aSLionel Sambuc bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
357f4a2713aSLionel Sambuc #include "clang/AST/TypeNodes.def"
358f4a2713aSLionel Sambuc
359f4a2713aSLionel Sambuc // ---- Methods on TypeLocs ----
360f4a2713aSLionel Sambuc // FIXME: this currently just calls the matching Type methods
361f4a2713aSLionel Sambuc
362f4a2713aSLionel Sambuc // Declare Traverse*() for all concrete TypeLoc classes.
363f4a2713aSLionel Sambuc #define ABSTRACT_TYPELOC(CLASS, BASE)
364*0a6a1f1dSLionel Sambuc #define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
365f4a2713aSLionel Sambuc #include "clang/AST/TypeLocNodes.def"
366f4a2713aSLionel Sambuc // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit.
367f4a2713aSLionel Sambuc
368f4a2713aSLionel Sambuc // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes.
WalkUpFromTypeLoc(TypeLoc TL)369f4a2713aSLionel Sambuc bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); }
VisitTypeLoc(TypeLoc TL)370f4a2713aSLionel Sambuc bool VisitTypeLoc(TypeLoc TL) { return true; }
371f4a2713aSLionel Sambuc
372f4a2713aSLionel Sambuc // QualifiedTypeLoc and UnqualTypeLoc are not declared in
373f4a2713aSLionel Sambuc // TypeNodes.def and thus need to be handled specially.
WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL)374f4a2713aSLionel Sambuc bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
375f4a2713aSLionel Sambuc return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
376f4a2713aSLionel Sambuc }
VisitQualifiedTypeLoc(QualifiedTypeLoc TL)377f4a2713aSLionel Sambuc bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; }
WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL)378f4a2713aSLionel Sambuc bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) {
379f4a2713aSLionel Sambuc return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
380f4a2713aSLionel Sambuc }
VisitUnqualTypeLoc(UnqualTypeLoc TL)381f4a2713aSLionel Sambuc bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; }
382f4a2713aSLionel Sambuc
383f4a2713aSLionel Sambuc // Note that BASE includes trailing 'Type' which CLASS doesn't.
384f4a2713aSLionel Sambuc #define TYPE(CLASS, BASE) \
385f4a2713aSLionel Sambuc bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
386f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##BASE##Loc(TL)); \
387f4a2713aSLionel Sambuc TRY_TO(Visit##CLASS##TypeLoc(TL)); \
388f4a2713aSLionel Sambuc return true; \
389f4a2713aSLionel Sambuc } \
390f4a2713aSLionel Sambuc bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
391f4a2713aSLionel Sambuc #include "clang/AST/TypeNodes.def"
392f4a2713aSLionel Sambuc
393f4a2713aSLionel Sambuc // ---- Methods on Decls ----
394f4a2713aSLionel Sambuc
395f4a2713aSLionel Sambuc // Declare Traverse*() for all concrete Decl classes.
396f4a2713aSLionel Sambuc #define ABSTRACT_DECL(DECL)
397*0a6a1f1dSLionel Sambuc #define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D);
398f4a2713aSLionel Sambuc #include "clang/AST/DeclNodes.inc"
399f4a2713aSLionel Sambuc // The above header #undefs ABSTRACT_DECL and DECL upon exit.
400f4a2713aSLionel Sambuc
401f4a2713aSLionel Sambuc // Define WalkUpFrom*() and empty Visit*() for all Decl classes.
WalkUpFromDecl(Decl * D)402f4a2713aSLionel Sambuc bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); }
VisitDecl(Decl * D)403f4a2713aSLionel Sambuc bool VisitDecl(Decl *D) { return true; }
404f4a2713aSLionel Sambuc #define DECL(CLASS, BASE) \
405f4a2713aSLionel Sambuc bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \
406f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##BASE(D)); \
407f4a2713aSLionel Sambuc TRY_TO(Visit##CLASS##Decl(D)); \
408f4a2713aSLionel Sambuc return true; \
409f4a2713aSLionel Sambuc } \
410f4a2713aSLionel Sambuc bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
411f4a2713aSLionel Sambuc #include "clang/AST/DeclNodes.inc"
412f4a2713aSLionel Sambuc
413f4a2713aSLionel Sambuc private:
414f4a2713aSLionel Sambuc // These are helper methods used by more than one Traverse* method.
415f4a2713aSLionel Sambuc bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
416f4a2713aSLionel Sambuc #define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \
417f4a2713aSLionel Sambuc bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
418f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_INST(Class)
419f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_INST(Var)
420f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_INST(Function)
421f4a2713aSLionel Sambuc #undef DEF_TRAVERSE_TMPL_INST
422f4a2713aSLionel Sambuc bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
423f4a2713aSLionel Sambuc unsigned Count);
424f4a2713aSLionel Sambuc bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
425f4a2713aSLionel Sambuc bool TraverseRecordHelper(RecordDecl *D);
426f4a2713aSLionel Sambuc bool TraverseCXXRecordHelper(CXXRecordDecl *D);
427f4a2713aSLionel Sambuc bool TraverseDeclaratorHelper(DeclaratorDecl *D);
428f4a2713aSLionel Sambuc bool TraverseDeclContextHelper(DeclContext *DC);
429f4a2713aSLionel Sambuc bool TraverseFunctionHelper(FunctionDecl *D);
430f4a2713aSLionel Sambuc bool TraverseVarHelper(VarDecl *D);
431*0a6a1f1dSLionel Sambuc bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
432*0a6a1f1dSLionel Sambuc bool TraverseOMPLoopDirective(OMPLoopDirective *S);
433f4a2713aSLionel Sambuc bool TraverseOMPClause(OMPClause *C);
434*0a6a1f1dSLionel Sambuc #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
435f4a2713aSLionel Sambuc #include "clang/Basic/OpenMPKinds.def"
436f4a2713aSLionel Sambuc /// \brief Process clauses with list of variables.
437*0a6a1f1dSLionel Sambuc template <typename T> bool VisitOMPClauseList(T *Node);
438f4a2713aSLionel Sambuc
439f4a2713aSLionel Sambuc struct EnqueueJob {
440f4a2713aSLionel Sambuc Stmt *S;
441f4a2713aSLionel Sambuc Stmt::child_iterator StmtIt;
442f4a2713aSLionel Sambuc
EnqueueJobEnqueueJob443f4a2713aSLionel Sambuc EnqueueJob(Stmt *S) : S(S), StmtIt() {}
444f4a2713aSLionel Sambuc };
445f4a2713aSLionel Sambuc bool dataTraverse(Stmt *S);
446f4a2713aSLionel Sambuc bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
447f4a2713aSLionel Sambuc };
448f4a2713aSLionel Sambuc
449f4a2713aSLionel Sambuc template <typename Derived>
dataTraverse(Stmt * S)450f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
451f4a2713aSLionel Sambuc
452f4a2713aSLionel Sambuc SmallVector<EnqueueJob, 16> Queue;
453f4a2713aSLionel Sambuc Queue.push_back(S);
454f4a2713aSLionel Sambuc
455f4a2713aSLionel Sambuc while (!Queue.empty()) {
456f4a2713aSLionel Sambuc EnqueueJob &job = Queue.back();
457f4a2713aSLionel Sambuc Stmt *CurrS = job.S;
458f4a2713aSLionel Sambuc if (!CurrS) {
459f4a2713aSLionel Sambuc Queue.pop_back();
460f4a2713aSLionel Sambuc continue;
461f4a2713aSLionel Sambuc }
462f4a2713aSLionel Sambuc
463f4a2713aSLionel Sambuc if (getDerived().shouldUseDataRecursionFor(CurrS)) {
464f4a2713aSLionel Sambuc if (job.StmtIt == Stmt::child_iterator()) {
465f4a2713aSLionel Sambuc bool EnqueueChildren = true;
466*0a6a1f1dSLionel Sambuc if (!dataTraverseNode(CurrS, EnqueueChildren))
467*0a6a1f1dSLionel Sambuc return false;
468f4a2713aSLionel Sambuc if (!EnqueueChildren) {
469f4a2713aSLionel Sambuc Queue.pop_back();
470f4a2713aSLionel Sambuc continue;
471f4a2713aSLionel Sambuc }
472f4a2713aSLionel Sambuc job.StmtIt = CurrS->child_begin();
473f4a2713aSLionel Sambuc } else {
474f4a2713aSLionel Sambuc ++job.StmtIt;
475f4a2713aSLionel Sambuc }
476f4a2713aSLionel Sambuc
477f4a2713aSLionel Sambuc if (job.StmtIt != CurrS->child_end())
478f4a2713aSLionel Sambuc Queue.push_back(*job.StmtIt);
479f4a2713aSLionel Sambuc else
480f4a2713aSLionel Sambuc Queue.pop_back();
481f4a2713aSLionel Sambuc continue;
482f4a2713aSLionel Sambuc }
483f4a2713aSLionel Sambuc
484f4a2713aSLionel Sambuc Queue.pop_back();
485f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(CurrS));
486f4a2713aSLionel Sambuc }
487f4a2713aSLionel Sambuc
488f4a2713aSLionel Sambuc return true;
489f4a2713aSLionel Sambuc }
490f4a2713aSLionel Sambuc
491f4a2713aSLionel Sambuc template <typename Derived>
dataTraverseNode(Stmt * S,bool & EnqueueChildren)492f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
493f4a2713aSLionel Sambuc bool &EnqueueChildren) {
494f4a2713aSLionel Sambuc
495f4a2713aSLionel Sambuc // Dispatch to the corresponding WalkUpFrom* function only if the derived
496f4a2713aSLionel Sambuc // class didn't override Traverse* (and thus the traversal is trivial).
497f4a2713aSLionel Sambuc #define DISPATCH_WALK(NAME, CLASS, VAR) \
498f4a2713aSLionel Sambuc { \
499f4a2713aSLionel Sambuc bool (Derived::*DerivedFn)(CLASS *) = &Derived::Traverse##NAME; \
500f4a2713aSLionel Sambuc bool (Derived::*BaseFn)(CLASS *) = &RecursiveASTVisitor::Traverse##NAME; \
501f4a2713aSLionel Sambuc if (DerivedFn == BaseFn) \
502f4a2713aSLionel Sambuc return getDerived().WalkUpFrom##NAME(static_cast<CLASS *>(VAR)); \
503f4a2713aSLionel Sambuc } \
504f4a2713aSLionel Sambuc EnqueueChildren = false; \
505f4a2713aSLionel Sambuc return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR));
506f4a2713aSLionel Sambuc
507f4a2713aSLionel Sambuc if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
508f4a2713aSLionel Sambuc switch (BinOp->getOpcode()) {
509f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
510*0a6a1f1dSLionel Sambuc case BO_##NAME: \
511*0a6a1f1dSLionel Sambuc DISPATCH_WALK(Bin##NAME, BinaryOperator, S);
512f4a2713aSLionel Sambuc
513f4a2713aSLionel Sambuc BINOP_LIST()
514f4a2713aSLionel Sambuc #undef OPERATOR
515f4a2713aSLionel Sambuc
516f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
517f4a2713aSLionel Sambuc case BO_##NAME##Assign: \
518f4a2713aSLionel Sambuc DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S);
519f4a2713aSLionel Sambuc
520f4a2713aSLionel Sambuc CAO_LIST()
521f4a2713aSLionel Sambuc #undef OPERATOR
522f4a2713aSLionel Sambuc }
523f4a2713aSLionel Sambuc } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
524f4a2713aSLionel Sambuc switch (UnOp->getOpcode()) {
525f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
526*0a6a1f1dSLionel Sambuc case UO_##NAME: \
527*0a6a1f1dSLionel Sambuc DISPATCH_WALK(Unary##NAME, UnaryOperator, S);
528f4a2713aSLionel Sambuc
529f4a2713aSLionel Sambuc UNARYOP_LIST()
530f4a2713aSLionel Sambuc #undef OPERATOR
531f4a2713aSLionel Sambuc }
532f4a2713aSLionel Sambuc }
533f4a2713aSLionel Sambuc
534f4a2713aSLionel Sambuc // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
535f4a2713aSLionel Sambuc switch (S->getStmtClass()) {
536*0a6a1f1dSLionel Sambuc case Stmt::NoStmtClass:
537*0a6a1f1dSLionel Sambuc break;
538f4a2713aSLionel Sambuc #define ABSTRACT_STMT(STMT)
539f4a2713aSLionel Sambuc #define STMT(CLASS, PARENT) \
540*0a6a1f1dSLionel Sambuc case Stmt::CLASS##Class: \
541*0a6a1f1dSLionel Sambuc DISPATCH_WALK(CLASS, CLASS, S);
542f4a2713aSLionel Sambuc #include "clang/AST/StmtNodes.inc"
543f4a2713aSLionel Sambuc }
544f4a2713aSLionel Sambuc
545f4a2713aSLionel Sambuc #undef DISPATCH_WALK
546f4a2713aSLionel Sambuc
547f4a2713aSLionel Sambuc return true;
548f4a2713aSLionel Sambuc }
549f4a2713aSLionel Sambuc
550f4a2713aSLionel Sambuc #define DISPATCH(NAME, CLASS, VAR) \
551f4a2713aSLionel Sambuc return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
552f4a2713aSLionel Sambuc
553f4a2713aSLionel Sambuc template <typename Derived>
TraverseStmt(Stmt * S)554f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
555f4a2713aSLionel Sambuc if (!S)
556f4a2713aSLionel Sambuc return true;
557f4a2713aSLionel Sambuc
558*0a6a1f1dSLionel Sambuc #define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR)
559*0a6a1f1dSLionel Sambuc
560f4a2713aSLionel Sambuc if (getDerived().shouldUseDataRecursionFor(S))
561f4a2713aSLionel Sambuc return dataTraverse(S);
562f4a2713aSLionel Sambuc
563f4a2713aSLionel Sambuc // If we have a binary expr, dispatch to the subcode of the binop. A smart
564f4a2713aSLionel Sambuc // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
565f4a2713aSLionel Sambuc // below.
566f4a2713aSLionel Sambuc if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
567f4a2713aSLionel Sambuc switch (BinOp->getOpcode()) {
568f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
569*0a6a1f1dSLionel Sambuc case BO_##NAME: \
570*0a6a1f1dSLionel Sambuc DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
571f4a2713aSLionel Sambuc
572f4a2713aSLionel Sambuc BINOP_LIST()
573f4a2713aSLionel Sambuc #undef OPERATOR
574f4a2713aSLionel Sambuc #undef BINOP_LIST
575f4a2713aSLionel Sambuc
576f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
577f4a2713aSLionel Sambuc case BO_##NAME##Assign: \
578*0a6a1f1dSLionel Sambuc DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
579f4a2713aSLionel Sambuc
580f4a2713aSLionel Sambuc CAO_LIST()
581f4a2713aSLionel Sambuc #undef OPERATOR
582f4a2713aSLionel Sambuc #undef CAO_LIST
583f4a2713aSLionel Sambuc }
584f4a2713aSLionel Sambuc } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
585f4a2713aSLionel Sambuc switch (UnOp->getOpcode()) {
586f4a2713aSLionel Sambuc #define OPERATOR(NAME) \
587*0a6a1f1dSLionel Sambuc case UO_##NAME: \
588*0a6a1f1dSLionel Sambuc DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
589f4a2713aSLionel Sambuc
590f4a2713aSLionel Sambuc UNARYOP_LIST()
591f4a2713aSLionel Sambuc #undef OPERATOR
592f4a2713aSLionel Sambuc #undef UNARYOP_LIST
593f4a2713aSLionel Sambuc }
594f4a2713aSLionel Sambuc }
595f4a2713aSLionel Sambuc
596f4a2713aSLionel Sambuc // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
597f4a2713aSLionel Sambuc switch (S->getStmtClass()) {
598*0a6a1f1dSLionel Sambuc case Stmt::NoStmtClass:
599*0a6a1f1dSLionel Sambuc break;
600f4a2713aSLionel Sambuc #define ABSTRACT_STMT(STMT)
601f4a2713aSLionel Sambuc #define STMT(CLASS, PARENT) \
602*0a6a1f1dSLionel Sambuc case Stmt::CLASS##Class: \
603*0a6a1f1dSLionel Sambuc DISPATCH_STMT(CLASS, CLASS, S);
604f4a2713aSLionel Sambuc #include "clang/AST/StmtNodes.inc"
605f4a2713aSLionel Sambuc }
606f4a2713aSLionel Sambuc
607f4a2713aSLionel Sambuc return true;
608f4a2713aSLionel Sambuc }
609f4a2713aSLionel Sambuc
610*0a6a1f1dSLionel Sambuc #undef DISPATCH_STMT
611*0a6a1f1dSLionel Sambuc
612f4a2713aSLionel Sambuc template <typename Derived>
TraverseType(QualType T)613f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
614f4a2713aSLionel Sambuc if (T.isNull())
615f4a2713aSLionel Sambuc return true;
616f4a2713aSLionel Sambuc
617f4a2713aSLionel Sambuc switch (T->getTypeClass()) {
618f4a2713aSLionel Sambuc #define ABSTRACT_TYPE(CLASS, BASE)
619f4a2713aSLionel Sambuc #define TYPE(CLASS, BASE) \
620*0a6a1f1dSLionel Sambuc case Type::CLASS: \
621*0a6a1f1dSLionel Sambuc DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr()));
622f4a2713aSLionel Sambuc #include "clang/AST/TypeNodes.def"
623f4a2713aSLionel Sambuc }
624f4a2713aSLionel Sambuc
625f4a2713aSLionel Sambuc return true;
626f4a2713aSLionel Sambuc }
627f4a2713aSLionel Sambuc
628f4a2713aSLionel Sambuc template <typename Derived>
TraverseTypeLoc(TypeLoc TL)629f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) {
630f4a2713aSLionel Sambuc if (TL.isNull())
631f4a2713aSLionel Sambuc return true;
632f4a2713aSLionel Sambuc
633f4a2713aSLionel Sambuc switch (TL.getTypeLocClass()) {
634f4a2713aSLionel Sambuc #define ABSTRACT_TYPELOC(CLASS, BASE)
635f4a2713aSLionel Sambuc #define TYPELOC(CLASS, BASE) \
636f4a2713aSLionel Sambuc case TypeLoc::CLASS: \
637f4a2713aSLionel Sambuc return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>());
638f4a2713aSLionel Sambuc #include "clang/AST/TypeLocNodes.def"
639f4a2713aSLionel Sambuc }
640f4a2713aSLionel Sambuc
641f4a2713aSLionel Sambuc return true;
642f4a2713aSLionel Sambuc }
643f4a2713aSLionel Sambuc
644*0a6a1f1dSLionel Sambuc // Define the Traverse*Attr(Attr* A) methods
645*0a6a1f1dSLionel Sambuc #define VISITORCLASS RecursiveASTVisitor
646*0a6a1f1dSLionel Sambuc #include "clang/AST/AttrVisitor.inc"
647*0a6a1f1dSLionel Sambuc #undef VISITORCLASS
648f4a2713aSLionel Sambuc
649f4a2713aSLionel Sambuc template <typename Derived>
TraverseDecl(Decl * D)650f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
651f4a2713aSLionel Sambuc if (!D)
652f4a2713aSLionel Sambuc return true;
653f4a2713aSLionel Sambuc
654f4a2713aSLionel Sambuc // As a syntax visitor, by default we want to ignore declarations for
655f4a2713aSLionel Sambuc // implicit declarations (ones not typed explicitly by the user).
656f4a2713aSLionel Sambuc if (!getDerived().shouldVisitImplicitCode() && D->isImplicit())
657f4a2713aSLionel Sambuc return true;
658f4a2713aSLionel Sambuc
659f4a2713aSLionel Sambuc switch (D->getKind()) {
660f4a2713aSLionel Sambuc #define ABSTRACT_DECL(DECL)
661f4a2713aSLionel Sambuc #define DECL(CLASS, BASE) \
662*0a6a1f1dSLionel Sambuc case Decl::CLASS: \
663*0a6a1f1dSLionel Sambuc if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \
664*0a6a1f1dSLionel Sambuc return false; \
665*0a6a1f1dSLionel Sambuc break;
666f4a2713aSLionel Sambuc #include "clang/AST/DeclNodes.inc"
667f4a2713aSLionel Sambuc }
668f4a2713aSLionel Sambuc
669*0a6a1f1dSLionel Sambuc // Visit any attributes attached to this declaration.
670*0a6a1f1dSLionel Sambuc for (auto *I : D->attrs()) {
671*0a6a1f1dSLionel Sambuc if (!getDerived().TraverseAttr(I))
672*0a6a1f1dSLionel Sambuc return false;
673*0a6a1f1dSLionel Sambuc }
674f4a2713aSLionel Sambuc return true;
675f4a2713aSLionel Sambuc }
676f4a2713aSLionel Sambuc
677f4a2713aSLionel Sambuc #undef DISPATCH
678f4a2713aSLionel Sambuc
679f4a2713aSLionel Sambuc template <typename Derived>
TraverseNestedNameSpecifier(NestedNameSpecifier * NNS)680f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
681f4a2713aSLionel Sambuc NestedNameSpecifier *NNS) {
682f4a2713aSLionel Sambuc if (!NNS)
683f4a2713aSLionel Sambuc return true;
684f4a2713aSLionel Sambuc
685f4a2713aSLionel Sambuc if (NNS->getPrefix())
686f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix()));
687f4a2713aSLionel Sambuc
688f4a2713aSLionel Sambuc switch (NNS->getKind()) {
689f4a2713aSLionel Sambuc case NestedNameSpecifier::Identifier:
690f4a2713aSLionel Sambuc case NestedNameSpecifier::Namespace:
691f4a2713aSLionel Sambuc case NestedNameSpecifier::NamespaceAlias:
692f4a2713aSLionel Sambuc case NestedNameSpecifier::Global:
693*0a6a1f1dSLionel Sambuc case NestedNameSpecifier::Super:
694f4a2713aSLionel Sambuc return true;
695f4a2713aSLionel Sambuc
696f4a2713aSLionel Sambuc case NestedNameSpecifier::TypeSpec:
697f4a2713aSLionel Sambuc case NestedNameSpecifier::TypeSpecWithTemplate:
698f4a2713aSLionel Sambuc TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
699f4a2713aSLionel Sambuc }
700f4a2713aSLionel Sambuc
701f4a2713aSLionel Sambuc return true;
702f4a2713aSLionel Sambuc }
703f4a2713aSLionel Sambuc
704f4a2713aSLionel Sambuc template <typename Derived>
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)705f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
706f4a2713aSLionel Sambuc NestedNameSpecifierLoc NNS) {
707f4a2713aSLionel Sambuc if (!NNS)
708f4a2713aSLionel Sambuc return true;
709f4a2713aSLionel Sambuc
710f4a2713aSLionel Sambuc if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
711f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
712f4a2713aSLionel Sambuc
713f4a2713aSLionel Sambuc switch (NNS.getNestedNameSpecifier()->getKind()) {
714f4a2713aSLionel Sambuc case NestedNameSpecifier::Identifier:
715f4a2713aSLionel Sambuc case NestedNameSpecifier::Namespace:
716f4a2713aSLionel Sambuc case NestedNameSpecifier::NamespaceAlias:
717f4a2713aSLionel Sambuc case NestedNameSpecifier::Global:
718*0a6a1f1dSLionel Sambuc case NestedNameSpecifier::Super:
719f4a2713aSLionel Sambuc return true;
720f4a2713aSLionel Sambuc
721f4a2713aSLionel Sambuc case NestedNameSpecifier::TypeSpec:
722f4a2713aSLionel Sambuc case NestedNameSpecifier::TypeSpecWithTemplate:
723f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
724f4a2713aSLionel Sambuc break;
725f4a2713aSLionel Sambuc }
726f4a2713aSLionel Sambuc
727f4a2713aSLionel Sambuc return true;
728f4a2713aSLionel Sambuc }
729f4a2713aSLionel Sambuc
730f4a2713aSLionel Sambuc template <typename Derived>
TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo)731f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
732f4a2713aSLionel Sambuc DeclarationNameInfo NameInfo) {
733f4a2713aSLionel Sambuc switch (NameInfo.getName().getNameKind()) {
734f4a2713aSLionel Sambuc case DeclarationName::CXXConstructorName:
735f4a2713aSLionel Sambuc case DeclarationName::CXXDestructorName:
736f4a2713aSLionel Sambuc case DeclarationName::CXXConversionFunctionName:
737f4a2713aSLionel Sambuc if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
738f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
739f4a2713aSLionel Sambuc
740f4a2713aSLionel Sambuc break;
741f4a2713aSLionel Sambuc
742f4a2713aSLionel Sambuc case DeclarationName::Identifier:
743f4a2713aSLionel Sambuc case DeclarationName::ObjCZeroArgSelector:
744f4a2713aSLionel Sambuc case DeclarationName::ObjCOneArgSelector:
745f4a2713aSLionel Sambuc case DeclarationName::ObjCMultiArgSelector:
746f4a2713aSLionel Sambuc case DeclarationName::CXXOperatorName:
747f4a2713aSLionel Sambuc case DeclarationName::CXXLiteralOperatorName:
748f4a2713aSLionel Sambuc case DeclarationName::CXXUsingDirective:
749f4a2713aSLionel Sambuc break;
750f4a2713aSLionel Sambuc }
751f4a2713aSLionel Sambuc
752f4a2713aSLionel Sambuc return true;
753f4a2713aSLionel Sambuc }
754f4a2713aSLionel Sambuc
755f4a2713aSLionel Sambuc template <typename Derived>
TraverseTemplateName(TemplateName Template)756f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
757f4a2713aSLionel Sambuc if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
758f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
759f4a2713aSLionel Sambuc else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
760f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier()));
761f4a2713aSLionel Sambuc
762f4a2713aSLionel Sambuc return true;
763f4a2713aSLionel Sambuc }
764f4a2713aSLionel Sambuc
765f4a2713aSLionel Sambuc template <typename Derived>
TraverseTemplateArgument(const TemplateArgument & Arg)766f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
767f4a2713aSLionel Sambuc const TemplateArgument &Arg) {
768f4a2713aSLionel Sambuc switch (Arg.getKind()) {
769f4a2713aSLionel Sambuc case TemplateArgument::Null:
770f4a2713aSLionel Sambuc case TemplateArgument::Declaration:
771f4a2713aSLionel Sambuc case TemplateArgument::Integral:
772f4a2713aSLionel Sambuc case TemplateArgument::NullPtr:
773f4a2713aSLionel Sambuc return true;
774f4a2713aSLionel Sambuc
775f4a2713aSLionel Sambuc case TemplateArgument::Type:
776f4a2713aSLionel Sambuc return getDerived().TraverseType(Arg.getAsType());
777f4a2713aSLionel Sambuc
778f4a2713aSLionel Sambuc case TemplateArgument::Template:
779f4a2713aSLionel Sambuc case TemplateArgument::TemplateExpansion:
780f4a2713aSLionel Sambuc return getDerived().TraverseTemplateName(
781f4a2713aSLionel Sambuc Arg.getAsTemplateOrTemplatePattern());
782f4a2713aSLionel Sambuc
783f4a2713aSLionel Sambuc case TemplateArgument::Expression:
784f4a2713aSLionel Sambuc return getDerived().TraverseStmt(Arg.getAsExpr());
785f4a2713aSLionel Sambuc
786f4a2713aSLionel Sambuc case TemplateArgument::Pack:
787f4a2713aSLionel Sambuc return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
788f4a2713aSLionel Sambuc Arg.pack_size());
789f4a2713aSLionel Sambuc }
790f4a2713aSLionel Sambuc
791f4a2713aSLionel Sambuc return true;
792f4a2713aSLionel Sambuc }
793f4a2713aSLionel Sambuc
794f4a2713aSLionel Sambuc // FIXME: no template name location?
795f4a2713aSLionel Sambuc // FIXME: no source locations for a template argument pack?
796f4a2713aSLionel Sambuc template <typename Derived>
TraverseTemplateArgumentLoc(const TemplateArgumentLoc & ArgLoc)797f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
798f4a2713aSLionel Sambuc const TemplateArgumentLoc &ArgLoc) {
799f4a2713aSLionel Sambuc const TemplateArgument &Arg = ArgLoc.getArgument();
800f4a2713aSLionel Sambuc
801f4a2713aSLionel Sambuc switch (Arg.getKind()) {
802f4a2713aSLionel Sambuc case TemplateArgument::Null:
803f4a2713aSLionel Sambuc case TemplateArgument::Declaration:
804f4a2713aSLionel Sambuc case TemplateArgument::Integral:
805f4a2713aSLionel Sambuc case TemplateArgument::NullPtr:
806f4a2713aSLionel Sambuc return true;
807f4a2713aSLionel Sambuc
808f4a2713aSLionel Sambuc case TemplateArgument::Type: {
809f4a2713aSLionel Sambuc // FIXME: how can TSI ever be NULL?
810f4a2713aSLionel Sambuc if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
811f4a2713aSLionel Sambuc return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
812f4a2713aSLionel Sambuc else
813f4a2713aSLionel Sambuc return getDerived().TraverseType(Arg.getAsType());
814f4a2713aSLionel Sambuc }
815f4a2713aSLionel Sambuc
816f4a2713aSLionel Sambuc case TemplateArgument::Template:
817f4a2713aSLionel Sambuc case TemplateArgument::TemplateExpansion:
818f4a2713aSLionel Sambuc if (ArgLoc.getTemplateQualifierLoc())
819f4a2713aSLionel Sambuc TRY_TO(getDerived().TraverseNestedNameSpecifierLoc(
820f4a2713aSLionel Sambuc ArgLoc.getTemplateQualifierLoc()));
821f4a2713aSLionel Sambuc return getDerived().TraverseTemplateName(
822f4a2713aSLionel Sambuc Arg.getAsTemplateOrTemplatePattern());
823f4a2713aSLionel Sambuc
824f4a2713aSLionel Sambuc case TemplateArgument::Expression:
825f4a2713aSLionel Sambuc return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
826f4a2713aSLionel Sambuc
827f4a2713aSLionel Sambuc case TemplateArgument::Pack:
828f4a2713aSLionel Sambuc return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
829f4a2713aSLionel Sambuc Arg.pack_size());
830f4a2713aSLionel Sambuc }
831f4a2713aSLionel Sambuc
832f4a2713aSLionel Sambuc return true;
833f4a2713aSLionel Sambuc }
834f4a2713aSLionel Sambuc
835f4a2713aSLionel Sambuc template <typename Derived>
TraverseTemplateArguments(const TemplateArgument * Args,unsigned NumArgs)836f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
837*0a6a1f1dSLionel Sambuc const TemplateArgument *Args, unsigned NumArgs) {
838f4a2713aSLionel Sambuc for (unsigned I = 0; I != NumArgs; ++I) {
839f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgument(Args[I]));
840f4a2713aSLionel Sambuc }
841f4a2713aSLionel Sambuc
842f4a2713aSLionel Sambuc return true;
843f4a2713aSLionel Sambuc }
844f4a2713aSLionel Sambuc
845f4a2713aSLionel Sambuc template <typename Derived>
TraverseConstructorInitializer(CXXCtorInitializer * Init)846f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
847f4a2713aSLionel Sambuc CXXCtorInitializer *Init) {
848f4a2713aSLionel Sambuc if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo())
849f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
850f4a2713aSLionel Sambuc
851f4a2713aSLionel Sambuc if (Init->isWritten() || getDerived().shouldVisitImplicitCode())
852f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(Init->getInit()));
853f4a2713aSLionel Sambuc return true;
854f4a2713aSLionel Sambuc }
855f4a2713aSLionel Sambuc
856f4a2713aSLionel Sambuc template <typename Derived>
857*0a6a1f1dSLionel Sambuc bool
TraverseLambdaCapture(LambdaExpr * LE,const LambdaCapture * C)858*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
859*0a6a1f1dSLionel Sambuc const LambdaCapture *C) {
860f4a2713aSLionel Sambuc if (C->isInitCapture())
861f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(C->getCapturedVar()));
862f4a2713aSLionel Sambuc return true;
863f4a2713aSLionel Sambuc }
864f4a2713aSLionel Sambuc
865f4a2713aSLionel Sambuc template <typename Derived>
TraverseLambdaBody(LambdaExpr * LE)866f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
867f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(LE->getBody()));
868f4a2713aSLionel Sambuc return true;
869f4a2713aSLionel Sambuc }
870f4a2713aSLionel Sambuc
871f4a2713aSLionel Sambuc // ----------------- Type traversal -----------------
872f4a2713aSLionel Sambuc
873f4a2713aSLionel Sambuc // This macro makes available a variable T, the passed-in type.
874f4a2713aSLionel Sambuc #define DEF_TRAVERSE_TYPE(TYPE, CODE) \
875f4a2713aSLionel Sambuc template <typename Derived> \
876f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \
877f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##TYPE(T)); \
878f4a2713aSLionel Sambuc { CODE; } \
879f4a2713aSLionel Sambuc return true; \
880f4a2713aSLionel Sambuc }
881f4a2713aSLionel Sambuc
882f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(BuiltinType, {})
883f4a2713aSLionel Sambuc
884*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); })
885f4a2713aSLionel Sambuc
886*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); })
887f4a2713aSLionel Sambuc
888*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(BlockPointerType,
889*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getPointeeType())); })
890f4a2713aSLionel Sambuc
891*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(LValueReferenceType,
892*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getPointeeType())); })
893f4a2713aSLionel Sambuc
894*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(RValueReferenceType,
895*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getPointeeType())); })
896f4a2713aSLionel Sambuc
897f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(MemberPointerType, {
898f4a2713aSLionel Sambuc TRY_TO(TraverseType(QualType(T->getClass(), 0)));
899f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getPointeeType()));
900f4a2713aSLionel Sambuc })
901f4a2713aSLionel Sambuc
902*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
903f4a2713aSLionel Sambuc
904*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
905f4a2713aSLionel Sambuc
906*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(ConstantArrayType,
907*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getElementType())); })
908*0a6a1f1dSLionel Sambuc
909*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(IncompleteArrayType,
910*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getElementType())); })
911f4a2713aSLionel Sambuc
912f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(VariableArrayType, {
913f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getElementType()));
914f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(T->getSizeExpr()));
915f4a2713aSLionel Sambuc })
916f4a2713aSLionel Sambuc
917f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(DependentSizedArrayType, {
918f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getElementType()));
919f4a2713aSLionel Sambuc if (T->getSizeExpr())
920f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(T->getSizeExpr()));
921f4a2713aSLionel Sambuc })
922f4a2713aSLionel Sambuc
923f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
924f4a2713aSLionel Sambuc if (T->getSizeExpr())
925f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(T->getSizeExpr()));
926f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getElementType()));
927f4a2713aSLionel Sambuc })
928f4a2713aSLionel Sambuc
929*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); })
930f4a2713aSLionel Sambuc
931*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); })
932f4a2713aSLionel Sambuc
933*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(FunctionNoProtoType,
934*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getReturnType())); })
935f4a2713aSLionel Sambuc
936f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(FunctionProtoType, {
937*0a6a1f1dSLionel Sambuc TRY_TO(TraverseType(T->getReturnType()));
938f4a2713aSLionel Sambuc
939*0a6a1f1dSLionel Sambuc for (const auto &A : T->param_types()) {
940*0a6a1f1dSLionel Sambuc TRY_TO(TraverseType(A));
941f4a2713aSLionel Sambuc }
942f4a2713aSLionel Sambuc
943*0a6a1f1dSLionel Sambuc for (const auto &E : T->exceptions()) {
944*0a6a1f1dSLionel Sambuc TRY_TO(TraverseType(E));
945f4a2713aSLionel Sambuc }
946*0a6a1f1dSLionel Sambuc
947*0a6a1f1dSLionel Sambuc if (Expr *NE = T->getNoexceptExpr())
948*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(NE));
949f4a2713aSLionel Sambuc })
950f4a2713aSLionel Sambuc
951f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
952f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(TypedefType, {})
953f4a2713aSLionel Sambuc
954*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(TypeOfExprType,
955*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
956f4a2713aSLionel Sambuc
957*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); })
958f4a2713aSLionel Sambuc
959*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(DecltypeType,
960*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
961f4a2713aSLionel Sambuc
962f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(UnaryTransformType, {
963f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getBaseType()));
964f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getUnderlyingType()));
965f4a2713aSLionel Sambuc })
966f4a2713aSLionel Sambuc
967*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); })
968f4a2713aSLionel Sambuc
969f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(RecordType, {})
970f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(EnumType, {})
971f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(TemplateTypeParmType, {})
972f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {})
973f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {})
974f4a2713aSLionel Sambuc
975f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
976f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateName(T->getTemplateName()));
977f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
978f4a2713aSLionel Sambuc })
979f4a2713aSLionel Sambuc
980f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
981f4a2713aSLionel Sambuc
982*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(AttributedType,
983*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getModifiedType())); })
984f4a2713aSLionel Sambuc
985*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); })
986f4a2713aSLionel Sambuc
987f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(ElaboratedType, {
988f4a2713aSLionel Sambuc if (T->getQualifier()) {
989f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
990f4a2713aSLionel Sambuc }
991f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getNamedType()));
992f4a2713aSLionel Sambuc })
993f4a2713aSLionel Sambuc
994*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(DependentNameType,
995*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); })
996f4a2713aSLionel Sambuc
997f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
998f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
999f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
1000f4a2713aSLionel Sambuc })
1001f4a2713aSLionel Sambuc
1002*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); })
1003f4a2713aSLionel Sambuc
1004f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(ObjCInterfaceType, {})
1005f4a2713aSLionel Sambuc
1006f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPE(ObjCObjectType, {
1007f4a2713aSLionel Sambuc // We have to watch out here because an ObjCInterfaceType's base
1008f4a2713aSLionel Sambuc // type is itself.
1009f4a2713aSLionel Sambuc if (T->getBaseType().getTypePtr() != T)
1010f4a2713aSLionel Sambuc TRY_TO(TraverseType(T->getBaseType()));
1011f4a2713aSLionel Sambuc })
1012f4a2713aSLionel Sambuc
1013*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
1014*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseType(T->getPointeeType())); })
1015f4a2713aSLionel Sambuc
1016*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
1017f4a2713aSLionel Sambuc
1018f4a2713aSLionel Sambuc #undef DEF_TRAVERSE_TYPE
1019f4a2713aSLionel Sambuc
1020f4a2713aSLionel Sambuc // ----------------- TypeLoc traversal -----------------
1021f4a2713aSLionel Sambuc
1022f4a2713aSLionel Sambuc // This macro makes available a variable TL, the passed-in TypeLoc.
1023f4a2713aSLionel Sambuc // If requested, it calls WalkUpFrom* for the Type in the given TypeLoc,
1024f4a2713aSLionel Sambuc // in addition to WalkUpFrom* for the TypeLoc itself, such that existing
1025f4a2713aSLionel Sambuc // clients that override the WalkUpFrom*Type() and/or Visit*Type() methods
1026f4a2713aSLionel Sambuc // continue to work.
1027f4a2713aSLionel Sambuc #define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
1028f4a2713aSLionel Sambuc template <typename Derived> \
1029f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
1030f4a2713aSLionel Sambuc if (getDerived().shouldWalkTypesOfTypeLocs()) \
1031f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \
1032f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
1033f4a2713aSLionel Sambuc { CODE; } \
1034f4a2713aSLionel Sambuc return true; \
1035f4a2713aSLionel Sambuc }
1036f4a2713aSLionel Sambuc
1037f4a2713aSLionel Sambuc template <typename Derived>
1038*0a6a1f1dSLionel Sambuc bool
TraverseQualifiedTypeLoc(QualifiedTypeLoc TL)1039*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) {
1040f4a2713aSLionel Sambuc // Move this over to the 'main' typeloc tree. Note that this is a
1041f4a2713aSLionel Sambuc // move -- we pretend that we were really looking at the unqualified
1042f4a2713aSLionel Sambuc // typeloc all along -- rather than a recursion, so we don't follow
1043f4a2713aSLionel Sambuc // the normal CRTP plan of going through
1044f4a2713aSLionel Sambuc // getDerived().TraverseTypeLoc. If we did, we'd be traversing
1045f4a2713aSLionel Sambuc // twice for the same type (once as a QualifiedTypeLoc version of
1046f4a2713aSLionel Sambuc // the type, once as an UnqualifiedTypeLoc version of the type),
1047f4a2713aSLionel Sambuc // which in effect means we'd call VisitTypeLoc twice with the
1048f4a2713aSLionel Sambuc // 'same' type. This solves that problem, at the cost of never
1049f4a2713aSLionel Sambuc // seeing the qualified version of the type (unless the client
1050f4a2713aSLionel Sambuc // subclasses TraverseQualifiedTypeLoc themselves). It's not a
1051f4a2713aSLionel Sambuc // perfect solution. A perfect solution probably requires making
1052f4a2713aSLionel Sambuc // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a
1053f4a2713aSLionel Sambuc // wrapper around Type* -- rather than being its own class in the
1054f4a2713aSLionel Sambuc // type hierarchy.
1055f4a2713aSLionel Sambuc return TraverseTypeLoc(TL.getUnqualifiedLoc());
1056f4a2713aSLionel Sambuc }
1057f4a2713aSLionel Sambuc
1058f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(BuiltinType, {})
1059f4a2713aSLionel Sambuc
1060f4a2713aSLionel Sambuc // FIXME: ComplexTypeLoc is unfinished
1061f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(ComplexType, {
1062f4a2713aSLionel Sambuc TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
1063f4a2713aSLionel Sambuc })
1064f4a2713aSLionel Sambuc
1065*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(PointerType,
1066*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
1067f4a2713aSLionel Sambuc
1068*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(BlockPointerType,
1069*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
1070f4a2713aSLionel Sambuc
1071*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(LValueReferenceType,
1072*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
1073f4a2713aSLionel Sambuc
1074*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(RValueReferenceType,
1075*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
1076f4a2713aSLionel Sambuc
1077f4a2713aSLionel Sambuc // FIXME: location of base class?
1078f4a2713aSLionel Sambuc // We traverse this in the type case as well, but how is it not reached through
1079f4a2713aSLionel Sambuc // the pointee type?
1080f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(MemberPointerType, {
1081f4a2713aSLionel Sambuc TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
1082f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
1083f4a2713aSLionel Sambuc })
1084f4a2713aSLionel Sambuc
1085*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(AdjustedType,
1086*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
1087*0a6a1f1dSLionel Sambuc
1088*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(DecayedType,
1089*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
1090f4a2713aSLionel Sambuc
1091f4a2713aSLionel Sambuc template <typename Derived>
TraverseArrayTypeLocHelper(ArrayTypeLoc TL)1092f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
1093f4a2713aSLionel Sambuc // This isn't available for ArrayType, but is for the ArrayTypeLoc.
1094f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(TL.getSizeExpr()));
1095f4a2713aSLionel Sambuc return true;
1096f4a2713aSLionel Sambuc }
1097f4a2713aSLionel Sambuc
1098f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
1099f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
1100f4a2713aSLionel Sambuc return TraverseArrayTypeLocHelper(TL);
1101f4a2713aSLionel Sambuc })
1102f4a2713aSLionel Sambuc
1103f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
1104f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
1105f4a2713aSLionel Sambuc return TraverseArrayTypeLocHelper(TL);
1106f4a2713aSLionel Sambuc })
1107f4a2713aSLionel Sambuc
1108f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(VariableArrayType, {
1109f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
1110f4a2713aSLionel Sambuc return TraverseArrayTypeLocHelper(TL);
1111f4a2713aSLionel Sambuc })
1112f4a2713aSLionel Sambuc
1113f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
1114f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
1115f4a2713aSLionel Sambuc return TraverseArrayTypeLocHelper(TL);
1116f4a2713aSLionel Sambuc })
1117f4a2713aSLionel Sambuc
1118f4a2713aSLionel Sambuc // FIXME: order? why not size expr first?
1119f4a2713aSLionel Sambuc // FIXME: base VectorTypeLoc is unfinished
1120f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
1121f4a2713aSLionel Sambuc if (TL.getTypePtr()->getSizeExpr())
1122f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
1123f4a2713aSLionel Sambuc TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
1124f4a2713aSLionel Sambuc })
1125f4a2713aSLionel Sambuc
1126f4a2713aSLionel Sambuc // FIXME: VectorTypeLoc is unfinished
1127f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(VectorType, {
1128f4a2713aSLionel Sambuc TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
1129f4a2713aSLionel Sambuc })
1130f4a2713aSLionel Sambuc
1131f4a2713aSLionel Sambuc // FIXME: size and attributes
1132f4a2713aSLionel Sambuc // FIXME: base VectorTypeLoc is unfinished
1133f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(ExtVectorType, {
1134f4a2713aSLionel Sambuc TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
1135f4a2713aSLionel Sambuc })
1136f4a2713aSLionel Sambuc
1137*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(FunctionNoProtoType,
1138*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); })
1139f4a2713aSLionel Sambuc
1140f4a2713aSLionel Sambuc // FIXME: location of exception specifications (attributes?)
1141f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
1142*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getReturnLoc()));
1143f4a2713aSLionel Sambuc
1144f4a2713aSLionel Sambuc const FunctionProtoType *T = TL.getTypePtr();
1145f4a2713aSLionel Sambuc
1146*0a6a1f1dSLionel Sambuc for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
1147*0a6a1f1dSLionel Sambuc if (TL.getParam(I)) {
1148*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(TL.getParam(I)));
1149*0a6a1f1dSLionel Sambuc } else if (I < T->getNumParams()) {
1150*0a6a1f1dSLionel Sambuc TRY_TO(TraverseType(T->getParamType(I)));
1151f4a2713aSLionel Sambuc }
1152f4a2713aSLionel Sambuc }
1153f4a2713aSLionel Sambuc
1154*0a6a1f1dSLionel Sambuc for (const auto &E : T->exceptions()) {
1155*0a6a1f1dSLionel Sambuc TRY_TO(TraverseType(E));
1156f4a2713aSLionel Sambuc }
1157*0a6a1f1dSLionel Sambuc
1158*0a6a1f1dSLionel Sambuc if (Expr *NE = T->getNoexceptExpr())
1159*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(NE));
1160f4a2713aSLionel Sambuc })
1161f4a2713aSLionel Sambuc
1162f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
1163f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(TypedefType, {})
1164f4a2713aSLionel Sambuc
1165*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(TypeOfExprType,
1166*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); })
1167f4a2713aSLionel Sambuc
1168f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(TypeOfType, {
1169f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
1170f4a2713aSLionel Sambuc })
1171f4a2713aSLionel Sambuc
1172f4a2713aSLionel Sambuc // FIXME: location of underlying expr
1173f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(DecltypeType, {
1174f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
1175f4a2713aSLionel Sambuc })
1176f4a2713aSLionel Sambuc
1177f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
1178f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
1179f4a2713aSLionel Sambuc })
1180f4a2713aSLionel Sambuc
1181f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(AutoType, {
1182f4a2713aSLionel Sambuc TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
1183f4a2713aSLionel Sambuc })
1184f4a2713aSLionel Sambuc
1185f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(RecordType, {})
1186f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(EnumType, {})
1187f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
1188f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {})
1189f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {})
1190f4a2713aSLionel Sambuc
1191f4a2713aSLionel Sambuc // FIXME: use the loc for the template name?
1192f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
1193f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
1194f4a2713aSLionel Sambuc for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
1195f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
1196f4a2713aSLionel Sambuc }
1197f4a2713aSLionel Sambuc })
1198f4a2713aSLionel Sambuc
1199f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {})
1200f4a2713aSLionel Sambuc
1201*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
1202f4a2713aSLionel Sambuc
1203*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(AttributedType,
1204*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); })
1205f4a2713aSLionel Sambuc
1206f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(ElaboratedType, {
1207f4a2713aSLionel Sambuc if (TL.getQualifierLoc()) {
1208f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
1209f4a2713aSLionel Sambuc }
1210f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
1211f4a2713aSLionel Sambuc })
1212f4a2713aSLionel Sambuc
1213f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(DependentNameType, {
1214f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
1215f4a2713aSLionel Sambuc })
1216f4a2713aSLionel Sambuc
1217f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
1218f4a2713aSLionel Sambuc if (TL.getQualifierLoc()) {
1219f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
1220f4a2713aSLionel Sambuc }
1221f4a2713aSLionel Sambuc
1222f4a2713aSLionel Sambuc for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
1223f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
1224f4a2713aSLionel Sambuc }
1225f4a2713aSLionel Sambuc })
1226f4a2713aSLionel Sambuc
1227*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(PackExpansionType,
1228*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); })
1229f4a2713aSLionel Sambuc
1230f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {})
1231f4a2713aSLionel Sambuc
1232f4a2713aSLionel Sambuc DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
1233f4a2713aSLionel Sambuc // We have to watch out here because an ObjCInterfaceType's base
1234f4a2713aSLionel Sambuc // type is itself.
1235f4a2713aSLionel Sambuc if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
1236f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
1237f4a2713aSLionel Sambuc })
1238f4a2713aSLionel Sambuc
1239*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
1240*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
1241f4a2713aSLionel Sambuc
1242*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
1243f4a2713aSLionel Sambuc
1244f4a2713aSLionel Sambuc #undef DEF_TRAVERSE_TYPELOC
1245f4a2713aSLionel Sambuc
1246f4a2713aSLionel Sambuc // ----------------- Decl traversal -----------------
1247f4a2713aSLionel Sambuc //
1248f4a2713aSLionel Sambuc // For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing
1249f4a2713aSLionel Sambuc // the children that come from the DeclContext associated with it.
1250f4a2713aSLionel Sambuc // Therefore each Traverse* only needs to worry about children other
1251f4a2713aSLionel Sambuc // than those.
1252f4a2713aSLionel Sambuc
1253f4a2713aSLionel Sambuc template <typename Derived>
TraverseDeclContextHelper(DeclContext * DC)1254f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
1255f4a2713aSLionel Sambuc if (!DC)
1256f4a2713aSLionel Sambuc return true;
1257f4a2713aSLionel Sambuc
1258*0a6a1f1dSLionel Sambuc for (auto *Child : DC->decls()) {
1259f4a2713aSLionel Sambuc // BlockDecls and CapturedDecls are traversed through BlockExprs and
1260f4a2713aSLionel Sambuc // CapturedStmts respectively.
1261*0a6a1f1dSLionel Sambuc if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child))
1262*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(Child));
1263f4a2713aSLionel Sambuc }
1264f4a2713aSLionel Sambuc
1265f4a2713aSLionel Sambuc return true;
1266f4a2713aSLionel Sambuc }
1267f4a2713aSLionel Sambuc
1268f4a2713aSLionel Sambuc // This macro makes available a variable D, the passed-in decl.
1269f4a2713aSLionel Sambuc #define DEF_TRAVERSE_DECL(DECL, CODE) \
1270f4a2713aSLionel Sambuc template <typename Derived> \
1271f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \
1272f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##DECL(D)); \
1273f4a2713aSLionel Sambuc { CODE; } \
1274f4a2713aSLionel Sambuc TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
1275f4a2713aSLionel Sambuc return true; \
1276f4a2713aSLionel Sambuc }
1277f4a2713aSLionel Sambuc
1278f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(AccessSpecDecl, {})
1279f4a2713aSLionel Sambuc
1280f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(BlockDecl, {
1281f4a2713aSLionel Sambuc if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
1282f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
1283f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getBody()));
1284*0a6a1f1dSLionel Sambuc for (const auto &I : D->captures()) {
1285*0a6a1f1dSLionel Sambuc if (I.hasCopyExpr()) {
1286*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(I.getCopyExpr()));
1287*0a6a1f1dSLionel Sambuc }
1288*0a6a1f1dSLionel Sambuc }
1289f4a2713aSLionel Sambuc // This return statement makes sure the traversal of nodes in
1290f4a2713aSLionel Sambuc // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
1291f4a2713aSLionel Sambuc // is skipped - don't remove it.
1292f4a2713aSLionel Sambuc return true;
1293f4a2713aSLionel Sambuc })
1294f4a2713aSLionel Sambuc
1295f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(CapturedDecl, {
1296f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getBody()));
1297f4a2713aSLionel Sambuc // This return statement makes sure the traversal of nodes in
1298f4a2713aSLionel Sambuc // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
1299f4a2713aSLionel Sambuc // is skipped - don't remove it.
1300f4a2713aSLionel Sambuc return true;
1301f4a2713aSLionel Sambuc })
1302f4a2713aSLionel Sambuc
1303f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(EmptyDecl, {})
1304f4a2713aSLionel Sambuc
1305*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(FileScopeAsmDecl,
1306*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseStmt(D->getAsmString())); })
1307f4a2713aSLionel Sambuc
1308f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(ImportDecl, {})
1309f4a2713aSLionel Sambuc
1310f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(FriendDecl, {
1311f4a2713aSLionel Sambuc // Friend is either decl or a type.
1312f4a2713aSLionel Sambuc if (D->getFriendType())
1313f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
1314f4a2713aSLionel Sambuc else
1315f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(D->getFriendDecl()));
1316f4a2713aSLionel Sambuc })
1317f4a2713aSLionel Sambuc
1318f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(FriendTemplateDecl, {
1319f4a2713aSLionel Sambuc if (D->getFriendType())
1320f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
1321f4a2713aSLionel Sambuc else
1322f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(D->getFriendDecl()));
1323f4a2713aSLionel Sambuc for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
1324f4a2713aSLionel Sambuc TemplateParameterList *TPL = D->getTemplateParameterList(I);
1325*0a6a1f1dSLionel Sambuc for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end();
1326f4a2713aSLionel Sambuc ITPL != ETPL; ++ITPL) {
1327f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(*ITPL));
1328f4a2713aSLionel Sambuc }
1329f4a2713aSLionel Sambuc }
1330f4a2713aSLionel Sambuc })
1331f4a2713aSLionel Sambuc
1332f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
1333f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(D->getSpecialization()));
1334f4a2713aSLionel Sambuc
1335f4a2713aSLionel Sambuc if (D->hasExplicitTemplateArgs()) {
1336f4a2713aSLionel Sambuc const TemplateArgumentListInfo &args = D->templateArgs();
1337*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(args.getArgumentArray(),
1338*0a6a1f1dSLionel Sambuc args.size()));
1339f4a2713aSLionel Sambuc }
1340f4a2713aSLionel Sambuc })
1341f4a2713aSLionel Sambuc
1342f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
1343f4a2713aSLionel Sambuc
1344*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this
1345f4a2713aSLionel Sambuc })
1346f4a2713aSLionel Sambuc
1347f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(StaticAssertDecl, {
1348f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getAssertExpr()));
1349f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getMessage()));
1350f4a2713aSLionel Sambuc })
1351f4a2713aSLionel Sambuc
1352*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(
1353*0a6a1f1dSLionel Sambuc TranslationUnitDecl,
1354*0a6a1f1dSLionel Sambuc {// Code in an unnamed namespace shows up automatically in
1355f4a2713aSLionel Sambuc // decls_begin()/decls_end(). Thus we don't need to recurse on
1356f4a2713aSLionel Sambuc // D->getAnonymousNamespace().
1357f4a2713aSLionel Sambuc })
1358f4a2713aSLionel Sambuc
1359f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
1360f4a2713aSLionel Sambuc // We shouldn't traverse an aliased namespace, since it will be
1361f4a2713aSLionel Sambuc // defined (and, therefore, traversed) somewhere else.
1362f4a2713aSLionel Sambuc //
1363f4a2713aSLionel Sambuc // This return statement makes sure the traversal of nodes in
1364f4a2713aSLionel Sambuc // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
1365f4a2713aSLionel Sambuc // is skipped - don't remove it.
1366f4a2713aSLionel Sambuc return true;
1367f4a2713aSLionel Sambuc })
1368f4a2713aSLionel Sambuc
1369*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl.
1370f4a2713aSLionel Sambuc })
1371f4a2713aSLionel Sambuc
1372*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(
1373*0a6a1f1dSLionel Sambuc NamespaceDecl,
1374*0a6a1f1dSLionel Sambuc {// Code in an unnamed namespace shows up automatically in
1375f4a2713aSLionel Sambuc // decls_begin()/decls_end(). Thus we don't need to recurse on
1376f4a2713aSLionel Sambuc // D->getAnonymousNamespace().
1377f4a2713aSLionel Sambuc })
1378f4a2713aSLionel Sambuc
1379*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
1380f4a2713aSLionel Sambuc })
1381f4a2713aSLionel Sambuc
1382*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
1383f4a2713aSLionel Sambuc })
1384f4a2713aSLionel Sambuc
1385*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
1386f4a2713aSLionel Sambuc })
1387f4a2713aSLionel Sambuc
1388*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
1389f4a2713aSLionel Sambuc })
1390f4a2713aSLionel Sambuc
1391*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
1392f4a2713aSLionel Sambuc })
1393f4a2713aSLionel Sambuc
1394*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
1395f4a2713aSLionel Sambuc })
1396f4a2713aSLionel Sambuc
1397f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(ObjCMethodDecl, {
1398*0a6a1f1dSLionel Sambuc if (D->getReturnTypeSourceInfo()) {
1399*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc()));
1400f4a2713aSLionel Sambuc }
1401*0a6a1f1dSLionel Sambuc for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end();
1402*0a6a1f1dSLionel Sambuc I != E; ++I) {
1403f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(*I));
1404f4a2713aSLionel Sambuc }
1405f4a2713aSLionel Sambuc if (D->isThisDeclarationADefinition()) {
1406f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getBody()));
1407f4a2713aSLionel Sambuc }
1408f4a2713aSLionel Sambuc return true;
1409f4a2713aSLionel Sambuc })
1410f4a2713aSLionel Sambuc
1411f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
1412*0a6a1f1dSLionel Sambuc if (D->getTypeSourceInfo())
1413*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
1414*0a6a1f1dSLionel Sambuc else
1415*0a6a1f1dSLionel Sambuc TRY_TO(TraverseType(D->getType()));
1416*0a6a1f1dSLionel Sambuc return true;
1417f4a2713aSLionel Sambuc })
1418f4a2713aSLionel Sambuc
1419f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(UsingDecl, {
1420f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1421f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
1422f4a2713aSLionel Sambuc })
1423f4a2713aSLionel Sambuc
1424f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
1425f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1426f4a2713aSLionel Sambuc })
1427f4a2713aSLionel Sambuc
1428f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(UsingShadowDecl, {})
1429f4a2713aSLionel Sambuc
1430f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
1431*0a6a1f1dSLionel Sambuc for (auto *I : D->varlists()) {
1432*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(I));
1433f4a2713aSLionel Sambuc }
1434f4a2713aSLionel Sambuc })
1435f4a2713aSLionel Sambuc
1436f4a2713aSLionel Sambuc // A helper method for TemplateDecl's children.
1437f4a2713aSLionel Sambuc template <typename Derived>
TraverseTemplateParameterListHelper(TemplateParameterList * TPL)1438f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
1439f4a2713aSLionel Sambuc TemplateParameterList *TPL) {
1440f4a2713aSLionel Sambuc if (TPL) {
1441f4a2713aSLionel Sambuc for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
1442f4a2713aSLionel Sambuc I != E; ++I) {
1443f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(*I));
1444f4a2713aSLionel Sambuc }
1445f4a2713aSLionel Sambuc }
1446f4a2713aSLionel Sambuc return true;
1447f4a2713aSLionel Sambuc }
1448f4a2713aSLionel Sambuc
1449*0a6a1f1dSLionel Sambuc template <typename Derived>
TraverseTemplateInstantiations(ClassTemplateDecl * D)1450*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
1451*0a6a1f1dSLionel Sambuc ClassTemplateDecl *D) {
1452*0a6a1f1dSLionel Sambuc for (auto *SD : D->specializations()) {
1453*0a6a1f1dSLionel Sambuc for (auto *RD : SD->redecls()) {
1454*0a6a1f1dSLionel Sambuc // We don't want to visit injected-class-names in this traversal.
1455*0a6a1f1dSLionel Sambuc if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
1456*0a6a1f1dSLionel Sambuc continue;
1457*0a6a1f1dSLionel Sambuc
1458*0a6a1f1dSLionel Sambuc switch (
1459*0a6a1f1dSLionel Sambuc cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
1460*0a6a1f1dSLionel Sambuc // Visit the implicit instantiations with the requested pattern.
1461*0a6a1f1dSLionel Sambuc case TSK_Undeclared:
1462*0a6a1f1dSLionel Sambuc case TSK_ImplicitInstantiation:
1463*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(RD));
1464*0a6a1f1dSLionel Sambuc break;
1465*0a6a1f1dSLionel Sambuc
1466*0a6a1f1dSLionel Sambuc // We don't need to do anything on an explicit instantiation
1467*0a6a1f1dSLionel Sambuc // or explicit specialization because there will be an explicit
1468*0a6a1f1dSLionel Sambuc // node for it elsewhere.
1469*0a6a1f1dSLionel Sambuc case TSK_ExplicitInstantiationDeclaration:
1470*0a6a1f1dSLionel Sambuc case TSK_ExplicitInstantiationDefinition:
1471*0a6a1f1dSLionel Sambuc case TSK_ExplicitSpecialization:
1472*0a6a1f1dSLionel Sambuc break;
1473*0a6a1f1dSLionel Sambuc }
1474*0a6a1f1dSLionel Sambuc }
1475f4a2713aSLionel Sambuc }
1476f4a2713aSLionel Sambuc
1477*0a6a1f1dSLionel Sambuc return true;
1478*0a6a1f1dSLionel Sambuc }
1479*0a6a1f1dSLionel Sambuc
1480*0a6a1f1dSLionel Sambuc template <typename Derived>
TraverseTemplateInstantiations(VarTemplateDecl * D)1481*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
1482*0a6a1f1dSLionel Sambuc VarTemplateDecl *D) {
1483*0a6a1f1dSLionel Sambuc for (auto *SD : D->specializations()) {
1484*0a6a1f1dSLionel Sambuc for (auto *RD : SD->redecls()) {
1485*0a6a1f1dSLionel Sambuc switch (
1486*0a6a1f1dSLionel Sambuc cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
1487*0a6a1f1dSLionel Sambuc case TSK_Undeclared:
1488*0a6a1f1dSLionel Sambuc case TSK_ImplicitInstantiation:
1489*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(RD));
1490*0a6a1f1dSLionel Sambuc break;
1491*0a6a1f1dSLionel Sambuc
1492*0a6a1f1dSLionel Sambuc case TSK_ExplicitInstantiationDeclaration:
1493*0a6a1f1dSLionel Sambuc case TSK_ExplicitInstantiationDefinition:
1494*0a6a1f1dSLionel Sambuc case TSK_ExplicitSpecialization:
1495*0a6a1f1dSLionel Sambuc break;
1496*0a6a1f1dSLionel Sambuc }
1497*0a6a1f1dSLionel Sambuc }
1498*0a6a1f1dSLionel Sambuc }
1499*0a6a1f1dSLionel Sambuc
1500*0a6a1f1dSLionel Sambuc return true;
1501*0a6a1f1dSLionel Sambuc }
1502f4a2713aSLionel Sambuc
1503f4a2713aSLionel Sambuc // A helper method for traversing the instantiations of a
1504f4a2713aSLionel Sambuc // function while skipping its specializations.
1505f4a2713aSLionel Sambuc template <typename Derived>
TraverseTemplateInstantiations(FunctionTemplateDecl * D)1506f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
1507f4a2713aSLionel Sambuc FunctionTemplateDecl *D) {
1508*0a6a1f1dSLionel Sambuc for (auto *FD : D->specializations()) {
1509*0a6a1f1dSLionel Sambuc for (auto *RD : FD->redecls()) {
1510*0a6a1f1dSLionel Sambuc switch (RD->getTemplateSpecializationKind()) {
1511f4a2713aSLionel Sambuc case TSK_Undeclared:
1512f4a2713aSLionel Sambuc case TSK_ImplicitInstantiation:
1513f4a2713aSLionel Sambuc // We don't know what kind of FunctionDecl this is.
1514*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(RD));
1515f4a2713aSLionel Sambuc break;
1516f4a2713aSLionel Sambuc
1517f4a2713aSLionel Sambuc // FIXME: For now traverse explicit instantiations here. Change that
1518f4a2713aSLionel Sambuc // once they are represented as dedicated nodes in the AST.
1519f4a2713aSLionel Sambuc case TSK_ExplicitInstantiationDeclaration:
1520f4a2713aSLionel Sambuc case TSK_ExplicitInstantiationDefinition:
1521*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(RD));
1522f4a2713aSLionel Sambuc break;
1523f4a2713aSLionel Sambuc
1524f4a2713aSLionel Sambuc case TSK_ExplicitSpecialization:
1525f4a2713aSLionel Sambuc break;
1526f4a2713aSLionel Sambuc }
1527f4a2713aSLionel Sambuc }
1528*0a6a1f1dSLionel Sambuc }
1529f4a2713aSLionel Sambuc
1530f4a2713aSLionel Sambuc return true;
1531f4a2713aSLionel Sambuc }
1532f4a2713aSLionel Sambuc
1533f4a2713aSLionel Sambuc // This macro unifies the traversal of class, variable and function
1534f4a2713aSLionel Sambuc // template declarations.
1535f4a2713aSLionel Sambuc #define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \
1536f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \
1537f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(D->getTemplatedDecl())); \
1538f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \
1539f4a2713aSLionel Sambuc \
1540*0a6a1f1dSLionel Sambuc /* By default, we do not traverse the instantiations of \
1541*0a6a1f1dSLionel Sambuc class templates since they do not appear in the user code. The \
1542*0a6a1f1dSLionel Sambuc following code optionally traverses them. \
1543*0a6a1f1dSLionel Sambuc \
1544*0a6a1f1dSLionel Sambuc We only traverse the class instantiations when we see the canonical \
1545f4a2713aSLionel Sambuc declaration of the template, to ensure we only visit them once. */ \
1546f4a2713aSLionel Sambuc if (getDerived().shouldVisitTemplateInstantiations() && \
1547f4a2713aSLionel Sambuc D == D->getCanonicalDecl()) \
1548f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateInstantiations(D)); \
1549f4a2713aSLionel Sambuc \
1550*0a6a1f1dSLionel Sambuc /* Note that getInstantiatedFromMemberTemplate() is just a link \
1551*0a6a1f1dSLionel Sambuc from a template instantiation back to the template from which \
1552f4a2713aSLionel Sambuc it was instantiated, and thus should not be traversed. */ \
1553f4a2713aSLionel Sambuc })
1554f4a2713aSLionel Sambuc
1555f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_DECL(Class)
DEF_TRAVERSE_TMPL_DECL(Var)1556f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_DECL(Var)
1557f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_DECL(Function)
1558f4a2713aSLionel Sambuc
1559f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
1560f4a2713aSLionel Sambuc // D is the "T" in something like
1561f4a2713aSLionel Sambuc // template <template <typename> class T> class container { };
1562f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(D->getTemplatedDecl()));
1563f4a2713aSLionel Sambuc if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
1564f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
1565f4a2713aSLionel Sambuc }
1566f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
1567f4a2713aSLionel Sambuc })
1568f4a2713aSLionel Sambuc
1569f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
1570f4a2713aSLionel Sambuc // D is the "T" in something like "template<typename T> class vector;"
1571f4a2713aSLionel Sambuc if (D->getTypeForDecl())
1572f4a2713aSLionel Sambuc TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
1573f4a2713aSLionel Sambuc if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
1574f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
1575f4a2713aSLionel Sambuc })
1576f4a2713aSLionel Sambuc
1577f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TypedefDecl, {
1578f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
1579f4a2713aSLionel Sambuc // We shouldn't traverse D->getTypeForDecl(); it's a result of
1580f4a2713aSLionel Sambuc // declaring the typedef, not something that was written in the
1581f4a2713aSLionel Sambuc // source.
1582f4a2713aSLionel Sambuc })
1583f4a2713aSLionel Sambuc
1584f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TypeAliasDecl, {
1585f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
1586f4a2713aSLionel Sambuc // We shouldn't traverse D->getTypeForDecl(); it's a result of
1587f4a2713aSLionel Sambuc // declaring the type alias, not something that was written in the
1588f4a2713aSLionel Sambuc // source.
1589f4a2713aSLionel Sambuc })
1590f4a2713aSLionel Sambuc
1591f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, {
1592f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(D->getTemplatedDecl()));
1593f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
1594f4a2713aSLionel Sambuc })
1595f4a2713aSLionel Sambuc
1596f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
1597f4a2713aSLionel Sambuc // A dependent using declaration which was marked with 'typename'.
1598f4a2713aSLionel Sambuc // template<class T> class A : public B<T> { using typename B<T>::foo; };
1599f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1600f4a2713aSLionel Sambuc // We shouldn't traverse D->getTypeForDecl(); it's a result of
1601f4a2713aSLionel Sambuc // declaring the type, not something that was written in the
1602f4a2713aSLionel Sambuc // source.
1603f4a2713aSLionel Sambuc })
1604f4a2713aSLionel Sambuc
1605f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(EnumDecl, {
1606f4a2713aSLionel Sambuc if (D->getTypeForDecl())
1607f4a2713aSLionel Sambuc TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
1608f4a2713aSLionel Sambuc
1609f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1610f4a2713aSLionel Sambuc // The enumerators are already traversed by
1611f4a2713aSLionel Sambuc // decls_begin()/decls_end().
1612f4a2713aSLionel Sambuc })
1613f4a2713aSLionel Sambuc
1614f4a2713aSLionel Sambuc // Helper methods for RecordDecl and its children.
1615f4a2713aSLionel Sambuc template <typename Derived>
1616*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) {
1617f4a2713aSLionel Sambuc // We shouldn't traverse D->getTypeForDecl(); it's a result of
1618f4a2713aSLionel Sambuc // declaring the type, not something that was written in the source.
1619f4a2713aSLionel Sambuc
1620f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1621f4a2713aSLionel Sambuc return true;
1622f4a2713aSLionel Sambuc }
1623f4a2713aSLionel Sambuc
1624f4a2713aSLionel Sambuc template <typename Derived>
TraverseCXXRecordHelper(CXXRecordDecl * D)1625*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) {
1626f4a2713aSLionel Sambuc if (!TraverseRecordHelper(D))
1627f4a2713aSLionel Sambuc return false;
1628f4a2713aSLionel Sambuc if (D->isCompleteDefinition()) {
1629*0a6a1f1dSLionel Sambuc for (const auto &I : D->bases()) {
1630*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc()));
1631f4a2713aSLionel Sambuc }
1632f4a2713aSLionel Sambuc // We don't traverse the friends or the conversions, as they are
1633f4a2713aSLionel Sambuc // already in decls_begin()/decls_end().
1634f4a2713aSLionel Sambuc }
1635f4a2713aSLionel Sambuc return true;
1636f4a2713aSLionel Sambuc }
1637f4a2713aSLionel Sambuc
1638*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); })
1639f4a2713aSLionel Sambuc
1640*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
1641f4a2713aSLionel Sambuc
1642f4a2713aSLionel Sambuc #define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \
1643f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \
1644*0a6a1f1dSLionel Sambuc /* For implicit instantiations ("set<int> x;"), we don't want to \
1645*0a6a1f1dSLionel Sambuc recurse at all, since the instatiated template isn't written in \
1646*0a6a1f1dSLionel Sambuc the source code anywhere. (Note the instatiated *type* -- \
1647*0a6a1f1dSLionel Sambuc set<int> -- is written, and will still get a callback of \
1648*0a6a1f1dSLionel Sambuc TemplateSpecializationType). For explicit instantiations \
1649*0a6a1f1dSLionel Sambuc ("template set<int>;"), we do need a callback, since this \
1650*0a6a1f1dSLionel Sambuc is the only callback that's made for this instantiation. \
1651f4a2713aSLionel Sambuc We use getTypeAsWritten() to distinguish. */ \
1652f4a2713aSLionel Sambuc if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \
1653f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \
1654f4a2713aSLionel Sambuc \
1655f4a2713aSLionel Sambuc if (!getDerived().shouldVisitTemplateInstantiations() && \
1656f4a2713aSLionel Sambuc D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \
1657*0a6a1f1dSLionel Sambuc /* Returning from here skips traversing the \
1658*0a6a1f1dSLionel Sambuc declaration context of the *TemplateSpecializationDecl \
1659*0a6a1f1dSLionel Sambuc (embedded in the DEF_TRAVERSE_DECL() macro) \
1660f4a2713aSLionel Sambuc which contains the instantiated members of the template. */ \
1661f4a2713aSLionel Sambuc return true; \
1662f4a2713aSLionel Sambuc })
1663f4a2713aSLionel Sambuc
DEF_TRAVERSE_TMPL_SPEC_DECL(Class)1664f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_SPEC_DECL(Class)
1665f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_SPEC_DECL(Var)
1666f4a2713aSLionel Sambuc
1667f4a2713aSLionel Sambuc template <typename Derived>
1668f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
1669f4a2713aSLionel Sambuc const TemplateArgumentLoc *TAL, unsigned Count) {
1670f4a2713aSLionel Sambuc for (unsigned I = 0; I < Count; ++I) {
1671f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
1672f4a2713aSLionel Sambuc }
1673f4a2713aSLionel Sambuc return true;
1674f4a2713aSLionel Sambuc }
1675f4a2713aSLionel Sambuc
1676f4a2713aSLionel Sambuc #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
1677f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \
1678f4a2713aSLionel Sambuc /* The partial specialization. */ \
1679f4a2713aSLionel Sambuc if (TemplateParameterList *TPL = D->getTemplateParameters()) { \
1680f4a2713aSLionel Sambuc for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \
1681f4a2713aSLionel Sambuc I != E; ++I) { \
1682f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(*I)); \
1683f4a2713aSLionel Sambuc } \
1684f4a2713aSLionel Sambuc } \
1685f4a2713aSLionel Sambuc /* The args that remains unspecialized. */ \
1686f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper( \
1687f4a2713aSLionel Sambuc D->getTemplateArgsAsWritten()->getTemplateArgs(), \
1688f4a2713aSLionel Sambuc D->getTemplateArgsAsWritten()->NumTemplateArgs)); \
1689f4a2713aSLionel Sambuc \
1690*0a6a1f1dSLionel Sambuc /* Don't need the *TemplatePartialSpecializationHelper, even \
1691*0a6a1f1dSLionel Sambuc though that's our parent class -- we already visit all the \
1692f4a2713aSLionel Sambuc template args here. */ \
1693f4a2713aSLionel Sambuc TRY_TO(Traverse##DECLKIND##Helper(D)); \
1694f4a2713aSLionel Sambuc \
1695f4a2713aSLionel Sambuc /* Instantiations will have been visited with the primary template. */ \
1696f4a2713aSLionel Sambuc })
1697f4a2713aSLionel Sambuc
DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class,CXXRecord)1698f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord)
1699f4a2713aSLionel Sambuc DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var)
1700f4a2713aSLionel Sambuc
1701*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); })
1702f4a2713aSLionel Sambuc
1703f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
1704f4a2713aSLionel Sambuc // Like UnresolvedUsingTypenameDecl, but without the 'typename':
1705f4a2713aSLionel Sambuc // template <class T> Class A : public Base<T> { using Base<T>::foo; };
1706f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1707f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
1708f4a2713aSLionel Sambuc })
1709f4a2713aSLionel Sambuc
1710f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
1711f4a2713aSLionel Sambuc
1712f4a2713aSLionel Sambuc template <typename Derived>
1713f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
1714f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1715f4a2713aSLionel Sambuc if (D->getTypeSourceInfo())
1716f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
1717f4a2713aSLionel Sambuc else
1718f4a2713aSLionel Sambuc TRY_TO(TraverseType(D->getType()));
1719f4a2713aSLionel Sambuc return true;
1720f4a2713aSLionel Sambuc }
1721f4a2713aSLionel Sambuc
1722*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
1723f4a2713aSLionel Sambuc
1724f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(FieldDecl, {
1725f4a2713aSLionel Sambuc TRY_TO(TraverseDeclaratorHelper(D));
1726f4a2713aSLionel Sambuc if (D->isBitField())
1727f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getBitWidth()));
1728f4a2713aSLionel Sambuc else if (D->hasInClassInitializer())
1729f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getInClassInitializer()));
1730f4a2713aSLionel Sambuc })
1731f4a2713aSLionel Sambuc
1732f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
1733f4a2713aSLionel Sambuc TRY_TO(TraverseDeclaratorHelper(D));
1734f4a2713aSLionel Sambuc if (D->isBitField())
1735f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getBitWidth()));
1736f4a2713aSLionel Sambuc // FIXME: implement the rest.
1737f4a2713aSLionel Sambuc })
1738f4a2713aSLionel Sambuc
1739f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(ObjCIvarDecl, {
1740f4a2713aSLionel Sambuc TRY_TO(TraverseDeclaratorHelper(D));
1741f4a2713aSLionel Sambuc if (D->isBitField())
1742f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getBitWidth()));
1743f4a2713aSLionel Sambuc // FIXME: implement the rest.
1744f4a2713aSLionel Sambuc })
1745f4a2713aSLionel Sambuc
1746f4a2713aSLionel Sambuc template <typename Derived>
TraverseFunctionHelper(FunctionDecl * D)1747f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
1748f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
1749f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
1750f4a2713aSLionel Sambuc
1751f4a2713aSLionel Sambuc // If we're an explicit template specialization, iterate over the
1752f4a2713aSLionel Sambuc // template args that were explicitly specified. If we were doing
1753f4a2713aSLionel Sambuc // this in typing order, we'd do it between the return type and
1754f4a2713aSLionel Sambuc // the function args, but both are handled by the FunctionTypeLoc
1755f4a2713aSLionel Sambuc // above, so we have to choose one side. I've decided to do before.
1756f4a2713aSLionel Sambuc if (const FunctionTemplateSpecializationInfo *FTSI =
1757f4a2713aSLionel Sambuc D->getTemplateSpecializationInfo()) {
1758f4a2713aSLionel Sambuc if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
1759f4a2713aSLionel Sambuc FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
1760f4a2713aSLionel Sambuc // A specialization might not have explicit template arguments if it has
1761f4a2713aSLionel Sambuc // a templated return type and concrete arguments.
1762f4a2713aSLionel Sambuc if (const ASTTemplateArgumentListInfo *TALI =
1763f4a2713aSLionel Sambuc FTSI->TemplateArgumentsAsWritten) {
1764f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
1765f4a2713aSLionel Sambuc TALI->NumTemplateArgs));
1766f4a2713aSLionel Sambuc }
1767f4a2713aSLionel Sambuc }
1768f4a2713aSLionel Sambuc }
1769f4a2713aSLionel Sambuc
1770f4a2713aSLionel Sambuc // Visit the function type itself, which can be either
1771f4a2713aSLionel Sambuc // FunctionNoProtoType or FunctionProtoType, or a typedef. This
1772f4a2713aSLionel Sambuc // also covers the return type and the function parameters,
1773f4a2713aSLionel Sambuc // including exception specifications.
1774f4a2713aSLionel Sambuc if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) {
1775f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
1776f4a2713aSLionel Sambuc } else if (getDerived().shouldVisitImplicitCode()) {
1777f4a2713aSLionel Sambuc // Visit parameter variable declarations of the implicit function
1778f4a2713aSLionel Sambuc // if the traverser is visiting implicit code. Parameter variable
1779f4a2713aSLionel Sambuc // declarations do not have valid TypeSourceInfo, so to visit them
1780f4a2713aSLionel Sambuc // we need to traverse the declarations explicitly.
1781f4a2713aSLionel Sambuc for (FunctionDecl::param_const_iterator I = D->param_begin(),
1782*0a6a1f1dSLionel Sambuc E = D->param_end();
1783*0a6a1f1dSLionel Sambuc I != E; ++I)
1784f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(*I));
1785f4a2713aSLionel Sambuc }
1786f4a2713aSLionel Sambuc
1787f4a2713aSLionel Sambuc if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
1788f4a2713aSLionel Sambuc // Constructor initializers.
1789*0a6a1f1dSLionel Sambuc for (auto *I : Ctor->inits()) {
1790*0a6a1f1dSLionel Sambuc TRY_TO(TraverseConstructorInitializer(I));
1791f4a2713aSLionel Sambuc }
1792f4a2713aSLionel Sambuc }
1793f4a2713aSLionel Sambuc
1794f4a2713aSLionel Sambuc if (D->isThisDeclarationADefinition()) {
1795f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getBody())); // Function body.
1796f4a2713aSLionel Sambuc }
1797f4a2713aSLionel Sambuc return true;
1798f4a2713aSLionel Sambuc }
1799f4a2713aSLionel Sambuc
1800f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(FunctionDecl, {
1801f4a2713aSLionel Sambuc // We skip decls_begin/decls_end, which are already covered by
1802f4a2713aSLionel Sambuc // TraverseFunctionHelper().
1803f4a2713aSLionel Sambuc return TraverseFunctionHelper(D);
1804f4a2713aSLionel Sambuc })
1805f4a2713aSLionel Sambuc
1806f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(CXXMethodDecl, {
1807f4a2713aSLionel Sambuc // We skip decls_begin/decls_end, which are already covered by
1808f4a2713aSLionel Sambuc // TraverseFunctionHelper().
1809f4a2713aSLionel Sambuc return TraverseFunctionHelper(D);
1810f4a2713aSLionel Sambuc })
1811f4a2713aSLionel Sambuc
1812f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(CXXConstructorDecl, {
1813f4a2713aSLionel Sambuc // We skip decls_begin/decls_end, which are already covered by
1814f4a2713aSLionel Sambuc // TraverseFunctionHelper().
1815f4a2713aSLionel Sambuc return TraverseFunctionHelper(D);
1816f4a2713aSLionel Sambuc })
1817f4a2713aSLionel Sambuc
1818f4a2713aSLionel Sambuc // CXXConversionDecl is the declaration of a type conversion operator.
1819f4a2713aSLionel Sambuc // It's not a cast expression.
1820f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(CXXConversionDecl, {
1821f4a2713aSLionel Sambuc // We skip decls_begin/decls_end, which are already covered by
1822f4a2713aSLionel Sambuc // TraverseFunctionHelper().
1823f4a2713aSLionel Sambuc return TraverseFunctionHelper(D);
1824f4a2713aSLionel Sambuc })
1825f4a2713aSLionel Sambuc
1826f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(CXXDestructorDecl, {
1827f4a2713aSLionel Sambuc // We skip decls_begin/decls_end, which are already covered by
1828f4a2713aSLionel Sambuc // TraverseFunctionHelper().
1829f4a2713aSLionel Sambuc return TraverseFunctionHelper(D);
1830f4a2713aSLionel Sambuc })
1831f4a2713aSLionel Sambuc
1832f4a2713aSLionel Sambuc template <typename Derived>
TraverseVarHelper(VarDecl * D)1833f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
1834f4a2713aSLionel Sambuc TRY_TO(TraverseDeclaratorHelper(D));
1835f4a2713aSLionel Sambuc // Default params are taken care of when we traverse the ParmVarDecl.
1836f4a2713aSLionel Sambuc if (!isa<ParmVarDecl>(D) &&
1837f4a2713aSLionel Sambuc (!D->isCXXForRangeDecl() || getDerived().shouldVisitImplicitCode()))
1838f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getInit()));
1839f4a2713aSLionel Sambuc return true;
1840f4a2713aSLionel Sambuc }
1841f4a2713aSLionel Sambuc
1842*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); })
1843f4a2713aSLionel Sambuc
1844*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); })
1845f4a2713aSLionel Sambuc
1846f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
1847f4a2713aSLionel Sambuc // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
1848f4a2713aSLionel Sambuc TRY_TO(TraverseDeclaratorHelper(D));
1849f4a2713aSLionel Sambuc if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
1850f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getDefaultArgument()));
1851f4a2713aSLionel Sambuc })
1852f4a2713aSLionel Sambuc
1853f4a2713aSLionel Sambuc DEF_TRAVERSE_DECL(ParmVarDecl, {
1854f4a2713aSLionel Sambuc TRY_TO(TraverseVarHelper(D));
1855f4a2713aSLionel Sambuc
1856*0a6a1f1dSLionel Sambuc if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() &&
1857f4a2713aSLionel Sambuc !D->hasUnparsedDefaultArg())
1858f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg()));
1859f4a2713aSLionel Sambuc
1860*0a6a1f1dSLionel Sambuc if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() &&
1861f4a2713aSLionel Sambuc !D->hasUnparsedDefaultArg())
1862f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(D->getDefaultArg()));
1863f4a2713aSLionel Sambuc })
1864f4a2713aSLionel Sambuc
1865f4a2713aSLionel Sambuc #undef DEF_TRAVERSE_DECL
1866f4a2713aSLionel Sambuc
1867f4a2713aSLionel Sambuc // ----------------- Stmt traversal -----------------
1868f4a2713aSLionel Sambuc //
1869f4a2713aSLionel Sambuc // For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
1870f4a2713aSLionel Sambuc // over the children defined in children() (every stmt defines these,
1871f4a2713aSLionel Sambuc // though sometimes the range is empty). Each individual Traverse*
1872f4a2713aSLionel Sambuc // method only needs to worry about children other than those. To see
1873f4a2713aSLionel Sambuc // what children() does for a given class, see, e.g.,
1874f4a2713aSLionel Sambuc // http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
1875f4a2713aSLionel Sambuc
1876f4a2713aSLionel Sambuc // This macro makes available a variable S, the passed-in stmt.
1877f4a2713aSLionel Sambuc #define DEF_TRAVERSE_STMT(STMT, CODE) \
1878f4a2713aSLionel Sambuc template <typename Derived> \
1879f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
1880f4a2713aSLionel Sambuc TRY_TO(WalkUpFrom##STMT(S)); \
1881f4a2713aSLionel Sambuc { CODE; } \
1882f4a2713aSLionel Sambuc for (Stmt::child_range range = S->children(); range; ++range) { \
1883f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(*range)); \
1884f4a2713aSLionel Sambuc } \
1885f4a2713aSLionel Sambuc return true; \
1886f4a2713aSLionel Sambuc }
1887f4a2713aSLionel Sambuc
1888f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(GCCAsmStmt, {
1889f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getAsmString()));
1890f4a2713aSLionel Sambuc for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
1891f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
1892f4a2713aSLionel Sambuc }
1893f4a2713aSLionel Sambuc for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
1894f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
1895f4a2713aSLionel Sambuc }
1896f4a2713aSLionel Sambuc for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
1897f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getClobberStringLiteral(I)));
1898f4a2713aSLionel Sambuc }
1899f4a2713aSLionel Sambuc // children() iterates over inputExpr and outputExpr.
1900f4a2713aSLionel Sambuc })
1901f4a2713aSLionel Sambuc
1902*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(
1903*0a6a1f1dSLionel Sambuc MSAsmStmt,
1904*0a6a1f1dSLionel Sambuc {// FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once
1905f4a2713aSLionel Sambuc // added this needs to be implemented.
1906f4a2713aSLionel Sambuc })
1907f4a2713aSLionel Sambuc
1908f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXCatchStmt, {
1909f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(S->getExceptionDecl()));
1910f4a2713aSLionel Sambuc // children() iterates over the handler block.
1911f4a2713aSLionel Sambuc })
1912f4a2713aSLionel Sambuc
1913f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(DeclStmt, {
1914*0a6a1f1dSLionel Sambuc for (auto *I : S->decls()) {
1915*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(I));
1916f4a2713aSLionel Sambuc }
1917f4a2713aSLionel Sambuc // Suppress the default iteration over children() by
1918f4a2713aSLionel Sambuc // returning. Here's why: A DeclStmt looks like 'type var [=
1919f4a2713aSLionel Sambuc // initializer]'. The decls above already traverse over the
1920f4a2713aSLionel Sambuc // initializers, so we don't have to do it again (which
1921f4a2713aSLionel Sambuc // children() would do).
1922f4a2713aSLionel Sambuc return true;
1923f4a2713aSLionel Sambuc })
1924f4a2713aSLionel Sambuc
1925f4a2713aSLionel Sambuc // These non-expr stmts (most of them), do not need any action except
1926f4a2713aSLionel Sambuc // iterating over the children.
1927f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(BreakStmt, {})
1928f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXTryStmt, {})
1929f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CaseStmt, {})
1930f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CompoundStmt, {})
1931f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ContinueStmt, {})
1932f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(DefaultStmt, {})
1933f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(DoStmt, {})
1934f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ForStmt, {})
1935f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(GotoStmt, {})
1936f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(IfStmt, {})
1937f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(IndirectGotoStmt, {})
1938f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(LabelStmt, {})
1939f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(AttributedStmt, {})
1940f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(NullStmt, {})
1941f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {})
1942f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {})
1943f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {})
1944f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {})
1945f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCAtTryStmt, {})
1946f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
1947f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
1948f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXForRangeStmt, {
1949f4a2713aSLionel Sambuc if (!getDerived().shouldVisitImplicitCode()) {
1950f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getLoopVarStmt()));
1951f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getRangeInit()));
1952f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getBody()));
1953f4a2713aSLionel Sambuc // Visit everything else only if shouldVisitImplicitCode().
1954f4a2713aSLionel Sambuc return true;
1955f4a2713aSLionel Sambuc }
1956f4a2713aSLionel Sambuc })
1957f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
1958f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
1959f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
1960f4a2713aSLionel Sambuc })
1961f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ReturnStmt, {})
1962f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(SwitchStmt, {})
1963f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(WhileStmt, {})
1964f4a2713aSLionel Sambuc
1965f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
1966f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
1967f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
1968f4a2713aSLionel Sambuc if (S->hasExplicitTemplateArgs()) {
1969*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
1970*0a6a1f1dSLionel Sambuc S->getNumTemplateArgs()));
1971f4a2713aSLionel Sambuc }
1972f4a2713aSLionel Sambuc })
1973f4a2713aSLionel Sambuc
1974f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(DeclRefExpr, {
1975f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
1976f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
1977*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
1978*0a6a1f1dSLionel Sambuc S->getNumTemplateArgs()));
1979f4a2713aSLionel Sambuc })
1980f4a2713aSLionel Sambuc
1981f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
1982f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
1983f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
1984f4a2713aSLionel Sambuc if (S->hasExplicitTemplateArgs()) {
1985f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(
1986f4a2713aSLionel Sambuc S->getExplicitTemplateArgs().getTemplateArgs(),
1987f4a2713aSLionel Sambuc S->getNumTemplateArgs()));
1988f4a2713aSLionel Sambuc }
1989f4a2713aSLionel Sambuc })
1990f4a2713aSLionel Sambuc
1991f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(MemberExpr, {
1992f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
1993f4a2713aSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
1994*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
1995*0a6a1f1dSLionel Sambuc S->getNumTemplateArgs()));
1996f4a2713aSLionel Sambuc })
1997f4a2713aSLionel Sambuc
1998*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(
1999*0a6a1f1dSLionel Sambuc ImplicitCastExpr,
2000*0a6a1f1dSLionel Sambuc {// We don't traverse the cast type, as it's not written in the
2001f4a2713aSLionel Sambuc // source code.
2002f4a2713aSLionel Sambuc })
2003f4a2713aSLionel Sambuc
2004f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CStyleCastExpr, {
2005f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
2006f4a2713aSLionel Sambuc })
2007f4a2713aSLionel Sambuc
2008f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
2009f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
2010f4a2713aSLionel Sambuc })
2011f4a2713aSLionel Sambuc
2012f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXConstCastExpr, {
2013f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
2014f4a2713aSLionel Sambuc })
2015f4a2713aSLionel Sambuc
2016f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
2017f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
2018f4a2713aSLionel Sambuc })
2019f4a2713aSLionel Sambuc
2020f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
2021f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
2022f4a2713aSLionel Sambuc })
2023f4a2713aSLionel Sambuc
2024f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
2025f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
2026f4a2713aSLionel Sambuc })
2027f4a2713aSLionel Sambuc
2028f4a2713aSLionel Sambuc // InitListExpr is a tricky one, because we want to do all our work on
2029f4a2713aSLionel Sambuc // the syntactic form of the listexpr, but this method takes the
2030f4a2713aSLionel Sambuc // semantic form by default. We can't use the macro helper because it
2031f4a2713aSLionel Sambuc // calls WalkUp*() on the semantic form, before our code can convert
2032f4a2713aSLionel Sambuc // to the syntactic form.
2033f4a2713aSLionel Sambuc template <typename Derived>
TraverseInitListExpr(InitListExpr * S)2034f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
2035f4a2713aSLionel Sambuc if (InitListExpr *Syn = S->getSyntacticForm())
2036f4a2713aSLionel Sambuc S = Syn;
2037f4a2713aSLionel Sambuc TRY_TO(WalkUpFromInitListExpr(S));
2038f4a2713aSLionel Sambuc // All we need are the default actions. FIXME: use a helper function.
2039f4a2713aSLionel Sambuc for (Stmt::child_range range = S->children(); range; ++range) {
2040f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(*range));
2041f4a2713aSLionel Sambuc }
2042f4a2713aSLionel Sambuc return true;
2043f4a2713aSLionel Sambuc }
2044f4a2713aSLionel Sambuc
2045f4a2713aSLionel Sambuc // GenericSelectionExpr is a special case because the types and expressions
2046f4a2713aSLionel Sambuc // are interleaved. We also need to watch out for null types (default
2047f4a2713aSLionel Sambuc // generic associations).
2048f4a2713aSLionel Sambuc template <typename Derived>
TraverseGenericSelectionExpr(GenericSelectionExpr * S)2049*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
2050*0a6a1f1dSLionel Sambuc GenericSelectionExpr *S) {
2051f4a2713aSLionel Sambuc TRY_TO(WalkUpFromGenericSelectionExpr(S));
2052f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getControllingExpr()));
2053f4a2713aSLionel Sambuc for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
2054f4a2713aSLionel Sambuc if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
2055f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
2056f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getAssocExpr(i)));
2057f4a2713aSLionel Sambuc }
2058f4a2713aSLionel Sambuc return true;
2059f4a2713aSLionel Sambuc }
2060f4a2713aSLionel Sambuc
2061f4a2713aSLionel Sambuc // PseudoObjectExpr is a special case because of the wierdness with
2062f4a2713aSLionel Sambuc // syntactic expressions and opaque values.
2063f4a2713aSLionel Sambuc template <typename Derived>
2064*0a6a1f1dSLionel Sambuc bool
TraversePseudoObjectExpr(PseudoObjectExpr * S)2065*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
2066f4a2713aSLionel Sambuc TRY_TO(WalkUpFromPseudoObjectExpr(S));
2067f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(S->getSyntacticForm()));
2068*0a6a1f1dSLionel Sambuc for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
2069*0a6a1f1dSLionel Sambuc e = S->semantics_end();
2070*0a6a1f1dSLionel Sambuc i != e; ++i) {
2071f4a2713aSLionel Sambuc Expr *sub = *i;
2072f4a2713aSLionel Sambuc if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
2073f4a2713aSLionel Sambuc sub = OVE->getSourceExpr();
2074f4a2713aSLionel Sambuc TRY_TO(TraverseStmt(sub));
2075f4a2713aSLionel Sambuc }
2076f4a2713aSLionel Sambuc return true;
2077f4a2713aSLionel Sambuc }
2078f4a2713aSLionel Sambuc
2079f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
2080f4a2713aSLionel Sambuc // This is called for code like 'return T()' where T is a built-in
2081f4a2713aSLionel Sambuc // (i.e. non-class) type.
2082f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
2083f4a2713aSLionel Sambuc })
2084f4a2713aSLionel Sambuc
2085f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXNewExpr, {
2086f4a2713aSLionel Sambuc // The child-iterator will pick up the other arguments.
2087f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc()));
2088f4a2713aSLionel Sambuc })
2089f4a2713aSLionel Sambuc
2090f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(OffsetOfExpr, {
2091f4a2713aSLionel Sambuc // The child-iterator will pick up the expression representing
2092f4a2713aSLionel Sambuc // the field.
2093f4a2713aSLionel Sambuc // FIMXE: for code like offsetof(Foo, a.b.c), should we get
2094f4a2713aSLionel Sambuc // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
2095f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
2096f4a2713aSLionel Sambuc })
2097f4a2713aSLionel Sambuc
2098f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, {
2099f4a2713aSLionel Sambuc // The child-iterator will pick up the arg if it's an expression,
2100f4a2713aSLionel Sambuc // but not if it's a type.
2101f4a2713aSLionel Sambuc if (S->isArgumentType())
2102f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
2103f4a2713aSLionel Sambuc })
2104f4a2713aSLionel Sambuc
2105f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXTypeidExpr, {
2106f4a2713aSLionel Sambuc // The child-iterator will pick up the arg if it's an expression,
2107f4a2713aSLionel Sambuc // but not if it's a type.
2108f4a2713aSLionel Sambuc if (S->isTypeOperand())
2109f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
2110f4a2713aSLionel Sambuc })
2111f4a2713aSLionel Sambuc
2112f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
2113f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
2114f4a2713aSLionel Sambuc })
2115f4a2713aSLionel Sambuc
2116f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXUuidofExpr, {
2117f4a2713aSLionel Sambuc // The child-iterator will pick up the arg if it's an expression,
2118f4a2713aSLionel Sambuc // but not if it's a type.
2119f4a2713aSLionel Sambuc if (S->isTypeOperand())
2120f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
2121f4a2713aSLionel Sambuc })
2122f4a2713aSLionel Sambuc
2123f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(TypeTraitExpr, {
2124f4a2713aSLionel Sambuc for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
2125f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc()));
2126f4a2713aSLionel Sambuc })
2127f4a2713aSLionel Sambuc
2128f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
2129f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
2130f4a2713aSLionel Sambuc })
2131f4a2713aSLionel Sambuc
2132*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(ExpressionTraitExpr,
2133*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseStmt(S->getQueriedExpression())); })
2134f4a2713aSLionel Sambuc
2135f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(VAArgExpr, {
2136f4a2713aSLionel Sambuc // The child-iterator will pick up the expression argument.
2137f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
2138f4a2713aSLionel Sambuc })
2139f4a2713aSLionel Sambuc
2140f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
2141f4a2713aSLionel Sambuc // This is called for code like 'return T()' where T is a class type.
2142f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
2143f4a2713aSLionel Sambuc })
2144f4a2713aSLionel Sambuc
2145f4a2713aSLionel Sambuc // Walk only the visible parts of lambda expressions.
2146f4a2713aSLionel Sambuc template <typename Derived>
TraverseLambdaExpr(LambdaExpr * S)2147f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
2148f4a2713aSLionel Sambuc TRY_TO(WalkUpFromLambdaExpr(S));
2149f4a2713aSLionel Sambuc
2150f4a2713aSLionel Sambuc for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
2151f4a2713aSLionel Sambuc CEnd = S->explicit_capture_end();
2152f4a2713aSLionel Sambuc C != CEnd; ++C) {
2153f4a2713aSLionel Sambuc TRY_TO(TraverseLambdaCapture(S, C));
2154f4a2713aSLionel Sambuc }
2155f4a2713aSLionel Sambuc
2156f4a2713aSLionel Sambuc TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
2157*0a6a1f1dSLionel Sambuc FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
2158*0a6a1f1dSLionel Sambuc
2159f4a2713aSLionel Sambuc if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
2160f4a2713aSLionel Sambuc // Visit the whole type.
2161f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TL));
2162*0a6a1f1dSLionel Sambuc } else {
2163f4a2713aSLionel Sambuc if (S->hasExplicitParameters()) {
2164f4a2713aSLionel Sambuc // Visit parameters.
2165*0a6a1f1dSLionel Sambuc for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
2166*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDecl(Proto.getParam(I)));
2167f4a2713aSLionel Sambuc }
2168*0a6a1f1dSLionel Sambuc } else if (S->hasExplicitResultType()) {
2169*0a6a1f1dSLionel Sambuc TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
2170f4a2713aSLionel Sambuc }
2171*0a6a1f1dSLionel Sambuc
2172*0a6a1f1dSLionel Sambuc auto *T = Proto.getTypePtr();
2173*0a6a1f1dSLionel Sambuc for (const auto &E : T->exceptions()) {
2174*0a6a1f1dSLionel Sambuc TRY_TO(TraverseType(E));
2175f4a2713aSLionel Sambuc }
2176*0a6a1f1dSLionel Sambuc
2177*0a6a1f1dSLionel Sambuc if (Expr *NE = T->getNoexceptExpr())
2178*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(NE));
2179f4a2713aSLionel Sambuc }
2180f4a2713aSLionel Sambuc
2181f4a2713aSLionel Sambuc TRY_TO(TraverseLambdaBody(S));
2182f4a2713aSLionel Sambuc return true;
2183f4a2713aSLionel Sambuc }
2184f4a2713aSLionel Sambuc
2185f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
2186f4a2713aSLionel Sambuc // This is called for code like 'T()', where T is a template argument.
2187f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
2188f4a2713aSLionel Sambuc })
2189f4a2713aSLionel Sambuc
2190f4a2713aSLionel Sambuc // These expressions all might take explicit template arguments.
2191f4a2713aSLionel Sambuc // We traverse those if so. FIXME: implement these.
2192f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXConstructExpr, {})
2193f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CallExpr, {})
2194f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
2195f4a2713aSLionel Sambuc
2196f4a2713aSLionel Sambuc // These exprs (most of them), do not need any action except iterating
2197f4a2713aSLionel Sambuc // over the children.
2198f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(AddrLabelExpr, {})
2199f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
2200f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(BlockExpr, {
2201f4a2713aSLionel Sambuc TRY_TO(TraverseDecl(S->getBlockDecl()));
2202f4a2713aSLionel Sambuc return true; // no child statements to loop through.
2203f4a2713aSLionel Sambuc })
2204f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ChooseExpr, {})
2205f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CompoundLiteralExpr, {
2206f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
2207f4a2713aSLionel Sambuc })
2208f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {})
2209f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {})
2210f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {})
2211f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {})
2212f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXDeleteExpr, {})
2213f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ExprWithCleanups, {})
2214f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {})
2215f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {})
2216f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
2217f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
2218f4a2713aSLionel Sambuc if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
2219f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
2220f4a2713aSLionel Sambuc if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
2221f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
2222f4a2713aSLionel Sambuc })
2223f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXThisExpr, {})
2224f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXThrowExpr, {})
2225f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
2226f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
2227f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
2228f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(GNUNullExpr, {})
2229f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
2230f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
2231f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
2232f4a2713aSLionel Sambuc if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
2233f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
2234f4a2713aSLionel Sambuc })
2235f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCIsaExpr, {})
2236f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {})
2237f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCMessageExpr, {
2238f4a2713aSLionel Sambuc if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo())
2239f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
2240f4a2713aSLionel Sambuc })
2241f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {})
2242f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {})
2243f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCProtocolExpr, {})
2244f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCSelectorExpr, {})
2245f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {})
2246f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
2247f4a2713aSLionel Sambuc TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
2248f4a2713aSLionel Sambuc })
2249f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ParenExpr, {})
2250f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ParenListExpr, {})
2251f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(PredefinedExpr, {})
2252f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
2253f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
2254f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(StmtExpr, {})
2255f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
2256f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
2257f4a2713aSLionel Sambuc if (S->hasExplicitTemplateArgs()) {
2258f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
2259f4a2713aSLionel Sambuc S->getNumTemplateArgs()));
2260f4a2713aSLionel Sambuc }
2261f4a2713aSLionel Sambuc })
2262f4a2713aSLionel Sambuc
2263f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
2264f4a2713aSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
2265f4a2713aSLionel Sambuc if (S->hasExplicitTemplateArgs()) {
2266f4a2713aSLionel Sambuc TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
2267f4a2713aSLionel Sambuc S->getNumTemplateArgs()));
2268f4a2713aSLionel Sambuc }
2269f4a2713aSLionel Sambuc })
2270f4a2713aSLionel Sambuc
2271f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(SEHTryStmt, {})
2272f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(SEHExceptStmt, {})
2273f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(SEHFinallyStmt, {})
2274*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
2275*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
2276f4a2713aSLionel Sambuc
2277f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
2278f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
2279*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(TypoExpr, {})
2280f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
2281f4a2713aSLionel Sambuc
2282f4a2713aSLionel Sambuc // These operators (all of them) do not need any action except
2283f4a2713aSLionel Sambuc // iterating over the children.
2284f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(BinaryConditionalOperator, {})
2285f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ConditionalOperator, {})
2286f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(UnaryOperator, {})
2287f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(BinaryOperator, {})
2288f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CompoundAssignOperator, {})
2289f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CXXNoexceptExpr, {})
2290f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(PackExpansionExpr, {})
2291f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
2292f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
2293f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
2294f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
2295f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
2296*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(CXXFoldExpr, {})
2297f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(AtomicExpr, {})
2298f4a2713aSLionel Sambuc
2299f4a2713aSLionel Sambuc // These literals (all of them) do not need any action.
2300f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(IntegerLiteral, {})
2301f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(CharacterLiteral, {})
2302f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(FloatingLiteral, {})
2303f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ImaginaryLiteral, {})
2304f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(StringLiteral, {})
2305f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCStringLiteral, {})
2306f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCBoxedExpr, {})
2307f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCArrayLiteral, {})
2308f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {})
2309f4a2713aSLionel Sambuc
2310f4a2713aSLionel Sambuc // Traverse OpenCL: AsType, Convert.
2311f4a2713aSLionel Sambuc DEF_TRAVERSE_STMT(AsTypeExpr, {})
2312f4a2713aSLionel Sambuc
2313f4a2713aSLionel Sambuc // OpenMP directives.
2314f4a2713aSLionel Sambuc template <typename Derived>
TraverseOMPExecutableDirective(OMPExecutableDirective * S)2315*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
2316*0a6a1f1dSLionel Sambuc OMPExecutableDirective *S) {
2317*0a6a1f1dSLionel Sambuc for (auto *C : S->clauses()) {
2318*0a6a1f1dSLionel Sambuc TRY_TO(TraverseOMPClause(C));
2319f4a2713aSLionel Sambuc }
2320f4a2713aSLionel Sambuc return true;
2321f4a2713aSLionel Sambuc }
2322f4a2713aSLionel Sambuc
2323f4a2713aSLionel Sambuc template <typename Derived>
2324*0a6a1f1dSLionel Sambuc bool
TraverseOMPLoopDirective(OMPLoopDirective * S)2325*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) {
2326*0a6a1f1dSLionel Sambuc return TraverseOMPExecutableDirective(S);
2327*0a6a1f1dSLionel Sambuc }
2328*0a6a1f1dSLionel Sambuc
2329*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPParallelDirective,
2330*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2331*0a6a1f1dSLionel Sambuc
2332*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPSimdDirective,
2333*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2334*0a6a1f1dSLionel Sambuc
2335*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPForDirective,
2336*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2337*0a6a1f1dSLionel Sambuc
2338*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPForSimdDirective,
2339*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2340*0a6a1f1dSLionel Sambuc
2341*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPSectionsDirective,
2342*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2343*0a6a1f1dSLionel Sambuc
2344*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPSectionDirective,
2345*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2346*0a6a1f1dSLionel Sambuc
2347*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPSingleDirective,
2348*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2349*0a6a1f1dSLionel Sambuc
2350*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPMasterDirective,
2351*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2352*0a6a1f1dSLionel Sambuc
2353*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPCriticalDirective, {
2354*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName()));
2355*0a6a1f1dSLionel Sambuc TRY_TO(TraverseOMPExecutableDirective(S));
2356*0a6a1f1dSLionel Sambuc })
2357*0a6a1f1dSLionel Sambuc
2358*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPParallelForDirective,
2359*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2360*0a6a1f1dSLionel Sambuc
2361*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
2362*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2363*0a6a1f1dSLionel Sambuc
2364*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
2365*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2366*0a6a1f1dSLionel Sambuc
2367*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPTaskDirective,
2368*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2369*0a6a1f1dSLionel Sambuc
2370*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPTaskyieldDirective,
2371*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2372*0a6a1f1dSLionel Sambuc
2373*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPBarrierDirective,
2374*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2375*0a6a1f1dSLionel Sambuc
2376*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
2377*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2378*0a6a1f1dSLionel Sambuc
2379*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPFlushDirective,
2380*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2381*0a6a1f1dSLionel Sambuc
2382*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPOrderedDirective,
2383*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2384*0a6a1f1dSLionel Sambuc
2385*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPAtomicDirective,
2386*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2387*0a6a1f1dSLionel Sambuc
2388*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPTargetDirective,
2389*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2390*0a6a1f1dSLionel Sambuc
2391*0a6a1f1dSLionel Sambuc DEF_TRAVERSE_STMT(OMPTeamsDirective,
2392*0a6a1f1dSLionel Sambuc { TRY_TO(TraverseOMPExecutableDirective(S)); })
2393*0a6a1f1dSLionel Sambuc
2394*0a6a1f1dSLionel Sambuc // OpenMP clauses.
2395*0a6a1f1dSLionel Sambuc template <typename Derived>
TraverseOMPClause(OMPClause * C)2396*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
2397*0a6a1f1dSLionel Sambuc if (!C)
2398*0a6a1f1dSLionel Sambuc return true;
2399*0a6a1f1dSLionel Sambuc switch (C->getClauseKind()) {
2400*0a6a1f1dSLionel Sambuc #define OPENMP_CLAUSE(Name, Class) \
2401*0a6a1f1dSLionel Sambuc case OMPC_##Name: \
2402*0a6a1f1dSLionel Sambuc TRY_TO(Visit##Class(static_cast<Class *>(C))); \
2403*0a6a1f1dSLionel Sambuc break;
2404*0a6a1f1dSLionel Sambuc #include "clang/Basic/OpenMPKinds.def"
2405*0a6a1f1dSLionel Sambuc case OMPC_threadprivate:
2406*0a6a1f1dSLionel Sambuc case OMPC_unknown:
2407*0a6a1f1dSLionel Sambuc break;
2408*0a6a1f1dSLionel Sambuc }
2409*0a6a1f1dSLionel Sambuc return true;
2410*0a6a1f1dSLionel Sambuc }
2411*0a6a1f1dSLionel Sambuc
2412*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPIfClause(OMPIfClause * C)2413*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
2414*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getCondition()));
2415*0a6a1f1dSLionel Sambuc return true;
2416*0a6a1f1dSLionel Sambuc }
2417*0a6a1f1dSLionel Sambuc
2418*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPFinalClause(OMPFinalClause * C)2419*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
2420*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getCondition()));
2421*0a6a1f1dSLionel Sambuc return true;
2422*0a6a1f1dSLionel Sambuc }
2423*0a6a1f1dSLionel Sambuc
2424*0a6a1f1dSLionel Sambuc template <typename Derived>
2425*0a6a1f1dSLionel Sambuc bool
VisitOMPNumThreadsClause(OMPNumThreadsClause * C)2426*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
2427*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getNumThreads()));
2428*0a6a1f1dSLionel Sambuc return true;
2429*0a6a1f1dSLionel Sambuc }
2430*0a6a1f1dSLionel Sambuc
2431*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPSafelenClause(OMPSafelenClause * C)2432*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
2433*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getSafelen()));
2434*0a6a1f1dSLionel Sambuc return true;
2435*0a6a1f1dSLionel Sambuc }
2436*0a6a1f1dSLionel Sambuc
2437*0a6a1f1dSLionel Sambuc template <typename Derived>
2438*0a6a1f1dSLionel Sambuc bool
VisitOMPCollapseClause(OMPCollapseClause * C)2439*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) {
2440*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getNumForLoops()));
2441*0a6a1f1dSLionel Sambuc return true;
2442*0a6a1f1dSLionel Sambuc }
2443*0a6a1f1dSLionel Sambuc
2444*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPDefaultClause(OMPDefaultClause *)2445*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) {
2446*0a6a1f1dSLionel Sambuc return true;
2447*0a6a1f1dSLionel Sambuc }
2448*0a6a1f1dSLionel Sambuc
2449*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPProcBindClause(OMPProcBindClause *)2450*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) {
2451*0a6a1f1dSLionel Sambuc return true;
2452*0a6a1f1dSLionel Sambuc }
2453*0a6a1f1dSLionel Sambuc
2454*0a6a1f1dSLionel Sambuc template <typename Derived>
2455*0a6a1f1dSLionel Sambuc bool
VisitOMPScheduleClause(OMPScheduleClause * C)2456*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
2457*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getChunkSize()));
2458*0a6a1f1dSLionel Sambuc return true;
2459*0a6a1f1dSLionel Sambuc }
2460*0a6a1f1dSLionel Sambuc
2461*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPOrderedClause(OMPOrderedClause *)2462*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
2463*0a6a1f1dSLionel Sambuc return true;
2464*0a6a1f1dSLionel Sambuc }
2465*0a6a1f1dSLionel Sambuc
2466*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPNowaitClause(OMPNowaitClause *)2467*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) {
2468*0a6a1f1dSLionel Sambuc return true;
2469*0a6a1f1dSLionel Sambuc }
2470*0a6a1f1dSLionel Sambuc
2471*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPUntiedClause(OMPUntiedClause *)2472*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) {
2473*0a6a1f1dSLionel Sambuc return true;
2474*0a6a1f1dSLionel Sambuc }
2475*0a6a1f1dSLionel Sambuc
2476*0a6a1f1dSLionel Sambuc template <typename Derived>
2477*0a6a1f1dSLionel Sambuc bool
VisitOMPMergeableClause(OMPMergeableClause *)2478*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) {
2479*0a6a1f1dSLionel Sambuc return true;
2480*0a6a1f1dSLionel Sambuc }
2481*0a6a1f1dSLionel Sambuc
2482*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPReadClause(OMPReadClause *)2483*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) {
2484*0a6a1f1dSLionel Sambuc return true;
2485*0a6a1f1dSLionel Sambuc }
2486*0a6a1f1dSLionel Sambuc
2487*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPWriteClause(OMPWriteClause *)2488*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) {
2489*0a6a1f1dSLionel Sambuc return true;
2490*0a6a1f1dSLionel Sambuc }
2491*0a6a1f1dSLionel Sambuc
2492*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPUpdateClause(OMPUpdateClause *)2493*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) {
2494*0a6a1f1dSLionel Sambuc return true;
2495*0a6a1f1dSLionel Sambuc }
2496*0a6a1f1dSLionel Sambuc
2497*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPCaptureClause(OMPCaptureClause *)2498*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
2499*0a6a1f1dSLionel Sambuc return true;
2500*0a6a1f1dSLionel Sambuc }
2501*0a6a1f1dSLionel Sambuc
2502*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPSeqCstClause(OMPSeqCstClause *)2503*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
2504f4a2713aSLionel Sambuc return true;
2505f4a2713aSLionel Sambuc }
2506f4a2713aSLionel Sambuc
2507f4a2713aSLionel Sambuc template <typename Derived>
2508f4a2713aSLionel Sambuc template <typename T>
VisitOMPClauseList(T * Node)2509*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
2510*0a6a1f1dSLionel Sambuc for (auto *E : Node->varlists()) {
2511*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(E));
2512*0a6a1f1dSLionel Sambuc }
2513*0a6a1f1dSLionel Sambuc return true;
2514f4a2713aSLionel Sambuc }
2515f4a2713aSLionel Sambuc
2516f4a2713aSLionel Sambuc template <typename Derived>
VisitOMPPrivateClause(OMPPrivateClause * C)2517f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
2518*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2519*0a6a1f1dSLionel Sambuc for (auto *E : C->private_copies()) {
2520*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(E));
2521*0a6a1f1dSLionel Sambuc }
2522f4a2713aSLionel Sambuc return true;
2523f4a2713aSLionel Sambuc }
2524f4a2713aSLionel Sambuc
2525f4a2713aSLionel Sambuc template <typename Derived>
VisitOMPFirstprivateClause(OMPFirstprivateClause * C)2526f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
2527f4a2713aSLionel Sambuc OMPFirstprivateClause *C) {
2528*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2529*0a6a1f1dSLionel Sambuc for (auto *E : C->private_copies()) {
2530*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(E));
2531*0a6a1f1dSLionel Sambuc }
2532*0a6a1f1dSLionel Sambuc for (auto *E : C->inits()) {
2533*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(E));
2534*0a6a1f1dSLionel Sambuc }
2535*0a6a1f1dSLionel Sambuc return true;
2536*0a6a1f1dSLionel Sambuc }
2537*0a6a1f1dSLionel Sambuc
2538*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPLastprivateClause(OMPLastprivateClause * C)2539*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
2540*0a6a1f1dSLionel Sambuc OMPLastprivateClause *C) {
2541*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2542f4a2713aSLionel Sambuc return true;
2543f4a2713aSLionel Sambuc }
2544f4a2713aSLionel Sambuc
2545f4a2713aSLionel Sambuc template <typename Derived>
VisitOMPSharedClause(OMPSharedClause * C)2546f4a2713aSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
2547*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2548*0a6a1f1dSLionel Sambuc return true;
2549*0a6a1f1dSLionel Sambuc }
2550*0a6a1f1dSLionel Sambuc
2551*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPLinearClause(OMPLinearClause * C)2552*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
2553*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getStep()));
2554*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2555*0a6a1f1dSLionel Sambuc return true;
2556*0a6a1f1dSLionel Sambuc }
2557*0a6a1f1dSLionel Sambuc
2558*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPAlignedClause(OMPAlignedClause * C)2559*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) {
2560*0a6a1f1dSLionel Sambuc TRY_TO(TraverseStmt(C->getAlignment()));
2561*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2562*0a6a1f1dSLionel Sambuc return true;
2563*0a6a1f1dSLionel Sambuc }
2564*0a6a1f1dSLionel Sambuc
2565*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPCopyinClause(OMPCopyinClause * C)2566*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
2567*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2568*0a6a1f1dSLionel Sambuc return true;
2569*0a6a1f1dSLionel Sambuc }
2570*0a6a1f1dSLionel Sambuc
2571*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPCopyprivateClause(OMPCopyprivateClause * C)2572*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
2573*0a6a1f1dSLionel Sambuc OMPCopyprivateClause *C) {
2574*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2575*0a6a1f1dSLionel Sambuc return true;
2576*0a6a1f1dSLionel Sambuc }
2577*0a6a1f1dSLionel Sambuc
2578*0a6a1f1dSLionel Sambuc template <typename Derived>
2579*0a6a1f1dSLionel Sambuc bool
VisitOMPReductionClause(OMPReductionClause * C)2580*0a6a1f1dSLionel Sambuc RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
2581*0a6a1f1dSLionel Sambuc TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
2582*0a6a1f1dSLionel Sambuc TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
2583*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2584*0a6a1f1dSLionel Sambuc return true;
2585*0a6a1f1dSLionel Sambuc }
2586*0a6a1f1dSLionel Sambuc
2587*0a6a1f1dSLionel Sambuc template <typename Derived>
VisitOMPFlushClause(OMPFlushClause * C)2588*0a6a1f1dSLionel Sambuc bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
2589*0a6a1f1dSLionel Sambuc TRY_TO(VisitOMPClauseList(C));
2590f4a2713aSLionel Sambuc return true;
2591f4a2713aSLionel Sambuc }
2592f4a2713aSLionel Sambuc
2593f4a2713aSLionel Sambuc // FIXME: look at the following tricky-seeming exprs to see if we
2594f4a2713aSLionel Sambuc // need to recurse on anything. These are ones that have methods
2595f4a2713aSLionel Sambuc // returning decls or qualtypes or nestednamespecifier -- though I'm
2596f4a2713aSLionel Sambuc // not sure if they own them -- or just seemed very complicated, or
2597f4a2713aSLionel Sambuc // had lots of sub-types to explore.
2598f4a2713aSLionel Sambuc //
2599f4a2713aSLionel Sambuc // VisitOverloadExpr and its children: recurse on template args? etc?
2600f4a2713aSLionel Sambuc
2601f4a2713aSLionel Sambuc // FIXME: go through all the stmts and exprs again, and see which of them
2602f4a2713aSLionel Sambuc // create new types, and recurse on the types (TypeLocs?) of those.
2603f4a2713aSLionel Sambuc // Candidates:
2604f4a2713aSLionel Sambuc //
2605f4a2713aSLionel Sambuc // http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
2606f4a2713aSLionel Sambuc // http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html
2607f4a2713aSLionel Sambuc // http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
2608f4a2713aSLionel Sambuc // Every class that has getQualifier.
2609f4a2713aSLionel Sambuc
2610f4a2713aSLionel Sambuc #undef DEF_TRAVERSE_STMT
2611f4a2713aSLionel Sambuc
2612f4a2713aSLionel Sambuc #undef TRY_TO
2613f4a2713aSLionel Sambuc
2614f4a2713aSLionel Sambuc } // end namespace clang
2615f4a2713aSLionel Sambuc
2616f4a2713aSLionel Sambuc #endif // LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
2617