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