1#include "clang/AST/JSONNodeDumper.h"
2#include "clang/AST/Type.h"
3#include "clang/Basic/SourceManager.h"
4#include "clang/Basic/Specifiers.h"
5#include "clang/Lex/Lexer.h"
6#include "llvm/ADT/StringExtras.h"
7#include <optional>
8
9using namespace clang;
10
11void JSONNodeDumper::addPreviousDeclaration(const Decl *D) {
12 switch (D->getKind()) {
13#define DECL(DERIVED, BASE) \
14 case Decl::DERIVED: \
15 return writePreviousDeclImpl(cast<DERIVED##Decl>(D));
16#define ABSTRACT_DECL(DECL)
17#include "clang/AST/DeclNodes.inc"
18#undef ABSTRACT_DECL
19#undef DECL
20 }
21 llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
22}
23
24void JSONNodeDumper::Visit(const Attr *A) {
25 const char *AttrName = nullptr;
26 switch (A->getKind()) {
27#define ATTR(X) \
28 case attr::X: \
29 AttrName = #X"Attr"; \
30 break;
31#include "clang/Basic/AttrList.inc"
32#undef ATTR
33 }
34 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: A));
35 JOS.attribute(Key: "kind", Contents: AttrName);
36 JOS.attributeObject(Key: "range", Contents: [A, this] { writeSourceRange(R: A->getRange()); });
37 attributeOnlyIfTrue(Key: "inherited", Value: A->isInherited());
38 attributeOnlyIfTrue(Key: "implicit", Value: A->isImplicit());
39
40 // FIXME: it would be useful for us to output the spelling kind as well as
41 // the actual spelling. This would allow us to distinguish between the
42 // various attribute syntaxes, but we don't currently track that information
43 // within the AST.
44 //JOS.attribute("spelling", A->getSpelling());
45
46 InnerAttrVisitor::Visit(A);
47}
48
49void JSONNodeDumper::Visit(const Stmt *S) {
50 if (!S)
51 return;
52
53 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: S));
54 JOS.attribute(Key: "kind", Contents: S->getStmtClassName());
55 JOS.attributeObject(Key: "range",
56 Contents: [S, this] { writeSourceRange(R: S->getSourceRange()); });
57
58 if (const auto *E = dyn_cast<Expr>(Val: S)) {
59 JOS.attribute(Key: "type", Contents: createQualType(QT: E->getType()));
60 const char *Category = nullptr;
61 switch (E->getValueKind()) {
62 case VK_LValue: Category = "lvalue"; break;
63 case VK_XValue: Category = "xvalue"; break;
64 case VK_PRValue:
65 Category = "prvalue";
66 break;
67 }
68 JOS.attribute(Key: "valueCategory", Contents: Category);
69 }
70 InnerStmtVisitor::Visit(S);
71}
72
73void JSONNodeDumper::Visit(const Type *T) {
74 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: T));
75
76 if (!T)
77 return;
78
79 JOS.attribute(Key: "kind", Contents: (llvm::Twine(T->getTypeClassName()) + "Type").str());
80 JOS.attribute(Key: "type", Contents: createQualType(QT: QualType(T, 0), /*Desugar=*/false));
81 attributeOnlyIfTrue(Key: "containsErrors", Value: T->containsErrors());
82 attributeOnlyIfTrue(Key: "isDependent", Value: T->isDependentType());
83 attributeOnlyIfTrue(Key: "isInstantiationDependent",
84 Value: T->isInstantiationDependentType());
85 attributeOnlyIfTrue(Key: "isVariablyModified", Value: T->isVariablyModifiedType());
86 attributeOnlyIfTrue(Key: "containsUnexpandedPack",
87 Value: T->containsUnexpandedParameterPack());
88 attributeOnlyIfTrue(Key: "isImported", Value: T->isFromAST());
89 InnerTypeVisitor::Visit(T);
90}
91
92void JSONNodeDumper::Visit(QualType T) {
93 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: T.getAsOpaquePtr()));
94 JOS.attribute(Key: "kind", Contents: "QualType");
95 JOS.attribute(Key: "type", Contents: createQualType(QT: T));
96 JOS.attribute(Key: "qualifiers", Contents: T.split().Quals.getAsString());
97}
98
99void JSONNodeDumper::Visit(TypeLoc TL) {
100 if (TL.isNull())
101 return;
102 JOS.attribute(Key: "kind",
103 Contents: (llvm::Twine(TL.getTypeLocClass() == TypeLoc::Qualified
104 ? "Qualified"
105 : TL.getTypePtr()->getTypeClassName()) +
106 "TypeLoc")
107 .str());
108 JOS.attribute(Key: "type",
109 Contents: createQualType(QT: QualType(TL.getType()), /*Desugar=*/false));
110 JOS.attributeObject(Key: "range",
111 Contents: [TL, this] { writeSourceRange(R: TL.getSourceRange()); });
112}
113
114void JSONNodeDumper::Visit(const Decl *D) {
115 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: D));
116
117 if (!D)
118 return;
119
120 JOS.attribute(Key: "kind", Contents: (llvm::Twine(D->getDeclKindName()) + "Decl").str());
121 JOS.attributeObject(Key: "loc",
122 Contents: [D, this] { writeSourceLocation(Loc: D->getLocation()); });
123 JOS.attributeObject(Key: "range",
124 Contents: [D, this] { writeSourceRange(R: D->getSourceRange()); });
125 attributeOnlyIfTrue(Key: "isImplicit", Value: D->isImplicit());
126 attributeOnlyIfTrue(Key: "isInvalid", Value: D->isInvalidDecl());
127
128 if (D->isUsed())
129 JOS.attribute(Key: "isUsed", Contents: true);
130 else if (D->isThisDeclarationReferenced())
131 JOS.attribute(Key: "isReferenced", Contents: true);
132
133 if (const auto *ND = dyn_cast<NamedDecl>(Val: D))
134 attributeOnlyIfTrue(Key: "isHidden", Value: !ND->isUnconditionallyVisible());
135
136 if (D->getLexicalDeclContext() != D->getDeclContext()) {
137 // Because of multiple inheritance, a DeclContext pointer does not produce
138 // the same pointer representation as a Decl pointer that references the
139 // same AST Node.
140 const auto *ParentDeclContextDecl = dyn_cast<Decl>(Val: D->getDeclContext());
141 JOS.attribute(Key: "parentDeclContextId",
142 Contents: createPointerRepresentation(Ptr: ParentDeclContextDecl));
143 }
144
145 addPreviousDeclaration(D);
146 InnerDeclVisitor::Visit(D);
147}
148
149void JSONNodeDumper::Visit(const comments::Comment *C,
150 const comments::FullComment *FC) {
151 if (!C)
152 return;
153
154 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: C));
155 JOS.attribute(Key: "kind", Contents: C->getCommentKindName());
156 JOS.attributeObject(Key: "loc",
157 Contents: [C, this] { writeSourceLocation(Loc: C->getLocation()); });
158 JOS.attributeObject(Key: "range",
159 Contents: [C, this] { writeSourceRange(R: C->getSourceRange()); });
160
161 InnerCommentVisitor::visit(C, P: FC);
162}
163
164void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
165 const Decl *From, StringRef Label) {
166 JOS.attribute(Key: "kind", Contents: "TemplateArgument");
167 if (R.isValid())
168 JOS.attributeObject(Key: "range", Contents: [R, this] { writeSourceRange(R); });
169
170 if (From)
171 JOS.attribute(Key: Label.empty() ? "fromDecl" : Label, Contents: createBareDeclRef(D: From));
172
173 InnerTemplateArgVisitor::Visit(TA);
174}
175
176void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
177 JOS.attribute(Key: "kind", Contents: "CXXCtorInitializer");
178 if (Init->isAnyMemberInitializer())
179 JOS.attribute(Key: "anyInit", Contents: createBareDeclRef(D: Init->getAnyMember()));
180 else if (Init->isBaseInitializer())
181 JOS.attribute(Key: "baseInit",
182 Contents: createQualType(QT: QualType(Init->getBaseClass(), 0)));
183 else if (Init->isDelegatingInitializer())
184 JOS.attribute(Key: "delegatingInit",
185 Contents: createQualType(QT: Init->getTypeSourceInfo()->getType()));
186 else
187 llvm_unreachable("Unknown initializer type");
188}
189
190void JSONNodeDumper::Visit(const OpenACCClause *C) {}
191
192void JSONNodeDumper::Visit(const OMPClause *C) {}
193
194void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {
195 JOS.attribute(Key: "kind", Contents: "Capture");
196 attributeOnlyIfTrue(Key: "byref", Value: C.isByRef());
197 attributeOnlyIfTrue(Key: "nested", Value: C.isNested());
198 if (C.getVariable())
199 JOS.attribute(Key: "var", Contents: createBareDeclRef(D: C.getVariable()));
200}
201
202void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
203 JOS.attribute(Key: "associationKind", Contents: A.getTypeSourceInfo() ? "case" : "default");
204 attributeOnlyIfTrue(Key: "selected", Value: A.isSelected());
205}
206
207void JSONNodeDumper::Visit(const concepts::Requirement *R) {
208 if (!R)
209 return;
210
211 switch (R->getKind()) {
212 case concepts::Requirement::RK_Type:
213 JOS.attribute(Key: "kind", Contents: "TypeRequirement");
214 break;
215 case concepts::Requirement::RK_Simple:
216 JOS.attribute(Key: "kind", Contents: "SimpleRequirement");
217 break;
218 case concepts::Requirement::RK_Compound:
219 JOS.attribute(Key: "kind", Contents: "CompoundRequirement");
220 break;
221 case concepts::Requirement::RK_Nested:
222 JOS.attribute(Key: "kind", Contents: "NestedRequirement");
223 break;
224 }
225
226 if (auto *ER = dyn_cast<concepts::ExprRequirement>(Val: R))
227 attributeOnlyIfTrue(Key: "noexcept", Value: ER->hasNoexceptRequirement());
228
229 attributeOnlyIfTrue(Key: "isDependent", Value: R->isDependent());
230 if (!R->isDependent())
231 JOS.attribute(Key: "satisfied", Contents: R->isSatisfied());
232 attributeOnlyIfTrue(Key: "containsUnexpandedPack",
233 Value: R->containsUnexpandedParameterPack());
234}
235
236void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {
237 std::string Str;
238 llvm::raw_string_ostream OS(Str);
239 Value.printPretty(OS, Ctx, Ty);
240 JOS.attribute(Key: "value", Contents: Str);
241}
242
243void JSONNodeDumper::Visit(const ConceptReference *CR) {
244 JOS.attribute(Key: "kind", Contents: "ConceptReference");
245 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: CR->getNamedConcept()));
246 if (const auto *Args = CR->getTemplateArgsAsWritten()) {
247 JOS.attributeArray(Key: "templateArgsAsWritten", Contents: [Args, this] {
248 for (const TemplateArgumentLoc &TAL : Args->arguments())
249 JOS.object(
250 Contents: [&TAL, this] { Visit(TA: TAL.getArgument(), R: TAL.getSourceRange()); });
251 });
252 }
253 JOS.attributeObject(Key: "loc",
254 Contents: [CR, this] { writeSourceLocation(Loc: CR->getLocation()); });
255 JOS.attributeObject(Key: "range",
256 Contents: [CR, this] { writeSourceRange(R: CR->getSourceRange()); });
257}
258
259void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
260 if (Loc.isInvalid())
261 return;
262
263 JOS.attributeBegin(Key: "includedFrom");
264 JOS.objectBegin();
265
266 if (!JustFirst) {
267 // Walk the stack recursively, then print out the presumed location.
268 writeIncludeStack(Loc: SM.getPresumedLoc(Loc: Loc.getIncludeLoc()));
269 }
270
271 JOS.attribute(Key: "file", Contents: Loc.getFilename());
272 JOS.objectEnd();
273 JOS.attributeEnd();
274}
275
276void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc,
277 bool IsSpelling) {
278 PresumedLoc Presumed = SM.getPresumedLoc(Loc);
279 unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc)
280 : SM.getExpansionLineNumber(Loc);
281 StringRef ActualFile = SM.getBufferName(Loc);
282
283 if (Presumed.isValid()) {
284 JOS.attribute(Key: "offset", Contents: SM.getDecomposedLoc(Loc).second);
285 if (LastLocFilename != ActualFile) {
286 JOS.attribute(Key: "file", Contents: ActualFile);
287 JOS.attribute(Key: "line", Contents: ActualLine);
288 } else if (LastLocLine != ActualLine)
289 JOS.attribute(Key: "line", Contents: ActualLine);
290
291 StringRef PresumedFile = Presumed.getFilename();
292 if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile)
293 JOS.attribute(Key: "presumedFile", Contents: PresumedFile);
294
295 unsigned PresumedLine = Presumed.getLine();
296 if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine)
297 JOS.attribute(Key: "presumedLine", Contents: PresumedLine);
298
299 JOS.attribute(Key: "col", Contents: Presumed.getColumn());
300 JOS.attribute(Key: "tokLen",
301 Contents: Lexer::MeasureTokenLength(Loc, SM, LangOpts: Ctx.getLangOpts()));
302 LastLocFilename = ActualFile;
303 LastLocPresumedFilename = PresumedFile;
304 LastLocPresumedLine = PresumedLine;
305 LastLocLine = ActualLine;
306
307 // Orthogonal to the file, line, and column de-duplication is whether the
308 // given location was a result of an include. If so, print where the
309 // include location came from.
310 writeIncludeStack(Loc: SM.getPresumedLoc(Loc: Presumed.getIncludeLoc()),
311 /*JustFirst*/ true);
312 }
313}
314
315void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) {
316 SourceLocation Spelling = SM.getSpellingLoc(Loc);
317 SourceLocation Expansion = SM.getExpansionLoc(Loc);
318
319 if (Expansion != Spelling) {
320 // If the expansion and the spelling are different, output subobjects
321 // describing both locations.
322 JOS.attributeObject(Key: "spellingLoc", Contents: [Spelling, this] {
323 writeBareSourceLocation(Loc: Spelling, /*IsSpelling*/ true);
324 });
325 JOS.attributeObject(Key: "expansionLoc", Contents: [Expansion, Loc, this] {
326 writeBareSourceLocation(Loc: Expansion, /*IsSpelling*/ false);
327 // If there is a macro expansion, add extra information if the interesting
328 // bit is the macro arg expansion.
329 if (SM.isMacroArgExpansion(Loc))
330 JOS.attribute(Key: "isMacroArgExpansion", Contents: true);
331 });
332 } else
333 writeBareSourceLocation(Loc: Spelling, /*IsSpelling*/ true);
334}
335
336void JSONNodeDumper::writeSourceRange(SourceRange R) {
337 JOS.attributeObject(Key: "begin",
338 Contents: [R, this] { writeSourceLocation(Loc: R.getBegin()); });
339 JOS.attributeObject(Key: "end", Contents: [R, this] { writeSourceLocation(Loc: R.getEnd()); });
340}
341
342std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) {
343 // Because JSON stores integer values as signed 64-bit integers, trying to
344 // represent them as such makes for very ugly pointer values in the resulting
345 // output. Instead, we convert the value to hex and treat it as a string.
346 return "0x" + llvm::utohexstr(X: reinterpret_cast<uint64_t>(Ptr), LowerCase: true);
347}
348
349llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) {
350 SplitQualType SQT = QT.split();
351 std::string SQTS = QualType::getAsString(split: SQT, Policy: PrintPolicy);
352 llvm::json::Object Ret{{.K: "qualType", .V: SQTS}};
353
354 if (Desugar && !QT.isNull()) {
355 SplitQualType DSQT = QT.getSplitDesugaredType();
356 if (DSQT != SQT) {
357 std::string DSQTS = QualType::getAsString(split: DSQT, Policy: PrintPolicy);
358 if (DSQTS != SQTS)
359 Ret["desugaredQualType"] = DSQTS;
360 }
361 if (const auto *TT = QT->getAs<TypedefType>())
362 Ret["typeAliasDeclId"] = createPointerRepresentation(Ptr: TT->getDecl());
363 }
364 return Ret;
365}
366
367void JSONNodeDumper::writeBareDeclRef(const Decl *D) {
368 JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: D));
369 if (!D)
370 return;
371
372 JOS.attribute(Key: "kind", Contents: (llvm::Twine(D->getDeclKindName()) + "Decl").str());
373 if (const auto *ND = dyn_cast<NamedDecl>(Val: D))
374 JOS.attribute(Key: "name", Contents: ND->getDeclName().getAsString());
375 if (const auto *VD = dyn_cast<ValueDecl>(Val: D))
376 JOS.attribute(Key: "type", Contents: createQualType(QT: VD->getType()));
377}
378
379llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) {
380 llvm::json::Object Ret{{.K: "id", .V: createPointerRepresentation(Ptr: D)}};
381 if (!D)
382 return Ret;
383
384 Ret["kind"] = (llvm::Twine(D->getDeclKindName()) + "Decl").str();
385 if (const auto *ND = dyn_cast<NamedDecl>(Val: D))
386 Ret["name"] = ND->getDeclName().getAsString();
387 if (const auto *VD = dyn_cast<ValueDecl>(Val: D))
388 Ret["type"] = createQualType(QT: VD->getType());
389 return Ret;
390}
391
392llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) {
393 llvm::json::Array Ret;
394 if (C->path_empty())
395 return Ret;
396
397 for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) {
398 const CXXBaseSpecifier *Base = *I;
399 const auto *RD =
400 cast<CXXRecordDecl>(Val: Base->getType()->castAs<RecordType>()->getDecl());
401
402 llvm::json::Object Val{{.K: "name", .V: RD->getName()}};
403 if (Base->isVirtual())
404 Val["isVirtual"] = true;
405 Ret.push_back(E: std::move(Val));
406 }
407 return Ret;
408}
409
410#define FIELD2(Name, Flag) if (RD->Flag()) Ret[Name] = true
411#define FIELD1(Flag) FIELD2(#Flag, Flag)
412
413static llvm::json::Object
414createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) {
415 llvm::json::Object Ret;
416
417 FIELD2("exists", hasDefaultConstructor);
418 FIELD2("trivial", hasTrivialDefaultConstructor);
419 FIELD2("nonTrivial", hasNonTrivialDefaultConstructor);
420 FIELD2("userProvided", hasUserProvidedDefaultConstructor);
421 FIELD2("isConstexpr", hasConstexprDefaultConstructor);
422 FIELD2("needsImplicit", needsImplicitDefaultConstructor);
423 FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr);
424
425 return Ret;
426}
427
428static llvm::json::Object
429createCopyConstructorDefinitionData(const CXXRecordDecl *RD) {
430 llvm::json::Object Ret;
431
432 FIELD2("simple", hasSimpleCopyConstructor);
433 FIELD2("trivial", hasTrivialCopyConstructor);
434 FIELD2("nonTrivial", hasNonTrivialCopyConstructor);
435 FIELD2("userDeclared", hasUserDeclaredCopyConstructor);
436 FIELD2("hasConstParam", hasCopyConstructorWithConstParam);
437 FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam);
438 FIELD2("needsImplicit", needsImplicitCopyConstructor);
439 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor);
440 if (!RD->needsOverloadResolutionForCopyConstructor())
441 FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted);
442
443 return Ret;
444}
445
446static llvm::json::Object
447createMoveConstructorDefinitionData(const CXXRecordDecl *RD) {
448 llvm::json::Object Ret;
449
450 FIELD2("exists", hasMoveConstructor);
451 FIELD2("simple", hasSimpleMoveConstructor);
452 FIELD2("trivial", hasTrivialMoveConstructor);
453 FIELD2("nonTrivial", hasNonTrivialMoveConstructor);
454 FIELD2("userDeclared", hasUserDeclaredMoveConstructor);
455 FIELD2("needsImplicit", needsImplicitMoveConstructor);
456 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor);
457 if (!RD->needsOverloadResolutionForMoveConstructor())
458 FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted);
459
460 return Ret;
461}
462
463static llvm::json::Object
464createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) {
465 llvm::json::Object Ret;
466
467 FIELD2("simple", hasSimpleCopyAssignment);
468 FIELD2("trivial", hasTrivialCopyAssignment);
469 FIELD2("nonTrivial", hasNonTrivialCopyAssignment);
470 FIELD2("hasConstParam", hasCopyAssignmentWithConstParam);
471 FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam);
472 FIELD2("userDeclared", hasUserDeclaredCopyAssignment);
473 FIELD2("needsImplicit", needsImplicitCopyAssignment);
474 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment);
475
476 return Ret;
477}
478
479static llvm::json::Object
480createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) {
481 llvm::json::Object Ret;
482
483 FIELD2("exists", hasMoveAssignment);
484 FIELD2("simple", hasSimpleMoveAssignment);
485 FIELD2("trivial", hasTrivialMoveAssignment);
486 FIELD2("nonTrivial", hasNonTrivialMoveAssignment);
487 FIELD2("userDeclared", hasUserDeclaredMoveAssignment);
488 FIELD2("needsImplicit", needsImplicitMoveAssignment);
489 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment);
490
491 return Ret;
492}
493
494static llvm::json::Object
495createDestructorDefinitionData(const CXXRecordDecl *RD) {
496 llvm::json::Object Ret;
497
498 FIELD2("simple", hasSimpleDestructor);
499 FIELD2("irrelevant", hasIrrelevantDestructor);
500 FIELD2("trivial", hasTrivialDestructor);
501 FIELD2("nonTrivial", hasNonTrivialDestructor);
502 FIELD2("userDeclared", hasUserDeclaredDestructor);
503 FIELD2("needsImplicit", needsImplicitDestructor);
504 FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor);
505 if (!RD->needsOverloadResolutionForDestructor())
506 FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted);
507
508 return Ret;
509}
510
511llvm::json::Object
512JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) {
513 llvm::json::Object Ret;
514
515 // This data is common to all C++ classes.
516 FIELD1(isGenericLambda);
517 FIELD1(isLambda);
518 FIELD1(isEmpty);
519 FIELD1(isAggregate);
520 FIELD1(isStandardLayout);
521 FIELD1(isTriviallyCopyable);
522 FIELD1(isPOD);
523 FIELD1(isTrivial);
524 FIELD1(isPolymorphic);
525 FIELD1(isAbstract);
526 FIELD1(isLiteral);
527 FIELD1(canPassInRegisters);
528 FIELD1(hasUserDeclaredConstructor);
529 FIELD1(hasConstexprNonCopyMoveConstructor);
530 FIELD1(hasMutableFields);
531 FIELD1(hasVariantMembers);
532 FIELD2("canConstDefaultInit", allowConstDefaultInit);
533
534 Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD);
535 Ret["copyCtor"] = createCopyConstructorDefinitionData(RD);
536 Ret["moveCtor"] = createMoveConstructorDefinitionData(RD);
537 Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD);
538 Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD);
539 Ret["dtor"] = createDestructorDefinitionData(RD);
540
541 return Ret;
542}
543
544#undef FIELD1
545#undef FIELD2
546
547std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) {
548 const auto AccessSpelling = getAccessSpelling(AS);
549 if (AccessSpelling.empty())
550 return "none";
551 return AccessSpelling.str();
552}
553
554llvm::json::Object
555JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) {
556 llvm::json::Object Ret;
557
558 Ret["type"] = createQualType(QT: BS.getType());
559 Ret["access"] = createAccessSpecifier(AS: BS.getAccessSpecifier());
560 Ret["writtenAccess"] =
561 createAccessSpecifier(AS: BS.getAccessSpecifierAsWritten());
562 if (BS.isVirtual())
563 Ret["isVirtual"] = true;
564 if (BS.isPackExpansion())
565 Ret["isPackExpansion"] = true;
566
567 return Ret;
568}
569
570void JSONNodeDumper::VisitAliasAttr(const AliasAttr *AA) {
571 JOS.attribute(Key: "aliasee", Contents: AA->getAliasee());
572}
573
574void JSONNodeDumper::VisitCleanupAttr(const CleanupAttr *CA) {
575 JOS.attribute(Key: "cleanup_function", Contents: createBareDeclRef(D: CA->getFunctionDecl()));
576}
577
578void JSONNodeDumper::VisitDeprecatedAttr(const DeprecatedAttr *DA) {
579 if (!DA->getMessage().empty())
580 JOS.attribute(Key: "message", Contents: DA->getMessage());
581 if (!DA->getReplacement().empty())
582 JOS.attribute(Key: "replacement", Contents: DA->getReplacement());
583}
584
585void JSONNodeDumper::VisitUnavailableAttr(const UnavailableAttr *UA) {
586 if (!UA->getMessage().empty())
587 JOS.attribute(Key: "message", Contents: UA->getMessage());
588}
589
590void JSONNodeDumper::VisitSectionAttr(const SectionAttr *SA) {
591 JOS.attribute(Key: "section_name", Contents: SA->getName());
592}
593
594void JSONNodeDumper::VisitVisibilityAttr(const VisibilityAttr *VA) {
595 JOS.attribute(Key: "visibility", Contents: VisibilityAttr::ConvertVisibilityTypeToStr(
596 Val: VA->getVisibility()));
597}
598
599void JSONNodeDumper::VisitTLSModelAttr(const TLSModelAttr *TA) {
600 JOS.attribute(Key: "tls_model", Contents: TA->getModel());
601}
602
603void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {
604 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TT->getDecl()));
605 if (!TT->typeMatchesDecl())
606 JOS.attribute(Key: "type", Contents: createQualType(QT: TT->desugar()));
607}
608
609void JSONNodeDumper::VisitUsingType(const UsingType *TT) {
610 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TT->getFoundDecl()));
611 if (!TT->typeMatchesDecl())
612 JOS.attribute(Key: "type", Contents: createQualType(QT: TT->desugar()));
613}
614
615void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {
616 FunctionType::ExtInfo E = T->getExtInfo();
617 attributeOnlyIfTrue(Key: "noreturn", Value: E.getNoReturn());
618 attributeOnlyIfTrue(Key: "producesResult", Value: E.getProducesResult());
619 if (E.getHasRegParm())
620 JOS.attribute(Key: "regParm", Contents: E.getRegParm());
621 JOS.attribute(Key: "cc", Contents: FunctionType::getNameForCallConv(CC: E.getCC()));
622}
623
624void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
625 FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo();
626 attributeOnlyIfTrue(Key: "trailingReturn", Value: E.HasTrailingReturn);
627 attributeOnlyIfTrue(Key: "const", Value: T->isConst());
628 attributeOnlyIfTrue(Key: "volatile", Value: T->isVolatile());
629 attributeOnlyIfTrue(Key: "restrict", Value: T->isRestrict());
630 attributeOnlyIfTrue(Key: "variadic", Value: E.Variadic);
631 switch (E.RefQualifier) {
632 case RQ_LValue: JOS.attribute(Key: "refQualifier", Contents: "&"); break;
633 case RQ_RValue: JOS.attribute(Key: "refQualifier", Contents: "&&"); break;
634 case RQ_None: break;
635 }
636 switch (E.ExceptionSpec.Type) {
637 case EST_DynamicNone:
638 case EST_Dynamic: {
639 JOS.attribute(Key: "exceptionSpec", Contents: "throw");
640 llvm::json::Array Types;
641 for (QualType QT : E.ExceptionSpec.Exceptions)
642 Types.push_back(E: createQualType(QT));
643 JOS.attribute(Key: "exceptionTypes", Contents: std::move(Types));
644 } break;
645 case EST_MSAny:
646 JOS.attribute(Key: "exceptionSpec", Contents: "throw");
647 JOS.attribute(Key: "throwsAny", Contents: true);
648 break;
649 case EST_BasicNoexcept:
650 JOS.attribute(Key: "exceptionSpec", Contents: "noexcept");
651 break;
652 case EST_NoexceptTrue:
653 case EST_NoexceptFalse:
654 JOS.attribute(Key: "exceptionSpec", Contents: "noexcept");
655 JOS.attribute(Key: "conditionEvaluatesTo",
656 Contents: E.ExceptionSpec.Type == EST_NoexceptTrue);
657 //JOS.attributeWithCall("exceptionSpecExpr",
658 // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); });
659 break;
660 case EST_NoThrow:
661 JOS.attribute(Key: "exceptionSpec", Contents: "nothrow");
662 break;
663 // FIXME: I cannot find a way to trigger these cases while dumping the AST. I
664 // suspect you can only run into them when executing an AST dump from within
665 // the debugger, which is not a use case we worry about for the JSON dumping
666 // feature.
667 case EST_DependentNoexcept:
668 case EST_Unevaluated:
669 case EST_Uninstantiated:
670 case EST_Unparsed:
671 case EST_None: break;
672 }
673 VisitFunctionType(T);
674}
675
676void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType *RT) {
677 attributeOnlyIfTrue(Key: "spelledAsLValue", Value: RT->isSpelledAsLValue());
678}
679
680void JSONNodeDumper::VisitArrayType(const ArrayType *AT) {
681 switch (AT->getSizeModifier()) {
682 case ArraySizeModifier::Star:
683 JOS.attribute(Key: "sizeModifier", Contents: "*");
684 break;
685 case ArraySizeModifier::Static:
686 JOS.attribute(Key: "sizeModifier", Contents: "static");
687 break;
688 case ArraySizeModifier::Normal:
689 break;
690 }
691
692 std::string Str = AT->getIndexTypeQualifiers().getAsString();
693 if (!Str.empty())
694 JOS.attribute(Key: "indexTypeQualifiers", Contents: Str);
695}
696
697void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) {
698 // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a
699 // narrowing conversion to int64_t so it cannot be expressed.
700 JOS.attribute(Key: "size", Contents: CAT->getSExtSize());
701 VisitArrayType(AT: CAT);
702}
703
704void JSONNodeDumper::VisitDependentSizedExtVectorType(
705 const DependentSizedExtVectorType *VT) {
706 JOS.attributeObject(
707 Key: "attrLoc", Contents: [VT, this] { writeSourceLocation(Loc: VT->getAttributeLoc()); });
708}
709
710void JSONNodeDumper::VisitVectorType(const VectorType *VT) {
711 JOS.attribute(Key: "numElements", Contents: VT->getNumElements());
712 switch (VT->getVectorKind()) {
713 case VectorKind::Generic:
714 break;
715 case VectorKind::AltiVecVector:
716 JOS.attribute(Key: "vectorKind", Contents: "altivec");
717 break;
718 case VectorKind::AltiVecPixel:
719 JOS.attribute(Key: "vectorKind", Contents: "altivec pixel");
720 break;
721 case VectorKind::AltiVecBool:
722 JOS.attribute(Key: "vectorKind", Contents: "altivec bool");
723 break;
724 case VectorKind::Neon:
725 JOS.attribute(Key: "vectorKind", Contents: "neon");
726 break;
727 case VectorKind::NeonPoly:
728 JOS.attribute(Key: "vectorKind", Contents: "neon poly");
729 break;
730 case VectorKind::SveFixedLengthData:
731 JOS.attribute(Key: "vectorKind", Contents: "fixed-length sve data vector");
732 break;
733 case VectorKind::SveFixedLengthPredicate:
734 JOS.attribute(Key: "vectorKind", Contents: "fixed-length sve predicate vector");
735 break;
736 case VectorKind::RVVFixedLengthData:
737 JOS.attribute(Key: "vectorKind", Contents: "fixed-length rvv data vector");
738 break;
739 case VectorKind::RVVFixedLengthMask:
740 JOS.attribute(Key: "vectorKind", Contents: "fixed-length rvv mask vector");
741 break;
742 }
743}
744
745void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {
746 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: UUT->getDecl()));
747}
748
749void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) {
750 switch (UTT->getUTTKind()) {
751#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
752 case UnaryTransformType::Enum: \
753 JOS.attribute("transformKind", #Trait); \
754 break;
755#include "clang/Basic/TransformTypeTraits.def"
756 }
757}
758
759void JSONNodeDumper::VisitTagType(const TagType *TT) {
760 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TT->getDecl()));
761}
762
763void JSONNodeDumper::VisitTemplateTypeParmType(
764 const TemplateTypeParmType *TTPT) {
765 JOS.attribute(Key: "depth", Contents: TTPT->getDepth());
766 JOS.attribute(Key: "index", Contents: TTPT->getIndex());
767 attributeOnlyIfTrue(Key: "isPack", Value: TTPT->isParameterPack());
768 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TTPT->getDecl()));
769}
770
771void JSONNodeDumper::VisitSubstTemplateTypeParmType(
772 const SubstTemplateTypeParmType *STTPT) {
773 JOS.attribute(Key: "index", Contents: STTPT->getIndex());
774 if (auto PackIndex = STTPT->getPackIndex())
775 JOS.attribute(Key: "pack_index", Contents: *PackIndex);
776}
777
778void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
779 const SubstTemplateTypeParmPackType *T) {
780 JOS.attribute(Key: "index", Contents: T->getIndex());
781}
782
783void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
784 JOS.attribute(Key: "undeduced", Contents: !AT->isDeduced());
785 switch (AT->getKeyword()) {
786 case AutoTypeKeyword::Auto:
787 JOS.attribute(Key: "typeKeyword", Contents: "auto");
788 break;
789 case AutoTypeKeyword::DecltypeAuto:
790 JOS.attribute(Key: "typeKeyword", Contents: "decltype(auto)");
791 break;
792 case AutoTypeKeyword::GNUAutoType:
793 JOS.attribute(Key: "typeKeyword", Contents: "__auto_type");
794 break;
795 }
796}
797
798void JSONNodeDumper::VisitTemplateSpecializationType(
799 const TemplateSpecializationType *TST) {
800 attributeOnlyIfTrue(Key: "isAlias", Value: TST->isTypeAlias());
801
802 std::string Str;
803 llvm::raw_string_ostream OS(Str);
804 TST->getTemplateName().print(OS, Policy: PrintPolicy);
805 JOS.attribute(Key: "templateName", Contents: Str);
806}
807
808void JSONNodeDumper::VisitInjectedClassNameType(
809 const InjectedClassNameType *ICNT) {
810 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: ICNT->getDecl()));
811}
812
813void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {
814 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: OIT->getDecl()));
815}
816
817void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) {
818 if (std::optional<unsigned> N = PET->getNumExpansions())
819 JOS.attribute(Key: "numExpansions", Contents: *N);
820}
821
822void JSONNodeDumper::VisitElaboratedType(const ElaboratedType *ET) {
823 if (const NestedNameSpecifier *NNS = ET->getQualifier()) {
824 std::string Str;
825 llvm::raw_string_ostream OS(Str);
826 NNS->print(OS, Policy: PrintPolicy, /*ResolveTemplateArgs*/ ResolveTemplateArguments: true);
827 JOS.attribute(Key: "qualifier", Contents: Str);
828 }
829 if (const TagDecl *TD = ET->getOwnedTagDecl())
830 JOS.attribute(Key: "ownedTagDecl", Contents: createBareDeclRef(D: TD));
831}
832
833void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) {
834 JOS.attribute(Key: "macroName", Contents: MQT->getMacroIdentifier()->getName());
835}
836
837void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) {
838 attributeOnlyIfTrue(Key: "isData", Value: MPT->isMemberDataPointer());
839 attributeOnlyIfTrue(Key: "isFunction", Value: MPT->isMemberFunctionPointer());
840}
841
842void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {
843 if (ND && ND->getDeclName()) {
844 JOS.attribute(Key: "name", Contents: ND->getNameAsString());
845 // FIXME: There are likely other contexts in which it makes no sense to ask
846 // for a mangled name.
847 if (isa<RequiresExprBodyDecl>(Val: ND->getDeclContext()))
848 return;
849
850 // If the declaration is dependent or is in a dependent context, then the
851 // mangling is unlikely to be meaningful (and in some cases may cause
852 // "don't know how to mangle this" assertion failures.
853 if (ND->isTemplated())
854 return;
855
856 // Mangled names are not meaningful for locals, and may not be well-defined
857 // in the case of VLAs.
858 auto *VD = dyn_cast<VarDecl>(Val: ND);
859 if (VD && VD->hasLocalStorage())
860 return;
861
862 // Do not mangle template deduction guides.
863 if (isa<CXXDeductionGuideDecl>(Val: ND))
864 return;
865
866 std::string MangledName = ASTNameGen.getName(D: ND);
867 if (!MangledName.empty())
868 JOS.attribute(Key: "mangledName", Contents: MangledName);
869 }
870}
871
872void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) {
873 VisitNamedDecl(ND: TD);
874 JOS.attribute(Key: "type", Contents: createQualType(QT: TD->getUnderlyingType()));
875}
876
877void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) {
878 VisitNamedDecl(ND: TAD);
879 JOS.attribute(Key: "type", Contents: createQualType(QT: TAD->getUnderlyingType()));
880}
881
882void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {
883 VisitNamedDecl(ND);
884 attributeOnlyIfTrue(Key: "isInline", Value: ND->isInline());
885 attributeOnlyIfTrue(Key: "isNested", Value: ND->isNested());
886 if (!ND->isFirstDecl())
887 JOS.attribute(Key: "originalNamespace", Contents: createBareDeclRef(D: ND->getFirstDecl()));
888}
889
890void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {
891 JOS.attribute(Key: "nominatedNamespace",
892 Contents: createBareDeclRef(D: UDD->getNominatedNamespace()));
893}
894
895void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {
896 VisitNamedDecl(ND: NAD);
897 JOS.attribute(Key: "aliasedNamespace",
898 Contents: createBareDeclRef(D: NAD->getAliasedNamespace()));
899}
900
901void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) {
902 std::string Name;
903 if (const NestedNameSpecifier *NNS = UD->getQualifier()) {
904 llvm::raw_string_ostream SOS(Name);
905 NNS->print(OS&: SOS, Policy: UD->getASTContext().getPrintingPolicy());
906 }
907 Name += UD->getNameAsString();
908 JOS.attribute(Key: "name", Contents: Name);
909}
910
911void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) {
912 JOS.attribute(Key: "target", Contents: createBareDeclRef(D: UED->getEnumDecl()));
913}
914
915void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) {
916 JOS.attribute(Key: "target", Contents: createBareDeclRef(D: USD->getTargetDecl()));
917}
918
919void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) {
920 VisitNamedDecl(ND: VD);
921 JOS.attribute(Key: "type", Contents: createQualType(QT: VD->getType()));
922 if (const auto *P = dyn_cast<ParmVarDecl>(Val: VD))
923 attributeOnlyIfTrue(Key: "explicitObjectParameter",
924 Value: P->isExplicitObjectParameter());
925
926 StorageClass SC = VD->getStorageClass();
927 if (SC != SC_None)
928 JOS.attribute(Key: "storageClass", Contents: VarDecl::getStorageClassSpecifierString(SC));
929 switch (VD->getTLSKind()) {
930 case VarDecl::TLS_Dynamic: JOS.attribute(Key: "tls", Contents: "dynamic"); break;
931 case VarDecl::TLS_Static: JOS.attribute(Key: "tls", Contents: "static"); break;
932 case VarDecl::TLS_None: break;
933 }
934 attributeOnlyIfTrue(Key: "nrvo", Value: VD->isNRVOVariable());
935 attributeOnlyIfTrue(Key: "inline", Value: VD->isInline());
936 attributeOnlyIfTrue(Key: "constexpr", Value: VD->isConstexpr());
937 attributeOnlyIfTrue(Key: "modulePrivate", Value: VD->isModulePrivate());
938 if (VD->hasInit()) {
939 switch (VD->getInitStyle()) {
940 case VarDecl::CInit: JOS.attribute(Key: "init", Contents: "c"); break;
941 case VarDecl::CallInit: JOS.attribute(Key: "init", Contents: "call"); break;
942 case VarDecl::ListInit: JOS.attribute(Key: "init", Contents: "list"); break;
943 case VarDecl::ParenListInit:
944 JOS.attribute(Key: "init", Contents: "paren-list");
945 break;
946 }
947 }
948 attributeOnlyIfTrue(Key: "isParameterPack", Value: VD->isParameterPack());
949}
950
951void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {
952 VisitNamedDecl(ND: FD);
953 JOS.attribute(Key: "type", Contents: createQualType(QT: FD->getType()));
954 attributeOnlyIfTrue(Key: "mutable", Value: FD->isMutable());
955 attributeOnlyIfTrue(Key: "modulePrivate", Value: FD->isModulePrivate());
956 attributeOnlyIfTrue(Key: "isBitfield", Value: FD->isBitField());
957 attributeOnlyIfTrue(Key: "hasInClassInitializer", Value: FD->hasInClassInitializer());
958}
959
960void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
961 VisitNamedDecl(ND: FD);
962 JOS.attribute(Key: "type", Contents: createQualType(QT: FD->getType()));
963 StorageClass SC = FD->getStorageClass();
964 if (SC != SC_None)
965 JOS.attribute(Key: "storageClass", Contents: VarDecl::getStorageClassSpecifierString(SC));
966 attributeOnlyIfTrue(Key: "inline", Value: FD->isInlineSpecified());
967 attributeOnlyIfTrue(Key: "virtual", Value: FD->isVirtualAsWritten());
968 attributeOnlyIfTrue(Key: "pure", Value: FD->isPureVirtual());
969 attributeOnlyIfTrue(Key: "explicitlyDeleted", Value: FD->isDeletedAsWritten());
970 attributeOnlyIfTrue(Key: "constexpr", Value: FD->isConstexpr());
971 attributeOnlyIfTrue(Key: "variadic", Value: FD->isVariadic());
972 attributeOnlyIfTrue(Key: "immediate", Value: FD->isImmediateFunction());
973
974 if (FD->isDefaulted())
975 JOS.attribute(Key: "explicitlyDefaulted",
976 Contents: FD->isDeleted() ? "deleted" : "default");
977
978 if (StringLiteral *Msg = FD->getDeletedMessage())
979 JOS.attribute(Key: "deletedMessage", Contents: Msg->getString());
980}
981
982void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) {
983 VisitNamedDecl(ND: ED);
984 if (ED->isFixed())
985 JOS.attribute(Key: "fixedUnderlyingType", Contents: createQualType(QT: ED->getIntegerType()));
986 if (ED->isScoped())
987 JOS.attribute(Key: "scopedEnumTag",
988 Contents: ED->isScopedUsingClassTag() ? "class" : "struct");
989}
990void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) {
991 VisitNamedDecl(ND: ECD);
992 JOS.attribute(Key: "type", Contents: createQualType(QT: ECD->getType()));
993}
994
995void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
996 VisitNamedDecl(ND: RD);
997 JOS.attribute(Key: "tagUsed", Contents: RD->getKindName());
998 attributeOnlyIfTrue(Key: "completeDefinition", Value: RD->isCompleteDefinition());
999}
1000void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
1001 VisitRecordDecl(RD);
1002
1003 // All other information requires a complete definition.
1004 if (!RD->isCompleteDefinition())
1005 return;
1006
1007 JOS.attribute(Key: "definitionData", Contents: createCXXRecordDefinitionData(RD));
1008 if (RD->getNumBases()) {
1009 JOS.attributeArray(Key: "bases", Contents: [this, RD] {
1010 for (const auto &Spec : RD->bases())
1011 JOS.value(V: createCXXBaseSpecifier(BS: Spec));
1012 });
1013 }
1014}
1015
1016void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
1017 VisitNamedDecl(ND: D);
1018 JOS.attribute(Key: "bufferKind", Contents: D->isCBuffer() ? "cbuffer" : "tbuffer");
1019}
1020
1021void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
1022 VisitNamedDecl(ND: D);
1023 JOS.attribute(Key: "tagUsed", Contents: D->wasDeclaredWithTypename() ? "typename" : "class");
1024 JOS.attribute(Key: "depth", Contents: D->getDepth());
1025 JOS.attribute(Key: "index", Contents: D->getIndex());
1026 attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack());
1027
1028 if (D->hasDefaultArgument())
1029 JOS.attributeObject(Key: "defaultArg", Contents: [=] {
1030 Visit(TA: D->getDefaultArgument().getArgument(), R: SourceRange(),
1031 From: D->getDefaultArgStorage().getInheritedFrom(),
1032 Label: D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1033 });
1034}
1035
1036void JSONNodeDumper::VisitNonTypeTemplateParmDecl(
1037 const NonTypeTemplateParmDecl *D) {
1038 VisitNamedDecl(ND: D);
1039 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1040 JOS.attribute(Key: "depth", Contents: D->getDepth());
1041 JOS.attribute(Key: "index", Contents: D->getIndex());
1042 attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack());
1043
1044 if (D->hasDefaultArgument())
1045 JOS.attributeObject(Key: "defaultArg", Contents: [=] {
1046 Visit(TA: D->getDefaultArgument().getArgument(), R: SourceRange(),
1047 From: D->getDefaultArgStorage().getInheritedFrom(),
1048 Label: D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1049 });
1050}
1051
1052void JSONNodeDumper::VisitTemplateTemplateParmDecl(
1053 const TemplateTemplateParmDecl *D) {
1054 VisitNamedDecl(ND: D);
1055 JOS.attribute(Key: "depth", Contents: D->getDepth());
1056 JOS.attribute(Key: "index", Contents: D->getIndex());
1057 attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack());
1058
1059 if (D->hasDefaultArgument())
1060 JOS.attributeObject(Key: "defaultArg", Contents: [=] {
1061 const auto *InheritedFrom = D->getDefaultArgStorage().getInheritedFrom();
1062 Visit(TA: D->getDefaultArgument().getArgument(),
1063 R: InheritedFrom ? InheritedFrom->getSourceRange() : SourceLocation{},
1064 From: InheritedFrom,
1065 Label: D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1066 });
1067}
1068
1069void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) {
1070 StringRef Lang;
1071 switch (LSD->getLanguage()) {
1072 case LinkageSpecLanguageIDs::C:
1073 Lang = "C";
1074 break;
1075 case LinkageSpecLanguageIDs::CXX:
1076 Lang = "C++";
1077 break;
1078 }
1079 JOS.attribute(Key: "language", Contents: Lang);
1080 attributeOnlyIfTrue(Key: "hasBraces", Value: LSD->hasBraces());
1081}
1082
1083void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) {
1084 JOS.attribute(Key: "access", Contents: createAccessSpecifier(AS: ASD->getAccess()));
1085}
1086
1087void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) {
1088 if (const TypeSourceInfo *T = FD->getFriendType())
1089 JOS.attribute(Key: "type", Contents: createQualType(QT: T->getType()));
1090}
1091
1092void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
1093 VisitNamedDecl(ND: D);
1094 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1095 attributeOnlyIfTrue(Key: "synthesized", Value: D->getSynthesize());
1096 switch (D->getAccessControl()) {
1097 case ObjCIvarDecl::None: JOS.attribute(Key: "access", Contents: "none"); break;
1098 case ObjCIvarDecl::Private: JOS.attribute(Key: "access", Contents: "private"); break;
1099 case ObjCIvarDecl::Protected: JOS.attribute(Key: "access", Contents: "protected"); break;
1100 case ObjCIvarDecl::Public: JOS.attribute(Key: "access", Contents: "public"); break;
1101 case ObjCIvarDecl::Package: JOS.attribute(Key: "access", Contents: "package"); break;
1102 }
1103}
1104
1105void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
1106 VisitNamedDecl(ND: D);
1107 JOS.attribute(Key: "returnType", Contents: createQualType(QT: D->getReturnType()));
1108 JOS.attribute(Key: "instance", Contents: D->isInstanceMethod());
1109 attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic());
1110}
1111
1112void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
1113 VisitNamedDecl(ND: D);
1114 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getUnderlyingType()));
1115 attributeOnlyIfTrue(Key: "bounded", Value: D->hasExplicitBound());
1116 switch (D->getVariance()) {
1117 case ObjCTypeParamVariance::Invariant:
1118 break;
1119 case ObjCTypeParamVariance::Covariant:
1120 JOS.attribute(Key: "variance", Contents: "covariant");
1121 break;
1122 case ObjCTypeParamVariance::Contravariant:
1123 JOS.attribute(Key: "variance", Contents: "contravariant");
1124 break;
1125 }
1126}
1127
1128void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
1129 VisitNamedDecl(ND: D);
1130 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1131 JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D: D->getImplementation()));
1132
1133 llvm::json::Array Protocols;
1134 for (const auto* P : D->protocols())
1135 Protocols.push_back(E: createBareDeclRef(D: P));
1136 if (!Protocols.empty())
1137 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1138}
1139
1140void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
1141 VisitNamedDecl(ND: D);
1142 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1143 JOS.attribute(Key: "categoryDecl", Contents: createBareDeclRef(D: D->getCategoryDecl()));
1144}
1145
1146void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
1147 VisitNamedDecl(ND: D);
1148
1149 llvm::json::Array Protocols;
1150 for (const auto *P : D->protocols())
1151 Protocols.push_back(E: createBareDeclRef(D: P));
1152 if (!Protocols.empty())
1153 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1154}
1155
1156void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
1157 VisitNamedDecl(ND: D);
1158 JOS.attribute(Key: "super", Contents: createBareDeclRef(D: D->getSuperClass()));
1159 JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D: D->getImplementation()));
1160
1161 llvm::json::Array Protocols;
1162 for (const auto* P : D->protocols())
1163 Protocols.push_back(E: createBareDeclRef(D: P));
1164 if (!Protocols.empty())
1165 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1166}
1167
1168void JSONNodeDumper::VisitObjCImplementationDecl(
1169 const ObjCImplementationDecl *D) {
1170 VisitNamedDecl(ND: D);
1171 JOS.attribute(Key: "super", Contents: createBareDeclRef(D: D->getSuperClass()));
1172 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1173}
1174
1175void JSONNodeDumper::VisitObjCCompatibleAliasDecl(
1176 const ObjCCompatibleAliasDecl *D) {
1177 VisitNamedDecl(ND: D);
1178 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1179}
1180
1181void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1182 VisitNamedDecl(ND: D);
1183 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1184
1185 switch (D->getPropertyImplementation()) {
1186 case ObjCPropertyDecl::None: break;
1187 case ObjCPropertyDecl::Required: JOS.attribute(Key: "control", Contents: "required"); break;
1188 case ObjCPropertyDecl::Optional: JOS.attribute(Key: "control", Contents: "optional"); break;
1189 }
1190
1191 ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
1192 if (Attrs != ObjCPropertyAttribute::kind_noattr) {
1193 if (Attrs & ObjCPropertyAttribute::kind_getter)
1194 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: D->getGetterMethodDecl()));
1195 if (Attrs & ObjCPropertyAttribute::kind_setter)
1196 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: D->getSetterMethodDecl()));
1197 attributeOnlyIfTrue(Key: "readonly",
1198 Value: Attrs & ObjCPropertyAttribute::kind_readonly);
1199 attributeOnlyIfTrue(Key: "assign", Value: Attrs & ObjCPropertyAttribute::kind_assign);
1200 attributeOnlyIfTrue(Key: "readwrite",
1201 Value: Attrs & ObjCPropertyAttribute::kind_readwrite);
1202 attributeOnlyIfTrue(Key: "retain", Value: Attrs & ObjCPropertyAttribute::kind_retain);
1203 attributeOnlyIfTrue(Key: "copy", Value: Attrs & ObjCPropertyAttribute::kind_copy);
1204 attributeOnlyIfTrue(Key: "nonatomic",
1205 Value: Attrs & ObjCPropertyAttribute::kind_nonatomic);
1206 attributeOnlyIfTrue(Key: "atomic", Value: Attrs & ObjCPropertyAttribute::kind_atomic);
1207 attributeOnlyIfTrue(Key: "weak", Value: Attrs & ObjCPropertyAttribute::kind_weak);
1208 attributeOnlyIfTrue(Key: "strong", Value: Attrs & ObjCPropertyAttribute::kind_strong);
1209 attributeOnlyIfTrue(Key: "unsafe_unretained",
1210 Value: Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);
1211 attributeOnlyIfTrue(Key: "class", Value: Attrs & ObjCPropertyAttribute::kind_class);
1212 attributeOnlyIfTrue(Key: "direct", Value: Attrs & ObjCPropertyAttribute::kind_direct);
1213 attributeOnlyIfTrue(Key: "nullability",
1214 Value: Attrs & ObjCPropertyAttribute::kind_nullability);
1215 attributeOnlyIfTrue(Key: "null_resettable",
1216 Value: Attrs & ObjCPropertyAttribute::kind_null_resettable);
1217 }
1218}
1219
1220void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1221 VisitNamedDecl(ND: D->getPropertyDecl());
1222 JOS.attribute(Key: "implKind", Contents: D->getPropertyImplementation() ==
1223 ObjCPropertyImplDecl::Synthesize
1224 ? "synthesize"
1225 : "dynamic");
1226 JOS.attribute(Key: "propertyDecl", Contents: createBareDeclRef(D: D->getPropertyDecl()));
1227 JOS.attribute(Key: "ivarDecl", Contents: createBareDeclRef(D: D->getPropertyIvarDecl()));
1228}
1229
1230void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) {
1231 attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic());
1232 attributeOnlyIfTrue(Key: "capturesThis", Value: D->capturesCXXThis());
1233}
1234
1235void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
1236 JOS.attribute(Key: "name", Contents: AE->getOpAsString());
1237}
1238
1239void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) {
1240 JOS.attribute(Key: "encodedType", Contents: createQualType(QT: OEE->getEncodedType()));
1241}
1242
1243void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *OME) {
1244 std::string Str;
1245 llvm::raw_string_ostream OS(Str);
1246
1247 OME->getSelector().print(OS);
1248 JOS.attribute(Key: "selector", Contents: Str);
1249
1250 switch (OME->getReceiverKind()) {
1251 case ObjCMessageExpr::Instance:
1252 JOS.attribute(Key: "receiverKind", Contents: "instance");
1253 break;
1254 case ObjCMessageExpr::Class:
1255 JOS.attribute(Key: "receiverKind", Contents: "class");
1256 JOS.attribute(Key: "classType", Contents: createQualType(QT: OME->getClassReceiver()));
1257 break;
1258 case ObjCMessageExpr::SuperInstance:
1259 JOS.attribute(Key: "receiverKind", Contents: "super (instance)");
1260 JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType()));
1261 break;
1262 case ObjCMessageExpr::SuperClass:
1263 JOS.attribute(Key: "receiverKind", Contents: "super (class)");
1264 JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType()));
1265 break;
1266 }
1267
1268 QualType CallReturnTy = OME->getCallReturnType(Ctx);
1269 if (OME->getType() != CallReturnTy)
1270 JOS.attribute(Key: "callReturnType", Contents: createQualType(QT: CallReturnTy));
1271}
1272
1273void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE) {
1274 if (const ObjCMethodDecl *MD = OBE->getBoxingMethod()) {
1275 std::string Str;
1276 llvm::raw_string_ostream OS(Str);
1277
1278 MD->getSelector().print(OS);
1279 JOS.attribute(Key: "selector", Contents: Str);
1280 }
1281}
1282
1283void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE) {
1284 std::string Str;
1285 llvm::raw_string_ostream OS(Str);
1286
1287 OSE->getSelector().print(OS);
1288 JOS.attribute(Key: "selector", Contents: Str);
1289}
1290
1291void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {
1292 JOS.attribute(Key: "protocol", Contents: createBareDeclRef(D: OPE->getProtocol()));
1293}
1294
1295void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {
1296 if (OPRE->isImplicitProperty()) {
1297 JOS.attribute(Key: "propertyKind", Contents: "implicit");
1298 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter())
1299 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: MD));
1300 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter())
1301 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: MD));
1302 } else {
1303 JOS.attribute(Key: "propertyKind", Contents: "explicit");
1304 JOS.attribute(Key: "property", Contents: createBareDeclRef(D: OPRE->getExplicitProperty()));
1305 }
1306
1307 attributeOnlyIfTrue(Key: "isSuperReceiver", Value: OPRE->isSuperReceiver());
1308 attributeOnlyIfTrue(Key: "isMessagingGetter", Value: OPRE->isMessagingGetter());
1309 attributeOnlyIfTrue(Key: "isMessagingSetter", Value: OPRE->isMessagingSetter());
1310}
1311
1312void JSONNodeDumper::VisitObjCSubscriptRefExpr(
1313 const ObjCSubscriptRefExpr *OSRE) {
1314 JOS.attribute(Key: "subscriptKind",
1315 Contents: OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary");
1316
1317 if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl())
1318 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: MD));
1319 if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl())
1320 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: MD));
1321}
1322
1323void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {
1324 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: OIRE->getDecl()));
1325 attributeOnlyIfTrue(Key: "isFreeIvar", Value: OIRE->isFreeIvar());
1326 JOS.attribute(Key: "isArrow", Contents: OIRE->isArrow());
1327}
1328
1329void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) {
1330 JOS.attribute(Key: "value", Contents: OBLE->getValue() ? "__objc_yes" : "__objc_no");
1331}
1332
1333void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
1334 JOS.attribute(Key: "referencedDecl", Contents: createBareDeclRef(D: DRE->getDecl()));
1335 if (DRE->getDecl() != DRE->getFoundDecl())
1336 JOS.attribute(Key: "foundReferencedDecl",
1337 Contents: createBareDeclRef(D: DRE->getFoundDecl()));
1338 switch (DRE->isNonOdrUse()) {
1339 case NOUR_None: break;
1340 case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break;
1341 case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break;
1342 case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break;
1343 }
1344 attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: DRE->isImmediateEscalating());
1345}
1346
1347void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
1348 const SYCLUniqueStableNameExpr *E) {
1349 JOS.attribute(Key: "typeSourceInfo",
1350 Contents: createQualType(QT: E->getTypeSourceInfo()->getType()));
1351}
1352
1353void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
1354 JOS.attribute(Key: "name", Contents: PredefinedExpr::getIdentKindName(IK: PE->getIdentKind()));
1355}
1356
1357void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {
1358 JOS.attribute(Key: "isPostfix", Contents: UO->isPostfix());
1359 JOS.attribute(Key: "opcode", Contents: UnaryOperator::getOpcodeStr(Op: UO->getOpcode()));
1360 if (!UO->canOverflow())
1361 JOS.attribute(Key: "canOverflow", Contents: false);
1362}
1363
1364void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) {
1365 JOS.attribute(Key: "opcode", Contents: BinaryOperator::getOpcodeStr(Op: BO->getOpcode()));
1366}
1367
1368void JSONNodeDumper::VisitCompoundAssignOperator(
1369 const CompoundAssignOperator *CAO) {
1370 VisitBinaryOperator(BO: CAO);
1371 JOS.attribute(Key: "computeLHSType", Contents: createQualType(QT: CAO->getComputationLHSType()));
1372 JOS.attribute(Key: "computeResultType",
1373 Contents: createQualType(QT: CAO->getComputationResultType()));
1374}
1375
1376void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) {
1377 // Note, we always write this Boolean field because the information it conveys
1378 // is critical to understanding the AST node.
1379 ValueDecl *VD = ME->getMemberDecl();
1380 JOS.attribute(Key: "name", Contents: VD && VD->getDeclName() ? VD->getNameAsString() : "");
1381 JOS.attribute(Key: "isArrow", Contents: ME->isArrow());
1382 JOS.attribute(Key: "referencedMemberDecl", Contents: createPointerRepresentation(Ptr: VD));
1383 switch (ME->isNonOdrUse()) {
1384 case NOUR_None: break;
1385 case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break;
1386 case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break;
1387 case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break;
1388 }
1389}
1390
1391void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {
1392 attributeOnlyIfTrue(Key: "isGlobal", Value: NE->isGlobalNew());
1393 attributeOnlyIfTrue(Key: "isArray", Value: NE->isArray());
1394 attributeOnlyIfTrue(Key: "isPlacement", Value: NE->getNumPlacementArgs() != 0);
1395 switch (NE->getInitializationStyle()) {
1396 case CXXNewInitializationStyle::None:
1397 break;
1398 case CXXNewInitializationStyle::Parens:
1399 JOS.attribute(Key: "initStyle", Contents: "call");
1400 break;
1401 case CXXNewInitializationStyle::Braces:
1402 JOS.attribute(Key: "initStyle", Contents: "list");
1403 break;
1404 }
1405 if (const FunctionDecl *FD = NE->getOperatorNew())
1406 JOS.attribute(Key: "operatorNewDecl", Contents: createBareDeclRef(D: FD));
1407 if (const FunctionDecl *FD = NE->getOperatorDelete())
1408 JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(D: FD));
1409}
1410void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {
1411 attributeOnlyIfTrue(Key: "isGlobal", Value: DE->isGlobalDelete());
1412 attributeOnlyIfTrue(Key: "isArray", Value: DE->isArrayForm());
1413 attributeOnlyIfTrue(Key: "isArrayAsWritten", Value: DE->isArrayFormAsWritten());
1414 if (const FunctionDecl *FD = DE->getOperatorDelete())
1415 JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(D: FD));
1416}
1417
1418void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) {
1419 attributeOnlyIfTrue(Key: "implicit", Value: TE->isImplicit());
1420}
1421
1422void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) {
1423 JOS.attribute(Key: "castKind", Contents: CE->getCastKindName());
1424 llvm::json::Array Path = createCastPath(C: CE);
1425 if (!Path.empty())
1426 JOS.attribute(Key: "path", Contents: std::move(Path));
1427 // FIXME: This may not be useful information as it can be obtusely gleaned
1428 // from the inner[] array.
1429 if (const NamedDecl *ND = CE->getConversionFunction())
1430 JOS.attribute(Key: "conversionFunc", Contents: createBareDeclRef(D: ND));
1431}
1432
1433void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
1434 VisitCastExpr(CE: ICE);
1435 attributeOnlyIfTrue(Key: "isPartOfExplicitCast", Value: ICE->isPartOfExplicitCast());
1436}
1437
1438void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {
1439 attributeOnlyIfTrue(Key: "adl", Value: CE->usesADL());
1440}
1441
1442void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
1443 const UnaryExprOrTypeTraitExpr *TTE) {
1444 JOS.attribute(Key: "name", Contents: getTraitSpelling(T: TTE->getKind()));
1445 if (TTE->isArgumentType())
1446 JOS.attribute(Key: "argType", Contents: createQualType(QT: TTE->getArgumentType()));
1447}
1448
1449void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) {
1450 VisitNamedDecl(ND: SOPE->getPack());
1451}
1452
1453void JSONNodeDumper::VisitUnresolvedLookupExpr(
1454 const UnresolvedLookupExpr *ULE) {
1455 JOS.attribute(Key: "usesADL", Contents: ULE->requiresADL());
1456 JOS.attribute(Key: "name", Contents: ULE->getName().getAsString());
1457
1458 JOS.attributeArray(Key: "lookups", Contents: [this, ULE] {
1459 for (const NamedDecl *D : ULE->decls())
1460 JOS.value(V: createBareDeclRef(D));
1461 });
1462}
1463
1464void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) {
1465 JOS.attribute(Key: "name", Contents: ALE->getLabel()->getName());
1466 JOS.attribute(Key: "labelDeclId", Contents: createPointerRepresentation(Ptr: ALE->getLabel()));
1467}
1468
1469void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
1470 if (CTE->isTypeOperand()) {
1471 QualType Adjusted = CTE->getTypeOperand(Context&: Ctx);
1472 QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType();
1473 JOS.attribute(Key: "typeArg", Contents: createQualType(QT: Unadjusted));
1474 if (Adjusted != Unadjusted)
1475 JOS.attribute(Key: "adjustedTypeArg", Contents: createQualType(QT: Adjusted));
1476 }
1477}
1478
1479void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
1480 if (CE->getResultAPValueKind() != APValue::None)
1481 Visit(Value: CE->getAPValueResult(), Ty: CE->getType());
1482}
1483
1484void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
1485 if (const FieldDecl *FD = ILE->getInitializedFieldInUnion())
1486 JOS.attribute(Key: "field", Contents: createBareDeclRef(D: FD));
1487}
1488
1489void JSONNodeDumper::VisitGenericSelectionExpr(
1490 const GenericSelectionExpr *GSE) {
1491 attributeOnlyIfTrue(Key: "resultDependent", Value: GSE->isResultDependent());
1492}
1493
1494void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(
1495 const CXXUnresolvedConstructExpr *UCE) {
1496 if (UCE->getType() != UCE->getTypeAsWritten())
1497 JOS.attribute(Key: "typeAsWritten", Contents: createQualType(QT: UCE->getTypeAsWritten()));
1498 attributeOnlyIfTrue(Key: "list", Value: UCE->isListInitialization());
1499}
1500
1501void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) {
1502 CXXConstructorDecl *Ctor = CE->getConstructor();
1503 JOS.attribute(Key: "ctorType", Contents: createQualType(QT: Ctor->getType()));
1504 attributeOnlyIfTrue(Key: "elidable", Value: CE->isElidable());
1505 attributeOnlyIfTrue(Key: "list", Value: CE->isListInitialization());
1506 attributeOnlyIfTrue(Key: "initializer_list", Value: CE->isStdInitListInitialization());
1507 attributeOnlyIfTrue(Key: "zeroing", Value: CE->requiresZeroInitialization());
1508 attributeOnlyIfTrue(Key: "hadMultipleCandidates", Value: CE->hadMultipleCandidates());
1509 attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: CE->isImmediateEscalating());
1510
1511 switch (CE->getConstructionKind()) {
1512 case CXXConstructionKind::Complete:
1513 JOS.attribute(Key: "constructionKind", Contents: "complete");
1514 break;
1515 case CXXConstructionKind::Delegating:
1516 JOS.attribute(Key: "constructionKind", Contents: "delegating");
1517 break;
1518 case CXXConstructionKind::NonVirtualBase:
1519 JOS.attribute(Key: "constructionKind", Contents: "non-virtual base");
1520 break;
1521 case CXXConstructionKind::VirtualBase:
1522 JOS.attribute(Key: "constructionKind", Contents: "virtual base");
1523 break;
1524 }
1525}
1526
1527void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {
1528 attributeOnlyIfTrue(Key: "cleanupsHaveSideEffects",
1529 Value: EWC->cleanupsHaveSideEffects());
1530 if (EWC->getNumObjects()) {
1531 JOS.attributeArray(Key: "cleanups", Contents: [this, EWC] {
1532 for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())
1533 if (auto *BD = CO.dyn_cast<BlockDecl *>()) {
1534 JOS.value(V: createBareDeclRef(D: BD));
1535 } else if (auto *CLE = CO.dyn_cast<CompoundLiteralExpr *>()) {
1536 llvm::json::Object Obj;
1537 Obj["id"] = createPointerRepresentation(Ptr: CLE);
1538 Obj["kind"] = CLE->getStmtClassName();
1539 JOS.value(V: std::move(Obj));
1540 } else {
1541 llvm_unreachable("unexpected cleanup object type");
1542 }
1543 });
1544 }
1545}
1546
1547void JSONNodeDumper::VisitCXXBindTemporaryExpr(
1548 const CXXBindTemporaryExpr *BTE) {
1549 const CXXTemporary *Temp = BTE->getTemporary();
1550 JOS.attribute(Key: "temp", Contents: createPointerRepresentation(Ptr: Temp));
1551 if (const CXXDestructorDecl *Dtor = Temp->getDestructor())
1552 JOS.attribute(Key: "dtor", Contents: createBareDeclRef(D: Dtor));
1553}
1554
1555void JSONNodeDumper::VisitMaterializeTemporaryExpr(
1556 const MaterializeTemporaryExpr *MTE) {
1557 if (const ValueDecl *VD = MTE->getExtendingDecl())
1558 JOS.attribute(Key: "extendingDecl", Contents: createBareDeclRef(D: VD));
1559
1560 switch (MTE->getStorageDuration()) {
1561 case SD_Automatic:
1562 JOS.attribute(Key: "storageDuration", Contents: "automatic");
1563 break;
1564 case SD_Dynamic:
1565 JOS.attribute(Key: "storageDuration", Contents: "dynamic");
1566 break;
1567 case SD_FullExpression:
1568 JOS.attribute(Key: "storageDuration", Contents: "full expression");
1569 break;
1570 case SD_Static:
1571 JOS.attribute(Key: "storageDuration", Contents: "static");
1572 break;
1573 case SD_Thread:
1574 JOS.attribute(Key: "storageDuration", Contents: "thread");
1575 break;
1576 }
1577
1578 attributeOnlyIfTrue(Key: "boundToLValueRef", Value: MTE->isBoundToLvalueReference());
1579}
1580
1581void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
1582 attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit());
1583}
1584
1585void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
1586 attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit());
1587}
1588
1589void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
1590 const CXXDependentScopeMemberExpr *DSME) {
1591 JOS.attribute(Key: "isArrow", Contents: DSME->isArrow());
1592 JOS.attribute(Key: "member", Contents: DSME->getMember().getAsString());
1593 attributeOnlyIfTrue(Key: "hasTemplateKeyword", Value: DSME->hasTemplateKeyword());
1594 attributeOnlyIfTrue(Key: "hasExplicitTemplateArgs",
1595 Value: DSME->hasExplicitTemplateArgs());
1596
1597 if (DSME->getNumTemplateArgs()) {
1598 JOS.attributeArray(Key: "explicitTemplateArgs", Contents: [DSME, this] {
1599 for (const TemplateArgumentLoc &TAL : DSME->template_arguments())
1600 JOS.object(
1601 Contents: [&TAL, this] { Visit(TA: TAL.getArgument(), R: TAL.getSourceRange()); });
1602 });
1603 }
1604}
1605
1606void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {
1607 if (!RE->isValueDependent())
1608 JOS.attribute(Key: "satisfied", Contents: RE->isSatisfied());
1609}
1610
1611void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {
1612 llvm::SmallString<16> Buffer;
1613 IL->getValue().toString(Str&: Buffer,
1614 /*Radix=*/10, Signed: IL->getType()->isSignedIntegerType());
1615 JOS.attribute(Key: "value", Contents: Buffer);
1616}
1617void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) {
1618 // FIXME: This should probably print the character literal as a string,
1619 // rather than as a numerical value. It would be nice if the behavior matched
1620 // what we do to print a string literal; right now, it is impossible to tell
1621 // the difference between 'a' and L'a' in C from the JSON output.
1622 JOS.attribute(Key: "value", Contents: CL->getValue());
1623}
1624void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) {
1625 JOS.attribute(Key: "value", Contents: FPL->getValueAsString(/*Radix=*/10));
1626}
1627void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) {
1628 llvm::SmallString<16> Buffer;
1629 FL->getValue().toString(Str&: Buffer);
1630 JOS.attribute(Key: "value", Contents: Buffer);
1631}
1632void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) {
1633 std::string Buffer;
1634 llvm::raw_string_ostream SS(Buffer);
1635 SL->outputString(OS&: SS);
1636 JOS.attribute(Key: "value", Contents: Buffer);
1637}
1638void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) {
1639 JOS.attribute(Key: "value", Contents: BLE->getValue());
1640}
1641
1642void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) {
1643 attributeOnlyIfTrue(Key: "hasInit", Value: IS->hasInitStorage());
1644 attributeOnlyIfTrue(Key: "hasVar", Value: IS->hasVarStorage());
1645 attributeOnlyIfTrue(Key: "hasElse", Value: IS->hasElseStorage());
1646 attributeOnlyIfTrue(Key: "isConstexpr", Value: IS->isConstexpr());
1647 attributeOnlyIfTrue(Key: "isConsteval", Value: IS->isConsteval());
1648 attributeOnlyIfTrue(Key: "constevalIsNegated", Value: IS->isNegatedConsteval());
1649}
1650
1651void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) {
1652 attributeOnlyIfTrue(Key: "hasInit", Value: SS->hasInitStorage());
1653 attributeOnlyIfTrue(Key: "hasVar", Value: SS->hasVarStorage());
1654}
1655void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
1656 attributeOnlyIfTrue(Key: "isGNURange", Value: CS->caseStmtIsGNURange());
1657}
1658
1659void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
1660 JOS.attribute(Key: "name", Contents: LS->getName());
1661 JOS.attribute(Key: "declId", Contents: createPointerRepresentation(Ptr: LS->getDecl()));
1662 attributeOnlyIfTrue(Key: "sideEntry", Value: LS->isSideEntry());
1663}
1664void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
1665 JOS.attribute(Key: "targetLabelDeclId",
1666 Contents: createPointerRepresentation(Ptr: GS->getLabel()));
1667}
1668
1669void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) {
1670 attributeOnlyIfTrue(Key: "hasVar", Value: WS->hasVarStorage());
1671}
1672
1673void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) {
1674 // FIXME: it would be nice for the ASTNodeTraverser would handle the catch
1675 // parameter the same way for C++ and ObjC rather. In this case, C++ gets a
1676 // null child node and ObjC gets no child node.
1677 attributeOnlyIfTrue(Key: "isCatchAll", Value: OACS->getCatchParamDecl() == nullptr);
1678}
1679
1680void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) {
1681 JOS.attribute(Key: "isNull", Contents: true);
1682}
1683void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
1684 JOS.attribute(Key: "type", Contents: createQualType(QT: TA.getAsType()));
1685}
1686void JSONNodeDumper::VisitDeclarationTemplateArgument(
1687 const TemplateArgument &TA) {
1688 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TA.getAsDecl()));
1689}
1690void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) {
1691 JOS.attribute(Key: "isNullptr", Contents: true);
1692}
1693void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
1694 JOS.attribute(Key: "value", Contents: TA.getAsIntegral().getSExtValue());
1695}
1696void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
1697 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1698 // the output format.
1699}
1700void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
1701 const TemplateArgument &TA) {
1702 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1703 // the output format.
1704}
1705void JSONNodeDumper::VisitExpressionTemplateArgument(
1706 const TemplateArgument &TA) {
1707 JOS.attribute(Key: "isExpr", Contents: true);
1708}
1709void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
1710 JOS.attribute(Key: "isPack", Contents: true);
1711}
1712
1713StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const {
1714 if (Traits)
1715 return Traits->getCommandInfo(CommandID)->Name;
1716 if (const comments::CommandInfo *Info =
1717 comments::CommandTraits::getBuiltinCommandInfo(CommandID))
1718 return Info->Name;
1719 return "<invalid>";
1720}
1721
1722void JSONNodeDumper::visitTextComment(const comments::TextComment *C,
1723 const comments::FullComment *) {
1724 JOS.attribute(Key: "text", Contents: C->getText());
1725}
1726
1727void JSONNodeDumper::visitInlineCommandComment(
1728 const comments::InlineCommandComment *C, const comments::FullComment *) {
1729 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1730
1731 switch (C->getRenderKind()) {
1732 case comments::InlineCommandRenderKind::Normal:
1733 JOS.attribute(Key: "renderKind", Contents: "normal");
1734 break;
1735 case comments::InlineCommandRenderKind::Bold:
1736 JOS.attribute(Key: "renderKind", Contents: "bold");
1737 break;
1738 case comments::InlineCommandRenderKind::Emphasized:
1739 JOS.attribute(Key: "renderKind", Contents: "emphasized");
1740 break;
1741 case comments::InlineCommandRenderKind::Monospaced:
1742 JOS.attribute(Key: "renderKind", Contents: "monospaced");
1743 break;
1744 case comments::InlineCommandRenderKind::Anchor:
1745 JOS.attribute(Key: "renderKind", Contents: "anchor");
1746 break;
1747 }
1748
1749 llvm::json::Array Args;
1750 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
1751 Args.push_back(E: C->getArgText(Idx: I));
1752
1753 if (!Args.empty())
1754 JOS.attribute(Key: "args", Contents: std::move(Args));
1755}
1756
1757void JSONNodeDumper::visitHTMLStartTagComment(
1758 const comments::HTMLStartTagComment *C, const comments::FullComment *) {
1759 JOS.attribute(Key: "name", Contents: C->getTagName());
1760 attributeOnlyIfTrue(Key: "selfClosing", Value: C->isSelfClosing());
1761 attributeOnlyIfTrue(Key: "malformed", Value: C->isMalformed());
1762
1763 llvm::json::Array Attrs;
1764 for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I)
1765 Attrs.push_back(
1766 E: {{"name", C->getAttr(Idx: I).Name}, {"value", C->getAttr(Idx: I).Value}});
1767
1768 if (!Attrs.empty())
1769 JOS.attribute(Key: "attrs", Contents: std::move(Attrs));
1770}
1771
1772void JSONNodeDumper::visitHTMLEndTagComment(
1773 const comments::HTMLEndTagComment *C, const comments::FullComment *) {
1774 JOS.attribute(Key: "name", Contents: C->getTagName());
1775}
1776
1777void JSONNodeDumper::visitBlockCommandComment(
1778 const comments::BlockCommandComment *C, const comments::FullComment *) {
1779 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1780
1781 llvm::json::Array Args;
1782 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
1783 Args.push_back(E: C->getArgText(Idx: I));
1784
1785 if (!Args.empty())
1786 JOS.attribute(Key: "args", Contents: std::move(Args));
1787}
1788
1789void JSONNodeDumper::visitParamCommandComment(
1790 const comments::ParamCommandComment *C, const comments::FullComment *FC) {
1791 switch (C->getDirection()) {
1792 case comments::ParamCommandPassDirection::In:
1793 JOS.attribute(Key: "direction", Contents: "in");
1794 break;
1795 case comments::ParamCommandPassDirection::Out:
1796 JOS.attribute(Key: "direction", Contents: "out");
1797 break;
1798 case comments::ParamCommandPassDirection::InOut:
1799 JOS.attribute(Key: "direction", Contents: "in,out");
1800 break;
1801 }
1802 attributeOnlyIfTrue(Key: "explicit", Value: C->isDirectionExplicit());
1803
1804 if (C->hasParamName())
1805 JOS.attribute(Key: "param", Contents: C->isParamIndexValid() ? C->getParamName(FC)
1806 : C->getParamNameAsWritten());
1807
1808 if (C->isParamIndexValid() && !C->isVarArgParam())
1809 JOS.attribute(Key: "paramIdx", Contents: C->getParamIndex());
1810}
1811
1812void JSONNodeDumper::visitTParamCommandComment(
1813 const comments::TParamCommandComment *C, const comments::FullComment *FC) {
1814 if (C->hasParamName())
1815 JOS.attribute(Key: "param", Contents: C->isPositionValid() ? C->getParamName(FC)
1816 : C->getParamNameAsWritten());
1817 if (C->isPositionValid()) {
1818 llvm::json::Array Positions;
1819 for (unsigned I = 0, E = C->getDepth(); I < E; ++I)
1820 Positions.push_back(E: C->getIndex(Depth: I));
1821
1822 if (!Positions.empty())
1823 JOS.attribute(Key: "positions", Contents: std::move(Positions));
1824 }
1825}
1826
1827void JSONNodeDumper::visitVerbatimBlockComment(
1828 const comments::VerbatimBlockComment *C, const comments::FullComment *) {
1829 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1830 JOS.attribute(Key: "closeName", Contents: C->getCloseName());
1831}
1832
1833void JSONNodeDumper::visitVerbatimBlockLineComment(
1834 const comments::VerbatimBlockLineComment *C,
1835 const comments::FullComment *) {
1836 JOS.attribute(Key: "text", Contents: C->getText());
1837}
1838
1839void JSONNodeDumper::visitVerbatimLineComment(
1840 const comments::VerbatimLineComment *C, const comments::FullComment *) {
1841 JOS.attribute(Key: "text", Contents: C->getText());
1842}
1843
1844llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) {
1845 llvm::json::Object Ret;
1846#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
1847 if (FPO.has##NAME##Override()) \
1848 Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override()));
1849#include "clang/Basic/FPOptions.def"
1850 return Ret;
1851}
1852
1853void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
1854 VisitStmt(Node: S);
1855 if (S->hasStoredFPFeatures())
1856 JOS.attribute(Key: "fpoptions", Contents: createFPOptions(FPO: S->getStoredFPFeatures()));
1857}
1858