1 | //===--- TextNodeDumper.cpp - Printing of AST nodes -----------------------===// |
---|---|
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 implements AST dumping of components of individual AST nodes. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "clang/AST/TextNodeDumper.h" |
14 | #include "clang/AST/APValue.h" |
15 | #include "clang/AST/DeclFriend.h" |
16 | #include "clang/AST/DeclOpenMP.h" |
17 | #include "clang/AST/DeclTemplate.h" |
18 | #include "clang/AST/LocInfoType.h" |
19 | #include "clang/AST/NestedNameSpecifier.h" |
20 | #include "clang/AST/Type.h" |
21 | #include "clang/AST/TypeLocVisitor.h" |
22 | #include "clang/Basic/Module.h" |
23 | #include "clang/Basic/SourceManager.h" |
24 | #include "clang/Basic/Specifiers.h" |
25 | #include "clang/Basic/TypeTraits.h" |
26 | #include "llvm/ADT/StringExtras.h" |
27 | #include "llvm/Frontend/HLSL/HLSLRootSignatureUtils.h" |
28 | |
29 | #include <algorithm> |
30 | #include <utility> |
31 | |
32 | using namespace clang; |
33 | |
34 | static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {} |
35 | |
36 | template <typename T> |
37 | static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) { |
38 | const T *First = D->getFirstDecl(); |
39 | if (First != D) |
40 | OS << " first "<< First; |
41 | } |
42 | |
43 | template <typename T> |
44 | static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) { |
45 | const T *Prev = D->getPreviousDecl(); |
46 | if (Prev) |
47 | OS << " prev "<< Prev; |
48 | } |
49 | |
50 | /// Dump the previous declaration in the redeclaration chain for a declaration, |
51 | /// if any. |
52 | static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) { |
53 | switch (D->getKind()) { |
54 | #define DECL(DERIVED, BASE) \ |
55 | case Decl::DERIVED: \ |
56 | return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D)); |
57 | #define ABSTRACT_DECL(DECL) |
58 | #include "clang/AST/DeclNodes.inc" |
59 | } |
60 | llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); |
61 | } |
62 | |
63 | TextNodeDumper::TextNodeDumper(raw_ostream &OS, const ASTContext &Context, |
64 | bool ShowColors) |
65 | : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors), |
66 | Context(&Context), SM(&Context.getSourceManager()), |
67 | PrintPolicy(Context.getPrintingPolicy()), |
68 | Traits(&Context.getCommentCommandTraits()) {} |
69 | |
70 | TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors) |
71 | : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors) {} |
72 | |
73 | void TextNodeDumper::Visit(const comments::Comment *C, |
74 | const comments::FullComment *FC) { |
75 | if (!C) { |
76 | ColorScope Color(OS, ShowColors, NullColor); |
77 | OS << "<<<NULL>>>"; |
78 | return; |
79 | } |
80 | |
81 | { |
82 | ColorScope Color(OS, ShowColors, CommentColor); |
83 | OS << C->getCommentKindName(); |
84 | } |
85 | dumpPointer(Ptr: C); |
86 | dumpSourceRange(R: C->getSourceRange()); |
87 | |
88 | ConstCommentVisitor<TextNodeDumper, void, |
89 | const comments::FullComment *>::visit(C, FC); |
90 | } |
91 | |
92 | void TextNodeDumper::Visit(const Attr *A) { |
93 | { |
94 | ColorScope Color(OS, ShowColors, AttrColor); |
95 | |
96 | switch (A->getKind()) { |
97 | #define ATTR(X) \ |
98 | case attr::X: \ |
99 | OS << #X; \ |
100 | break; |
101 | #include "clang/Basic/AttrList.inc" |
102 | } |
103 | OS << "Attr"; |
104 | } |
105 | dumpPointer(Ptr: A); |
106 | dumpSourceRange(R: A->getRange()); |
107 | if (A->isInherited()) |
108 | OS << " Inherited"; |
109 | if (A->isImplicit()) |
110 | OS << " Implicit"; |
111 | |
112 | ConstAttrVisitor<TextNodeDumper>::Visit(A); |
113 | } |
114 | |
115 | void TextNodeDumper::Visit(const TemplateArgument &TA, SourceRange R, |
116 | const Decl *From, StringRef Label) { |
117 | OS << "TemplateArgument"; |
118 | if (R.isValid()) |
119 | dumpSourceRange(R); |
120 | |
121 | if (From) |
122 | dumpDeclRef(D: From, Label); |
123 | |
124 | ConstTemplateArgumentVisitor<TextNodeDumper>::Visit(TA); |
125 | } |
126 | |
127 | void TextNodeDumper::Visit(const Stmt *Node) { |
128 | if (!Node) { |
129 | ColorScope Color(OS, ShowColors, NullColor); |
130 | OS << "<<<NULL>>>"; |
131 | return; |
132 | } |
133 | { |
134 | ColorScope Color(OS, ShowColors, StmtColor); |
135 | OS << Node->getStmtClassName(); |
136 | } |
137 | dumpPointer(Ptr: Node); |
138 | dumpSourceRange(R: Node->getSourceRange()); |
139 | |
140 | if (const auto *E = dyn_cast<Expr>(Val: Node)) { |
141 | dumpType(T: E->getType()); |
142 | |
143 | if (E->containsErrors()) { |
144 | ColorScope Color(OS, ShowColors, ErrorsColor); |
145 | OS << " contains-errors"; |
146 | } |
147 | |
148 | { |
149 | ColorScope Color(OS, ShowColors, ValueKindColor); |
150 | switch (E->getValueKind()) { |
151 | case VK_PRValue: |
152 | break; |
153 | case VK_LValue: |
154 | OS << " lvalue"; |
155 | break; |
156 | case VK_XValue: |
157 | OS << " xvalue"; |
158 | break; |
159 | } |
160 | } |
161 | |
162 | { |
163 | ColorScope Color(OS, ShowColors, ObjectKindColor); |
164 | switch (E->getObjectKind()) { |
165 | case OK_Ordinary: |
166 | break; |
167 | case OK_BitField: |
168 | OS << " bitfield"; |
169 | break; |
170 | case OK_ObjCProperty: |
171 | OS << " objcproperty"; |
172 | break; |
173 | case OK_ObjCSubscript: |
174 | OS << " objcsubscript"; |
175 | break; |
176 | case OK_VectorComponent: |
177 | OS << " vectorcomponent"; |
178 | break; |
179 | case OK_MatrixComponent: |
180 | OS << " matrixcomponent"; |
181 | break; |
182 | } |
183 | } |
184 | } |
185 | |
186 | ConstStmtVisitor<TextNodeDumper>::Visit(Node); |
187 | } |
188 | |
189 | void TextNodeDumper::Visit(const Type *T) { |
190 | if (!T) { |
191 | ColorScope Color(OS, ShowColors, NullColor); |
192 | OS << "<<<NULL>>>"; |
193 | return; |
194 | } |
195 | if (isa<LocInfoType>(Val: T)) { |
196 | { |
197 | ColorScope Color(OS, ShowColors, TypeColor); |
198 | OS << "LocInfo Type"; |
199 | } |
200 | dumpPointer(Ptr: T); |
201 | return; |
202 | } |
203 | |
204 | { |
205 | ColorScope Color(OS, ShowColors, TypeColor); |
206 | OS << T->getTypeClassName() << "Type"; |
207 | } |
208 | dumpPointer(Ptr: T); |
209 | OS << " "; |
210 | dumpBareType(T: QualType(T, 0), Desugar: false); |
211 | |
212 | QualType SingleStepDesugar = |
213 | T->getLocallyUnqualifiedSingleStepDesugaredType(); |
214 | if (SingleStepDesugar != QualType(T, 0)) |
215 | OS << " sugar"; |
216 | |
217 | if (T->containsErrors()) { |
218 | ColorScope Color(OS, ShowColors, ErrorsColor); |
219 | OS << " contains-errors"; |
220 | } |
221 | |
222 | if (T->isDependentType()) |
223 | OS << " dependent"; |
224 | else if (T->isInstantiationDependentType()) |
225 | OS << " instantiation_dependent"; |
226 | |
227 | if (T->isVariablyModifiedType()) |
228 | OS << " variably_modified"; |
229 | if (T->containsUnexpandedParameterPack()) |
230 | OS << " contains_unexpanded_pack"; |
231 | if (T->isFromAST()) |
232 | OS << " imported"; |
233 | |
234 | TypeVisitor<TextNodeDumper>::Visit(T); |
235 | } |
236 | |
237 | void TextNodeDumper::Visit(QualType T) { |
238 | OS << "QualType"; |
239 | dumpPointer(Ptr: T.getAsOpaquePtr()); |
240 | OS << " "; |
241 | dumpBareType(T, Desugar: false); |
242 | OS << " "<< T.split().Quals.getAsString(); |
243 | } |
244 | |
245 | void TextNodeDumper::Visit(TypeLoc TL) { |
246 | if (!TL) { |
247 | ColorScope Color(OS, ShowColors, NullColor); |
248 | OS << "<<<NULL>>>"; |
249 | return; |
250 | } |
251 | |
252 | { |
253 | ColorScope Color(OS, ShowColors, TypeColor); |
254 | OS << (TL.getTypeLocClass() == TypeLoc::Qualified |
255 | ? "Qualified" |
256 | : TL.getType()->getTypeClassName()) |
257 | << "TypeLoc"; |
258 | } |
259 | dumpSourceRange(R: TL.getSourceRange()); |
260 | OS << ' '; |
261 | dumpBareType(T: TL.getType(), /*Desugar=*/false); |
262 | |
263 | TypeLocVisitor<TextNodeDumper>::Visit(TyLoc: TL); |
264 | } |
265 | |
266 | void TextNodeDumper::Visit(const Decl *D) { |
267 | if (!D) { |
268 | ColorScope Color(OS, ShowColors, NullColor); |
269 | OS << "<<<NULL>>>"; |
270 | return; |
271 | } |
272 | |
273 | { |
274 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
275 | OS << D->getDeclKindName() << "Decl"; |
276 | } |
277 | dumpPointer(Ptr: D); |
278 | if (D->getLexicalDeclContext() != D->getDeclContext()) |
279 | OS << " parent "<< cast<Decl>(Val: D->getDeclContext()); |
280 | dumpPreviousDecl(OS, D); |
281 | dumpSourceRange(R: D->getSourceRange()); |
282 | OS << ' '; |
283 | dumpLocation(Loc: D->getLocation()); |
284 | if (D->isFromASTFile()) |
285 | OS << " imported"; |
286 | if (Module *M = D->getOwningModule()) |
287 | OS << " in "<< M->getFullModuleName(); |
288 | if (auto *ND = dyn_cast<NamedDecl>(Val: D)) |
289 | for (Module *M : D->getASTContext().getModulesWithMergedDefinition( |
290 | Def: const_cast<NamedDecl *>(ND))) |
291 | AddChild(DoAddChild: [=] { OS << "also in "<< M->getFullModuleName(); }); |
292 | if (const NamedDecl *ND = dyn_cast<NamedDecl>(Val: D)) |
293 | if (!ND->isUnconditionallyVisible()) |
294 | OS << " hidden"; |
295 | if (D->isImplicit()) |
296 | OS << " implicit"; |
297 | |
298 | if (D->isUsed()) |
299 | OS << " used"; |
300 | else if (D->isThisDeclarationReferenced()) |
301 | OS << " referenced"; |
302 | |
303 | if (D->isInvalidDecl()) |
304 | OS << " invalid"; |
305 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) { |
306 | if (FD->isConstexprSpecified()) |
307 | OS << " constexpr"; |
308 | if (FD->isConsteval()) |
309 | OS << " consteval"; |
310 | else if (FD->isImmediateFunction()) |
311 | OS << " immediate"; |
312 | if (FD->isMultiVersion()) |
313 | OS << " multiversion"; |
314 | } |
315 | |
316 | if (!isa<FunctionDecl>(Val: *D)) { |
317 | const auto *MD = dyn_cast<ObjCMethodDecl>(Val: D); |
318 | if (!MD || !MD->isThisDeclarationADefinition()) { |
319 | const auto *DC = dyn_cast<DeclContext>(Val: D); |
320 | if (DC && DC->hasExternalLexicalStorage()) { |
321 | ColorScope Color(OS, ShowColors, UndeserializedColor); |
322 | OS << " <undeserialized declarations>"; |
323 | } |
324 | } |
325 | } |
326 | |
327 | switch (D->getFriendObjectKind()) { |
328 | case Decl::FOK_None: |
329 | break; |
330 | case Decl::FOK_Declared: |
331 | OS << " friend"; |
332 | break; |
333 | case Decl::FOK_Undeclared: |
334 | OS << " friend_undeclared"; |
335 | break; |
336 | } |
337 | |
338 | ConstDeclVisitor<TextNodeDumper>::Visit(D); |
339 | } |
340 | |
341 | void TextNodeDumper::Visit(const CXXCtorInitializer *Init) { |
342 | OS << "CXXCtorInitializer"; |
343 | if (Init->isAnyMemberInitializer()) { |
344 | OS << ' '; |
345 | dumpBareDeclRef(Init->getAnyMember()); |
346 | } else if (Init->isBaseInitializer()) { |
347 | dumpType(T: QualType(Init->getBaseClass(), 0)); |
348 | } else if (Init->isDelegatingInitializer()) { |
349 | dumpType(T: Init->getTypeSourceInfo()->getType()); |
350 | } else { |
351 | llvm_unreachable("Unknown initializer type"); |
352 | } |
353 | } |
354 | |
355 | void TextNodeDumper::Visit(const BlockDecl::Capture &C) { |
356 | OS << "capture"; |
357 | if (C.isByRef()) |
358 | OS << " byref"; |
359 | if (C.isNested()) |
360 | OS << " nested"; |
361 | if (C.getVariable()) { |
362 | OS << ' '; |
363 | dumpBareDeclRef(C.getVariable()); |
364 | } |
365 | } |
366 | |
367 | void TextNodeDumper::Visit(const OMPClause *C) { |
368 | if (!C) { |
369 | ColorScope Color(OS, ShowColors, NullColor); |
370 | OS << "<<<NULL>>> OMPClause"; |
371 | return; |
372 | } |
373 | { |
374 | ColorScope Color(OS, ShowColors, AttrColor); |
375 | StringRef ClauseName(llvm::omp::getOpenMPClauseName(C->getClauseKind())); |
376 | OS << "OMP"<< ClauseName.substr(/*Start=*/0, /*N=*/1).upper() |
377 | << ClauseName.drop_front() << "Clause"; |
378 | } |
379 | dumpPointer(Ptr: C); |
380 | dumpSourceRange(R: SourceRange(C->getBeginLoc(), C->getEndLoc())); |
381 | if (C->isImplicit()) |
382 | OS << " <implicit>"; |
383 | } |
384 | |
385 | void TextNodeDumper::VisitOpenACCAsteriskSizeExpr( |
386 | const OpenACCAsteriskSizeExpr *E) { |
387 | // Nothing to do here, only location exists, and that is printed elsewhere. |
388 | } |
389 | |
390 | void TextNodeDumper::Visit(const OpenACCClause *C) { |
391 | if (!C) { |
392 | ColorScope Color(OS, ShowColors, NullColor); |
393 | OS << "<<<NULL>>> OpenACCClause"; |
394 | return; |
395 | } |
396 | { |
397 | ColorScope Color(OS, ShowColors, AttrColor); |
398 | OS << C->getClauseKind(); |
399 | |
400 | // Handle clauses with parens for types that have no children, likely |
401 | // because there is no sub expression. |
402 | switch (C->getClauseKind()) { |
403 | case OpenACCClauseKind::Default: |
404 | OS << '(' << cast<OpenACCDefaultClause>(Val: C)->getDefaultClauseKind() << ')'; |
405 | break; |
406 | case OpenACCClauseKind::Async: |
407 | case OpenACCClauseKind::Auto: |
408 | case OpenACCClauseKind::Attach: |
409 | case OpenACCClauseKind::Host: |
410 | case OpenACCClauseKind::If: |
411 | case OpenACCClauseKind::IfPresent: |
412 | case OpenACCClauseKind::Independent: |
413 | case OpenACCClauseKind::Detach: |
414 | case OpenACCClauseKind::Delete: |
415 | case OpenACCClauseKind::Device: |
416 | case OpenACCClauseKind::DeviceNum: |
417 | case OpenACCClauseKind::DefaultAsync: |
418 | case OpenACCClauseKind::DeviceResident: |
419 | case OpenACCClauseKind::DevicePtr: |
420 | case OpenACCClauseKind::Finalize: |
421 | case OpenACCClauseKind::FirstPrivate: |
422 | case OpenACCClauseKind::Link: |
423 | case OpenACCClauseKind::NoCreate: |
424 | case OpenACCClauseKind::NoHost: |
425 | case OpenACCClauseKind::NumGangs: |
426 | case OpenACCClauseKind::NumWorkers: |
427 | case OpenACCClauseKind::Present: |
428 | case OpenACCClauseKind::Private: |
429 | case OpenACCClauseKind::Self: |
430 | case OpenACCClauseKind::Seq: |
431 | case OpenACCClauseKind::Tile: |
432 | case OpenACCClauseKind::Worker: |
433 | case OpenACCClauseKind::UseDevice: |
434 | case OpenACCClauseKind::Vector: |
435 | case OpenACCClauseKind::VectorLength: |
436 | case OpenACCClauseKind::Invalid: |
437 | case OpenACCClauseKind::Shortloop: |
438 | // The condition expression will be printed as a part of the 'children', |
439 | // but print 'clause' here so it is clear what is happening from the dump. |
440 | OS << " clause"; |
441 | break; |
442 | case OpenACCClauseKind::Gang: { |
443 | OS << " clause"; |
444 | // print the list of all GangKinds, so that there is some sort of |
445 | // relationship to the expressions listed afterwards. |
446 | auto *GC = cast<OpenACCGangClause>(Val: C); |
447 | |
448 | for (unsigned I = 0; I < GC->getNumExprs(); ++I) { |
449 | OS << " "<< GC->getExpr(I).first; |
450 | } |
451 | break; |
452 | } |
453 | case OpenACCClauseKind::Collapse: |
454 | OS << " clause"; |
455 | if (cast<OpenACCCollapseClause>(Val: C)->hasForce()) |
456 | OS << ": force"; |
457 | break; |
458 | |
459 | case OpenACCClauseKind::Copy: |
460 | case OpenACCClauseKind::PCopy: |
461 | case OpenACCClauseKind::PresentOrCopy: |
462 | OS << " clause"; |
463 | if (cast<OpenACCCopyClause>(Val: C)->getModifierList() != |
464 | OpenACCModifierKind::Invalid) |
465 | OS << " modifiers: "<< cast<OpenACCCopyClause>(Val: C)->getModifierList(); |
466 | break; |
467 | case OpenACCClauseKind::CopyIn: |
468 | case OpenACCClauseKind::PCopyIn: |
469 | case OpenACCClauseKind::PresentOrCopyIn: |
470 | OS << " clause"; |
471 | if (cast<OpenACCCopyInClause>(Val: C)->getModifierList() != |
472 | OpenACCModifierKind::Invalid) |
473 | OS << " modifiers: "<< cast<OpenACCCopyInClause>(Val: C)->getModifierList(); |
474 | break; |
475 | case OpenACCClauseKind::CopyOut: |
476 | case OpenACCClauseKind::PCopyOut: |
477 | case OpenACCClauseKind::PresentOrCopyOut: |
478 | OS << " clause"; |
479 | if (cast<OpenACCCopyOutClause>(Val: C)->getModifierList() != |
480 | OpenACCModifierKind::Invalid) |
481 | OS << " modifiers: " |
482 | << cast<OpenACCCopyOutClause>(Val: C)->getModifierList(); |
483 | break; |
484 | case OpenACCClauseKind::Create: |
485 | case OpenACCClauseKind::PCreate: |
486 | case OpenACCClauseKind::PresentOrCreate: |
487 | OS << " clause"; |
488 | if (cast<OpenACCCreateClause>(Val: C)->getModifierList() != |
489 | OpenACCModifierKind::Invalid) |
490 | OS << " modifiers: "<< cast<OpenACCCreateClause>(Val: C)->getModifierList(); |
491 | break; |
492 | case OpenACCClauseKind::Wait: |
493 | OS << " clause"; |
494 | if (cast<OpenACCWaitClause>(Val: C)->hasDevNumExpr()) |
495 | OS << " has devnum"; |
496 | if (cast<OpenACCWaitClause>(Val: C)->hasQueuesTag()) |
497 | OS << " has queues tag"; |
498 | break; |
499 | case OpenACCClauseKind::DeviceType: |
500 | case OpenACCClauseKind::DType: |
501 | OS << "("; |
502 | llvm::interleaveComma( |
503 | c: cast<OpenACCDeviceTypeClause>(Val: C)->getArchitectures(), os&: OS, |
504 | each_fn: [&](const DeviceTypeArgument &Arch) { |
505 | if (Arch.getIdentifierInfo() == nullptr) |
506 | OS << "*"; |
507 | else |
508 | OS << Arch.getIdentifierInfo()->getName(); |
509 | }); |
510 | OS << ")"; |
511 | break; |
512 | case OpenACCClauseKind::Reduction: |
513 | OS << " clause Operator: " |
514 | << cast<OpenACCReductionClause>(Val: C)->getReductionOp(); |
515 | break; |
516 | case OpenACCClauseKind::Bind: |
517 | OS << " clause"; |
518 | if (cast<OpenACCBindClause>(Val: C)->isIdentifierArgument()) |
519 | OS << " identifier '" |
520 | << cast<OpenACCBindClause>(Val: C)->getIdentifierArgument()->getName() |
521 | << "'"; |
522 | else |
523 | AddChild( |
524 | DoAddChild: [=] { Visit(cast<OpenACCBindClause>(Val: C)->getStringArgument()); }); |
525 | } |
526 | } |
527 | dumpPointer(Ptr: C); |
528 | dumpSourceRange(R: SourceRange(C->getBeginLoc(), C->getEndLoc())); |
529 | } |
530 | |
531 | void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) { |
532 | const TypeSourceInfo *TSI = A.getTypeSourceInfo(); |
533 | if (TSI) { |
534 | OS << "case "; |
535 | dumpType(T: TSI->getType()); |
536 | } else { |
537 | OS << "default"; |
538 | } |
539 | |
540 | if (A.isSelected()) |
541 | OS << " selected"; |
542 | } |
543 | |
544 | void TextNodeDumper::Visit(const ConceptReference *R) { |
545 | if (!R) { |
546 | ColorScope Color(OS, ShowColors, NullColor); |
547 | OS << "<<<NULL>>> ConceptReference"; |
548 | return; |
549 | } |
550 | |
551 | OS << "ConceptReference"; |
552 | dumpPointer(Ptr: R); |
553 | dumpSourceRange(R: R->getSourceRange()); |
554 | OS << ' '; |
555 | dumpBareDeclRef(R->getNamedConcept()); |
556 | } |
557 | |
558 | void TextNodeDumper::Visit(const concepts::Requirement *R) { |
559 | if (!R) { |
560 | ColorScope Color(OS, ShowColors, NullColor); |
561 | OS << "<<<NULL>>> Requirement"; |
562 | return; |
563 | } |
564 | |
565 | { |
566 | ColorScope Color(OS, ShowColors, StmtColor); |
567 | switch (R->getKind()) { |
568 | case concepts::Requirement::RK_Type: |
569 | OS << "TypeRequirement"; |
570 | break; |
571 | case concepts::Requirement::RK_Simple: |
572 | OS << "SimpleRequirement"; |
573 | break; |
574 | case concepts::Requirement::RK_Compound: |
575 | OS << "CompoundRequirement"; |
576 | break; |
577 | case concepts::Requirement::RK_Nested: |
578 | OS << "NestedRequirement"; |
579 | break; |
580 | } |
581 | } |
582 | |
583 | dumpPointer(Ptr: R); |
584 | |
585 | if (auto *ER = dyn_cast<concepts::ExprRequirement>(Val: R)) { |
586 | if (ER->hasNoexceptRequirement()) |
587 | OS << " noexcept"; |
588 | } |
589 | |
590 | if (R->isDependent()) |
591 | OS << " dependent"; |
592 | else |
593 | OS << (R->isSatisfied() ? " satisfied": " unsatisfied"); |
594 | if (R->containsUnexpandedParameterPack()) |
595 | OS << " contains_unexpanded_pack"; |
596 | } |
597 | |
598 | static double GetApproxValue(const llvm::APFloat &F) { |
599 | llvm::APFloat V = F; |
600 | bool ignored; |
601 | V.convert(ToSemantics: llvm::APFloat::IEEEdouble(), RM: llvm::APFloat::rmNearestTiesToEven, |
602 | losesInfo: &ignored); |
603 | return V.convertToDouble(); |
604 | } |
605 | |
606 | /// True if the \p APValue \p Value can be folded onto the current line. |
607 | static bool isSimpleAPValue(const APValue &Value) { |
608 | switch (Value.getKind()) { |
609 | case APValue::None: |
610 | case APValue::Indeterminate: |
611 | case APValue::Int: |
612 | case APValue::Float: |
613 | case APValue::FixedPoint: |
614 | case APValue::ComplexInt: |
615 | case APValue::ComplexFloat: |
616 | case APValue::LValue: |
617 | case APValue::MemberPointer: |
618 | case APValue::AddrLabelDiff: |
619 | return true; |
620 | case APValue::Vector: |
621 | case APValue::Array: |
622 | case APValue::Struct: |
623 | return false; |
624 | case APValue::Union: |
625 | return isSimpleAPValue(Value: Value.getUnionValue()); |
626 | } |
627 | llvm_unreachable("unexpected APValue kind!"); |
628 | } |
629 | |
630 | /// Dump the children of the \p APValue \p Value. |
631 | /// |
632 | /// \param[in] Value The \p APValue to visit |
633 | /// \param[in] Ty The \p QualType passed to \p Visit |
634 | /// |
635 | /// \param[in] IdxToChildFun A function mapping an \p APValue and an index |
636 | /// to one of the child of the \p APValue |
637 | /// |
638 | /// \param[in] NumChildren \p IdxToChildFun will be called on \p Value with |
639 | /// the indices in the range \p [0,NumChildren( |
640 | /// |
641 | /// \param[in] LabelSingular The label to use on a line with a single child |
642 | /// \param[in] LabelPlurial The label to use on a line with multiple children |
643 | void TextNodeDumper::dumpAPValueChildren( |
644 | const APValue &Value, QualType Ty, |
645 | const APValue &(*IdxToChildFun)(const APValue &, unsigned), |
646 | unsigned NumChildren, StringRef LabelSingular, StringRef LabelPlurial) { |
647 | // To save some vertical space we print up to MaxChildrenPerLine APValues |
648 | // considered to be simple (by isSimpleAPValue) on a single line. |
649 | constexpr unsigned MaxChildrenPerLine = 4; |
650 | unsigned I = 0; |
651 | while (I < NumChildren) { |
652 | unsigned J = I; |
653 | while (J < NumChildren) { |
654 | if (isSimpleAPValue(Value: IdxToChildFun(Value, J)) && |
655 | (J - I < MaxChildrenPerLine)) { |
656 | ++J; |
657 | continue; |
658 | } |
659 | break; |
660 | } |
661 | |
662 | J = std::max(a: I + 1, b: J); |
663 | |
664 | // Print [I,J) on a single line. |
665 | AddChild(Label: J - I > 1 ? LabelPlurial : LabelSingular, DoAddChild: [=]() { |
666 | for (unsigned X = I; X < J; ++X) { |
667 | Visit(Value: IdxToChildFun(Value, X), Ty); |
668 | if (X + 1 != J) |
669 | OS << ", "; |
670 | } |
671 | }); |
672 | I = J; |
673 | } |
674 | } |
675 | |
676 | void TextNodeDumper::Visit(const APValue &Value, QualType Ty) { |
677 | ColorScope Color(OS, ShowColors, ValueKindColor); |
678 | switch (Value.getKind()) { |
679 | case APValue::None: |
680 | OS << "None"; |
681 | return; |
682 | case APValue::Indeterminate: |
683 | OS << "Indeterminate"; |
684 | return; |
685 | case APValue::Int: |
686 | OS << "Int "; |
687 | { |
688 | ColorScope Color(OS, ShowColors, ValueColor); |
689 | OS << Value.getInt(); |
690 | } |
691 | return; |
692 | case APValue::Float: |
693 | OS << "Float "; |
694 | { |
695 | ColorScope Color(OS, ShowColors, ValueColor); |
696 | OS << GetApproxValue(F: Value.getFloat()); |
697 | } |
698 | return; |
699 | case APValue::FixedPoint: |
700 | OS << "FixedPoint "; |
701 | { |
702 | ColorScope Color(OS, ShowColors, ValueColor); |
703 | OS << Value.getFixedPoint(); |
704 | } |
705 | return; |
706 | case APValue::Vector: { |
707 | unsigned VectorLength = Value.getVectorLength(); |
708 | OS << "Vector length="<< VectorLength; |
709 | |
710 | dumpAPValueChildren( |
711 | Value, Ty, |
712 | IdxToChildFun: [](const APValue &Value, unsigned Index) -> const APValue & { |
713 | return Value.getVectorElt(I: Index); |
714 | }, |
715 | NumChildren: VectorLength, LabelSingular: "element", LabelPlurial: "elements"); |
716 | return; |
717 | } |
718 | case APValue::ComplexInt: |
719 | OS << "ComplexInt "; |
720 | { |
721 | ColorScope Color(OS, ShowColors, ValueColor); |
722 | OS << Value.getComplexIntReal() << " + "<< Value.getComplexIntImag() |
723 | << 'i'; |
724 | } |
725 | return; |
726 | case APValue::ComplexFloat: |
727 | OS << "ComplexFloat "; |
728 | { |
729 | ColorScope Color(OS, ShowColors, ValueColor); |
730 | OS << GetApproxValue(F: Value.getComplexFloatReal()) << " + " |
731 | << GetApproxValue(F: Value.getComplexFloatImag()) << 'i'; |
732 | } |
733 | return; |
734 | case APValue::LValue: { |
735 | (void)Context; |
736 | OS << "LValue Base="; |
737 | APValue::LValueBase B = Value.getLValueBase(); |
738 | if (B.isNull()) |
739 | OS << "null"; |
740 | else if (const auto *BE = B.dyn_cast<const Expr *>()) { |
741 | OS << BE->getStmtClassName() << ' '; |
742 | dumpPointer(Ptr: BE); |
743 | } else if (const auto BTI = B.dyn_cast<TypeInfoLValue>()) { |
744 | OS << "TypeInfoLValue "; |
745 | ColorScope Color(OS, ShowColors, TypeColor); |
746 | BTI.print(Out&: OS, Policy: PrintPolicy); |
747 | } else if (B.is<DynamicAllocLValue>()) { |
748 | OS << "DynamicAllocLValue"; |
749 | auto BDA = B.getDynamicAllocType(); |
750 | dumpType(T: BDA); |
751 | } else { |
752 | const auto *VDB = B.get<const ValueDecl *>(); |
753 | OS << VDB->getDeclKindName() << "Decl"; |
754 | dumpPointer(Ptr: VDB); |
755 | } |
756 | OS << ", Null="<< Value.isNullPointer() |
757 | << ", Offset="<< Value.getLValueOffset().getQuantity() |
758 | << ", HasPath="<< Value.hasLValuePath(); |
759 | if (Value.hasLValuePath()) { |
760 | OS << ", PathLength="<< Value.getLValuePath().size(); |
761 | OS << ", Path=("; |
762 | llvm::ListSeparator Sep; |
763 | for (const auto &PathEntry : Value.getLValuePath()) { |
764 | // We're printing all entries as array indices because don't have the |
765 | // type information here to do anything else. |
766 | OS << Sep << PathEntry.getAsArrayIndex(); |
767 | } |
768 | OS << ")"; |
769 | } |
770 | return; |
771 | } |
772 | case APValue::Array: { |
773 | unsigned ArraySize = Value.getArraySize(); |
774 | unsigned NumInitializedElements = Value.getArrayInitializedElts(); |
775 | OS << "Array size="<< ArraySize; |
776 | |
777 | dumpAPValueChildren( |
778 | Value, Ty, |
779 | IdxToChildFun: [](const APValue &Value, unsigned Index) -> const APValue & { |
780 | return Value.getArrayInitializedElt(I: Index); |
781 | }, |
782 | NumChildren: NumInitializedElements, LabelSingular: "element", LabelPlurial: "elements"); |
783 | |
784 | if (Value.hasArrayFiller()) { |
785 | AddChild(Label: "filler", DoAddChild: [=] { |
786 | { |
787 | ColorScope Color(OS, ShowColors, ValueColor); |
788 | OS << ArraySize - NumInitializedElements << " x "; |
789 | } |
790 | Visit(Value: Value.getArrayFiller(), Ty); |
791 | }); |
792 | } |
793 | |
794 | return; |
795 | } |
796 | case APValue::Struct: { |
797 | OS << "Struct"; |
798 | |
799 | dumpAPValueChildren( |
800 | Value, Ty, |
801 | IdxToChildFun: [](const APValue &Value, unsigned Index) -> const APValue & { |
802 | return Value.getStructBase(i: Index); |
803 | }, |
804 | NumChildren: Value.getStructNumBases(), LabelSingular: "base", LabelPlurial: "bases"); |
805 | |
806 | dumpAPValueChildren( |
807 | Value, Ty, |
808 | IdxToChildFun: [](const APValue &Value, unsigned Index) -> const APValue & { |
809 | return Value.getStructField(i: Index); |
810 | }, |
811 | NumChildren: Value.getStructNumFields(), LabelSingular: "field", LabelPlurial: "fields"); |
812 | |
813 | return; |
814 | } |
815 | case APValue::Union: { |
816 | OS << "Union"; |
817 | { |
818 | ColorScope Color(OS, ShowColors, ValueColor); |
819 | if (const FieldDecl *FD = Value.getUnionField()) |
820 | OS << " ."<< *cast<NamedDecl>(Val: FD); |
821 | } |
822 | // If the union value is considered to be simple, fold it into the |
823 | // current line to save some vertical space. |
824 | const APValue &UnionValue = Value.getUnionValue(); |
825 | if (isSimpleAPValue(Value: UnionValue)) { |
826 | OS << ' '; |
827 | Visit(Value: UnionValue, Ty); |
828 | } else { |
829 | AddChild(DoAddChild: [=] { Visit(Value: UnionValue, Ty); }); |
830 | } |
831 | |
832 | return; |
833 | } |
834 | case APValue::MemberPointer: { |
835 | OS << "MemberPointer "; |
836 | auto Path = Value.getMemberPointerPath(); |
837 | for (const CXXRecordDecl *D : Path) { |
838 | { |
839 | ColorScope Color(OS, ShowColors, DeclNameColor); |
840 | OS << D->getDeclName(); |
841 | } |
842 | OS << "::"; |
843 | } |
844 | |
845 | ColorScope Color(OS, ShowColors, DeclNameColor); |
846 | OS << Value.getMemberPointerDecl()->getDeclName(); |
847 | return; |
848 | } |
849 | case APValue::AddrLabelDiff: |
850 | OS << "AddrLabelDiff <todo>"; |
851 | return; |
852 | } |
853 | llvm_unreachable("Unknown APValue kind!"); |
854 | } |
855 | |
856 | void TextNodeDumper::dumpPointer(const void *Ptr) { |
857 | ColorScope Color(OS, ShowColors, AddressColor); |
858 | OS << ' ' << Ptr; |
859 | } |
860 | |
861 | void TextNodeDumper::dumpLocation(SourceLocation Loc) { |
862 | if (!SM) |
863 | return; |
864 | |
865 | ColorScope Color(OS, ShowColors, LocationColor); |
866 | SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); |
867 | |
868 | // The general format we print out is filename:line:col, but we drop pieces |
869 | // that haven't changed since the last loc printed. |
870 | PresumedLoc PLoc = SM->getPresumedLoc(Loc: SpellingLoc); |
871 | |
872 | if (PLoc.isInvalid()) { |
873 | OS << "<invalid sloc>"; |
874 | return; |
875 | } |
876 | |
877 | if (strcmp(s1: PLoc.getFilename(), s2: LastLocFilename) != 0) { |
878 | OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' |
879 | << PLoc.getColumn(); |
880 | LastLocFilename = PLoc.getFilename(); |
881 | LastLocLine = PLoc.getLine(); |
882 | } else if (PLoc.getLine() != LastLocLine) { |
883 | OS << "line"<< ':' << PLoc.getLine() << ':' << PLoc.getColumn(); |
884 | LastLocLine = PLoc.getLine(); |
885 | } else { |
886 | OS << "col"<< ':' << PLoc.getColumn(); |
887 | } |
888 | } |
889 | |
890 | void TextNodeDumper::dumpSourceRange(SourceRange R) { |
891 | // Can't translate locations if a SourceManager isn't available. |
892 | if (!SM) |
893 | return; |
894 | |
895 | OS << " <"; |
896 | dumpLocation(Loc: R.getBegin()); |
897 | if (R.getBegin() != R.getEnd()) { |
898 | OS << ", "; |
899 | dumpLocation(Loc: R.getEnd()); |
900 | } |
901 | OS << ">"; |
902 | |
903 | // <t2.c:123:421[blah], t2.c:412:321> |
904 | } |
905 | |
906 | void TextNodeDumper::dumpBareType(QualType T, bool Desugar) { |
907 | ColorScope Color(OS, ShowColors, TypeColor); |
908 | |
909 | SplitQualType T_split = T.split(); |
910 | std::string T_str = QualType::getAsString(split: T_split, Policy: PrintPolicy); |
911 | OS << "'"<< T_str << "'"; |
912 | |
913 | if (Desugar && !T.isNull()) { |
914 | // If the type is sugared, also dump a (shallow) desugared type when |
915 | // it is visibly different. |
916 | SplitQualType D_split = T.getSplitDesugaredType(); |
917 | if (T_split != D_split) { |
918 | std::string D_str = QualType::getAsString(split: D_split, Policy: PrintPolicy); |
919 | if (T_str != D_str) |
920 | OS << ":'"<< QualType::getAsString(split: D_split, Policy: PrintPolicy) << "'"; |
921 | } |
922 | } |
923 | } |
924 | |
925 | void TextNodeDumper::dumpType(QualType T) { |
926 | OS << ' '; |
927 | dumpBareType(T); |
928 | } |
929 | |
930 | void TextNodeDumper::dumpBareDeclRef(const Decl *D) { |
931 | if (!D) { |
932 | ColorScope Color(OS, ShowColors, NullColor); |
933 | OS << "<<<NULL>>>"; |
934 | return; |
935 | } |
936 | |
937 | { |
938 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
939 | OS << D->getDeclKindName(); |
940 | } |
941 | dumpPointer(Ptr: D); |
942 | |
943 | if (const NamedDecl *ND = dyn_cast<NamedDecl>(Val: D)) { |
944 | ColorScope Color(OS, ShowColors, DeclNameColor); |
945 | if (DeclarationName Name = ND->getDeclName()) |
946 | OS << " '"<< Name << '\''; |
947 | else |
948 | switch (ND->getKind()) { |
949 | case Decl::Decomposition: { |
950 | auto *DD = cast<DecompositionDecl>(Val: ND); |
951 | OS << " first_binding '"<< DD->bindings()[0]->getDeclName() << '\''; |
952 | break; |
953 | } |
954 | case Decl::Field: { |
955 | auto *FD = cast<FieldDecl>(Val: ND); |
956 | OS << " field_index "<< FD->getFieldIndex(); |
957 | break; |
958 | } |
959 | case Decl::ParmVar: { |
960 | auto *PD = cast<ParmVarDecl>(Val: ND); |
961 | OS << " depth "<< PD->getFunctionScopeDepth() << " index " |
962 | << PD->getFunctionScopeIndex(); |
963 | break; |
964 | } |
965 | case Decl::TemplateTypeParm: { |
966 | auto *TD = cast<TemplateTypeParmDecl>(Val: ND); |
967 | OS << " depth "<< TD->getDepth() << " index "<< TD->getIndex(); |
968 | break; |
969 | } |
970 | case Decl::NonTypeTemplateParm: { |
971 | auto *TD = cast<NonTypeTemplateParmDecl>(Val: ND); |
972 | OS << " depth "<< TD->getDepth() << " index "<< TD->getIndex(); |
973 | break; |
974 | } |
975 | default: |
976 | // Var, Namespace, (CXX)Record: Nothing else besides source location. |
977 | dumpSourceRange(R: ND->getSourceRange()); |
978 | break; |
979 | } |
980 | } |
981 | |
982 | if (const ValueDecl *VD = dyn_cast<ValueDecl>(Val: D)) |
983 | dumpType(T: VD->getType()); |
984 | } |
985 | |
986 | void TextNodeDumper::dumpName(const NamedDecl *ND) { |
987 | if (ND->getDeclName()) { |
988 | ColorScope Color(OS, ShowColors, DeclNameColor); |
989 | OS << ' ' << ND->getDeclName(); |
990 | } |
991 | } |
992 | |
993 | void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) { |
994 | const auto AccessSpelling = getAccessSpelling(AS); |
995 | if (AccessSpelling.empty()) |
996 | return; |
997 | OS << AccessSpelling; |
998 | } |
999 | |
1000 | void TextNodeDumper::dumpCleanupObject( |
1001 | const ExprWithCleanups::CleanupObject &C) { |
1002 | if (auto *BD = dyn_cast<BlockDecl *>(Val: C)) |
1003 | dumpDeclRef(BD, "cleanup"); |
1004 | else if (auto *CLE = dyn_cast<CompoundLiteralExpr *>(Val: C)) |
1005 | AddChild(DoAddChild: [=] { |
1006 | OS << "cleanup "; |
1007 | { |
1008 | ColorScope Color(OS, ShowColors, StmtColor); |
1009 | OS << CLE->getStmtClassName(); |
1010 | } |
1011 | dumpPointer(Ptr: CLE); |
1012 | }); |
1013 | else |
1014 | llvm_unreachable("unexpected cleanup type"); |
1015 | } |
1016 | |
1017 | void clang::TextNodeDumper::dumpTemplateSpecializationKind( |
1018 | TemplateSpecializationKind TSK) { |
1019 | switch (TSK) { |
1020 | case TSK_Undeclared: |
1021 | break; |
1022 | case TSK_ImplicitInstantiation: |
1023 | OS << " implicit_instantiation"; |
1024 | break; |
1025 | case TSK_ExplicitSpecialization: |
1026 | OS << " explicit_specialization"; |
1027 | break; |
1028 | case TSK_ExplicitInstantiationDeclaration: |
1029 | OS << " explicit_instantiation_declaration"; |
1030 | break; |
1031 | case TSK_ExplicitInstantiationDefinition: |
1032 | OS << " explicit_instantiation_definition"; |
1033 | break; |
1034 | } |
1035 | } |
1036 | |
1037 | void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *NNS) { |
1038 | if (!NNS) |
1039 | return; |
1040 | |
1041 | AddChild(DoAddChild: [=] { |
1042 | OS << "NestedNameSpecifier"; |
1043 | |
1044 | switch (NNS->getKind()) { |
1045 | case NestedNameSpecifier::Identifier: |
1046 | OS << " Identifier"; |
1047 | OS << " '"<< NNS->getAsIdentifier()->getName() << "'"; |
1048 | break; |
1049 | case NestedNameSpecifier::Namespace: |
1050 | OS << " "; // "Namespace" is printed as the decl kind. |
1051 | dumpBareDeclRef(NNS->getAsNamespace()); |
1052 | break; |
1053 | case NestedNameSpecifier::NamespaceAlias: |
1054 | OS << " "; // "NamespaceAlias" is printed as the decl kind. |
1055 | dumpBareDeclRef(NNS->getAsNamespaceAlias()); |
1056 | break; |
1057 | case NestedNameSpecifier::TypeSpec: |
1058 | OS << " TypeSpec"; |
1059 | dumpType(T: QualType(NNS->getAsType(), 0)); |
1060 | break; |
1061 | case NestedNameSpecifier::Global: |
1062 | OS << " Global"; |
1063 | break; |
1064 | case NestedNameSpecifier::Super: |
1065 | OS << " Super"; |
1066 | break; |
1067 | } |
1068 | |
1069 | dumpNestedNameSpecifier(NNS: NNS->getPrefix()); |
1070 | }); |
1071 | } |
1072 | |
1073 | void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) { |
1074 | if (!D) |
1075 | return; |
1076 | |
1077 | AddChild(DoAddChild: [=] { |
1078 | if (!Label.empty()) |
1079 | OS << Label << ' '; |
1080 | dumpBareDeclRef(D); |
1081 | }); |
1082 | } |
1083 | |
1084 | void TextNodeDumper::dumpTemplateArgument(const TemplateArgument &TA) { |
1085 | llvm::SmallString<128> Str; |
1086 | { |
1087 | llvm::raw_svector_ostream SS(Str); |
1088 | TA.print(Policy: PrintPolicy, Out&: SS, /*IncludeType=*/true); |
1089 | } |
1090 | OS << " '"<< Str << "'"; |
1091 | |
1092 | if (!Context) |
1093 | return; |
1094 | |
1095 | if (TemplateArgument CanonTA = Context->getCanonicalTemplateArgument(Arg: TA); |
1096 | !CanonTA.structurallyEquals(Other: TA)) { |
1097 | llvm::SmallString<128> CanonStr; |
1098 | { |
1099 | llvm::raw_svector_ostream SS(CanonStr); |
1100 | CanonTA.print(Policy: PrintPolicy, Out&: SS, /*IncludeType=*/true); |
1101 | } |
1102 | if (CanonStr != Str) |
1103 | OS << ":'"<< CanonStr << "'"; |
1104 | } |
1105 | } |
1106 | |
1107 | const char *TextNodeDumper::getCommandName(unsigned CommandID) { |
1108 | if (Traits) |
1109 | return Traits->getCommandInfo(CommandID)->Name; |
1110 | const comments::CommandInfo *Info = |
1111 | comments::CommandTraits::getBuiltinCommandInfo(CommandID); |
1112 | if (Info) |
1113 | return Info->Name; |
1114 | return "<not a builtin command>"; |
1115 | } |
1116 | |
1117 | void TextNodeDumper::printFPOptions(FPOptionsOverride FPO) { |
1118 | #define FP_OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
1119 | if (FPO.has##NAME##Override()) \ |
1120 | OS << " " #NAME "=" << FPO.get##NAME##Override(); |
1121 | #include "clang/Basic/FPOptions.def" |
1122 | } |
1123 | |
1124 | void TextNodeDumper::visitTextComment(const comments::TextComment *C, |
1125 | const comments::FullComment *) { |
1126 | OS << " Text=\""<< C->getText() << "\""; |
1127 | } |
1128 | |
1129 | void TextNodeDumper::visitInlineCommandComment( |
1130 | const comments::InlineCommandComment *C, const comments::FullComment *) { |
1131 | OS << " Name=\""<< getCommandName(CommandID: C->getCommandID()) << "\""; |
1132 | switch (C->getRenderKind()) { |
1133 | case comments::InlineCommandRenderKind::Normal: |
1134 | OS << " RenderNormal"; |
1135 | break; |
1136 | case comments::InlineCommandRenderKind::Bold: |
1137 | OS << " RenderBold"; |
1138 | break; |
1139 | case comments::InlineCommandRenderKind::Monospaced: |
1140 | OS << " RenderMonospaced"; |
1141 | break; |
1142 | case comments::InlineCommandRenderKind::Emphasized: |
1143 | OS << " RenderEmphasized"; |
1144 | break; |
1145 | case comments::InlineCommandRenderKind::Anchor: |
1146 | OS << " RenderAnchor"; |
1147 | break; |
1148 | } |
1149 | |
1150 | for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) |
1151 | OS << " Arg["<< i << "]=\""<< C->getArgText(Idx: i) << "\""; |
1152 | } |
1153 | |
1154 | void TextNodeDumper::visitHTMLStartTagComment( |
1155 | const comments::HTMLStartTagComment *C, const comments::FullComment *) { |
1156 | OS << " Name=\""<< C->getTagName() << "\""; |
1157 | if (C->getNumAttrs() != 0) { |
1158 | OS << " Attrs: "; |
1159 | for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) { |
1160 | const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(Idx: i); |
1161 | OS << " \""<< Attr.Name << "=\""<< Attr.Value << "\""; |
1162 | } |
1163 | } |
1164 | if (C->isSelfClosing()) |
1165 | OS << " SelfClosing"; |
1166 | } |
1167 | |
1168 | void TextNodeDumper::visitHTMLEndTagComment( |
1169 | const comments::HTMLEndTagComment *C, const comments::FullComment *) { |
1170 | OS << " Name=\""<< C->getTagName() << "\""; |
1171 | } |
1172 | |
1173 | void TextNodeDumper::visitBlockCommandComment( |
1174 | const comments::BlockCommandComment *C, const comments::FullComment *) { |
1175 | OS << " Name=\""<< getCommandName(CommandID: C->getCommandID()) << "\""; |
1176 | for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) |
1177 | OS << " Arg["<< i << "]=\""<< C->getArgText(Idx: i) << "\""; |
1178 | } |
1179 | |
1180 | void TextNodeDumper::visitParamCommandComment( |
1181 | const comments::ParamCommandComment *C, const comments::FullComment *FC) { |
1182 | OS << " " |
1183 | << comments::ParamCommandComment::getDirectionAsString(D: C->getDirection()); |
1184 | |
1185 | if (C->isDirectionExplicit()) |
1186 | OS << " explicitly"; |
1187 | else |
1188 | OS << " implicitly"; |
1189 | |
1190 | if (C->hasParamName()) { |
1191 | if (C->isParamIndexValid()) |
1192 | OS << " Param=\""<< C->getParamName(FC) << "\""; |
1193 | else |
1194 | OS << " Param=\""<< C->getParamNameAsWritten() << "\""; |
1195 | } |
1196 | |
1197 | if (C->isParamIndexValid() && !C->isVarArgParam()) |
1198 | OS << " ParamIndex="<< C->getParamIndex(); |
1199 | } |
1200 | |
1201 | void TextNodeDumper::visitTParamCommandComment( |
1202 | const comments::TParamCommandComment *C, const comments::FullComment *FC) { |
1203 | if (C->hasParamName()) { |
1204 | if (C->isPositionValid()) |
1205 | OS << " Param=\""<< C->getParamName(FC) << "\""; |
1206 | else |
1207 | OS << " Param=\""<< C->getParamNameAsWritten() << "\""; |
1208 | } |
1209 | |
1210 | if (C->isPositionValid()) { |
1211 | OS << " Position=<"; |
1212 | for (unsigned i = 0, e = C->getDepth(); i != e; ++i) { |
1213 | OS << C->getIndex(Depth: i); |
1214 | if (i != e - 1) |
1215 | OS << ", "; |
1216 | } |
1217 | OS << ">"; |
1218 | } |
1219 | } |
1220 | |
1221 | void TextNodeDumper::visitVerbatimBlockComment( |
1222 | const comments::VerbatimBlockComment *C, const comments::FullComment *) { |
1223 | OS << " Name=\""<< getCommandName(CommandID: C->getCommandID()) |
1224 | << "\"" |
1225 | " CloseName=\"" |
1226 | << C->getCloseName() << "\""; |
1227 | } |
1228 | |
1229 | void TextNodeDumper::visitVerbatimBlockLineComment( |
1230 | const comments::VerbatimBlockLineComment *C, |
1231 | const comments::FullComment *) { |
1232 | OS << " Text=\""<< C->getText() << "\""; |
1233 | } |
1234 | |
1235 | void TextNodeDumper::visitVerbatimLineComment( |
1236 | const comments::VerbatimLineComment *C, const comments::FullComment *) { |
1237 | OS << " Text=\""<< C->getText() << "\""; |
1238 | } |
1239 | |
1240 | void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) { |
1241 | OS << " null"; |
1242 | } |
1243 | |
1244 | void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) { |
1245 | OS << " type"; |
1246 | dumpTemplateArgument(TA); |
1247 | } |
1248 | |
1249 | void TextNodeDumper::VisitDeclarationTemplateArgument( |
1250 | const TemplateArgument &TA) { |
1251 | OS << " decl"; |
1252 | dumpTemplateArgument(TA); |
1253 | dumpDeclRef(TA.getAsDecl()); |
1254 | } |
1255 | |
1256 | void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) { |
1257 | OS << " nullptr"; |
1258 | dumpTemplateArgument(TA); |
1259 | } |
1260 | |
1261 | void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) { |
1262 | OS << " integral"; |
1263 | dumpTemplateArgument(TA); |
1264 | } |
1265 | |
1266 | void TextNodeDumper::VisitStructuralValueTemplateArgument( |
1267 | const TemplateArgument &TA) { |
1268 | OS << " structural value"; |
1269 | dumpTemplateArgument(TA); |
1270 | } |
1271 | |
1272 | void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) { |
1273 | AddChild(Label, DoAddChild: [=] { |
1274 | { |
1275 | llvm::SmallString<128> Str; |
1276 | { |
1277 | llvm::raw_svector_ostream SS(Str); |
1278 | TN.print(OS&: SS, Policy: PrintPolicy); |
1279 | } |
1280 | OS << "'"<< Str << "'"; |
1281 | |
1282 | if (Context) { |
1283 | if (TemplateName CanonTN = Context->getCanonicalTemplateName(Name: TN); |
1284 | CanonTN != TN) { |
1285 | llvm::SmallString<128> CanonStr; |
1286 | { |
1287 | llvm::raw_svector_ostream SS(CanonStr); |
1288 | CanonTN.print(OS&: SS, Policy: PrintPolicy); |
1289 | } |
1290 | if (CanonStr != Str) |
1291 | OS << ":'"<< CanonStr << "'"; |
1292 | } |
1293 | } |
1294 | } |
1295 | dumpBareTemplateName(TN); |
1296 | }); |
1297 | } |
1298 | |
1299 | void TextNodeDumper::dumpBareTemplateName(TemplateName TN) { |
1300 | switch (TN.getKind()) { |
1301 | case TemplateName::Template: |
1302 | AddChild(DoAddChild: [=] { Visit(TN.getAsTemplateDecl()); }); |
1303 | return; |
1304 | case TemplateName::UsingTemplate: { |
1305 | const UsingShadowDecl *USD = TN.getAsUsingShadowDecl(); |
1306 | AddChild(DoAddChild: [=] { Visit(USD); }); |
1307 | AddChild(Label: "target", DoAddChild: [=] { Visit(USD->getTargetDecl()); }); |
1308 | return; |
1309 | } |
1310 | case TemplateName::QualifiedTemplate: { |
1311 | OS << " qualified"; |
1312 | const QualifiedTemplateName *QTN = TN.getAsQualifiedTemplateName(); |
1313 | if (QTN->hasTemplateKeyword()) |
1314 | OS << " keyword"; |
1315 | dumpNestedNameSpecifier(NNS: QTN->getQualifier()); |
1316 | dumpBareTemplateName(TN: QTN->getUnderlyingTemplate()); |
1317 | return; |
1318 | } |
1319 | case TemplateName::DependentTemplate: { |
1320 | OS << " dependent"; |
1321 | const DependentTemplateName *DTN = TN.getAsDependentTemplateName(); |
1322 | dumpNestedNameSpecifier(NNS: DTN->getQualifier()); |
1323 | return; |
1324 | } |
1325 | case TemplateName::SubstTemplateTemplateParm: { |
1326 | OS << " subst"; |
1327 | const SubstTemplateTemplateParmStorage *STS = |
1328 | TN.getAsSubstTemplateTemplateParm(); |
1329 | OS << " index "<< STS->getIndex(); |
1330 | if (UnsignedOrNone PackIndex = STS->getPackIndex()) |
1331 | OS << " pack_index "<< *PackIndex; |
1332 | if (STS->getFinal()) |
1333 | OS << " final"; |
1334 | if (const TemplateTemplateParmDecl *P = STS->getParameter()) |
1335 | AddChild(Label: "parameter", DoAddChild: [=] { Visit(P); }); |
1336 | dumpDeclRef(D: STS->getAssociatedDecl(), Label: "associated"); |
1337 | dumpTemplateName(TN: STS->getReplacement(), Label: "replacement"); |
1338 | return; |
1339 | } |
1340 | case TemplateName::DeducedTemplate: { |
1341 | OS << " deduced"; |
1342 | const DeducedTemplateStorage *DTS = TN.getAsDeducedTemplateName(); |
1343 | dumpTemplateName(TN: DTS->getUnderlying(), Label: "underlying"); |
1344 | AddChild(Label: "defaults", DoAddChild: [=] { |
1345 | auto [StartPos, Args] = DTS->getDefaultArguments(); |
1346 | OS << " start "<< StartPos; |
1347 | for (const TemplateArgument &Arg : Args) |
1348 | AddChild(DoAddChild: [=] { Visit(TA: Arg, R: SourceRange()); }); |
1349 | }); |
1350 | return; |
1351 | } |
1352 | // FIXME: Implement these. |
1353 | case TemplateName::OverloadedTemplate: |
1354 | OS << " overloaded"; |
1355 | return; |
1356 | case TemplateName::AssumedTemplate: |
1357 | OS << " assumed"; |
1358 | return; |
1359 | case TemplateName::SubstTemplateTemplateParmPack: |
1360 | OS << " subst_pack"; |
1361 | return; |
1362 | } |
1363 | llvm_unreachable("Unexpected TemplateName Kind"); |
1364 | } |
1365 | |
1366 | void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) { |
1367 | OS << " template"; |
1368 | dumpTemplateArgument(TA); |
1369 | dumpBareTemplateName(TN: TA.getAsTemplate()); |
1370 | } |
1371 | |
1372 | void TextNodeDumper::VisitTemplateExpansionTemplateArgument( |
1373 | const TemplateArgument &TA) { |
1374 | OS << " template expansion"; |
1375 | dumpTemplateArgument(TA); |
1376 | dumpBareTemplateName(TN: TA.getAsTemplateOrTemplatePattern()); |
1377 | } |
1378 | |
1379 | void TextNodeDumper::VisitExpressionTemplateArgument( |
1380 | const TemplateArgument &TA) { |
1381 | OS << " expr"; |
1382 | if (TA.isCanonicalExpr()) |
1383 | OS << " canonical"; |
1384 | dumpTemplateArgument(TA); |
1385 | } |
1386 | |
1387 | void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) { |
1388 | OS << " pack"; |
1389 | dumpTemplateArgument(TA); |
1390 | } |
1391 | |
1392 | static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { |
1393 | if (Node->path_empty()) |
1394 | return; |
1395 | |
1396 | OS << " ("; |
1397 | bool First = true; |
1398 | for (CastExpr::path_const_iterator I = Node->path_begin(), |
1399 | E = Node->path_end(); |
1400 | I != E; ++I) { |
1401 | const CXXBaseSpecifier *Base = *I; |
1402 | if (!First) |
1403 | OS << " -> "; |
1404 | |
1405 | const auto *RD = |
1406 | cast<CXXRecordDecl>(Val: Base->getType()->castAs<RecordType>()->getDecl()); |
1407 | |
1408 | if (Base->isVirtual()) |
1409 | OS << "virtual "; |
1410 | OS << RD->getName(); |
1411 | First = false; |
1412 | } |
1413 | |
1414 | OS << ')'; |
1415 | } |
1416 | |
1417 | void TextNodeDumper::VisitIfStmt(const IfStmt *Node) { |
1418 | if (Node->hasInitStorage()) |
1419 | OS << " has_init"; |
1420 | if (Node->hasVarStorage()) |
1421 | OS << " has_var"; |
1422 | if (Node->hasElseStorage()) |
1423 | OS << " has_else"; |
1424 | if (Node->isConstexpr()) |
1425 | OS << " constexpr"; |
1426 | if (Node->isConsteval()) { |
1427 | OS << " "; |
1428 | if (Node->isNegatedConsteval()) |
1429 | OS << "!"; |
1430 | OS << "consteval"; |
1431 | } |
1432 | } |
1433 | |
1434 | void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) { |
1435 | if (Node->hasInitStorage()) |
1436 | OS << " has_init"; |
1437 | if (Node->hasVarStorage()) |
1438 | OS << " has_var"; |
1439 | } |
1440 | |
1441 | void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) { |
1442 | if (Node->hasVarStorage()) |
1443 | OS << " has_var"; |
1444 | } |
1445 | |
1446 | void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) { |
1447 | OS << " '"<< Node->getName() << "'"; |
1448 | if (Node->isSideEntry()) |
1449 | OS << " side_entry"; |
1450 | } |
1451 | |
1452 | void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) { |
1453 | OS << " '"<< Node->getLabel()->getName() << "'"; |
1454 | dumpPointer(Ptr: Node->getLabel()); |
1455 | } |
1456 | |
1457 | void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) { |
1458 | if (Node->caseStmtIsGNURange()) |
1459 | OS << " gnu_range"; |
1460 | } |
1461 | |
1462 | void clang::TextNodeDumper::VisitReturnStmt(const ReturnStmt *Node) { |
1463 | if (const VarDecl *Cand = Node->getNRVOCandidate()) { |
1464 | OS << " nrvo_candidate("; |
1465 | dumpBareDeclRef(Cand); |
1466 | OS << ")"; |
1467 | } |
1468 | } |
1469 | |
1470 | void clang::TextNodeDumper::VisitCoawaitExpr(const CoawaitExpr *Node) { |
1471 | if (Node->isImplicit()) |
1472 | OS << " implicit"; |
1473 | } |
1474 | |
1475 | void clang::TextNodeDumper::VisitCoreturnStmt(const CoreturnStmt *Node) { |
1476 | if (Node->isImplicit()) |
1477 | OS << " implicit"; |
1478 | } |
1479 | |
1480 | void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) { |
1481 | if (Node->hasAPValueResult()) |
1482 | AddChild(Label: "value", |
1483 | DoAddChild: [=] { Visit(Node->getAPValueResult(), Node->getType()); }); |
1484 | } |
1485 | |
1486 | void TextNodeDumper::VisitCallExpr(const CallExpr *Node) { |
1487 | if (Node->usesADL()) |
1488 | OS << " adl"; |
1489 | if (Node->hasStoredFPFeatures()) |
1490 | printFPOptions(FPO: Node->getFPFeatures()); |
1491 | } |
1492 | |
1493 | void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) { |
1494 | const char *OperatorSpelling = clang::getOperatorSpelling(Operator: Node->getOperator()); |
1495 | if (OperatorSpelling) |
1496 | OS << " '"<< OperatorSpelling << "'"; |
1497 | |
1498 | VisitCallExpr(Node); |
1499 | } |
1500 | |
1501 | void TextNodeDumper::VisitCastExpr(const CastExpr *Node) { |
1502 | OS << " <"; |
1503 | { |
1504 | ColorScope Color(OS, ShowColors, CastColor); |
1505 | OS << Node->getCastKindName(); |
1506 | } |
1507 | dumpBasePath(OS, Node); |
1508 | OS << ">"; |
1509 | if (Node->hasStoredFPFeatures()) |
1510 | printFPOptions(FPO: Node->getFPFeatures()); |
1511 | } |
1512 | |
1513 | void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) { |
1514 | VisitCastExpr(Node); |
1515 | if (Node->isPartOfExplicitCast()) |
1516 | OS << " part_of_explicit_cast"; |
1517 | } |
1518 | |
1519 | void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { |
1520 | OS << " "; |
1521 | dumpBareDeclRef(Node->getDecl()); |
1522 | dumpNestedNameSpecifier(NNS: Node->getQualifier()); |
1523 | if (Node->getDecl() != Node->getFoundDecl()) { |
1524 | OS << " ("; |
1525 | dumpBareDeclRef(Node->getFoundDecl()); |
1526 | OS << ")"; |
1527 | } |
1528 | switch (Node->isNonOdrUse()) { |
1529 | case NOUR_None: break; |
1530 | case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break; |
1531 | case NOUR_Constant: OS << " non_odr_use_constant"; break; |
1532 | case NOUR_Discarded: OS << " non_odr_use_discarded"; break; |
1533 | } |
1534 | if (Node->isCapturedByCopyInLambdaWithExplicitObjectParameter()) |
1535 | OS << " dependent_capture"; |
1536 | else if (Node->refersToEnclosingVariableOrCapture()) |
1537 | OS << " refers_to_enclosing_variable_or_capture"; |
1538 | |
1539 | if (Node->isImmediateEscalating()) |
1540 | OS << " immediate-escalating"; |
1541 | } |
1542 | |
1543 | void clang::TextNodeDumper::VisitDependentScopeDeclRefExpr( |
1544 | const DependentScopeDeclRefExpr *Node) { |
1545 | |
1546 | dumpNestedNameSpecifier(NNS: Node->getQualifier()); |
1547 | } |
1548 | |
1549 | void TextNodeDumper::VisitUnresolvedLookupExpr( |
1550 | const UnresolvedLookupExpr *Node) { |
1551 | OS << " ("; |
1552 | if (!Node->requiresADL()) |
1553 | OS << "no "; |
1554 | OS << "ADL) = '"<< Node->getName() << '\''; |
1555 | |
1556 | UnresolvedLookupExpr::decls_iterator I = Node->decls_begin(), |
1557 | E = Node->decls_end(); |
1558 | if (I == E) |
1559 | OS << " empty"; |
1560 | for (; I != E; ++I) |
1561 | dumpPointer(Ptr: *I); |
1562 | } |
1563 | |
1564 | void TextNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { |
1565 | { |
1566 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
1567 | OS << " "<< Node->getDecl()->getDeclKindName() << "Decl"; |
1568 | } |
1569 | OS << "='"<< *Node->getDecl() << "'"; |
1570 | dumpPointer(Ptr: Node->getDecl()); |
1571 | if (Node->isFreeIvar()) |
1572 | OS << " isFreeIvar"; |
1573 | } |
1574 | |
1575 | void TextNodeDumper::VisitSYCLUniqueStableNameExpr( |
1576 | const SYCLUniqueStableNameExpr *Node) { |
1577 | dumpType(T: Node->getTypeSourceInfo()->getType()); |
1578 | } |
1579 | |
1580 | void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { |
1581 | OS << " "<< PredefinedExpr::getIdentKindName(IK: Node->getIdentKind()); |
1582 | } |
1583 | |
1584 | void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { |
1585 | ColorScope Color(OS, ShowColors, ValueColor); |
1586 | OS << " "<< Node->getValue(); |
1587 | } |
1588 | |
1589 | void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) { |
1590 | bool isSigned = Node->getType()->isSignedIntegerType(); |
1591 | ColorScope Color(OS, ShowColors, ValueColor); |
1592 | OS << " "<< toString(Node->getValue(), 10, isSigned); |
1593 | } |
1594 | |
1595 | void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) { |
1596 | ColorScope Color(OS, ShowColors, ValueColor); |
1597 | OS << " "<< Node->getValueAsString(/*Radix=*/10); |
1598 | } |
1599 | |
1600 | void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) { |
1601 | ColorScope Color(OS, ShowColors, ValueColor); |
1602 | OS << " "<< Node->getValueAsApproximateDouble(); |
1603 | } |
1604 | |
1605 | void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) { |
1606 | ColorScope Color(OS, ShowColors, ValueColor); |
1607 | OS << " "; |
1608 | Str->outputString(OS); |
1609 | } |
1610 | |
1611 | void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) { |
1612 | if (auto *Field = ILE->getInitializedFieldInUnion()) { |
1613 | OS << " field "; |
1614 | dumpBareDeclRef(Field); |
1615 | } |
1616 | } |
1617 | |
1618 | void TextNodeDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) { |
1619 | if (E->isResultDependent()) |
1620 | OS << " result_dependent"; |
1621 | } |
1622 | |
1623 | void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) { |
1624 | OS << " "<< (Node->isPostfix() ? "postfix": "prefix") << " '" |
1625 | << UnaryOperator::getOpcodeStr(Op: Node->getOpcode()) << "'"; |
1626 | if (!Node->canOverflow()) |
1627 | OS << " cannot overflow"; |
1628 | if (Node->hasStoredFPFeatures()) |
1629 | printFPOptions(FPO: Node->getStoredFPFeatures()); |
1630 | } |
1631 | |
1632 | void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr( |
1633 | const UnaryExprOrTypeTraitExpr *Node) { |
1634 | OS << " "<< getTraitSpelling(T: Node->getKind()); |
1635 | |
1636 | if (Node->isArgumentType()) |
1637 | dumpType(T: Node->getArgumentType()); |
1638 | } |
1639 | |
1640 | void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) { |
1641 | OS << " "<< (Node->isArrow() ? "->": ".") << *Node->getMemberDecl(); |
1642 | dumpPointer(Ptr: Node->getMemberDecl()); |
1643 | dumpNestedNameSpecifier(NNS: Node->getQualifier()); |
1644 | switch (Node->isNonOdrUse()) { |
1645 | case NOUR_None: break; |
1646 | case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break; |
1647 | case NOUR_Constant: OS << " non_odr_use_constant"; break; |
1648 | case NOUR_Discarded: OS << " non_odr_use_discarded"; break; |
1649 | } |
1650 | } |
1651 | |
1652 | void TextNodeDumper::VisitExtVectorElementExpr( |
1653 | const ExtVectorElementExpr *Node) { |
1654 | OS << " "<< Node->getAccessor().getNameStart(); |
1655 | } |
1656 | |
1657 | void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) { |
1658 | OS << " '"<< BinaryOperator::getOpcodeStr(Op: Node->getOpcode()) << "'"; |
1659 | if (Node->hasStoredFPFeatures()) |
1660 | printFPOptions(FPO: Node->getStoredFPFeatures()); |
1661 | } |
1662 | |
1663 | void TextNodeDumper::VisitCompoundAssignOperator( |
1664 | const CompoundAssignOperator *Node) { |
1665 | OS << " '"<< BinaryOperator::getOpcodeStr(Node->getOpcode()) |
1666 | << "' ComputeLHSTy="; |
1667 | dumpBareType(T: Node->getComputationLHSType()); |
1668 | OS << " ComputeResultTy="; |
1669 | dumpBareType(T: Node->getComputationResultType()); |
1670 | if (Node->hasStoredFPFeatures()) |
1671 | printFPOptions(FPO: Node->getStoredFPFeatures()); |
1672 | } |
1673 | |
1674 | void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { |
1675 | OS << " "<< Node->getLabel()->getName(); |
1676 | dumpPointer(Ptr: Node->getLabel()); |
1677 | } |
1678 | |
1679 | void TextNodeDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) { |
1680 | OS << " "<< Node->getCastName() << "<" |
1681 | << Node->getTypeAsWritten().getAsString() << ">" |
1682 | << " <"<< Node->getCastKindName(); |
1683 | dumpBasePath(OS, Node); |
1684 | OS << ">"; |
1685 | } |
1686 | |
1687 | void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) { |
1688 | OS << " "<< (Node->getValue() ? "true": "false"); |
1689 | } |
1690 | |
1691 | void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) { |
1692 | if (Node->isImplicit()) |
1693 | OS << " implicit"; |
1694 | if (Node->isCapturedByCopyInLambdaWithExplicitObjectParameter()) |
1695 | OS << " dependent_capture"; |
1696 | OS << " this"; |
1697 | } |
1698 | |
1699 | void TextNodeDumper::VisitCXXFunctionalCastExpr( |
1700 | const CXXFunctionalCastExpr *Node) { |
1701 | OS << " functional cast to "<< Node->getTypeAsWritten().getAsString() << " <" |
1702 | << Node->getCastKindName() << ">"; |
1703 | if (Node->hasStoredFPFeatures()) |
1704 | printFPOptions(FPO: Node->getFPFeatures()); |
1705 | } |
1706 | |
1707 | void TextNodeDumper::VisitCXXStaticCastExpr(const CXXStaticCastExpr *Node) { |
1708 | VisitCXXNamedCastExpr(Node); |
1709 | if (Node->hasStoredFPFeatures()) |
1710 | printFPOptions(FPO: Node->getFPFeatures()); |
1711 | } |
1712 | |
1713 | void TextNodeDumper::VisitCXXUnresolvedConstructExpr( |
1714 | const CXXUnresolvedConstructExpr *Node) { |
1715 | dumpType(T: Node->getTypeAsWritten()); |
1716 | if (Node->isListInitialization()) |
1717 | OS << " list"; |
1718 | } |
1719 | |
1720 | void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { |
1721 | CXXConstructorDecl *Ctor = Node->getConstructor(); |
1722 | dumpType(T: Ctor->getType()); |
1723 | if (Node->isElidable()) |
1724 | OS << " elidable"; |
1725 | if (Node->isListInitialization()) |
1726 | OS << " list"; |
1727 | if (Node->isStdInitListInitialization()) |
1728 | OS << " std::initializer_list"; |
1729 | if (Node->requiresZeroInitialization()) |
1730 | OS << " zeroing"; |
1731 | if (Node->isImmediateEscalating()) |
1732 | OS << " immediate-escalating"; |
1733 | } |
1734 | |
1735 | void TextNodeDumper::VisitCXXBindTemporaryExpr( |
1736 | const CXXBindTemporaryExpr *Node) { |
1737 | OS << " (CXXTemporary"; |
1738 | dumpPointer(Ptr: Node); |
1739 | OS << ")"; |
1740 | } |
1741 | |
1742 | void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) { |
1743 | if (Node->isGlobalNew()) |
1744 | OS << " global"; |
1745 | if (Node->isArray()) |
1746 | OS << " array"; |
1747 | if (Node->getOperatorNew()) { |
1748 | OS << ' '; |
1749 | dumpBareDeclRef(Node->getOperatorNew()); |
1750 | } |
1751 | // We could dump the deallocation function used in case of error, but it's |
1752 | // usually not that interesting. |
1753 | } |
1754 | |
1755 | void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) { |
1756 | if (Node->isGlobalDelete()) |
1757 | OS << " global"; |
1758 | if (Node->isArrayForm()) |
1759 | OS << " array"; |
1760 | if (Node->getOperatorDelete()) { |
1761 | OS << ' '; |
1762 | dumpBareDeclRef(Node->getOperatorDelete()); |
1763 | } |
1764 | } |
1765 | |
1766 | void TextNodeDumper::VisitTypeTraitExpr(const TypeTraitExpr *Node) { |
1767 | OS << " "<< getTraitSpelling(T: Node->getTrait()); |
1768 | } |
1769 | |
1770 | void TextNodeDumper::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node) { |
1771 | OS << " "<< getTraitSpelling(T: Node->getTrait()); |
1772 | } |
1773 | |
1774 | void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) { |
1775 | OS << " "<< getTraitSpelling(T: Node->getTrait()); |
1776 | } |
1777 | |
1778 | void TextNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { |
1779 | if (Node->hasRewrittenInit()) |
1780 | OS << " has rewritten init"; |
1781 | } |
1782 | |
1783 | void TextNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { |
1784 | if (Node->hasRewrittenInit()) |
1785 | OS << " has rewritten init"; |
1786 | } |
1787 | |
1788 | void TextNodeDumper::VisitMaterializeTemporaryExpr( |
1789 | const MaterializeTemporaryExpr *Node) { |
1790 | if (const ValueDecl *VD = Node->getExtendingDecl()) { |
1791 | OS << " extended by "; |
1792 | dumpBareDeclRef(VD); |
1793 | } |
1794 | } |
1795 | |
1796 | void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) { |
1797 | for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) |
1798 | dumpCleanupObject(C: Node->getObject(i)); |
1799 | } |
1800 | |
1801 | void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { |
1802 | dumpPointer(Ptr: Node->getPack()); |
1803 | dumpName(ND: Node->getPack()); |
1804 | } |
1805 | |
1806 | void TextNodeDumper::VisitCXXDependentScopeMemberExpr( |
1807 | const CXXDependentScopeMemberExpr *Node) { |
1808 | OS << " "<< (Node->isArrow() ? "->": ".") << Node->getMember(); |
1809 | } |
1810 | |
1811 | void TextNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { |
1812 | OS << " selector="; |
1813 | Node->getSelector().print(OS); |
1814 | switch (Node->getReceiverKind()) { |
1815 | case ObjCMessageExpr::Instance: |
1816 | break; |
1817 | |
1818 | case ObjCMessageExpr::Class: |
1819 | OS << " class="; |
1820 | dumpBareType(T: Node->getClassReceiver()); |
1821 | break; |
1822 | |
1823 | case ObjCMessageExpr::SuperInstance: |
1824 | OS << " super (instance)"; |
1825 | break; |
1826 | |
1827 | case ObjCMessageExpr::SuperClass: |
1828 | OS << " super (class)"; |
1829 | break; |
1830 | } |
1831 | } |
1832 | |
1833 | void TextNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { |
1834 | if (auto *BoxingMethod = Node->getBoxingMethod()) { |
1835 | OS << " selector="; |
1836 | BoxingMethod->getSelector().print(OS); |
1837 | } |
1838 | } |
1839 | |
1840 | void TextNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { |
1841 | if (!Node->getCatchParamDecl()) |
1842 | OS << " catch all"; |
1843 | } |
1844 | |
1845 | void TextNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { |
1846 | dumpType(T: Node->getEncodedType()); |
1847 | } |
1848 | |
1849 | void TextNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) { |
1850 | OS << " "; |
1851 | Node->getSelector().print(OS); |
1852 | } |
1853 | |
1854 | void TextNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) { |
1855 | OS << ' ' << *Node->getProtocol(); |
1856 | } |
1857 | |
1858 | void TextNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { |
1859 | if (Node->isImplicitProperty()) { |
1860 | OS << " Kind=MethodRef Getter=\""; |
1861 | if (Node->getImplicitPropertyGetter()) |
1862 | Node->getImplicitPropertyGetter()->getSelector().print(OS); |
1863 | else |
1864 | OS << "(null)"; |
1865 | |
1866 | OS << "\" Setter=\""; |
1867 | if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) |
1868 | Setter->getSelector().print(OS); |
1869 | else |
1870 | OS << "(null)"; |
1871 | OS << "\""; |
1872 | } else { |
1873 | OS << " Kind=PropertyRef Property=\""<< *Node->getExplicitProperty() |
1874 | << '"'; |
1875 | } |
1876 | |
1877 | if (Node->isSuperReceiver()) |
1878 | OS << " super"; |
1879 | |
1880 | OS << " Messaging="; |
1881 | if (Node->isMessagingGetter() && Node->isMessagingSetter()) |
1882 | OS << "Getter&Setter"; |
1883 | else if (Node->isMessagingGetter()) |
1884 | OS << "Getter"; |
1885 | else if (Node->isMessagingSetter()) |
1886 | OS << "Setter"; |
1887 | } |
1888 | |
1889 | void TextNodeDumper::VisitObjCSubscriptRefExpr( |
1890 | const ObjCSubscriptRefExpr *Node) { |
1891 | if (Node->isArraySubscriptRefExpr()) |
1892 | OS << " Kind=ArraySubscript GetterForArray=\""; |
1893 | else |
1894 | OS << " Kind=DictionarySubscript GetterForDictionary=\""; |
1895 | if (Node->getAtIndexMethodDecl()) |
1896 | Node->getAtIndexMethodDecl()->getSelector().print(OS); |
1897 | else |
1898 | OS << "(null)"; |
1899 | |
1900 | if (Node->isArraySubscriptRefExpr()) |
1901 | OS << "\" SetterForArray=\""; |
1902 | else |
1903 | OS << "\" SetterForDictionary=\""; |
1904 | if (Node->setAtIndexMethodDecl()) |
1905 | Node->setAtIndexMethodDecl()->getSelector().print(OS); |
1906 | else |
1907 | OS << "(null)"; |
1908 | } |
1909 | |
1910 | void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) { |
1911 | OS << " "<< (Node->getValue() ? "__objc_yes": "__objc_no"); |
1912 | } |
1913 | |
1914 | void TextNodeDumper::VisitOMPIteratorExpr(const OMPIteratorExpr *Node) { |
1915 | OS << " "; |
1916 | for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) { |
1917 | Visit(D: Node->getIteratorDecl(I)); |
1918 | OS << " = "; |
1919 | const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I); |
1920 | OS << " begin "; |
1921 | Visit(Range.Begin); |
1922 | OS << " end "; |
1923 | Visit(Range.End); |
1924 | if (Range.Step) { |
1925 | OS << " step "; |
1926 | Visit(Range.Step); |
1927 | } |
1928 | } |
1929 | } |
1930 | |
1931 | void TextNodeDumper::VisitConceptSpecializationExpr( |
1932 | const ConceptSpecializationExpr *Node) { |
1933 | OS << " "; |
1934 | dumpBareDeclRef(Node->getFoundDecl()); |
1935 | } |
1936 | |
1937 | void TextNodeDumper::VisitRequiresExpr( |
1938 | const RequiresExpr *Node) { |
1939 | if (!Node->isValueDependent()) |
1940 | OS << (Node->isSatisfied() ? " satisfied": " unsatisfied"); |
1941 | } |
1942 | |
1943 | void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) { |
1944 | if (T->isSpelledAsLValue()) |
1945 | OS << " written as lvalue reference"; |
1946 | } |
1947 | |
1948 | void TextNodeDumper::VisitArrayType(const ArrayType *T) { |
1949 | switch (T->getSizeModifier()) { |
1950 | case ArraySizeModifier::Normal: |
1951 | break; |
1952 | case ArraySizeModifier::Static: |
1953 | OS << " static"; |
1954 | break; |
1955 | case ArraySizeModifier::Star: |
1956 | OS << " *"; |
1957 | break; |
1958 | } |
1959 | OS << " "<< T->getIndexTypeQualifiers().getAsString(); |
1960 | } |
1961 | |
1962 | void TextNodeDumper::VisitConstantArrayType(const ConstantArrayType *T) { |
1963 | OS << " "<< T->getSize(); |
1964 | VisitArrayType(T); |
1965 | } |
1966 | |
1967 | void TextNodeDumper::VisitVariableArrayType(const VariableArrayType *T) { |
1968 | VisitArrayType(T); |
1969 | } |
1970 | |
1971 | void TextNodeDumper::VisitDependentSizedArrayType( |
1972 | const DependentSizedArrayType *T) { |
1973 | VisitArrayType(T); |
1974 | } |
1975 | |
1976 | void TextNodeDumper::VisitDependentSizedExtVectorType( |
1977 | const DependentSizedExtVectorType *T) { |
1978 | OS << " "; |
1979 | dumpLocation(Loc: T->getAttributeLoc()); |
1980 | } |
1981 | |
1982 | void TextNodeDumper::VisitVectorType(const VectorType *T) { |
1983 | switch (T->getVectorKind()) { |
1984 | case VectorKind::Generic: |
1985 | break; |
1986 | case VectorKind::AltiVecVector: |
1987 | OS << " altivec"; |
1988 | break; |
1989 | case VectorKind::AltiVecPixel: |
1990 | OS << " altivec pixel"; |
1991 | break; |
1992 | case VectorKind::AltiVecBool: |
1993 | OS << " altivec bool"; |
1994 | break; |
1995 | case VectorKind::Neon: |
1996 | OS << " neon"; |
1997 | break; |
1998 | case VectorKind::NeonPoly: |
1999 | OS << " neon poly"; |
2000 | break; |
2001 | case VectorKind::SveFixedLengthData: |
2002 | OS << " fixed-length sve data vector"; |
2003 | break; |
2004 | case VectorKind::SveFixedLengthPredicate: |
2005 | OS << " fixed-length sve predicate vector"; |
2006 | break; |
2007 | case VectorKind::RVVFixedLengthData: |
2008 | OS << " fixed-length rvv data vector"; |
2009 | break; |
2010 | case VectorKind::RVVFixedLengthMask: |
2011 | case VectorKind::RVVFixedLengthMask_1: |
2012 | case VectorKind::RVVFixedLengthMask_2: |
2013 | case VectorKind::RVVFixedLengthMask_4: |
2014 | OS << " fixed-length rvv mask vector"; |
2015 | break; |
2016 | } |
2017 | OS << " "<< T->getNumElements(); |
2018 | } |
2019 | |
2020 | void TextNodeDumper::VisitFunctionType(const FunctionType *T) { |
2021 | auto EI = T->getExtInfo(); |
2022 | if (EI.getNoReturn()) |
2023 | OS << " noreturn"; |
2024 | if (EI.getProducesResult()) |
2025 | OS << " produces_result"; |
2026 | if (EI.getHasRegParm()) |
2027 | OS << " regparm "<< EI.getRegParm(); |
2028 | OS << " "<< FunctionType::getNameForCallConv(CC: EI.getCC()); |
2029 | } |
2030 | |
2031 | void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) { |
2032 | auto EPI = T->getExtProtoInfo(); |
2033 | if (EPI.HasTrailingReturn) |
2034 | OS << " trailing_return"; |
2035 | if (T->isConst()) |
2036 | OS << " const"; |
2037 | if (T->isVolatile()) |
2038 | OS << " volatile"; |
2039 | if (T->isRestrict()) |
2040 | OS << " restrict"; |
2041 | if (T->getExtProtoInfo().Variadic) |
2042 | OS << " variadic"; |
2043 | switch (EPI.RefQualifier) { |
2044 | case RQ_None: |
2045 | break; |
2046 | case RQ_LValue: |
2047 | OS << " &"; |
2048 | break; |
2049 | case RQ_RValue: |
2050 | OS << " &&"; |
2051 | break; |
2052 | } |
2053 | |
2054 | switch (EPI.ExceptionSpec.Type) { |
2055 | case EST_None: |
2056 | break; |
2057 | case EST_DynamicNone: |
2058 | OS << " exceptionspec_dynamic_none"; |
2059 | break; |
2060 | case EST_Dynamic: |
2061 | OS << " exceptionspec_dynamic"; |
2062 | break; |
2063 | case EST_MSAny: |
2064 | OS << " exceptionspec_ms_any"; |
2065 | break; |
2066 | case EST_NoThrow: |
2067 | OS << " exceptionspec_nothrow"; |
2068 | break; |
2069 | case EST_BasicNoexcept: |
2070 | OS << " exceptionspec_basic_noexcept"; |
2071 | break; |
2072 | case EST_DependentNoexcept: |
2073 | OS << " exceptionspec_dependent_noexcept"; |
2074 | break; |
2075 | case EST_NoexceptFalse: |
2076 | OS << " exceptionspec_noexcept_false"; |
2077 | break; |
2078 | case EST_NoexceptTrue: |
2079 | OS << " exceptionspec_noexcept_true"; |
2080 | break; |
2081 | case EST_Unevaluated: |
2082 | OS << " exceptionspec_unevaluated"; |
2083 | break; |
2084 | case EST_Uninstantiated: |
2085 | OS << " exceptionspec_uninstantiated"; |
2086 | break; |
2087 | case EST_Unparsed: |
2088 | OS << " exceptionspec_unparsed"; |
2089 | break; |
2090 | } |
2091 | if (!EPI.ExceptionSpec.Exceptions.empty()) { |
2092 | AddChild(DoAddChild: [=] { |
2093 | OS << "Exceptions:"; |
2094 | for (unsigned I = 0, N = EPI.ExceptionSpec.Exceptions.size(); I != N; |
2095 | ++I) { |
2096 | if (I) |
2097 | OS << ","; |
2098 | dumpType(T: EPI.ExceptionSpec.Exceptions[I]); |
2099 | } |
2100 | }); |
2101 | } |
2102 | if (EPI.ExceptionSpec.NoexceptExpr) { |
2103 | AddChild(DoAddChild: [=] { |
2104 | OS << "NoexceptExpr: "; |
2105 | Visit(EPI.ExceptionSpec.NoexceptExpr); |
2106 | }); |
2107 | } |
2108 | dumpDeclRef(D: EPI.ExceptionSpec.SourceDecl, Label: "ExceptionSourceDecl"); |
2109 | dumpDeclRef(D: EPI.ExceptionSpec.SourceTemplate, Label: "ExceptionSourceTemplate"); |
2110 | |
2111 | // FIXME: Consumed parameters. |
2112 | VisitFunctionType(T); |
2113 | } |
2114 | |
2115 | void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { |
2116 | dumpDeclRef(T->getDecl()); |
2117 | } |
2118 | |
2119 | void TextNodeDumper::VisitUsingType(const UsingType *T) { |
2120 | dumpDeclRef(T->getFoundDecl()); |
2121 | if (!T->typeMatchesDecl()) |
2122 | OS << " divergent"; |
2123 | } |
2124 | |
2125 | void TextNodeDumper::VisitTypedefType(const TypedefType *T) { |
2126 | dumpDeclRef(T->getDecl()); |
2127 | if (!T->typeMatchesDecl()) |
2128 | OS << " divergent"; |
2129 | } |
2130 | |
2131 | void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) { |
2132 | switch (T->getUTTKind()) { |
2133 | #define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ |
2134 | case UnaryTransformType::Enum: \ |
2135 | OS << " " #Trait; \ |
2136 | break; |
2137 | #include "clang/Basic/TransformTypeTraits.def" |
2138 | } |
2139 | } |
2140 | |
2141 | void TextNodeDumper::VisitTagType(const TagType *T) { |
2142 | dumpDeclRef(T->getDecl()); |
2143 | } |
2144 | |
2145 | void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { |
2146 | OS << " depth "<< T->getDepth() << " index "<< T->getIndex(); |
2147 | if (T->isParameterPack()) |
2148 | OS << " pack"; |
2149 | dumpDeclRef(T->getDecl()); |
2150 | } |
2151 | |
2152 | void TextNodeDumper::VisitSubstTemplateTypeParmType( |
2153 | const SubstTemplateTypeParmType *T) { |
2154 | dumpDeclRef(D: T->getAssociatedDecl()); |
2155 | VisitTemplateTypeParmDecl(D: T->getReplacedParameter()); |
2156 | if (auto PackIndex = T->getPackIndex()) |
2157 | OS << " pack_index "<< *PackIndex; |
2158 | if (T->getFinal()) |
2159 | OS << " final"; |
2160 | } |
2161 | |
2162 | void TextNodeDumper::VisitSubstTemplateTypeParmPackType( |
2163 | const SubstTemplateTypeParmPackType *T) { |
2164 | dumpDeclRef(D: T->getAssociatedDecl()); |
2165 | VisitTemplateTypeParmDecl(D: T->getReplacedParameter()); |
2166 | } |
2167 | |
2168 | void TextNodeDumper::VisitAutoType(const AutoType *T) { |
2169 | if (T->isDecltypeAuto()) |
2170 | OS << " decltype(auto)"; |
2171 | if (!T->isDeduced()) |
2172 | OS << " undeduced"; |
2173 | if (T->isConstrained()) |
2174 | dumpDeclRef(T->getTypeConstraintConcept()); |
2175 | } |
2176 | |
2177 | void TextNodeDumper::VisitDeducedTemplateSpecializationType( |
2178 | const DeducedTemplateSpecializationType *T) { |
2179 | dumpTemplateName(TN: T->getTemplateName(), Label: "name"); |
2180 | } |
2181 | |
2182 | void TextNodeDumper::VisitTemplateSpecializationType( |
2183 | const TemplateSpecializationType *T) { |
2184 | if (T->isTypeAlias()) |
2185 | OS << " alias"; |
2186 | dumpTemplateName(TN: T->getTemplateName(), Label: "name"); |
2187 | } |
2188 | |
2189 | void TextNodeDumper::VisitInjectedClassNameType( |
2190 | const InjectedClassNameType *T) { |
2191 | dumpDeclRef(T->getDecl()); |
2192 | } |
2193 | |
2194 | void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) { |
2195 | dumpDeclRef(T->getDecl()); |
2196 | } |
2197 | |
2198 | void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) { |
2199 | if (auto N = T->getNumExpansions()) |
2200 | OS << " expansions "<< *N; |
2201 | } |
2202 | |
2203 | void TextNodeDumper::VisitTypeLoc(TypeLoc TL) { |
2204 | // By default, add extra Type details with no extra loc info. |
2205 | TypeVisitor<TextNodeDumper>::Visit(T: TL.getTypePtr()); |
2206 | } |
2207 | // FIXME: override behavior for TypeLocs that have interesting location |
2208 | // information, such as the qualifier in ElaboratedTypeLoc. |
2209 | |
2210 | void TextNodeDumper::VisitLabelDecl(const LabelDecl *D) { dumpName(D); } |
2211 | |
2212 | void TextNodeDumper::VisitTypedefDecl(const TypedefDecl *D) { |
2213 | dumpName(D); |
2214 | dumpType(T: D->getUnderlyingType()); |
2215 | if (D->isModulePrivate()) |
2216 | OS << " __module_private__"; |
2217 | } |
2218 | |
2219 | void TextNodeDumper::VisitEnumDecl(const EnumDecl *D) { |
2220 | if (D->isScoped()) { |
2221 | if (D->isScopedUsingClassTag()) |
2222 | OS << " class"; |
2223 | else |
2224 | OS << " struct"; |
2225 | } |
2226 | dumpName(D); |
2227 | if (D->isModulePrivate()) |
2228 | OS << " __module_private__"; |
2229 | if (D->isFixed()) |
2230 | dumpType(T: D->getIntegerType()); |
2231 | |
2232 | if (const auto *Instance = D->getInstantiatedFromMemberEnum()) { |
2233 | OS << " instantiated_from"; |
2234 | dumpPointer(Ptr: Instance); |
2235 | } |
2236 | } |
2237 | |
2238 | void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) { |
2239 | OS << ' ' << D->getKindName(); |
2240 | dumpName(D); |
2241 | if (D->isModulePrivate()) |
2242 | OS << " __module_private__"; |
2243 | if (D->isCompleteDefinition()) |
2244 | OS << " definition"; |
2245 | } |
2246 | |
2247 | void TextNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { |
2248 | dumpName(D); |
2249 | dumpType(T: D->getType()); |
2250 | } |
2251 | |
2252 | void TextNodeDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { |
2253 | dumpName(D); |
2254 | dumpType(T: D->getType()); |
2255 | |
2256 | for (const auto *Child : D->chain()) |
2257 | dumpDeclRef(Child); |
2258 | } |
2259 | |
2260 | void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { |
2261 | dumpName(D); |
2262 | dumpType(T: D->getType()); |
2263 | dumpTemplateSpecializationKind(TSK: D->getTemplateSpecializationKind()); |
2264 | |
2265 | StorageClass SC = D->getStorageClass(); |
2266 | if (SC != SC_None) |
2267 | OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); |
2268 | if (D->isInlineSpecified()) |
2269 | OS << " inline"; |
2270 | if (D->isVirtualAsWritten()) |
2271 | OS << " virtual"; |
2272 | if (D->isModulePrivate()) |
2273 | OS << " __module_private__"; |
2274 | |
2275 | if (D->isPureVirtual()) |
2276 | OS << " pure"; |
2277 | if (D->isDefaulted()) { |
2278 | OS << " default"; |
2279 | if (D->isDeleted()) |
2280 | OS << "_delete"; |
2281 | } |
2282 | if (D->isDeletedAsWritten()) |
2283 | OS << " delete"; |
2284 | if (D->isTrivial()) |
2285 | OS << " trivial"; |
2286 | |
2287 | if (const StringLiteral *M = D->getDeletedMessage()) |
2288 | AddChild(Label: "delete message", DoAddChild: [=] { Visit(M); }); |
2289 | |
2290 | if (D->isIneligibleOrNotSelected()) |
2291 | OS << (isa<CXXDestructorDecl>(Val: D) ? " not_selected": " ineligible"); |
2292 | |
2293 | if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) { |
2294 | FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); |
2295 | switch (EPI.ExceptionSpec.Type) { |
2296 | default: |
2297 | break; |
2298 | case EST_Unevaluated: |
2299 | OS << " noexcept-unevaluated "<< EPI.ExceptionSpec.SourceDecl; |
2300 | break; |
2301 | case EST_Uninstantiated: |
2302 | OS << " noexcept-uninstantiated "<< EPI.ExceptionSpec.SourceTemplate; |
2303 | break; |
2304 | } |
2305 | } |
2306 | |
2307 | if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: D)) { |
2308 | if (MD->size_overridden_methods() != 0) { |
2309 | auto dumpOverride = [=](const CXXMethodDecl *D) { |
2310 | SplitQualType T_split = D->getType().split(); |
2311 | OS << D << " "<< D->getParent()->getName() << "::"<< D->getDeclName() |
2312 | << " '"<< QualType::getAsString(split: T_split, Policy: PrintPolicy) << "'"; |
2313 | }; |
2314 | |
2315 | AddChild(DoAddChild: [=] { |
2316 | auto Overrides = MD->overridden_methods(); |
2317 | OS << "Overrides: [ "; |
2318 | dumpOverride(*Overrides.begin()); |
2319 | for (const auto *Override : llvm::drop_begin(RangeOrContainer&: Overrides)) { |
2320 | OS << ", "; |
2321 | dumpOverride(Override); |
2322 | } |
2323 | OS << " ]"; |
2324 | }); |
2325 | } |
2326 | } |
2327 | |
2328 | if (!D->isInlineSpecified() && D->isInlined()) { |
2329 | OS << " implicit-inline"; |
2330 | } |
2331 | // Since NumParams comes from the FunctionProtoType of the FunctionDecl and |
2332 | // the Params are set later, it is possible for a dump during debugging to |
2333 | // encounter a FunctionDecl that has been created but hasn't been assigned |
2334 | // ParmVarDecls yet. |
2335 | if (!D->param_empty() && !D->param_begin()) |
2336 | OS << " <<<NULL params x "<< D->getNumParams() << ">>>"; |
2337 | |
2338 | if (const auto *Instance = D->getInstantiatedFromMemberFunction()) { |
2339 | OS << " instantiated_from"; |
2340 | dumpPointer(Ptr: Instance); |
2341 | } |
2342 | } |
2343 | |
2344 | void TextNodeDumper::VisitCXXDeductionGuideDecl( |
2345 | const CXXDeductionGuideDecl *D) { |
2346 | VisitFunctionDecl(D); |
2347 | switch (D->getDeductionCandidateKind()) { |
2348 | case DeductionCandidate::Normal: |
2349 | case DeductionCandidate::Copy: |
2350 | return; |
2351 | case DeductionCandidate::Aggregate: |
2352 | OS << " aggregate "; |
2353 | break; |
2354 | } |
2355 | } |
2356 | |
2357 | void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl( |
2358 | const LifetimeExtendedTemporaryDecl *D) { |
2359 | OS << " extended by "; |
2360 | dumpBareDeclRef(D->getExtendingDecl()); |
2361 | OS << " mangling "; |
2362 | { |
2363 | ColorScope Color(OS, ShowColors, ValueColor); |
2364 | OS << D->getManglingNumber(); |
2365 | } |
2366 | } |
2367 | |
2368 | void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) { |
2369 | dumpName(D); |
2370 | dumpType(T: D->getType()); |
2371 | if (D->isMutable()) |
2372 | OS << " mutable"; |
2373 | if (D->isModulePrivate()) |
2374 | OS << " __module_private__"; |
2375 | } |
2376 | |
2377 | void TextNodeDumper::VisitVarDecl(const VarDecl *D) { |
2378 | dumpNestedNameSpecifier(NNS: D->getQualifier()); |
2379 | dumpName(D); |
2380 | if (const auto *P = dyn_cast<ParmVarDecl>(Val: D); |
2381 | P && P->isExplicitObjectParameter()) |
2382 | OS << " this"; |
2383 | |
2384 | dumpType(T: D->getType()); |
2385 | dumpTemplateSpecializationKind(TSK: D->getTemplateSpecializationKind()); |
2386 | StorageClass SC = D->getStorageClass(); |
2387 | if (SC != SC_None) |
2388 | OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); |
2389 | switch (D->getTLSKind()) { |
2390 | case VarDecl::TLS_None: |
2391 | break; |
2392 | case VarDecl::TLS_Static: |
2393 | OS << " tls"; |
2394 | break; |
2395 | case VarDecl::TLS_Dynamic: |
2396 | OS << " tls_dynamic"; |
2397 | break; |
2398 | } |
2399 | if (D->isModulePrivate()) |
2400 | OS << " __module_private__"; |
2401 | if (D->isNRVOVariable()) |
2402 | OS << " nrvo"; |
2403 | if (D->isInline()) |
2404 | OS << " inline"; |
2405 | if (D->isConstexpr()) |
2406 | OS << " constexpr"; |
2407 | if (D->hasInit()) { |
2408 | switch (D->getInitStyle()) { |
2409 | case VarDecl::CInit: |
2410 | OS << " cinit"; |
2411 | break; |
2412 | case VarDecl::CallInit: |
2413 | OS << " callinit"; |
2414 | break; |
2415 | case VarDecl::ListInit: |
2416 | OS << " listinit"; |
2417 | break; |
2418 | case VarDecl::ParenListInit: |
2419 | OS << " parenlistinit"; |
2420 | } |
2421 | } |
2422 | if (D->needsDestruction(Ctx: D->getASTContext())) |
2423 | OS << " destroyed"; |
2424 | if (D->isParameterPack()) |
2425 | OS << " pack"; |
2426 | |
2427 | if (D->hasInit()) { |
2428 | const Expr *E = D->getInit(); |
2429 | // Only dump the value of constexpr VarDecls for now. |
2430 | if (E && !E->isValueDependent() && D->isConstexpr() && |
2431 | !D->getType()->isDependentType()) { |
2432 | const APValue *Value = D->evaluateValue(); |
2433 | if (Value) |
2434 | AddChild(Label: "value", DoAddChild: [=] { Visit(Value: *Value, Ty: E->getType()); }); |
2435 | } |
2436 | } |
2437 | } |
2438 | |
2439 | void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) { |
2440 | dumpName(D); |
2441 | dumpType(T: D->getType()); |
2442 | } |
2443 | |
2444 | void TextNodeDumper::VisitCapturedDecl(const CapturedDecl *D) { |
2445 | if (D->isNothrow()) |
2446 | OS << " nothrow"; |
2447 | } |
2448 | |
2449 | void TextNodeDumper::VisitImportDecl(const ImportDecl *D) { |
2450 | OS << ' ' << D->getImportedModule()->getFullModuleName(); |
2451 | |
2452 | for (Decl *InitD : |
2453 | D->getASTContext().getModuleInitializers(D->getImportedModule())) |
2454 | dumpDeclRef(InitD, "initializer"); |
2455 | } |
2456 | |
2457 | void TextNodeDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) { |
2458 | OS << ' '; |
2459 | switch (D->getCommentKind()) { |
2460 | case PCK_Unknown: |
2461 | llvm_unreachable("unexpected pragma comment kind"); |
2462 | case PCK_Compiler: |
2463 | OS << "compiler"; |
2464 | break; |
2465 | case PCK_ExeStr: |
2466 | OS << "exestr"; |
2467 | break; |
2468 | case PCK_Lib: |
2469 | OS << "lib"; |
2470 | break; |
2471 | case PCK_Linker: |
2472 | OS << "linker"; |
2473 | break; |
2474 | case PCK_User: |
2475 | OS << "user"; |
2476 | break; |
2477 | } |
2478 | StringRef Arg = D->getArg(); |
2479 | if (!Arg.empty()) |
2480 | OS << " \""<< Arg << "\""; |
2481 | } |
2482 | |
2483 | void TextNodeDumper::VisitPragmaDetectMismatchDecl( |
2484 | const PragmaDetectMismatchDecl *D) { |
2485 | OS << " \""<< D->getName() << "\" \""<< D->getValue() << "\""; |
2486 | } |
2487 | |
2488 | void TextNodeDumper::VisitOMPExecutableDirective( |
2489 | const OMPExecutableDirective *D) { |
2490 | if (D->isStandaloneDirective()) |
2491 | OS << " openmp_standalone_directive"; |
2492 | } |
2493 | |
2494 | void TextNodeDumper::VisitOMPDeclareReductionDecl( |
2495 | const OMPDeclareReductionDecl *D) { |
2496 | dumpName(D); |
2497 | dumpType(T: D->getType()); |
2498 | OS << " combiner"; |
2499 | dumpPointer(Ptr: D->getCombiner()); |
2500 | if (const auto *Initializer = D->getInitializer()) { |
2501 | OS << " initializer"; |
2502 | dumpPointer(Ptr: Initializer); |
2503 | switch (D->getInitializerKind()) { |
2504 | case OMPDeclareReductionInitKind::Direct: |
2505 | OS << " omp_priv = "; |
2506 | break; |
2507 | case OMPDeclareReductionInitKind::Copy: |
2508 | OS << " omp_priv ()"; |
2509 | break; |
2510 | case OMPDeclareReductionInitKind::Call: |
2511 | break; |
2512 | } |
2513 | } |
2514 | } |
2515 | |
2516 | void TextNodeDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) { |
2517 | for (const auto *C : D->clauselists()) { |
2518 | AddChild(DoAddChild: [=] { |
2519 | if (!C) { |
2520 | ColorScope Color(OS, ShowColors, NullColor); |
2521 | OS << "<<<NULL>>> OMPClause"; |
2522 | return; |
2523 | } |
2524 | { |
2525 | ColorScope Color(OS, ShowColors, AttrColor); |
2526 | StringRef ClauseName( |
2527 | llvm::omp::getOpenMPClauseName(C->getClauseKind())); |
2528 | OS << "OMP"<< ClauseName.substr(/*Start=*/0, /*N=*/1).upper() |
2529 | << ClauseName.drop_front() << "Clause"; |
2530 | } |
2531 | dumpPointer(Ptr: C); |
2532 | dumpSourceRange(R: SourceRange(C->getBeginLoc(), C->getEndLoc())); |
2533 | }); |
2534 | } |
2535 | } |
2536 | |
2537 | void TextNodeDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { |
2538 | dumpName(D); |
2539 | dumpType(T: D->getType()); |
2540 | } |
2541 | |
2542 | void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) { |
2543 | dumpName(D); |
2544 | if (D->isInline()) |
2545 | OS << " inline"; |
2546 | if (D->isNested()) |
2547 | OS << " nested"; |
2548 | if (!D->isFirstDecl()) |
2549 | dumpDeclRef(D: D->getFirstDecl(), Label: "original"); |
2550 | } |
2551 | |
2552 | void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { |
2553 | OS << ' '; |
2554 | dumpBareDeclRef(D->getNominatedNamespace()); |
2555 | } |
2556 | |
2557 | void TextNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { |
2558 | dumpName(D); |
2559 | dumpDeclRef(D->getAliasedNamespace()); |
2560 | } |
2561 | |
2562 | void TextNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { |
2563 | dumpName(D); |
2564 | dumpType(T: D->getUnderlyingType()); |
2565 | } |
2566 | |
2567 | void TextNodeDumper::VisitTypeAliasTemplateDecl( |
2568 | const TypeAliasTemplateDecl *D) { |
2569 | dumpName(D); |
2570 | } |
2571 | |
2572 | void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { |
2573 | VisitRecordDecl(D); |
2574 | if (const auto *Instance = D->getInstantiatedFromMemberClass()) { |
2575 | OS << " instantiated_from"; |
2576 | dumpPointer(Ptr: Instance); |
2577 | } |
2578 | if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) { |
2579 | dumpTemplateSpecializationKind(TSK: CTSD->getSpecializationKind()); |
2580 | if (CTSD->hasStrictPackMatch()) |
2581 | OS << " strict-pack-match"; |
2582 | } |
2583 | |
2584 | dumpNestedNameSpecifier(NNS: D->getQualifier()); |
2585 | |
2586 | if (!D->isCompleteDefinition()) |
2587 | return; |
2588 | |
2589 | AddChild(DoAddChild: [=] { |
2590 | { |
2591 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
2592 | OS << "DefinitionData"; |
2593 | } |
2594 | #define FLAG(fn, name) \ |
2595 | if (D->fn()) \ |
2596 | OS << " " #name; |
2597 | FLAG(isParsingBaseSpecifiers, parsing_base_specifiers); |
2598 | |
2599 | FLAG(isGenericLambda, generic); |
2600 | FLAG(isLambda, lambda); |
2601 | |
2602 | FLAG(isAnonymousStructOrUnion, is_anonymous); |
2603 | FLAG(canPassInRegisters, pass_in_registers); |
2604 | FLAG(isEmpty, empty); |
2605 | FLAG(isAggregate, aggregate); |
2606 | FLAG(isStandardLayout, standard_layout); |
2607 | FLAG(isTriviallyCopyable, trivially_copyable); |
2608 | FLAG(isPOD, pod); |
2609 | FLAG(isTrivial, trivial); |
2610 | FLAG(isPolymorphic, polymorphic); |
2611 | FLAG(isAbstract, abstract); |
2612 | FLAG(isLiteral, literal); |
2613 | |
2614 | FLAG(hasUserDeclaredConstructor, has_user_declared_ctor); |
2615 | FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor); |
2616 | FLAG(hasMutableFields, has_mutable_fields); |
2617 | FLAG(hasVariantMembers, has_variant_members); |
2618 | FLAG(allowConstDefaultInit, can_const_default_init); |
2619 | |
2620 | AddChild(DoAddChild: [=] { |
2621 | { |
2622 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
2623 | OS << "DefaultConstructor"; |
2624 | } |
2625 | FLAG(hasDefaultConstructor, exists); |
2626 | FLAG(hasTrivialDefaultConstructor, trivial); |
2627 | FLAG(hasNonTrivialDefaultConstructor, non_trivial); |
2628 | FLAG(hasUserProvidedDefaultConstructor, user_provided); |
2629 | FLAG(hasConstexprDefaultConstructor, constexpr); |
2630 | FLAG(needsImplicitDefaultConstructor, needs_implicit); |
2631 | FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr); |
2632 | }); |
2633 | |
2634 | AddChild(DoAddChild: [=] { |
2635 | { |
2636 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
2637 | OS << "CopyConstructor"; |
2638 | } |
2639 | FLAG(hasSimpleCopyConstructor, simple); |
2640 | FLAG(hasTrivialCopyConstructor, trivial); |
2641 | FLAG(hasNonTrivialCopyConstructor, non_trivial); |
2642 | FLAG(hasUserDeclaredCopyConstructor, user_declared); |
2643 | FLAG(hasCopyConstructorWithConstParam, has_const_param); |
2644 | FLAG(needsImplicitCopyConstructor, needs_implicit); |
2645 | FLAG(needsOverloadResolutionForCopyConstructor, |
2646 | needs_overload_resolution); |
2647 | if (!D->needsOverloadResolutionForCopyConstructor()) |
2648 | FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted); |
2649 | FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param); |
2650 | }); |
2651 | |
2652 | AddChild(DoAddChild: [=] { |
2653 | { |
2654 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
2655 | OS << "MoveConstructor"; |
2656 | } |
2657 | FLAG(hasMoveConstructor, exists); |
2658 | FLAG(hasSimpleMoveConstructor, simple); |
2659 | FLAG(hasTrivialMoveConstructor, trivial); |
2660 | FLAG(hasNonTrivialMoveConstructor, non_trivial); |
2661 | FLAG(hasUserDeclaredMoveConstructor, user_declared); |
2662 | FLAG(needsImplicitMoveConstructor, needs_implicit); |
2663 | FLAG(needsOverloadResolutionForMoveConstructor, |
2664 | needs_overload_resolution); |
2665 | if (!D->needsOverloadResolutionForMoveConstructor()) |
2666 | FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted); |
2667 | }); |
2668 | |
2669 | AddChild(DoAddChild: [=] { |
2670 | { |
2671 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
2672 | OS << "CopyAssignment"; |
2673 | } |
2674 | FLAG(hasSimpleCopyAssignment, simple); |
2675 | FLAG(hasTrivialCopyAssignment, trivial); |
2676 | FLAG(hasNonTrivialCopyAssignment, non_trivial); |
2677 | FLAG(hasCopyAssignmentWithConstParam, has_const_param); |
2678 | FLAG(hasUserDeclaredCopyAssignment, user_declared); |
2679 | FLAG(needsImplicitCopyAssignment, needs_implicit); |
2680 | FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution); |
2681 | FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param); |
2682 | }); |
2683 | |
2684 | AddChild(DoAddChild: [=] { |
2685 | { |
2686 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
2687 | OS << "MoveAssignment"; |
2688 | } |
2689 | FLAG(hasMoveAssignment, exists); |
2690 | FLAG(hasSimpleMoveAssignment, simple); |
2691 | FLAG(hasTrivialMoveAssignment, trivial); |
2692 | FLAG(hasNonTrivialMoveAssignment, non_trivial); |
2693 | FLAG(hasUserDeclaredMoveAssignment, user_declared); |
2694 | FLAG(needsImplicitMoveAssignment, needs_implicit); |
2695 | FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution); |
2696 | }); |
2697 | |
2698 | AddChild(DoAddChild: [=] { |
2699 | { |
2700 | ColorScope Color(OS, ShowColors, DeclKindNameColor); |
2701 | OS << "Destructor"; |
2702 | } |
2703 | FLAG(hasSimpleDestructor, simple); |
2704 | FLAG(hasIrrelevantDestructor, irrelevant); |
2705 | FLAG(hasTrivialDestructor, trivial); |
2706 | FLAG(hasNonTrivialDestructor, non_trivial); |
2707 | FLAG(hasUserDeclaredDestructor, user_declared); |
2708 | FLAG(hasConstexprDestructor, constexpr); |
2709 | FLAG(needsImplicitDestructor, needs_implicit); |
2710 | FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution); |
2711 | if (!D->needsOverloadResolutionForDestructor()) |
2712 | FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted); |
2713 | }); |
2714 | }); |
2715 | |
2716 | for (const auto &I : D->bases()) { |
2717 | AddChild(DoAddChild: [=] { |
2718 | if (I.isVirtual()) |
2719 | OS << "virtual "; |
2720 | dumpAccessSpecifier(AS: I.getAccessSpecifier()); |
2721 | dumpType(T: I.getType()); |
2722 | if (I.isPackExpansion()) |
2723 | OS << "..."; |
2724 | }); |
2725 | } |
2726 | } |
2727 | |
2728 | void TextNodeDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { |
2729 | dumpName(D); |
2730 | } |
2731 | |
2732 | void TextNodeDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { |
2733 | dumpName(D); |
2734 | } |
2735 | |
2736 | void TextNodeDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { |
2737 | dumpName(D); |
2738 | } |
2739 | |
2740 | void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { |
2741 | dumpName(D); |
2742 | } |
2743 | |
2744 | void TextNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { |
2745 | if (const auto *TC = D->getTypeConstraint()) { |
2746 | OS << " "; |
2747 | dumpBareDeclRef(TC->getNamedConcept()); |
2748 | if (TC->getNamedConcept() != TC->getFoundDecl()) { |
2749 | OS << " ("; |
2750 | dumpBareDeclRef(TC->getFoundDecl()); |
2751 | OS << ")"; |
2752 | } |
2753 | } else if (D->wasDeclaredWithTypename()) |
2754 | OS << " typename"; |
2755 | else |
2756 | OS << " class"; |
2757 | OS << " depth "<< D->getDepth() << " index "<< D->getIndex(); |
2758 | if (D->isParameterPack()) |
2759 | OS << " ..."; |
2760 | dumpName(D); |
2761 | } |
2762 | |
2763 | void TextNodeDumper::VisitNonTypeTemplateParmDecl( |
2764 | const NonTypeTemplateParmDecl *D) { |
2765 | dumpType(T: D->getType()); |
2766 | OS << " depth "<< D->getDepth() << " index "<< D->getIndex(); |
2767 | if (D->isParameterPack()) |
2768 | OS << " ..."; |
2769 | dumpName(D); |
2770 | } |
2771 | |
2772 | void TextNodeDumper::VisitTemplateTemplateParmDecl( |
2773 | const TemplateTemplateParmDecl *D) { |
2774 | OS << " depth "<< D->getDepth() << " index "<< D->getIndex(); |
2775 | if (D->isParameterPack()) |
2776 | OS << " ..."; |
2777 | dumpName(D); |
2778 | } |
2779 | |
2780 | void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) { |
2781 | OS << ' '; |
2782 | if (D->getQualifier()) |
2783 | D->getQualifier()->print(OS, Policy: D->getASTContext().getPrintingPolicy()); |
2784 | OS << D->getDeclName(); |
2785 | dumpNestedNameSpecifier(NNS: D->getQualifier()); |
2786 | } |
2787 | |
2788 | void TextNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *D) { |
2789 | OS << ' '; |
2790 | dumpBareDeclRef(D->getEnumDecl()); |
2791 | } |
2792 | |
2793 | void TextNodeDumper::VisitUnresolvedUsingTypenameDecl( |
2794 | const UnresolvedUsingTypenameDecl *D) { |
2795 | OS << ' '; |
2796 | if (D->getQualifier()) |
2797 | D->getQualifier()->print(OS, Policy: D->getASTContext().getPrintingPolicy()); |
2798 | OS << D->getDeclName(); |
2799 | } |
2800 | |
2801 | void TextNodeDumper::VisitUnresolvedUsingValueDecl( |
2802 | const UnresolvedUsingValueDecl *D) { |
2803 | OS << ' '; |
2804 | if (D->getQualifier()) |
2805 | D->getQualifier()->print(OS, Policy: D->getASTContext().getPrintingPolicy()); |
2806 | OS << D->getDeclName(); |
2807 | dumpType(T: D->getType()); |
2808 | } |
2809 | |
2810 | void TextNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { |
2811 | OS << ' '; |
2812 | dumpBareDeclRef(D->getTargetDecl()); |
2813 | } |
2814 | |
2815 | void TextNodeDumper::VisitConstructorUsingShadowDecl( |
2816 | const ConstructorUsingShadowDecl *D) { |
2817 | if (D->constructsVirtualBase()) |
2818 | OS << " virtual"; |
2819 | |
2820 | AddChild(DoAddChild: [=] { |
2821 | OS << "target "; |
2822 | dumpBareDeclRef(D: D->getTargetDecl()); |
2823 | }); |
2824 | |
2825 | AddChild(DoAddChild: [=] { |
2826 | OS << "nominated "; |
2827 | dumpBareDeclRef(D->getNominatedBaseClass()); |
2828 | OS << ' '; |
2829 | dumpBareDeclRef(D->getNominatedBaseClassShadowDecl()); |
2830 | }); |
2831 | |
2832 | AddChild(DoAddChild: [=] { |
2833 | OS << "constructed "; |
2834 | dumpBareDeclRef(D->getConstructedBaseClass()); |
2835 | OS << ' '; |
2836 | dumpBareDeclRef(D->getConstructedBaseClassShadowDecl()); |
2837 | }); |
2838 | } |
2839 | |
2840 | void TextNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { |
2841 | switch (D->getLanguage()) { |
2842 | case LinkageSpecLanguageIDs::C: |
2843 | OS << " C"; |
2844 | break; |
2845 | case LinkageSpecLanguageIDs::CXX: |
2846 | OS << " C++"; |
2847 | break; |
2848 | } |
2849 | } |
2850 | |
2851 | void TextNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { |
2852 | OS << ' '; |
2853 | dumpAccessSpecifier(AS: D->getAccess()); |
2854 | } |
2855 | |
2856 | void TextNodeDumper::VisitFriendDecl(const FriendDecl *D) { |
2857 | if (TypeSourceInfo *T = D->getFriendType()) |
2858 | dumpType(T: T->getType()); |
2859 | if (D->isPackExpansion()) |
2860 | OS << "..."; |
2861 | } |
2862 | |
2863 | void TextNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { |
2864 | dumpName(D); |
2865 | dumpType(T: D->getType()); |
2866 | if (D->getSynthesize()) |
2867 | OS << " synthesize"; |
2868 | |
2869 | switch (D->getAccessControl()) { |
2870 | case ObjCIvarDecl::None: |
2871 | OS << " none"; |
2872 | break; |
2873 | case ObjCIvarDecl::Private: |
2874 | OS << " private"; |
2875 | break; |
2876 | case ObjCIvarDecl::Protected: |
2877 | OS << " protected"; |
2878 | break; |
2879 | case ObjCIvarDecl::Public: |
2880 | OS << " public"; |
2881 | break; |
2882 | case ObjCIvarDecl::Package: |
2883 | OS << " package"; |
2884 | break; |
2885 | } |
2886 | } |
2887 | |
2888 | void TextNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { |
2889 | if (D->isInstanceMethod()) |
2890 | OS << " -"; |
2891 | else |
2892 | OS << " +"; |
2893 | dumpName(D); |
2894 | dumpType(T: D->getReturnType()); |
2895 | |
2896 | if (D->isVariadic()) |
2897 | OS << " variadic"; |
2898 | } |
2899 | |
2900 | void TextNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) { |
2901 | dumpName(D); |
2902 | switch (D->getVariance()) { |
2903 | case ObjCTypeParamVariance::Invariant: |
2904 | break; |
2905 | |
2906 | case ObjCTypeParamVariance::Covariant: |
2907 | OS << " covariant"; |
2908 | break; |
2909 | |
2910 | case ObjCTypeParamVariance::Contravariant: |
2911 | OS << " contravariant"; |
2912 | break; |
2913 | } |
2914 | |
2915 | if (D->hasExplicitBound()) |
2916 | OS << " bounded"; |
2917 | dumpType(T: D->getUnderlyingType()); |
2918 | } |
2919 | |
2920 | void TextNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { |
2921 | dumpName(D); |
2922 | dumpDeclRef(D->getClassInterface()); |
2923 | dumpDeclRef(D->getImplementation()); |
2924 | for (const auto *P : D->protocols()) |
2925 | dumpDeclRef(P); |
2926 | } |
2927 | |
2928 | void TextNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { |
2929 | dumpName(D); |
2930 | dumpDeclRef(D: D->getClassInterface()); |
2931 | dumpDeclRef(D->getCategoryDecl()); |
2932 | } |
2933 | |
2934 | void TextNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { |
2935 | dumpName(D); |
2936 | |
2937 | for (const auto *Child : D->protocols()) |
2938 | dumpDeclRef(Child); |
2939 | } |
2940 | |
2941 | void TextNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { |
2942 | dumpName(D); |
2943 | dumpDeclRef(D->getSuperClass(), "super"); |
2944 | |
2945 | dumpDeclRef(D->getImplementation()); |
2946 | for (const auto *Child : D->protocols()) |
2947 | dumpDeclRef(Child); |
2948 | } |
2949 | |
2950 | void TextNodeDumper::VisitObjCImplementationDecl( |
2951 | const ObjCImplementationDecl *D) { |
2952 | dumpName(D); |
2953 | dumpDeclRef(D->getSuperClass(), "super"); |
2954 | dumpDeclRef(D: D->getClassInterface()); |
2955 | } |
2956 | |
2957 | void TextNodeDumper::VisitObjCCompatibleAliasDecl( |
2958 | const ObjCCompatibleAliasDecl *D) { |
2959 | dumpName(D); |
2960 | dumpDeclRef(D->getClassInterface()); |
2961 | } |
2962 | |
2963 | void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { |
2964 | dumpName(D); |
2965 | dumpType(T: D->getType()); |
2966 | |
2967 | if (D->getPropertyImplementation() == ObjCPropertyDecl::Required) |
2968 | OS << " required"; |
2969 | else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional) |
2970 | OS << " optional"; |
2971 | |
2972 | ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes(); |
2973 | if (Attrs != ObjCPropertyAttribute::kind_noattr) { |
2974 | if (Attrs & ObjCPropertyAttribute::kind_readonly) |
2975 | OS << " readonly"; |
2976 | if (Attrs & ObjCPropertyAttribute::kind_assign) |
2977 | OS << " assign"; |
2978 | if (Attrs & ObjCPropertyAttribute::kind_readwrite) |
2979 | OS << " readwrite"; |
2980 | if (Attrs & ObjCPropertyAttribute::kind_retain) |
2981 | OS << " retain"; |
2982 | if (Attrs & ObjCPropertyAttribute::kind_copy) |
2983 | OS << " copy"; |
2984 | if (Attrs & ObjCPropertyAttribute::kind_nonatomic) |
2985 | OS << " nonatomic"; |
2986 | if (Attrs & ObjCPropertyAttribute::kind_atomic) |
2987 | OS << " atomic"; |
2988 | if (Attrs & ObjCPropertyAttribute::kind_weak) |
2989 | OS << " weak"; |
2990 | if (Attrs & ObjCPropertyAttribute::kind_strong) |
2991 | OS << " strong"; |
2992 | if (Attrs & ObjCPropertyAttribute::kind_unsafe_unretained) |
2993 | OS << " unsafe_unretained"; |
2994 | if (Attrs & ObjCPropertyAttribute::kind_class) |
2995 | OS << " class"; |
2996 | if (Attrs & ObjCPropertyAttribute::kind_direct) |
2997 | OS << " direct"; |
2998 | if (Attrs & ObjCPropertyAttribute::kind_getter) |
2999 | dumpDeclRef(D->getGetterMethodDecl(), "getter"); |
3000 | if (Attrs & ObjCPropertyAttribute::kind_setter) |
3001 | dumpDeclRef(D->getSetterMethodDecl(), "setter"); |
3002 | } |
3003 | } |
3004 | |
3005 | void TextNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { |
3006 | dumpName(D->getPropertyDecl()); |
3007 | if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) |
3008 | OS << " synthesize"; |
3009 | else |
3010 | OS << " dynamic"; |
3011 | dumpDeclRef(D->getPropertyDecl()); |
3012 | dumpDeclRef(D->getPropertyIvarDecl()); |
3013 | } |
3014 | |
3015 | void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) { |
3016 | if (D->isVariadic()) |
3017 | OS << " variadic"; |
3018 | |
3019 | if (D->capturesCXXThis()) |
3020 | OS << " captures_this"; |
3021 | } |
3022 | |
3023 | void TextNodeDumper::VisitConceptDecl(const ConceptDecl *D) { |
3024 | dumpName(D); |
3025 | } |
3026 | |
3027 | void TextNodeDumper::VisitCompoundStmt(const CompoundStmt *S) { |
3028 | VisitStmt(S); |
3029 | if (S->hasStoredFPFeatures()) |
3030 | printFPOptions(FPO: S->getStoredFPFeatures()); |
3031 | } |
3032 | |
3033 | void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) { |
3034 | if (D->isCBuffer()) |
3035 | OS << " cbuffer"; |
3036 | else |
3037 | OS << " tbuffer"; |
3038 | dumpName(D); |
3039 | } |
3040 | |
3041 | void TextNodeDumper::VisitHLSLRootSignatureDecl( |
3042 | const HLSLRootSignatureDecl *D) { |
3043 | dumpName(D); |
3044 | llvm::hlsl::rootsig::dumpRootElements(OS, Elements: D->getRootElements()); |
3045 | } |
3046 | |
3047 | void TextNodeDumper::VisitHLSLOutArgExpr(const HLSLOutArgExpr *E) { |
3048 | OS << (E->isInOut() ? " inout": " out"); |
3049 | } |
3050 | |
3051 | void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) { |
3052 | OS << " "<< S->getDirectiveKind(); |
3053 | } |
3054 | void TextNodeDumper::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S) { |
3055 | if (S->isOrphanedLoopConstruct()) |
3056 | OS << " <orphan>"; |
3057 | else |
3058 | OS << " parent: "<< S->getParentComputeConstructKind(); |
3059 | } |
3060 | |
3061 | void TextNodeDumper::VisitOpenACCCombinedConstruct( |
3062 | const OpenACCCombinedConstruct *S) { |
3063 | VisitOpenACCConstructStmt(S); |
3064 | } |
3065 | |
3066 | void TextNodeDumper::VisitOpenACCDataConstruct(const OpenACCDataConstruct *S) { |
3067 | VisitOpenACCConstructStmt(S); |
3068 | } |
3069 | |
3070 | void TextNodeDumper::VisitOpenACCEnterDataConstruct( |
3071 | const OpenACCEnterDataConstruct *S) { |
3072 | VisitOpenACCConstructStmt(S); |
3073 | } |
3074 | |
3075 | void TextNodeDumper::VisitOpenACCExitDataConstruct( |
3076 | const OpenACCExitDataConstruct *S) { |
3077 | VisitOpenACCConstructStmt(S); |
3078 | } |
3079 | |
3080 | void TextNodeDumper::VisitOpenACCHostDataConstruct( |
3081 | const OpenACCHostDataConstruct *S) { |
3082 | VisitOpenACCConstructStmt(S); |
3083 | } |
3084 | |
3085 | void TextNodeDumper::VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S) { |
3086 | VisitOpenACCConstructStmt(S); |
3087 | } |
3088 | void TextNodeDumper::VisitOpenACCCacheConstruct( |
3089 | const OpenACCCacheConstruct *S) { |
3090 | VisitOpenACCConstructStmt(S); |
3091 | if (S->hasReadOnly()) |
3092 | OS <<" readonly"; |
3093 | } |
3094 | void TextNodeDumper::VisitOpenACCInitConstruct(const OpenACCInitConstruct *S) { |
3095 | VisitOpenACCConstructStmt(S); |
3096 | } |
3097 | void TextNodeDumper::VisitOpenACCShutdownConstruct( |
3098 | const OpenACCShutdownConstruct *S) { |
3099 | VisitOpenACCConstructStmt(S); |
3100 | } |
3101 | void TextNodeDumper::VisitOpenACCSetConstruct(const OpenACCSetConstruct *S) { |
3102 | VisitOpenACCConstructStmt(S); |
3103 | } |
3104 | void TextNodeDumper::VisitOpenACCUpdateConstruct( |
3105 | const OpenACCUpdateConstruct *S) { |
3106 | VisitOpenACCConstructStmt(S); |
3107 | } |
3108 | |
3109 | void TextNodeDumper::VisitOpenACCAtomicConstruct( |
3110 | const OpenACCAtomicConstruct *S) { |
3111 | VisitOpenACCConstructStmt(S); |
3112 | OS << ' ' << S->getAtomicKind(); |
3113 | } |
3114 | |
3115 | void TextNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) { |
3116 | OS << " "<< D->getDirectiveKind(); |
3117 | |
3118 | for (const OpenACCClause *C : D->clauses()) |
3119 | AddChild([=] { |
3120 | Visit(C); |
3121 | for (const Stmt *S : C->children()) |
3122 | AddChild([=] { Visit(S); }); |
3123 | }); |
3124 | } |
3125 | void TextNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) { |
3126 | OS << " "<< D->getDirectiveKind(); |
3127 | |
3128 | dumpSourceRange(R: SourceRange{D->getLParenLoc(), D->getRParenLoc()}); |
3129 | |
3130 | AddChild(DoAddChild: [=] { Visit(D->getFunctionReference()); }); |
3131 | |
3132 | for (const OpenACCClause *C : D->clauses()) |
3133 | AddChild([=] { |
3134 | Visit(C); |
3135 | for (const Stmt *S : C->children()) |
3136 | AddChild([=] { Visit(S); }); |
3137 | }); |
3138 | } |
3139 | |
3140 | void TextNodeDumper::VisitOpenACCRoutineDeclAttr( |
3141 | const OpenACCRoutineDeclAttr *A) { |
3142 | for (const OpenACCClause *C : A->Clauses) |
3143 | AddChild([=] { |
3144 | Visit(C); |
3145 | for (const Stmt *S : C->children()) |
3146 | AddChild([=] { Visit(S); }); |
3147 | }); |
3148 | } |
3149 | |
3150 | void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) { |
3151 | AddChild(Label: "begin", DoAddChild: [=] { OS << S->getStartingElementPos(); }); |
3152 | AddChild(Label: "number of elements", DoAddChild: [=] { OS << S->getDataElementCount(); }); |
3153 | } |
3154 | |
3155 | void TextNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) { |
3156 | OS << ' ' << AE->getOpAsString(); |
3157 | } |
3158 | |
3159 | void TextNodeDumper::VisitConvertVectorExpr(const ConvertVectorExpr *S) { |
3160 | VisitStmt(S); |
3161 | if (S->hasStoredFPFeatures()) |
3162 | printFPOptions(FPO: S->getStoredFPFeatures()); |
3163 | } |
3164 |
Definitions
- dumpPreviousDeclImpl
- dumpPreviousDeclImpl
- dumpPreviousDeclImpl
- dumpPreviousDecl
- TextNodeDumper
- TextNodeDumper
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- VisitOpenACCAsteriskSizeExpr
- Visit
- Visit
- Visit
- Visit
- GetApproxValue
- isSimpleAPValue
- dumpAPValueChildren
- Visit
- dumpPointer
- dumpLocation
- dumpSourceRange
- dumpBareType
- dumpType
- dumpBareDeclRef
- dumpName
- dumpAccessSpecifier
- dumpCleanupObject
- dumpTemplateSpecializationKind
- dumpNestedNameSpecifier
- dumpDeclRef
- dumpTemplateArgument
- getCommandName
- printFPOptions
- visitTextComment
- visitInlineCommandComment
- visitHTMLStartTagComment
- visitHTMLEndTagComment
- visitBlockCommandComment
- visitParamCommandComment
- visitTParamCommandComment
- visitVerbatimBlockComment
- visitVerbatimBlockLineComment
- visitVerbatimLineComment
- VisitNullTemplateArgument
- VisitTypeTemplateArgument
- VisitDeclarationTemplateArgument
- VisitNullPtrTemplateArgument
- VisitIntegralTemplateArgument
- VisitStructuralValueTemplateArgument
- dumpTemplateName
- dumpBareTemplateName
- VisitTemplateTemplateArgument
- VisitTemplateExpansionTemplateArgument
- VisitExpressionTemplateArgument
- VisitPackTemplateArgument
- dumpBasePath
- VisitIfStmt
- VisitSwitchStmt
- VisitWhileStmt
- VisitLabelStmt
- VisitGotoStmt
- VisitCaseStmt
- VisitReturnStmt
- VisitCoawaitExpr
- VisitCoreturnStmt
- VisitConstantExpr
- VisitCallExpr
- VisitCXXOperatorCallExpr
- VisitCastExpr
- VisitImplicitCastExpr
- VisitDeclRefExpr
- VisitDependentScopeDeclRefExpr
- VisitUnresolvedLookupExpr
- VisitObjCIvarRefExpr
- VisitSYCLUniqueStableNameExpr
- VisitPredefinedExpr
- VisitCharacterLiteral
- VisitIntegerLiteral
- VisitFixedPointLiteral
- VisitFloatingLiteral
- VisitStringLiteral
- VisitInitListExpr
- VisitGenericSelectionExpr
- VisitUnaryOperator
- VisitUnaryExprOrTypeTraitExpr
- VisitMemberExpr
- VisitExtVectorElementExpr
- VisitBinaryOperator
- VisitCompoundAssignOperator
- VisitAddrLabelExpr
- VisitCXXNamedCastExpr
- VisitCXXBoolLiteralExpr
- VisitCXXThisExpr
- VisitCXXFunctionalCastExpr
- VisitCXXStaticCastExpr
- VisitCXXUnresolvedConstructExpr
- VisitCXXConstructExpr
- VisitCXXBindTemporaryExpr
- VisitCXXNewExpr
- VisitCXXDeleteExpr
- VisitTypeTraitExpr
- VisitArrayTypeTraitExpr
- VisitExpressionTraitExpr
- VisitCXXDefaultArgExpr
- VisitCXXDefaultInitExpr
- VisitMaterializeTemporaryExpr
- VisitExprWithCleanups
- VisitSizeOfPackExpr
- VisitCXXDependentScopeMemberExpr
- VisitObjCMessageExpr
- VisitObjCBoxedExpr
- VisitObjCAtCatchStmt
- VisitObjCEncodeExpr
- VisitObjCSelectorExpr
- VisitObjCProtocolExpr
- VisitObjCPropertyRefExpr
- VisitObjCSubscriptRefExpr
- VisitObjCBoolLiteralExpr
- VisitOMPIteratorExpr
- VisitConceptSpecializationExpr
- VisitRequiresExpr
- VisitRValueReferenceType
- VisitArrayType
- VisitConstantArrayType
- VisitVariableArrayType
- VisitDependentSizedArrayType
- VisitDependentSizedExtVectorType
- VisitVectorType
- VisitFunctionType
- VisitFunctionProtoType
- VisitUnresolvedUsingType
- VisitUsingType
- VisitTypedefType
- VisitUnaryTransformType
- VisitTagType
- VisitTemplateTypeParmType
- VisitSubstTemplateTypeParmType
- VisitSubstTemplateTypeParmPackType
- VisitAutoType
- VisitDeducedTemplateSpecializationType
- VisitTemplateSpecializationType
- VisitInjectedClassNameType
- VisitObjCInterfaceType
- VisitPackExpansionType
- VisitTypeLoc
- VisitLabelDecl
- VisitTypedefDecl
- VisitEnumDecl
- VisitRecordDecl
- VisitEnumConstantDecl
- VisitIndirectFieldDecl
- VisitFunctionDecl
- VisitCXXDeductionGuideDecl
- VisitLifetimeExtendedTemporaryDecl
- VisitFieldDecl
- VisitVarDecl
- VisitBindingDecl
- VisitCapturedDecl
- VisitImportDecl
- VisitPragmaCommentDecl
- VisitPragmaDetectMismatchDecl
- VisitOMPExecutableDirective
- VisitOMPDeclareReductionDecl
- VisitOMPRequiresDecl
- VisitOMPCapturedExprDecl
- VisitNamespaceDecl
- VisitUsingDirectiveDecl
- VisitNamespaceAliasDecl
- VisitTypeAliasDecl
- VisitTypeAliasTemplateDecl
- VisitCXXRecordDecl
- VisitFunctionTemplateDecl
- VisitClassTemplateDecl
- VisitVarTemplateDecl
- VisitBuiltinTemplateDecl
- VisitTemplateTypeParmDecl
- VisitNonTypeTemplateParmDecl
- VisitTemplateTemplateParmDecl
- VisitUsingDecl
- VisitUsingEnumDecl
- VisitUnresolvedUsingTypenameDecl
- VisitUnresolvedUsingValueDecl
- VisitUsingShadowDecl
- VisitConstructorUsingShadowDecl
- VisitLinkageSpecDecl
- VisitAccessSpecDecl
- VisitFriendDecl
- VisitObjCIvarDecl
- VisitObjCMethodDecl
- VisitObjCTypeParamDecl
- VisitObjCCategoryDecl
- VisitObjCCategoryImplDecl
- VisitObjCProtocolDecl
- VisitObjCInterfaceDecl
- VisitObjCImplementationDecl
- VisitObjCCompatibleAliasDecl
- VisitObjCPropertyDecl
- VisitObjCPropertyImplDecl
- VisitBlockDecl
- VisitConceptDecl
- VisitCompoundStmt
- VisitHLSLBufferDecl
- VisitHLSLRootSignatureDecl
- VisitHLSLOutArgExpr
- VisitOpenACCConstructStmt
- VisitOpenACCLoopConstruct
- VisitOpenACCCombinedConstruct
- VisitOpenACCDataConstruct
- VisitOpenACCEnterDataConstruct
- VisitOpenACCExitDataConstruct
- VisitOpenACCHostDataConstruct
- VisitOpenACCWaitConstruct
- VisitOpenACCCacheConstruct
- VisitOpenACCInitConstruct
- VisitOpenACCShutdownConstruct
- VisitOpenACCSetConstruct
- VisitOpenACCUpdateConstruct
- VisitOpenACCAtomicConstruct
- VisitOpenACCDeclareDecl
- VisitOpenACCRoutineDecl
- VisitOpenACCRoutineDeclAttr
- VisitEmbedExpr
- VisitAtomicExpr
Learn to use CMake with our Intro Training
Find out more