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