Bug Summary

File:build/source/clang/include/clang/AST/RecursiveASTVisitor.h
Warning:line 327, column 55
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name FunctionCognitiveComplexityCheck.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D CLANG_REPOSITORY_STRING="++20230510111145+7df43bdb42ae-1~exp1~20230510111303.1288" -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/tools/extra/clang-tidy/readability -I /build/source/clang-tools-extra/clang-tidy/readability -I tools/clang/tools/extra/clang-tidy -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp

/build/source/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp

1//===--- FunctionCognitiveComplexityCheck.cpp - clang-tidy ------*- 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#include "FunctionCognitiveComplexityCheck.h"
10#include "../ClangTidyDiagnosticConsumer.h"
11#include "clang/AST/Decl.h"
12#include "clang/AST/DeclBase.h"
13#include "clang/AST/Expr.h"
14#include "clang/AST/RecursiveASTVisitor.h"
15#include "clang/AST/Stmt.h"
16#include "clang/ASTMatchers/ASTMatchFinder.h"
17#include "clang/ASTMatchers/ASTMatchers.h"
18#include "clang/ASTMatchers/ASTMatchersInternal.h"
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Basic/DiagnosticIDs.h"
21#include "clang/Basic/LLVM.h"
22#include "clang/Basic/SourceLocation.h"
23#include "llvm/ADT/SmallVector.h"
24#include "llvm/Support/Casting.h"
25#include "llvm/Support/ErrorHandling.h"
26#include <array>
27#include <cassert>
28#include <optional>
29#include <stack>
30#include <tuple>
31#include <type_traits>
32#include <utility>
33
34using namespace clang::ast_matchers;
35
36namespace clang::tidy::readability {
37namespace {
38
39struct CognitiveComplexity final {
40 // Any increment is based on some combination of reasons.
41 // For details you can look at the Specification at
42 // https://www.sonarsource.com/docs/CognitiveComplexity.pdf
43 // or user-facing docs at
44 // http://clang.llvm.org/extra/clang-tidy/checks/readability/function-cognitive-complexity.html
45 // Here are all the possible reasons:
46 enum Criteria : uint8_t {
47 None = 0U,
48
49 // B1, increases cognitive complexity (by 1)
50 // What causes it:
51 // * if, else if, else, ConditionalOperator (not BinaryConditionalOperator)
52 // * SwitchStmt
53 // * ForStmt, CXXForRangeStmt
54 // * WhileStmt, DoStmt
55 // * CXXCatchStmt
56 // * GotoStmt, IndirectGotoStmt (but not BreakStmt, ContinueStmt)
57 // * sequences of binary logical operators (BinOpLAnd, BinOpLOr)
58 // * each method in a recursion cycle (not implemented)
59 Increment = 1U << 0,
60
61 // B2, increases current nesting level (by 1)
62 // What causes it:
63 // * if, else if, else, ConditionalOperator (not BinaryConditionalOperator)
64 // * SwitchStmt
65 // * ForStmt, CXXForRangeStmt
66 // * WhileStmt, DoStmt
67 // * CXXCatchStmt
68 // * nested CXXConstructor, CXXDestructor, CXXMethod (incl. C++11 Lambda)
69 // * GNU Statement Expression
70 // * Apple Block declaration
71 IncrementNesting = 1U << 1,
72
73 // B3, increases cognitive complexity by the current nesting level
74 // Applied before IncrementNesting
75 // What causes it:
76 // * IfStmt, ConditionalOperator (not BinaryConditionalOperator)
77 // * SwitchStmt
78 // * ForStmt, CXXForRangeStmt
79 // * WhileStmt, DoStmt
80 // * CXXCatchStmt
81 PenalizeNesting = 1U << 2,
82
83 All = Increment | PenalizeNesting | IncrementNesting,
84 };
85
86 // The helper struct used to record one increment occurrence, with all the
87 // details necessary.
88 struct Detail {
89 const SourceLocation Loc; // What caused the increment?
90 const unsigned short Nesting; // How deeply nested is Loc located?
91 const Criteria C; // The criteria of the increment
92
93 Detail(SourceLocation SLoc, unsigned short CurrentNesting, Criteria Crit)
94 : Loc(SLoc), Nesting(CurrentNesting), C(Crit) {}
95
96 // To minimize the sizeof(Detail), we only store the minimal info there.
97 // This function is used to convert from the stored info into the usable
98 // information - what message to output, how much of an increment did this
99 // occurrence actually result in.
100 std::pair<unsigned, unsigned short> process() const {
101 assert(C != Criteria::None && "invalid criteria")(static_cast <bool> (C != Criteria::None && "invalid criteria"
) ? void (0) : __assert_fail ("C != Criteria::None && \"invalid criteria\""
, "clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp"
, 101, __extension__ __PRETTY_FUNCTION__))
;
102
103 unsigned MsgId; // The id of the message to output.
104 unsigned short Increment; // How much of an increment?
105
106 if (C == Criteria::All) {
107 Increment = 1 + Nesting;
108 MsgId = 0;
109 } else if (C == (Criteria::Increment | Criteria::IncrementNesting)) {
110 Increment = 1;
111 MsgId = 1;
112 } else if (C == Criteria::Increment) {
113 Increment = 1;
114 MsgId = 2;
115 } else if (C == Criteria::IncrementNesting) {
116 Increment = 0; // Unused in this message.
117 MsgId = 3;
118 } else
119 llvm_unreachable("should not get to here.")::llvm::llvm_unreachable_internal("should not get to here.", "clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp"
, 119)
;
120
121 return std::make_pair(MsgId, Increment);
122 }
123 };
124
125 // Limit of 25 is the "upstream"'s default.
126 static constexpr unsigned DefaultLimit = 25U;
127
128 // Based on the publicly-avaliable numbers for some big open-source projects
129 // https://sonarcloud.io/projects?languages=c%2Ccpp&size=5 we can estimate:
130 // value ~20 would result in no allocs for 98% of functions, ~12 for 96%, ~10
131 // for 91%, ~8 for 88%, ~6 for 84%, ~4 for 77%, ~2 for 64%, and ~1 for 37%.
132 static_assert(sizeof(Detail) <= 8,
133 "Since we use SmallVector to minimize the amount of "
134 "allocations, we also need to consider the price we pay for "
135 "that in terms of stack usage. "
136 "Thus, it is good to minimize the size of the Detail struct.");
137 SmallVector<Detail, DefaultLimit> Details; // 25 elements is 200 bytes.
138 // Yes, 25 is a magic number. This is the seemingly-sane default for the
139 // upper limit for function cognitive complexity. Thus it would make sense
140 // to avoid allocations for any function that does not violate the limit.
141
142 // The grand total Cognitive Complexity of the function.
143 unsigned Total = 0;
144
145 // The function used to store new increment, calculate the total complexity.
146 void account(SourceLocation Loc, unsigned short Nesting, Criteria C);
147};
148
149// All the possible messages that can be output. The choice of the message
150// to use is based of the combination of the CognitiveComplexity::Criteria.
151// It would be nice to have it in CognitiveComplexity struct, but then it is
152// not static.
153static const std::array<const StringRef, 4> Msgs = {{
154 // B1 + B2 + B3
155 "+%0, including nesting penalty of %1, nesting level increased to %2",
156
157 // B1 + B2
158 "+%0, nesting level increased to %2",
159
160 // B1
161 "+%0",
162
163 // B2
164 "nesting level increased to %2",
165}};
166
167// Criteria is a bitset, thus a few helpers are needed.
168CognitiveComplexity::Criteria operator|(CognitiveComplexity::Criteria LHS,
169 CognitiveComplexity::Criteria RHS) {
170 return static_cast<CognitiveComplexity::Criteria>(
171 static_cast<std::underlying_type_t<CognitiveComplexity::Criteria>>(LHS) |
172 static_cast<std::underlying_type_t<CognitiveComplexity::Criteria>>(RHS));
173}
174CognitiveComplexity::Criteria operator&(CognitiveComplexity::Criteria LHS,
175 CognitiveComplexity::Criteria RHS) {
176 return static_cast<CognitiveComplexity::Criteria>(
177 static_cast<std::underlying_type_t<CognitiveComplexity::Criteria>>(LHS) &
178 static_cast<std::underlying_type_t<CognitiveComplexity::Criteria>>(RHS));
179}
180CognitiveComplexity::Criteria &operator|=(CognitiveComplexity::Criteria &LHS,
181 CognitiveComplexity::Criteria RHS) {
182 LHS = operator|(LHS, RHS);
183 return LHS;
184}
185CognitiveComplexity::Criteria &operator&=(CognitiveComplexity::Criteria &LHS,
186 CognitiveComplexity::Criteria RHS) {
187 LHS = operator&(LHS, RHS);
188 return LHS;
189}
190
191void CognitiveComplexity::account(SourceLocation Loc, unsigned short Nesting,
192 Criteria C) {
193 C &= Criteria::All;
194 assert(C != Criteria::None && "invalid criteria")(static_cast <bool> (C != Criteria::None && "invalid criteria"
) ? void (0) : __assert_fail ("C != Criteria::None && \"invalid criteria\""
, "clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp"
, 194, __extension__ __PRETTY_FUNCTION__))
;
195
196 Details.emplace_back(Loc, Nesting, C);
197 const Detail &D = Details.back();
198
199 unsigned MsgId;
200 unsigned short Increase;
201 std::tie(MsgId, Increase) = D.process();
202
203 Total += Increase;
204}
205
206class FunctionASTVisitor final
207 : public RecursiveASTVisitor<FunctionASTVisitor> {
208 using Base = RecursiveASTVisitor<FunctionASTVisitor>;
209
210 // If set to true, macros are ignored during analysis.
211 const bool IgnoreMacros;
212
213 // The current nesting level (increased by Criteria::IncrementNesting).
214 unsigned short CurrentNestingLevel = 0;
215
216 // Used to efficiently know the last type of the binary sequence operator
217 // that was encountered. It would make sense for the function call to start
218 // the new sequence, thus it is a stack.
219 using OBO = std::optional<BinaryOperator::Opcode>;
220 std::stack<OBO, SmallVector<OBO, 4>> BinaryOperatorsStack;
221
222public:
223 explicit FunctionASTVisitor(const bool IgnoreMacros)
224 : IgnoreMacros(IgnoreMacros) {}
225
226 bool traverseStmtWithIncreasedNestingLevel(Stmt *Node) {
227 ++CurrentNestingLevel;
228 bool ShouldContinue = Base::TraverseStmt(Node);
229 --CurrentNestingLevel;
230 return ShouldContinue;
231 }
232
233 bool traverseDeclWithIncreasedNestingLevel(Decl *Node) {
234 ++CurrentNestingLevel;
235 bool ShouldContinue = Base::TraverseDecl(Node);
236 --CurrentNestingLevel;
237 return ShouldContinue;
238 }
239
240 bool TraverseIfStmt(IfStmt *Node, bool InElseIf = false) {
241 if (!Node)
242 return Base::TraverseIfStmt(Node);
243
244 {
245 CognitiveComplexity::Criteria Reasons;
246
247 Reasons = CognitiveComplexity::Criteria::None;
248
249 // "If" increases cognitive complexity.
250 Reasons |= CognitiveComplexity::Criteria::Increment;
251 // "If" increases nesting level.
252 Reasons |= CognitiveComplexity::Criteria::IncrementNesting;
253
254 if (!InElseIf) {
255 // "If" receives a nesting increment commensurate with it's nested
256 // depth, if it is not part of "else if".
257 Reasons |= CognitiveComplexity::Criteria::PenalizeNesting;
258 }
259
260 CC.account(Node->getIfLoc(), CurrentNestingLevel, Reasons);
261 }
262
263 // If this IfStmt is *NOT* "else if", then only the body (i.e. "Then" and
264 // "Else") is traversed with increased Nesting level.
265 // However if this IfStmt *IS* "else if", then Nesting level is increased
266 // for the whole IfStmt (i.e. for "Init", "Cond", "Then" and "Else").
267
268 if (!InElseIf) {
269 if (!TraverseStmt(Node->getInit()))
270 return false;
271
272 if (!TraverseStmt(Node->getCond()))
273 return false;
274 } else {
275 if (!traverseStmtWithIncreasedNestingLevel(Node->getInit()))
276 return false;
277
278 if (!traverseStmtWithIncreasedNestingLevel(Node->getCond()))
279 return false;
280 }
281
282 // "Then" always increases nesting level.
283 if (!traverseStmtWithIncreasedNestingLevel(Node->getThen()))
284 return false;
285
286 if (!Node->getElse())
287 return true;
288
289 if (auto *E = dyn_cast<IfStmt>(Node->getElse()))
290 return TraverseIfStmt(E, true);
291
292 {
293 CognitiveComplexity::Criteria Reasons;
294
295 Reasons = CognitiveComplexity::Criteria::None;
296
297 // "Else" increases cognitive complexity.
298 Reasons |= CognitiveComplexity::Criteria::Increment;
299 // "Else" increases nesting level.
300 Reasons |= CognitiveComplexity::Criteria::IncrementNesting;
301 // "Else" DOES NOT receive a nesting increment commensurate with it's
302 // nested depth.
303
304 CC.account(Node->getElseLoc(), CurrentNestingLevel, Reasons);
305 }
306
307 // "Else" always increases nesting level.
308 return traverseStmtWithIncreasedNestingLevel(Node->getElse());
309 }
310
311// The currently-being-processed stack entry, which is always the top.
312#define CurrentBinaryOperator BinaryOperatorsStack.top()
313
314 // In a sequence of binary logical operators, if the new operator is different
315 // from the previous one, then the cognitive complexity is increased.
316 bool TraverseBinaryOperator(BinaryOperator *Op) {
317 if (!Op || !Op->isLogicalOp())
318 return Base::TraverseBinaryOperator(Op);
319
320 // Make sure that there is always at least one frame in the stack.
321 if (BinaryOperatorsStack.empty())
322 BinaryOperatorsStack.emplace();
323
324 // If this is the first binary operator that we are processing, or the
325 // previous binary operator was different, there is an increment.
326 if (!CurrentBinaryOperator || Op->getOpcode() != CurrentBinaryOperator)
327 CC.account(Op->getOperatorLoc(), CurrentNestingLevel,
328 CognitiveComplexity::Criteria::Increment);
329
330 // We might encounter a function call, which starts a new sequence, thus
331 // we need to save the current previous binary operator.
332 const std::optional<BinaryOperator::Opcode> BinOpCopy(
333 CurrentBinaryOperator);
334
335 // Record the operator that we are currently processing and traverse it.
336 CurrentBinaryOperator = Op->getOpcode();
337 bool ShouldContinue = Base::TraverseBinaryOperator(Op);
338
339 // And restore the previous binary operator, which might be nonexistent.
340 CurrentBinaryOperator = BinOpCopy;
341
342 return ShouldContinue;
343 }
344
345 // It would make sense for the function call to start the new binary
346 // operator sequence, thus let's make sure that it creates a new stack frame.
347 bool TraverseCallExpr(CallExpr *Node) {
348 // If we are not currently processing any binary operator sequence, then
349 // no Node-handling is needed.
350 if (!Node || BinaryOperatorsStack.empty() || !CurrentBinaryOperator)
1
Assuming 'Node' is null
351 return Base::TraverseCallExpr(Node);
2
Passing null pointer value via 1st parameter 'S'
3
Calling 'RecursiveASTVisitor::TraverseCallExpr'
352
353 // Else, do add [uninitialized] frame to the stack, and traverse call.
354 BinaryOperatorsStack.emplace();
355 bool ShouldContinue = Base::TraverseCallExpr(Node);
356 // And remove the top frame.
357 BinaryOperatorsStack.pop();
358
359 return ShouldContinue;
360 }
361
362#undef CurrentBinaryOperator
363
364 bool TraverseStmt(Stmt *Node) {
365 if (!Node)
366 return Base::TraverseStmt(Node);
367
368 if (IgnoreMacros && Node->getBeginLoc().isMacroID())
369 return true;
370
371 // Three following switch()'es have huge duplication, but it is better to
372 // keep them separate, to simplify comparing them with the Specification.
373
374 CognitiveComplexity::Criteria Reasons = CognitiveComplexity::Criteria::None;
375 SourceLocation Location = Node->getBeginLoc();
376
377 // B1. Increments
378 // There is an increment for each of the following:
379 switch (Node->getStmtClass()) {
380 // if, else if, else are handled in TraverseIfStmt(),
381 // FIXME: "each method in a recursion cycle" Increment is not implemented.
382 case Stmt::ConditionalOperatorClass:
383 case Stmt::SwitchStmtClass:
384 case Stmt::ForStmtClass:
385 case Stmt::CXXForRangeStmtClass:
386 case Stmt::WhileStmtClass:
387 case Stmt::DoStmtClass:
388 case Stmt::CXXCatchStmtClass:
389 case Stmt::GotoStmtClass:
390 case Stmt::IndirectGotoStmtClass:
391 Reasons |= CognitiveComplexity::Criteria::Increment;
392 break;
393 default:
394 // break LABEL, continue LABEL increase cognitive complexity,
395 // but they are not supported in C++ or C.
396 // Regular break/continue do not increase cognitive complexity.
397 break;
398 }
399
400 // B2. Nesting level
401 // The following structures increment the nesting level:
402 switch (Node->getStmtClass()) {
403 // if, else if, else are handled in TraverseIfStmt(),
404 // Nested methods and such are handled in TraverseDecl.
405 case Stmt::ConditionalOperatorClass:
406 case Stmt::SwitchStmtClass:
407 case Stmt::ForStmtClass:
408 case Stmt::CXXForRangeStmtClass:
409 case Stmt::WhileStmtClass:
410 case Stmt::DoStmtClass:
411 case Stmt::CXXCatchStmtClass:
412 case Stmt::LambdaExprClass:
413 case Stmt::StmtExprClass:
414 Reasons |= CognitiveComplexity::Criteria::IncrementNesting;
415 break;
416 default:
417 break;
418 }
419
420 // B3. Nesting increments
421 // The following structures receive a nesting increment
422 // commensurate with their nested depth inside B2 structures:
423 switch (Node->getStmtClass()) {
424 // if, else if, else are handled in TraverseIfStmt().
425 case Stmt::ConditionalOperatorClass:
426 case Stmt::SwitchStmtClass:
427 case Stmt::ForStmtClass:
428 case Stmt::CXXForRangeStmtClass:
429 case Stmt::WhileStmtClass:
430 case Stmt::DoStmtClass:
431 case Stmt::CXXCatchStmtClass:
432 Reasons |= CognitiveComplexity::Criteria::PenalizeNesting;
433 break;
434 default:
435 break;
436 }
437
438 if (Node->getStmtClass() == Stmt::ConditionalOperatorClass) {
439 // A little beautification.
440 // For conditional operator "cond ? true : false" point at the "?"
441 // symbol.
442 Location = cast<ConditionalOperator>(Node)->getQuestionLoc();
443 }
444
445 // If we have found any reasons, let's account it.
446 if (Reasons & CognitiveComplexity::Criteria::All)
447 CC.account(Location, CurrentNestingLevel, Reasons);
448
449 // Did we decide that the nesting level should be increased?
450 if (!(Reasons & CognitiveComplexity::Criteria::IncrementNesting))
451 return Base::TraverseStmt(Node);
452
453 return traverseStmtWithIncreasedNestingLevel(Node);
454 }
455
456 // The parameter MainAnalyzedFunction is needed to differentiate between the
457 // cases where TraverseDecl() is the entry point from
458 // FunctionCognitiveComplexityCheck::check() and the cases where it was called
459 // from the FunctionASTVisitor itself. Explanation: if we get a function
460 // definition (e.g. constructor, destructor, method), the Cognitive Complexity
461 // specification states that the Nesting level shall be increased. But if this
462 // function is the entry point, then the Nesting level should not be
463 // increased. Thus that parameter is there and is used to fall-through
464 // directly to traversing if this is the main function that is being analyzed.
465 bool TraverseDecl(Decl *Node, bool MainAnalyzedFunction = false) {
466 if (!Node || MainAnalyzedFunction)
467 return Base::TraverseDecl(Node);
468
469 // B2. Nesting level
470 // The following structures increment the nesting level:
471 switch (Node->getKind()) {
472 case Decl::Function:
473 case Decl::CXXMethod:
474 case Decl::CXXConstructor:
475 case Decl::CXXDestructor:
476 case Decl::Block:
477 break;
478 default:
479 // If this is something else, we use early return!
480 return Base::TraverseDecl(Node);
481 break;
482 }
483
484 CC.account(Node->getBeginLoc(), CurrentNestingLevel,
485 CognitiveComplexity::Criteria::IncrementNesting);
486
487 return traverseDeclWithIncreasedNestingLevel(Node);
488 }
489
490 CognitiveComplexity CC;
491};
492
493} // namespace
494
495FunctionCognitiveComplexityCheck::FunctionCognitiveComplexityCheck(
496 StringRef Name, ClangTidyContext *Context)
497 : ClangTidyCheck(Name, Context),
498 Threshold(Options.get("Threshold", CognitiveComplexity::DefaultLimit)),
499 DescribeBasicIncrements(Options.get("DescribeBasicIncrements", true)),
500 IgnoreMacros(Options.get("IgnoreMacros", false)) {}
501
502void FunctionCognitiveComplexityCheck::storeOptions(
503 ClangTidyOptions::OptionMap &Opts) {
504 Options.store(Opts, "Threshold", Threshold);
505 Options.store(Opts, "DescribeBasicIncrements", DescribeBasicIncrements);
506 Options.store(Opts, "IgnoreMacros", IgnoreMacros);
507}
508
509void FunctionCognitiveComplexityCheck::registerMatchers(MatchFinder *Finder) {
510 Finder->addMatcher(
511 functionDecl(isDefinition(),
512 unless(anyOf(isDefaulted(), isDeleted(), isWeak())))
513 .bind("func"),
514 this);
515 Finder->addMatcher(lambdaExpr().bind("lambda"), this);
516}
517
518void FunctionCognitiveComplexityCheck::check(
519 const MatchFinder::MatchResult &Result) {
520
521 FunctionASTVisitor Visitor(IgnoreMacros);
522 SourceLocation Loc;
523
524 const auto *TheDecl = Result.Nodes.getNodeAs<FunctionDecl>("func");
525 const auto *TheLambdaExpr = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
526 if (TheDecl) {
527 assert(TheDecl->hasBody() &&(static_cast <bool> (TheDecl->hasBody() && "The matchers should only match the functions that "
"have user-provided body.") ? void (0) : __assert_fail ("TheDecl->hasBody() && \"The matchers should only match the functions that \" \"have user-provided body.\""
, "clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp"
, 529, __extension__ __PRETTY_FUNCTION__))
528 "The matchers should only match the functions that "(static_cast <bool> (TheDecl->hasBody() && "The matchers should only match the functions that "
"have user-provided body.") ? void (0) : __assert_fail ("TheDecl->hasBody() && \"The matchers should only match the functions that \" \"have user-provided body.\""
, "clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp"
, 529, __extension__ __PRETTY_FUNCTION__))
529 "have user-provided body.")(static_cast <bool> (TheDecl->hasBody() && "The matchers should only match the functions that "
"have user-provided body.") ? void (0) : __assert_fail ("TheDecl->hasBody() && \"The matchers should only match the functions that \" \"have user-provided body.\""
, "clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp"
, 529, __extension__ __PRETTY_FUNCTION__))
;
530 Loc = TheDecl->getLocation();
531 Visitor.TraverseDecl(const_cast<FunctionDecl *>(TheDecl), true);
532 } else {
533 Loc = TheLambdaExpr->getBeginLoc();
534 Visitor.TraverseLambdaExpr(const_cast<LambdaExpr *>(TheLambdaExpr));
535 }
536
537 if (Visitor.CC.Total <= Threshold)
538 return;
539
540 if (TheDecl)
541 diag(Loc, "function %0 has cognitive complexity of %1 (threshold %2)")
542 << TheDecl << Visitor.CC.Total << Threshold;
543 else
544 diag(Loc, "lambda has cognitive complexity of %0 (threshold %1)")
545 << Visitor.CC.Total << Threshold;
546
547 if (!DescribeBasicIncrements)
548 return;
549
550 // Output all the basic increments of complexity.
551 for (const auto &Detail : Visitor.CC.Details) {
552 unsigned MsgId; // The id of the message to output.
553 unsigned short Increase; // How much of an increment?
554 std::tie(MsgId, Increase) = Detail.process();
555 assert(MsgId < Msgs.size() && "MsgId should always be valid")(static_cast <bool> (MsgId < Msgs.size() && "MsgId should always be valid"
) ? void (0) : __assert_fail ("MsgId < Msgs.size() && \"MsgId should always be valid\""
, "clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp"
, 555, __extension__ __PRETTY_FUNCTION__))
;
556 // Increase, on the other hand, can be 0.
557
558 diag(Detail.Loc, Msgs[MsgId], DiagnosticIDs::Note)
559 << (unsigned)Increase << (unsigned)Detail.Nesting << 1 + Detail.Nesting;
560 }
561}
562
563} // namespace clang::tidy::readability

/build/source/clang/include/clang/AST/RecursiveASTVisitor.h

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