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/ASTConcept.h" |
17 | #include "clang/AST/Attr.h" |
18 | #include "clang/AST/Decl.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/DeclarationName.h" |
26 | #include "clang/AST/Expr.h" |
27 | #include "clang/AST/ExprCXX.h" |
28 | #include "clang/AST/ExprConcepts.h" |
29 | #include "clang/AST/ExprObjC.h" |
30 | #include "clang/AST/ExprOpenMP.h" |
31 | #include "clang/AST/LambdaCapture.h" |
32 | #include "clang/AST/NestedNameSpecifier.h" |
33 | #include "clang/AST/OpenMPClause.h" |
34 | #include "clang/AST/Stmt.h" |
35 | #include "clang/AST/StmtCXX.h" |
36 | #include "clang/AST/StmtObjC.h" |
37 | #include "clang/AST/StmtOpenACC.h" |
38 | #include "clang/AST/StmtOpenMP.h" |
39 | #include "clang/AST/TemplateBase.h" |
40 | #include "clang/AST/TemplateName.h" |
41 | #include "clang/AST/Type.h" |
42 | #include "clang/AST/TypeLoc.h" |
43 | #include "clang/Basic/LLVM.h" |
44 | #include "clang/Basic/OpenMPKinds.h" |
45 | #include "clang/Basic/Specifiers.h" |
46 | #include "llvm/ADT/PointerIntPair.h" |
47 | #include "llvm/ADT/SmallVector.h" |
48 | #include "llvm/Support/Casting.h" |
49 | #include <algorithm> |
50 | #include <cstddef> |
51 | #include <type_traits> |
52 | |
53 | namespace clang { |
54 | |
55 | // A helper macro to implement short-circuiting when recursing. It |
56 | // invokes CALL_EXPR, which must be a method call, on the derived |
57 | // object (s.t. a user of RecursiveASTVisitor can override the method |
58 | // in CALL_EXPR). |
59 | #define TRY_TO(CALL_EXPR) \ |
60 | do { \ |
61 | if (!getDerived().CALL_EXPR) \ |
62 | return false; \ |
63 | } while (false) |
64 | |
65 | namespace detail { |
66 | |
67 | template <typename T, typename U> |
68 | struct has_same_member_pointer_type : std::false_type {}; |
69 | template <typename T, typename U, typename R, typename... P> |
70 | struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> |
71 | : std::true_type {}; |
72 | |
73 | /// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr |
74 | /// are pointers to the same non-static member function. |
75 | template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> |
76 | LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_NODEBUG auto |
77 | isSameMethod([[maybe_unused]] FirstMethodPtrTy FirstMethodPtr, |
78 | [[maybe_unused]] SecondMethodPtrTy SecondMethodPtr) |
79 | -> bool { |
80 | if constexpr (has_same_member_pointer_type<FirstMethodPtrTy, |
81 | SecondMethodPtrTy>::value) |
82 | return FirstMethodPtr == SecondMethodPtr; |
83 | return false; |
84 | } |
85 | |
86 | } // end namespace detail |
87 | |
88 | /// A class that does preorder or postorder |
89 | /// depth-first traversal on the entire Clang AST and visits each node. |
90 | /// |
91 | /// This class performs three distinct tasks: |
92 | /// 1. traverse the AST (i.e. go to each node); |
93 | /// 2. at a given node, walk up the class hierarchy, starting from |
94 | /// the node's dynamic type, until the top-most class (e.g. Stmt, |
95 | /// Decl, or Type) is reached. |
96 | /// 3. given a (node, class) combination, where 'class' is some base |
97 | /// class of the dynamic type of 'node', call a user-overridable |
98 | /// function to actually visit the node. |
99 | /// |
100 | /// These tasks are done by three groups of methods, respectively: |
101 | /// 1. TraverseDecl(Decl *x) does task #1. It is the entry point |
102 | /// for traversing an AST rooted at x. This method simply |
103 | /// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo |
104 | /// is the dynamic type of *x, which calls WalkUpFromFoo(x) and |
105 | /// then recursively visits the child nodes of x. |
106 | /// TraverseStmt(Stmt *x) and TraverseType(QualType x) work |
107 | /// similarly. |
108 | /// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit |
109 | /// any child node of x. Instead, it first calls WalkUpFromBar(x) |
110 | /// where Bar is the direct parent class of Foo (unless Foo has |
111 | /// no parent), and then calls VisitFoo(x) (see the next list item). |
112 | /// 3. VisitFoo(Foo *x) does task #3. |
113 | /// |
114 | /// These three method groups are tiered (Traverse* > WalkUpFrom* > |
115 | /// Visit*). A method (e.g. Traverse*) may call methods from the same |
116 | /// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). |
117 | /// It may not call methods from a higher tier. |
118 | /// |
119 | /// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar |
120 | /// is Foo's super class) before calling VisitFoo(), the result is |
121 | /// that the Visit*() methods for a given node are called in the |
122 | /// top-down order (e.g. for a node of type NamespaceDecl, the order will |
123 | /// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). |
124 | /// |
125 | /// This scheme guarantees that all Visit*() calls for the same AST |
126 | /// node are grouped together. In other words, Visit*() methods for |
127 | /// different nodes are never interleaved. |
128 | /// |
129 | /// Clients of this visitor should subclass the visitor (providing |
130 | /// themselves as the template argument, using the curiously recurring |
131 | /// template pattern) and override any of the Traverse*, WalkUpFrom*, |
132 | /// and Visit* methods for declarations, types, statements, |
133 | /// expressions, or other AST nodes where the visitor should customize |
134 | /// behavior. Most users only need to override Visit*. Advanced |
135 | /// users may override Traverse* and WalkUpFrom* to implement custom |
136 | /// traversal strategies. Returning false from one of these overridden |
137 | /// functions will abort the entire traversal. |
138 | /// |
139 | /// By default, this visitor tries to visit every part of the explicit |
140 | /// source code exactly once. The default policy towards templates |
141 | /// is to descend into the 'pattern' class or function body, not any |
142 | /// explicit or implicit instantiations. Explicit specializations |
143 | /// are still visited, and the patterns of partial specializations |
144 | /// are visited separately. This behavior can be changed by |
145 | /// overriding shouldVisitTemplateInstantiations() in the derived class |
146 | /// to return true, in which case all known implicit and explicit |
147 | /// instantiations will be visited at the same time as the pattern |
148 | /// from which they were produced. |
149 | /// |
150 | /// By default, this visitor preorder traverses the AST. If postorder traversal |
151 | /// is needed, the \c shouldTraversePostOrder method needs to be overridden |
152 | /// to return \c true. |
153 | template <typename Derived> class RecursiveASTVisitor { |
154 | public: |
155 | /// A queue used for performing data recursion over statements. |
156 | /// Parameters involving this type are used to implement data |
157 | /// recursion over Stmts and Exprs within this class, and should |
158 | /// typically not be explicitly specified by derived classes. |
159 | /// The bool bit indicates whether the statement has been traversed or not. |
160 | typedef SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>> |
161 | DataRecursionQueue; |
162 | |
163 | /// Return a reference to the derived class. |
164 | Derived &getDerived() { return *static_cast<Derived *>(this); } |
165 | |
166 | /// Return whether this visitor should recurse into |
167 | /// template instantiations. |
168 | bool shouldVisitTemplateInstantiations() const { return false; } |
169 | |
170 | /// Return whether this visitor should recurse into the types of |
171 | /// TypeLocs. |
172 | bool shouldWalkTypesOfTypeLocs() const { return true; } |
173 | |
174 | /// Return whether this visitor should recurse into implicit |
175 | /// code, e.g., implicit constructors and destructors. |
176 | bool shouldVisitImplicitCode() const { return false; } |
177 | |
178 | /// Return whether this visitor should recurse into lambda body |
179 | bool shouldVisitLambdaBody() const { return true; } |
180 | |
181 | /// Return whether this visitor should traverse post-order. |
182 | bool shouldTraversePostOrder() const { return false; } |
183 | |
184 | /// Recursively visits an entire AST, starting from the TranslationUnitDecl. |
185 | /// \returns false if visitation was terminated early. |
186 | bool TraverseAST(ASTContext &AST) { |
187 | // Currently just an alias for TraverseDecl(TUDecl), but kept in case |
188 | // we change the implementation again. |
189 | return getDerived().TraverseDecl(AST.getTranslationUnitDecl()); |
190 | } |
191 | |
192 | /// Recursively visit a statement or expression, by |
193 | /// dispatching to Traverse*() based on the argument's dynamic type. |
194 | /// |
195 | /// \returns false if the visitation was terminated early, true |
196 | /// otherwise (including when the argument is nullptr). |
197 | bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr); |
198 | |
199 | /// Invoked before visiting a statement or expression via data recursion. |
200 | /// |
201 | /// \returns false to skip visiting the node, true otherwise. |
202 | bool dataTraverseStmtPre(Stmt *S) { return true; } |
203 | |
204 | /// Invoked after visiting a statement or expression via data recursion. |
205 | /// This is not invoked if the previously invoked \c dataTraverseStmtPre |
206 | /// returned false. |
207 | /// |
208 | /// \returns false if the visitation was terminated early, true otherwise. |
209 | bool dataTraverseStmtPost(Stmt *S) { return true; } |
210 | |
211 | /// Recursively visit a type, by dispatching to |
212 | /// Traverse*Type() based on the argument's getTypeClass() property. |
213 | /// |
214 | /// \returns false if the visitation was terminated early, true |
215 | /// otherwise (including when the argument is a Null type). |
216 | bool TraverseType(QualType T); |
217 | |
218 | /// Recursively visit a type with location, by dispatching to |
219 | /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. |
220 | /// |
221 | /// \returns false if the visitation was terminated early, true |
222 | /// otherwise (including when the argument is a Null type location). |
223 | bool TraverseTypeLoc(TypeLoc TL); |
224 | |
225 | /// Recursively visit an attribute, by dispatching to |
226 | /// Traverse*Attr() based on the argument's dynamic type. |
227 | /// |
228 | /// \returns false if the visitation was terminated early, true |
229 | /// otherwise (including when the argument is a Null type location). |
230 | bool TraverseAttr(Attr *At); |
231 | |
232 | /// Recursively visit a declaration, by dispatching to |
233 | /// Traverse*Decl() based on the argument's dynamic type. |
234 | /// |
235 | /// \returns false if the visitation was terminated early, true |
236 | /// otherwise (including when the argument is NULL). |
237 | bool TraverseDecl(Decl *D); |
238 | |
239 | /// Recursively visit a C++ nested-name-specifier. |
240 | /// |
241 | /// \returns false if the visitation was terminated early, true otherwise. |
242 | bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); |
243 | |
244 | /// Recursively visit a C++ nested-name-specifier with location |
245 | /// information. |
246 | /// |
247 | /// \returns false if the visitation was terminated early, true otherwise. |
248 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); |
249 | |
250 | /// Recursively visit a name with its location information. |
251 | /// |
252 | /// \returns false if the visitation was terminated early, true otherwise. |
253 | bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); |
254 | |
255 | /// Recursively visit a template name and dispatch to the |
256 | /// appropriate method. |
257 | /// |
258 | /// \returns false if the visitation was terminated early, true otherwise. |
259 | bool TraverseTemplateName(TemplateName Template); |
260 | |
261 | /// Recursively visit a template argument and dispatch to the |
262 | /// appropriate method for the argument type. |
263 | /// |
264 | /// \returns false if the visitation was terminated early, true otherwise. |
265 | // FIXME: migrate callers to TemplateArgumentLoc instead. |
266 | bool TraverseTemplateArgument(const TemplateArgument &Arg); |
267 | |
268 | /// Recursively visit a template argument location and dispatch to the |
269 | /// appropriate method for the argument type. |
270 | /// |
271 | /// \returns false if the visitation was terminated early, true otherwise. |
272 | bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); |
273 | |
274 | /// Recursively visit a set of template arguments. |
275 | /// This can be overridden by a subclass, but it's not expected that |
276 | /// will be needed -- this visitor always dispatches to another. |
277 | /// |
278 | /// \returns false if the visitation was terminated early, true otherwise. |
279 | // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. |
280 | bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args); |
281 | |
282 | /// Recursively visit a base specifier. This can be overridden by a |
283 | /// subclass. |
284 | /// |
285 | /// \returns false if the visitation was terminated early, true otherwise. |
286 | bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base); |
287 | |
288 | /// Recursively visit a constructor initializer. This |
289 | /// automatically dispatches to another visitor for the initializer |
290 | /// expression, but not for the name of the initializer, so may |
291 | /// be overridden for clients that need access to the name. |
292 | /// |
293 | /// \returns false if the visitation was terminated early, true otherwise. |
294 | bool TraverseConstructorInitializer(CXXCtorInitializer *Init); |
295 | |
296 | /// Recursively visit a lambda capture. \c Init is the expression that |
297 | /// will be used to initialize the capture. |
298 | /// |
299 | /// \returns false if the visitation was terminated early, true otherwise. |
300 | bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, |
301 | Expr *Init); |
302 | |
303 | /// Recursively visit the syntactic or semantic form of an |
304 | /// initialization list. |
305 | /// |
306 | /// \returns false if the visitation was terminated early, true otherwise. |
307 | bool TraverseSynOrSemInitListExpr(InitListExpr *S, |
308 | DataRecursionQueue *Queue = nullptr); |
309 | |
310 | /// Recursively visit an Objective-C protocol reference with location |
311 | /// information. |
312 | /// |
313 | /// \returns false if the visitation was terminated early, true otherwise. |
314 | bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc); |
315 | |
316 | /// Recursively visit concept reference with location information. |
317 | /// |
318 | /// \returns false if the visitation was terminated early, true otherwise. |
319 | bool TraverseConceptReference(ConceptReference *CR); |
320 | |
321 | // Visit concept reference. |
322 | bool VisitConceptReference(ConceptReference *CR) { return true; } |
323 | // ---- Methods on Attrs ---- |
324 | |
325 | // Visit an attribute. |
326 | bool VisitAttr(Attr *A) { return true; } |
327 | |
328 | // Declare Traverse* and empty Visit* for all Attr classes. |
329 | #define ATTR_VISITOR_DECLS_ONLY |
330 | #include "clang/AST/AttrVisitor.inc" |
331 | #undef ATTR_VISITOR_DECLS_ONLY |
332 | |
333 | // ---- Methods on Stmts ---- |
334 | |
335 | Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } |
336 | |
337 | private: |
338 | // Traverse the given statement. If the most-derived traverse function takes a |
339 | // data recursion queue, pass it on; otherwise, discard it. Note that the |
340 | // first branch of this conditional must compile whether or not the derived |
341 | // class can take a queue, so if we're taking the second arm, make the first |
342 | // arm call our function rather than the derived class version. |
343 | #define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \ |
344 | (::clang::detail::has_same_member_pointer_type< \ |
345 | decltype(&RecursiveASTVisitor::Traverse##NAME), \ |
346 | decltype(&Derived::Traverse##NAME)>::value \ |
347 | ? static_cast<std::conditional_t< \ |
348 | ::clang::detail::has_same_member_pointer_type< \ |
349 | decltype(&RecursiveASTVisitor::Traverse##NAME), \ |
350 | decltype(&Derived::Traverse##NAME)>::value, \ |
351 | Derived &, RecursiveASTVisitor &>>(*this) \ |
352 | .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \ |
353 | : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))) |
354 | |
355 | // Try to traverse the given statement, or enqueue it if we're performing data |
356 | // recursion in the middle of traversing another statement. Can only be called |
357 | // from within a DEF_TRAVERSE_STMT body or similar context. |
358 | #define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \ |
359 | do { \ |
360 | if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \ |
361 | return false; \ |
362 | } while (false) |
363 | |
364 | public: |
365 | // Declare Traverse*() for all concrete Stmt classes. |
366 | #define ABSTRACT_STMT(STMT) |
367 | #define STMT(CLASS, PARENT) \ |
368 | bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr); |
369 | #include "clang/AST/StmtNodes.inc" |
370 | // The above header #undefs ABSTRACT_STMT and STMT upon exit. |
371 | |
372 | // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. |
373 | bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } |
374 | bool VisitStmt(Stmt *S) { return true; } |
375 | #define STMT(CLASS, PARENT) \ |
376 | bool WalkUpFrom##CLASS(CLASS *S) { \ |
377 | TRY_TO(WalkUpFrom##PARENT(S)); \ |
378 | TRY_TO(Visit##CLASS(S)); \ |
379 | return true; \ |
380 | } \ |
381 | bool Visit##CLASS(CLASS *S) { return true; } |
382 | #include "clang/AST/StmtNodes.inc" |
383 | |
384 | // ---- Methods on Types ---- |
385 | // FIXME: revamp to take TypeLoc's rather than Types. |
386 | |
387 | // Declare Traverse*() for all concrete Type classes. |
388 | #define ABSTRACT_TYPE(CLASS, BASE) |
389 | #define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); |
390 | #include "clang/AST/TypeNodes.inc" |
391 | // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. |
392 | |
393 | // Define WalkUpFrom*() and empty Visit*() for all Type classes. |
394 | bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } |
395 | bool VisitType(Type *T) { return true; } |
396 | #define TYPE(CLASS, BASE) \ |
397 | bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ |
398 | TRY_TO(WalkUpFrom##BASE(T)); \ |
399 | TRY_TO(Visit##CLASS##Type(T)); \ |
400 | return true; \ |
401 | } \ |
402 | bool Visit##CLASS##Type(CLASS##Type *T) { return true; } |
403 | #include "clang/AST/TypeNodes.inc" |
404 | |
405 | // ---- Methods on TypeLocs ---- |
406 | // FIXME: this currently just calls the matching Type methods |
407 | |
408 | // Declare Traverse*() for all concrete TypeLoc classes. |
409 | #define ABSTRACT_TYPELOC(CLASS, BASE) |
410 | #define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); |
411 | #include "clang/AST/TypeLocNodes.def" |
412 | // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. |
413 | |
414 | // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. |
415 | bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } |
416 | bool VisitTypeLoc(TypeLoc TL) { return true; } |
417 | |
418 | // QualifiedTypeLoc and UnqualTypeLoc are not declared in |
419 | // TypeNodes.inc and thus need to be handled specially. |
420 | bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { |
421 | return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); |
422 | } |
423 | bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } |
424 | bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { |
425 | return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); |
426 | } |
427 | bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } |
428 | |
429 | // Note that BASE includes trailing 'Type' which CLASS doesn't. |
430 | #define TYPE(CLASS, BASE) \ |
431 | bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ |
432 | TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ |
433 | TRY_TO(Visit##CLASS##TypeLoc(TL)); \ |
434 | return true; \ |
435 | } \ |
436 | bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } |
437 | #include "clang/AST/TypeNodes.inc" |
438 | |
439 | // ---- Methods on Decls ---- |
440 | |
441 | // Declare Traverse*() for all concrete Decl classes. |
442 | #define ABSTRACT_DECL(DECL) |
443 | #define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D); |
444 | #include "clang/AST/DeclNodes.inc" |
445 | // The above header #undefs ABSTRACT_DECL and DECL upon exit. |
446 | |
447 | // Define WalkUpFrom*() and empty Visit*() for all Decl classes. |
448 | bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } |
449 | bool VisitDecl(Decl *D) { return true; } |
450 | #define DECL(CLASS, BASE) \ |
451 | bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ |
452 | TRY_TO(WalkUpFrom##BASE(D)); \ |
453 | TRY_TO(Visit##CLASS##Decl(D)); \ |
454 | return true; \ |
455 | } \ |
456 | bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } |
457 | #include "clang/AST/DeclNodes.inc" |
458 | |
459 | bool canIgnoreChildDeclWhileTraversingDeclContext(const Decl *Child); |
460 | |
461 | #define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ |
462 | bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D); |
463 | DEF_TRAVERSE_TMPL_INST(Class) |
464 | DEF_TRAVERSE_TMPL_INST(Var) |
465 | DEF_TRAVERSE_TMPL_INST(Function) |
466 | #undef DEF_TRAVERSE_TMPL_INST |
467 | |
468 | bool TraverseTypeConstraint(const TypeConstraint *C); |
469 | |
470 | bool TraverseConceptRequirement(concepts::Requirement *R); |
471 | bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R); |
472 | bool TraverseConceptExprRequirement(concepts::ExprRequirement *R); |
473 | bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R); |
474 | |
475 | bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); |
476 | |
477 | private: |
478 | // These are helper methods used by more than one Traverse* method. |
479 | bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); |
480 | |
481 | // Traverses template parameter lists of either a DeclaratorDecl or TagDecl. |
482 | template <typename T> |
483 | bool TraverseDeclTemplateParameterLists(T *D); |
484 | |
485 | bool TraverseTemplateTypeParamDeclConstraints(const TemplateTypeParmDecl *D); |
486 | |
487 | bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, |
488 | unsigned Count); |
489 | bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); |
490 | bool TraverseRecordHelper(RecordDecl *D); |
491 | bool TraverseCXXRecordHelper(CXXRecordDecl *D); |
492 | bool TraverseDeclaratorHelper(DeclaratorDecl *D); |
493 | bool TraverseDeclContextHelper(DeclContext *DC); |
494 | bool TraverseFunctionHelper(FunctionDecl *D); |
495 | bool TraverseVarHelper(VarDecl *D); |
496 | bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); |
497 | bool TraverseOMPLoopDirective(OMPLoopDirective *S); |
498 | bool TraverseOMPClause(OMPClause *C); |
499 | #define GEN_CLANG_CLAUSE_CLASS |
500 | #define CLAUSE_CLASS(Enum, Str, Class) bool Visit##Class(Class *C); |
501 | #include "llvm/Frontend/OpenMP/OMP.inc" |
502 | /// Process clauses with list of variables. |
503 | template <typename T> bool VisitOMPClauseList(T *Node); |
504 | /// Process clauses with pre-initis. |
505 | bool VisitOMPClauseWithPreInit(OMPClauseWithPreInit *Node); |
506 | bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node); |
507 | |
508 | bool PostVisitStmt(Stmt *S); |
509 | bool TraverseOpenACCConstructStmt(OpenACCConstructStmt *S); |
510 | bool |
511 | TraverseOpenACCAssociatedStmtConstruct(OpenACCAssociatedStmtConstruct *S); |
512 | bool VisitOpenACCClauseList(ArrayRef<const OpenACCClause *>); |
513 | }; |
514 | |
515 | template <typename Derived> |
516 | bool RecursiveASTVisitor<Derived>::TraverseTypeConstraint( |
517 | const TypeConstraint *C) { |
518 | if (!getDerived().shouldVisitImplicitCode()) { |
519 | TRY_TO(TraverseConceptReference(C->getConceptReference())); |
520 | return true; |
521 | } |
522 | if (Expr *IDC = C->getImmediatelyDeclaredConstraint()) { |
523 | TRY_TO(TraverseStmt(IDC)); |
524 | } else { |
525 | // Avoid traversing the ConceptReference in the TypeConstraint |
526 | // if we have an immediately-declared-constraint, otherwise |
527 | // we'll end up visiting the concept and the arguments in |
528 | // the TC twice. |
529 | TRY_TO(TraverseConceptReference(C->getConceptReference())); |
530 | } |
531 | return true; |
532 | } |
533 | |
534 | template <typename Derived> |
535 | bool RecursiveASTVisitor<Derived>::TraverseConceptRequirement( |
536 | concepts::Requirement *R) { |
537 | switch (R->getKind()) { |
538 | case concepts::Requirement::RK_Type: |
539 | return getDerived().TraverseConceptTypeRequirement( |
540 | cast<concepts::TypeRequirement>(R)); |
541 | case concepts::Requirement::RK_Simple: |
542 | case concepts::Requirement::RK_Compound: |
543 | return getDerived().TraverseConceptExprRequirement( |
544 | cast<concepts::ExprRequirement>(R)); |
545 | case concepts::Requirement::RK_Nested: |
546 | return getDerived().TraverseConceptNestedRequirement( |
547 | cast<concepts::NestedRequirement>(R)); |
548 | } |
549 | llvm_unreachable("unexpected case" ); |
550 | } |
551 | |
552 | template <typename Derived> |
553 | bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, |
554 | DataRecursionQueue *Queue) { |
555 | // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. |
556 | switch (S->getStmtClass()) { |
557 | case Stmt::NoStmtClass: |
558 | break; |
559 | #define ABSTRACT_STMT(STMT) |
560 | #define STMT(CLASS, PARENT) \ |
561 | case Stmt::CLASS##Class: \ |
562 | return TRAVERSE_STMT_BASE(CLASS, CLASS, S, Queue); |
563 | #include "clang/AST/StmtNodes.inc" |
564 | } |
565 | |
566 | return true; |
567 | } |
568 | |
569 | #undef DISPATCH_STMT |
570 | |
571 | template <typename Derived> |
572 | bool RecursiveASTVisitor<Derived>::TraverseConceptTypeRequirement( |
573 | concepts::TypeRequirement *R) { |
574 | if (R->isSubstitutionFailure()) |
575 | return true; |
576 | return getDerived().TraverseTypeLoc(R->getType()->getTypeLoc()); |
577 | } |
578 | |
579 | template <typename Derived> |
580 | bool RecursiveASTVisitor<Derived>::TraverseConceptExprRequirement( |
581 | concepts::ExprRequirement *R) { |
582 | if (!R->isExprSubstitutionFailure()) |
583 | TRY_TO(TraverseStmt(R->getExpr())); |
584 | auto &RetReq = R->getReturnTypeRequirement(); |
585 | if (RetReq.isTypeConstraint()) { |
586 | if (getDerived().shouldVisitImplicitCode()) { |
587 | TRY_TO(TraverseTemplateParameterListHelper( |
588 | RetReq.getTypeConstraintTemplateParameterList())); |
589 | } else { |
590 | // Template parameter list is implicit, visit constraint directly. |
591 | TRY_TO(TraverseTypeConstraint(RetReq.getTypeConstraint())); |
592 | } |
593 | } |
594 | return true; |
595 | } |
596 | |
597 | template <typename Derived> |
598 | bool RecursiveASTVisitor<Derived>::TraverseConceptNestedRequirement( |
599 | concepts::NestedRequirement *R) { |
600 | if (!R->hasInvalidConstraint()) |
601 | return getDerived().TraverseStmt(R->getConstraintExpr()); |
602 | return true; |
603 | } |
604 | |
605 | template <typename Derived> |
606 | bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) { |
607 | // In pre-order traversal mode, each Traverse##STMT method is responsible for |
608 | // calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT and |
609 | // does not call the default implementation, the WalkUpFrom callback is not |
610 | // called. Post-order traversal mode should provide the same behavior |
611 | // regarding method overrides. |
612 | // |
613 | // In post-order traversal mode the Traverse##STMT method, when it receives a |
614 | // DataRecursionQueue, can't call WalkUpFrom after traversing children because |
615 | // it only enqueues the children and does not traverse them. TraverseStmt |
616 | // traverses the enqueued children, and we call WalkUpFrom here. |
617 | // |
618 | // However, to make pre-order and post-order modes identical with regards to |
619 | // whether they call WalkUpFrom at all, we call WalkUpFrom if and only if the |
620 | // user did not override the Traverse##STMT method. We implement the override |
621 | // check with isSameMethod calls below. |
622 | |
623 | switch (S->getStmtClass()) { |
624 | case Stmt::NoStmtClass: |
625 | break; |
626 | #define ABSTRACT_STMT(STMT) |
627 | #define STMT(CLASS, PARENT) \ |
628 | case Stmt::CLASS##Class: \ |
629 | if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \ |
630 | &Derived::Traverse##CLASS)) { \ |
631 | TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); \ |
632 | } \ |
633 | break; |
634 | #define INITLISTEXPR(CLASS, PARENT) \ |
635 | case Stmt::CLASS##Class: \ |
636 | if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \ |
637 | &Derived::Traverse##CLASS)) { \ |
638 | auto ILE = static_cast<CLASS *>(S); \ |
639 | if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \ |
640 | TRY_TO(WalkUpFrom##CLASS(Syn)); \ |
641 | if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \ |
642 | TRY_TO(WalkUpFrom##CLASS(Sem)); \ |
643 | } \ |
644 | break; |
645 | #include "clang/AST/StmtNodes.inc" |
646 | } |
647 | |
648 | return true; |
649 | } |
650 | |
651 | #undef DISPATCH_STMT |
652 | |
653 | template <typename Derived> |
654 | bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S, |
655 | DataRecursionQueue *Queue) { |
656 | if (!S) |
657 | return true; |
658 | |
659 | if (Queue) { |
660 | Queue->push_back({S, false}); |
661 | return true; |
662 | } |
663 | |
664 | SmallVector<llvm::PointerIntPair<Stmt *, 1, bool>, 8> LocalQueue; |
665 | LocalQueue.push_back({S, false}); |
666 | |
667 | while (!LocalQueue.empty()) { |
668 | auto &CurrSAndVisited = LocalQueue.back(); |
669 | Stmt *CurrS = CurrSAndVisited.getPointer(); |
670 | bool Visited = CurrSAndVisited.getInt(); |
671 | if (Visited) { |
672 | LocalQueue.pop_back(); |
673 | TRY_TO(dataTraverseStmtPost(CurrS)); |
674 | if (getDerived().shouldTraversePostOrder()) { |
675 | TRY_TO(PostVisitStmt(CurrS)); |
676 | } |
677 | continue; |
678 | } |
679 | |
680 | if (getDerived().dataTraverseStmtPre(CurrS)) { |
681 | CurrSAndVisited.setInt(true); |
682 | size_t N = LocalQueue.size(); |
683 | TRY_TO(dataTraverseNode(CurrS, &LocalQueue)); |
684 | // Process new children in the order they were added. |
685 | std::reverse(LocalQueue.begin() + N, LocalQueue.end()); |
686 | } else { |
687 | LocalQueue.pop_back(); |
688 | } |
689 | } |
690 | |
691 | return true; |
692 | } |
693 | |
694 | template <typename Derived> |
695 | bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { |
696 | if (T.isNull()) |
697 | return true; |
698 | |
699 | switch (T->getTypeClass()) { |
700 | #define ABSTRACT_TYPE(CLASS, BASE) |
701 | #define TYPE(CLASS, BASE) \ |
702 | case Type::CLASS: \ |
703 | return getDerived().Traverse##CLASS##Type( \ |
704 | static_cast<CLASS##Type *>(const_cast<Type *>(T.getTypePtr()))); |
705 | #include "clang/AST/TypeNodes.inc" |
706 | } |
707 | |
708 | return true; |
709 | } |
710 | |
711 | template <typename Derived> |
712 | bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { |
713 | if (TL.isNull()) |
714 | return true; |
715 | |
716 | switch (TL.getTypeLocClass()) { |
717 | #define ABSTRACT_TYPELOC(CLASS, BASE) |
718 | #define TYPELOC(CLASS, BASE) \ |
719 | case TypeLoc::CLASS: \ |
720 | return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); |
721 | #include "clang/AST/TypeLocNodes.def" |
722 | } |
723 | |
724 | return true; |
725 | } |
726 | |
727 | // Define the Traverse*Attr(Attr* A) methods |
728 | #define VISITORCLASS RecursiveASTVisitor |
729 | #include "clang/AST/AttrVisitor.inc" |
730 | #undef VISITORCLASS |
731 | |
732 | template <typename Derived> |
733 | bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { |
734 | if (!D) |
735 | return true; |
736 | |
737 | // As a syntax visitor, by default we want to ignore declarations for |
738 | // implicit declarations (ones not typed explicitly by the user). |
739 | if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) { |
740 | // For an implicit template type parameter, its type constraints are not |
741 | // implicit and are not represented anywhere else. We still need to visit |
742 | // them. |
743 | if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D)) |
744 | return TraverseTemplateTypeParamDeclConstraints(D: TTPD); |
745 | return true; |
746 | } |
747 | |
748 | switch (D->getKind()) { |
749 | #define ABSTRACT_DECL(DECL) |
750 | #define DECL(CLASS, BASE) \ |
751 | case Decl::CLASS: \ |
752 | if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \ |
753 | return false; \ |
754 | break; |
755 | #include "clang/AST/DeclNodes.inc" |
756 | } |
757 | return true; |
758 | } |
759 | |
760 | template <typename Derived> |
761 | bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( |
762 | NestedNameSpecifier *NNS) { |
763 | if (!NNS) |
764 | return true; |
765 | |
766 | if (NNS->getPrefix()) |
767 | TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); |
768 | |
769 | switch (NNS->getKind()) { |
770 | case NestedNameSpecifier::Identifier: |
771 | case NestedNameSpecifier::Namespace: |
772 | case NestedNameSpecifier::NamespaceAlias: |
773 | case NestedNameSpecifier::Global: |
774 | case NestedNameSpecifier::Super: |
775 | return true; |
776 | |
777 | case NestedNameSpecifier::TypeSpec: |
778 | case NestedNameSpecifier::TypeSpecWithTemplate: |
779 | TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); |
780 | } |
781 | |
782 | return true; |
783 | } |
784 | |
785 | template <typename Derived> |
786 | bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( |
787 | NestedNameSpecifierLoc NNS) { |
788 | if (!NNS) |
789 | return true; |
790 | |
791 | if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) |
792 | TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); |
793 | |
794 | switch (NNS.getNestedNameSpecifier()->getKind()) { |
795 | case NestedNameSpecifier::Identifier: |
796 | case NestedNameSpecifier::Namespace: |
797 | case NestedNameSpecifier::NamespaceAlias: |
798 | case NestedNameSpecifier::Global: |
799 | case NestedNameSpecifier::Super: |
800 | return true; |
801 | |
802 | case NestedNameSpecifier::TypeSpec: |
803 | case NestedNameSpecifier::TypeSpecWithTemplate: |
804 | TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); |
805 | break; |
806 | } |
807 | |
808 | return true; |
809 | } |
810 | |
811 | template <typename Derived> |
812 | bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( |
813 | DeclarationNameInfo NameInfo) { |
814 | switch (NameInfo.getName().getNameKind()) { |
815 | case DeclarationName::CXXConstructorName: |
816 | case DeclarationName::CXXDestructorName: |
817 | case DeclarationName::CXXConversionFunctionName: |
818 | if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) |
819 | TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); |
820 | break; |
821 | |
822 | case DeclarationName::CXXDeductionGuideName: |
823 | TRY_TO(TraverseTemplateName( |
824 | TemplateName(NameInfo.getName().getCXXDeductionGuideTemplate()))); |
825 | break; |
826 | |
827 | case DeclarationName::Identifier: |
828 | case DeclarationName::ObjCZeroArgSelector: |
829 | case DeclarationName::ObjCOneArgSelector: |
830 | case DeclarationName::ObjCMultiArgSelector: |
831 | case DeclarationName::CXXOperatorName: |
832 | case DeclarationName::CXXLiteralOperatorName: |
833 | case DeclarationName::CXXUsingDirective: |
834 | break; |
835 | } |
836 | |
837 | return true; |
838 | } |
839 | |
840 | template <typename Derived> |
841 | bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { |
842 | if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) |
843 | TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); |
844 | else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) |
845 | TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); |
846 | |
847 | return true; |
848 | } |
849 | |
850 | template <typename Derived> |
851 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( |
852 | const TemplateArgument &Arg) { |
853 | switch (Arg.getKind()) { |
854 | case TemplateArgument::Null: |
855 | case TemplateArgument::Declaration: |
856 | case TemplateArgument::Integral: |
857 | case TemplateArgument::NullPtr: |
858 | case TemplateArgument::StructuralValue: |
859 | return true; |
860 | |
861 | case TemplateArgument::Type: |
862 | return getDerived().TraverseType(Arg.getAsType()); |
863 | |
864 | case TemplateArgument::Template: |
865 | case TemplateArgument::TemplateExpansion: |
866 | return getDerived().TraverseTemplateName( |
867 | Arg.getAsTemplateOrTemplatePattern()); |
868 | |
869 | case TemplateArgument::Expression: |
870 | return getDerived().TraverseStmt(Arg.getAsExpr()); |
871 | |
872 | case TemplateArgument::Pack: |
873 | return getDerived().TraverseTemplateArguments(Arg.pack_elements()); |
874 | } |
875 | |
876 | return true; |
877 | } |
878 | |
879 | // FIXME: no template name location? |
880 | // FIXME: no source locations for a template argument pack? |
881 | template <typename Derived> |
882 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( |
883 | const TemplateArgumentLoc &ArgLoc) { |
884 | const TemplateArgument &Arg = ArgLoc.getArgument(); |
885 | |
886 | switch (Arg.getKind()) { |
887 | case TemplateArgument::Null: |
888 | case TemplateArgument::Declaration: |
889 | case TemplateArgument::Integral: |
890 | case TemplateArgument::NullPtr: |
891 | case TemplateArgument::StructuralValue: |
892 | return true; |
893 | |
894 | case TemplateArgument::Type: { |
895 | // FIXME: how can TSI ever be NULL? |
896 | if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) |
897 | return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); |
898 | else |
899 | return getDerived().TraverseType(Arg.getAsType()); |
900 | } |
901 | |
902 | case TemplateArgument::Template: |
903 | case TemplateArgument::TemplateExpansion: |
904 | if (ArgLoc.getTemplateQualifierLoc()) |
905 | TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( |
906 | ArgLoc.getTemplateQualifierLoc())); |
907 | return getDerived().TraverseTemplateName( |
908 | Arg.getAsTemplateOrTemplatePattern()); |
909 | |
910 | case TemplateArgument::Expression: |
911 | return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); |
912 | |
913 | case TemplateArgument::Pack: |
914 | return getDerived().TraverseTemplateArguments(Arg.pack_elements()); |
915 | } |
916 | |
917 | return true; |
918 | } |
919 | |
920 | template <typename Derived> |
921 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( |
922 | ArrayRef<TemplateArgument> Args) { |
923 | for (const TemplateArgument &Arg : Args) |
924 | TRY_TO(TraverseTemplateArgument(Arg)); |
925 | |
926 | return true; |
927 | } |
928 | |
929 | template <typename Derived> |
930 | bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( |
931 | CXXCtorInitializer *Init) { |
932 | if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) |
933 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
934 | |
935 | if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) |
936 | TRY_TO(TraverseStmt(Init->getInit())); |
937 | |
938 | return true; |
939 | } |
940 | |
941 | template <typename Derived> |
942 | bool |
943 | RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, |
944 | const LambdaCapture *C, |
945 | Expr *Init) { |
946 | if (LE->isInitCapture(Capture: C)) |
947 | TRY_TO(TraverseDecl(C->getCapturedVar())); |
948 | else |
949 | TRY_TO(TraverseStmt(Init)); |
950 | return true; |
951 | } |
952 | |
953 | // ----------------- Type traversal ----------------- |
954 | |
955 | // This macro makes available a variable T, the passed-in type. |
956 | #define DEF_TRAVERSE_TYPE(TYPE, CODE) \ |
957 | template <typename Derived> \ |
958 | bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \ |
959 | if (!getDerived().shouldTraversePostOrder()) \ |
960 | TRY_TO(WalkUpFrom##TYPE(T)); \ |
961 | { CODE; } \ |
962 | if (getDerived().shouldTraversePostOrder()) \ |
963 | TRY_TO(WalkUpFrom##TYPE(T)); \ |
964 | return true; \ |
965 | } |
966 | |
967 | DEF_TRAVERSE_TYPE(BuiltinType, {}) |
968 | |
969 | DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) |
970 | |
971 | DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) |
972 | |
973 | DEF_TRAVERSE_TYPE(BlockPointerType, |
974 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
975 | |
976 | DEF_TRAVERSE_TYPE(LValueReferenceType, |
977 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
978 | |
979 | DEF_TRAVERSE_TYPE(RValueReferenceType, |
980 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
981 | |
982 | DEF_TRAVERSE_TYPE(MemberPointerType, { |
983 | TRY_TO(TraverseType(QualType(T->getClass(), 0))); |
984 | TRY_TO(TraverseType(T->getPointeeType())); |
985 | }) |
986 | |
987 | DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) |
988 | |
989 | DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) |
990 | |
991 | DEF_TRAVERSE_TYPE(ConstantArrayType, { |
992 | TRY_TO(TraverseType(T->getElementType())); |
993 | if (T->getSizeExpr()) |
994 | TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr()))); |
995 | }) |
996 | |
997 | DEF_TRAVERSE_TYPE(ArrayParameterType, { |
998 | TRY_TO(TraverseType(T->getElementType())); |
999 | if (T->getSizeExpr()) |
1000 | TRY_TO(TraverseStmt(const_cast<Expr *>(T->getSizeExpr()))); |
1001 | }) |
1002 | |
1003 | DEF_TRAVERSE_TYPE(IncompleteArrayType, |
1004 | { TRY_TO(TraverseType(T->getElementType())); }) |
1005 | |
1006 | DEF_TRAVERSE_TYPE(VariableArrayType, { |
1007 | TRY_TO(TraverseType(T->getElementType())); |
1008 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
1009 | }) |
1010 | |
1011 | DEF_TRAVERSE_TYPE(DependentSizedArrayType, { |
1012 | TRY_TO(TraverseType(T->getElementType())); |
1013 | if (T->getSizeExpr()) |
1014 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
1015 | }) |
1016 | |
1017 | DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { |
1018 | TRY_TO(TraverseStmt(T->getAddrSpaceExpr())); |
1019 | TRY_TO(TraverseType(T->getPointeeType())); |
1020 | }) |
1021 | |
1022 | DEF_TRAVERSE_TYPE(DependentVectorType, { |
1023 | if (T->getSizeExpr()) |
1024 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
1025 | TRY_TO(TraverseType(T->getElementType())); |
1026 | }) |
1027 | |
1028 | DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { |
1029 | if (T->getSizeExpr()) |
1030 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
1031 | TRY_TO(TraverseType(T->getElementType())); |
1032 | }) |
1033 | |
1034 | DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) |
1035 | |
1036 | DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) |
1037 | |
1038 | DEF_TRAVERSE_TYPE(ConstantMatrixType, |
1039 | { TRY_TO(TraverseType(T->getElementType())); }) |
1040 | |
1041 | DEF_TRAVERSE_TYPE(DependentSizedMatrixType, { |
1042 | if (T->getRowExpr()) |
1043 | TRY_TO(TraverseStmt(T->getRowExpr())); |
1044 | if (T->getColumnExpr()) |
1045 | TRY_TO(TraverseStmt(T->getColumnExpr())); |
1046 | TRY_TO(TraverseType(T->getElementType())); |
1047 | }) |
1048 | |
1049 | DEF_TRAVERSE_TYPE(FunctionNoProtoType, |
1050 | { TRY_TO(TraverseType(T->getReturnType())); }) |
1051 | |
1052 | DEF_TRAVERSE_TYPE(FunctionProtoType, { |
1053 | TRY_TO(TraverseType(T->getReturnType())); |
1054 | |
1055 | for (const auto &A : T->param_types()) { |
1056 | TRY_TO(TraverseType(A)); |
1057 | } |
1058 | |
1059 | for (const auto &E : T->exceptions()) { |
1060 | TRY_TO(TraverseType(E)); |
1061 | } |
1062 | |
1063 | if (Expr *NE = T->getNoexceptExpr()) |
1064 | TRY_TO(TraverseStmt(NE)); |
1065 | }) |
1066 | |
1067 | DEF_TRAVERSE_TYPE(UsingType, {}) |
1068 | DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) |
1069 | DEF_TRAVERSE_TYPE(TypedefType, {}) |
1070 | |
1071 | DEF_TRAVERSE_TYPE(TypeOfExprType, |
1072 | { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) |
1073 | |
1074 | DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnmodifiedType())); }) |
1075 | |
1076 | DEF_TRAVERSE_TYPE(DecltypeType, |
1077 | { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) |
1078 | |
1079 | DEF_TRAVERSE_TYPE(PackIndexingType, { |
1080 | TRY_TO(TraverseType(T->getPattern())); |
1081 | TRY_TO(TraverseStmt(T->getIndexExpr())); |
1082 | }) |
1083 | |
1084 | DEF_TRAVERSE_TYPE(UnaryTransformType, { |
1085 | TRY_TO(TraverseType(T->getBaseType())); |
1086 | TRY_TO(TraverseType(T->getUnderlyingType())); |
1087 | }) |
1088 | |
1089 | DEF_TRAVERSE_TYPE(AutoType, { |
1090 | TRY_TO(TraverseType(T->getDeducedType())); |
1091 | if (T->isConstrained()) { |
1092 | TRY_TO(TraverseTemplateArguments(T->getTypeConstraintArguments())); |
1093 | } |
1094 | }) |
1095 | DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { |
1096 | TRY_TO(TraverseTemplateName(T->getTemplateName())); |
1097 | TRY_TO(TraverseType(T->getDeducedType())); |
1098 | }) |
1099 | |
1100 | DEF_TRAVERSE_TYPE(RecordType, {}) |
1101 | DEF_TRAVERSE_TYPE(EnumType, {}) |
1102 | DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) |
1103 | DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { |
1104 | TRY_TO(TraverseType(T->getReplacementType())); |
1105 | }) |
1106 | DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { |
1107 | TRY_TO(TraverseTemplateArgument(T->getArgumentPack())); |
1108 | }) |
1109 | |
1110 | DEF_TRAVERSE_TYPE(TemplateSpecializationType, { |
1111 | TRY_TO(TraverseTemplateName(T->getTemplateName())); |
1112 | TRY_TO(TraverseTemplateArguments(T->template_arguments())); |
1113 | }) |
1114 | |
1115 | DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) |
1116 | |
1117 | DEF_TRAVERSE_TYPE(AttributedType, |
1118 | { TRY_TO(TraverseType(T->getModifiedType())); }) |
1119 | |
1120 | DEF_TRAVERSE_TYPE(CountAttributedType, { |
1121 | if (T->getCountExpr()) |
1122 | TRY_TO(TraverseStmt(T->getCountExpr())); |
1123 | TRY_TO(TraverseType(T->desugar())); |
1124 | }) |
1125 | |
1126 | DEF_TRAVERSE_TYPE(BTFTagAttributedType, |
1127 | { TRY_TO(TraverseType(T->getWrappedType())); }) |
1128 | |
1129 | DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) |
1130 | |
1131 | DEF_TRAVERSE_TYPE(MacroQualifiedType, |
1132 | { TRY_TO(TraverseType(T->getUnderlyingType())); }) |
1133 | |
1134 | DEF_TRAVERSE_TYPE(ElaboratedType, { |
1135 | if (T->getQualifier()) { |
1136 | TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); |
1137 | } |
1138 | TRY_TO(TraverseType(T->getNamedType())); |
1139 | }) |
1140 | |
1141 | DEF_TRAVERSE_TYPE(DependentNameType, |
1142 | { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) |
1143 | |
1144 | DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { |
1145 | TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); |
1146 | TRY_TO(TraverseTemplateArguments(T->template_arguments())); |
1147 | }) |
1148 | |
1149 | DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) |
1150 | |
1151 | DEF_TRAVERSE_TYPE(ObjCTypeParamType, {}) |
1152 | |
1153 | DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) |
1154 | |
1155 | DEF_TRAVERSE_TYPE(ObjCObjectType, { |
1156 | // We have to watch out here because an ObjCInterfaceType's base |
1157 | // type is itself. |
1158 | if (T->getBaseType().getTypePtr() != T) |
1159 | TRY_TO(TraverseType(T->getBaseType())); |
1160 | for (auto typeArg : T->getTypeArgsAsWritten()) { |
1161 | TRY_TO(TraverseType(typeArg)); |
1162 | } |
1163 | }) |
1164 | |
1165 | DEF_TRAVERSE_TYPE(ObjCObjectPointerType, |
1166 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
1167 | |
1168 | DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) |
1169 | |
1170 | DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); }) |
1171 | |
1172 | DEF_TRAVERSE_TYPE(BitIntType, {}) |
1173 | DEF_TRAVERSE_TYPE(DependentBitIntType, |
1174 | { TRY_TO(TraverseStmt(T->getNumBitsExpr())); }) |
1175 | |
1176 | #undef DEF_TRAVERSE_TYPE |
1177 | |
1178 | // ----------------- TypeLoc traversal ----------------- |
1179 | |
1180 | // This macro makes available a variable TL, the passed-in TypeLoc. |
1181 | // If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, |
1182 | // in addition to WalkUpFrom* for the TypeLoc itself, such that existing |
1183 | // clients that override the WalkUpFrom*Type() and/or Visit*Type() methods |
1184 | // continue to work. |
1185 | #define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ |
1186 | template <typename Derived> \ |
1187 | bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ |
1188 | if (!getDerived().shouldTraversePostOrder()) { \ |
1189 | TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ |
1190 | if (getDerived().shouldWalkTypesOfTypeLocs()) \ |
1191 | TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ |
1192 | } \ |
1193 | { CODE; } \ |
1194 | if (getDerived().shouldTraversePostOrder()) { \ |
1195 | TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ |
1196 | if (getDerived().shouldWalkTypesOfTypeLocs()) \ |
1197 | TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ |
1198 | } \ |
1199 | return true; \ |
1200 | } |
1201 | |
1202 | template <typename Derived> |
1203 | bool |
1204 | RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { |
1205 | // Move this over to the 'main' typeloc tree. Note that this is a |
1206 | // move -- we pretend that we were really looking at the unqualified |
1207 | // typeloc all along -- rather than a recursion, so we don't follow |
1208 | // the normal CRTP plan of going through |
1209 | // getDerived().TraverseTypeLoc. If we did, we'd be traversing |
1210 | // twice for the same type (once as a QualifiedTypeLoc version of |
1211 | // the type, once as an UnqualifiedTypeLoc version of the type), |
1212 | // which in effect means we'd call VisitTypeLoc twice with the |
1213 | // 'same' type. This solves that problem, at the cost of never |
1214 | // seeing the qualified version of the type (unless the client |
1215 | // subclasses TraverseQualifiedTypeLoc themselves). It's not a |
1216 | // perfect solution. A perfect solution probably requires making |
1217 | // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a |
1218 | // wrapper around Type* -- rather than being its own class in the |
1219 | // type hierarchy. |
1220 | return TraverseTypeLoc(TL: TL.getUnqualifiedLoc()); |
1221 | } |
1222 | |
1223 | DEF_TRAVERSE_TYPELOC(BuiltinType, {}) |
1224 | |
1225 | // FIXME: ComplexTypeLoc is unfinished |
1226 | DEF_TRAVERSE_TYPELOC(ComplexType, { |
1227 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1228 | }) |
1229 | |
1230 | DEF_TRAVERSE_TYPELOC(PointerType, |
1231 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1232 | |
1233 | DEF_TRAVERSE_TYPELOC(BlockPointerType, |
1234 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1235 | |
1236 | DEF_TRAVERSE_TYPELOC(LValueReferenceType, |
1237 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1238 | |
1239 | DEF_TRAVERSE_TYPELOC(RValueReferenceType, |
1240 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1241 | |
1242 | // We traverse this in the type case as well, but how is it not reached through |
1243 | // the pointee type? |
1244 | DEF_TRAVERSE_TYPELOC(MemberPointerType, { |
1245 | if (auto *TSI = TL.getClassTInfo()) |
1246 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); |
1247 | else |
1248 | TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); |
1249 | TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); |
1250 | }) |
1251 | |
1252 | DEF_TRAVERSE_TYPELOC(AdjustedType, |
1253 | { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) |
1254 | |
1255 | DEF_TRAVERSE_TYPELOC(DecayedType, |
1256 | { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) |
1257 | |
1258 | template <typename Derived> |
1259 | bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { |
1260 | // This isn't available for ArrayType, but is for the ArrayTypeLoc. |
1261 | TRY_TO(TraverseStmt(TL.getSizeExpr())); |
1262 | return true; |
1263 | } |
1264 | |
1265 | DEF_TRAVERSE_TYPELOC(ConstantArrayType, { |
1266 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1267 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1268 | }) |
1269 | |
1270 | DEF_TRAVERSE_TYPELOC(ArrayParameterType, { |
1271 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1272 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1273 | }) |
1274 | |
1275 | DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { |
1276 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1277 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1278 | }) |
1279 | |
1280 | DEF_TRAVERSE_TYPELOC(VariableArrayType, { |
1281 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1282 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1283 | }) |
1284 | |
1285 | DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { |
1286 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
1287 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
1288 | }) |
1289 | |
1290 | DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, { |
1291 | TRY_TO(TraverseStmt(TL.getTypePtr()->getAddrSpaceExpr())); |
1292 | TRY_TO(TraverseType(TL.getTypePtr()->getPointeeType())); |
1293 | }) |
1294 | |
1295 | // FIXME: order? why not size expr first? |
1296 | // FIXME: base VectorTypeLoc is unfinished |
1297 | DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { |
1298 | if (TL.getTypePtr()->getSizeExpr()) |
1299 | TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); |
1300 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1301 | }) |
1302 | |
1303 | // FIXME: VectorTypeLoc is unfinished |
1304 | DEF_TRAVERSE_TYPELOC(VectorType, { |
1305 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1306 | }) |
1307 | |
1308 | DEF_TRAVERSE_TYPELOC(DependentVectorType, { |
1309 | if (TL.getTypePtr()->getSizeExpr()) |
1310 | TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); |
1311 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1312 | }) |
1313 | |
1314 | // FIXME: size and attributes |
1315 | // FIXME: base VectorTypeLoc is unfinished |
1316 | DEF_TRAVERSE_TYPELOC(ExtVectorType, { |
1317 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1318 | }) |
1319 | |
1320 | DEF_TRAVERSE_TYPELOC(ConstantMatrixType, { |
1321 | TRY_TO(TraverseStmt(TL.getAttrRowOperand())); |
1322 | TRY_TO(TraverseStmt(TL.getAttrColumnOperand())); |
1323 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1324 | }) |
1325 | |
1326 | DEF_TRAVERSE_TYPELOC(DependentSizedMatrixType, { |
1327 | TRY_TO(TraverseStmt(TL.getAttrRowOperand())); |
1328 | TRY_TO(TraverseStmt(TL.getAttrColumnOperand())); |
1329 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
1330 | }) |
1331 | |
1332 | DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, |
1333 | { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) |
1334 | |
1335 | // FIXME: location of exception specifications (attributes?) |
1336 | DEF_TRAVERSE_TYPELOC(FunctionProtoType, { |
1337 | TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); |
1338 | |
1339 | const FunctionProtoType *T = TL.getTypePtr(); |
1340 | |
1341 | for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { |
1342 | if (TL.getParam(I)) { |
1343 | TRY_TO(TraverseDecl(TL.getParam(I))); |
1344 | } else if (I < T->getNumParams()) { |
1345 | TRY_TO(TraverseType(T->getParamType(I))); |
1346 | } |
1347 | } |
1348 | |
1349 | for (const auto &E : T->exceptions()) { |
1350 | TRY_TO(TraverseType(E)); |
1351 | } |
1352 | |
1353 | if (Expr *NE = T->getNoexceptExpr()) |
1354 | TRY_TO(TraverseStmt(NE)); |
1355 | }) |
1356 | |
1357 | DEF_TRAVERSE_TYPELOC(UsingType, {}) |
1358 | DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) |
1359 | DEF_TRAVERSE_TYPELOC(TypedefType, {}) |
1360 | |
1361 | DEF_TRAVERSE_TYPELOC(TypeOfExprType, |
1362 | { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) |
1363 | |
1364 | DEF_TRAVERSE_TYPELOC(TypeOfType, { |
1365 | TRY_TO(TraverseTypeLoc(TL.getUnmodifiedTInfo()->getTypeLoc())); |
1366 | }) |
1367 | |
1368 | // FIXME: location of underlying expr |
1369 | DEF_TRAVERSE_TYPELOC(DecltypeType, { |
1370 | TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); |
1371 | }) |
1372 | |
1373 | DEF_TRAVERSE_TYPELOC(PackIndexingType, { |
1374 | TRY_TO(TraverseType(TL.getPattern())); |
1375 | TRY_TO(TraverseStmt(TL.getTypePtr()->getIndexExpr())); |
1376 | }) |
1377 | |
1378 | DEF_TRAVERSE_TYPELOC(UnaryTransformType, { |
1379 | TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); |
1380 | }) |
1381 | |
1382 | DEF_TRAVERSE_TYPELOC(AutoType, { |
1383 | TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); |
1384 | if (TL.isConstrained()) { |
1385 | TRY_TO(TraverseConceptReference(TL.getConceptReference())); |
1386 | } |
1387 | }) |
1388 | |
1389 | DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, { |
1390 | TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); |
1391 | TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); |
1392 | }) |
1393 | |
1394 | DEF_TRAVERSE_TYPELOC(RecordType, {}) |
1395 | DEF_TRAVERSE_TYPELOC(EnumType, {}) |
1396 | DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) |
1397 | DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { |
1398 | TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType())); |
1399 | }) |
1400 | DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { |
1401 | TRY_TO(TraverseTemplateArgument(TL.getTypePtr()->getArgumentPack())); |
1402 | }) |
1403 | |
1404 | // FIXME: use the loc for the template name? |
1405 | DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { |
1406 | TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); |
1407 | for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { |
1408 | TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); |
1409 | } |
1410 | }) |
1411 | |
1412 | DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {}) |
1413 | |
1414 | DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
1415 | |
1416 | DEF_TRAVERSE_TYPELOC(MacroQualifiedType, |
1417 | { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
1418 | |
1419 | DEF_TRAVERSE_TYPELOC(AttributedType, |
1420 | { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) |
1421 | |
1422 | DEF_TRAVERSE_TYPELOC(CountAttributedType, |
1423 | { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
1424 | |
1425 | DEF_TRAVERSE_TYPELOC(BTFTagAttributedType, |
1426 | { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); }) |
1427 | |
1428 | DEF_TRAVERSE_TYPELOC(ElaboratedType, { |
1429 | if (TL.getQualifierLoc()) { |
1430 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
1431 | } |
1432 | TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); |
1433 | }) |
1434 | |
1435 | DEF_TRAVERSE_TYPELOC(DependentNameType, { |
1436 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
1437 | }) |
1438 | |
1439 | DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { |
1440 | if (TL.getQualifierLoc()) { |
1441 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
1442 | } |
1443 | |
1444 | for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { |
1445 | TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); |
1446 | } |
1447 | }) |
1448 | |
1449 | DEF_TRAVERSE_TYPELOC(PackExpansionType, |
1450 | { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) |
1451 | |
1452 | DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, { |
1453 | for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { |
1454 | ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I)); |
1455 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
1456 | } |
1457 | }) |
1458 | |
1459 | DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) |
1460 | |
1461 | DEF_TRAVERSE_TYPELOC(ObjCObjectType, { |
1462 | // We have to watch out here because an ObjCInterfaceType's base |
1463 | // type is itself. |
1464 | if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) |
1465 | TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); |
1466 | for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) |
1467 | TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc())); |
1468 | for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { |
1469 | ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I)); |
1470 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
1471 | } |
1472 | }) |
1473 | |
1474 | DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, |
1475 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
1476 | |
1477 | DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) |
1478 | |
1479 | DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) |
1480 | |
1481 | DEF_TRAVERSE_TYPELOC(BitIntType, {}) |
1482 | DEF_TRAVERSE_TYPELOC(DependentBitIntType, { |
1483 | TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr())); |
1484 | }) |
1485 | |
1486 | #undef DEF_TRAVERSE_TYPELOC |
1487 | |
1488 | // ----------------- Decl traversal ----------------- |
1489 | // |
1490 | // For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing |
1491 | // the children that come from the DeclContext associated with it. |
1492 | // Therefore each Traverse* only needs to worry about children other |
1493 | // than those. |
1494 | |
1495 | template <typename Derived> |
1496 | bool RecursiveASTVisitor<Derived>::canIgnoreChildDeclWhileTraversingDeclContext( |
1497 | const Decl *Child) { |
1498 | // BlockDecls are traversed through BlockExprs, |
1499 | // CapturedDecls are traversed through CapturedStmts. |
1500 | if (isa<BlockDecl>(Child) || isa<CapturedDecl>(Child)) |
1501 | return true; |
1502 | // Lambda classes are traversed through LambdaExprs. |
1503 | if (const CXXRecordDecl* Cls = dyn_cast<CXXRecordDecl>(Child)) |
1504 | return Cls->isLambda(); |
1505 | return false; |
1506 | } |
1507 | |
1508 | template <typename Derived> |
1509 | bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { |
1510 | if (!DC) |
1511 | return true; |
1512 | |
1513 | for (auto *Child : DC->decls()) { |
1514 | if (!canIgnoreChildDeclWhileTraversingDeclContext(Child)) |
1515 | TRY_TO(TraverseDecl(Child)); |
1516 | } |
1517 | |
1518 | return true; |
1519 | } |
1520 | |
1521 | // This macro makes available a variable D, the passed-in decl. |
1522 | #define DEF_TRAVERSE_DECL(DECL, CODE) \ |
1523 | template <typename Derived> \ |
1524 | bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \ |
1525 | bool ShouldVisitChildren = true; \ |
1526 | bool ReturnValue = true; \ |
1527 | if (!getDerived().shouldTraversePostOrder()) \ |
1528 | TRY_TO(WalkUpFrom##DECL(D)); \ |
1529 | { CODE; } \ |
1530 | if (ReturnValue && ShouldVisitChildren) \ |
1531 | TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ |
1532 | if (ReturnValue) { \ |
1533 | /* Visit any attributes attached to this declaration. */ \ |
1534 | for (auto *I : D->attrs()) \ |
1535 | TRY_TO(getDerived().TraverseAttr(I)); \ |
1536 | } \ |
1537 | if (ReturnValue && getDerived().shouldTraversePostOrder()) \ |
1538 | TRY_TO(WalkUpFrom##DECL(D)); \ |
1539 | return ReturnValue; \ |
1540 | } |
1541 | |
1542 | DEF_TRAVERSE_DECL(AccessSpecDecl, {}) |
1543 | |
1544 | DEF_TRAVERSE_DECL(BlockDecl, { |
1545 | if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) |
1546 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
1547 | TRY_TO(TraverseStmt(D->getBody())); |
1548 | for (const auto &I : D->captures()) { |
1549 | if (I.hasCopyExpr()) { |
1550 | TRY_TO(TraverseStmt(I.getCopyExpr())); |
1551 | } |
1552 | } |
1553 | ShouldVisitChildren = false; |
1554 | }) |
1555 | |
1556 | DEF_TRAVERSE_DECL(CapturedDecl, { |
1557 | TRY_TO(TraverseStmt(D->getBody())); |
1558 | ShouldVisitChildren = false; |
1559 | }) |
1560 | |
1561 | DEF_TRAVERSE_DECL(EmptyDecl, {}) |
1562 | |
1563 | DEF_TRAVERSE_DECL(HLSLBufferDecl, {}) |
1564 | |
1565 | DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, { |
1566 | TRY_TO(TraverseStmt(D->getTemporaryExpr())); |
1567 | }) |
1568 | |
1569 | DEF_TRAVERSE_DECL(FileScopeAsmDecl, |
1570 | { TRY_TO(TraverseStmt(D->getAsmString())); }) |
1571 | |
1572 | DEF_TRAVERSE_DECL(TopLevelStmtDecl, { TRY_TO(TraverseStmt(D->getStmt())); }) |
1573 | |
1574 | DEF_TRAVERSE_DECL(ImportDecl, {}) |
1575 | |
1576 | DEF_TRAVERSE_DECL(FriendDecl, { |
1577 | // Friend is either decl or a type. |
1578 | if (D->getFriendType()) { |
1579 | TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); |
1580 | // Traverse any CXXRecordDecl owned by this type, since |
1581 | // it will not be in the parent context: |
1582 | if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>()) |
1583 | TRY_TO(TraverseDecl(ET->getOwnedTagDecl())); |
1584 | } else { |
1585 | TRY_TO(TraverseDecl(D->getFriendDecl())); |
1586 | } |
1587 | }) |
1588 | |
1589 | DEF_TRAVERSE_DECL(FriendTemplateDecl, { |
1590 | if (D->getFriendType()) |
1591 | TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); |
1592 | else |
1593 | TRY_TO(TraverseDecl(D->getFriendDecl())); |
1594 | for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { |
1595 | TemplateParameterList *TPL = D->getTemplateParameterList(I); |
1596 | for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end(); |
1597 | ITPL != ETPL; ++ITPL) { |
1598 | TRY_TO(TraverseDecl(*ITPL)); |
1599 | } |
1600 | } |
1601 | }) |
1602 | |
1603 | DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) |
1604 | |
1605 | DEF_TRAVERSE_DECL(ExportDecl, {}) |
1606 | |
1607 | DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this |
1608 | }) |
1609 | |
1610 | DEF_TRAVERSE_DECL(StaticAssertDecl, { |
1611 | TRY_TO(TraverseStmt(D->getAssertExpr())); |
1612 | TRY_TO(TraverseStmt(D->getMessage())); |
1613 | }) |
1614 | |
1615 | DEF_TRAVERSE_DECL(TranslationUnitDecl, { |
1616 | // Code in an unnamed namespace shows up automatically in |
1617 | // decls_begin()/decls_end(). Thus we don't need to recurse on |
1618 | // D->getAnonymousNamespace(). |
1619 | |
1620 | // If the traversal scope is set, then consider them to be the children of |
1621 | // the TUDecl, rather than traversing (and loading?) all top-level decls. |
1622 | auto Scope = D->getASTContext().getTraversalScope(); |
1623 | bool HasLimitedScope = |
1624 | Scope.size() != 1 || !isa<TranslationUnitDecl>(Scope.front()); |
1625 | if (HasLimitedScope) { |
1626 | ShouldVisitChildren = false; // we'll do that here instead |
1627 | for (auto *Child : Scope) { |
1628 | if (!canIgnoreChildDeclWhileTraversingDeclContext(Child)) |
1629 | TRY_TO(TraverseDecl(Child)); |
1630 | } |
1631 | } |
1632 | }) |
1633 | |
1634 | DEF_TRAVERSE_DECL(PragmaCommentDecl, {}) |
1635 | |
1636 | DEF_TRAVERSE_DECL(PragmaDetectMismatchDecl, {}) |
1637 | |
1638 | DEF_TRAVERSE_DECL(ExternCContextDecl, {}) |
1639 | |
1640 | DEF_TRAVERSE_DECL(NamespaceAliasDecl, { |
1641 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1642 | |
1643 | // We shouldn't traverse an aliased namespace, since it will be |
1644 | // defined (and, therefore, traversed) somewhere else. |
1645 | ShouldVisitChildren = false; |
1646 | }) |
1647 | |
1648 | DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl. |
1649 | }) |
1650 | |
1651 | DEF_TRAVERSE_DECL( |
1652 | NamespaceDecl, |
1653 | {// Code in an unnamed namespace shows up automatically in |
1654 | // decls_begin()/decls_end(). Thus we don't need to recurse on |
1655 | // D->getAnonymousNamespace(). |
1656 | }) |
1657 | |
1658 | DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement |
1659 | }) |
1660 | |
1661 | DEF_TRAVERSE_DECL(ObjCCategoryDecl, { |
1662 | if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) { |
1663 | for (auto typeParam : *typeParamList) { |
1664 | TRY_TO(TraverseObjCTypeParamDecl(typeParam)); |
1665 | } |
1666 | } |
1667 | for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { |
1668 | ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); |
1669 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
1670 | } |
1671 | }) |
1672 | |
1673 | DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement |
1674 | }) |
1675 | |
1676 | DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement |
1677 | }) |
1678 | |
1679 | DEF_TRAVERSE_DECL(ObjCInterfaceDecl, { |
1680 | if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) { |
1681 | for (auto typeParam : *typeParamList) { |
1682 | TRY_TO(TraverseObjCTypeParamDecl(typeParam)); |
1683 | } |
1684 | } |
1685 | |
1686 | if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) { |
1687 | TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc())); |
1688 | } |
1689 | if (D->isThisDeclarationADefinition()) { |
1690 | for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { |
1691 | ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); |
1692 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
1693 | } |
1694 | } |
1695 | }) |
1696 | |
1697 | DEF_TRAVERSE_DECL(ObjCProtocolDecl, { |
1698 | if (D->isThisDeclarationADefinition()) { |
1699 | for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { |
1700 | ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); |
1701 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
1702 | } |
1703 | } |
1704 | }) |
1705 | |
1706 | DEF_TRAVERSE_DECL(ObjCMethodDecl, { |
1707 | if (D->getReturnTypeSourceInfo()) { |
1708 | TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); |
1709 | } |
1710 | for (ParmVarDecl *Parameter : D->parameters()) { |
1711 | TRY_TO(TraverseDecl(Parameter)); |
1712 | } |
1713 | if (D->isThisDeclarationADefinition()) { |
1714 | TRY_TO(TraverseStmt(D->getBody())); |
1715 | } |
1716 | ShouldVisitChildren = false; |
1717 | }) |
1718 | |
1719 | DEF_TRAVERSE_DECL(ObjCTypeParamDecl, { |
1720 | if (D->hasExplicitBound()) { |
1721 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1722 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1723 | // declaring the type alias, not something that was written in the |
1724 | // source. |
1725 | } |
1726 | }) |
1727 | |
1728 | DEF_TRAVERSE_DECL(ObjCPropertyDecl, { |
1729 | if (D->getTypeSourceInfo()) |
1730 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1731 | else |
1732 | TRY_TO(TraverseType(D->getType())); |
1733 | ShouldVisitChildren = false; |
1734 | }) |
1735 | |
1736 | DEF_TRAVERSE_DECL(UsingDecl, { |
1737 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1738 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
1739 | }) |
1740 | |
1741 | DEF_TRAVERSE_DECL(UsingEnumDecl, |
1742 | { TRY_TO(TraverseTypeLoc(D->getEnumTypeLoc())); }) |
1743 | |
1744 | DEF_TRAVERSE_DECL(UsingPackDecl, {}) |
1745 | |
1746 | DEF_TRAVERSE_DECL(UsingDirectiveDecl, { |
1747 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1748 | }) |
1749 | |
1750 | DEF_TRAVERSE_DECL(UsingShadowDecl, {}) |
1751 | |
1752 | DEF_TRAVERSE_DECL(ConstructorUsingShadowDecl, {}) |
1753 | |
1754 | DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { |
1755 | for (auto *I : D->varlists()) { |
1756 | TRY_TO(TraverseStmt(I)); |
1757 | } |
1758 | }) |
1759 | |
1760 | DEF_TRAVERSE_DECL(OMPRequiresDecl, { |
1761 | for (auto *C : D->clauselists()) { |
1762 | TRY_TO(TraverseOMPClause(C)); |
1763 | } |
1764 | }) |
1765 | |
1766 | DEF_TRAVERSE_DECL(OMPDeclareReductionDecl, { |
1767 | TRY_TO(TraverseStmt(D->getCombiner())); |
1768 | if (auto *Initializer = D->getInitializer()) |
1769 | TRY_TO(TraverseStmt(Initializer)); |
1770 | TRY_TO(TraverseType(D->getType())); |
1771 | return true; |
1772 | }) |
1773 | |
1774 | DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, { |
1775 | for (auto *C : D->clauselists()) |
1776 | TRY_TO(TraverseOMPClause(C)); |
1777 | TRY_TO(TraverseType(D->getType())); |
1778 | return true; |
1779 | }) |
1780 | |
1781 | DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); }) |
1782 | |
1783 | DEF_TRAVERSE_DECL(OMPAllocateDecl, { |
1784 | for (auto *I : D->varlists()) |
1785 | TRY_TO(TraverseStmt(I)); |
1786 | for (auto *C : D->clauselists()) |
1787 | TRY_TO(TraverseOMPClause(C)); |
1788 | }) |
1789 | |
1790 | // A helper method for TemplateDecl's children. |
1791 | template <typename Derived> |
1792 | bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( |
1793 | TemplateParameterList *TPL) { |
1794 | if (TPL) { |
1795 | for (NamedDecl *D : *TPL) { |
1796 | TRY_TO(TraverseDecl(D)); |
1797 | } |
1798 | if (Expr *RequiresClause = TPL->getRequiresClause()) { |
1799 | TRY_TO(TraverseStmt(RequiresClause)); |
1800 | } |
1801 | } |
1802 | return true; |
1803 | } |
1804 | |
1805 | template <typename Derived> |
1806 | template <typename T> |
1807 | bool RecursiveASTVisitor<Derived>::TraverseDeclTemplateParameterLists(T *D) { |
1808 | for (unsigned i = 0; i < D->getNumTemplateParameterLists(); i++) { |
1809 | TemplateParameterList *TPL = D->getTemplateParameterList(i); |
1810 | TraverseTemplateParameterListHelper(TPL); |
1811 | } |
1812 | return true; |
1813 | } |
1814 | |
1815 | template <typename Derived> |
1816 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
1817 | ClassTemplateDecl *D) { |
1818 | for (auto *SD : D->specializations()) { |
1819 | for (auto *RD : SD->redecls()) { |
1820 | assert(!cast<CXXRecordDecl>(RD)->isInjectedClassName()); |
1821 | switch ( |
1822 | cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) { |
1823 | // Visit the implicit instantiations with the requested pattern. |
1824 | case TSK_Undeclared: |
1825 | case TSK_ImplicitInstantiation: |
1826 | TRY_TO(TraverseDecl(RD)); |
1827 | break; |
1828 | |
1829 | // We don't need to do anything on an explicit instantiation |
1830 | // or explicit specialization because there will be an explicit |
1831 | // node for it elsewhere. |
1832 | case TSK_ExplicitInstantiationDeclaration: |
1833 | case TSK_ExplicitInstantiationDefinition: |
1834 | case TSK_ExplicitSpecialization: |
1835 | break; |
1836 | } |
1837 | } |
1838 | } |
1839 | |
1840 | return true; |
1841 | } |
1842 | |
1843 | template <typename Derived> |
1844 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
1845 | VarTemplateDecl *D) { |
1846 | for (auto *SD : D->specializations()) { |
1847 | for (auto *RD : SD->redecls()) { |
1848 | switch ( |
1849 | cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) { |
1850 | case TSK_Undeclared: |
1851 | case TSK_ImplicitInstantiation: |
1852 | TRY_TO(TraverseDecl(RD)); |
1853 | break; |
1854 | |
1855 | case TSK_ExplicitInstantiationDeclaration: |
1856 | case TSK_ExplicitInstantiationDefinition: |
1857 | case TSK_ExplicitSpecialization: |
1858 | break; |
1859 | } |
1860 | } |
1861 | } |
1862 | |
1863 | return true; |
1864 | } |
1865 | |
1866 | // A helper method for traversing the instantiations of a |
1867 | // function while skipping its specializations. |
1868 | template <typename Derived> |
1869 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
1870 | FunctionTemplateDecl *D) { |
1871 | for (auto *FD : D->specializations()) { |
1872 | for (auto *RD : FD->redecls()) { |
1873 | switch (RD->getTemplateSpecializationKind()) { |
1874 | case TSK_Undeclared: |
1875 | case TSK_ImplicitInstantiation: |
1876 | // We don't know what kind of FunctionDecl this is. |
1877 | TRY_TO(TraverseDecl(RD)); |
1878 | break; |
1879 | |
1880 | // FIXME: For now traverse explicit instantiations here. Change that |
1881 | // once they are represented as dedicated nodes in the AST. |
1882 | case TSK_ExplicitInstantiationDeclaration: |
1883 | case TSK_ExplicitInstantiationDefinition: |
1884 | TRY_TO(TraverseDecl(RD)); |
1885 | break; |
1886 | |
1887 | case TSK_ExplicitSpecialization: |
1888 | break; |
1889 | } |
1890 | } |
1891 | } |
1892 | |
1893 | return true; |
1894 | } |
1895 | |
1896 | // This macro unifies the traversal of class, variable and function |
1897 | // template declarations. |
1898 | #define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ |
1899 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ |
1900 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ |
1901 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ |
1902 | \ |
1903 | /* By default, we do not traverse the instantiations of \ |
1904 | class templates since they do not appear in the user code. The \ |
1905 | following code optionally traverses them. \ |
1906 | \ |
1907 | We only traverse the class instantiations when we see the canonical \ |
1908 | declaration of the template, to ensure we only visit them once. */ \ |
1909 | if (getDerived().shouldVisitTemplateInstantiations() && \ |
1910 | D == D->getCanonicalDecl()) \ |
1911 | TRY_TO(TraverseTemplateInstantiations(D)); \ |
1912 | \ |
1913 | /* Note that getInstantiatedFromMemberTemplate() is just a link \ |
1914 | from a template instantiation back to the template from which \ |
1915 | it was instantiated, and thus should not be traversed. */ \ |
1916 | }) |
1917 | |
1918 | DEF_TRAVERSE_TMPL_DECL(Class) |
1919 | DEF_TRAVERSE_TMPL_DECL(Var) |
1920 | DEF_TRAVERSE_TMPL_DECL(Function) |
1921 | |
1922 | DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { |
1923 | // D is the "T" in something like |
1924 | // template <template <typename> class T> class container { }; |
1925 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); |
1926 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
1927 | TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); |
1928 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1929 | }) |
1930 | |
1931 | DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { |
1932 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1933 | }) |
1934 | |
1935 | template <typename Derived> |
1936 | bool RecursiveASTVisitor<Derived>::TraverseTemplateTypeParamDeclConstraints( |
1937 | const TemplateTypeParmDecl *D) { |
1938 | if (const auto *TC = D->getTypeConstraint()) |
1939 | TRY_TO(TraverseTypeConstraint(TC)); |
1940 | return true; |
1941 | } |
1942 | |
1943 | DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { |
1944 | // D is the "T" in something like "template<typename T> class vector;" |
1945 | if (D->getTypeForDecl()) |
1946 | TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); |
1947 | TRY_TO(TraverseTemplateTypeParamDeclConstraints(D)); |
1948 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
1949 | TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); |
1950 | }) |
1951 | |
1952 | DEF_TRAVERSE_DECL(TypedefDecl, { |
1953 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1954 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1955 | // declaring the typedef, not something that was written in the |
1956 | // source. |
1957 | }) |
1958 | |
1959 | DEF_TRAVERSE_DECL(TypeAliasDecl, { |
1960 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
1961 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1962 | // declaring the type alias, not something that was written in the |
1963 | // source. |
1964 | }) |
1965 | |
1966 | DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { |
1967 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); |
1968 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1969 | }) |
1970 | |
1971 | DEF_TRAVERSE_DECL(ConceptDecl, { |
1972 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
1973 | TRY_TO(TraverseStmt(D->getConstraintExpr())); |
1974 | }) |
1975 | |
1976 | DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { |
1977 | // A dependent using declaration which was marked with 'typename'. |
1978 | // template<class T> class A : public B<T> { using typename B<T>::foo; }; |
1979 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1980 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
1981 | // declaring the type, not something that was written in the |
1982 | // source. |
1983 | }) |
1984 | |
1985 | DEF_TRAVERSE_DECL(UnresolvedUsingIfExistsDecl, {}) |
1986 | |
1987 | DEF_TRAVERSE_DECL(EnumDecl, { |
1988 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
1989 | |
1990 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
1991 | if (auto *TSI = D->getIntegerTypeSourceInfo()) |
1992 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); |
1993 | // The enumerators are already traversed by |
1994 | // decls_begin()/decls_end(). |
1995 | }) |
1996 | |
1997 | // Helper methods for RecordDecl and its children. |
1998 | template <typename Derived> |
1999 | bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) { |
2000 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
2001 | // declaring the type, not something that was written in the source. |
2002 | |
2003 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
2004 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
2005 | return true; |
2006 | } |
2007 | |
2008 | template <typename Derived> |
2009 | bool RecursiveASTVisitor<Derived>::TraverseCXXBaseSpecifier( |
2010 | const CXXBaseSpecifier &Base) { |
2011 | TRY_TO(TraverseTypeLoc(Base.getTypeSourceInfo()->getTypeLoc())); |
2012 | return true; |
2013 | } |
2014 | |
2015 | template <typename Derived> |
2016 | bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) { |
2017 | if (!TraverseRecordHelper(D)) |
2018 | return false; |
2019 | if (D->isCompleteDefinition()) { |
2020 | for (const auto &I : D->bases()) { |
2021 | TRY_TO(TraverseCXXBaseSpecifier(I)); |
2022 | } |
2023 | // We don't traverse the friends or the conversions, as they are |
2024 | // already in decls_begin()/decls_end(). |
2025 | } |
2026 | return true; |
2027 | } |
2028 | |
2029 | DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) |
2030 | |
2031 | DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) |
2032 | |
2033 | #define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ |
2034 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ |
2035 | /* For implicit instantiations ("set<int> x;"), we don't want to \ |
2036 | recurse at all, since the instatiated template isn't written in \ |
2037 | the source code anywhere. (Note the instatiated *type* -- \ |
2038 | set<int> -- is written, and will still get a callback of \ |
2039 | TemplateSpecializationType). For explicit instantiations \ |
2040 | ("template set<int>;"), we do need a callback, since this \ |
2041 | is the only callback that's made for this instantiation. \ |
2042 | We use getTypeAsWritten() to distinguish. */ \ |
2043 | if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ |
2044 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ |
2045 | \ |
2046 | if (getDerived().shouldVisitTemplateInstantiations() || \ |
2047 | D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ |
2048 | /* Traverse base definition for explicit specializations */ \ |
2049 | TRY_TO(Traverse##DECLKIND##Helper(D)); \ |
2050 | } else { \ |
2051 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ |
2052 | \ |
2053 | /* Returning from here skips traversing the \ |
2054 | declaration context of the *TemplateSpecializationDecl \ |
2055 | (embedded in the DEF_TRAVERSE_DECL() macro) \ |
2056 | which contains the instantiated members of the template. */ \ |
2057 | return true; \ |
2058 | } \ |
2059 | }) |
2060 | |
2061 | DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord) |
2062 | DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var) |
2063 | |
2064 | template <typename Derived> |
2065 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( |
2066 | const TemplateArgumentLoc *TAL, unsigned Count) { |
2067 | for (unsigned I = 0; I < Count; ++I) { |
2068 | TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); |
2069 | } |
2070 | return true; |
2071 | } |
2072 | |
2073 | #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ |
2074 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ |
2075 | /* The partial specialization. */ \ |
2076 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ |
2077 | /* The args that remains unspecialized. */ \ |
2078 | TRY_TO(TraverseTemplateArgumentLocsHelper( \ |
2079 | D->getTemplateArgsAsWritten()->getTemplateArgs(), \ |
2080 | D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ |
2081 | \ |
2082 | /* Don't need the *TemplatePartialSpecializationHelper, even \ |
2083 | though that's our parent class -- we already visit all the \ |
2084 | template args here. */ \ |
2085 | TRY_TO(Traverse##DECLKIND##Helper(D)); \ |
2086 | \ |
2087 | /* Instantiations will have been visited with the primary template. */ \ |
2088 | }) |
2089 | |
2090 | DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord) |
2091 | DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var) |
2092 | |
2093 | DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); }) |
2094 | |
2095 | DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { |
2096 | // Like UnresolvedUsingTypenameDecl, but without the 'typename': |
2097 | // template <class T> Class A : public Base<T> { using Base<T>::foo; }; |
2098 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
2099 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
2100 | }) |
2101 | |
2102 | DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) |
2103 | |
2104 | template <typename Derived> |
2105 | bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { |
2106 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
2107 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
2108 | if (D->getTypeSourceInfo()) |
2109 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
2110 | else |
2111 | TRY_TO(TraverseType(D->getType())); |
2112 | return true; |
2113 | } |
2114 | |
2115 | DEF_TRAVERSE_DECL(DecompositionDecl, { |
2116 | TRY_TO(TraverseVarHelper(D)); |
2117 | for (auto *Binding : D->bindings()) { |
2118 | TRY_TO(TraverseDecl(Binding)); |
2119 | } |
2120 | }) |
2121 | |
2122 | DEF_TRAVERSE_DECL(BindingDecl, { |
2123 | if (getDerived().shouldVisitImplicitCode()) |
2124 | TRY_TO(TraverseStmt(D->getBinding())); |
2125 | }) |
2126 | |
2127 | DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) |
2128 | |
2129 | DEF_TRAVERSE_DECL(MSGuidDecl, {}) |
2130 | DEF_TRAVERSE_DECL(UnnamedGlobalConstantDecl, {}) |
2131 | |
2132 | DEF_TRAVERSE_DECL(TemplateParamObjectDecl, {}) |
2133 | |
2134 | DEF_TRAVERSE_DECL(FieldDecl, { |
2135 | TRY_TO(TraverseDeclaratorHelper(D)); |
2136 | if (D->isBitField()) |
2137 | TRY_TO(TraverseStmt(D->getBitWidth())); |
2138 | if (D->hasInClassInitializer()) |
2139 | TRY_TO(TraverseStmt(D->getInClassInitializer())); |
2140 | }) |
2141 | |
2142 | DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { |
2143 | TRY_TO(TraverseDeclaratorHelper(D)); |
2144 | if (D->isBitField()) |
2145 | TRY_TO(TraverseStmt(D->getBitWidth())); |
2146 | // FIXME: implement the rest. |
2147 | }) |
2148 | |
2149 | DEF_TRAVERSE_DECL(ObjCIvarDecl, { |
2150 | TRY_TO(TraverseDeclaratorHelper(D)); |
2151 | if (D->isBitField()) |
2152 | TRY_TO(TraverseStmt(D->getBitWidth())); |
2153 | // FIXME: implement the rest. |
2154 | }) |
2155 | |
2156 | template <typename Derived> |
2157 | bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { |
2158 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
2159 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
2160 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
2161 | |
2162 | // If we're an explicit template specialization, iterate over the |
2163 | // template args that were explicitly specified. If we were doing |
2164 | // this in typing order, we'd do it between the return type and |
2165 | // the function args, but both are handled by the FunctionTypeLoc |
2166 | // above, so we have to choose one side. I've decided to do before. |
2167 | if (const FunctionTemplateSpecializationInfo *FTSI = |
2168 | D->getTemplateSpecializationInfo()) { |
2169 | if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && |
2170 | FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { |
2171 | // A specialization might not have explicit template arguments if it has |
2172 | // a templated return type and concrete arguments. |
2173 | if (const ASTTemplateArgumentListInfo *TALI = |
2174 | FTSI->TemplateArgumentsAsWritten) { |
2175 | TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), |
2176 | TALI->NumTemplateArgs)); |
2177 | } |
2178 | } |
2179 | } else if (const DependentFunctionTemplateSpecializationInfo *DFSI = |
2180 | D->getDependentSpecializationInfo()) { |
2181 | if (const ASTTemplateArgumentListInfo *TALI = |
2182 | DFSI->TemplateArgumentsAsWritten) { |
2183 | TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), |
2184 | TALI->NumTemplateArgs)); |
2185 | } |
2186 | } |
2187 | |
2188 | // Visit the function type itself, which can be either |
2189 | // FunctionNoProtoType or FunctionProtoType, or a typedef. This |
2190 | // also covers the return type and the function parameters, |
2191 | // including exception specifications. |
2192 | if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) { |
2193 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); |
2194 | } else if (getDerived().shouldVisitImplicitCode()) { |
2195 | // Visit parameter variable declarations of the implicit function |
2196 | // if the traverser is visiting implicit code. Parameter variable |
2197 | // declarations do not have valid TypeSourceInfo, so to visit them |
2198 | // we need to traverse the declarations explicitly. |
2199 | for (ParmVarDecl *Parameter : D->parameters()) { |
2200 | TRY_TO(TraverseDecl(Parameter)); |
2201 | } |
2202 | } |
2203 | |
2204 | // Visit the trailing requires clause, if any. |
2205 | if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) { |
2206 | TRY_TO(TraverseStmt(TrailingRequiresClause)); |
2207 | } |
2208 | |
2209 | if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { |
2210 | // Constructor initializers. |
2211 | for (auto *I : Ctor->inits()) { |
2212 | if (I->isWritten() || getDerived().shouldVisitImplicitCode()) |
2213 | TRY_TO(TraverseConstructorInitializer(I)); |
2214 | } |
2215 | } |
2216 | |
2217 | bool VisitBody = |
2218 | D->isThisDeclarationADefinition() && |
2219 | // Don't visit the function body if the function definition is generated |
2220 | // by clang. |
2221 | (!D->isDefaulted() || getDerived().shouldVisitImplicitCode()); |
2222 | |
2223 | if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { |
2224 | if (const CXXRecordDecl *RD = MD->getParent()) { |
2225 | if (RD->isLambda() && |
2226 | declaresSameEntity(RD->getLambdaCallOperator(), MD)) { |
2227 | VisitBody = VisitBody && getDerived().shouldVisitLambdaBody(); |
2228 | } |
2229 | } |
2230 | } |
2231 | |
2232 | if (VisitBody) { |
2233 | TRY_TO(TraverseStmt(D->getBody())); |
2234 | // Body may contain using declarations whose shadows are parented to the |
2235 | // FunctionDecl itself. |
2236 | for (auto *Child : D->decls()) { |
2237 | if (isa<UsingShadowDecl>(Child)) |
2238 | TRY_TO(TraverseDecl(Child)); |
2239 | } |
2240 | } |
2241 | return true; |
2242 | } |
2243 | |
2244 | DEF_TRAVERSE_DECL(FunctionDecl, { |
2245 | // We skip decls_begin/decls_end, which are already covered by |
2246 | // TraverseFunctionHelper(). |
2247 | ShouldVisitChildren = false; |
2248 | ReturnValue = TraverseFunctionHelper(D); |
2249 | }) |
2250 | |
2251 | DEF_TRAVERSE_DECL(CXXDeductionGuideDecl, { |
2252 | // We skip decls_begin/decls_end, which are already covered by |
2253 | // TraverseFunctionHelper(). |
2254 | ShouldVisitChildren = false; |
2255 | ReturnValue = TraverseFunctionHelper(D); |
2256 | }) |
2257 | |
2258 | DEF_TRAVERSE_DECL(CXXMethodDecl, { |
2259 | // We skip decls_begin/decls_end, which are already covered by |
2260 | // TraverseFunctionHelper(). |
2261 | ShouldVisitChildren = false; |
2262 | ReturnValue = TraverseFunctionHelper(D); |
2263 | }) |
2264 | |
2265 | DEF_TRAVERSE_DECL(CXXConstructorDecl, { |
2266 | // We skip decls_begin/decls_end, which are already covered by |
2267 | // TraverseFunctionHelper(). |
2268 | ShouldVisitChildren = false; |
2269 | ReturnValue = TraverseFunctionHelper(D); |
2270 | }) |
2271 | |
2272 | // CXXConversionDecl is the declaration of a type conversion operator. |
2273 | // It's not a cast expression. |
2274 | DEF_TRAVERSE_DECL(CXXConversionDecl, { |
2275 | // We skip decls_begin/decls_end, which are already covered by |
2276 | // TraverseFunctionHelper(). |
2277 | ShouldVisitChildren = false; |
2278 | ReturnValue = TraverseFunctionHelper(D); |
2279 | }) |
2280 | |
2281 | DEF_TRAVERSE_DECL(CXXDestructorDecl, { |
2282 | // We skip decls_begin/decls_end, which are already covered by |
2283 | // TraverseFunctionHelper(). |
2284 | ShouldVisitChildren = false; |
2285 | ReturnValue = TraverseFunctionHelper(D); |
2286 | }) |
2287 | |
2288 | template <typename Derived> |
2289 | bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { |
2290 | TRY_TO(TraverseDeclaratorHelper(D)); |
2291 | // Default params are taken care of when we traverse the ParmVarDecl. |
2292 | if (!isa<ParmVarDecl>(D) && |
2293 | (!D->isCXXForRangeDecl() || getDerived().shouldVisitImplicitCode())) |
2294 | TRY_TO(TraverseStmt(D->getInit())); |
2295 | return true; |
2296 | } |
2297 | |
2298 | DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); }) |
2299 | |
2300 | DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); }) |
2301 | |
2302 | DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { |
2303 | // A non-type template parameter, e.g. "S" in template<int S> class Foo ... |
2304 | TRY_TO(TraverseDeclaratorHelper(D)); |
2305 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
2306 | TRY_TO(TraverseStmt(D->getDefaultArgument())); |
2307 | }) |
2308 | |
2309 | DEF_TRAVERSE_DECL(ParmVarDecl, { |
2310 | TRY_TO(TraverseVarHelper(D)); |
2311 | |
2312 | if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && |
2313 | !D->hasUnparsedDefaultArg()) |
2314 | TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); |
2315 | |
2316 | if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() && |
2317 | !D->hasUnparsedDefaultArg()) |
2318 | TRY_TO(TraverseStmt(D->getDefaultArg())); |
2319 | }) |
2320 | |
2321 | DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {}) |
2322 | |
2323 | DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { |
2324 | TRY_TO(TraverseTemplateArguments(D->getTemplateArguments())); |
2325 | }) |
2326 | |
2327 | #undef DEF_TRAVERSE_DECL |
2328 | |
2329 | // ----------------- Stmt traversal ----------------- |
2330 | // |
2331 | // For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating |
2332 | // over the children defined in children() (every stmt defines these, |
2333 | // though sometimes the range is empty). Each individual Traverse* |
2334 | // method only needs to worry about children other than those. To see |
2335 | // what children() does for a given class, see, e.g., |
2336 | // http://clang.llvm.org/doxygen/Stmt_8cpp_source.html |
2337 | |
2338 | // This macro makes available a variable S, the passed-in stmt. |
2339 | #define DEF_TRAVERSE_STMT(STMT, CODE) \ |
2340 | template <typename Derived> \ |
2341 | bool RecursiveASTVisitor<Derived>::Traverse##STMT( \ |
2342 | STMT *S, DataRecursionQueue *Queue) { \ |
2343 | bool ShouldVisitChildren = true; \ |
2344 | bool ReturnValue = true; \ |
2345 | if (!getDerived().shouldTraversePostOrder()) \ |
2346 | TRY_TO(WalkUpFrom##STMT(S)); \ |
2347 | { CODE; } \ |
2348 | if (ShouldVisitChildren) { \ |
2349 | for (Stmt * SubStmt : getDerived().getStmtChildren(S)) { \ |
2350 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \ |
2351 | } \ |
2352 | } \ |
2353 | /* Call WalkUpFrom if TRY_TO_TRAVERSE_OR_ENQUEUE_STMT has traversed the \ |
2354 | * children already. If TRY_TO_TRAVERSE_OR_ENQUEUE_STMT only enqueued the \ |
2355 | * children, PostVisitStmt will call WalkUpFrom after we are done visiting \ |
2356 | * children. */ \ |
2357 | if (!Queue && ReturnValue && getDerived().shouldTraversePostOrder()) { \ |
2358 | TRY_TO(WalkUpFrom##STMT(S)); \ |
2359 | } \ |
2360 | return ReturnValue; \ |
2361 | } |
2362 | |
2363 | DEF_TRAVERSE_STMT(GCCAsmStmt, { |
2364 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); |
2365 | for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { |
2366 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); |
2367 | } |
2368 | for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { |
2369 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); |
2370 | } |
2371 | for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { |
2372 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); |
2373 | } |
2374 | // children() iterates over inputExpr and outputExpr. |
2375 | }) |
2376 | |
2377 | DEF_TRAVERSE_STMT( |
2378 | MSAsmStmt, |
2379 | {// FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once |
2380 | // added this needs to be implemented. |
2381 | }) |
2382 | |
2383 | DEF_TRAVERSE_STMT(CXXCatchStmt, { |
2384 | TRY_TO(TraverseDecl(S->getExceptionDecl())); |
2385 | // children() iterates over the handler block. |
2386 | }) |
2387 | |
2388 | DEF_TRAVERSE_STMT(DeclStmt, { |
2389 | for (auto *I : S->decls()) { |
2390 | TRY_TO(TraverseDecl(I)); |
2391 | } |
2392 | // Suppress the default iteration over children() by |
2393 | // returning. Here's why: A DeclStmt looks like 'type var [= |
2394 | // initializer]'. The decls above already traverse over the |
2395 | // initializers, so we don't have to do it again (which |
2396 | // children() would do). |
2397 | ShouldVisitChildren = false; |
2398 | }) |
2399 | |
2400 | // These non-expr stmts (most of them), do not need any action except |
2401 | // iterating over the children. |
2402 | DEF_TRAVERSE_STMT(BreakStmt, {}) |
2403 | DEF_TRAVERSE_STMT(CXXTryStmt, {}) |
2404 | DEF_TRAVERSE_STMT(CaseStmt, {}) |
2405 | DEF_TRAVERSE_STMT(CompoundStmt, {}) |
2406 | DEF_TRAVERSE_STMT(ContinueStmt, {}) |
2407 | DEF_TRAVERSE_STMT(DefaultStmt, {}) |
2408 | DEF_TRAVERSE_STMT(DoStmt, {}) |
2409 | DEF_TRAVERSE_STMT(ForStmt, {}) |
2410 | DEF_TRAVERSE_STMT(GotoStmt, {}) |
2411 | DEF_TRAVERSE_STMT(IfStmt, {}) |
2412 | DEF_TRAVERSE_STMT(IndirectGotoStmt, {}) |
2413 | DEF_TRAVERSE_STMT(LabelStmt, {}) |
2414 | DEF_TRAVERSE_STMT(AttributedStmt, {}) |
2415 | DEF_TRAVERSE_STMT(NullStmt, {}) |
2416 | DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {}) |
2417 | DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {}) |
2418 | DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {}) |
2419 | DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {}) |
2420 | DEF_TRAVERSE_STMT(ObjCAtTryStmt, {}) |
2421 | DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {}) |
2422 | DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {}) |
2423 | |
2424 | DEF_TRAVERSE_STMT(CXXForRangeStmt, { |
2425 | if (!getDerived().shouldVisitImplicitCode()) { |
2426 | if (S->getInit()) |
2427 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInit()); |
2428 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt()); |
2429 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit()); |
2430 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); |
2431 | // Visit everything else only if shouldVisitImplicitCode(). |
2432 | ShouldVisitChildren = false; |
2433 | } |
2434 | }) |
2435 | |
2436 | DEF_TRAVERSE_STMT(MSDependentExistsStmt, { |
2437 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2438 | TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); |
2439 | }) |
2440 | |
2441 | DEF_TRAVERSE_STMT(ReturnStmt, {}) |
2442 | DEF_TRAVERSE_STMT(SwitchStmt, {}) |
2443 | DEF_TRAVERSE_STMT(WhileStmt, {}) |
2444 | |
2445 | DEF_TRAVERSE_STMT(ConstantExpr, {}) |
2446 | |
2447 | DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { |
2448 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2449 | TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); |
2450 | if (S->hasExplicitTemplateArgs()) { |
2451 | TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), |
2452 | S->getNumTemplateArgs())); |
2453 | } |
2454 | }) |
2455 | |
2456 | DEF_TRAVERSE_STMT(DeclRefExpr, { |
2457 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2458 | TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); |
2459 | TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), |
2460 | S->getNumTemplateArgs())); |
2461 | }) |
2462 | |
2463 | DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { |
2464 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2465 | TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); |
2466 | if (S->hasExplicitTemplateArgs()) { |
2467 | TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), |
2468 | S->getNumTemplateArgs())); |
2469 | } |
2470 | }) |
2471 | |
2472 | DEF_TRAVERSE_STMT(MemberExpr, { |
2473 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2474 | TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); |
2475 | TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), |
2476 | S->getNumTemplateArgs())); |
2477 | }) |
2478 | |
2479 | DEF_TRAVERSE_STMT( |
2480 | ImplicitCastExpr, |
2481 | {// We don't traverse the cast type, as it's not written in the |
2482 | // source code. |
2483 | }) |
2484 | |
2485 | DEF_TRAVERSE_STMT(CStyleCastExpr, { |
2486 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2487 | }) |
2488 | |
2489 | DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { |
2490 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2491 | }) |
2492 | |
2493 | DEF_TRAVERSE_STMT(CXXAddrspaceCastExpr, { |
2494 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2495 | }) |
2496 | |
2497 | DEF_TRAVERSE_STMT(CXXConstCastExpr, { |
2498 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2499 | }) |
2500 | |
2501 | DEF_TRAVERSE_STMT(CXXDynamicCastExpr, { |
2502 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2503 | }) |
2504 | |
2505 | DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, { |
2506 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2507 | }) |
2508 | |
2509 | DEF_TRAVERSE_STMT(CXXStaticCastExpr, { |
2510 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2511 | }) |
2512 | |
2513 | DEF_TRAVERSE_STMT(BuiltinBitCastExpr, { |
2514 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2515 | }) |
2516 | |
2517 | template <typename Derived> |
2518 | bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr( |
2519 | InitListExpr *S, DataRecursionQueue *Queue) { |
2520 | if (S) { |
2521 | // Skip this if we traverse postorder. We will visit it later |
2522 | // in PostVisitStmt. |
2523 | if (!getDerived().shouldTraversePostOrder()) |
2524 | TRY_TO(WalkUpFromInitListExpr(S)); |
2525 | |
2526 | // All we need are the default actions. FIXME: use a helper function. |
2527 | for (Stmt *SubStmt : S->children()) { |
2528 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); |
2529 | } |
2530 | |
2531 | if (!Queue && getDerived().shouldTraversePostOrder()) |
2532 | TRY_TO(WalkUpFromInitListExpr(S)); |
2533 | } |
2534 | return true; |
2535 | } |
2536 | |
2537 | template <typename Derived> |
2538 | bool RecursiveASTVisitor<Derived>::TraverseObjCProtocolLoc( |
2539 | ObjCProtocolLoc ProtocolLoc) { |
2540 | return true; |
2541 | } |
2542 | |
2543 | template <typename Derived> |
2544 | bool RecursiveASTVisitor<Derived>::TraverseConceptReference( |
2545 | ConceptReference *CR) { |
2546 | if (!getDerived().shouldTraversePostOrder()) |
2547 | TRY_TO(VisitConceptReference(CR)); |
2548 | TRY_TO(TraverseNestedNameSpecifierLoc(CR->getNestedNameSpecifierLoc())); |
2549 | TRY_TO(TraverseDeclarationNameInfo(CR->getConceptNameInfo())); |
2550 | if (CR->hasExplicitTemplateArgs()) |
2551 | TRY_TO(TraverseTemplateArgumentLocsHelper( |
2552 | CR->getTemplateArgsAsWritten()->getTemplateArgs(), |
2553 | CR->getTemplateArgsAsWritten()->NumTemplateArgs)); |
2554 | if (getDerived().shouldTraversePostOrder()) |
2555 | TRY_TO(VisitConceptReference(CR)); |
2556 | return true; |
2557 | } |
2558 | |
2559 | // If shouldVisitImplicitCode() returns false, this method traverses only the |
2560 | // syntactic form of InitListExpr. |
2561 | // If shouldVisitImplicitCode() return true, this method is called once for |
2562 | // each pair of syntactic and semantic InitListExpr, and it traverses the |
2563 | // subtrees defined by the two forms. This may cause some of the children to be |
2564 | // visited twice, if they appear both in the syntactic and the semantic form. |
2565 | // |
2566 | // There is no guarantee about which form \p S takes when this method is called. |
2567 | template <typename Derived> |
2568 | bool RecursiveASTVisitor<Derived>::TraverseInitListExpr( |
2569 | InitListExpr *S, DataRecursionQueue *Queue) { |
2570 | if (S->isSemanticForm() && S->isSyntacticForm()) { |
2571 | // `S` does not have alternative forms, traverse only once. |
2572 | TRY_TO(TraverseSynOrSemInitListExpr(S, Queue)); |
2573 | return true; |
2574 | } |
2575 | TRY_TO(TraverseSynOrSemInitListExpr( |
2576 | S->isSemanticForm() ? S->getSyntacticForm() : S, Queue)); |
2577 | if (getDerived().shouldVisitImplicitCode()) { |
2578 | // Only visit the semantic form if the clients are interested in implicit |
2579 | // compiler-generated. |
2580 | TRY_TO(TraverseSynOrSemInitListExpr( |
2581 | S->isSemanticForm() ? S : S->getSemanticForm(), Queue)); |
2582 | } |
2583 | return true; |
2584 | } |
2585 | |
2586 | // GenericSelectionExpr is a special case because the types and expressions |
2587 | // are interleaved. We also need to watch out for null types (default |
2588 | // generic associations). |
2589 | DEF_TRAVERSE_STMT(GenericSelectionExpr, { |
2590 | if (S->isExprPredicate()) |
2591 | TRY_TO(TraverseStmt(S->getControllingExpr())); |
2592 | else |
2593 | TRY_TO(TraverseTypeLoc(S->getControllingType()->getTypeLoc())); |
2594 | |
2595 | for (const GenericSelectionExpr::Association Assoc : S->associations()) { |
2596 | if (TypeSourceInfo *TSI = Assoc.getTypeSourceInfo()) |
2597 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); |
2598 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(Assoc.getAssociationExpr()); |
2599 | } |
2600 | ShouldVisitChildren = false; |
2601 | }) |
2602 | |
2603 | // PseudoObjectExpr is a special case because of the weirdness with |
2604 | // syntactic expressions and opaque values. |
2605 | DEF_TRAVERSE_STMT(PseudoObjectExpr, { |
2606 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm()); |
2607 | for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(), |
2608 | e = S->semantics_end(); |
2609 | i != e; ++i) { |
2610 | Expr *sub = *i; |
2611 | if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub)) |
2612 | sub = OVE->getSourceExpr(); |
2613 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub); |
2614 | } |
2615 | ShouldVisitChildren = false; |
2616 | }) |
2617 | |
2618 | DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { |
2619 | // This is called for code like 'return T()' where T is a built-in |
2620 | // (i.e. non-class) type. |
2621 | TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); |
2622 | }) |
2623 | |
2624 | DEF_TRAVERSE_STMT(CXXNewExpr, { |
2625 | // The child-iterator will pick up the other arguments. |
2626 | TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc())); |
2627 | }) |
2628 | |
2629 | DEF_TRAVERSE_STMT(OffsetOfExpr, { |
2630 | // The child-iterator will pick up the expression representing |
2631 | // the field. |
2632 | // FIMXE: for code like offsetof(Foo, a.b.c), should we get |
2633 | // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? |
2634 | TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); |
2635 | }) |
2636 | |
2637 | DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { |
2638 | // The child-iterator will pick up the arg if it's an expression, |
2639 | // but not if it's a type. |
2640 | if (S->isArgumentType()) |
2641 | TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); |
2642 | }) |
2643 | |
2644 | DEF_TRAVERSE_STMT(CXXTypeidExpr, { |
2645 | // The child-iterator will pick up the arg if it's an expression, |
2646 | // but not if it's a type. |
2647 | if (S->isTypeOperand()) |
2648 | TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); |
2649 | }) |
2650 | |
2651 | DEF_TRAVERSE_STMT(MSPropertyRefExpr, { |
2652 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2653 | }) |
2654 | |
2655 | DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {}) |
2656 | |
2657 | DEF_TRAVERSE_STMT(CXXUuidofExpr, { |
2658 | // The child-iterator will pick up the arg if it's an expression, |
2659 | // but not if it's a type. |
2660 | if (S->isTypeOperand()) |
2661 | TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); |
2662 | }) |
2663 | |
2664 | DEF_TRAVERSE_STMT(TypeTraitExpr, { |
2665 | for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) |
2666 | TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc())); |
2667 | }) |
2668 | |
2669 | DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { |
2670 | TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); |
2671 | }) |
2672 | |
2673 | DEF_TRAVERSE_STMT(ExpressionTraitExpr, |
2674 | { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); }) |
2675 | |
2676 | DEF_TRAVERSE_STMT(VAArgExpr, { |
2677 | // The child-iterator will pick up the expression argument. |
2678 | TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); |
2679 | }) |
2680 | |
2681 | DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { |
2682 | // This is called for code like 'return T()' where T is a class type. |
2683 | TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); |
2684 | }) |
2685 | |
2686 | // Walk only the visible parts of lambda expressions. |
2687 | DEF_TRAVERSE_STMT(LambdaExpr, { |
2688 | // Visit the capture list. |
2689 | for (unsigned I = 0, N = S->capture_size(); I != N; ++I) { |
2690 | const LambdaCapture *C = S->capture_begin() + I; |
2691 | if (C->isExplicit() || getDerived().shouldVisitImplicitCode()) { |
2692 | TRY_TO(TraverseLambdaCapture(S, C, S->capture_init_begin()[I])); |
2693 | } |
2694 | } |
2695 | |
2696 | if (getDerived().shouldVisitImplicitCode()) { |
2697 | // The implicit model is simple: everything else is in the lambda class. |
2698 | TRY_TO(TraverseDecl(S->getLambdaClass())); |
2699 | } else { |
2700 | // We need to poke around to find the bits that might be explicitly written. |
2701 | TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); |
2702 | FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>(); |
2703 | |
2704 | TRY_TO(TraverseTemplateParameterListHelper(S->getTemplateParameterList())); |
2705 | if (S->hasExplicitParameters()) { |
2706 | // Visit parameters. |
2707 | for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) |
2708 | TRY_TO(TraverseDecl(Proto.getParam(I))); |
2709 | } |
2710 | |
2711 | auto *T = Proto.getTypePtr(); |
2712 | for (const auto &E : T->exceptions()) |
2713 | TRY_TO(TraverseType(E)); |
2714 | |
2715 | if (Expr *NE = T->getNoexceptExpr()) |
2716 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE); |
2717 | |
2718 | if (S->hasExplicitResultType()) |
2719 | TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); |
2720 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getTrailingRequiresClause()); |
2721 | |
2722 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); |
2723 | } |
2724 | ShouldVisitChildren = false; |
2725 | }) |
2726 | |
2727 | DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { |
2728 | // This is called for code like 'T()', where T is a template argument. |
2729 | TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); |
2730 | }) |
2731 | |
2732 | // These expressions all might take explicit template arguments. |
2733 | // We traverse those if so. FIXME: implement these. |
2734 | DEF_TRAVERSE_STMT(CXXConstructExpr, {}) |
2735 | DEF_TRAVERSE_STMT(CallExpr, {}) |
2736 | DEF_TRAVERSE_STMT(CXXMemberCallExpr, {}) |
2737 | |
2738 | // These exprs (most of them), do not need any action except iterating |
2739 | // over the children. |
2740 | DEF_TRAVERSE_STMT(AddrLabelExpr, {}) |
2741 | DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) |
2742 | DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {}) |
2743 | DEF_TRAVERSE_STMT(OMPArraySectionExpr, {}) |
2744 | DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {}) |
2745 | DEF_TRAVERSE_STMT(OMPIteratorExpr, {}) |
2746 | |
2747 | DEF_TRAVERSE_STMT(BlockExpr, { |
2748 | TRY_TO(TraverseDecl(S->getBlockDecl())); |
2749 | return true; // no child statements to loop through. |
2750 | }) |
2751 | |
2752 | DEF_TRAVERSE_STMT(ChooseExpr, {}) |
2753 | DEF_TRAVERSE_STMT(CompoundLiteralExpr, { |
2754 | TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); |
2755 | }) |
2756 | DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {}) |
2757 | DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {}) |
2758 | |
2759 | DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { |
2760 | if (getDerived().shouldVisitImplicitCode()) |
2761 | TRY_TO(TraverseStmt(S->getExpr())); |
2762 | }) |
2763 | |
2764 | DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { |
2765 | if (getDerived().shouldVisitImplicitCode()) |
2766 | TRY_TO(TraverseStmt(S->getExpr())); |
2767 | }) |
2768 | |
2769 | DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) |
2770 | DEF_TRAVERSE_STMT(ExprWithCleanups, {}) |
2771 | DEF_TRAVERSE_STMT(CXXInheritedCtorInitExpr, {}) |
2772 | DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {}) |
2773 | DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {}) |
2774 | |
2775 | DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { |
2776 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2777 | if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) |
2778 | TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc())); |
2779 | if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo()) |
2780 | TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc())); |
2781 | }) |
2782 | |
2783 | DEF_TRAVERSE_STMT(CXXThisExpr, {}) |
2784 | DEF_TRAVERSE_STMT(CXXThrowExpr, {}) |
2785 | DEF_TRAVERSE_STMT(UserDefinedLiteral, {}) |
2786 | DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) |
2787 | DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {}) |
2788 | DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) |
2789 | DEF_TRAVERSE_STMT(GNUNullExpr, {}) |
2790 | DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) |
2791 | DEF_TRAVERSE_STMT(NoInitExpr, {}) |
2792 | DEF_TRAVERSE_STMT(ArrayInitLoopExpr, { |
2793 | // FIXME: The source expression of the OVE should be listed as |
2794 | // a child of the ArrayInitLoopExpr. |
2795 | if (OpaqueValueExpr *OVE = S->getCommonExpr()) |
2796 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(OVE->getSourceExpr()); |
2797 | }) |
2798 | DEF_TRAVERSE_STMT(ArrayInitIndexExpr, {}) |
2799 | DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) |
2800 | |
2801 | DEF_TRAVERSE_STMT(ObjCEncodeExpr, { |
2802 | if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) |
2803 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
2804 | }) |
2805 | |
2806 | DEF_TRAVERSE_STMT(ObjCIsaExpr, {}) |
2807 | DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {}) |
2808 | |
2809 | DEF_TRAVERSE_STMT(ObjCMessageExpr, { |
2810 | if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo()) |
2811 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
2812 | }) |
2813 | |
2814 | DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { |
2815 | if (S->isClassReceiver()) { |
2816 | ObjCInterfaceDecl *IDecl = S->getClassReceiver(); |
2817 | QualType Type = IDecl->getASTContext().getObjCInterfaceType(IDecl); |
2818 | ObjCInterfaceLocInfo Data; |
2819 | Data.NameLoc = S->getReceiverLocation(); |
2820 | Data.NameEndLoc = Data.NameLoc; |
2821 | TRY_TO(TraverseTypeLoc(TypeLoc(Type, &Data))); |
2822 | } |
2823 | }) |
2824 | DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {}) |
2825 | DEF_TRAVERSE_STMT(ObjCProtocolExpr, {}) |
2826 | DEF_TRAVERSE_STMT(ObjCSelectorExpr, {}) |
2827 | DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {}) |
2828 | |
2829 | DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, { |
2830 | TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); |
2831 | }) |
2832 | |
2833 | DEF_TRAVERSE_STMT(ObjCAvailabilityCheckExpr, {}) |
2834 | DEF_TRAVERSE_STMT(ParenExpr, {}) |
2835 | DEF_TRAVERSE_STMT(ParenListExpr, {}) |
2836 | DEF_TRAVERSE_STMT(SYCLUniqueStableNameExpr, { |
2837 | TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); |
2838 | }) |
2839 | DEF_TRAVERSE_STMT(PredefinedExpr, {}) |
2840 | DEF_TRAVERSE_STMT(ShuffleVectorExpr, {}) |
2841 | DEF_TRAVERSE_STMT(ConvertVectorExpr, {}) |
2842 | DEF_TRAVERSE_STMT(StmtExpr, {}) |
2843 | DEF_TRAVERSE_STMT(SourceLocExpr, {}) |
2844 | |
2845 | DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { |
2846 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2847 | if (S->hasExplicitTemplateArgs()) { |
2848 | TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), |
2849 | S->getNumTemplateArgs())); |
2850 | } |
2851 | }) |
2852 | |
2853 | DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { |
2854 | TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |
2855 | if (S->hasExplicitTemplateArgs()) { |
2856 | TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), |
2857 | S->getNumTemplateArgs())); |
2858 | } |
2859 | }) |
2860 | |
2861 | DEF_TRAVERSE_STMT(SEHTryStmt, {}) |
2862 | DEF_TRAVERSE_STMT(SEHExceptStmt, {}) |
2863 | DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) |
2864 | DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) |
2865 | DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) |
2866 | |
2867 | DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) |
2868 | DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, { |
2869 | if (!getDerived().shouldVisitImplicitCode()) { |
2870 | CXXRewrittenBinaryOperator::DecomposedForm Decomposed = |
2871 | S->getDecomposedForm(); |
2872 | TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.LHS))); |
2873 | TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.RHS))); |
2874 | ShouldVisitChildren = false; |
2875 | } |
2876 | }) |
2877 | DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) |
2878 | DEF_TRAVERSE_STMT(TypoExpr, {}) |
2879 | DEF_TRAVERSE_STMT(RecoveryExpr, {}) |
2880 | DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) |
2881 | |
2882 | // These operators (all of them) do not need any action except |
2883 | // iterating over the children. |
2884 | DEF_TRAVERSE_STMT(BinaryConditionalOperator, {}) |
2885 | DEF_TRAVERSE_STMT(ConditionalOperator, {}) |
2886 | DEF_TRAVERSE_STMT(UnaryOperator, {}) |
2887 | DEF_TRAVERSE_STMT(BinaryOperator, {}) |
2888 | DEF_TRAVERSE_STMT(CompoundAssignOperator, {}) |
2889 | DEF_TRAVERSE_STMT(CXXNoexceptExpr, {}) |
2890 | DEF_TRAVERSE_STMT(PackExpansionExpr, {}) |
2891 | DEF_TRAVERSE_STMT(SizeOfPackExpr, {}) |
2892 | DEF_TRAVERSE_STMT(PackIndexingExpr, {}) |
2893 | DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) |
2894 | DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) |
2895 | DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) |
2896 | DEF_TRAVERSE_STMT(CXXFoldExpr, {}) |
2897 | DEF_TRAVERSE_STMT(AtomicExpr, {}) |
2898 | DEF_TRAVERSE_STMT(CXXParenListInitExpr, {}) |
2899 | |
2900 | DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { |
2901 | if (S->getLifetimeExtendedTemporaryDecl()) { |
2902 | TRY_TO(TraverseLifetimeExtendedTemporaryDecl( |
2903 | S->getLifetimeExtendedTemporaryDecl())); |
2904 | ShouldVisitChildren = false; |
2905 | } |
2906 | }) |
2907 | // For coroutines expressions, traverse either the operand |
2908 | // as written or the implied calls, depending on what the |
2909 | // derived class requests. |
2910 | DEF_TRAVERSE_STMT(CoroutineBodyStmt, { |
2911 | if (!getDerived().shouldVisitImplicitCode()) { |
2912 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); |
2913 | ShouldVisitChildren = false; |
2914 | } |
2915 | }) |
2916 | DEF_TRAVERSE_STMT(CoreturnStmt, { |
2917 | if (!getDerived().shouldVisitImplicitCode()) { |
2918 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); |
2919 | ShouldVisitChildren = false; |
2920 | } |
2921 | }) |
2922 | DEF_TRAVERSE_STMT(CoawaitExpr, { |
2923 | if (!getDerived().shouldVisitImplicitCode()) { |
2924 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); |
2925 | ShouldVisitChildren = false; |
2926 | } |
2927 | }) |
2928 | DEF_TRAVERSE_STMT(DependentCoawaitExpr, { |
2929 | if (!getDerived().shouldVisitImplicitCode()) { |
2930 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); |
2931 | ShouldVisitChildren = false; |
2932 | } |
2933 | }) |
2934 | DEF_TRAVERSE_STMT(CoyieldExpr, { |
2935 | if (!getDerived().shouldVisitImplicitCode()) { |
2936 | TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); |
2937 | ShouldVisitChildren = false; |
2938 | } |
2939 | }) |
2940 | |
2941 | DEF_TRAVERSE_STMT(ConceptSpecializationExpr, { |
2942 | TRY_TO(TraverseConceptReference(S->getConceptReference())); |
2943 | }) |
2944 | |
2945 | DEF_TRAVERSE_STMT(RequiresExpr, { |
2946 | TRY_TO(TraverseDecl(S->getBody())); |
2947 | for (ParmVarDecl *Parm : S->getLocalParameters()) |
2948 | TRY_TO(TraverseDecl(Parm)); |
2949 | for (concepts::Requirement *Req : S->getRequirements()) |
2950 | TRY_TO(TraverseConceptRequirement(Req)); |
2951 | }) |
2952 | |
2953 | // These literals (all of them) do not need any action. |
2954 | DEF_TRAVERSE_STMT(IntegerLiteral, {}) |
2955 | DEF_TRAVERSE_STMT(FixedPointLiteral, {}) |
2956 | DEF_TRAVERSE_STMT(CharacterLiteral, {}) |
2957 | DEF_TRAVERSE_STMT(FloatingLiteral, {}) |
2958 | DEF_TRAVERSE_STMT(ImaginaryLiteral, {}) |
2959 | DEF_TRAVERSE_STMT(StringLiteral, {}) |
2960 | DEF_TRAVERSE_STMT(ObjCStringLiteral, {}) |
2961 | DEF_TRAVERSE_STMT(ObjCBoxedExpr, {}) |
2962 | DEF_TRAVERSE_STMT(ObjCArrayLiteral, {}) |
2963 | DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {}) |
2964 | |
2965 | // Traverse OpenCL: AsType, Convert. |
2966 | DEF_TRAVERSE_STMT(AsTypeExpr, {}) |
2967 | |
2968 | // OpenMP directives. |
2969 | template <typename Derived> |
2970 | bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( |
2971 | OMPExecutableDirective *S) { |
2972 | for (auto *C : S->clauses()) { |
2973 | TRY_TO(TraverseOMPClause(C)); |
2974 | } |
2975 | return true; |
2976 | } |
2977 | |
2978 | DEF_TRAVERSE_STMT(OMPCanonicalLoop, { |
2979 | if (!getDerived().shouldVisitImplicitCode()) { |
2980 | // Visit only the syntactical loop. |
2981 | TRY_TO(TraverseStmt(S->getLoopStmt())); |
2982 | ShouldVisitChildren = false; |
2983 | } |
2984 | }) |
2985 | |
2986 | template <typename Derived> |
2987 | bool |
2988 | RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { |
2989 | return TraverseOMPExecutableDirective(S); |
2990 | } |
2991 | |
2992 | DEF_TRAVERSE_STMT(OMPMetaDirective, |
2993 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
2994 | |
2995 | DEF_TRAVERSE_STMT(OMPParallelDirective, |
2996 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
2997 | |
2998 | DEF_TRAVERSE_STMT(OMPSimdDirective, |
2999 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3000 | |
3001 | DEF_TRAVERSE_STMT(OMPTileDirective, |
3002 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3003 | |
3004 | DEF_TRAVERSE_STMT(OMPUnrollDirective, |
3005 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3006 | |
3007 | DEF_TRAVERSE_STMT(OMPForDirective, |
3008 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3009 | |
3010 | DEF_TRAVERSE_STMT(OMPForSimdDirective, |
3011 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3012 | |
3013 | DEF_TRAVERSE_STMT(OMPSectionsDirective, |
3014 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3015 | |
3016 | DEF_TRAVERSE_STMT(OMPSectionDirective, |
3017 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3018 | |
3019 | DEF_TRAVERSE_STMT(OMPScopeDirective, |
3020 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3021 | |
3022 | DEF_TRAVERSE_STMT(OMPSingleDirective, |
3023 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3024 | |
3025 | DEF_TRAVERSE_STMT(OMPMasterDirective, |
3026 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3027 | |
3028 | DEF_TRAVERSE_STMT(OMPCriticalDirective, { |
3029 | TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); |
3030 | TRY_TO(TraverseOMPExecutableDirective(S)); |
3031 | }) |
3032 | |
3033 | DEF_TRAVERSE_STMT(OMPParallelForDirective, |
3034 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3035 | |
3036 | DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, |
3037 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3038 | |
3039 | DEF_TRAVERSE_STMT(OMPParallelMasterDirective, |
3040 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3041 | |
3042 | DEF_TRAVERSE_STMT(OMPParallelMaskedDirective, |
3043 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3044 | |
3045 | DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, |
3046 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3047 | |
3048 | DEF_TRAVERSE_STMT(OMPTaskDirective, |
3049 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3050 | |
3051 | DEF_TRAVERSE_STMT(OMPTaskyieldDirective, |
3052 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3053 | |
3054 | DEF_TRAVERSE_STMT(OMPBarrierDirective, |
3055 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3056 | |
3057 | DEF_TRAVERSE_STMT(OMPTaskwaitDirective, |
3058 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3059 | |
3060 | DEF_TRAVERSE_STMT(OMPTaskgroupDirective, |
3061 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3062 | |
3063 | DEF_TRAVERSE_STMT(OMPCancellationPointDirective, |
3064 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3065 | |
3066 | DEF_TRAVERSE_STMT(OMPCancelDirective, |
3067 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3068 | |
3069 | DEF_TRAVERSE_STMT(OMPFlushDirective, |
3070 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3071 | |
3072 | DEF_TRAVERSE_STMT(OMPDepobjDirective, |
3073 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3074 | |
3075 | DEF_TRAVERSE_STMT(OMPScanDirective, |
3076 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3077 | |
3078 | DEF_TRAVERSE_STMT(OMPOrderedDirective, |
3079 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3080 | |
3081 | DEF_TRAVERSE_STMT(OMPAtomicDirective, |
3082 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3083 | |
3084 | DEF_TRAVERSE_STMT(OMPTargetDirective, |
3085 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3086 | |
3087 | DEF_TRAVERSE_STMT(OMPTargetDataDirective, |
3088 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3089 | |
3090 | DEF_TRAVERSE_STMT(OMPTargetEnterDataDirective, |
3091 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3092 | |
3093 | DEF_TRAVERSE_STMT(OMPTargetExitDataDirective, |
3094 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3095 | |
3096 | DEF_TRAVERSE_STMT(OMPTargetParallelDirective, |
3097 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3098 | |
3099 | DEF_TRAVERSE_STMT(OMPTargetParallelForDirective, |
3100 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3101 | |
3102 | DEF_TRAVERSE_STMT(OMPTeamsDirective, |
3103 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3104 | |
3105 | DEF_TRAVERSE_STMT(OMPTargetUpdateDirective, |
3106 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3107 | |
3108 | DEF_TRAVERSE_STMT(OMPTaskLoopDirective, |
3109 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3110 | |
3111 | DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective, |
3112 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3113 | |
3114 | DEF_TRAVERSE_STMT(OMPMasterTaskLoopDirective, |
3115 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3116 | |
3117 | DEF_TRAVERSE_STMT(OMPMasterTaskLoopSimdDirective, |
3118 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3119 | |
3120 | DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopDirective, |
3121 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3122 | |
3123 | DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopSimdDirective, |
3124 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3125 | |
3126 | DEF_TRAVERSE_STMT(OMPMaskedTaskLoopDirective, |
3127 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3128 | |
3129 | DEF_TRAVERSE_STMT(OMPMaskedTaskLoopSimdDirective, |
3130 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3131 | |
3132 | DEF_TRAVERSE_STMT(OMPParallelMaskedTaskLoopDirective, |
3133 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3134 | |
3135 | DEF_TRAVERSE_STMT(OMPParallelMaskedTaskLoopSimdDirective, |
3136 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3137 | |
3138 | DEF_TRAVERSE_STMT(OMPDistributeDirective, |
3139 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3140 | |
3141 | DEF_TRAVERSE_STMT(OMPDistributeParallelForDirective, |
3142 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3143 | |
3144 | DEF_TRAVERSE_STMT(OMPDistributeParallelForSimdDirective, |
3145 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3146 | |
3147 | DEF_TRAVERSE_STMT(OMPDistributeSimdDirective, |
3148 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3149 | |
3150 | DEF_TRAVERSE_STMT(OMPTargetParallelForSimdDirective, |
3151 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3152 | |
3153 | DEF_TRAVERSE_STMT(OMPTargetSimdDirective, |
3154 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3155 | |
3156 | DEF_TRAVERSE_STMT(OMPTeamsDistributeDirective, |
3157 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3158 | |
3159 | DEF_TRAVERSE_STMT(OMPTeamsDistributeSimdDirective, |
3160 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3161 | |
3162 | DEF_TRAVERSE_STMT(OMPTeamsDistributeParallelForSimdDirective, |
3163 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3164 | |
3165 | DEF_TRAVERSE_STMT(OMPTeamsDistributeParallelForDirective, |
3166 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3167 | |
3168 | DEF_TRAVERSE_STMT(OMPTargetTeamsDirective, |
3169 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3170 | |
3171 | DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeDirective, |
3172 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3173 | |
3174 | DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeParallelForDirective, |
3175 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3176 | |
3177 | DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeParallelForSimdDirective, |
3178 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3179 | |
3180 | DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeSimdDirective, |
3181 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3182 | |
3183 | DEF_TRAVERSE_STMT(OMPInteropDirective, |
3184 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3185 | |
3186 | DEF_TRAVERSE_STMT(OMPDispatchDirective, |
3187 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3188 | |
3189 | DEF_TRAVERSE_STMT(OMPMaskedDirective, |
3190 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3191 | |
3192 | DEF_TRAVERSE_STMT(OMPGenericLoopDirective, |
3193 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3194 | |
3195 | DEF_TRAVERSE_STMT(OMPTeamsGenericLoopDirective, |
3196 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3197 | |
3198 | DEF_TRAVERSE_STMT(OMPTargetTeamsGenericLoopDirective, |
3199 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3200 | |
3201 | DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective, |
3202 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3203 | |
3204 | DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective, |
3205 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3206 | |
3207 | DEF_TRAVERSE_STMT(OMPErrorDirective, |
3208 | { TRY_TO(TraverseOMPExecutableDirective(S)); }) |
3209 | |
3210 | // OpenMP clauses. |
3211 | template <typename Derived> |
3212 | bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { |
3213 | if (!C) |
3214 | return true; |
3215 | switch (C->getClauseKind()) { |
3216 | #define GEN_CLANG_CLAUSE_CLASS |
3217 | #define CLAUSE_CLASS(Enum, Str, Class) \ |
3218 | case llvm::omp::Clause::Enum: \ |
3219 | TRY_TO(Visit##Class(static_cast<Class *>(C))); \ |
3220 | break; |
3221 | #define CLAUSE_NO_CLASS(Enum, Str) \ |
3222 | case llvm::omp::Clause::Enum: \ |
3223 | break; |
3224 | #include "llvm/Frontend/OpenMP/OMP.inc" |
3225 | } |
3226 | return true; |
3227 | } |
3228 | |
3229 | template <typename Derived> |
3230 | bool RecursiveASTVisitor<Derived>::VisitOMPClauseWithPreInit( |
3231 | OMPClauseWithPreInit *Node) { |
3232 | TRY_TO(TraverseStmt(Node->getPreInitStmt())); |
3233 | return true; |
3234 | } |
3235 | |
3236 | template <typename Derived> |
3237 | bool RecursiveASTVisitor<Derived>::VisitOMPClauseWithPostUpdate( |
3238 | OMPClauseWithPostUpdate *Node) { |
3239 | TRY_TO(VisitOMPClauseWithPreInit(Node)); |
3240 | TRY_TO(TraverseStmt(Node->getPostUpdateExpr())); |
3241 | return true; |
3242 | } |
3243 | |
3244 | template <typename Derived> |
3245 | bool RecursiveASTVisitor<Derived>::VisitOMPAllocatorClause( |
3246 | OMPAllocatorClause *C) { |
3247 | TRY_TO(TraverseStmt(C->getAllocator())); |
3248 | return true; |
3249 | } |
3250 | |
3251 | template <typename Derived> |
3252 | bool RecursiveASTVisitor<Derived>::VisitOMPAllocateClause(OMPAllocateClause *C) { |
3253 | TRY_TO(TraverseStmt(C->getAllocator())); |
3254 | TRY_TO(VisitOMPClauseList(C)); |
3255 | return true; |
3256 | } |
3257 | |
3258 | template <typename Derived> |
3259 | bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { |
3260 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3261 | TRY_TO(TraverseStmt(C->getCondition())); |
3262 | return true; |
3263 | } |
3264 | |
3265 | template <typename Derived> |
3266 | bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { |
3267 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3268 | TRY_TO(TraverseStmt(C->getCondition())); |
3269 | return true; |
3270 | } |
3271 | |
3272 | template <typename Derived> |
3273 | bool |
3274 | RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { |
3275 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3276 | TRY_TO(TraverseStmt(C->getNumThreads())); |
3277 | return true; |
3278 | } |
3279 | |
3280 | template <typename Derived> |
3281 | bool RecursiveASTVisitor<Derived>::VisitOMPAlignClause(OMPAlignClause *C) { |
3282 | TRY_TO(TraverseStmt(C->getAlignment())); |
3283 | return true; |
3284 | } |
3285 | |
3286 | template <typename Derived> |
3287 | bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) { |
3288 | TRY_TO(TraverseStmt(C->getSafelen())); |
3289 | return true; |
3290 | } |
3291 | |
3292 | template <typename Derived> |
3293 | bool RecursiveASTVisitor<Derived>::VisitOMPSimdlenClause(OMPSimdlenClause *C) { |
3294 | TRY_TO(TraverseStmt(C->getSimdlen())); |
3295 | return true; |
3296 | } |
3297 | |
3298 | template <typename Derived> |
3299 | bool RecursiveASTVisitor<Derived>::VisitOMPSizesClause(OMPSizesClause *C) { |
3300 | for (Expr *E : C->getSizesRefs()) |
3301 | TRY_TO(TraverseStmt(E)); |
3302 | return true; |
3303 | } |
3304 | |
3305 | template <typename Derived> |
3306 | bool RecursiveASTVisitor<Derived>::VisitOMPFullClause(OMPFullClause *C) { |
3307 | return true; |
3308 | } |
3309 | |
3310 | template <typename Derived> |
3311 | bool RecursiveASTVisitor<Derived>::VisitOMPPartialClause(OMPPartialClause *C) { |
3312 | TRY_TO(TraverseStmt(C->getFactor())); |
3313 | return true; |
3314 | } |
3315 | |
3316 | template <typename Derived> |
3317 | bool |
3318 | RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) { |
3319 | TRY_TO(TraverseStmt(C->getNumForLoops())); |
3320 | return true; |
3321 | } |
3322 | |
3323 | template <typename Derived> |
3324 | bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) { |
3325 | return true; |
3326 | } |
3327 | |
3328 | template <typename Derived> |
3329 | bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) { |
3330 | return true; |
3331 | } |
3332 | |
3333 | template <typename Derived> |
3334 | bool RecursiveASTVisitor<Derived>::VisitOMPUnifiedAddressClause( |
3335 | OMPUnifiedAddressClause *) { |
3336 | return true; |
3337 | } |
3338 | |
3339 | template <typename Derived> |
3340 | bool RecursiveASTVisitor<Derived>::VisitOMPUnifiedSharedMemoryClause( |
3341 | OMPUnifiedSharedMemoryClause *) { |
3342 | return true; |
3343 | } |
3344 | |
3345 | template <typename Derived> |
3346 | bool RecursiveASTVisitor<Derived>::VisitOMPReverseOffloadClause( |
3347 | OMPReverseOffloadClause *) { |
3348 | return true; |
3349 | } |
3350 | |
3351 | template <typename Derived> |
3352 | bool RecursiveASTVisitor<Derived>::VisitOMPDynamicAllocatorsClause( |
3353 | OMPDynamicAllocatorsClause *) { |
3354 | return true; |
3355 | } |
3356 | |
3357 | template <typename Derived> |
3358 | bool RecursiveASTVisitor<Derived>::VisitOMPAtomicDefaultMemOrderClause( |
3359 | OMPAtomicDefaultMemOrderClause *) { |
3360 | return true; |
3361 | } |
3362 | |
3363 | template <typename Derived> |
3364 | bool RecursiveASTVisitor<Derived>::VisitOMPAtClause(OMPAtClause *) { |
3365 | return true; |
3366 | } |
3367 | |
3368 | template <typename Derived> |
3369 | bool RecursiveASTVisitor<Derived>::VisitOMPSeverityClause(OMPSeverityClause *) { |
3370 | return true; |
3371 | } |
3372 | |
3373 | template <typename Derived> |
3374 | bool RecursiveASTVisitor<Derived>::VisitOMPMessageClause(OMPMessageClause *C) { |
3375 | TRY_TO(TraverseStmt(C->getMessageString())); |
3376 | return true; |
3377 | } |
3378 | |
3379 | template <typename Derived> |
3380 | bool |
3381 | RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { |
3382 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3383 | TRY_TO(TraverseStmt(C->getChunkSize())); |
3384 | return true; |
3385 | } |
3386 | |
3387 | template <typename Derived> |
3388 | bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) { |
3389 | TRY_TO(TraverseStmt(C->getNumForLoops())); |
3390 | return true; |
3391 | } |
3392 | |
3393 | template <typename Derived> |
3394 | bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) { |
3395 | return true; |
3396 | } |
3397 | |
3398 | template <typename Derived> |
3399 | bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) { |
3400 | return true; |
3401 | } |
3402 | |
3403 | template <typename Derived> |
3404 | bool |
3405 | RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { |
3406 | return true; |
3407 | } |
3408 | |
3409 | template <typename Derived> |
3410 | bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { |
3411 | return true; |
3412 | } |
3413 | |
3414 | template <typename Derived> |
3415 | bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { |
3416 | return true; |
3417 | } |
3418 | |
3419 | template <typename Derived> |
3420 | bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { |
3421 | return true; |
3422 | } |
3423 | |
3424 | template <typename Derived> |
3425 | bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { |
3426 | return true; |
3427 | } |
3428 | |
3429 | template <typename Derived> |
3430 | bool RecursiveASTVisitor<Derived>::VisitOMPCompareClause(OMPCompareClause *) { |
3431 | return true; |
3432 | } |
3433 | |
3434 | template <typename Derived> |
3435 | bool RecursiveASTVisitor<Derived>::VisitOMPFailClause(OMPFailClause *) { |
3436 | return true; |
3437 | } |
3438 | |
3439 | template <typename Derived> |
3440 | bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { |
3441 | return true; |
3442 | } |
3443 | |
3444 | template <typename Derived> |
3445 | bool RecursiveASTVisitor<Derived>::VisitOMPAcqRelClause(OMPAcqRelClause *) { |
3446 | return true; |
3447 | } |
3448 | |
3449 | template <typename Derived> |
3450 | bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) { |
3451 | return true; |
3452 | } |
3453 | |
3454 | template <typename Derived> |
3455 | bool RecursiveASTVisitor<Derived>::VisitOMPReleaseClause(OMPReleaseClause *) { |
3456 | return true; |
3457 | } |
3458 | |
3459 | template <typename Derived> |
3460 | bool RecursiveASTVisitor<Derived>::VisitOMPRelaxedClause(OMPRelaxedClause *) { |
3461 | return true; |
3462 | } |
3463 | |
3464 | template <typename Derived> |
3465 | bool RecursiveASTVisitor<Derived>::VisitOMPWeakClause(OMPWeakClause *) { |
3466 | return true; |
3467 | } |
3468 | |
3469 | template <typename Derived> |
3470 | bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) { |
3471 | return true; |
3472 | } |
3473 | |
3474 | template <typename Derived> |
3475 | bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) { |
3476 | return true; |
3477 | } |
3478 | |
3479 | template <typename Derived> |
3480 | bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) { |
3481 | return true; |
3482 | } |
3483 | |
3484 | template <typename Derived> |
3485 | bool RecursiveASTVisitor<Derived>::VisitOMPInitClause(OMPInitClause *C) { |
3486 | TRY_TO(VisitOMPClauseList(C)); |
3487 | return true; |
3488 | } |
3489 | |
3490 | template <typename Derived> |
3491 | bool RecursiveASTVisitor<Derived>::VisitOMPUseClause(OMPUseClause *C) { |
3492 | TRY_TO(TraverseStmt(C->getInteropVar())); |
3493 | return true; |
3494 | } |
3495 | |
3496 | template <typename Derived> |
3497 | bool RecursiveASTVisitor<Derived>::VisitOMPDestroyClause(OMPDestroyClause *C) { |
3498 | TRY_TO(TraverseStmt(C->getInteropVar())); |
3499 | return true; |
3500 | } |
3501 | |
3502 | template <typename Derived> |
3503 | bool RecursiveASTVisitor<Derived>::VisitOMPNovariantsClause( |
3504 | OMPNovariantsClause *C) { |
3505 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3506 | TRY_TO(TraverseStmt(C->getCondition())); |
3507 | return true; |
3508 | } |
3509 | |
3510 | template <typename Derived> |
3511 | bool RecursiveASTVisitor<Derived>::VisitOMPNocontextClause( |
3512 | OMPNocontextClause *C) { |
3513 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3514 | TRY_TO(TraverseStmt(C->getCondition())); |
3515 | return true; |
3516 | } |
3517 | |
3518 | template <typename Derived> |
3519 | template <typename T> |
3520 | bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { |
3521 | for (auto *E : Node->varlists()) { |
3522 | TRY_TO(TraverseStmt(E)); |
3523 | } |
3524 | return true; |
3525 | } |
3526 | |
3527 | template <typename Derived> |
3528 | bool RecursiveASTVisitor<Derived>::VisitOMPInclusiveClause( |
3529 | OMPInclusiveClause *C) { |
3530 | TRY_TO(VisitOMPClauseList(C)); |
3531 | return true; |
3532 | } |
3533 | |
3534 | template <typename Derived> |
3535 | bool RecursiveASTVisitor<Derived>::VisitOMPExclusiveClause( |
3536 | OMPExclusiveClause *C) { |
3537 | TRY_TO(VisitOMPClauseList(C)); |
3538 | return true; |
3539 | } |
3540 | |
3541 | template <typename Derived> |
3542 | bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { |
3543 | TRY_TO(VisitOMPClauseList(C)); |
3544 | for (auto *E : C->private_copies()) { |
3545 | TRY_TO(TraverseStmt(E)); |
3546 | } |
3547 | return true; |
3548 | } |
3549 | |
3550 | template <typename Derived> |
3551 | bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( |
3552 | OMPFirstprivateClause *C) { |
3553 | TRY_TO(VisitOMPClauseList(C)); |
3554 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3555 | for (auto *E : C->private_copies()) { |
3556 | TRY_TO(TraverseStmt(E)); |
3557 | } |
3558 | for (auto *E : C->inits()) { |
3559 | TRY_TO(TraverseStmt(E)); |
3560 | } |
3561 | return true; |
3562 | } |
3563 | |
3564 | template <typename Derived> |
3565 | bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause( |
3566 | OMPLastprivateClause *C) { |
3567 | TRY_TO(VisitOMPClauseList(C)); |
3568 | TRY_TO(VisitOMPClauseWithPostUpdate(C)); |
3569 | for (auto *E : C->private_copies()) { |
3570 | TRY_TO(TraverseStmt(E)); |
3571 | } |
3572 | for (auto *E : C->source_exprs()) { |
3573 | TRY_TO(TraverseStmt(E)); |
3574 | } |
3575 | for (auto *E : C->destination_exprs()) { |
3576 | TRY_TO(TraverseStmt(E)); |
3577 | } |
3578 | for (auto *E : C->assignment_ops()) { |
3579 | TRY_TO(TraverseStmt(E)); |
3580 | } |
3581 | return true; |
3582 | } |
3583 | |
3584 | template <typename Derived> |
3585 | bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) { |
3586 | TRY_TO(VisitOMPClauseList(C)); |
3587 | return true; |
3588 | } |
3589 | |
3590 | template <typename Derived> |
3591 | bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) { |
3592 | TRY_TO(TraverseStmt(C->getStep())); |
3593 | TRY_TO(TraverseStmt(C->getCalcStep())); |
3594 | TRY_TO(VisitOMPClauseList(C)); |
3595 | TRY_TO(VisitOMPClauseWithPostUpdate(C)); |
3596 | for (auto *E : C->privates()) { |
3597 | TRY_TO(TraverseStmt(E)); |
3598 | } |
3599 | for (auto *E : C->inits()) { |
3600 | TRY_TO(TraverseStmt(E)); |
3601 | } |
3602 | for (auto *E : C->updates()) { |
3603 | TRY_TO(TraverseStmt(E)); |
3604 | } |
3605 | for (auto *E : C->finals()) { |
3606 | TRY_TO(TraverseStmt(E)); |
3607 | } |
3608 | return true; |
3609 | } |
3610 | |
3611 | template <typename Derived> |
3612 | bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) { |
3613 | TRY_TO(TraverseStmt(C->getAlignment())); |
3614 | TRY_TO(VisitOMPClauseList(C)); |
3615 | return true; |
3616 | } |
3617 | |
3618 | template <typename Derived> |
3619 | bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) { |
3620 | TRY_TO(VisitOMPClauseList(C)); |
3621 | for (auto *E : C->source_exprs()) { |
3622 | TRY_TO(TraverseStmt(E)); |
3623 | } |
3624 | for (auto *E : C->destination_exprs()) { |
3625 | TRY_TO(TraverseStmt(E)); |
3626 | } |
3627 | for (auto *E : C->assignment_ops()) { |
3628 | TRY_TO(TraverseStmt(E)); |
3629 | } |
3630 | return true; |
3631 | } |
3632 | |
3633 | template <typename Derived> |
3634 | bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause( |
3635 | OMPCopyprivateClause *C) { |
3636 | TRY_TO(VisitOMPClauseList(C)); |
3637 | for (auto *E : C->source_exprs()) { |
3638 | TRY_TO(TraverseStmt(E)); |
3639 | } |
3640 | for (auto *E : C->destination_exprs()) { |
3641 | TRY_TO(TraverseStmt(E)); |
3642 | } |
3643 | for (auto *E : C->assignment_ops()) { |
3644 | TRY_TO(TraverseStmt(E)); |
3645 | } |
3646 | return true; |
3647 | } |
3648 | |
3649 | template <typename Derived> |
3650 | bool |
3651 | RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { |
3652 | TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); |
3653 | TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); |
3654 | TRY_TO(VisitOMPClauseList(C)); |
3655 | TRY_TO(VisitOMPClauseWithPostUpdate(C)); |
3656 | for (auto *E : C->privates()) { |
3657 | TRY_TO(TraverseStmt(E)); |
3658 | } |
3659 | for (auto *E : C->lhs_exprs()) { |
3660 | TRY_TO(TraverseStmt(E)); |
3661 | } |
3662 | for (auto *E : C->rhs_exprs()) { |
3663 | TRY_TO(TraverseStmt(E)); |
3664 | } |
3665 | for (auto *E : C->reduction_ops()) { |
3666 | TRY_TO(TraverseStmt(E)); |
3667 | } |
3668 | if (C->getModifier() == OMPC_REDUCTION_inscan) { |
3669 | for (auto *E : C->copy_ops()) { |
3670 | TRY_TO(TraverseStmt(E)); |
3671 | } |
3672 | for (auto *E : C->copy_array_temps()) { |
3673 | TRY_TO(TraverseStmt(E)); |
3674 | } |
3675 | for (auto *E : C->copy_array_elems()) { |
3676 | TRY_TO(TraverseStmt(E)); |
3677 | } |
3678 | } |
3679 | return true; |
3680 | } |
3681 | |
3682 | template <typename Derived> |
3683 | bool RecursiveASTVisitor<Derived>::VisitOMPTaskReductionClause( |
3684 | OMPTaskReductionClause *C) { |
3685 | TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); |
3686 | TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); |
3687 | TRY_TO(VisitOMPClauseList(C)); |
3688 | TRY_TO(VisitOMPClauseWithPostUpdate(C)); |
3689 | for (auto *E : C->privates()) { |
3690 | TRY_TO(TraverseStmt(E)); |
3691 | } |
3692 | for (auto *E : C->lhs_exprs()) { |
3693 | TRY_TO(TraverseStmt(E)); |
3694 | } |
3695 | for (auto *E : C->rhs_exprs()) { |
3696 | TRY_TO(TraverseStmt(E)); |
3697 | } |
3698 | for (auto *E : C->reduction_ops()) { |
3699 | TRY_TO(TraverseStmt(E)); |
3700 | } |
3701 | return true; |
3702 | } |
3703 | |
3704 | template <typename Derived> |
3705 | bool RecursiveASTVisitor<Derived>::VisitOMPInReductionClause( |
3706 | OMPInReductionClause *C) { |
3707 | TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); |
3708 | TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); |
3709 | TRY_TO(VisitOMPClauseList(C)); |
3710 | TRY_TO(VisitOMPClauseWithPostUpdate(C)); |
3711 | for (auto *E : C->privates()) { |
3712 | TRY_TO(TraverseStmt(E)); |
3713 | } |
3714 | for (auto *E : C->lhs_exprs()) { |
3715 | TRY_TO(TraverseStmt(E)); |
3716 | } |
3717 | for (auto *E : C->rhs_exprs()) { |
3718 | TRY_TO(TraverseStmt(E)); |
3719 | } |
3720 | for (auto *E : C->reduction_ops()) { |
3721 | TRY_TO(TraverseStmt(E)); |
3722 | } |
3723 | for (auto *E : C->taskgroup_descriptors()) |
3724 | TRY_TO(TraverseStmt(E)); |
3725 | return true; |
3726 | } |
3727 | |
3728 | template <typename Derived> |
3729 | bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { |
3730 | TRY_TO(VisitOMPClauseList(C)); |
3731 | return true; |
3732 | } |
3733 | |
3734 | template <typename Derived> |
3735 | bool RecursiveASTVisitor<Derived>::VisitOMPDepobjClause(OMPDepobjClause *C) { |
3736 | TRY_TO(TraverseStmt(C->getDepobj())); |
3737 | return true; |
3738 | } |
3739 | |
3740 | template <typename Derived> |
3741 | bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) { |
3742 | TRY_TO(VisitOMPClauseList(C)); |
3743 | return true; |
3744 | } |
3745 | |
3746 | template <typename Derived> |
3747 | bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) { |
3748 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3749 | TRY_TO(TraverseStmt(C->getDevice())); |
3750 | return true; |
3751 | } |
3752 | |
3753 | template <typename Derived> |
3754 | bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) { |
3755 | TRY_TO(VisitOMPClauseList(C)); |
3756 | return true; |
3757 | } |
3758 | |
3759 | template <typename Derived> |
3760 | bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause( |
3761 | OMPNumTeamsClause *C) { |
3762 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3763 | TRY_TO(TraverseStmt(C->getNumTeams())); |
3764 | return true; |
3765 | } |
3766 | |
3767 | template <typename Derived> |
3768 | bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause( |
3769 | OMPThreadLimitClause *C) { |
3770 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3771 | TRY_TO(TraverseStmt(C->getThreadLimit())); |
3772 | return true; |
3773 | } |
3774 | |
3775 | template <typename Derived> |
3776 | bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause( |
3777 | OMPPriorityClause *C) { |
3778 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3779 | TRY_TO(TraverseStmt(C->getPriority())); |
3780 | return true; |
3781 | } |
3782 | |
3783 | template <typename Derived> |
3784 | bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause( |
3785 | OMPGrainsizeClause *C) { |
3786 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3787 | TRY_TO(TraverseStmt(C->getGrainsize())); |
3788 | return true; |
3789 | } |
3790 | |
3791 | template <typename Derived> |
3792 | bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause( |
3793 | OMPNumTasksClause *C) { |
3794 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3795 | TRY_TO(TraverseStmt(C->getNumTasks())); |
3796 | return true; |
3797 | } |
3798 | |
3799 | template <typename Derived> |
3800 | bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) { |
3801 | TRY_TO(TraverseStmt(C->getHint())); |
3802 | return true; |
3803 | } |
3804 | |
3805 | template <typename Derived> |
3806 | bool RecursiveASTVisitor<Derived>::VisitOMPDistScheduleClause( |
3807 | OMPDistScheduleClause *C) { |
3808 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3809 | TRY_TO(TraverseStmt(C->getChunkSize())); |
3810 | return true; |
3811 | } |
3812 | |
3813 | template <typename Derived> |
3814 | bool |
3815 | RecursiveASTVisitor<Derived>::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) { |
3816 | return true; |
3817 | } |
3818 | |
3819 | template <typename Derived> |
3820 | bool RecursiveASTVisitor<Derived>::VisitOMPToClause(OMPToClause *C) { |
3821 | TRY_TO(VisitOMPClauseList(C)); |
3822 | return true; |
3823 | } |
3824 | |
3825 | template <typename Derived> |
3826 | bool RecursiveASTVisitor<Derived>::VisitOMPFromClause(OMPFromClause *C) { |
3827 | TRY_TO(VisitOMPClauseList(C)); |
3828 | return true; |
3829 | } |
3830 | |
3831 | template <typename Derived> |
3832 | bool RecursiveASTVisitor<Derived>::VisitOMPUseDevicePtrClause( |
3833 | OMPUseDevicePtrClause *C) { |
3834 | TRY_TO(VisitOMPClauseList(C)); |
3835 | return true; |
3836 | } |
3837 | |
3838 | template <typename Derived> |
3839 | bool RecursiveASTVisitor<Derived>::VisitOMPUseDeviceAddrClause( |
3840 | OMPUseDeviceAddrClause *C) { |
3841 | TRY_TO(VisitOMPClauseList(C)); |
3842 | return true; |
3843 | } |
3844 | |
3845 | template <typename Derived> |
3846 | bool RecursiveASTVisitor<Derived>::VisitOMPIsDevicePtrClause( |
3847 | OMPIsDevicePtrClause *C) { |
3848 | TRY_TO(VisitOMPClauseList(C)); |
3849 | return true; |
3850 | } |
3851 | |
3852 | template <typename Derived> |
3853 | bool RecursiveASTVisitor<Derived>::VisitOMPHasDeviceAddrClause( |
3854 | OMPHasDeviceAddrClause *C) { |
3855 | TRY_TO(VisitOMPClauseList(C)); |
3856 | return true; |
3857 | } |
3858 | |
3859 | template <typename Derived> |
3860 | bool RecursiveASTVisitor<Derived>::VisitOMPNontemporalClause( |
3861 | OMPNontemporalClause *C) { |
3862 | TRY_TO(VisitOMPClauseList(C)); |
3863 | for (auto *E : C->private_refs()) { |
3864 | TRY_TO(TraverseStmt(E)); |
3865 | } |
3866 | return true; |
3867 | } |
3868 | |
3869 | template <typename Derived> |
3870 | bool RecursiveASTVisitor<Derived>::VisitOMPOrderClause(OMPOrderClause *) { |
3871 | return true; |
3872 | } |
3873 | |
3874 | template <typename Derived> |
3875 | bool RecursiveASTVisitor<Derived>::VisitOMPDetachClause(OMPDetachClause *C) { |
3876 | TRY_TO(TraverseStmt(C->getEventHandler())); |
3877 | return true; |
3878 | } |
3879 | |
3880 | template <typename Derived> |
3881 | bool RecursiveASTVisitor<Derived>::VisitOMPUsesAllocatorsClause( |
3882 | OMPUsesAllocatorsClause *C) { |
3883 | for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { |
3884 | const OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I); |
3885 | TRY_TO(TraverseStmt(Data.Allocator)); |
3886 | TRY_TO(TraverseStmt(Data.AllocatorTraits)); |
3887 | } |
3888 | return true; |
3889 | } |
3890 | |
3891 | template <typename Derived> |
3892 | bool RecursiveASTVisitor<Derived>::VisitOMPAffinityClause( |
3893 | OMPAffinityClause *C) { |
3894 | TRY_TO(TraverseStmt(C->getModifier())); |
3895 | for (Expr *E : C->varlists()) |
3896 | TRY_TO(TraverseStmt(E)); |
3897 | return true; |
3898 | } |
3899 | |
3900 | template <typename Derived> |
3901 | bool RecursiveASTVisitor<Derived>::VisitOMPFilterClause(OMPFilterClause *C) { |
3902 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3903 | TRY_TO(TraverseStmt(C->getThreadID())); |
3904 | return true; |
3905 | } |
3906 | |
3907 | template <typename Derived> |
3908 | bool RecursiveASTVisitor<Derived>::VisitOMPBindClause(OMPBindClause *C) { |
3909 | return true; |
3910 | } |
3911 | |
3912 | template <typename Derived> |
3913 | bool RecursiveASTVisitor<Derived>::VisitOMPXDynCGroupMemClause( |
3914 | OMPXDynCGroupMemClause *C) { |
3915 | TRY_TO(VisitOMPClauseWithPreInit(C)); |
3916 | TRY_TO(TraverseStmt(C->getSize())); |
3917 | return true; |
3918 | } |
3919 | |
3920 | template <typename Derived> |
3921 | bool RecursiveASTVisitor<Derived>::VisitOMPDoacrossClause( |
3922 | OMPDoacrossClause *C) { |
3923 | TRY_TO(VisitOMPClauseList(C)); |
3924 | return true; |
3925 | } |
3926 | |
3927 | template <typename Derived> |
3928 | bool RecursiveASTVisitor<Derived>::VisitOMPXAttributeClause( |
3929 | OMPXAttributeClause *C) { |
3930 | return true; |
3931 | } |
3932 | |
3933 | template <typename Derived> |
3934 | bool RecursiveASTVisitor<Derived>::VisitOMPXBareClause(OMPXBareClause *C) { |
3935 | return true; |
3936 | } |
3937 | |
3938 | template <typename Derived> |
3939 | bool RecursiveASTVisitor<Derived>::TraverseOpenACCConstructStmt( |
3940 | OpenACCConstructStmt *C) { |
3941 | TRY_TO(VisitOpenACCClauseList(C->clauses())); |
3942 | return true; |
3943 | } |
3944 | |
3945 | template <typename Derived> |
3946 | bool RecursiveASTVisitor<Derived>::TraverseOpenACCAssociatedStmtConstruct( |
3947 | OpenACCAssociatedStmtConstruct *S) { |
3948 | TRY_TO(TraverseOpenACCConstructStmt(S)); |
3949 | TRY_TO(TraverseStmt(S->getAssociatedStmt())); |
3950 | return true; |
3951 | } |
3952 | |
3953 | template <typename Derived> |
3954 | bool RecursiveASTVisitor<Derived>::VisitOpenACCClauseList( |
3955 | ArrayRef<const OpenACCClause *>) { |
3956 | // TODO OpenACC: When we have Clauses with expressions, we should visit them |
3957 | // here. |
3958 | return true; |
3959 | } |
3960 | |
3961 | DEF_TRAVERSE_STMT(OpenACCComputeConstruct, |
3962 | { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) |
3963 | |
3964 | // FIXME: look at the following tricky-seeming exprs to see if we |
3965 | // need to recurse on anything. These are ones that have methods |
3966 | // returning decls or qualtypes or nestednamespecifier -- though I'm |
3967 | // not sure if they own them -- or just seemed very complicated, or |
3968 | // had lots of sub-types to explore. |
3969 | // |
3970 | // VisitOverloadExpr and its children: recurse on template args? etc? |
3971 | |
3972 | // FIXME: go through all the stmts and exprs again, and see which of them |
3973 | // create new types, and recurse on the types (TypeLocs?) of those. |
3974 | // Candidates: |
3975 | // |
3976 | // http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html |
3977 | // http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html |
3978 | // http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html |
3979 | // Every class that has getQualifier. |
3980 | |
3981 | #undef DEF_TRAVERSE_STMT |
3982 | #undef TRAVERSE_STMT |
3983 | #undef TRAVERSE_STMT_BASE |
3984 | |
3985 | #undef TRY_TO |
3986 | |
3987 | } // end namespace clang |
3988 | |
3989 | #endif // LLVM_CLANG_AST_RECURSIVEASTVISITOR_H |
3990 | |