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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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