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::VisitExplicitInstantiationDecl(
1123 const ExplicitInstantiationDecl *D) {
1124 attributeOnlyIfTrue(Key: "isExternTemplate", Value: D->isExternTemplate());
1125 if (D->getSpecialization())
1126 JOS.attribute(Key: "specializationDeclId",
1127 Contents: createPointerRepresentation(Ptr: D->getSpecialization()));
1128 switch (D->getTemplateSpecializationKind()) {
1129 case TSK_Undeclared:
1130 break;
1131 case TSK_ImplicitInstantiation:
1132 JOS.attribute(Key: "templateSpecializationKind", Contents: "implicit_instantiation");
1133 break;
1134 case TSK_ExplicitSpecialization:
1135 JOS.attribute(Key: "templateSpecializationKind", Contents: "explicit_specialization");
1136 break;
1137 case TSK_ExplicitInstantiationDeclaration:
1138 JOS.attribute(Key: "templateSpecializationKind",
1139 Contents: "explicit_instantiation_declaration");
1140 break;
1141 case TSK_ExplicitInstantiationDefinition:
1142 JOS.attribute(Key: "templateSpecializationKind",
1143 Contents: "explicit_instantiation_definition");
1144 break;
1145 }
1146}
1147
1148void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) {
1149 if (const TypeSourceInfo *T = FD->getFriendType())
1150 JOS.attribute(Key: "type", Contents: createQualType(QT: T->getType()));
1151 attributeOnlyIfTrue(Key: "isPackExpansion", Value: FD->isPackExpansion());
1152}
1153
1154void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
1155 VisitNamedDecl(ND: D);
1156 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1157 attributeOnlyIfTrue(Key: "synthesized", Value: D->getSynthesize());
1158 switch (D->getAccessControl()) {
1159 case ObjCIvarDecl::None: JOS.attribute(Key: "access", Contents: "none"); break;
1160 case ObjCIvarDecl::Private: JOS.attribute(Key: "access", Contents: "private"); break;
1161 case ObjCIvarDecl::Protected: JOS.attribute(Key: "access", Contents: "protected"); break;
1162 case ObjCIvarDecl::Public: JOS.attribute(Key: "access", Contents: "public"); break;
1163 case ObjCIvarDecl::Package: JOS.attribute(Key: "access", Contents: "package"); break;
1164 }
1165}
1166
1167void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
1168 VisitNamedDecl(ND: D);
1169 JOS.attribute(Key: "returnType", Contents: createQualType(QT: D->getReturnType()));
1170 JOS.attribute(Key: "instance", Contents: D->isInstanceMethod());
1171 attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic());
1172}
1173
1174void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
1175 VisitNamedDecl(ND: D);
1176 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getUnderlyingType()));
1177 attributeOnlyIfTrue(Key: "bounded", Value: D->hasExplicitBound());
1178 switch (D->getVariance()) {
1179 case ObjCTypeParamVariance::Invariant:
1180 break;
1181 case ObjCTypeParamVariance::Covariant:
1182 JOS.attribute(Key: "variance", Contents: "covariant");
1183 break;
1184 case ObjCTypeParamVariance::Contravariant:
1185 JOS.attribute(Key: "variance", Contents: "contravariant");
1186 break;
1187 }
1188}
1189
1190void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
1191 VisitNamedDecl(ND: D);
1192 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1193 JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D: D->getImplementation()));
1194
1195 llvm::json::Array Protocols;
1196 for (const auto* P : D->protocols())
1197 Protocols.push_back(E: createBareDeclRef(D: P));
1198 if (!Protocols.empty())
1199 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1200}
1201
1202void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
1203 VisitNamedDecl(ND: D);
1204 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1205 JOS.attribute(Key: "categoryDecl", Contents: createBareDeclRef(D: D->getCategoryDecl()));
1206}
1207
1208void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
1209 VisitNamedDecl(ND: D);
1210
1211 llvm::json::Array Protocols;
1212 for (const auto *P : D->protocols())
1213 Protocols.push_back(E: createBareDeclRef(D: P));
1214 if (!Protocols.empty())
1215 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1216}
1217
1218void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
1219 VisitNamedDecl(ND: D);
1220 JOS.attribute(Key: "super", Contents: createBareDeclRef(D: D->getSuperClass()));
1221 JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D: D->getImplementation()));
1222
1223 llvm::json::Array Protocols;
1224 for (const auto* P : D->protocols())
1225 Protocols.push_back(E: createBareDeclRef(D: P));
1226 if (!Protocols.empty())
1227 JOS.attribute(Key: "protocols", Contents: std::move(Protocols));
1228}
1229
1230void JSONNodeDumper::VisitObjCImplementationDecl(
1231 const ObjCImplementationDecl *D) {
1232 VisitNamedDecl(ND: D);
1233 JOS.attribute(Key: "super", Contents: createBareDeclRef(D: D->getSuperClass()));
1234 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1235}
1236
1237void JSONNodeDumper::VisitObjCCompatibleAliasDecl(
1238 const ObjCCompatibleAliasDecl *D) {
1239 VisitNamedDecl(ND: D);
1240 JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface()));
1241}
1242
1243void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1244 VisitNamedDecl(ND: D);
1245 JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType()));
1246
1247 switch (D->getPropertyImplementation()) {
1248 case ObjCPropertyDecl::None: break;
1249 case ObjCPropertyDecl::Required: JOS.attribute(Key: "control", Contents: "required"); break;
1250 case ObjCPropertyDecl::Optional: JOS.attribute(Key: "control", Contents: "optional"); break;
1251 }
1252
1253 ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
1254 if (Attrs != ObjCPropertyAttribute::kind_noattr) {
1255 if (Attrs & ObjCPropertyAttribute::kind_getter)
1256 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: D->getGetterMethodDecl()));
1257 if (Attrs & ObjCPropertyAttribute::kind_setter)
1258 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: D->getSetterMethodDecl()));
1259 attributeOnlyIfTrue(Key: "readonly",
1260 Value: Attrs & ObjCPropertyAttribute::kind_readonly);
1261 attributeOnlyIfTrue(Key: "assign", Value: Attrs & ObjCPropertyAttribute::kind_assign);
1262 attributeOnlyIfTrue(Key: "readwrite",
1263 Value: Attrs & ObjCPropertyAttribute::kind_readwrite);
1264 attributeOnlyIfTrue(Key: "retain", Value: Attrs & ObjCPropertyAttribute::kind_retain);
1265 attributeOnlyIfTrue(Key: "copy", Value: Attrs & ObjCPropertyAttribute::kind_copy);
1266 attributeOnlyIfTrue(Key: "nonatomic",
1267 Value: Attrs & ObjCPropertyAttribute::kind_nonatomic);
1268 attributeOnlyIfTrue(Key: "atomic", Value: Attrs & ObjCPropertyAttribute::kind_atomic);
1269 attributeOnlyIfTrue(Key: "weak", Value: Attrs & ObjCPropertyAttribute::kind_weak);
1270 attributeOnlyIfTrue(Key: "strong", Value: Attrs & ObjCPropertyAttribute::kind_strong);
1271 attributeOnlyIfTrue(Key: "unsafe_unretained",
1272 Value: Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);
1273 attributeOnlyIfTrue(Key: "class", Value: Attrs & ObjCPropertyAttribute::kind_class);
1274 attributeOnlyIfTrue(Key: "direct", Value: Attrs & ObjCPropertyAttribute::kind_direct);
1275 attributeOnlyIfTrue(Key: "nullability",
1276 Value: Attrs & ObjCPropertyAttribute::kind_nullability);
1277 attributeOnlyIfTrue(Key: "null_resettable",
1278 Value: Attrs & ObjCPropertyAttribute::kind_null_resettable);
1279 }
1280}
1281
1282void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1283 VisitNamedDecl(ND: D->getPropertyDecl());
1284 JOS.attribute(Key: "implKind", Contents: D->getPropertyImplementation() ==
1285 ObjCPropertyImplDecl::Synthesize
1286 ? "synthesize"
1287 : "dynamic");
1288 JOS.attribute(Key: "propertyDecl", Contents: createBareDeclRef(D: D->getPropertyDecl()));
1289 JOS.attribute(Key: "ivarDecl", Contents: createBareDeclRef(D: D->getPropertyIvarDecl()));
1290}
1291
1292void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) {
1293 attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic());
1294 attributeOnlyIfTrue(Key: "capturesThis", Value: D->capturesCXXThis());
1295}
1296
1297void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
1298 JOS.attribute(Key: "name", Contents: AE->getOpAsString());
1299}
1300
1301void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) {
1302 JOS.attribute(Key: "encodedType", Contents: createQualType(QT: OEE->getEncodedType()));
1303}
1304
1305void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *OME) {
1306 std::string Str;
1307 llvm::raw_string_ostream OS(Str);
1308
1309 OME->getSelector().print(OS);
1310 JOS.attribute(Key: "selector", Contents: Str);
1311
1312 switch (OME->getReceiverKind()) {
1313 case ObjCMessageExpr::Instance:
1314 JOS.attribute(Key: "receiverKind", Contents: "instance");
1315 break;
1316 case ObjCMessageExpr::Class:
1317 JOS.attribute(Key: "receiverKind", Contents: "class");
1318 JOS.attribute(Key: "classType", Contents: createQualType(QT: OME->getClassReceiver()));
1319 break;
1320 case ObjCMessageExpr::SuperInstance:
1321 JOS.attribute(Key: "receiverKind", Contents: "super (instance)");
1322 JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType()));
1323 break;
1324 case ObjCMessageExpr::SuperClass:
1325 JOS.attribute(Key: "receiverKind", Contents: "super (class)");
1326 JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType()));
1327 break;
1328 }
1329
1330 QualType CallReturnTy = OME->getCallReturnType(Ctx);
1331 if (OME->getType() != CallReturnTy)
1332 JOS.attribute(Key: "callReturnType", Contents: createQualType(QT: CallReturnTy));
1333}
1334
1335void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE) {
1336 if (const ObjCMethodDecl *MD = OBE->getBoxingMethod()) {
1337 std::string Str;
1338 llvm::raw_string_ostream OS(Str);
1339
1340 MD->getSelector().print(OS);
1341 JOS.attribute(Key: "selector", Contents: Str);
1342 }
1343}
1344
1345void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE) {
1346 std::string Str;
1347 llvm::raw_string_ostream OS(Str);
1348
1349 OSE->getSelector().print(OS);
1350 JOS.attribute(Key: "selector", Contents: Str);
1351}
1352
1353void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {
1354 JOS.attribute(Key: "protocol", Contents: createBareDeclRef(D: OPE->getProtocol()));
1355}
1356
1357void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {
1358 if (OPRE->isImplicitProperty()) {
1359 JOS.attribute(Key: "propertyKind", Contents: "implicit");
1360 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter())
1361 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: MD));
1362 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter())
1363 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: MD));
1364 } else {
1365 JOS.attribute(Key: "propertyKind", Contents: "explicit");
1366 JOS.attribute(Key: "property", Contents: createBareDeclRef(D: OPRE->getExplicitProperty()));
1367 }
1368
1369 attributeOnlyIfTrue(Key: "isSuperReceiver", Value: OPRE->isSuperReceiver());
1370 attributeOnlyIfTrue(Key: "isMessagingGetter", Value: OPRE->isMessagingGetter());
1371 attributeOnlyIfTrue(Key: "isMessagingSetter", Value: OPRE->isMessagingSetter());
1372}
1373
1374void JSONNodeDumper::VisitObjCSubscriptRefExpr(
1375 const ObjCSubscriptRefExpr *OSRE) {
1376 JOS.attribute(Key: "subscriptKind",
1377 Contents: OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary");
1378
1379 if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl())
1380 JOS.attribute(Key: "getter", Contents: createBareDeclRef(D: MD));
1381 if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl())
1382 JOS.attribute(Key: "setter", Contents: createBareDeclRef(D: MD));
1383}
1384
1385void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {
1386 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: OIRE->getDecl()));
1387 attributeOnlyIfTrue(Key: "isFreeIvar", Value: OIRE->isFreeIvar());
1388 JOS.attribute(Key: "isArrow", Contents: OIRE->isArrow());
1389}
1390
1391void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) {
1392 JOS.attribute(Key: "value", Contents: OBLE->getValue() ? "__objc_yes" : "__objc_no");
1393}
1394
1395void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
1396 JOS.attribute(Key: "referencedDecl", Contents: createBareDeclRef(D: DRE->getDecl()));
1397 if (DRE->getDecl() != DRE->getFoundDecl())
1398 JOS.attribute(Key: "foundReferencedDecl",
1399 Contents: createBareDeclRef(D: DRE->getFoundDecl()));
1400 switch (DRE->isNonOdrUse()) {
1401 case NOUR_None: break;
1402 case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break;
1403 case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break;
1404 case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break;
1405 }
1406 attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: DRE->isImmediateEscalating());
1407}
1408
1409void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
1410 const SYCLUniqueStableNameExpr *E) {
1411 JOS.attribute(Key: "typeSourceInfo",
1412 Contents: createQualType(QT: E->getTypeSourceInfo()->getType()));
1413}
1414
1415void JSONNodeDumper::VisitOpenACCAsteriskSizeExpr(
1416 const OpenACCAsteriskSizeExpr *E) {}
1417
1418void JSONNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) {}
1419void JSONNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) {}
1420
1421void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
1422 JOS.attribute(Key: "name", Contents: PredefinedExpr::getIdentKindName(IK: PE->getIdentKind()));
1423}
1424
1425void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {
1426 JOS.attribute(Key: "isPostfix", Contents: UO->isPostfix());
1427 JOS.attribute(Key: "opcode", Contents: UnaryOperator::getOpcodeStr(Op: UO->getOpcode()));
1428 if (!UO->canOverflow())
1429 JOS.attribute(Key: "canOverflow", Contents: false);
1430}
1431
1432void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) {
1433 JOS.attribute(Key: "opcode", Contents: BinaryOperator::getOpcodeStr(Op: BO->getOpcode()));
1434}
1435
1436void JSONNodeDumper::VisitCompoundAssignOperator(
1437 const CompoundAssignOperator *CAO) {
1438 VisitBinaryOperator(BO: CAO);
1439 JOS.attribute(Key: "computeLHSType", Contents: createQualType(QT: CAO->getComputationLHSType()));
1440 JOS.attribute(Key: "computeResultType",
1441 Contents: createQualType(QT: CAO->getComputationResultType()));
1442}
1443
1444void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) {
1445 // Note, we always write this Boolean field because the information it conveys
1446 // is critical to understanding the AST node.
1447 ValueDecl *VD = ME->getMemberDecl();
1448 JOS.attribute(Key: "name", Contents: VD && VD->getDeclName() ? VD->getNameAsString() : "");
1449 JOS.attribute(Key: "isArrow", Contents: ME->isArrow());
1450 JOS.attribute(Key: "referencedMemberDecl", Contents: createPointerRepresentation(Ptr: VD));
1451 switch (ME->isNonOdrUse()) {
1452 case NOUR_None: break;
1453 case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break;
1454 case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break;
1455 case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break;
1456 }
1457}
1458
1459void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {
1460 attributeOnlyIfTrue(Key: "isGlobal", Value: NE->isGlobalNew());
1461 attributeOnlyIfTrue(Key: "isArray", Value: NE->isArray());
1462 attributeOnlyIfTrue(Key: "isPlacement", Value: NE->getNumPlacementArgs() != 0);
1463 switch (NE->getInitializationStyle()) {
1464 case CXXNewInitializationStyle::None:
1465 break;
1466 case CXXNewInitializationStyle::Parens:
1467 JOS.attribute(Key: "initStyle", Contents: "call");
1468 break;
1469 case CXXNewInitializationStyle::Braces:
1470 JOS.attribute(Key: "initStyle", Contents: "list");
1471 break;
1472 }
1473 if (const FunctionDecl *FD = NE->getOperatorNew())
1474 JOS.attribute(Key: "operatorNewDecl", Contents: createBareDeclRef(D: FD));
1475 if (const FunctionDecl *FD = NE->getOperatorDelete())
1476 JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(D: FD));
1477}
1478void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {
1479 attributeOnlyIfTrue(Key: "isGlobal", Value: DE->isGlobalDelete());
1480 attributeOnlyIfTrue(Key: "isArray", Value: DE->isArrayForm());
1481 attributeOnlyIfTrue(Key: "isArrayAsWritten", Value: DE->isArrayFormAsWritten());
1482 if (const FunctionDecl *FD = DE->getOperatorDelete())
1483 JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(D: FD));
1484}
1485
1486void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) {
1487 attributeOnlyIfTrue(Key: "implicit", Value: TE->isImplicit());
1488}
1489
1490void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) {
1491 JOS.attribute(Key: "castKind", Contents: CE->getCastKindName());
1492 llvm::json::Array Path = createCastPath(C: CE);
1493 if (!Path.empty())
1494 JOS.attribute(Key: "path", Contents: std::move(Path));
1495 // FIXME: This may not be useful information as it can be obtusely gleaned
1496 // from the inner[] array.
1497 if (const NamedDecl *ND = CE->getConversionFunction())
1498 JOS.attribute(Key: "conversionFunc", Contents: createBareDeclRef(D: ND));
1499}
1500
1501void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
1502 VisitCastExpr(CE: ICE);
1503 attributeOnlyIfTrue(Key: "isPartOfExplicitCast", Value: ICE->isPartOfExplicitCast());
1504}
1505
1506void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {
1507 attributeOnlyIfTrue(Key: "adl", Value: CE->usesADL());
1508}
1509
1510void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
1511 const UnaryExprOrTypeTraitExpr *TTE) {
1512 JOS.attribute(Key: "name", Contents: getTraitSpelling(T: TTE->getKind()));
1513 if (TTE->isArgumentType())
1514 JOS.attribute(Key: "argType", Contents: createQualType(QT: TTE->getArgumentType()));
1515}
1516
1517void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) {
1518 VisitNamedDecl(ND: SOPE->getPack());
1519}
1520
1521void JSONNodeDumper::VisitUnresolvedLookupExpr(
1522 const UnresolvedLookupExpr *ULE) {
1523 JOS.attribute(Key: "usesADL", Contents: ULE->requiresADL());
1524 JOS.attribute(Key: "name", Contents: ULE->getName().getAsString());
1525
1526 JOS.attributeArray(Key: "lookups", Contents: [this, ULE] {
1527 for (const NamedDecl *D : ULE->decls())
1528 JOS.value(V: createBareDeclRef(D));
1529 });
1530}
1531
1532void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) {
1533 JOS.attribute(Key: "name", Contents: ALE->getLabel()->getName());
1534 JOS.attribute(Key: "labelDeclId", Contents: createPointerRepresentation(Ptr: ALE->getLabel()));
1535}
1536
1537void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
1538 if (CTE->isTypeOperand()) {
1539 QualType Adjusted = CTE->getTypeOperand(Context: Ctx);
1540 QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType();
1541 JOS.attribute(Key: "typeArg", Contents: createQualType(QT: Unadjusted));
1542 if (Adjusted != Unadjusted)
1543 JOS.attribute(Key: "adjustedTypeArg", Contents: createQualType(QT: Adjusted));
1544 }
1545}
1546
1547void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
1548 if (CE->getResultAPValueKind() != APValue::None)
1549 Visit(Value: CE->getAPValueResult(), Ty: CE->getType());
1550}
1551
1552void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
1553 if (const FieldDecl *FD = ILE->getInitializedFieldInUnion())
1554 JOS.attribute(Key: "field", Contents: createBareDeclRef(D: FD));
1555}
1556
1557void JSONNodeDumper::VisitGenericSelectionExpr(
1558 const GenericSelectionExpr *GSE) {
1559 attributeOnlyIfTrue(Key: "resultDependent", Value: GSE->isResultDependent());
1560}
1561
1562void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(
1563 const CXXUnresolvedConstructExpr *UCE) {
1564 if (UCE->getType() != UCE->getTypeAsWritten())
1565 JOS.attribute(Key: "typeAsWritten", Contents: createQualType(QT: UCE->getTypeAsWritten()));
1566 attributeOnlyIfTrue(Key: "list", Value: UCE->isListInitialization());
1567}
1568
1569void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) {
1570 CXXConstructorDecl *Ctor = CE->getConstructor();
1571 JOS.attribute(Key: "ctorType", Contents: createQualType(QT: Ctor->getType()));
1572 attributeOnlyIfTrue(Key: "elidable", Value: CE->isElidable());
1573 attributeOnlyIfTrue(Key: "list", Value: CE->isListInitialization());
1574 attributeOnlyIfTrue(Key: "initializer_list", Value: CE->isStdInitListInitialization());
1575 attributeOnlyIfTrue(Key: "zeroing", Value: CE->requiresZeroInitialization());
1576 attributeOnlyIfTrue(Key: "hadMultipleCandidates", Value: CE->hadMultipleCandidates());
1577 attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: CE->isImmediateEscalating());
1578
1579 switch (CE->getConstructionKind()) {
1580 case CXXConstructionKind::Complete:
1581 JOS.attribute(Key: "constructionKind", Contents: "complete");
1582 break;
1583 case CXXConstructionKind::Delegating:
1584 JOS.attribute(Key: "constructionKind", Contents: "delegating");
1585 break;
1586 case CXXConstructionKind::NonVirtualBase:
1587 JOS.attribute(Key: "constructionKind", Contents: "non-virtual base");
1588 break;
1589 case CXXConstructionKind::VirtualBase:
1590 JOS.attribute(Key: "constructionKind", Contents: "virtual base");
1591 break;
1592 }
1593}
1594
1595void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {
1596 attributeOnlyIfTrue(Key: "cleanupsHaveSideEffects",
1597 Value: EWC->cleanupsHaveSideEffects());
1598 if (EWC->getNumObjects()) {
1599 JOS.attributeArray(Key: "cleanups", Contents: [this, EWC] {
1600 for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())
1601 if (auto *BD = dyn_cast<BlockDecl *>(Val: CO)) {
1602 JOS.value(V: createBareDeclRef(D: BD));
1603 } else if (auto *CLE = dyn_cast<CompoundLiteralExpr *>(Val: CO)) {
1604 llvm::json::Object Obj;
1605 Obj["id"] = createPointerRepresentation(Ptr: CLE);
1606 Obj["kind"] = CLE->getStmtClassName();
1607 JOS.value(V: std::move(Obj));
1608 } else {
1609 llvm_unreachable("unexpected cleanup object type");
1610 }
1611 });
1612 }
1613}
1614
1615void JSONNodeDumper::VisitCXXBindTemporaryExpr(
1616 const CXXBindTemporaryExpr *BTE) {
1617 const CXXTemporary *Temp = BTE->getTemporary();
1618 JOS.attribute(Key: "temp", Contents: createPointerRepresentation(Ptr: Temp));
1619 if (const CXXDestructorDecl *Dtor = Temp->getDestructor())
1620 JOS.attribute(Key: "dtor", Contents: createBareDeclRef(D: Dtor));
1621}
1622
1623void JSONNodeDumper::VisitMaterializeTemporaryExpr(
1624 const MaterializeTemporaryExpr *MTE) {
1625 if (const ValueDecl *VD = MTE->getExtendingDecl())
1626 JOS.attribute(Key: "extendingDecl", Contents: createBareDeclRef(D: VD));
1627
1628 switch (MTE->getStorageDuration()) {
1629 case SD_Automatic:
1630 JOS.attribute(Key: "storageDuration", Contents: "automatic");
1631 break;
1632 case SD_Dynamic:
1633 JOS.attribute(Key: "storageDuration", Contents: "dynamic");
1634 break;
1635 case SD_FullExpression:
1636 JOS.attribute(Key: "storageDuration", Contents: "full expression");
1637 break;
1638 case SD_Static:
1639 JOS.attribute(Key: "storageDuration", Contents: "static");
1640 break;
1641 case SD_Thread:
1642 JOS.attribute(Key: "storageDuration", Contents: "thread");
1643 break;
1644 }
1645
1646 attributeOnlyIfTrue(Key: "boundToLValueRef", Value: MTE->isBoundToLvalueReference());
1647}
1648
1649void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
1650 attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit());
1651}
1652
1653void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
1654 attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit());
1655}
1656
1657void JSONNodeDumper::VisitLambdaExpr(const LambdaExpr *LE) {
1658 JOS.attribute(Key: "hasExplicitParameters", Contents: LE->hasExplicitParameters());
1659}
1660
1661void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
1662 const CXXDependentScopeMemberExpr *DSME) {
1663 JOS.attribute(Key: "isArrow", Contents: DSME->isArrow());
1664 JOS.attribute(Key: "member", Contents: DSME->getMember().getAsString());
1665 attributeOnlyIfTrue(Key: "hasTemplateKeyword", Value: DSME->hasTemplateKeyword());
1666 attributeOnlyIfTrue(Key: "hasExplicitTemplateArgs",
1667 Value: DSME->hasExplicitTemplateArgs());
1668
1669 if (DSME->getNumTemplateArgs()) {
1670 JOS.attributeArray(Key: "explicitTemplateArgs", Contents: [DSME, this] {
1671 for (const TemplateArgumentLoc &TAL : DSME->template_arguments())
1672 JOS.object(
1673 Contents: [&TAL, this] { Visit(TA: TAL.getArgument(), R: TAL.getSourceRange()); });
1674 });
1675 }
1676}
1677
1678void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {
1679 if (!RE->isValueDependent())
1680 JOS.attribute(Key: "satisfied", Contents: RE->isSatisfied());
1681}
1682
1683void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {
1684 llvm::SmallString<16> Buffer;
1685 IL->getValue().toString(Str&: Buffer,
1686 /*Radix=*/10, Signed: IL->getType()->isSignedIntegerType());
1687 JOS.attribute(Key: "value", Contents: Buffer);
1688}
1689void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) {
1690 // FIXME: This should probably print the character literal as a string,
1691 // rather than as a numerical value. It would be nice if the behavior matched
1692 // what we do to print a string literal; right now, it is impossible to tell
1693 // the difference between 'a' and L'a' in C from the JSON output.
1694 JOS.attribute(Key: "value", Contents: CL->getValue());
1695}
1696void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) {
1697 JOS.attribute(Key: "value", Contents: FPL->getValueAsString(/*Radix=*/10));
1698}
1699void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) {
1700 llvm::SmallString<16> Buffer;
1701 FL->getValue().toString(Str&: Buffer);
1702 JOS.attribute(Key: "value", Contents: Buffer);
1703}
1704void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) {
1705 std::string Buffer;
1706 llvm::raw_string_ostream SS(Buffer);
1707 SL->outputString(OS&: SS);
1708 JOS.attribute(Key: "value", Contents: Buffer);
1709}
1710void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) {
1711 JOS.attribute(Key: "value", Contents: BLE->getValue());
1712}
1713
1714void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) {
1715 attributeOnlyIfTrue(Key: "hasInit", Value: IS->hasInitStorage());
1716 attributeOnlyIfTrue(Key: "hasVar", Value: IS->hasVarStorage());
1717 attributeOnlyIfTrue(Key: "hasElse", Value: IS->hasElseStorage());
1718 attributeOnlyIfTrue(Key: "isConstexpr", Value: IS->isConstexpr());
1719 attributeOnlyIfTrue(Key: "isConsteval", Value: IS->isConsteval());
1720 attributeOnlyIfTrue(Key: "constevalIsNegated", Value: IS->isNegatedConsteval());
1721}
1722
1723void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) {
1724 attributeOnlyIfTrue(Key: "hasInit", Value: SS->hasInitStorage());
1725 attributeOnlyIfTrue(Key: "hasVar", Value: SS->hasVarStorage());
1726}
1727void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
1728 attributeOnlyIfTrue(Key: "isGNURange", Value: CS->caseStmtIsGNURange());
1729}
1730
1731void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
1732 JOS.attribute(Key: "name", Contents: LS->getName());
1733 JOS.attribute(Key: "declId", Contents: createPointerRepresentation(Ptr: LS->getDecl()));
1734 attributeOnlyIfTrue(Key: "sideEntry", Value: LS->isSideEntry());
1735}
1736
1737void JSONNodeDumper::VisitLoopControlStmt(const LoopControlStmt *LS) {
1738 if (LS->hasLabelTarget())
1739 JOS.attribute(Key: "targetLabelDeclId",
1740 Contents: createPointerRepresentation(Ptr: LS->getLabelDecl()));
1741}
1742
1743void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
1744 JOS.attribute(Key: "targetLabelDeclId",
1745 Contents: createPointerRepresentation(Ptr: GS->getLabel()));
1746}
1747
1748void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) {
1749 attributeOnlyIfTrue(Key: "hasVar", Value: WS->hasVarStorage());
1750}
1751
1752void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) {
1753 // FIXME: it would be nice for the ASTNodeTraverser would handle the catch
1754 // parameter the same way for C++ and ObjC rather. In this case, C++ gets a
1755 // null child node and ObjC gets no child node.
1756 attributeOnlyIfTrue(Key: "isCatchAll", Value: OACS->getCatchParamDecl() == nullptr);
1757}
1758
1759void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) {
1760 JOS.attribute(Key: "isNull", Contents: true);
1761}
1762void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
1763 JOS.attribute(Key: "type", Contents: createQualType(QT: TA.getAsType()));
1764}
1765void JSONNodeDumper::VisitDeclarationTemplateArgument(
1766 const TemplateArgument &TA) {
1767 JOS.attribute(Key: "decl", Contents: createBareDeclRef(D: TA.getAsDecl()));
1768}
1769void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) {
1770 JOS.attribute(Key: "isNullptr", Contents: true);
1771}
1772void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
1773 JOS.attribute(Key: "value", Contents: TA.getAsIntegral().getSExtValue());
1774}
1775void JSONNodeDumper::VisitStructuralValueTemplateArgument(
1776 const TemplateArgument &TA) {
1777 Visit(Value: TA.getAsStructuralValue(), Ty: TA.getStructuralValueType());
1778}
1779void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
1780 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1781 // the output format.
1782}
1783void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
1784 const TemplateArgument &TA) {
1785 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1786 // the output format.
1787}
1788void JSONNodeDumper::VisitExpressionTemplateArgument(
1789 const TemplateArgument &TA) {
1790 JOS.attribute(Key: "isExpr", Contents: true);
1791 if (TA.isCanonicalExpr())
1792 JOS.attribute(Key: "isCanonical", Contents: true);
1793}
1794void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
1795 JOS.attribute(Key: "isPack", Contents: true);
1796}
1797
1798StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const {
1799 if (Traits)
1800 return Traits->getCommandInfo(CommandID)->Name;
1801 if (const comments::CommandInfo *Info =
1802 comments::CommandTraits::getBuiltinCommandInfo(CommandID))
1803 return Info->Name;
1804 return "<invalid>";
1805}
1806
1807void JSONNodeDumper::visitTextComment(const comments::TextComment *C,
1808 const comments::FullComment *) {
1809 JOS.attribute(Key: "text", Contents: C->getText());
1810}
1811
1812void JSONNodeDumper::visitInlineCommandComment(
1813 const comments::InlineCommandComment *C, const comments::FullComment *) {
1814 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1815
1816 switch (C->getRenderKind()) {
1817 case comments::InlineCommandRenderKind::Normal:
1818 JOS.attribute(Key: "renderKind", Contents: "normal");
1819 break;
1820 case comments::InlineCommandRenderKind::Bold:
1821 JOS.attribute(Key: "renderKind", Contents: "bold");
1822 break;
1823 case comments::InlineCommandRenderKind::Emphasized:
1824 JOS.attribute(Key: "renderKind", Contents: "emphasized");
1825 break;
1826 case comments::InlineCommandRenderKind::Monospaced:
1827 JOS.attribute(Key: "renderKind", Contents: "monospaced");
1828 break;
1829 case comments::InlineCommandRenderKind::Anchor:
1830 JOS.attribute(Key: "renderKind", Contents: "anchor");
1831 break;
1832 }
1833
1834 llvm::json::Array Args;
1835 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
1836 Args.push_back(E: C->getArgText(Idx: I));
1837
1838 if (!Args.empty())
1839 JOS.attribute(Key: "args", Contents: std::move(Args));
1840}
1841
1842void JSONNodeDumper::visitHTMLStartTagComment(
1843 const comments::HTMLStartTagComment *C, const comments::FullComment *) {
1844 JOS.attribute(Key: "name", Contents: C->getTagName());
1845 attributeOnlyIfTrue(Key: "selfClosing", Value: C->isSelfClosing());
1846 attributeOnlyIfTrue(Key: "malformed", Value: C->isMalformed());
1847
1848 llvm::json::Array Attrs;
1849 for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I)
1850 Attrs.push_back(
1851 E: {{"name", C->getAttr(Idx: I).Name}, {"value", C->getAttr(Idx: I).Value}});
1852
1853 if (!Attrs.empty())
1854 JOS.attribute(Key: "attrs", Contents: std::move(Attrs));
1855}
1856
1857void JSONNodeDumper::visitHTMLEndTagComment(
1858 const comments::HTMLEndTagComment *C, const comments::FullComment *) {
1859 JOS.attribute(Key: "name", Contents: C->getTagName());
1860}
1861
1862void JSONNodeDumper::visitBlockCommandComment(
1863 const comments::BlockCommandComment *C, const comments::FullComment *) {
1864 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1865
1866 llvm::json::Array Args;
1867 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
1868 Args.push_back(E: C->getArgText(Idx: I));
1869
1870 if (!Args.empty())
1871 JOS.attribute(Key: "args", Contents: std::move(Args));
1872}
1873
1874void JSONNodeDumper::visitParamCommandComment(
1875 const comments::ParamCommandComment *C, const comments::FullComment *FC) {
1876 switch (C->getDirection()) {
1877 case comments::ParamCommandPassDirection::In:
1878 JOS.attribute(Key: "direction", Contents: "in");
1879 break;
1880 case comments::ParamCommandPassDirection::Out:
1881 JOS.attribute(Key: "direction", Contents: "out");
1882 break;
1883 case comments::ParamCommandPassDirection::InOut:
1884 JOS.attribute(Key: "direction", Contents: "in,out");
1885 break;
1886 }
1887 attributeOnlyIfTrue(Key: "explicit", Value: C->isDirectionExplicit());
1888
1889 if (C->hasParamName())
1890 JOS.attribute(Key: "param", Contents: C->isParamIndexValid() ? C->getParamName(FC)
1891 : C->getParamNameAsWritten());
1892
1893 if (C->isParamIndexValid() && !C->isVarArgParam())
1894 JOS.attribute(Key: "paramIdx", Contents: C->getParamIndex());
1895}
1896
1897void JSONNodeDumper::visitTParamCommandComment(
1898 const comments::TParamCommandComment *C, const comments::FullComment *FC) {
1899 if (C->hasParamName())
1900 JOS.attribute(Key: "param", Contents: C->isPositionValid() ? C->getParamName(FC)
1901 : C->getParamNameAsWritten());
1902 if (C->isPositionValid()) {
1903 llvm::json::Array Positions;
1904 for (unsigned I = 0, E = C->getDepth(); I < E; ++I)
1905 Positions.push_back(E: C->getIndex(Depth: I));
1906
1907 if (!Positions.empty())
1908 JOS.attribute(Key: "positions", Contents: std::move(Positions));
1909 }
1910}
1911
1912void JSONNodeDumper::visitVerbatimBlockComment(
1913 const comments::VerbatimBlockComment *C, const comments::FullComment *) {
1914 JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID()));
1915 JOS.attribute(Key: "closeName", Contents: C->getCloseName());
1916}
1917
1918void JSONNodeDumper::visitVerbatimBlockLineComment(
1919 const comments::VerbatimBlockLineComment *C,
1920 const comments::FullComment *) {
1921 JOS.attribute(Key: "text", Contents: C->getText());
1922}
1923
1924void JSONNodeDumper::visitVerbatimLineComment(
1925 const comments::VerbatimLineComment *C, const comments::FullComment *) {
1926 JOS.attribute(Key: "text", Contents: C->getText());
1927}
1928
1929llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) {
1930 llvm::json::Object Ret;
1931#define FP_OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
1932 if (FPO.has##NAME##Override()) \
1933 Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override()));
1934#include "clang/Basic/FPOptions.def"
1935 return Ret;
1936}
1937
1938void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
1939 VisitStmt(Node: S);
1940 if (S->hasStoredFPFeatures())
1941 JOS.attribute(Key: "fpoptions", Contents: createFPOptions(FPO: S->getStoredFPFeatures()));
1942}
1943