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