Bug Summary

File:build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/include/clang/AST/RecursiveASTVisitor.h
Warning:line 328, 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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/tools/extra/clang-tidy/readability -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang-tools-extra/clang-tidy/readability -I tools/clang/tools/extra/clang-tidy -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/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-16/lib/clang/16.0.0/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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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-2022-09-04-125545-48738-1 -x c++ /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp

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

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