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

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