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::VisitAvailabilityAttr(const AvailabilityAttr *AA) {
600 if (const IdentifierInfo *Platform = AA->getPlatform())
601 JOS.attribute(Key: "platform", Contents: Platform->getName());
602 if (!AA->getIntroduced().empty())
603 JOS.attribute(Key: "introduced", Contents: AA->getIntroduced().getAsString());
604 if (!AA->getDeprecated().empty())
605 JOS.attribute(Key: "deprecated", Contents: AA->getDeprecated().getAsString());
606 if (!AA->getObsoleted().empty())
607 JOS.attribute(Key: "obsoleted", Contents: AA->getObsoleted().getAsString());
608 attributeOnlyIfTrue(Key: "unavailable", Value: AA->getUnavailable());
609 if (!AA->getMessage().empty())
610 JOS.attribute(Key: "message", Contents: AA->getMessage());
611 attributeOnlyIfTrue(Key: "strict", Value: AA->getStrict());
612 if (!AA->getReplacement().empty())
613 JOS.attribute(Key: "replacement", Contents: AA->getReplacement());
614 if (AA->getPriority() != 0)
615 JOS.attribute(Key: "priority", Contents: AA->getPriority());
616 if (const IdentifierInfo *Env = AA->getEnvironment())
617 JOS.attribute(Key: "environment", Contents: Env->getName());
618}
619
620void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {
621 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TT->getDecl()));
622 if (!TT->typeMatchesDecl())
623 JOS.attribute(Key: "type", Contents: createQualType(QT: TT->desugar()));
624}
625
626void JSONNodeDumper::VisitUsingType(const UsingType *TT) {
627 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TT->getDecl()));
628 JOS.attribute(Key: "type", Contents: createQualType(QT: TT->desugar()));
629}
630
631void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {
632 FunctionType::ExtInfo E = T->getExtInfo();
633 attributeOnlyIfTrue(Key: "noreturn", Value: E.getNoReturn());
634 attributeOnlyIfTrue(Key: "producesResult", Value: E.getProducesResult());
635 if (E.getHasRegParm())
636 JOS.attribute(Key: "regParm", Contents: E.getRegParm());
637 JOS.attribute(Key: "cc", Contents: FunctionType::getNameForCallConv(CC: E.getCC()));
638}
639
640void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
641 FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo();
642 attributeOnlyIfTrue(Key: "trailingReturn", Value: E.HasTrailingReturn);
643 attributeOnlyIfTrue(Key: "const", Value: T->isConst());
644 attributeOnlyIfTrue(Key: "volatile", Value: T->isVolatile());
645 attributeOnlyIfTrue(Key: "restrict", Value: T->isRestrict());
646 attributeOnlyIfTrue(Key: "variadic", Value: E.Variadic);
647 switch (E.RefQualifier) {
648 case RQ_LValue: JOS.attribute(Key: "refQualifier", Contents: "&"); break;
649 case RQ_RValue: JOS.attribute(Key: "refQualifier", Contents: "&&"); break;
650 case RQ_None: break;
651 }
652 switch (E.ExceptionSpec.Type) {
653 case EST_DynamicNone:
654 case EST_Dynamic: {
655 JOS.attribute(Key: "exceptionSpec", Contents: "throw");
656 llvm::json::Array Types;
657 for (QualType QT : E.ExceptionSpec.Exceptions)
658 Types.push_back(E: createQualType(QT));
659 JOS.attribute(Key: "exceptionTypes", Contents: std::move(Types));
660 } break;
661 case EST_MSAny:
662 JOS.attribute(Key: "exceptionSpec", Contents: "throw");
663 JOS.attribute(Key: "throwsAny", Contents: true);
664 break;
665 case EST_BasicNoexcept:
666 JOS.attribute(Key: "exceptionSpec", Contents: "noexcept");
667 break;
668 case EST_NoexceptTrue:
669 case EST_NoexceptFalse:
670 JOS.attribute(Key: "exceptionSpec", Contents: "noexcept");
671 JOS.attribute(Key: "conditionEvaluatesTo",
672 Contents: E.ExceptionSpec.Type == EST_NoexceptTrue);
673 //JOS.attributeWithCall("exceptionSpecExpr",
674 // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); });
675 break;
676 case EST_NoThrow:
677 JOS.attribute(Key: "exceptionSpec", Contents: "nothrow");
678 break;
679 // FIXME: I cannot find a way to trigger these cases while dumping the AST. I
680 // suspect you can only run into them when executing an AST dump from within
681 // the debugger, which is not a use case we worry about for the JSON dumping
682 // feature.
683 case EST_DependentNoexcept:
684 case EST_Unevaluated:
685 case EST_Uninstantiated:
686 case EST_Unparsed:
687 case EST_None: break;
688 }
689 VisitFunctionType(T);
690}
691
692void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType *RT) {
693 attributeOnlyIfTrue(Key: "spelledAsLValue", Value: RT->isSpelledAsLValue());
694}
695
696void JSONNodeDumper::VisitArrayType(const ArrayType *AT) {
697 switch (AT->getSizeModifier()) {
698 case ArraySizeModifier::Star:
699 JOS.attribute(Key: "sizeModifier", Contents: "*");
700 break;
701 case ArraySizeModifier::Static:
702 JOS.attribute(Key: "sizeModifier", Contents: "static");
703 break;
704 case ArraySizeModifier::Normal:
705 break;
706 }
707
708 std::string Str = AT->getIndexTypeQualifiers().getAsString();
709 if (!Str.empty())
710 JOS.attribute(Key: "indexTypeQualifiers", Contents: Str);
711}
712
713void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) {
714 // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a
715 // narrowing conversion to int64_t so it cannot be expressed.
716 JOS.attribute(Key: "size", Contents: CAT->getSExtSize());
717 VisitArrayType(AT: CAT);
718}
719
720void JSONNodeDumper::VisitDependentSizedExtVectorType(
721 const DependentSizedExtVectorType *VT) {
722 JOS.attributeObject(
723 Key: "attrLoc", Contents: [VT, this] { writeSourceLocation(Loc: VT->getAttributeLoc()); });
724}
725
726void JSONNodeDumper::VisitVectorType(const VectorType *VT) {
727 JOS.attribute(Key: "numElements", Contents: VT->getNumElements());
728 switch (VT->getVectorKind()) {
729 case VectorKind::Generic:
730 break;
731 case VectorKind::AltiVecVector:
732 JOS.attribute(Key: "vectorKind", Contents: "altivec");
733 break;
734 case VectorKind::AltiVecPixel:
735 JOS.attribute(Key: "vectorKind", Contents: "altivec pixel");
736 break;
737 case VectorKind::AltiVecBool:
738 JOS.attribute(Key: "vectorKind", Contents: "altivec bool");
739 break;
740 case VectorKind::Neon:
741 JOS.attribute(Key: "vectorKind", Contents: "neon");
742 break;
743 case VectorKind::NeonPoly:
744 JOS.attribute(Key: "vectorKind", Contents: "neon poly");
745 break;
746 case VectorKind::SveFixedLengthData:
747 JOS.attribute(Key: "vectorKind", Contents: "fixed-length sve data vector");
748 break;
749 case VectorKind::SveFixedLengthPredicate:
750 JOS.attribute(Key: "vectorKind", Contents: "fixed-length sve predicate vector");
751 break;
752 case VectorKind::RVVFixedLengthData:
753 JOS.attribute(Key: "vectorKind", Contents: "fixed-length rvv data vector");
754 break;
755 case VectorKind::RVVFixedLengthMask:
756 case VectorKind::RVVFixedLengthMask_1:
757 case VectorKind::RVVFixedLengthMask_2:
758 case VectorKind::RVVFixedLengthMask_4:
759 JOS.attribute(Key: "vectorKind", Contents: "fixed-length rvv mask vector");
760 break;
761 }
762}
763
764void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {
765 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: UUT->getDecl()));
766}
767
768void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) {
769 switch (UTT->getUTTKind()) {
770#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
771 case UnaryTransformType::Enum: \
772 JOS.attribute("transformKind", #Trait); \
773 break;
774#include "clang/Basic/TransformTypeTraits.def"
775 }
776}
777
778void JSONNodeDumper::VisitTagType(const TagType *TT) {
779 if (NestedNameSpecifier Qualifier = TT->getQualifier()) {
780 std::string Str;
781 llvm::raw_string_ostream OS(Str);
782 Qualifier.print(OS, Policy: PrintPolicy, /*ResolveTemplateArguments=*/true);
783 JOS.attribute(Key: "qualifier", Contents: Str);
784 }
785 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TT->getDecl()));
786 if (TT->isTagOwned())
787 JOS.attribute(Key: "isTagOwned", Contents: true);
788}
789
790void JSONNodeDumper::VisitTemplateTypeParmType(
791 const TemplateTypeParmType *TTPT) {
792 JOS.attribute(Key: "depth", Contents: TTPT->getDepth());
793 JOS.attribute(Key: "index", Contents: TTPT->getIndex());
794 attributeOnlyIfTrue(Key: "isPack", Value: TTPT->isParameterPack());
795 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TTPT->getDecl()));
796}
797
798void JSONNodeDumper::VisitSubstTemplateTypeParmType(
799 const SubstTemplateTypeParmType *STTPT) {
800 JOS.attribute(Key: "index", Contents: STTPT->getIndex());
801 if (auto PackIndex = STTPT->getPackIndex())
802 JOS.attribute(Key: "pack_index", Contents: *PackIndex);
803}
804
805void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
806 const SubstTemplateTypeParmPackType *T) {
807 JOS.attribute(Key: "index", Contents: T->getIndex());
808}
809
810void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
811 JOS.attribute(Key: "undeduced", Contents: !AT->isDeduced());
812 switch (AT->getKeyword()) {
813 case AutoTypeKeyword::Auto:
814 JOS.attribute(Key: "typeKeyword", Contents: "auto");
815 break;
816 case AutoTypeKeyword::DecltypeAuto:
817 JOS.attribute(Key: "typeKeyword", Contents: "decltype(auto)");
818 break;
819 case AutoTypeKeyword::GNUAutoType:
820 JOS.attribute(Key: "typeKeyword", Contents: "__auto_type");
821 break;
822 }
823}
824
825void JSONNodeDumper::VisitTemplateSpecializationType(
826 const TemplateSpecializationType *TST) {
827 attributeOnlyIfTrue(Key: "isAlias", Value: TST->isTypeAlias());
828
829 std::string Str;
830 llvm::raw_string_ostream OS(Str);
831 TST->getTemplateName().print(OS, Policy: PrintPolicy);
832 JOS.attribute(Key: "templateName", Contents: Str);
833}
834
835void JSONNodeDumper::VisitInjectedClassNameType(
836 const InjectedClassNameType *ICNT) {
837 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: ICNT->getDecl()));
838}
839
840void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {
841 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: OIT->getDecl()));
842}
843
844void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) {
845 if (UnsignedOrNone N = PET->getNumExpansions())
846 JOS.attribute(Key: "numExpansions", Contents: *N);
847}
848
849void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) {
850 JOS.attribute(Key: "macroName", Contents: MQT->getMacroIdentifier()->getName());
851}
852
853void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) {
854 attributeOnlyIfTrue(Key: "isData", Value: MPT->isMemberDataPointer());
855 attributeOnlyIfTrue(Key: "isFunction", Value: MPT->isMemberFunctionPointer());
856}
857
858void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {
859 if (ND && ND->getDeclName()) {
860 JOS.attribute(Key: "name", Contents: ND->getNameAsString());
861 // FIXME: There are likely other contexts in which it makes no sense to ask
862 // for a mangled name.
863 if (isa<RequiresExprBodyDecl>(Val: ND->getDeclContext()))
864 return;
865
866 // If the declaration is dependent or is in a dependent context, then the
867 // mangling is unlikely to be meaningful (and in some cases may cause
868 // "don't know how to mangle this" assertion failures.
869 if (ND->isTemplated())
870 return;
871
872 // Mangled names are not meaningful for locals, and may not be well-defined
873 // in the case of VLAs.
874 auto *VD = dyn_cast<VarDecl>(Val: ND);
875 if (VD && VD->hasLocalStorage())
876 return;
877
878 // Do not mangle template deduction guides.
879 if (isa<CXXDeductionGuideDecl>(Val: ND))
880 return;
881
882 std::string MangledName = ASTNameGen.getName(D: ND);
883 if (!MangledName.empty())
884 JOS.attribute(Key: "mangledName", Contents: MangledName);
885 }
886}
887
888void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) {
889 VisitNamedDecl(ND: TD);
890 JOS.attribute(Key: "type", Contents: createQualType(QT: TD->getUnderlyingType()));
891}
892
893void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) {
894 VisitNamedDecl(ND: TAD);
895 JOS.attribute(Key: "type", Contents: createQualType(QT: TAD->getUnderlyingType()));
896}
897
898void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {
899 VisitNamedDecl(ND);
900 attributeOnlyIfTrue(Key: "isInline", Value: ND->isInline());
901 attributeOnlyIfTrue(Key: "isNested", Value: ND->isNested());
902 if (!ND->isFirstDecl())
903 JOS.attribute(Key: "originalNamespace", Contents: createBareDeclRef(D: ND->getFirstDecl()));
904}
905
906void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {
907 JOS.attribute(Key: "nominatedNamespace",
908 Contents: createBareDeclRef(D: UDD->getNominatedNamespace()));
909}
910
911void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {
912 VisitNamedDecl(ND: NAD);
913 JOS.attribute(Key: "aliasedNamespace",
914 Contents: createBareDeclRef(D: NAD->getAliasedNamespace()));
915}
916
917void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) {
918 std::string Name;
919 if (NestedNameSpecifier Qualifier = UD->getQualifier()) {
920 llvm::raw_string_ostream SOS(Name);
921 Qualifier.print(OS&: SOS, Policy: UD->getASTContext().getPrintingPolicy());
922 }
923 Name += UD->getNameAsString();
924 JOS.attribute(Key: "name", Contents: Name);
925}
926
927void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) {
928 JOS.attribute(Key: "target", Contents: createBareDeclRef(D: UED->getEnumDecl()));
929}
930
931void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) {
932 JOS.attribute(Key: "target", Contents: createBareDeclRef(D: USD->getTargetDecl()));
933}
934
935void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) {
936 VisitNamedDecl(ND: VD);
937 JOS.attribute(Key: "type", Contents: createQualType(QT: VD->getType()));
938 if (const auto *P = dyn_cast<ParmVarDecl>(Val: VD))
939 attributeOnlyIfTrue(Key: "explicitObjectParameter",
940 Value: P->isExplicitObjectParameter());
941
942 StorageClass SC = VD->getStorageClass();
943 if (SC != SC_None)
944 JOS.attribute(Key: "storageClass", Contents: VarDecl::getStorageClassSpecifierString(SC));
945 switch (VD->getTLSKind()) {
946 case VarDecl::TLS_Dynamic: JOS.attribute(Key: "tls", Contents: "dynamic"); break;
947 case VarDecl::TLS_Static: JOS.attribute(Key: "tls", Contents: "static"); break;
948 case VarDecl::TLS_None: break;
949 }
950 attributeOnlyIfTrue(Key: "nrvo", Value: VD->isNRVOVariable());
951 attributeOnlyIfTrue(Key: "inline", Value: VD->isInline());
952 attributeOnlyIfTrue(Key: "constexpr", Value: VD->isConstexpr());
953 attributeOnlyIfTrue(Key: "modulePrivate", Value: VD->isModulePrivate());
954 if (VD->hasInit()) {
955 switch (VD->getInitStyle()) {
956 case VarDecl::CInit: JOS.attribute(Key: "init", Contents: "c"); break;
957 case VarDecl::CallInit: JOS.attribute(Key: "init", Contents: "call"); break;
958 case VarDecl::ListInit: JOS.attribute(Key: "init", Contents: "list"); break;
959 case VarDecl::ParenListInit:
960 JOS.attribute(Key: "init", Contents: "paren-list");
961 break;
962 }
963 }
964 attributeOnlyIfTrue(Key: "isParameterPack", Value: VD->isParameterPack());
965 if (const auto *Instance = VD->getTemplateInstantiationPattern())
966 JOS.attribute(Key: "TemplateInstantiationPattern",
967 Contents: createPointerRepresentation(Ptr: Instance));
968}
969
970void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {
971 VisitNamedDecl(ND: FD);
972 JOS.attribute(Key: "type", Contents: createQualType(QT: FD->getType()));
973 attributeOnlyIfTrue(Key: "mutable", Value: FD->isMutable());
974 attributeOnlyIfTrue(Key: "modulePrivate", Value: FD->isModulePrivate());
975 attributeOnlyIfTrue(Key: "isBitfield", Value: FD->isBitField());
976 attributeOnlyIfTrue(Key: "hasInClassInitializer", Value: FD->hasInClassInitializer());
977}
978
979void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
980 VisitNamedDecl(ND: FD);
981 JOS.attribute(Key: "type", Contents: createQualType(QT: FD->getType()));
982 StorageClass SC = FD->getStorageClass();
983 if (SC != SC_None)
984 JOS.attribute(Key: "storageClass", Contents: VarDecl::getStorageClassSpecifierString(SC));
985 attributeOnlyIfTrue(Key: "inline", Value: FD->isInlineSpecified());
986 attributeOnlyIfTrue(Key: "virtual", Value: FD->isVirtualAsWritten());
987 attributeOnlyIfTrue(Key: "pure", Value: FD->isPureVirtual());
988 attributeOnlyIfTrue(Key: "explicitlyDeleted", Value: FD->isDeletedAsWritten());
989 attributeOnlyIfTrue(Key: "constexpr", Value: FD->isConstexpr());
990 attributeOnlyIfTrue(Key: "variadic", Value: FD->isVariadic());
991 attributeOnlyIfTrue(Key: "immediate", Value: FD->isImmediateFunction());
992
993 if (FD->isDefaulted())
994 JOS.attribute(Key: "explicitlyDefaulted",
995 Contents: FD->isDeleted() ? "deleted" : "default");
996
997 if (StringLiteral *Msg = FD->getDeletedMessage())
998 JOS.attribute(Key: "deletedMessage", Contents: Msg->getString());
999
1000 if (const auto *Instance = FD->getTemplateInstantiationPattern())
1001 JOS.attribute(Key: "TemplateInstantiationPattern",
1002 Contents: createPointerRepresentation(Ptr: Instance));
1003}
1004
1005void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) {
1006 VisitNamedDecl(ND: ED);
1007 if (ED->isFixed())
1008 JOS.attribute(Key: "fixedUnderlyingType", Contents: createQualType(QT: ED->getIntegerType()));
1009 if (ED->isScoped())
1010 JOS.attribute(Key: "scopedEnumTag",
1011 Contents: ED->isScopedUsingClassTag() ? "class" : "struct");
1012 if (const auto *Instance = ED->getTemplateInstantiationPattern())
1013 JOS.attribute(Key: "TemplateInstantiationPattern",
1014 Contents: createPointerRepresentation(Ptr: Instance));
1015}
1016void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) {
1017 VisitNamedDecl(ND: ECD);
1018 JOS.attribute(Key: "type", Contents: createQualType(QT: ECD->getType()));
1019}
1020
1021void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
1022 VisitNamedDecl(ND: RD);
1023 JOS.attribute(Key: "tagUsed", Contents: RD->getKindName());
1024 attributeOnlyIfTrue(Key: "completeDefinition", Value: RD->isCompleteDefinition());
1025}
1026void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
1027 VisitRecordDecl(RD);
1028
1029 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Val: RD)) {
1030 if (CTSD->hasStrictPackMatch())
1031 JOS.attribute(Key: "strict-pack-match", Contents: true);
1032 }
1033
1034 if (const auto *Instance = RD->getTemplateInstantiationPattern())
1035 JOS.attribute(Key: "TemplateInstantiationPattern",
1036 Contents: createPointerRepresentation(Ptr: Instance));
1037
1038 // All other information requires a complete definition.
1039 if (!RD->isCompleteDefinition())
1040 return;
1041
1042 JOS.attribute(Key: "definitionData", Contents: createCXXRecordDefinitionData(RD));
1043 if (RD->getNumBases()) {
1044 JOS.attributeArray(Key: "bases", Contents: [this, RD] {
1045 for (const auto &Spec : RD->bases())
1046 JOS.value(V: createCXXBaseSpecifier(BS: Spec));
1047 });
1048 }
1049}
1050
1051void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
1052 VisitNamedDecl(ND: D);
1053 JOS.attribute(Key: "bufferKind", Contents: D->isCBuffer() ? "cbuffer" : "tbuffer");
1054}
1055
1056void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
1057 VisitNamedDecl(ND: D);
1058 JOS.attribute(Key: "tagUsed", Contents: D->wasDeclaredWithTypename() ? "typename" : "class");
1059 JOS.attribute(Key: "depth", Contents: D->getDepth());
1060 JOS.attribute(Key: "index", Contents: D->getIndex());
1061 attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack());
1062
1063 if (D->hasDefaultArgument())
1064 JOS.attributeObject(Key: "defaultArg", Contents: [=] {
1065 Visit(TA: D->getDefaultArgument().getArgument(), R: SourceRange(),
1066 From: D->getDefaultArgStorage().getInheritedFrom(),
1067 Label: D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1068 });
1069}
1070
1071void JSONNodeDumper::VisitNonTypeTemplateParmDecl(
1072 const NonTypeTemplateParmDecl *D) {
1073 VisitNamedDecl(ND: D);
1074 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1075 JOS.attribute(Key: "depth", Contents: D->getDepth());
1076 JOS.attribute(Key: "index", Contents: D->getIndex());
1077 attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack());
1078
1079 if (D->hasDefaultArgument())
1080 JOS.attributeObject(Key: "defaultArg", Contents: [=] {
1081 Visit(TA: D->getDefaultArgument().getArgument(), R: SourceRange(),
1082 From: D->getDefaultArgStorage().getInheritedFrom(),
1083 Label: D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1084 });
1085}
1086
1087void JSONNodeDumper::VisitTemplateTemplateParmDecl(
1088 const TemplateTemplateParmDecl *D) {
1089 VisitNamedDecl(ND: D);
1090 JOS.attribute(Key: "depth", Contents: D->getDepth());
1091 JOS.attribute(Key: "index", Contents: D->getIndex());
1092 attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack());
1093
1094 if (D->hasDefaultArgument())
1095 JOS.attributeObject(Key: "defaultArg", Contents: [=] {
1096 const auto *InheritedFrom = D->getDefaultArgStorage().getInheritedFrom();
1097 Visit(TA: D->getDefaultArgument().getArgument(),
1098 R: InheritedFrom ? InheritedFrom->getSourceRange() : SourceLocation{},
1099 From: InheritedFrom,
1100 Label: D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1101 });
1102}
1103
1104void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) {
1105 StringRef Lang;
1106 switch (LSD->getLanguage()) {
1107 case LinkageSpecLanguageIDs::C:
1108 Lang = "C";
1109 break;
1110 case LinkageSpecLanguageIDs::CXX:
1111 Lang = "C++";
1112 break;
1113 }
1114 JOS.attribute(Key: "language", Contents: Lang);
1115 attributeOnlyIfTrue(Key: "hasBraces", Value: LSD->hasBraces());
1116}
1117
1118void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) {
1119 JOS.attribute(Key: "access", Contents: createAccessSpecifier(AS: ASD->getAccess()));
1120}
1121
1122void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) {
1123 if (const TypeSourceInfo *T = FD->getFriendType())
1124 JOS.attribute(Key: "type", Contents: createQualType(QT: T->getType()));
1125 attributeOnlyIfTrue(Key: "isPackExpansion", Value: FD->isPackExpansion());
1126}
1127
1128void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
1129 VisitNamedDecl(ND: D);
1130 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1131 attributeOnlyIfTrue(Key: "synthesized", Value: D->getSynthesize());
1132 switch (D->getAccessControl()) {
1133 case ObjCIvarDecl::None: JOS.attribute(Key: "access", Contents: "none"); break;
1134 case ObjCIvarDecl::Private: JOS.attribute(Key: "access", Contents: "private"); break;
1135 case ObjCIvarDecl::Protected: JOS.attribute(Key: "access", Contents: "protected"); break;
1136 case ObjCIvarDecl::Public: JOS.attribute(Key: "access", Contents: "public"); break;
1137 case ObjCIvarDecl::Package: JOS.attribute(Key: "access", Contents: "package"); break;
1138 }
1139}
1140
1141void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
1142 VisitNamedDecl(ND: D);
1143 JOS.attribute(Key: "returnType", Contents: createQualType(QT: D->getReturnType()));
1144 JOS.attribute(Key: "instance", Contents: D->isInstanceMethod());
1145 attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic());
1146}
1147
1148void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
1149 VisitNamedDecl(ND: D);
1150 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getUnderlyingType()));
1151 attributeOnlyIfTrue(Key: "bounded", Value: D->hasExplicitBound());
1152 switch (D->getVariance()) {
1153 case ObjCTypeParamVariance::Invariant:
1154 break;
1155 case ObjCTypeParamVariance::Covariant:
1156 JOS.attribute(Key: "variance", Contents: "covariant");
1157 break;
1158 case ObjCTypeParamVariance::Contravariant:
1159 JOS.attribute(Key: "variance", Contents: "contravariant");
1160 break;
1161 }
1162}
1163
1164void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
1165 VisitNamedDecl(ND: D);
1166 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1167 JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D: D->getImplementation()));
1168
1169 llvm::json::Array Protocols;
1170 for (const auto* P : D->protocols())
1171 Protocols.push_back(E: createBareDeclRef(D: P));
1172 if (!Protocols.empty())
1173 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1174}
1175
1176void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
1177 VisitNamedDecl(ND: D);
1178 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1179 JOS.attribute(Key: "categoryDecl", Contents: createBareDeclRef(D: D->getCategoryDecl()));
1180}
1181
1182void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
1183 VisitNamedDecl(ND: D);
1184
1185 llvm::json::Array Protocols;
1186 for (const auto *P : D->protocols())
1187 Protocols.push_back(E: createBareDeclRef(D: P));
1188 if (!Protocols.empty())
1189 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1190}
1191
1192void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
1193 VisitNamedDecl(ND: D);
1194 JOS.attribute(Key: "super", Contents: createBareDeclRef(D: D->getSuperClass()));
1195 JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D: D->getImplementation()));
1196
1197 llvm::json::Array Protocols;
1198 for (const auto* P : D->protocols())
1199 Protocols.push_back(E: createBareDeclRef(D: P));
1200 if (!Protocols.empty())
1201 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1202}
1203
1204void JSONNodeDumper::VisitObjCImplementationDecl(
1205 const ObjCImplementationDecl *D) {
1206 VisitNamedDecl(ND: D);
1207 JOS.attribute(Key: "super", Contents: createBareDeclRef(D: D->getSuperClass()));
1208 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1209}
1210
1211void JSONNodeDumper::VisitObjCCompatibleAliasDecl(
1212 const ObjCCompatibleAliasDecl *D) {
1213 VisitNamedDecl(ND: D);
1214 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1215}
1216
1217void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1218 VisitNamedDecl(ND: D);
1219 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1220
1221 switch (D->getPropertyImplementation()) {
1222 case ObjCPropertyDecl::None: break;
1223 case ObjCPropertyDecl::Required: JOS.attribute(Key: "control", Contents: "required"); break;
1224 case ObjCPropertyDecl::Optional: JOS.attribute(Key: "control", Contents: "optional"); break;
1225 }
1226
1227 ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
1228 if (Attrs != ObjCPropertyAttribute::kind_noattr) {
1229 if (Attrs & ObjCPropertyAttribute::kind_getter)
1230 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: D->getGetterMethodDecl()));
1231 if (Attrs & ObjCPropertyAttribute::kind_setter)
1232 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: D->getSetterMethodDecl()));
1233 attributeOnlyIfTrue(Key: "readonly",
1234 Value: Attrs & ObjCPropertyAttribute::kind_readonly);
1235 attributeOnlyIfTrue(Key: "assign", Value: Attrs & ObjCPropertyAttribute::kind_assign);
1236 attributeOnlyIfTrue(Key: "readwrite",
1237 Value: Attrs & ObjCPropertyAttribute::kind_readwrite);
1238 attributeOnlyIfTrue(Key: "retain", Value: Attrs & ObjCPropertyAttribute::kind_retain);
1239 attributeOnlyIfTrue(Key: "copy", Value: Attrs & ObjCPropertyAttribute::kind_copy);
1240 attributeOnlyIfTrue(Key: "nonatomic",
1241 Value: Attrs & ObjCPropertyAttribute::kind_nonatomic);
1242 attributeOnlyIfTrue(Key: "atomic", Value: Attrs & ObjCPropertyAttribute::kind_atomic);
1243 attributeOnlyIfTrue(Key: "weak", Value: Attrs & ObjCPropertyAttribute::kind_weak);
1244 attributeOnlyIfTrue(Key: "strong", Value: Attrs & ObjCPropertyAttribute::kind_strong);
1245 attributeOnlyIfTrue(Key: "unsafe_unretained",
1246 Value: Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);
1247 attributeOnlyIfTrue(Key: "class", Value: Attrs & ObjCPropertyAttribute::kind_class);
1248 attributeOnlyIfTrue(Key: "direct", Value: Attrs & ObjCPropertyAttribute::kind_direct);
1249 attributeOnlyIfTrue(Key: "nullability",
1250 Value: Attrs & ObjCPropertyAttribute::kind_nullability);
1251 attributeOnlyIfTrue(Key: "null_resettable",
1252 Value: Attrs & ObjCPropertyAttribute::kind_null_resettable);
1253 }
1254}
1255
1256void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1257 VisitNamedDecl(ND: D->getPropertyDecl());
1258 JOS.attribute(Key: "implKind", Contents: D->getPropertyImplementation() ==
1259 ObjCPropertyImplDecl::Synthesize
1260 ? "synthesize"
1261 : "dynamic");
1262 JOS.attribute(Key: "propertyDecl", Contents: createBareDeclRef(D: D->getPropertyDecl()));
1263 JOS.attribute(Key: "ivarDecl", Contents: createBareDeclRef(D: D->getPropertyIvarDecl()));
1264}
1265
1266void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) {
1267 attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic());
1268 attributeOnlyIfTrue(Key: "capturesThis", Value: D->capturesCXXThis());
1269}
1270
1271void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
1272 JOS.attribute(Key: "name", Contents: AE->getOpAsString());
1273}
1274
1275void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) {
1276 JOS.attribute(Key: "encodedType", Contents: createQualType(QT: OEE->getEncodedType()));
1277}
1278
1279void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *OME) {
1280 std::string Str;
1281 llvm::raw_string_ostream OS(Str);
1282
1283 OME->getSelector().print(OS);
1284 JOS.attribute(Key: "selector", Contents: Str);
1285
1286 switch (OME->getReceiverKind()) {
1287 case ObjCMessageExpr::Instance:
1288 JOS.attribute(Key: "receiverKind", Contents: "instance");
1289 break;
1290 case ObjCMessageExpr::Class:
1291 JOS.attribute(Key: "receiverKind", Contents: "class");
1292 JOS.attribute(Key: "classType", Contents: createQualType(QT: OME->getClassReceiver()));
1293 break;
1294 case ObjCMessageExpr::SuperInstance:
1295 JOS.attribute(Key: "receiverKind", Contents: "super (instance)");
1296 JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType()));
1297 break;
1298 case ObjCMessageExpr::SuperClass:
1299 JOS.attribute(Key: "receiverKind", Contents: "super (class)");
1300 JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType()));
1301 break;
1302 }
1303
1304 QualType CallReturnTy = OME->getCallReturnType(Ctx);
1305 if (OME->getType() != CallReturnTy)
1306 JOS.attribute(Key: "callReturnType", Contents: createQualType(QT: CallReturnTy));
1307}
1308
1309void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE) {
1310 if (const ObjCMethodDecl *MD = OBE->getBoxingMethod()) {
1311 std::string Str;
1312 llvm::raw_string_ostream OS(Str);
1313
1314 MD->getSelector().print(OS);
1315 JOS.attribute(Key: "selector", Contents: Str);
1316 }
1317}
1318
1319void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE) {
1320 std::string Str;
1321 llvm::raw_string_ostream OS(Str);
1322
1323 OSE->getSelector().print(OS);
1324 JOS.attribute(Key: "selector", Contents: Str);
1325}
1326
1327void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {
1328 JOS.attribute(Key: "protocol", Contents: createBareDeclRef(D: OPE->getProtocol()));
1329}
1330
1331void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {
1332 if (OPRE->isImplicitProperty()) {
1333 JOS.attribute(Key: "propertyKind", Contents: "implicit");
1334 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter())
1335 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: MD));
1336 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter())
1337 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: MD));
1338 } else {
1339 JOS.attribute(Key: "propertyKind", Contents: "explicit");
1340 JOS.attribute(Key: "property", Contents: createBareDeclRef(D: OPRE->getExplicitProperty()));
1341 }
1342
1343 attributeOnlyIfTrue(Key: "isSuperReceiver", Value: OPRE->isSuperReceiver());
1344 attributeOnlyIfTrue(Key: "isMessagingGetter", Value: OPRE->isMessagingGetter());
1345 attributeOnlyIfTrue(Key: "isMessagingSetter", Value: OPRE->isMessagingSetter());
1346}
1347
1348void JSONNodeDumper::VisitObjCSubscriptRefExpr(
1349 const ObjCSubscriptRefExpr *OSRE) {
1350 JOS.attribute(Key: "subscriptKind",
1351 Contents: OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary");
1352
1353 if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl())
1354 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: MD));
1355 if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl())
1356 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: MD));
1357}
1358
1359void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {
1360 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: OIRE->getDecl()));
1361 attributeOnlyIfTrue(Key: "isFreeIvar", Value: OIRE->isFreeIvar());
1362 JOS.attribute(Key: "isArrow", Contents: OIRE->isArrow());
1363}
1364
1365void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) {
1366 JOS.attribute(Key: "value", Contents: OBLE->getValue() ? "__objc_yes" : "__objc_no");
1367}
1368
1369void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
1370 JOS.attribute(Key: "referencedDecl", Contents: createBareDeclRef(D: DRE->getDecl()));
1371 if (DRE->getDecl() != DRE->getFoundDecl())
1372 JOS.attribute(Key: "foundReferencedDecl",
1373 Contents: createBareDeclRef(D: DRE->getFoundDecl()));
1374 switch (DRE->isNonOdrUse()) {
1375 case NOUR_None: break;
1376 case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break;
1377 case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break;
1378 case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break;
1379 }
1380 attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: DRE->isImmediateEscalating());
1381}
1382
1383void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
1384 const SYCLUniqueStableNameExpr *E) {
1385 JOS.attribute(Key: "typeSourceInfo",
1386 Contents: createQualType(QT: E->getTypeSourceInfo()->getType()));
1387}
1388
1389void JSONNodeDumper::VisitOpenACCAsteriskSizeExpr(
1390 const OpenACCAsteriskSizeExpr *E) {}
1391
1392void JSONNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) {}
1393void JSONNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) {}
1394
1395void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
1396 JOS.attribute(Key: "name", Contents: PredefinedExpr::getIdentKindName(IK: PE->getIdentKind()));
1397}
1398
1399void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {
1400 JOS.attribute(Key: "isPostfix", Contents: UO->isPostfix());
1401 JOS.attribute(Key: "opcode", Contents: UnaryOperator::getOpcodeStr(Op: UO->getOpcode()));
1402 if (!UO->canOverflow())
1403 JOS.attribute(Key: "canOverflow", Contents: false);
1404}
1405
1406void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) {
1407 JOS.attribute(Key: "opcode", Contents: BinaryOperator::getOpcodeStr(Op: BO->getOpcode()));
1408}
1409
1410void JSONNodeDumper::VisitCompoundAssignOperator(
1411 const CompoundAssignOperator *CAO) {
1412 VisitBinaryOperator(BO: CAO);
1413 JOS.attribute(Key: "computeLHSType", Contents: createQualType(QT: CAO->getComputationLHSType()));
1414 JOS.attribute(Key: "computeResultType",
1415 Contents: createQualType(QT: CAO->getComputationResultType()));
1416}
1417
1418void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) {
1419 // Note, we always write this Boolean field because the information it conveys
1420 // is critical to understanding the AST node.
1421 ValueDecl *VD = ME->getMemberDecl();
1422 JOS.attribute(Key: "name", Contents: VD && VD->getDeclName() ? VD->getNameAsString() : "");
1423 JOS.attribute(Key: "isArrow", Contents: ME->isArrow());
1424 JOS.attribute(Key: "referencedMemberDecl", Contents: createPointerRepresentation(Ptr: VD));
1425 switch (ME->isNonOdrUse()) {
1426 case NOUR_None: break;
1427 case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break;
1428 case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break;
1429 case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break;
1430 }
1431}
1432
1433void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {
1434 attributeOnlyIfTrue(Key: "isGlobal", Value: NE->isGlobalNew());
1435 attributeOnlyIfTrue(Key: "isArray", Value: NE->isArray());
1436 attributeOnlyIfTrue(Key: "isPlacement", Value: NE->getNumPlacementArgs() != 0);
1437 switch (NE->getInitializationStyle()) {
1438 case CXXNewInitializationStyle::None:
1439 break;
1440 case CXXNewInitializationStyle::Parens:
1441 JOS.attribute(Key: "initStyle", Contents: "call");
1442 break;
1443 case CXXNewInitializationStyle::Braces:
1444 JOS.attribute(Key: "initStyle", Contents: "list");
1445 break;
1446 }
1447 if (const FunctionDecl *FD = NE->getOperatorNew())
1448 JOS.attribute(Key: "operatorNewDecl", Contents: createBareDeclRef(D: FD));
1449 if (const FunctionDecl *FD = NE->getOperatorDelete())
1450 JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(D: FD));
1451}
1452void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {
1453 attributeOnlyIfTrue(Key: "isGlobal", Value: DE->isGlobalDelete());
1454 attributeOnlyIfTrue(Key: "isArray", Value: DE->isArrayForm());
1455 attributeOnlyIfTrue(Key: "isArrayAsWritten", Value: DE->isArrayFormAsWritten());
1456 if (const FunctionDecl *FD = DE->getOperatorDelete())
1457 JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(D: FD));
1458}
1459
1460void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) {
1461 attributeOnlyIfTrue(Key: "implicit", Value: TE->isImplicit());
1462}
1463
1464void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) {
1465 JOS.attribute(Key: "castKind", Contents: CE->getCastKindName());
1466 llvm::json::Array Path = createCastPath(C: CE);
1467 if (!Path.empty())
1468 JOS.attribute(Key: "path", Contents: std::move(Path));
1469 // FIXME: This may not be useful information as it can be obtusely gleaned
1470 // from the inner[] array.
1471 if (const NamedDecl *ND = CE->getConversionFunction())
1472 JOS.attribute(Key: "conversionFunc", Contents: createBareDeclRef(D: ND));
1473}
1474
1475void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
1476 VisitCastExpr(CE: ICE);
1477 attributeOnlyIfTrue(Key: "isPartOfExplicitCast", Value: ICE->isPartOfExplicitCast());
1478}
1479
1480void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {
1481 attributeOnlyIfTrue(Key: "adl", Value: CE->usesADL());
1482}
1483
1484void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
1485 const UnaryExprOrTypeTraitExpr *TTE) {
1486 JOS.attribute(Key: "name", Contents: getTraitSpelling(T: TTE->getKind()));
1487 if (TTE->isArgumentType())
1488 JOS.attribute(Key: "argType", Contents: createQualType(QT: TTE->getArgumentType()));
1489}
1490
1491void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) {
1492 VisitNamedDecl(ND: SOPE->getPack());
1493}
1494
1495void JSONNodeDumper::VisitUnresolvedLookupExpr(
1496 const UnresolvedLookupExpr *ULE) {
1497 JOS.attribute(Key: "usesADL", Contents: ULE->requiresADL());
1498 JOS.attribute(Key: "name", Contents: ULE->getName().getAsString());
1499
1500 JOS.attributeArray(Key: "lookups", Contents: [this, ULE] {
1501 for (const NamedDecl *D : ULE->decls())
1502 JOS.value(V: createBareDeclRef(D));
1503 });
1504}
1505
1506void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) {
1507 JOS.attribute(Key: "name", Contents: ALE->getLabel()->getName());
1508 JOS.attribute(Key: "labelDeclId", Contents: createPointerRepresentation(Ptr: ALE->getLabel()));
1509}
1510
1511void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
1512 if (CTE->isTypeOperand()) {
1513 QualType Adjusted = CTE->getTypeOperand(Context: Ctx);
1514 QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType();
1515 JOS.attribute(Key: "typeArg", Contents: createQualType(QT: Unadjusted));
1516 if (Adjusted != Unadjusted)
1517 JOS.attribute(Key: "adjustedTypeArg", Contents: createQualType(QT: Adjusted));
1518 }
1519}
1520
1521void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
1522 if (CE->getResultAPValueKind() != APValue::None)
1523 Visit(Value: CE->getAPValueResult(), Ty: CE->getType());
1524}
1525
1526void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
1527 if (const FieldDecl *FD = ILE->getInitializedFieldInUnion())
1528 JOS.attribute(Key: "field", Contents: createBareDeclRef(D: FD));
1529}
1530
1531void JSONNodeDumper::VisitGenericSelectionExpr(
1532 const GenericSelectionExpr *GSE) {
1533 attributeOnlyIfTrue(Key: "resultDependent", Value: GSE->isResultDependent());
1534}
1535
1536void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(
1537 const CXXUnresolvedConstructExpr *UCE) {
1538 if (UCE->getType() != UCE->getTypeAsWritten())
1539 JOS.attribute(Key: "typeAsWritten", Contents: createQualType(QT: UCE->getTypeAsWritten()));
1540 attributeOnlyIfTrue(Key: "list", Value: UCE->isListInitialization());
1541}
1542
1543void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) {
1544 CXXConstructorDecl *Ctor = CE->getConstructor();
1545 JOS.attribute(Key: "ctorType", Contents: createQualType(QT: Ctor->getType()));
1546 attributeOnlyIfTrue(Key: "elidable", Value: CE->isElidable());
1547 attributeOnlyIfTrue(Key: "list", Value: CE->isListInitialization());
1548 attributeOnlyIfTrue(Key: "initializer_list", Value: CE->isStdInitListInitialization());
1549 attributeOnlyIfTrue(Key: "zeroing", Value: CE->requiresZeroInitialization());
1550 attributeOnlyIfTrue(Key: "hadMultipleCandidates", Value: CE->hadMultipleCandidates());
1551 attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: CE->isImmediateEscalating());
1552
1553 switch (CE->getConstructionKind()) {
1554 case CXXConstructionKind::Complete:
1555 JOS.attribute(Key: "constructionKind", Contents: "complete");
1556 break;
1557 case CXXConstructionKind::Delegating:
1558 JOS.attribute(Key: "constructionKind", Contents: "delegating");
1559 break;
1560 case CXXConstructionKind::NonVirtualBase:
1561 JOS.attribute(Key: "constructionKind", Contents: "non-virtual base");
1562 break;
1563 case CXXConstructionKind::VirtualBase:
1564 JOS.attribute(Key: "constructionKind", Contents: "virtual base");
1565 break;
1566 }
1567}
1568
1569void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {
1570 attributeOnlyIfTrue(Key: "cleanupsHaveSideEffects",
1571 Value: EWC->cleanupsHaveSideEffects());
1572 if (EWC->getNumObjects()) {
1573 JOS.attributeArray(Key: "cleanups", Contents: [this, EWC] {
1574 for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())
1575 if (auto *BD = dyn_cast<BlockDecl *>(Val: CO)) {
1576 JOS.value(V: createBareDeclRef(D: BD));
1577 } else if (auto *CLE = dyn_cast<CompoundLiteralExpr *>(Val: CO)) {
1578 llvm::json::Object Obj;
1579 Obj["id"] = createPointerRepresentation(Ptr: CLE);
1580 Obj["kind"] = CLE->getStmtClassName();
1581 JOS.value(V: std::move(Obj));
1582 } else {
1583 llvm_unreachable("unexpected cleanup object type");
1584 }
1585 });
1586 }
1587}
1588
1589void JSONNodeDumper::VisitCXXBindTemporaryExpr(
1590 const CXXBindTemporaryExpr *BTE) {
1591 const CXXTemporary *Temp = BTE->getTemporary();
1592 JOS.attribute(Key: "temp", Contents: createPointerRepresentation(Ptr: Temp));
1593 if (const CXXDestructorDecl *Dtor = Temp->getDestructor())
1594 JOS.attribute(Key: "dtor", Contents: createBareDeclRef(D: Dtor));
1595}
1596
1597void JSONNodeDumper::VisitMaterializeTemporaryExpr(
1598 const MaterializeTemporaryExpr *MTE) {
1599 if (const ValueDecl *VD = MTE->getExtendingDecl())
1600 JOS.attribute(Key: "extendingDecl", Contents: createBareDeclRef(D: VD));
1601
1602 switch (MTE->getStorageDuration()) {
1603 case SD_Automatic:
1604 JOS.attribute(Key: "storageDuration", Contents: "automatic");
1605 break;
1606 case SD_Dynamic:
1607 JOS.attribute(Key: "storageDuration", Contents: "dynamic");
1608 break;
1609 case SD_FullExpression:
1610 JOS.attribute(Key: "storageDuration", Contents: "full expression");
1611 break;
1612 case SD_Static:
1613 JOS.attribute(Key: "storageDuration", Contents: "static");
1614 break;
1615 case SD_Thread:
1616 JOS.attribute(Key: "storageDuration", Contents: "thread");
1617 break;
1618 }
1619
1620 attributeOnlyIfTrue(Key: "boundToLValueRef", Value: MTE->isBoundToLvalueReference());
1621}
1622
1623void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
1624 attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit());
1625}
1626
1627void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
1628 attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit());
1629}
1630
1631void JSONNodeDumper::VisitLambdaExpr(const LambdaExpr *LE) {
1632 JOS.attribute(Key: "hasExplicitParameters", Contents: LE->hasExplicitParameters());
1633}
1634
1635void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
1636 const CXXDependentScopeMemberExpr *DSME) {
1637 JOS.attribute(Key: "isArrow", Contents: DSME->isArrow());
1638 JOS.attribute(Key: "member", Contents: DSME->getMember().getAsString());
1639 attributeOnlyIfTrue(Key: "hasTemplateKeyword", Value: DSME->hasTemplateKeyword());
1640 attributeOnlyIfTrue(Key: "hasExplicitTemplateArgs",
1641 Value: DSME->hasExplicitTemplateArgs());
1642
1643 if (DSME->getNumTemplateArgs()) {
1644 JOS.attributeArray(Key: "explicitTemplateArgs", Contents: [DSME, this] {
1645 for (const TemplateArgumentLoc &TAL : DSME->template_arguments())
1646 JOS.object(
1647 Contents: [&TAL, this] { Visit(TA: TAL.getArgument(), R: TAL.getSourceRange()); });
1648 });
1649 }
1650}
1651
1652void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {
1653 if (!RE->isValueDependent())
1654 JOS.attribute(Key: "satisfied", Contents: RE->isSatisfied());
1655}
1656
1657void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {
1658 llvm::SmallString<16> Buffer;
1659 IL->getValue().toString(Str&: Buffer,
1660 /*Radix=*/10, Signed: IL->getType()->isSignedIntegerType());
1661 JOS.attribute(Key: "value", Contents: Buffer);
1662}
1663void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) {
1664 // FIXME: This should probably print the character literal as a string,
1665 // rather than as a numerical value. It would be nice if the behavior matched
1666 // what we do to print a string literal; right now, it is impossible to tell
1667 // the difference between 'a' and L'a' in C from the JSON output.
1668 JOS.attribute(Key: "value", Contents: CL->getValue());
1669}
1670void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) {
1671 JOS.attribute(Key: "value", Contents: FPL->getValueAsString(/*Radix=*/10));
1672}
1673void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) {
1674 llvm::SmallString<16> Buffer;
1675 FL->getValue().toString(Str&: Buffer);
1676 JOS.attribute(Key: "value", Contents: Buffer);
1677}
1678void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) {
1679 std::string Buffer;
1680 llvm::raw_string_ostream SS(Buffer);
1681 SL->outputString(OS&: SS);
1682 JOS.attribute(Key: "value", Contents: Buffer);
1683}
1684void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) {
1685 JOS.attribute(Key: "value", Contents: BLE->getValue());
1686}
1687
1688void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) {
1689 attributeOnlyIfTrue(Key: "hasInit", Value: IS->hasInitStorage());
1690 attributeOnlyIfTrue(Key: "hasVar", Value: IS->hasVarStorage());
1691 attributeOnlyIfTrue(Key: "hasElse", Value: IS->hasElseStorage());
1692 attributeOnlyIfTrue(Key: "isConstexpr", Value: IS->isConstexpr());
1693 attributeOnlyIfTrue(Key: "isConsteval", Value: IS->isConsteval());
1694 attributeOnlyIfTrue(Key: "constevalIsNegated", Value: IS->isNegatedConsteval());
1695}
1696
1697void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) {
1698 attributeOnlyIfTrue(Key: "hasInit", Value: SS->hasInitStorage());
1699 attributeOnlyIfTrue(Key: "hasVar", Value: SS->hasVarStorage());
1700}
1701void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
1702 attributeOnlyIfTrue(Key: "isGNURange", Value: CS->caseStmtIsGNURange());
1703}
1704
1705void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
1706 JOS.attribute(Key: "name", Contents: LS->getName());
1707 JOS.attribute(Key: "declId", Contents: createPointerRepresentation(Ptr: LS->getDecl()));
1708 attributeOnlyIfTrue(Key: "sideEntry", Value: LS->isSideEntry());
1709}
1710
1711void JSONNodeDumper::VisitLoopControlStmt(const LoopControlStmt *LS) {
1712 if (LS->hasLabelTarget())
1713 JOS.attribute(Key: "targetLabelDeclId",
1714 Contents: createPointerRepresentation(Ptr: LS->getLabelDecl()));
1715}
1716
1717void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
1718 JOS.attribute(Key: "targetLabelDeclId",
1719 Contents: createPointerRepresentation(Ptr: GS->getLabel()));
1720}
1721
1722void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) {
1723 attributeOnlyIfTrue(Key: "hasVar", Value: WS->hasVarStorage());
1724}
1725
1726void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) {
1727 // FIXME: it would be nice for the ASTNodeTraverser would handle the catch
1728 // parameter the same way for C++ and ObjC rather. In this case, C++ gets a
1729 // null child node and ObjC gets no child node.
1730 attributeOnlyIfTrue(Key: "isCatchAll", Value: OACS->getCatchParamDecl() == nullptr);
1731}
1732
1733void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) {
1734 JOS.attribute(Key: "isNull", Contents: true);
1735}
1736void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
1737 JOS.attribute(Key: "type", Contents: createQualType(QT: TA.getAsType()));
1738}
1739void JSONNodeDumper::VisitDeclarationTemplateArgument(
1740 const TemplateArgument &TA) {
1741 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TA.getAsDecl()));
1742}
1743void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) {
1744 JOS.attribute(Key: "isNullptr", Contents: true);
1745}
1746void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
1747 JOS.attribute(Key: "value", Contents: TA.getAsIntegral().getSExtValue());
1748}
1749void JSONNodeDumper::VisitStructuralValueTemplateArgument(
1750 const TemplateArgument &TA) {
1751 Visit(Value: TA.getAsStructuralValue(), Ty: TA.getStructuralValueType());
1752}
1753void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
1754 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1755 // the output format.
1756}
1757void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
1758 const TemplateArgument &TA) {
1759 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1760 // the output format.
1761}
1762void JSONNodeDumper::VisitExpressionTemplateArgument(
1763 const TemplateArgument &TA) {
1764 JOS.attribute(Key: "isExpr", Contents: true);
1765 if (TA.isCanonicalExpr())
1766 JOS.attribute(Key: "isCanonical", Contents: true);
1767}
1768void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
1769 JOS.attribute(Key: "isPack", Contents: true);
1770}
1771
1772StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const {
1773 if (Traits)
1774 return Traits->getCommandInfo(CommandID)->Name;
1775 if (const comments::CommandInfo *Info =
1776 comments::CommandTraits::getBuiltinCommandInfo(CommandID))
1777 return Info->Name;
1778 return "<invalid>";
1779}
1780
1781void JSONNodeDumper::visitTextComment(const comments::TextComment *C,
1782 const comments::FullComment *) {
1783 JOS.attribute(Key: "text", Contents: C->getText());
1784}
1785
1786void JSONNodeDumper::visitInlineCommandComment(
1787 const comments::InlineCommandComment *C, const comments::FullComment *) {
1788 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1789
1790 switch (C->getRenderKind()) {
1791 case comments::InlineCommandRenderKind::Normal:
1792 JOS.attribute(Key: "renderKind", Contents: "normal");
1793 break;
1794 case comments::InlineCommandRenderKind::Bold:
1795 JOS.attribute(Key: "renderKind", Contents: "bold");
1796 break;
1797 case comments::InlineCommandRenderKind::Emphasized:
1798 JOS.attribute(Key: "renderKind", Contents: "emphasized");
1799 break;
1800 case comments::InlineCommandRenderKind::Monospaced:
1801 JOS.attribute(Key: "renderKind", Contents: "monospaced");
1802 break;
1803 case comments::InlineCommandRenderKind::Anchor:
1804 JOS.attribute(Key: "renderKind", Contents: "anchor");
1805 break;
1806 }
1807
1808 llvm::json::Array Args;
1809 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
1810 Args.push_back(E: C->getArgText(Idx: I));
1811
1812 if (!Args.empty())
1813 JOS.attribute(Key: "args", Contents: std::move(Args));
1814}
1815
1816void JSONNodeDumper::visitHTMLStartTagComment(
1817 const comments::HTMLStartTagComment *C, const comments::FullComment *) {
1818 JOS.attribute(Key: "name", Contents: C->getTagName());
1819 attributeOnlyIfTrue(Key: "selfClosing", Value: C->isSelfClosing());
1820 attributeOnlyIfTrue(Key: "malformed", Value: C->isMalformed());
1821
1822 llvm::json::Array Attrs;
1823 for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I)
1824 Attrs.push_back(
1825 E: {{"name", C->getAttr(Idx: I).Name}, {"value", C->getAttr(Idx: I).Value}});
1826
1827 if (!Attrs.empty())
1828 JOS.attribute(Key: "attrs", Contents: std::move(Attrs));
1829}
1830
1831void JSONNodeDumper::visitHTMLEndTagComment(
1832 const comments::HTMLEndTagComment *C, const comments::FullComment *) {
1833 JOS.attribute(Key: "name", Contents: C->getTagName());
1834}
1835
1836void JSONNodeDumper::visitBlockCommandComment(
1837 const comments::BlockCommandComment *C, const comments::FullComment *) {
1838 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1839
1840 llvm::json::Array Args;
1841 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
1842 Args.push_back(E: C->getArgText(Idx: I));
1843
1844 if (!Args.empty())
1845 JOS.attribute(Key: "args", Contents: std::move(Args));
1846}
1847
1848void JSONNodeDumper::visitParamCommandComment(
1849 const comments::ParamCommandComment *C, const comments::FullComment *FC) {
1850 switch (C->getDirection()) {
1851 case comments::ParamCommandPassDirection::In:
1852 JOS.attribute(Key: "direction", Contents: "in");
1853 break;
1854 case comments::ParamCommandPassDirection::Out:
1855 JOS.attribute(Key: "direction", Contents: "out");
1856 break;
1857 case comments::ParamCommandPassDirection::InOut:
1858 JOS.attribute(Key: "direction", Contents: "in,out");
1859 break;
1860 }
1861 attributeOnlyIfTrue(Key: "explicit", Value: C->isDirectionExplicit());
1862
1863 if (C->hasParamName())
1864 JOS.attribute(Key: "param", Contents: C->isParamIndexValid() ? C->getParamName(FC)
1865 : C->getParamNameAsWritten());
1866
1867 if (C->isParamIndexValid() && !C->isVarArgParam())
1868 JOS.attribute(Key: "paramIdx", Contents: C->getParamIndex());
1869}
1870
1871void JSONNodeDumper::visitTParamCommandComment(
1872 const comments::TParamCommandComment *C, const comments::FullComment *FC) {
1873 if (C->hasParamName())
1874 JOS.attribute(Key: "param", Contents: C->isPositionValid() ? C->getParamName(FC)
1875 : C->getParamNameAsWritten());
1876 if (C->isPositionValid()) {
1877 llvm::json::Array Positions;
1878 for (unsigned I = 0, E = C->getDepth(); I < E; ++I)
1879 Positions.push_back(E: C->getIndex(Depth: I));
1880
1881 if (!Positions.empty())
1882 JOS.attribute(Key: "positions", Contents: std::move(Positions));
1883 }
1884}
1885
1886void JSONNodeDumper::visitVerbatimBlockComment(
1887 const comments::VerbatimBlockComment *C, const comments::FullComment *) {
1888 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1889 JOS.attribute(Key: "closeName", Contents: C->getCloseName());
1890}
1891
1892void JSONNodeDumper::visitVerbatimBlockLineComment(
1893 const comments::VerbatimBlockLineComment *C,
1894 const comments::FullComment *) {
1895 JOS.attribute(Key: "text", Contents: C->getText());
1896}
1897
1898void JSONNodeDumper::visitVerbatimLineComment(
1899 const comments::VerbatimLineComment *C, const comments::FullComment *) {
1900 JOS.attribute(Key: "text", Contents: C->getText());
1901}
1902
1903llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) {
1904 llvm::json::Object Ret;
1905#define FP_OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
1906 if (FPO.has##NAME##Override()) \
1907 Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override()));
1908#include "clang/Basic/FPOptions.def"
1909 return Ret;
1910}
1911
1912void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
1913 VisitStmt(Node: S);
1914 if (S->hasStoredFPFeatures())
1915 JOS.attribute(Key: "fpoptions", Contents: createFPOptions(FPO: S->getStoredFPFeatures()));
1916}
1917