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

source code of clang/lib/AST/JSONNodeDumper.cpp