1 | //===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines the RecursiveASTVisitor interface, which recursively |
10 | // traverses the entire AST. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H |
14 | #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H |
15 | |
16 | #include "clang/AST/Attr.h" |
17 | #include "clang/AST/Decl.h" |
18 | #include "clang/AST/DeclarationName.h" |
19 | #include "clang/AST/DeclBase.h" |
20 | #include "clang/AST/DeclCXX.h" |
21 | #include "clang/AST/DeclFriend.h" |
22 | #include "clang/AST/DeclObjC.h" |
23 | #include "clang/AST/DeclOpenMP.h" |
24 | #include "clang/AST/DeclTemplate.h" |
25 | #include "clang/AST/Expr.h" |
26 | #include "clang/AST/ExprConcepts.h" |
27 | #include "clang/AST/ExprCXX.h" |
28 | #include "clang/AST/ExprObjC.h" |
29 | #include "clang/AST/ExprOpenMP.h" |
30 | #include "clang/AST/LambdaCapture.h" |
31 | #include "clang/AST/NestedNameSpecifier.h" |
32 | #include "clang/AST/OpenMPClause.h" |
33 | #include "clang/AST/Stmt.h" |
34 | #include "clang/AST/StmtCXX.h" |
35 | #include "clang/AST/StmtObjC.h" |
36 | #include "clang/AST/StmtOpenMP.h" |
37 | #include "clang/AST/TemplateBase.h" |
38 | #include "clang/AST/TemplateName.h" |
39 | #include "clang/AST/Type.h" |
40 | #include "clang/AST/TypeLoc.h" |
41 | #include "clang/Basic/LLVM.h" |
42 | #include "clang/Basic/OpenMPKinds.h" |
43 | #include "clang/Basic/Specifiers.h" |
44 | #include "llvm/ADT/PointerIntPair.h" |
45 | #include "llvm/ADT/SmallVector.h" |
46 | #include "llvm/Support/Casting.h" |
47 | #include <algorithm> |
48 | #include <cstddef> |
49 | #include <type_traits> |
50 | |
51 | // The following three macros are used for meta programming. The code |
52 | // using them is responsible for defining macro OPERATOR(). |
53 | |
54 | // All unary operators. |
55 | #define UNARYOP_LIST() \ |
56 | OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \ |
57 | OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \ |
58 | OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \ |
59 | OPERATOR(Extension) OPERATOR(Coawait) |
60 | |
61 | // All binary operators (excluding compound assign operators). |
62 | #define BINOP_LIST() \ |
63 | OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \ |
64 | OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \ |
65 | OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \ |
66 | OPERATOR(NE) OPERATOR(Cmp) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \ |
67 | OPERATOR(LAnd) OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) |
68 | |
69 | // All compound assign operators. |
70 | #define CAO_LIST() \ |
71 | OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ |
72 | OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) |
73 | |
74 | namespace clang { |
75 | |
76 | // A helper macro to implement short-circuiting when recursing. It |
77 | // invokes CALL_EXPR, which must be a method call, on the derived |
78 | // object (s.t. a user of RecursiveASTVisitor can override the method |
79 | // in CALL_EXPR). |
80 | #define TRY_TO(CALL_EXPR) \ |
81 | do { \ |
82 | if (!getDerived().CALL_EXPR) \ |
83 | return false; \ |
84 | } while (false) |
85 | |
86 | /// A class that does preorder or postorder |
87 | /// depth-first traversal on the entire Clang AST and visits each node. |
88 | /// |
89 | /// This class performs three distinct tasks: |
90 | /// 1. traverse the AST (i.e. go to each node); |
91 | /// 2. at a given node, walk up the class hierarchy, starting from |
92 | /// the node's dynamic type, until the top-most class (e.g. Stmt, |
93 | /// Decl, or Type) is reached. |
94 | /// 3. given a (node, class) combination, where 'class' is some base |
95 | /// class of the dynamic type of 'node', call a user-overridable |
96 | /// function to actually visit the node. |
97 | /// |
98 | /// These tasks are done by three groups of methods, respectively: |
99 | /// 1. TraverseDecl(Decl *x) does task #1. It is the entry point |
100 | /// for traversing an AST rooted at x. This method simply |
101 | /// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo |
102 | /// is the dynamic type of *x, which calls WalkUpFromFoo(x) and |
103 | /// then recursively visits the child nodes of x. |
104 | /// TraverseStmt(Stmt *x) and TraverseType(QualType x) work |
105 | /// similarly. |
106 | /// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit |
107 | /// any child node of x. Instead, it first calls WalkUpFromBar(x) |
108 | /// where Bar is the direct parent class of Foo (unless Foo has |
109 | /// no parent), and then calls VisitFoo(x) (see the next list item). |
110 | /// 3. VisitFoo(Foo *x) does task #3. |
111 | /// |
112 | /// These three method groups are tiered (Traverse* > WalkUpFrom* > |
113 | /// Visit*). A method (e.g. Traverse*) may call methods from the same |
114 | /// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). |
115 | /// It may not call methods from a higher tier. |
116 | /// |
117 | /// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar |
118 | /// is Foo's super class) before calling VisitFoo(), the result is |
119 | /// that the Visit*() methods for a given node are called in the |
120 | /// top-down order (e.g. for a node of type NamespaceDecl, the order will |
121 | /// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). |
122 | /// |
123 | /// This scheme guarantees that all Visit*() calls for the same AST |
124 | /// node are grouped together. In other words, Visit*() methods for |
125 | /// different nodes are never interleaved. |
126 | /// |
127 | /// Clients of this visitor should subclass the visitor (providing |
128 | /// themselves as the template argument, using the curiously recurring |
129 | /// template pattern) and override any of the Traverse*, WalkUpFrom*, |
130 | /// and Visit* methods for declarations, types, statements, |
131 | /// expressions, or other AST nodes where the visitor should customize |
132 | /// behavior. Most users only need to override Visit*. Advanced |
133 | /// users may override Traverse* and WalkUpFrom* to implement custom |
134 | /// traversal strategies. Returning false from one of these overridden |
135 | /// functions will abort the entire traversal. |
136 | /// |
137 | /// By default, this visitor tries to visit every part of the explicit |
138 | /// source code exactly once. The default policy towards templates |
139 | /// is to descend into the 'pattern' class or function body, not any |
140 | /// explicit or implicit instantiations. Explicit specializations |
141 | /// are still visited, and the patterns of partial specializations |
142 | /// are visited separately. This behavior can be changed by |
143 | /// overriding shouldVisitTemplateInstantiations() in the derived class |
144 | /// to return true, in which case all known implicit and explicit |
145 | /// instantiations will be visited at the same time as the pattern |
146 | /// from which they were produced. |
147 | /// |
148 | /// By default, this visitor preorder traverses the AST. If postorder traversal |
149 | /// is needed, the \c shouldTraversePostOrder method needs to be overridden |
150 | /// to return \c true. |
151 | template <typename Derived> class RecursiveASTVisitor { |
152 | public: |
153 | /// A queue used for performing data recursion over statements. |
154 | /// Parameters involving this type are used to implement data |
155 | /// recursion over Stmts and Exprs within this class, and should |
156 | /// typically not be explicitly specified by derived classes. |
157 | /// The bool bit indicates whether the statement has been traversed or not. |
158 | typedef SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>> |
159 | DataRecursionQueue; |
160 | |
161 | /// Return a reference to the derived class. |
162 | Derived &getDerived() { return *static_cast<Derived *>(this); } |
163 | |
164 | /// Return whether this visitor should recurse into |
165 | /// template instantiations. |
166 | bool shouldVisitTemplateInstantiations() const { return false; } |
167 | |
168 | /// Return whether this visitor should recurse into the types of |
169 | /// TypeLocs. |
170 | bool shouldWalkTypesOfTypeLocs() const { return true; } |
171 | |
172 | /// Return whether this visitor should recurse into implicit |
173 | /// code, e.g., implicit constructors and destructors. |
174 | bool shouldVisitImplicitCode() const { return false; } |
175 | |
176 | /// Return whether this visitor should traverse post-order. |
177 | bool shouldTraversePostOrder() const { return false; } |
178 | |
179 | /// Recursively visits an entire AST, starting from the top-level Decls |
180 | /// in the AST traversal scope (by default, the TranslationUnitDecl). |
181 | /// \returns false if visitation was terminated early. |
182 | bool TraverseAST(ASTContext &AST) { |
183 | for (Decl *D : AST.getTraversalScope()) |
184 | if (!getDerived().TraverseDecl(D)) |
185 | return false; |
186 | return true; |
187 | } |
188 | |
189 | /// Recursively visit a statement or expression, by |
190 | /// dispatching to Traverse*() based on the argument's dynamic type. |
191 | /// |
192 | /// \returns false if the visitation was terminated early, true |
193 | /// otherwise (including when the argument is nullptr). |
194 | bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr); |
195 | |
196 | /// Invoked before visiting a statement or expression via data recursion. |
197 | /// |
198 | /// \returns false to skip visiting the node, true otherwise. |
199 | bool dataTraverseStmtPre(Stmt *S) { return true; } |
200 | |
201 | /// Invoked after visiting a statement or expression via data recursion. |
202 | /// This is not invoked if the previously invoked \c dataTraverseStmtPre |
203 | /// returned false. |
204 | /// |
205 | /// \returns false if the visitation was terminated early, true otherwise. |
206 | bool dataTraverseStmtPost(Stmt *S) { return true; } |
207 | |
208 | /// Recursively visit a type, by dispatching to |
209 | /// Traverse*Type() based on the argument's getTypeClass() property. |
210 | /// |
211 | /// \returns false if the visitation was terminated early, true |
212 | /// otherwise (including when the argument is a Null type). |
213 | bool TraverseType(QualType T); |
214 | |
215 | /// Recursively visit a type with location, by dispatching to |
216 | /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. |
217 | /// |
218 | /// \returns false if the visitation was terminated early, true |
219 | /// otherwise (including when the argument is a Null type location). |
220 | bool TraverseTypeLoc(TypeLoc TL); |
221 | |
222 | /// Recursively visit an attribute, by dispatching to |
223 | /// Traverse*Attr() based on the argument's dynamic type. |
224 | /// |
225 | /// \returns false if the visitation was terminated early, true |
226 | /// otherwise (including when the argument is a Null type location). |
227 | bool TraverseAttr(Attr *At); |
228 | |
229 | /// Recursively visit a declaration, by dispatching to |
230 | /// Traverse*Decl() based on the argument's dynamic type. |
231 | /// |
232 | /// \returns false if the visitation was terminated early, true |
233 | /// otherwise (including when the argument is NULL). |
234 | bool TraverseDecl(Decl *D); |
235 | |
236 | /// Recursively visit a C++ nested-name-specifier. |
237 | /// |
238 | /// \returns false if the visitation was terminated early, true otherwise. |
239 | bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); |
240 | |
241 | /// Recursively visit a C++ nested-name-specifier with location |
242 | /// information. |
243 | /// |
244 | /// \returns false if the visitation was terminated early, true otherwise. |
245 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); |
246 | |
247 | /// Recursively visit a name with its location information. |
248 | /// |
249 | /// \returns false if the visitation was terminated early, true otherwise. |
250 | bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); |
251 | |
252 | /// Recursively visit a template name and dispatch to the |
253 | /// appropriate method. |
254 | /// |
255 | /// \returns false if the visitation was terminated early, true otherwise. |
256 | bool TraverseTemplateName(TemplateName Template); |
257 | |
258 | /// Recursively visit a template argument and dispatch to the |
259 | /// appropriate method for the argument type. |
260 | /// |
261 | /// \returns false if the visitation was terminated early, true otherwise. |
262 | // FIXME: migrate callers to TemplateArgumentLoc instead. |
263 | bool TraverseTemplateArgument(const TemplateArgument &Arg); |
264 | |
265 | /// Recursively visit a template argument location and dispatch to the |
266 | /// appropriate method for the argument type. |
267 | /// |
268 | /// \returns false if the visitation was terminated early, true otherwise. |
269 | bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); |
270 | |
271 | /// Recursively visit a set of template arguments. |
272 | /// This can be overridden by a subclass, but it's not expected that |
273 | /// will be needed -- this visitor always dispatches to another. |
274 | /// |
275 | /// \returns false if the visitation was terminated early, true otherwise. |
276 | // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. |
277 | bool TraverseTemplateArguments(const TemplateArgument *Args, |
278 | unsigned NumArgs); |
279 | |
280 | /// Recursively visit a base specifier. This can be overridden by a |
281 | /// subclass. |
282 | /// |
283 | /// \returns false if the visitation was terminated early, true otherwise. |
284 | bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base); |
285 | |
286 | /// Recursively visit a constructor initializer. This |
287 | /// automatically dispatches to another visitor for the initializer |
288 | /// expression, but not for the name of the initializer, so may |
289 | /// be overridden for clients that need access to the name. |
290 | /// |
291 | /// \returns false if the visitation was terminated early, true otherwise. |
292 | bool TraverseConstructorInitializer(CXXCtorInitializer *Init); |
293 | |
294 | /// Recursively visit a lambda capture. \c Init is the expression that |
295 | /// will be used to initialize the capture. |
296 | /// |
297 | /// \returns false if the visitation was terminated early, true otherwise. |
298 | bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, |
299 | Expr *Init); |
300 | |
301 | /// Recursively visit the syntactic or semantic form of an |
302 | /// initialization list. |
303 | /// |
304 | /// \returns false if the visitation was terminated early, true otherwise. |
305 | bool TraverseSynOrSemInitListExpr(InitListExpr *S, |
306 | DataRecursionQueue *Queue = nullptr); |
307 | |
308 | /// Recursively visit a reference to a concept with potential arguments. |
309 | /// |
310 | /// \returns false if the visitation was terminated early, true otherwise. |
311 | bool TraverseConceptReference(const ConceptReference &C); |
312 | |
313 | // ---- Methods on Attrs ---- |
314 | |
315 | // Visit an attribute. |
316 | bool VisitAttr(Attr *A) { return true; } |
317 | |
318 | // Declare Traverse* and empty Visit* for all Attr classes. |
319 | #define ATTR_VISITOR_DECLS_ONLY |
320 | #include "clang/AST/AttrVisitor.inc" |
321 | #undef ATTR_VISITOR_DECLS_ONLY |
322 | |
323 | // ---- Methods on Stmts ---- |
324 | |
325 | Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } |
326 | |
327 | private: |
328 | template<typename T, typename U> |
329 | struct has_same_member_pointer_type : std::false_type {}; |
330 | template<typename T, typename U, typename R, typename... P> |
331 | struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> |
332 | : std::true_type {}; |
333 | |
334 | // Traverse the given statement. If the most-derived traverse function takes a |
335 | // data recursion queue, pass it on; otherwise, discard it. Note that the |
336 | // first branch of this conditional must compile whether or not the derived |
337 | // class can take a queue, so if we're taking the second arm, make the first |
338 | // arm call our function rather than the derived class version. |
339 | #define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \ |
340 | (has_same_member_pointer_type<decltype( \ |
341 | &RecursiveASTVisitor::Traverse##NAME), \ |
342 | decltype(&Derived::Traverse##NAME)>::value \ |
343 | ? static_cast<std::conditional_t< \ |
344 | has_same_member_pointer_type< \ |
345 | decltype(&RecursiveASTVisitor::Traverse##NAME), \ |
346 | decltype(&Derived::Traverse##NAME)>::value, \ |
347 | Derived &, RecursiveASTVisitor &>>(*this) \ |
348 | .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \ |
349 | : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))) |
350 | |
351 | // Try to traverse the given statement, or enqueue it if we're performing data |
352 | // recursion in the middle of traversing another statement. Can only be called |
353 | // from within a DEF_TRAVERSE_STMT body or similar context. |
354 | #define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \ |
355 | do { \ |
356 | if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \ |
357 | return false; \ |
358 | } while (false) |
359 | |
360 | public: |
361 | // Declare Traverse*() for all concrete Stmt classes. |
362 | #define ABSTRACT_STMT(STMT) |
363 | #define STMT(CLASS, PARENT) \ |
364 | bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr); |
365 | #include "clang/AST/StmtNodes.inc" |
366 | // The above header #undefs ABSTRACT_STMT and STMT upon exit. |
367 | |
368 | // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. |
369 | bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } |
370 | bool VisitStmt(Stmt *S) { return true; } |
371 | #define STMT(CLASS, PARENT) \ |
372 | bool WalkUpFrom##CLASS(CLASS *S) { \ |
373 | TRY_TO(WalkUpFrom##PARENT(S)); \ |
374 | TRY_TO(Visit##CLASS(S)); \ |
375 | return true; \ |
376 | } \ |
377 | bool Visit##CLASS(CLASS *S) { return true; } |
378 | #include "clang/AST/StmtNodes.inc" |
379 | |
380 | // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary |
381 | // operator methods. Unary operators are not classes in themselves |
382 | // (they're all opcodes in UnaryOperator) but do have visitors. |
383 | #define OPERATOR(NAME) \ |
384 | bool TraverseUnary##NAME(UnaryOperator *S, \ |
385 | DataRecursionQueue *Queue = nullptr) { \ |
386 | if (!getDerived().shouldTraversePostOrder()) \ |
387 | TRY_TO(WalkUpFromUnary##NAME(S)); \ |
388 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \ |
389 | return true; \ |
390 | } \ |
391 | bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ |
392 | TRY_TO(WalkUpFromUnaryOperator(S)); \ |
393 | TRY_TO(VisitUnary##NAME(S)); \ |
394 | return true; \ |
395 | } \ |
396 | bool VisitUnary##NAME(UnaryOperator *S) { return true; } |
397 | |
398 | UNARYOP_LIST() |
399 | #undef OPERATOR |
400 | |
401 | // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary |
402 | // operator methods. Binary operators are not classes in themselves |
403 | // (they're all opcodes in BinaryOperator) but do have visitors. |
404 | #define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ |
405 | bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \ |
406 | if (!getDerived().shouldTraversePostOrder()) \ |
407 | TRY_TO(WalkUpFromBin##NAME(S)); \ |
408 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \ |
409 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \ |
410 | return true; \ |
411 | } \ |
412 | bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ |
413 | TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ |
414 | TRY_TO(VisitBin##NAME(S)); \ |
415 | return true; \ |
416 | } \ |
417 | bool VisitBin##NAME(BINOP_TYPE *S) { return true; } |
418 | |
419 | #define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) |
420 | BINOP_LIST() |
421 | #undef OPERATOR |
422 | |
423 | // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound |
424 | // assignment methods. Compound assignment operators are not |
425 | // classes in themselves (they're all opcodes in |
426 | // CompoundAssignOperator) but do have visitors. |
427 | #define OPERATOR(NAME) \ |
428 | GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) |
429 | |
430 | CAO_LIST() |
431 | #undef OPERATOR |
432 | #undef GENERAL_BINOP_FALLBACK |
433 | |
434 | // ---- Methods on Types ---- |
435 | // FIXME: revamp to take TypeLoc's rather than Types. |
436 | |
437 | // Declare Traverse*() for all concrete Type classes. |
438 | #define ABSTRACT_TYPE(CLASS, BASE) |
439 | #define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); |
440 | #include "clang/AST/TypeNodes.inc" |
441 | // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. |
442 | |
443 | // Define WalkUpFrom*() and empty Visit*() for all Type classes. |
444 | bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } |
445 | bool VisitType(Type *T) { return true; } |
446 | #define TYPE(CLASS, BASE) \ |
447 | bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ |
448 | TRY_TO(WalkUpFrom##BASE(T)); \ |
449 | TRY_TO(Visit##CLASS##Type(T)); \ |
450 | return true; \ |
451 | } \ |
452 | bool Visit##CLASS##Type(CLASS##Type *T) { return true; } |
453 | #include "clang/AST/TypeNodes.inc" |
454 | |
455 | // ---- Methods on TypeLocs ---- |
456 | // FIXME: this currently just calls the matching Type methods |
457 | |
458 | // Declare Traverse*() for all concrete TypeLoc classes. |
459 | #define ABSTRACT_TYPELOC(CLASS, BASE) |
460 | #define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); |
461 | #include "clang/AST/TypeLocNodes.def" |
462 | // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. |
463 | |
464 | // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. |
465 | bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } |
466 | bool VisitTypeLoc(TypeLoc TL) { return true; } |
467 | |
468 | // QualifiedTypeLoc and UnqualTypeLoc are not declared in |
469 | // TypeNodes.inc and thus need to be handled specially. |
470 | bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { |
471 | return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); |
472 | } |
473 | bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } |
474 | bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { |
475 | return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); |
476 | } |
477 | bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } |
478 | |
479 | // Note that BASE includes trailing 'Type' which CLASS doesn't. |
480 | #define TYPE(CLASS, BASE) \ |
481 | bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ |
482 | TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ |
483 | TRY_TO(Visit##CLASS##TypeLoc(TL)); \ |
484 | return true; \ |
485 | } \ |
486 | bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } |
487 | #include "clang/AST/TypeNodes.inc" |
488 | |
489 | // ---- Methods on Decls ---- |
490 | |
491 | // Declare Traverse*() for all concrete Decl classes. |
492 | #define ABSTRACT_DECL(DECL) |
493 | #define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D); |
494 | #include "clang/AST/DeclNodes.inc" |
495 | // The above header #undefs ABSTRACT_DECL and DECL upon exit. |
496 | |
497 | // Define WalkUpFrom*() and empty Visit*() for all Decl classes. |
498 | bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } |
499 | bool VisitDecl(Decl *D) { return true; } |
500 | #define DECL(CLASS, BASE) \ |
501 | bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ |
502 | TRY_TO(WalkUpFrom##BASE(D)); \ |
503 | TRY_TO(Visit##CLASS##Decl(D)); \ |
504 | return true; \ |
505 | } \ |
506 | bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } |
507 | #include "clang/AST/DeclNodes.inc" |
508 | |
509 | bool canIgnoreChildDeclWhileTraversingDeclContext(const Decl *Child); |
510 | |
511 | private: |
512 | // These are helper methods used by more than one Traverse* method. |
513 | bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); |
514 | |
515 | // Traverses template parameter lists of either a DeclaratorDecl or TagDecl. |
516 | template <typename T> |
517 | bool TraverseDeclTemplateParameterLists(T *D); |
518 | |
519 | #define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ |
520 | bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D); |
521 | DEF_TRAVERSE_TMPL_INST(Class) |
522 | DEF_TRAVERSE_TMPL_INST(Var) |
523 | DEF_TRAVERSE_TMPL_INST(Function) |
524 | #undef DEF_TRAVERSE_TMPL_INST |
525 | bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, |
526 | unsigned Count); |
527 | bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); |
528 | bool TraverseRecordHelper(RecordDecl *D); |
529 | bool TraverseCXXRecordHelper(CXXRecordDecl *D); |
530 | bool TraverseDeclaratorHelper(DeclaratorDecl *D); |
531 | bool TraverseDeclContextHelper(DeclContext *DC); |
532 | bool TraverseFunctionHelper(FunctionDecl *D); |
533 | bool TraverseVarHelper(VarDecl *D); |
534 | bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); |
535 | bool TraverseOMPLoopDirective(OMPLoopDirective *S); |
536 | bool TraverseOMPClause(OMPClause *C); |
537 | #define OMP_CLAUSE_CLASS(Enum, Str, Class) bool Visit##Class(Class *C); |
538 | #include "llvm/Frontend/OpenMP/OMPKinds.def" |
539 | /// Process clauses with list of variables. |
540 | template <typename T> bool VisitOMPClauseList(T *Node); |
541 | /// Process clauses with pre-initis. |
542 | bool VisitOMPClauseWithPreInit(OMPClauseWithPreInit *Node); |
543 | bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node); |
544 | |
545 | bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); |
546 | bool PostVisitStmt(Stmt *S); |
547 | }; |
548 | |
549 | template <typename Derived> |
550 | bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, |
551 | DataRecursionQueue *Queue) { |
552 | #define DISPATCH_STMT(NAME, CLASS, VAR) \ |
553 | return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue); |
554 | |
555 | // If we have a binary expr, dispatch to the subcode of the binop. A smart |
556 | // optimizer (e.g. LLVM) will fold this comparison into the switch stmt |
557 | // below. |
558 | if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { |
559 | switch (BinOp->getOpcode()) { |
560 | #define OPERATOR(NAME) \ |
561 | case BO_##NAME: \ |
562 | DISPATCH_STMT(Bin##NAME, BinaryOperator, S); |
563 | |
564 | BINOP_LIST() |
565 | #undef OPERATOR |
566 | #undef BINOP_LIST |
567 | |
568 | #define OPERATOR(NAME) \ |
569 | case BO_##NAME##Assign: \ |
570 | DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); |
571 | |
572 | CAO_LIST() |
573 | #undef OPERATOR |
574 | #undef CAO_LIST |
575 | } |
576 | } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { |
577 | switch (UnOp->getOpcode()) { |
578 | #define OPERATOR(NAME) \ |
579 | case UO_##NAME: \ |
580 | DISPATCH_STMT(Unary##NAME, UnaryOperator, S); |
581 | |
582 | UNARYOP_LIST() |
583 | #undef OPERATOR |
584 | #undef UNARYOP_LIST |
585 | } |
586 | } |
587 | |
588 | // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. |
589 | switch (S->getStmtClass()) { |
590 | case Stmt::NoStmtClass: |
591 | break; |
592 | #define ABSTRACT_STMT(STMT) |
593 | #define STMT(CLASS, PARENT) \ |
594 | case Stmt::CLASS##Class: \ |
595 | DISPATCH_STMT(CLASS, CLASS, S); |
596 | #include "clang/AST/StmtNodes.inc" |
597 | } |
598 | |
599 | return true; |
600 | } |
601 | |
602 | #undef DISPATCH_STMT |
603 | |
604 | template <typename Derived> |
605 | bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) { |
606 | switch (S->getStmtClass()) { |
607 | case Stmt::NoStmtClass: |
608 | break; |
609 | #define ABSTRACT_STMT(STMT) |
610 | #define STMT(CLASS, PARENT) \ |
611 | case Stmt::CLASS##Class: \ |
612 | TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break; |
613 | #define INITLISTEXPR(CLASS, PARENT) \ |
614 | case Stmt::CLASS##Class: \ |
615 | { \ |
616 | auto ILE = static_cast<CLASS *>(S); \ |
617 | if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \ |
618 | TRY_TO(WalkUpFrom##CLASS(Syn)); \ |
619 | if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \ |
620 | TRY_TO(WalkUpFrom##CLASS(Sem)); \ |
621 | break; \ |
622 | } |
623 | #include "clang/AST/StmtNodes.inc" |
624 | } |
625 | |
626 | return true; |
627 | } |
628 | |
629 | #undef DISPATCH_STMT |
630 | |
631 | template <typename Derived> |
632 | bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S, |
633 | DataRecursionQueue *Queue) { |
634 | if (!S) |
635 | return true; |
636 | |
637 | if (Queue) { |
638 | Queue->push_back({S, false}); |
639 | return true; |
640 | } |
641 | |
642 | SmallVector<llvm::PointerIntPair<Stmt *, 1, bool>, 8> LocalQueue; |
643 | LocalQueue.push_back({S, false}); |
644 | |
645 | while (!LocalQueue.empty()) { |
646 | auto &CurrSAndVisited = LocalQueue.back(); |
647 | Stmt *CurrS = CurrSAndVisited.getPointer(); |
648 | bool Visited = CurrSAndVisited.getInt(); |
649 | if (Visited) { |
650 | LocalQueue.pop_back(); |
651 | TRY_TO(dataTraverseStmtPost(CurrS)); |
652 | if (getDerived().shouldTraversePostOrder()) { |
653 | TRY_TO(PostVisitStmt(CurrS)); |
654 | } |
655 | continue; |
656 | } |
657 | |
658 | if (getDerived().dataTraverseStmtPre(CurrS)) { |
659 | CurrSAndVisited.setInt(true); |
660 | size_t N = LocalQueue.size(); |
661 | TRY_TO(dataTraverseNode(CurrS, &LocalQueue)); |
662 | // Process new children in the order they were added. |
663 | std::reverse(LocalQueue.begin() + N, LocalQueue.end()); |
664 | } else { |
665 | LocalQueue.pop_back(); |
666 | } |
667 | } |
668 | |
669 | return true; |
670 | } |
671 | |
672 | #define DISPATCH(NAME, CLASS, VAR) \ |
673 | return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) |
674 | |
675 | template <typename Derived> |
676 | bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { |
677 | if (T.isNull()) |
678 | return true; |
679 | |
680 | switch (T->getTypeClass()) { |
681 | #define ABSTRACT_TYPE(CLASS, BASE) |
682 | #define TYPE(CLASS, BASE) \ |
683 | case Type::CLASS: \ |
684 | DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr())); |
685 | #include "clang/AST/TypeNodes.inc" |
686 | } |
687 | |
688 | return true; |
689 | } |
690 | |
691 | template <typename Derived> |
692 | bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { |
693 | if (TL.isNull()) |
694 | return true; |
695 | |
696 | switch (TL.getTypeLocClass()) { |
697 | #define ABSTRACT_TYPELOC(CLASS, BASE) |
698 | #define TYPELOC(CLASS, BASE) \ |
699 | case TypeLoc::CLASS: \ |
700 | return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); |
701 | #include "clang/AST/TypeLocNodes.def" |
702 | } |
703 | |
704 | return true; |
705 | } |
706 | |
707 | // Define the Traverse*Attr(Attr* A) methods |
708 | #define VISITORCLASS RecursiveASTVisitor |
709 | #include "clang/AST/AttrVisitor.inc" |
710 | #undef VISITORCLASS |
711 | |
712 | template <typename Derived> |
713 | bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { |
714 | if (!D) |
715 | return true; |
716 | |
717 | // As a syntax visitor, by default we want to ignore declarations for |
718 | // implicit declarations (ones not typed explicitly by the user). |
719 | if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) |
720 | return true; |
721 | |
722 | switch (D->getKind()) { |
723 | #define ABSTRACT_DECL(DECL) |
724 | #define DECL(CLASS, BASE) \ |
725 | case Decl::CLASS: \ |
726 | if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \ |
727 | return false; \ |
728 | break; |
729 | #include "clang/AST/DeclNodes.inc" |
730 | } |
731 | return true; |
732 | } |
733 | |
734 | #undef DISPATCH |
735 | |
736 | template <typename Derived> |
737 | bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( |
738 | NestedNameSpecifier *NNS) { |
739 | if (!NNS) |
740 | return true; |
741 | |
742 | if (NNS->getPrefix()) |
743 | TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); |
744 | |
745 | switch (NNS->getKind()) { |
746 | case NestedNameSpecifier::Identifier: |
747 | case NestedNameSpecifier::Namespace: |
748 | case NestedNameSpecifier::NamespaceAlias: |
749 | case NestedNameSpecifier::Global: |
750 | case NestedNameSpecifier::Super: |
751 | return true; |
752 | |
753 | case NestedNameSpecifier::TypeSpec: |
754 | case NestedNameSpecifier::TypeSpecWithTemplate: |
755 | TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); |
756 | } |
757 | |
758 | return true; |
759 | } |
760 | |
761 | template <typename Derived> |
762 | bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( |
763 | NestedNameSpecifierLoc NNS) { |
764 | if (!NNS) |
765 | return true; |
766 | |
767 | if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) |
768 | TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); |
769 | |
770 | switch (NNS.getNestedNameSpecifier()->getKind()) { |
771 | case NestedNameSpecifier::Identifier: |
772 | case NestedNameSpecifier::Namespace: |
773 | case NestedNameSpecifier::NamespaceAlias: |
774 | case NestedNameSpecifier::Global: |
775 | case NestedNameSpecifier::Super: |
776 | return true; |
777 | |
778 | case NestedNameSpecifier::TypeSpec: |
779 | case NestedNameSpecifier::TypeSpecWithTemplate: |
780 | TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); |
781 | break; |
782 | } |
783 | |
784 | return true; |
785 | } |
786 | |
787 | template <typename Derived> |
788 | bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( |
789 | DeclarationNameInfo NameInfo) { |
790 | switch (NameInfo.getName().getNameKind()) { |
791 | case DeclarationName::CXXConstructorName: |
792 | case DeclarationName::CXXDestructorName: |
793 | case DeclarationName::CXXConversionFunctionName: |
794 | if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) |
795 | TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); |
796 | break; |
797 | |
798 | case DeclarationName::CXXDeductionGuideName: |
799 | TRY_TO(TraverseTemplateName( |
800 | TemplateName(NameInfo.getName().getCXXDeductionGuideTemplate()))); |
801 | break; |
802 | |
803 | case DeclarationName::Identifier: |
804 | case DeclarationName::ObjCZeroArgSelector: |
805 | case DeclarationName::ObjCOneArgSelector: |
806 | case DeclarationName::ObjCMultiArgSelector: |
807 | case DeclarationName::CXXOperatorName: |
808 | case DeclarationName::CXXLiteralOperatorName: |
809 | case DeclarationName::CXXUsingDirective: |
810 | break; |
811 | } |
812 | |
813 | return true; |
814 | } |
815 | |
816 | template <typename Derived> |
817 | bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { |
818 | if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) |
819 | TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); |
820 | else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) |
821 | TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); |
822 | |
823 | return true; |
824 | } |
825 | |
826 | template <typename Derived> |
827 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( |
828 | const TemplateArgument &Arg) { |
829 | switch (Arg.getKind()) { |
830 | case TemplateArgument::Null: |
831 | case TemplateArgument::Declaration: |
832 | case TemplateArgument::Integral: |
833 | case TemplateArgument::NullPtr: |
834 | return true; |
835 | |
836 | case TemplateArgument::Type: |
837 | return getDerived().TraverseType(Arg.getAsType()); |
838 | |
839 | case TemplateArgument::Template: |
840 | case TemplateArgument::TemplateExpansion: |
841 | return getDerived().TraverseTemplateName( |
842 | Arg.getAsTemplateOrTemplatePattern()); |
843 | |
844 | case TemplateArgument::Expression: |
845 | return getDerived().TraverseStmt(Arg.getAsExpr()); |
846 | |
847 | case TemplateArgument::Pack: |
848 | return getDerived().TraverseTemplateArguments(Arg.pack_begin(), |
849 | Arg.pack_size()); |
850 | } |
851 | |
852 | return true; |
853 | } |
854 | |
855 | // FIXME: no template name location? |
856 | // FIXME: no source locations for a template argument pack? |
857 | template <typename Derived> |
858 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( |
859 | const TemplateArgumentLoc &ArgLoc) { |
860 | const TemplateArgument &Arg = ArgLoc.getArgument(); |
861 | |
862 | switch (Arg.getKind()) { |
863 | case TemplateArgument::Null: |
864 | case TemplateArgument::Declaration: |
865 | case TemplateArgument::Integral: |
866 | case TemplateArgument::NullPtr: |
867 | return true; |
868 | |
869 | case TemplateArgument::Type: { |
870 | // FIXME: how can TSI ever be NULL? |
871 | if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) |
872 | return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); |
873 | else |
874 | return getDerived().TraverseType(Arg.getAsType()); |
875 | } |
876 | |
877 | case TemplateArgument::Template: |
878 | case TemplateArgument::TemplateExpansion: |
879 | if (ArgLoc.getTemplateQualifierLoc()) |
880 | TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( |
881 | ArgLoc.getTemplateQualifierLoc())); |
882 | return getDerived().TraverseTemplateName( |
883 | Arg.getAsTemplateOrTemplatePattern()); |
884 | |
885 | case TemplateArgument::Expression: |
886 | return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); |
887 | |
888 | case TemplateArgument::Pack: |
889 | return getDerived().TraverseTemplateArguments(Arg.pack_begin(), |
890 | Arg.pack_size()); |
891 | } |
892 | |
893 | return true; |
894 | } |
895 | |
896 | template <typename Derived> |
897 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( |
898 | const TemplateArgument *Args, unsigned NumArgs) { |
899 | for (unsigned I = 0; I != NumArgs; ++I) { |
900 | TRY_TO(TraverseTemplateArgument(Args[I])); |
901 | } |
902 | |
903 | return true; |
904 | } |
905 | |
906 | template <typename Derived> |
907 | bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( |
908 | CXXCtorInitializer *Init) { |
909 | if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) |
910 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
911 | |
912 | if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) |
913 | TRY_TO(TraverseStmt(Init->getInit())); |
914 | |
915 | return true; |
916 | } |
917 | |
918 | template <typename Derived> |
919 | bool |
920 | RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, |
921 | const LambdaCapture *C, |
922 | Expr *Init) { |
923 | if (LE->isInitCapture(C)) |
924 | TRY_TO(TraverseDecl(C->getCapturedVar())); |
925 | else |
926 | TRY_TO(TraverseStmt(Init)); |
927 | return true; |
928 | } |
929 | |
930 | // ----------------- Type traversal ----------------- |
931 | |
932 | // This macro makes available a variable T, the passed-in type. |
933 | #define DEF_TRAVERSE_TYPE(TYPE, CODE) \ |
934 | template <typename Derived> \ |
935 | bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \ |
936 | if (!getDerived().shouldTraversePostOrder()) \ |
937 | TRY_TO(WalkUpFrom##TYPE(T)); \ |
938 | { CODE; } \ |
939 | if (getDerived().shouldTraversePostOrder()) \ |
940 | TRY_TO(WalkUpFrom##TYPE(T)); \ |
941 | return true; \ |
942 | } |
943 | |
944 | DEF_TRAVERSE_TYPE(BuiltinType, {}) |
945 | |
946 | DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) |
947 | |
948 | DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) |
949 | |
950 | DEF_TRAVERSE_TYPE(BlockPointerType, |
951 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
952 | |
953 | DEF_TRAVERSE_TYPE(LValueReferenceType, |
954 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
955 | |
956 | DEF_TRAVERSE_TYPE(RValueReferenceType, |
957 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
958 | |
959 | DEF_TRAVERSE_TYPE(MemberPointerType, { |
960 | TRY_TO(TraverseType(QualType(T->getClass(), 0))); |
961 | TRY_TO(TraverseType(T->getPointeeType())); |
962 | }) |
963 | |
964 | DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) |
965 | |
966 | DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) |
967 | |
968 | DEF_TRAVERSE_TYPE(ConstantArrayType, { |
969 | TRY_TO(TraverseType(T->getElementType())); |
970 | if (T->getSizeExpr()) |
971 | TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr()))); |
972 | }) |
973 | |
974 | DEF_TRAVERSE_TYPE(IncompleteArrayType, |
975 | { TRY_TO(TraverseType(T->getElementType())); }) |
976 | |
977 | DEF_TRAVERSE_TYPE(VariableArrayType, { |
978 | TRY_TO(TraverseType(T->getElementType())); |
979 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
980 | }) |
981 | |
982 | DEF_TRAVERSE_TYPE(DependentSizedArrayType, { |
983 | TRY_TO(TraverseType(T->getElementType())); |
984 | if (T->getSizeExpr()) |
985 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
986 | }) |
987 | |
988 | DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { |
989 | TRY_TO(TraverseStmt(T->getAddrSpaceExpr())); |
990 | TRY_TO(TraverseType(T->getPointeeType())); |
991 | }) |
992 | |
993 | DEF_TRAVERSE_TYPE(DependentVectorType, { |
994 | if (T->getSizeExpr()) |
995 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
996 | TRY_TO(TraverseType(T->getElementType())); |
997 | }) |
998 | |
999 | DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { |
1000 | if (T->getSizeExpr()) |
1001 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
1002 | TRY_TO(TraverseType(T->getElementType())); |
1003 | }) |
1004 | |
1005 | DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) |
1006 | |
1007 | DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) |
1008 | |
1009 | DEF_TRAVERSE_TYPE(FunctionNoProtoType, |
1010 | { TRY_TO(TraverseType(T->getReturnType())); }) |
1011 | |
1012 | DEF_TRAVERSE_TYPE(FunctionProtoType, { |
1013 | TRY_TO(TraverseType(T->getReturnType())); |
1014 | |
1015 | for (const auto &A : T->param_types()) { |
1016 | TRY_TO(TraverseType(A)); |
1017 | } |
1018 | |
1019 | for (const auto &E : T->exceptions()) { |
1020 | TRY_TO(TraverseType(E)); |
1021 | } |
1022 | |
1023 | if (Expr *NE = T->getNoexceptExpr()) |
1024 | TRY_TO(TraverseStmt(NE)); |
1025 | }) |
1026 | |
1027 | DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) |
1028 | DEF_TRAVERSE_TYPE(TypedefType, {}) |
1029 | |
1030 | DEF_TRAVERSE_TYPE(TypeOfExprType, |
1031 | { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) |
1032 | |
1033 | DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); }) |
1034 | |
1035 | DEF_TRAVERSE_TYPE(DecltypeType, |
1036 | { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) |
1037 | |
1038 | DEF_TRAVERSE_TYPE(UnaryTransformType, { |
1039 | TRY_TO(TraverseType(T->getBaseType())); |
1040 | TRY_TO(TraverseType(T->getUnderlyingType())); |
1041 | }) |
1042 | |
1043 | DEF_TRAVERSE_TYPE(AutoType, { |
1044 | TRY_TO(TraverseType(T->getDeducedType())); |
1045 | if (T->isConstrained()) { |
1046 | TRY_TO(TraverseDecl(T->getTypeConstraintConcept())); |
1047 | TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); |
1048 | } |
1049 | }) |
1050 | DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { |
1051 | TRY_TO(TraverseTemplateName(T->getTemplateName())); |
1052 | TRY_TO(TraverseType(T->getDeducedType())); |
1053 | }) |
1054 | |
1055 | DEF_TRAVERSE_TYPE(RecordType, {}) |
1056 | DEF_TRAVERSE_TYPE(EnumType, {}) |
1057 | DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) |
1058 | DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { |
1059 | TRY_TO(TraverseType(T->getReplacementType())); |
1060 | }) |
1061 | DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { |
1062 | TRY_TO(TraverseTemplateArgument(T->getArgumentPack())); |
1063 | }) |
1064 | |
1065 | DEF_TRAVERSE_TYPE(TemplateSpecializationType, { |
1066 | TRY_TO(TraverseTemplateName(T->getTemplateName())); |
1067 | TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); |
1068 | }) |
1069 | |
1070 | DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) |
1071 | |
1072 | DEF_TRAVERSE_TYPE(AttributedType, |
1073 | { TRY_TO(TraverseType(T->getModifiedType())); }) |
1074 | |
1075 | DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) |
1076 | |
1077 | DEF_TRAVERSE_TYPE(MacroQualifiedType, |
1078 | { TRY_TO(TraverseType(T->getUnderlyingType())); }) |
1079 | |
1080 | DEF_TRAVERSE_TYPE(ElaboratedType, { |
1081 | if (T->getQualifier()) { |
1082 | TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); |
1083 | } |
1084 | TRY_TO(TraverseType(T->getNamedType())); |
1085 | }) |
1086 | |
1087 | DEF_TRAVERSE_TYPE(DependentNameType, |
1088 | { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) |
1089 | |
1090 | DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { |
1091 | TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); |
1092 | TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); |
1093 | }) |
1094 | |
1095 | DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) |
1096 | |
1097 | DEF_TRAVERSE_TYPE(ObjCTypeParamType, {}) |
1098 | |
1099 | DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) |
1100 | |
1101 | DEF_TRAVERSE_TYPE(ObjCObjectType, { |
1102 | // We have to watch out here because an ObjCInterfaceType's base |
1103 | // type is itself. |
1104 | if (T->getBaseType().getTypePtr() != T) |
1105 | TRY_TO(TraverseType(T->getBaseType())); |
1106 | for (auto typeArg : T->getTypeArgsAsWritten()) { |
1107 | TRY_TO(TraverseType(typeArg)); |
1108 | } |
1109 | }) |
1110 | |
1111 | DEF_TRAVERSE_TYPE(ObjCObjectPointerType, |
1112 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
1113 | |
1114 | DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) |
1115 | |
1116 | DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); }) |
1117 | |
1118 | DEF_TRAVERSE_TYPE(ExtIntType, {}) |
1119 | DEF_TRAVERSE_TYPE(DependentExtIntType, |
1120 | { TRY_TO(TraverseStmt(T->getNumBitsExpr())); }) |
1121 | |
1122 | #undef DEF_TRAVERSE_TYPE |
1123 | |
1124 | // ----------------- TypeLoc traversal ----------------- |
1125 | |
1126 | // This macro makes available a variable TL, the passed-in TypeLoc. |
1127 | // If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, |
1128 | // in addition to WalkUpFrom* for the TypeLoc itself, such that existing |
1129 | // clients that override the WalkUpFrom*Type() and/or Visit*Type() methods |
1130 | // continue to work. |
1131 | #define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ |
1132 | template <typename Derived> \ |
1133 | bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ |
1134 | if (!getDerived().shouldTraversePostOrder()) { \ |
1135 | TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ |
1136 | if (getDerived().shouldWalkTypesOfTypeLocs()) \ |
1137 | TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ |
1138 | } \ |
1139 | { CODE; } \ |
1140 | if (getDerived().shouldTraversePostOrder()) { \ |
1141 | TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ |
1142 | if (getDerived().shouldWalkTypesOfTypeLocs()) \ |
1143 | TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ |
1144 | } \ |
1145 | return true; \ |
1146 | } |
1147 | |
1148 | template <typename Derived> |
1149 | bool |
1150 | RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { |
1151 | // Move this over to the 'main' typeloc tree. Note that this is a |
1152 | // move -- we pretend that we were really looking at the unqualified |
1153 | // typeloc all along -- rather than a recursion, so we don't follow |
1154 | // the normal CRTP plan of going through |
1155 | // getDerived().TraverseTypeLoc. If we did, we'd be traversing |
1156 | // twice for the same type (once as a QualifiedTypeLoc version of |
1157 | // the type, once as an UnqualifiedTypeLoc version of the type), |
1158 | // which in effect means we'd call VisitTypeLoc twice with the |
1159 | // 'same' type. This solves that problem, at the cost of never |
1160 | // seeing the qualified version of the type (unless the client |
1161 | // subclasses TraverseQualifiedTypeLoc themselves). It's not a |
1162 | // perfect solution. A perfect solution probably requires making |
1163 | // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a |
1164 | // wrapper around Type* -- rather than being its own class in the |
1165 | // type hierarchy. |
1166 | return TraverseTypeLoc(TL.getUnqualifiedLoc()); |
1167 | } |
1168 | |
1169 | DEF_TRAVERSE_TYPELOC(BuiltinType, {}) |
1170 | |
1171 | // FIXME: ComplexTypeLoc is unfinished |
1172 | DEF_TRAVERSE_TYPELOC(ComplexType, { |
1173 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1174 | }) |
1175 | |
1176 | DEF_TRAVERSE_TYPELOC(PointerType, |
1177 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1178 | |
1179 | DEF_TRAVERSE_TYPELOC(BlockPointerType, |
1180 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1181 | |
1182 | DEF_TRAVERSE_TYPELOC(LValueReferenceType, |
1183 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1184 | |
1185 | DEF_TRAVERSE_TYPELOC(RValueReferenceType, |
1186 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1187 | |
1188 | // We traverse this in the type case as well, but how is it not reached through |
1189 | // the pointee type? |
1190 | DEF_TRAVERSE_TYPELOC(MemberPointerType, { |
1191 | if (auto *TSI = TL.getClassTInfo()) |
1192 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); |
1193 | else |
1194 | TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); |
1195 | TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); |
1196 | }) |
1197 | |
1198 | DEF_TRAVERSE_TYPELOC(AdjustedType, |
1199 | { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) |
1200 | |
1201 | DEF_TRAVERSE_TYPELOC(DecayedType, |
1202 | { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) |
1203 | |
1204 | template <typename Derived> |
1205 | bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { |
1206 | // This isn't available for ArrayType, but is for the ArrayTypeLoc. |
1207 | TRY_TO(TraverseStmt(TL.getSizeExpr())); |
1208 | return true; |
1209 | } |
1210 | |
1211 | DEF_TRAVERSE_TYPELOC(ConstantArrayType, { |
1212 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1213 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1214 | }) |
1215 | |
1216 | DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { |
1217 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1218 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1219 | }) |
1220 | |
1221 | DEF_TRAVERSE_TYPELOC(VariableArrayType, { |
1222 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1223 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1224 | }) |
1225 | |
1226 | DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { |
1227 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1228 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1229 | }) |
1230 | |
1231 | DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, { |
1232 | TRY_TO(TraverseStmt(TL.getTypePtr()->getAddrSpaceExpr())); |
1233 | TRY_TO(TraverseType(TL.getTypePtr()->getPointeeType())); |
1234 | }) |
1235 | |
1236 | // FIXME: order? why not size expr first? |
1237 | // FIXME: base VectorTypeLoc is unfinished |
1238 | DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { |
1239 | if (TL.getTypePtr()->getSizeExpr()) |
1240 | TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); |
1241 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1242 | }) |
1243 | |
1244 | // FIXME: VectorTypeLoc is unfinished |
1245 | DEF_TRAVERSE_TYPELOC(VectorType, { |
1246 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1247 | }) |
1248 | |
1249 | DEF_TRAVERSE_TYPELOC(DependentVectorType, { |
1250 | if (TL.getTypePtr()->getSizeExpr()) |
1251 | TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); |
1252 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1253 | }) |
1254 | |
1255 | // FIXME: size and attributes |
1256 | // FIXME: base VectorTypeLoc is unfinished |
1257 | DEF_TRAVERSE_TYPELOC(ExtVectorType, { |
1258 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1259 | }) |
1260 | |
1261 | DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, |
1262 | { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) |
1263 | |
1264 | // FIXME: location of exception specifications (attributes?) |
1265 | DEF_TRAVERSE_TYPELOC(FunctionProtoType, { |
1266 | TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); |
1267 | |
1268 | const FunctionProtoType *T = TL.getTypePtr(); |
1269 | |
1270 | for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { |
1271 | if (TL.getParam(I)) { |
1272 | TRY_TO(TraverseDecl(TL.getParam(I))); |
1273 | } else if (I < T->getNumParams()) { |
1274 | TRY_TO(TraverseType(T->getParamType(I))); |
1275 | } |
1276 | } |
1277 | |
1278 | for (const auto &E : T->exceptions()) { |
1279 | TRY_TO(TraverseType(E)); |
1280 | } |
1281 | |
1282 | if (Expr *NE = T->getNoexceptExpr()) |
1283 | TRY_TO(TraverseStmt(NE)); |
1284 | }) |
1285 | |
1286 | DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) |
1287 | DEF_TRAVERSE_TYPELOC(TypedefType, {}) |
1288 | |
1289 | DEF_TRAVERSE_TYPELOC(TypeOfExprType, |
1290 | { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) |
1291 | |
1292 | DEF_TRAVERSE_TYPELOC(TypeOfType, { |
1293 | TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); |
1294 | }) |
1295 | |
1296 | // FIXME: location of underlying expr |
1297 | DEF_TRAVERSE_TYPELOC(DecltypeType, { |
1298 | TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); |
1299 | }) |
1300 | |
1301 | DEF_TRAVERSE_TYPELOC(UnaryTransformType, { |
1302 | TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); |
1303 | }) |
1304 | |
1305 | DEF_TRAVERSE_TYPELOC(AutoType, { |
1306 | TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); |
1307 | if (TL.isConstrained()) { |
1308 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc())); |
1309 | TRY_TO(TraverseDeclarationNameInfo(TL.getConceptNameInfo())); |
1310 | for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) |
1311 | TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); |
1312 | } |
1313 | }) |
1314 | |
1315 | DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, { |
1316 | TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); |
1317 | TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); |
1318 | }) |
1319 | |
1320 | DEF_TRAVERSE_TYPELOC(RecordType, {}) |
1321 | DEF_TRAVERSE_TYPELOC(EnumType, {}) |
1322 | DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) |
1323 | DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { |
1324 | TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType())); |
1325 | }) |
1326 | DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { |
1327 | TRY_TO(TraverseTemplateArgument(TL.getTypePtr()->getArgumentPack())); |
1328 | }) |
1329 | |
1330 | // FIXME: use the loc for the template name? |
1331 | DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { |
1332 | TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); |
1333 | for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { |
1334 | TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); |
1335 | } |
1336 | }) |
1337 | |
1338 | DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {}) |
1339 | |
1340 | DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
1341 | |
1342 | DEF_TRAVERSE_TYPELOC(MacroQualifiedType, |
1343 | { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
1344 | |
1345 | DEF_TRAVERSE_TYPELOC(AttributedType, |
1346 | { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) |
1347 | |
1348 | DEF_TRAVERSE_TYPELOC(ElaboratedType, { |
1349 | if (TL.getQualifierLoc()) { |
1350 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
1351 | } |
1352 | TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); |
1353 | }) |
1354 | |
1355 | DEF_TRAVERSE_TYPELOC(DependentNameType, { |
1356 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
1357 | }) |
1358 | |
1359 | DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { |
1360 | if (TL.getQualifierLoc()) { |
1361 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
1362 | } |
1363 | |
1364 | for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { |
1365 | TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); |
1366 | } |
1367 | }) |
1368 | |
1369 | DEF_TRAVERSE_TYPELOC(PackExpansionType, |
1370 | { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) |
1371 | |
1372 | DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, {}) |
1373 | |
1374 | DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) |
1375 | |
1376 | DEF_TRAVERSE_TYPELOC(ObjCObjectType, { |
1377 | // We have to watch out here because an ObjCInterfaceType's base |
1378 | // type is itself. |
1379 | if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) |
1380 | TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); |
1381 | for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) |
1382 | TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc())); |
1383 | }) |
1384 | |
1385 | DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, |
1386 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1387 | |
1388 | DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) |
1389 | |
1390 | DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) |
1391 | |
1392 | DEF_TRAVERSE_TYPELOC(ExtIntType, {}) |
1393 | DEF_TRAVERSE_TYPELOC(DependentExtIntType, { |
1394 | TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr())); |
1395 | }) |
1396 | |
1397 | #undef DEF_TRAVERSE_TYPELOC |
1398 | |
1399 | // ----------------- Decl traversal ----------------- |
1400 | // |
1401 | // For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing |
1402 | // the children that come from the DeclContext associated with it. |
1403 | // Therefore each Traverse* only needs to worry about children other |
1404 | // than those. |
1405 | |
1406 | template <typename Derived> |
1407 | bool RecursiveASTVisitor<Derived>::canIgnoreChildDeclWhileTraversingDeclContext( |
1408 | const Decl *Child) { |
1409 | // BlockDecls are traversed through BlockExprs, |
1410 | // CapturedDecls are traversed through CapturedStmts. |
1411 | if (isa<BlockDecl>(Child) || isa<CapturedDecl>(Child)) |
1412 | return true; |
1413 | // Lambda classes are traversed through LambdaExprs. |
1414 | if (const CXXRecordDecl* Cls = dyn_cast<CXXRecordDecl>(Child)) |
1415 | return Cls->isLambda(); |
1416 | return false; |
1417 | } |
1418 | |
1419 | template <typename Derived> |
1420 | bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { |
1421 | if (!DC) |
1422 | return true; |
1423 | |
1424 | for (auto *Child : DC->decls()) { |
1425 | if (!canIgnoreChildDeclWhileTraversingDeclContext(Child)) |
1426 | TRY_TO(TraverseDecl(Child)); |
1427 | } |
1428 | |
1429 | return true; |
1430 | } |
1431 | |
1432 | // This macro makes available a variable D, the passed-in decl. |
1433 | #define DEF_TRAVERSE_DECL(DECL, CODE) \ |
1434 | template <typename Derived> \ |
1435 | bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \ |
1436 | bool ShouldVisitChildren = true; \ |
1437 | bool ReturnValue = true; \ |
1438 | if (!getDerived().shouldTraversePostOrder()) \ |
1439 | TRY_TO(WalkUpFrom##DECL(D)); \ |
1440 | { CODE; } \ |
1441 | if (ReturnValue && ShouldVisitChildren) \ |
1442 | TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ |
1443 | if (ReturnValue) { \ |
1444 | /* Visit any attributes attached to this declaration. */ \ |
1445 | for (auto *I : D->attrs()) \ |
1446 | TRY_TO(getDerived().TraverseAttr(I)); \ |
1447 | } \ |
1448 | if (ReturnValue && getDerived().shouldTraversePostOrder()) \ |
1449 | TRY_TO(WalkUpFrom##DECL(D)); \ |
1450 | return ReturnValue; \ |
1451 | } |
1452 | |
1453 | DEF_TRAVERSE_DECL(AccessSpecDecl, {}) |
1454 | |
1455 | DEF_TRAVERSE_DECL(BlockDecl, { |
1456 | if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) |
1457 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
1458 | TRY_TO(TraverseStmt(D->getBody())); |
1459 | for (const auto &I : D->captures()) { |
1460 | if (I.hasCopyExpr()) { |
1461 | TRY_TO(TraverseStmt(I.getCopyExpr())); |
1462 | } |
1463 | } |
1464 | ShouldVisitChildren = false; |
1465 | }) |
1466 | |
1467 | DEF_TRAVERSE_DECL(CapturedDecl, { |
1468 | TRY_TO(TraverseStmt(D->getBody())); |
1469 | ShouldVisitChildren = false; |
1470 | }) |
1471 | |
1472 | DEF_TRAVERSE_DECL(EmptyDecl, {}) |
1473 | |
1474 | DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, { |
1475 | TRY_TO(TraverseStmt(D->getTemporaryExpr())); |
1476 | }) |
1477 | |
1478 | DEF_TRAVERSE_DECL(FileScopeAsmDecl, |
1479 | { TRY_TO(TraverseStmt(D->getAsmString())); }) |
1480 | |
1481 | DEF_TRAVERSE_DECL(ImportDecl, {}) |
1482 | |
1483 | DEF_TRAVERSE_DECL(FriendDecl, { |
1484 | // Friend is either decl or a type. |
1485 | if (D->getFriendType()) |
1486 | TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); |
1487 | else |
1488 | TRY_TO(TraverseDecl(D->getFriendDecl())); |
1489 | }) |
1490 | |
1491 | DEF_TRAVERSE_DECL(FriendTemplateDecl, { |
1492 | if (D->getFriendType()) |
1493 | TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); |
1494 | else |
1495 | TRY_TO(TraverseDecl(D->getFriendDecl())); |
1496 | for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { |
1497 | TemplateParameterList *TPL = D->getTemplateParameterList(I); |
1498 | for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end(); |
1499 | ITPL != ETPL; ++ITPL) { |
1500 | TRY_TO(TraverseDecl(*ITPL)); |
1501 | } |
1502 | } |
1503 | }) |
1504 | |
1505 | DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { |
1506 | TRY_TO(TraverseDecl(D->getSpecialization())); |
1507 | |
1508 | if (D->hasExplicitTemplateArgs()) { |
1509 | TRY_TO(TraverseTemplateArgumentLocsHelper( |
1510 | D->getTemplateArgsAsWritten()->getTemplateArgs(), |
1511 | D->getTemplateArgsAsWritten()->NumTemplateArgs)); |
1512 | } |
1513 | }) |
1514 | |
1515 | DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) |
1516 | |
1517 | DEF_TRAVERSE_DECL(ExportDecl, {}) |
1518 | |
1519 | DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this |
1520 | }) |
1521 | |
1522 | DEF_TRAVERSE_DECL(StaticAssertDecl, { |
1523 | TRY_TO(TraverseStmt(D->getAssertExpr())); |
1524 | TRY_TO(TraverseStmt(D->getMessage())); |
1525 | }) |
1526 | |
1527 | DEF_TRAVERSE_DECL( |
1528 | TranslationUnitDecl, |
1529 | {// Code in an unnamed namespace shows up automatically in |
1530 | // decls_begin()/decls_end(). Thus we don't need to recurse on |
1531 | // D->getAnonymousNamespace(). |
1532 | }) |
1533 | |
1534 | DEF_TRAVERSE_DECL(PragmaCommentDecl, {}) |
1535 | |
1536 | DEF_TRAVERSE_DECL(PragmaDetectMismatchDecl, {}) |
1537 | |
1538 | DEF_TRAVERSE_DECL(ExternCContextDecl, {}) |
1539 | |
1540 | DEF_TRAVERSE_DECL(NamespaceAliasDecl, { |
1541 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1542 | |
1543 | // We shouldn't traverse an aliased namespace, since it will be |
1544 | // defined (and, therefore, traversed) somewhere else. |
1545 | ShouldVisitChildren = false; |
1546 | }) |
1547 | |
1548 | DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl. |
1549 | }) |
1550 | |
1551 | DEF_TRAVERSE_DECL( |
1552 | NamespaceDecl, |
1553 | {// Code in an unnamed namespace shows up automatically in |
1554 | // decls_begin()/decls_end(). Thus we don't need to recurse on |
1555 | // D->getAnonymousNamespace(). |
1556 | }) |
1557 | |
1558 | DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement |
1559 | }) |
1560 | |
1561 | DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement |
1562 | if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) { |
1563 | for (auto typeParam : *typeParamList) { |
1564 | TRY_TO(TraverseObjCTypeParamDecl(typeParam)); |
1565 | } |
1566 | } |
1567 | }) |
1568 | |
1569 | DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement |
1570 | }) |
1571 | |
1572 | DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement |
1573 | }) |
1574 | |
1575 | DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement |
1576 | if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) { |
1577 | for (auto typeParam : *typeParamList) { |
1578 | TRY_TO(TraverseObjCTypeParamDecl(typeParam)); |
1579 | } |
1580 | } |
1581 | |
1582 | if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) { |
1583 | TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc())); |
1584 | } |
1585 | }) |
1586 | |
1587 | DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement |
1588 | }) |
1589 | |
1590 | DEF_TRAVERSE_DECL(ObjCMethodDecl, { |
1591 | if (D->getReturnTypeSourceInfo()) { |
1592 | TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); |
1593 | } |
1594 | for (ParmVarDecl *Parameter : D->parameters()) { |
1595 | TRY_TO(TraverseDecl(Parameter)); |
1596 | } |
1597 | if (D->isThisDeclarationADefinition()) { |
1598 | TRY_TO(TraverseStmt(D->getBody())); |
1599 | } |
1600 | ShouldVisitChildren = false; |
1601 | }) |
1602 | |
1603 | DEF_TRAVERSE_DECL(ObjCTypeParamDecl, { |
1604 | if (D->hasExplicitBound()) { |
1605 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1606 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1607 | // declaring the type alias, not something that was written in the |
1608 | // source. |
1609 | } |
1610 | }) |
1611 | |
1612 | DEF_TRAVERSE_DECL(ObjCPropertyDecl, { |
1613 | if (D->getTypeSourceInfo()) |
1614 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1615 | else |
1616 | TRY_TO(TraverseType(D->getType())); |
1617 | ShouldVisitChildren = false; |
1618 | }) |
1619 | |
1620 | DEF_TRAVERSE_DECL(UsingDecl, { |
1621 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1622 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
1623 | }) |
1624 | |
1625 | DEF_TRAVERSE_DECL(UsingPackDecl, {}) |
1626 | |
1627 | DEF_TRAVERSE_DECL(UsingDirectiveDecl, { |
1628 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1629 | }) |
1630 | |
1631 | DEF_TRAVERSE_DECL(UsingShadowDecl, {}) |
1632 | |
1633 | DEF_TRAVERSE_DECL(ConstructorUsingShadowDecl, {}) |
1634 | |
1635 | DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { |
1636 | for (auto *I : D->varlists()) { |
1637 | TRY_TO(TraverseStmt(I)); |
1638 | } |
1639 | }) |
1640 | |
1641 | DEF_TRAVERSE_DECL(OMPRequiresDecl, { |
1642 | for (auto *C : D->clauselists()) { |
1643 | TRY_TO(TraverseOMPClause(C)); |
1644 | } |
1645 | }) |
1646 | |
1647 | DEF_TRAVERSE_DECL(OMPDeclareReductionDecl, { |
1648 | TRY_TO(TraverseStmt(D->getCombiner())); |
1649 | if (auto *Initializer = D->getInitializer()) |
1650 | TRY_TO(TraverseStmt(Initializer)); |
1651 | TRY_TO(TraverseType(D->getType())); |
1652 | return true; |
1653 | }) |
1654 | |
1655 | DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, { |
1656 | for (auto *C : D->clauselists()) |
1657 | TRY_TO(TraverseOMPClause(C)); |
1658 | TRY_TO(TraverseType(D->getType())); |
1659 | return true; |
1660 | }) |
1661 | |
1662 | DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); }) |
1663 | |
1664 | DEF_TRAVERSE_DECL(OMPAllocateDecl, { |
1665 | for (auto *I : D->varlists()) |
1666 | TRY_TO(TraverseStmt(I)); |
1667 | for (auto *C : D->clauselists()) |
1668 | TRY_TO(TraverseOMPClause(C)); |
1669 | }) |
1670 | |
1671 | // A helper method for TemplateDecl's children. |
1672 | template <typename Derived> |
1673 | bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( |
1674 | TemplateParameterList *TPL) { |
1675 | if (TPL) { |
1676 | for (NamedDecl *D : *TPL) { |
1677 | TRY_TO(TraverseDecl(D)); |
1678 | } |
1679 | if (Expr *RequiresClause = TPL->getRequiresClause()) { |
1680 | TRY_TO(TraverseStmt(RequiresClause)); |
1681 | } |
1682 | } |
1683 | return true; |
1684 | } |
1685 | |
1686 | template <typename Derived> |
1687 | template <typename T> |
1688 | bool RecursiveASTVisitor<Derived>::TraverseDeclTemplateParameterLists(T *D) { |
1689 | for (unsigned i = 0; i < D->getNumTemplateParameterLists(); i++) { |
1690 | TemplateParameterList *TPL = D->getTemplateParameterList(i); |
1691 | TraverseTemplateParameterListHelper(TPL); |
1692 | } |
1693 | return true; |
1694 | } |
1695 | |
1696 | template <typename Derived> |
1697 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
1698 | ClassTemplateDecl *D) { |
1699 | for (auto *SD : D->specializations()) { |
1700 | for (auto *RD : SD->redecls()) { |
1701 | // We don't want to visit injected-class-names in this traversal. |
1702 | if (cast<CXXRecordDecl>(RD)->isInjectedClassName()) |
1703 | continue; |
1704 | |
1705 | switch ( |
1706 | cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) { |
1707 | // Visit the implicit instantiations with the requested pattern. |
1708 | case TSK_Undeclared: |
1709 | case TSK_ImplicitInstantiation: |
1710 | TRY_TO(TraverseDecl(RD)); |
1711 | break; |
1712 | |
1713 | // We don't need to do anything on an explicit instantiation |
1714 | // or explicit specialization because there will be an explicit |
1715 | // node for it elsewhere. |
1716 | case TSK_ExplicitInstantiationDeclaration: |
1717 | case TSK_ExplicitInstantiationDefinition: |
1718 | case TSK_ExplicitSpecialization: |
1719 | break; |
1720 | } |
1721 | } |
1722 | } |
1723 | |
1724 | return true; |
1725 | } |
1726 | |
1727 | template <typename Derived> |
1728 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
1729 | VarTemplateDecl *D) { |
1730 | for (auto *SD : D->specializations()) { |
1731 | for (auto *RD : SD->redecls()) { |
1732 | switch ( |
1733 | cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) { |
1734 | case TSK_Undeclared: |
1735 | case TSK_ImplicitInstantiation: |
1736 | TRY_TO(TraverseDecl(RD)); |
1737 | break; |
1738 | |
1739 | case TSK_ExplicitInstantiationDeclaration: |
1740 | case TSK_ExplicitInstantiationDefinition: |
1741 | case TSK_ExplicitSpecialization: |
1742 | break; |
1743 | } |
1744 | } |
1745 | } |
1746 | |
1747 | return true; |
1748 | } |
1749 | |
1750 | // A helper method for traversing the instantiations of a |
1751 | // function while skipping its specializations. |
1752 | template <typename Derived> |
1753 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
1754 | FunctionTemplateDecl *D) { |
1755 | for (auto *FD : D->specializations()) { |
1756 | for (auto *RD : FD->redecls()) { |
1757 | switch (RD->getTemplateSpecializationKind()) { |
1758 | case TSK_Undeclared: |
1759 | case TSK_ImplicitInstantiation: |
1760 | // We don't know what kind of FunctionDecl this is. |
1761 | TRY_TO(TraverseDecl(RD)); |
1762 | break; |
1763 | |
1764 | // FIXME: For now traverse explicit instantiations here. Change that |
1765 | // once they are represented as dedicated nodes in the AST. |
1766 | case TSK_ExplicitInstantiationDeclaration: |
1767 | case TSK_ExplicitInstantiationDefinition: |
1768 | TRY_TO(TraverseDecl(RD)); |
1769 | break; |
1770 | |
1771 | case TSK_ExplicitSpecialization: |
1772 | break; |
1773 | } |
1774 | } |
1775 | } |
1776 | |
1777 | return true; |
1778 | } |
1779 | |
1780 | // This macro unifies the traversal of class, variable and function |
1781 | // template declarations. |
1782 | #define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ |
1783 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ |
1784 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ |
1785 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ |
1786 | \ |
1787 | /* By default, we do not traverse the instantiations of \ |
1788 | class templates since they do not appear in the user code. The \ |
1789 | following code optionally traverses them. \ |
1790 | \ |
1791 | We only traverse the class instantiations when we see the canonical \ |
1792 | declaration of the template, to ensure we only visit them once. */ \ |
1793 | if (getDerived().shouldVisitTemplateInstantiations() && \ |
1794 | D == D->getCanonicalDecl()) \ |
1795 | TRY_TO(TraverseTemplateInstantiations(D)); \ |
1796 | \ |
1797 | /* Note that getInstantiatedFromMemberTemplate() is just a link \ |
1798 | from a template instantiation back to the template from which \ |
1799 | it was instantiated, and thus should not be traversed. */ \ |
1800 | }) |
1801 | |
1802 | DEF_TRAVERSE_TMPL_DECL(Class) |
1803 | DEF_TRAVERSE_TMPL_DECL(Var) |
1804 | DEF_TRAVERSE_TMPL_DECL(Function) |
1805 | |
1806 | DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { |
1807 | // D is the "T" in something like |
1808 | // template <template <typename> class T> class container { }; |
1809 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); |
1810 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
1811 | TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); |
1812 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1813 | }) |
1814 | |
1815 | DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { |
1816 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1817 | }) |
1818 | |
1819 | DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { |
1820 | // D is the "T" in something like "template<typename T> class vector;" |
1821 | if (D->getTypeForDecl()) |
1822 | TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); |
1823 | if (const auto *TC = D->getTypeConstraint()) |
1824 | TRY_TO(TraverseConceptReference(*TC)); |
1825 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
1826 | TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); |
1827 | }) |
1828 | |
1829 | DEF_TRAVERSE_DECL(TypedefDecl, { |
1830 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1831 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1832 | // declaring the typedef, not something that was written in the |
1833 | // source. |
1834 | }) |
1835 | |
1836 | DEF_TRAVERSE_DECL(TypeAliasDecl, { |
1837 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1838 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1839 | // declaring the type alias, not something that was written in the |
1840 | // source. |
1841 | }) |
1842 | |
1843 | DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { |
1844 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); |
1845 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1846 | }) |
1847 | |
1848 | DEF_TRAVERSE_DECL(ConceptDecl, { |
1849 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1850 | TRY_TO(TraverseStmt(D->getConstraintExpr())); |
1851 | }) |
1852 | |
1853 | DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { |
1854 | // A dependent using declaration which was marked with 'typename'. |
1855 | // template<class T> class A : public B<T> { using typename B<T>::foo; }; |
1856 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1857 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1858 | // declaring the type, not something that was written in the |
1859 | // source. |
1860 | }) |
1861 | |
1862 | DEF_TRAVERSE_DECL(EnumDecl, { |
1863 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
1864 | |
1865 | if (D->getTypeForDecl()) |
1866 | TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); |
1867 | |
1868 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1869 | // The enumerators are already traversed by |
1870 | // decls_begin()/decls_end(). |
1871 | }) |
1872 | |
1873 | // Helper methods for RecordDecl and its children. |
1874 | template <typename Derived> |
1875 | bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) { |
1876 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1877 | // declaring the type, not something that was written in the source. |
1878 | |
1879 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
1880 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1881 | return true; |
1882 | } |
1883 | |
1884 | template <typename Derived> |
1885 | bool RecursiveASTVisitor<Derived>::TraverseCXXBaseSpecifier( |
1886 | const CXXBaseSpecifier &Base) { |
1887 | TRY_TO(TraverseTypeLoc(Base.getTypeSourceInfo()->getTypeLoc())); |
1888 | return true; |
1889 | } |
1890 | |
1891 | template <typename Derived> |
1892 | bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) { |
1893 | if (!TraverseRecordHelper(D)) |
1894 | return false; |
1895 | if (D->isCompleteDefinition()) { |
1896 | for (const auto &I : D->bases()) { |
1897 | TRY_TO(TraverseCXXBaseSpecifier(I)); |
1898 | } |
1899 | // We don't traverse the friends or the conversions, as they are |
1900 | // already in decls_begin()/decls_end(). |
1901 | } |
1902 | return true; |
1903 | } |
1904 | |
1905 | DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) |
1906 | |
1907 | DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) |
1908 | |
1909 | #define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ |
1910 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ |
1911 | /* For implicit instantiations ("set<int> x;"), we don't want to \ |
1912 | recurse at all, since the instatiated template isn't written in \ |
1913 | the source code anywhere. (Note the instatiated *type* -- \ |
1914 | set<int> -- is written, and will still get a callback of \ |
1915 | TemplateSpecializationType). For explicit instantiations \ |
1916 | ("template set<int>;"), we do need a callback, since this \ |
1917 | is the only callback that's made for this instantiation. \ |
1918 | We use getTypeAsWritten() to distinguish. */ \ |
1919 | if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ |
1920 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ |
1921 | \ |
1922 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ |
1923 | if (!getDerived().shouldVisitTemplateInstantiations() && \ |
1924 | D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ |
1925 | /* Returning from here skips traversing the \ |
1926 | declaration context of the *TemplateSpecializationDecl \ |
1927 | (embedded in the DEF_TRAVERSE_DECL() macro) \ |
1928 | which contains the instantiated members of the template. */ \ |
1929 | return true; \ |
1930 | }) |
1931 | |
1932 | DEF_TRAVERSE_TMPL_SPEC_DECL(Class) |
1933 | DEF_TRAVERSE_TMPL_SPEC_DECL(Var) |
1934 | |
1935 | template <typename Derived> |
1936 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( |
1937 | const TemplateArgumentLoc *TAL, unsigned Count) { |
1938 | for (unsigned I = 0; I < Count; ++I) { |
1939 | TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); |
1940 | } |
1941 | return true; |
1942 | } |
1943 | |
1944 | #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ |
1945 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ |
1946 | /* The partial specialization. */ \ |
1947 | if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ |
1948 | for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ |
1949 | I != E; ++I) { \ |
1950 | TRY_TO(TraverseDecl(*I)); \ |
1951 | } \ |
1952 | } \ |
1953 | /* The args that remains unspecialized. */ \ |
1954 | TRY_TO(TraverseTemplateArgumentLocsHelper( \ |
1955 | D->getTemplateArgsAsWritten()->getTemplateArgs(), \ |
1956 | D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ |
1957 | \ |
1958 | /* Don't need the *TemplatePartialSpecializationHelper, even \ |
1959 | though that's our parent class -- we already visit all the \ |
1960 | template args here. */ \ |
1961 | TRY_TO(Traverse##DECLKIND##Helper(D)); \ |
1962 | \ |
1963 | /* Instantiations will have been visited with the primary template. */ \ |
1964 | }) |
1965 | |
1966 | DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord) |
1967 | DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var) |
1968 | |
1969 | DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); }) |
1970 | |
1971 | DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { |
1972 | // Like UnresolvedUsingTypenameDecl, but without the 'typename': |
1973 | // template <class T> Class A : public Base<T> { using Base<T>::foo; }; |
1974 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1975 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
1976 | }) |
1977 | |
1978 | DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) |
1979 | |
1980 | template <typename Derived> |
1981 | bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { |
1982 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
1983 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1984 | if (D->getTypeSourceInfo()) |
1985 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1986 | else |
1987 | TRY_TO(TraverseType(D->getType())); |
1988 | return true; |
1989 | } |
1990 | |
1991 | DEF_TRAVERSE_DECL(DecompositionDecl, { |
1992 | TRY_TO(TraverseVarHelper(D)); |
1993 | for (auto *Binding : D->bindings()) { |
1994 | TRY_TO(TraverseDecl(Binding)); |
1995 | } |
1996 | }) |
1997 | |
1998 | DEF_TRAVERSE_DECL(BindingDecl, { |
1999 | if (getDerived().shouldVisitImplicitCode()) |
2000 | TRY_TO(TraverseStmt(D->getBinding())); |
2001 | }) |
2002 | |
2003 | DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) |
2004 | |
2005 | DEF_TRAVERSE_DECL(MSGuidDecl, {}) |
2006 | |
2007 | DEF_TRAVERSE_DECL(FieldDecl, { |
2008 | TRY_TO(TraverseDeclaratorHelper(D)); |
2009 | if (D->isBitField()) |
2010 | TRY_TO(TraverseStmt(D->getBitWidth())); |
2011 | else if (D->hasInClassInitializer()) |
2012 | TRY_TO(TraverseStmt(D->getInClassInitializer())); |
2013 | }) |
2014 | |
2015 | DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { |
2016 | |
---|