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
8 using namespace clang;
9
addPreviousDeclaration(const Decl * D)10 void 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
Visit(const Attr * A)23 void 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("id", createPointerRepresentation(A));
34 JOS.attribute("kind", AttrName);
35 JOS.attributeObject("range", [A, this] { writeSourceRange(A->getRange()); });
36 attributeOnlyIfTrue("inherited", A->isInherited());
37 attributeOnlyIfTrue("implicit", 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
Visit(const Stmt * S)48 void JSONNodeDumper::Visit(const Stmt *S) {
49 if (!S)
50 return;
51
52 JOS.attribute("id", createPointerRepresentation(S));
53 JOS.attribute("kind", S->getStmtClassName());
54 JOS.attributeObject("range",
55 [S, this] { writeSourceRange(S->getSourceRange()); });
56
57 if (const auto *E = dyn_cast<Expr>(S)) {
58 JOS.attribute("type", createQualType(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("valueCategory", Category);
68 }
69 InnerStmtVisitor::Visit(S);
70 }
71
Visit(const Type * T)72 void JSONNodeDumper::Visit(const Type *T) {
73 JOS.attribute("id", createPointerRepresentation(T));
74
75 if (!T)
76 return;
77
78 JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str());
79 JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar=*/false));
80 attributeOnlyIfTrue("containsErrors", T->containsErrors());
81 attributeOnlyIfTrue("isDependent", T->isDependentType());
82 attributeOnlyIfTrue("isInstantiationDependent",
83 T->isInstantiationDependentType());
84 attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType());
85 attributeOnlyIfTrue("containsUnexpandedPack",
86 T->containsUnexpandedParameterPack());
87 attributeOnlyIfTrue("isImported", T->isFromAST());
88 InnerTypeVisitor::Visit(T);
89 }
90
Visit(QualType T)91 void JSONNodeDumper::Visit(QualType T) {
92 JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
93 JOS.attribute("kind", "QualType");
94 JOS.attribute("type", createQualType(T));
95 JOS.attribute("qualifiers", T.split().Quals.getAsString());
96 }
97
Visit(TypeLoc TL)98 void JSONNodeDumper::Visit(TypeLoc TL) {
99 if (TL.isNull())
100 return;
101 JOS.attribute("kind",
102 (llvm::Twine(TL.getTypeLocClass() == TypeLoc::Qualified
103 ? "Qualified"
104 : TL.getTypePtr()->getTypeClassName()) +
105 "TypeLoc")
106 .str());
107 JOS.attribute("type",
108 createQualType(QualType(TL.getType()), /*Desugar=*/false));
109 JOS.attributeObject("range",
110 [TL, this] { writeSourceRange(TL.getSourceRange()); });
111 }
112
Visit(const Decl * D)113 void JSONNodeDumper::Visit(const Decl *D) {
114 JOS.attribute("id", createPointerRepresentation(D));
115
116 if (!D)
117 return;
118
119 JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
120 JOS.attributeObject("loc",
121 [D, this] { writeSourceLocation(D->getLocation()); });
122 JOS.attributeObject("range",
123 [D, this] { writeSourceRange(D->getSourceRange()); });
124 attributeOnlyIfTrue("isImplicit", D->isImplicit());
125 attributeOnlyIfTrue("isInvalid", D->isInvalidDecl());
126
127 if (D->isUsed())
128 JOS.attribute("isUsed", true);
129 else if (D->isThisDeclarationReferenced())
130 JOS.attribute("isReferenced", true);
131
132 if (const auto *ND = dyn_cast<NamedDecl>(D))
133 attributeOnlyIfTrue("isHidden", !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>(D->getDeclContext());
140 JOS.attribute("parentDeclContextId",
141 createPointerRepresentation(ParentDeclContextDecl));
142 }
143
144 addPreviousDeclaration(D);
145 InnerDeclVisitor::Visit(D);
146 }
147
Visit(const comments::Comment * C,const comments::FullComment * FC)148 void JSONNodeDumper::Visit(const comments::Comment *C,
149 const comments::FullComment *FC) {
150 if (!C)
151 return;
152
153 JOS.attribute("id", createPointerRepresentation(C));
154 JOS.attribute("kind", C->getCommentKindName());
155 JOS.attributeObject("loc",
156 [C, this] { writeSourceLocation(C->getLocation()); });
157 JOS.attributeObject("range",
158 [C, this] { writeSourceRange(C->getSourceRange()); });
159
160 InnerCommentVisitor::visit(C, FC);
161 }
162
Visit(const TemplateArgument & TA,SourceRange R,const Decl * From,StringRef Label)163 void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
164 const Decl *From, StringRef Label) {
165 JOS.attribute("kind", "TemplateArgument");
166 if (R.isValid())
167 JOS.attributeObject("range", [R, this] { writeSourceRange(R); });
168
169 if (From)
170 JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From));
171
172 InnerTemplateArgVisitor::Visit(TA);
173 }
174
Visit(const CXXCtorInitializer * Init)175 void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
176 JOS.attribute("kind", "CXXCtorInitializer");
177 if (Init->isAnyMemberInitializer())
178 JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember()));
179 else if (Init->isBaseInitializer())
180 JOS.attribute("baseInit",
181 createQualType(QualType(Init->getBaseClass(), 0)));
182 else if (Init->isDelegatingInitializer())
183 JOS.attribute("delegatingInit",
184 createQualType(Init->getTypeSourceInfo()->getType()));
185 else
186 llvm_unreachable("Unknown initializer type");
187 }
188
Visit(const OpenACCClause * C)189 void JSONNodeDumper::Visit(const OpenACCClause *C) {}
190
Visit(const OMPClause * C)191 void JSONNodeDumper::Visit(const OMPClause *C) {}
192
Visit(const BlockDecl::Capture & C)193 void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {
194 JOS.attribute("kind", "Capture");
195 attributeOnlyIfTrue("byref", C.isByRef());
196 attributeOnlyIfTrue("nested", C.isNested());
197 if (C.getVariable())
198 JOS.attribute("var", createBareDeclRef(C.getVariable()));
199 }
200
Visit(const GenericSelectionExpr::ConstAssociation & A)201 void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
202 JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default");
203 attributeOnlyIfTrue("selected", A.isSelected());
204 }
205
Visit(const concepts::Requirement * R)206 void 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("kind", "TypeRequirement");
213 break;
214 case concepts::Requirement::RK_Simple:
215 JOS.attribute("kind", "SimpleRequirement");
216 break;
217 case concepts::Requirement::RK_Compound:
218 JOS.attribute("kind", "CompoundRequirement");
219 break;
220 case concepts::Requirement::RK_Nested:
221 JOS.attribute("kind", "NestedRequirement");
222 break;
223 }
224
225 if (auto *ER = dyn_cast<concepts::ExprRequirement>(R))
226 attributeOnlyIfTrue("noexcept", ER->hasNoexceptRequirement());
227
228 attributeOnlyIfTrue("isDependent", R->isDependent());
229 if (!R->isDependent())
230 JOS.attribute("satisfied", R->isSatisfied());
231 attributeOnlyIfTrue("containsUnexpandedPack",
232 R->containsUnexpandedParameterPack());
233 }
234
Visit(const APValue & Value,QualType Ty)235 void 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("value", Str);
240 }
241
Visit(const ConceptReference * CR)242 void JSONNodeDumper::Visit(const ConceptReference *CR) {
243 JOS.attribute("kind", "ConceptReference");
244 JOS.attribute("id", createPointerRepresentation(CR->getNamedConcept()));
245 if (const auto *Args = CR->getTemplateArgsAsWritten()) {
246 JOS.attributeArray("templateArgsAsWritten", [Args, this] {
247 for (const TemplateArgumentLoc &TAL : Args->arguments())
248 JOS.object(
249 [&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });
250 });
251 }
252 JOS.attributeObject("loc",
253 [CR, this] { writeSourceLocation(CR->getLocation()); });
254 JOS.attributeObject("range",
255 [CR, this] { writeSourceRange(CR->getSourceRange()); });
256 }
257
writeIncludeStack(PresumedLoc Loc,bool JustFirst)258 void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
259 if (Loc.isInvalid())
260 return;
261
262 JOS.attributeBegin("includedFrom");
263 JOS.objectBegin();
264
265 if (!JustFirst) {
266 // Walk the stack recursively, then print out the presumed location.
267 writeIncludeStack(SM.getPresumedLoc(Loc.getIncludeLoc()));
268 }
269
270 JOS.attribute("file", Loc.getFilename());
271 JOS.objectEnd();
272 JOS.attributeEnd();
273 }
274
writeBareSourceLocation(SourceLocation Loc,bool IsSpelling)275 void 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("offset", SM.getDecomposedLoc(Loc).second);
284 if (LastLocFilename != ActualFile) {
285 JOS.attribute("file", ActualFile);
286 JOS.attribute("line", ActualLine);
287 } else if (LastLocLine != ActualLine)
288 JOS.attribute("line", ActualLine);
289
290 StringRef PresumedFile = Presumed.getFilename();
291 if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile)
292 JOS.attribute("presumedFile", PresumedFile);
293
294 unsigned PresumedLine = Presumed.getLine();
295 if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine)
296 JOS.attribute("presumedLine", PresumedLine);
297
298 JOS.attribute("col", Presumed.getColumn());
299 JOS.attribute("tokLen",
300 Lexer::MeasureTokenLength(Loc, SM, 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(SM.getPresumedLoc(Presumed.getIncludeLoc()),
310 /*JustFirst*/ true);
311 }
312 }
313
writeSourceLocation(SourceLocation Loc)314 void 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("spellingLoc", [Spelling, this] {
322 writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
323 });
324 JOS.attributeObject("expansionLoc", [Expansion, Loc, this] {
325 writeBareSourceLocation(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("isMacroArgExpansion", true);
330 });
331 } else
332 writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
333 }
334
writeSourceRange(SourceRange R)335 void JSONNodeDumper::writeSourceRange(SourceRange R) {
336 JOS.attributeObject("begin",
337 [R, this] { writeSourceLocation(R.getBegin()); });
338 JOS.attributeObject("end", [R, this] { writeSourceLocation(R.getEnd()); });
339 }
340
createPointerRepresentation(const void * Ptr)341 std::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(reinterpret_cast<uint64_t>(Ptr), true);
346 }
347
createQualType(QualType QT,bool Desugar)348 llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) {
349 SplitQualType SQT = QT.split();
350 std::string SQTS = QualType::getAsString(SQT, PrintPolicy);
351 llvm::json::Object Ret{{"qualType", SQTS}};
352
353 if (Desugar && !QT.isNull()) {
354 SplitQualType DSQT = QT.getSplitDesugaredType();
355 if (DSQT != SQT) {
356 std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);
357 if (DSQTS != SQTS)
358 Ret["desugaredQualType"] = DSQTS;
359 }
360 if (const auto *TT = QT->getAs<TypedefType>())
361 Ret["typeAliasDeclId"] = createPointerRepresentation(TT->getDecl());
362 }
363 return Ret;
364 }
365
writeBareDeclRef(const Decl * D)366 void JSONNodeDumper::writeBareDeclRef(const Decl *D) {
367 JOS.attribute("id", createPointerRepresentation(D));
368 if (!D)
369 return;
370
371 JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
372 if (const auto *ND = dyn_cast<NamedDecl>(D))
373 JOS.attribute("name", ND->getDeclName().getAsString());
374 if (const auto *VD = dyn_cast<ValueDecl>(D))
375 JOS.attribute("type", createQualType(VD->getType()));
376 }
377
createBareDeclRef(const Decl * D)378 llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) {
379 llvm::json::Object Ret{{"id", createPointerRepresentation(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>(D))
385 Ret["name"] = ND->getDeclName().getAsString();
386 if (const auto *VD = dyn_cast<ValueDecl>(D))
387 Ret["type"] = createQualType(VD->getType());
388 return Ret;
389 }
390
createCastPath(const CastExpr * C)391 llvm::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>(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(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
412 static llvm::json::Object
createDefaultConstructorDefinitionData(const CXXRecordDecl * RD)413 createDefaultConstructorDefinitionData(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
427 static llvm::json::Object
createCopyConstructorDefinitionData(const CXXRecordDecl * RD)428 createCopyConstructorDefinitionData(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
445 static llvm::json::Object
createMoveConstructorDefinitionData(const CXXRecordDecl * RD)446 createMoveConstructorDefinitionData(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
462 static llvm::json::Object
createCopyAssignmentDefinitionData(const CXXRecordDecl * RD)463 createCopyAssignmentDefinitionData(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
478 static llvm::json::Object
createMoveAssignmentDefinitionData(const CXXRecordDecl * RD)479 createMoveAssignmentDefinitionData(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
493 static llvm::json::Object
createDestructorDefinitionData(const CXXRecordDecl * RD)494 createDestructorDefinitionData(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
510 llvm::json::Object
createCXXRecordDefinitionData(const CXXRecordDecl * RD)511 JSONNodeDumper::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
createAccessSpecifier(AccessSpecifier AS)546 std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) {
547 const auto AccessSpelling = getAccessSpelling(AS);
548 if (AccessSpelling.empty())
549 return "none";
550 return AccessSpelling.str();
551 }
552
553 llvm::json::Object
createCXXBaseSpecifier(const CXXBaseSpecifier & BS)554 JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) {
555 llvm::json::Object Ret;
556
557 Ret["type"] = createQualType(BS.getType());
558 Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier());
559 Ret["writtenAccess"] =
560 createAccessSpecifier(BS.getAccessSpecifierAsWritten());
561 if (BS.isVirtual())
562 Ret["isVirtual"] = true;
563 if (BS.isPackExpansion())
564 Ret["isPackExpansion"] = true;
565
566 return Ret;
567 }
568
VisitAliasAttr(const AliasAttr * AA)569 void JSONNodeDumper::VisitAliasAttr(const AliasAttr *AA) {
570 JOS.attribute("aliasee", AA->getAliasee());
571 }
572
VisitCleanupAttr(const CleanupAttr * CA)573 void JSONNodeDumper::VisitCleanupAttr(const CleanupAttr *CA) {
574 JOS.attribute("cleanup_function", createBareDeclRef(CA->getFunctionDecl()));
575 }
576
VisitDeprecatedAttr(const DeprecatedAttr * DA)577 void JSONNodeDumper::VisitDeprecatedAttr(const DeprecatedAttr *DA) {
578 if (!DA->getMessage().empty())
579 JOS.attribute("message", DA->getMessage());
580 if (!DA->getReplacement().empty())
581 JOS.attribute("replacement", DA->getReplacement());
582 }
583
VisitUnavailableAttr(const UnavailableAttr * UA)584 void JSONNodeDumper::VisitUnavailableAttr(const UnavailableAttr *UA) {
585 if (!UA->getMessage().empty())
586 JOS.attribute("message", UA->getMessage());
587 }
588
VisitSectionAttr(const SectionAttr * SA)589 void JSONNodeDumper::VisitSectionAttr(const SectionAttr *SA) {
590 JOS.attribute("section_name", SA->getName());
591 }
592
VisitVisibilityAttr(const VisibilityAttr * VA)593 void JSONNodeDumper::VisitVisibilityAttr(const VisibilityAttr *VA) {
594 JOS.attribute("visibility", VisibilityAttr::ConvertVisibilityTypeToStr(
595 VA->getVisibility()));
596 }
597
VisitTLSModelAttr(const TLSModelAttr * TA)598 void JSONNodeDumper::VisitTLSModelAttr(const TLSModelAttr *TA) {
599 JOS.attribute("tls_model", TA->getModel());
600 }
601
VisitTypedefType(const TypedefType * TT)602 void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {
603 JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
604 if (!TT->typeMatchesDecl())
605 JOS.attribute("type", createQualType(TT->desugar()));
606 }
607
VisitUsingType(const UsingType * TT)608 void JSONNodeDumper::VisitUsingType(const UsingType *TT) {
609 JOS.attribute("decl", createBareDeclRef(TT->getFoundDecl()));
610 if (!TT->typeMatchesDecl())
611 JOS.attribute("type", createQualType(TT->desugar()));
612 }
613
VisitFunctionType(const FunctionType * T)614 void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {
615 FunctionType::ExtInfo E = T->getExtInfo();
616 attributeOnlyIfTrue("noreturn", E.getNoReturn());
617 attributeOnlyIfTrue("producesResult", E.getProducesResult());
618 if (E.getHasRegParm())
619 JOS.attribute("regParm", E.getRegParm());
620 JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC()));
621 }
622
VisitFunctionProtoType(const FunctionProtoType * T)623 void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
624 FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo();
625 attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn);
626 attributeOnlyIfTrue("const", T->isConst());
627 attributeOnlyIfTrue("volatile", T->isVolatile());
628 attributeOnlyIfTrue("restrict", T->isRestrict());
629 attributeOnlyIfTrue("variadic", E.Variadic);
630 switch (E.RefQualifier) {
631 case RQ_LValue: JOS.attribute("refQualifier", "&"); break;
632 case RQ_RValue: JOS.attribute("refQualifier", "&&"); break;
633 case RQ_None: break;
634 }
635 switch (E.ExceptionSpec.Type) {
636 case EST_DynamicNone:
637 case EST_Dynamic: {
638 JOS.attribute("exceptionSpec", "throw");
639 llvm::json::Array Types;
640 for (QualType QT : E.ExceptionSpec.Exceptions)
641 Types.push_back(createQualType(QT));
642 JOS.attribute("exceptionTypes", std::move(Types));
643 } break;
644 case EST_MSAny:
645 JOS.attribute("exceptionSpec", "throw");
646 JOS.attribute("throwsAny", true);
647 break;
648 case EST_BasicNoexcept:
649 JOS.attribute("exceptionSpec", "noexcept");
650 break;
651 case EST_NoexceptTrue:
652 case EST_NoexceptFalse:
653 JOS.attribute("exceptionSpec", "noexcept");
654 JOS.attribute("conditionEvaluatesTo",
655 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("exceptionSpec", "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
VisitRValueReferenceType(const ReferenceType * RT)675 void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType *RT) {
676 attributeOnlyIfTrue("spelledAsLValue", RT->isSpelledAsLValue());
677 }
678
VisitArrayType(const ArrayType * AT)679 void JSONNodeDumper::VisitArrayType(const ArrayType *AT) {
680 switch (AT->getSizeModifier()) {
681 case ArraySizeModifier::Star:
682 JOS.attribute("sizeModifier", "*");
683 break;
684 case ArraySizeModifier::Static:
685 JOS.attribute("sizeModifier", "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("indexTypeQualifiers", Str);
694 }
695
VisitConstantArrayType(const ConstantArrayType * CAT)696 void 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("size", CAT->getSExtSize());
700 VisitArrayType(CAT);
701 }
702
VisitDependentSizedExtVectorType(const DependentSizedExtVectorType * VT)703 void JSONNodeDumper::VisitDependentSizedExtVectorType(
704 const DependentSizedExtVectorType *VT) {
705 JOS.attributeObject(
706 "attrLoc", [VT, this] { writeSourceLocation(VT->getAttributeLoc()); });
707 }
708
VisitVectorType(const VectorType * VT)709 void JSONNodeDumper::VisitVectorType(const VectorType *VT) {
710 JOS.attribute("numElements", VT->getNumElements());
711 switch (VT->getVectorKind()) {
712 case VectorKind::Generic:
713 break;
714 case VectorKind::AltiVecVector:
715 JOS.attribute("vectorKind", "altivec");
716 break;
717 case VectorKind::AltiVecPixel:
718 JOS.attribute("vectorKind", "altivec pixel");
719 break;
720 case VectorKind::AltiVecBool:
721 JOS.attribute("vectorKind", "altivec bool");
722 break;
723 case VectorKind::Neon:
724 JOS.attribute("vectorKind", "neon");
725 break;
726 case VectorKind::NeonPoly:
727 JOS.attribute("vectorKind", "neon poly");
728 break;
729 case VectorKind::SveFixedLengthData:
730 JOS.attribute("vectorKind", "fixed-length sve data vector");
731 break;
732 case VectorKind::SveFixedLengthPredicate:
733 JOS.attribute("vectorKind", "fixed-length sve predicate vector");
734 break;
735 case VectorKind::RVVFixedLengthData:
736 JOS.attribute("vectorKind", "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("vectorKind", "fixed-length rvv mask vector");
743 break;
744 }
745 }
746
VisitUnresolvedUsingType(const UnresolvedUsingType * UUT)747 void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {
748 JOS.attribute("decl", createBareDeclRef(UUT->getDecl()));
749 }
750
VisitUnaryTransformType(const UnaryTransformType * UTT)751 void 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
VisitTagType(const TagType * TT)761 void JSONNodeDumper::VisitTagType(const TagType *TT) {
762 JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
763 }
764
VisitTemplateTypeParmType(const TemplateTypeParmType * TTPT)765 void JSONNodeDumper::VisitTemplateTypeParmType(
766 const TemplateTypeParmType *TTPT) {
767 JOS.attribute("depth", TTPT->getDepth());
768 JOS.attribute("index", TTPT->getIndex());
769 attributeOnlyIfTrue("isPack", TTPT->isParameterPack());
770 JOS.attribute("decl", createBareDeclRef(TTPT->getDecl()));
771 }
772
VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType * STTPT)773 void JSONNodeDumper::VisitSubstTemplateTypeParmType(
774 const SubstTemplateTypeParmType *STTPT) {
775 JOS.attribute("index", STTPT->getIndex());
776 if (auto PackIndex = STTPT->getPackIndex())
777 JOS.attribute("pack_index", *PackIndex);
778 }
779
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType * T)780 void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
781 const SubstTemplateTypeParmPackType *T) {
782 JOS.attribute("index", T->getIndex());
783 }
784
VisitAutoType(const AutoType * AT)785 void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
786 JOS.attribute("undeduced", !AT->isDeduced());
787 switch (AT->getKeyword()) {
788 case AutoTypeKeyword::Auto:
789 JOS.attribute("typeKeyword", "auto");
790 break;
791 case AutoTypeKeyword::DecltypeAuto:
792 JOS.attribute("typeKeyword", "decltype(auto)");
793 break;
794 case AutoTypeKeyword::GNUAutoType:
795 JOS.attribute("typeKeyword", "__auto_type");
796 break;
797 }
798 }
799
VisitTemplateSpecializationType(const TemplateSpecializationType * TST)800 void JSONNodeDumper::VisitTemplateSpecializationType(
801 const TemplateSpecializationType *TST) {
802 attributeOnlyIfTrue("isAlias", TST->isTypeAlias());
803
804 std::string Str;
805 llvm::raw_string_ostream OS(Str);
806 TST->getTemplateName().print(OS, PrintPolicy);
807 JOS.attribute("templateName", Str);
808 }
809
VisitInjectedClassNameType(const InjectedClassNameType * ICNT)810 void JSONNodeDumper::VisitInjectedClassNameType(
811 const InjectedClassNameType *ICNT) {
812 JOS.attribute("decl", createBareDeclRef(ICNT->getDecl()));
813 }
814
VisitObjCInterfaceType(const ObjCInterfaceType * OIT)815 void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {
816 JOS.attribute("decl", createBareDeclRef(OIT->getDecl()));
817 }
818
VisitPackExpansionType(const PackExpansionType * PET)819 void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) {
820 if (UnsignedOrNone N = PET->getNumExpansions())
821 JOS.attribute("numExpansions", *N);
822 }
823
VisitElaboratedType(const ElaboratedType * ET)824 void 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, PrintPolicy, /*ResolveTemplateArgs*/ true);
829 JOS.attribute("qualifier", Str);
830 }
831 if (const TagDecl *TD = ET->getOwnedTagDecl())
832 JOS.attribute("ownedTagDecl", createBareDeclRef(TD));
833 }
834
VisitMacroQualifiedType(const MacroQualifiedType * MQT)835 void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) {
836 JOS.attribute("macroName", MQT->getMacroIdentifier()->getName());
837 }
838
VisitMemberPointerType(const MemberPointerType * MPT)839 void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) {
840 attributeOnlyIfTrue("isData", MPT->isMemberDataPointer());
841 attributeOnlyIfTrue("isFunction", MPT->isMemberFunctionPointer());
842 }
843
VisitNamedDecl(const NamedDecl * ND)844 void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {
845 if (ND && ND->getDeclName()) {
846 JOS.attribute("name", 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>(ND);
861 if (VD && VD->hasLocalStorage())
862 return;
863
864 // Do not mangle template deduction guides.
865 if (isa<CXXDeductionGuideDecl>(ND))
866 return;
867
868 std::string MangledName = ASTNameGen.getName(ND);
869 if (!MangledName.empty())
870 JOS.attribute("mangledName", MangledName);
871 }
872 }
873
VisitTypedefDecl(const TypedefDecl * TD)874 void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) {
875 VisitNamedDecl(TD);
876 JOS.attribute("type", createQualType(TD->getUnderlyingType()));
877 }
878
VisitTypeAliasDecl(const TypeAliasDecl * TAD)879 void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) {
880 VisitNamedDecl(TAD);
881 JOS.attribute("type", createQualType(TAD->getUnderlyingType()));
882 }
883
VisitNamespaceDecl(const NamespaceDecl * ND)884 void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {
885 VisitNamedDecl(ND);
886 attributeOnlyIfTrue("isInline", ND->isInline());
887 attributeOnlyIfTrue("isNested", ND->isNested());
888 if (!ND->isFirstDecl())
889 JOS.attribute("originalNamespace", createBareDeclRef(ND->getFirstDecl()));
890 }
891
VisitUsingDirectiveDecl(const UsingDirectiveDecl * UDD)892 void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {
893 JOS.attribute("nominatedNamespace",
894 createBareDeclRef(UDD->getNominatedNamespace()));
895 }
896
VisitNamespaceAliasDecl(const NamespaceAliasDecl * NAD)897 void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {
898 VisitNamedDecl(NAD);
899 JOS.attribute("aliasedNamespace",
900 createBareDeclRef(NAD->getAliasedNamespace()));
901 }
902
VisitUsingDecl(const UsingDecl * UD)903 void 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(SOS, UD->getASTContext().getPrintingPolicy());
908 }
909 Name += UD->getNameAsString();
910 JOS.attribute("name", Name);
911 }
912
VisitUsingEnumDecl(const UsingEnumDecl * UED)913 void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) {
914 JOS.attribute("target", createBareDeclRef(UED->getEnumDecl()));
915 }
916
VisitUsingShadowDecl(const UsingShadowDecl * USD)917 void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) {
918 JOS.attribute("target", createBareDeclRef(USD->getTargetDecl()));
919 }
920
VisitVarDecl(const VarDecl * VD)921 void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) {
922 VisitNamedDecl(VD);
923 JOS.attribute("type", createQualType(VD->getType()));
924 if (const auto *P = dyn_cast<ParmVarDecl>(VD))
925 attributeOnlyIfTrue("explicitObjectParameter",
926 P->isExplicitObjectParameter());
927
928 StorageClass SC = VD->getStorageClass();
929 if (SC != SC_None)
930 JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));
931 switch (VD->getTLSKind()) {
932 case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break;
933 case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break;
934 case VarDecl::TLS_None: break;
935 }
936 attributeOnlyIfTrue("nrvo", VD->isNRVOVariable());
937 attributeOnlyIfTrue("inline", VD->isInline());
938 attributeOnlyIfTrue("constexpr", VD->isConstexpr());
939 attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate());
940 if (VD->hasInit()) {
941 switch (VD->getInitStyle()) {
942 case VarDecl::CInit: JOS.attribute("init", "c"); break;
943 case VarDecl::CallInit: JOS.attribute("init", "call"); break;
944 case VarDecl::ListInit: JOS.attribute("init", "list"); break;
945 case VarDecl::ParenListInit:
946 JOS.attribute("init", "paren-list");
947 break;
948 }
949 }
950 attributeOnlyIfTrue("isParameterPack", VD->isParameterPack());
951 }
952
VisitFieldDecl(const FieldDecl * FD)953 void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {
954 VisitNamedDecl(FD);
955 JOS.attribute("type", createQualType(FD->getType()));
956 attributeOnlyIfTrue("mutable", FD->isMutable());
957 attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate());
958 attributeOnlyIfTrue("isBitfield", FD->isBitField());
959 attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer());
960 }
961
VisitFunctionDecl(const FunctionDecl * FD)962 void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
963 VisitNamedDecl(FD);
964 JOS.attribute("type", createQualType(FD->getType()));
965 StorageClass SC = FD->getStorageClass();
966 if (SC != SC_None)
967 JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));
968 attributeOnlyIfTrue("inline", FD->isInlineSpecified());
969 attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten());
970 attributeOnlyIfTrue("pure", FD->isPureVirtual());
971 attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten());
972 attributeOnlyIfTrue("constexpr", FD->isConstexpr());
973 attributeOnlyIfTrue("variadic", FD->isVariadic());
974 attributeOnlyIfTrue("immediate", FD->isImmediateFunction());
975
976 if (FD->isDefaulted())
977 JOS.attribute("explicitlyDefaulted",
978 FD->isDeleted() ? "deleted" : "default");
979
980 if (StringLiteral *Msg = FD->getDeletedMessage())
981 JOS.attribute("deletedMessage", Msg->getString());
982 }
983
VisitEnumDecl(const EnumDecl * ED)984 void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) {
985 VisitNamedDecl(ED);
986 if (ED->isFixed())
987 JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType()));
988 if (ED->isScoped())
989 JOS.attribute("scopedEnumTag",
990 ED->isScopedUsingClassTag() ? "class" : "struct");
991 }
VisitEnumConstantDecl(const EnumConstantDecl * ECD)992 void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) {
993 VisitNamedDecl(ECD);
994 JOS.attribute("type", createQualType(ECD->getType()));
995 }
996
VisitRecordDecl(const RecordDecl * RD)997 void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
998 VisitNamedDecl(RD);
999 JOS.attribute("tagUsed", RD->getKindName());
1000 attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition());
1001 }
VisitCXXRecordDecl(const CXXRecordDecl * RD)1002 void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
1003 VisitRecordDecl(RD);
1004
1005 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
1006 if (CTSD->hasStrictPackMatch())
1007 JOS.attribute("strict-pack-match", true);
1008 }
1009
1010 // All other information requires a complete definition.
1011 if (!RD->isCompleteDefinition())
1012 return;
1013
1014 JOS.attribute("definitionData", createCXXRecordDefinitionData(RD));
1015 if (RD->getNumBases()) {
1016 JOS.attributeArray("bases", [this, RD] {
1017 for (const auto &Spec : RD->bases())
1018 JOS.value(createCXXBaseSpecifier(Spec));
1019 });
1020 }
1021 }
1022
VisitHLSLBufferDecl(const HLSLBufferDecl * D)1023 void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
1024 VisitNamedDecl(D);
1025 JOS.attribute("bufferKind", D->isCBuffer() ? "cbuffer" : "tbuffer");
1026 }
1027
VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)1028 void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
1029 VisitNamedDecl(D);
1030 JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class");
1031 JOS.attribute("depth", D->getDepth());
1032 JOS.attribute("index", D->getIndex());
1033 attributeOnlyIfTrue("isParameterPack", D->isParameterPack());
1034
1035 if (D->hasDefaultArgument())
1036 JOS.attributeObject("defaultArg", [=] {
1037 Visit(D->getDefaultArgument().getArgument(), SourceRange(),
1038 D->getDefaultArgStorage().getInheritedFrom(),
1039 D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1040 });
1041 }
1042
VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)1043 void JSONNodeDumper::VisitNonTypeTemplateParmDecl(
1044 const NonTypeTemplateParmDecl *D) {
1045 VisitNamedDecl(D);
1046 JOS.attribute("type", createQualType(D->getType()));
1047 JOS.attribute("depth", D->getDepth());
1048 JOS.attribute("index", D->getIndex());
1049 attributeOnlyIfTrue("isParameterPack", D->isParameterPack());
1050
1051 if (D->hasDefaultArgument())
1052 JOS.attributeObject("defaultArg", [=] {
1053 Visit(D->getDefaultArgument().getArgument(), SourceRange(),
1054 D->getDefaultArgStorage().getInheritedFrom(),
1055 D->defaultArgumentWasInherited() ? "inherited from" : "previous");
1056 });
1057 }
1058
VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)1059 void JSONNodeDumper::VisitTemplateTemplateParmDecl(
1060 const TemplateTemplateParmDecl *D) {
1061 VisitNamedDecl(D);
1062 JOS.attribute("depth", D->getDepth());
1063 JOS.attribute("index", D->getIndex());
1064 attributeOnlyIfTrue("isParameterPack", D->isParameterPack());
1065
1066 if (D->hasDefaultArgument())
1067 JOS.attributeObject("defaultArg", [=] {
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
VisitLinkageSpecDecl(const LinkageSpecDecl * LSD)1076 void 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("language", Lang);
1087 attributeOnlyIfTrue("hasBraces", LSD->hasBraces());
1088 }
1089
VisitAccessSpecDecl(const AccessSpecDecl * ASD)1090 void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) {
1091 JOS.attribute("access", createAccessSpecifier(ASD->getAccess()));
1092 }
1093
VisitFriendDecl(const FriendDecl * FD)1094 void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) {
1095 if (const TypeSourceInfo *T = FD->getFriendType())
1096 JOS.attribute("type", createQualType(T->getType()));
1097 attributeOnlyIfTrue("isPackExpansion", FD->isPackExpansion());
1098 }
1099
VisitObjCIvarDecl(const ObjCIvarDecl * D)1100 void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
1101 VisitNamedDecl(D);
1102 JOS.attribute("type", createQualType(D->getType()));
1103 attributeOnlyIfTrue("synthesized", D->getSynthesize());
1104 switch (D->getAccessControl()) {
1105 case ObjCIvarDecl::None: JOS.attribute("access", "none"); break;
1106 case ObjCIvarDecl::Private: JOS.attribute("access", "private"); break;
1107 case ObjCIvarDecl::Protected: JOS.attribute("access", "protected"); break;
1108 case ObjCIvarDecl::Public: JOS.attribute("access", "public"); break;
1109 case ObjCIvarDecl::Package: JOS.attribute("access", "package"); break;
1110 }
1111 }
1112
VisitObjCMethodDecl(const ObjCMethodDecl * D)1113 void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
1114 VisitNamedDecl(D);
1115 JOS.attribute("returnType", createQualType(D->getReturnType()));
1116 JOS.attribute("instance", D->isInstanceMethod());
1117 attributeOnlyIfTrue("variadic", D->isVariadic());
1118 }
1119
VisitObjCTypeParamDecl(const ObjCTypeParamDecl * D)1120 void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
1121 VisitNamedDecl(D);
1122 JOS.attribute("type", createQualType(D->getUnderlyingType()));
1123 attributeOnlyIfTrue("bounded", D->hasExplicitBound());
1124 switch (D->getVariance()) {
1125 case ObjCTypeParamVariance::Invariant:
1126 break;
1127 case ObjCTypeParamVariance::Covariant:
1128 JOS.attribute("variance", "covariant");
1129 break;
1130 case ObjCTypeParamVariance::Contravariant:
1131 JOS.attribute("variance", "contravariant");
1132 break;
1133 }
1134 }
1135
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)1136 void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
1137 VisitNamedDecl(D);
1138 JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
1139 JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));
1140
1141 llvm::json::Array Protocols;
1142 for (const auto* P : D->protocols())
1143 Protocols.push_back(createBareDeclRef(P));
1144 if (!Protocols.empty())
1145 JOS.attribute("protocols", std::move(Protocols));
1146 }
1147
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)1148 void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
1149 VisitNamedDecl(D);
1150 JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
1151 JOS.attribute("categoryDecl", createBareDeclRef(D->getCategoryDecl()));
1152 }
1153
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)1154 void 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(createBareDeclRef(P));
1160 if (!Protocols.empty())
1161 JOS.attribute("protocols", std::move(Protocols));
1162 }
1163
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)1164 void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
1165 VisitNamedDecl(D);
1166 JOS.attribute("super", createBareDeclRef(D->getSuperClass()));
1167 JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));
1168
1169 llvm::json::Array Protocols;
1170 for (const auto* P : D->protocols())
1171 Protocols.push_back(createBareDeclRef(P));
1172 if (!Protocols.empty())
1173 JOS.attribute("protocols", std::move(Protocols));
1174 }
1175
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)1176 void JSONNodeDumper::VisitObjCImplementationDecl(
1177 const ObjCImplementationDecl *D) {
1178 VisitNamedDecl(D);
1179 JOS.attribute("super", createBareDeclRef(D->getSuperClass()));
1180 JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
1181 }
1182
VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl * D)1183 void JSONNodeDumper::VisitObjCCompatibleAliasDecl(
1184 const ObjCCompatibleAliasDecl *D) {
1185 VisitNamedDecl(D);
1186 JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
1187 }
1188
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)1189 void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1190 VisitNamedDecl(D);
1191 JOS.attribute("type", createQualType(D->getType()));
1192
1193 switch (D->getPropertyImplementation()) {
1194 case ObjCPropertyDecl::None: break;
1195 case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break;
1196 case ObjCPropertyDecl::Optional: JOS.attribute("control", "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("getter", createBareDeclRef(D->getGetterMethodDecl()));
1203 if (Attrs & ObjCPropertyAttribute::kind_setter)
1204 JOS.attribute("setter", createBareDeclRef(D->getSetterMethodDecl()));
1205 attributeOnlyIfTrue("readonly",
1206 Attrs & ObjCPropertyAttribute::kind_readonly);
1207 attributeOnlyIfTrue("assign", Attrs & ObjCPropertyAttribute::kind_assign);
1208 attributeOnlyIfTrue("readwrite",
1209 Attrs & ObjCPropertyAttribute::kind_readwrite);
1210 attributeOnlyIfTrue("retain", Attrs & ObjCPropertyAttribute::kind_retain);
1211 attributeOnlyIfTrue("copy", Attrs & ObjCPropertyAttribute::kind_copy);
1212 attributeOnlyIfTrue("nonatomic",
1213 Attrs & ObjCPropertyAttribute::kind_nonatomic);
1214 attributeOnlyIfTrue("atomic", Attrs & ObjCPropertyAttribute::kind_atomic);
1215 attributeOnlyIfTrue("weak", Attrs & ObjCPropertyAttribute::kind_weak);
1216 attributeOnlyIfTrue("strong", Attrs & ObjCPropertyAttribute::kind_strong);
1217 attributeOnlyIfTrue("unsafe_unretained",
1218 Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);
1219 attributeOnlyIfTrue("class", Attrs & ObjCPropertyAttribute::kind_class);
1220 attributeOnlyIfTrue("direct", Attrs & ObjCPropertyAttribute::kind_direct);
1221 attributeOnlyIfTrue("nullability",
1222 Attrs & ObjCPropertyAttribute::kind_nullability);
1223 attributeOnlyIfTrue("null_resettable",
1224 Attrs & ObjCPropertyAttribute::kind_null_resettable);
1225 }
1226 }
1227
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)1228 void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1229 VisitNamedDecl(D->getPropertyDecl());
1230 JOS.attribute("implKind", D->getPropertyImplementation() ==
1231 ObjCPropertyImplDecl::Synthesize
1232 ? "synthesize"
1233 : "dynamic");
1234 JOS.attribute("propertyDecl", createBareDeclRef(D->getPropertyDecl()));
1235 JOS.attribute("ivarDecl", createBareDeclRef(D->getPropertyIvarDecl()));
1236 }
1237
VisitBlockDecl(const BlockDecl * D)1238 void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) {
1239 attributeOnlyIfTrue("variadic", D->isVariadic());
1240 attributeOnlyIfTrue("capturesThis", D->capturesCXXThis());
1241 }
1242
VisitAtomicExpr(const AtomicExpr * AE)1243 void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
1244 JOS.attribute("name", AE->getOpAsString());
1245 }
1246
VisitObjCEncodeExpr(const ObjCEncodeExpr * OEE)1247 void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) {
1248 JOS.attribute("encodedType", createQualType(OEE->getEncodedType()));
1249 }
1250
VisitObjCMessageExpr(const ObjCMessageExpr * OME)1251 void 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("selector", Str);
1257
1258 switch (OME->getReceiverKind()) {
1259 case ObjCMessageExpr::Instance:
1260 JOS.attribute("receiverKind", "instance");
1261 break;
1262 case ObjCMessageExpr::Class:
1263 JOS.attribute("receiverKind", "class");
1264 JOS.attribute("classType", createQualType(OME->getClassReceiver()));
1265 break;
1266 case ObjCMessageExpr::SuperInstance:
1267 JOS.attribute("receiverKind", "super (instance)");
1268 JOS.attribute("superType", createQualType(OME->getSuperType()));
1269 break;
1270 case ObjCMessageExpr::SuperClass:
1271 JOS.attribute("receiverKind", "super (class)");
1272 JOS.attribute("superType", createQualType(OME->getSuperType()));
1273 break;
1274 }
1275
1276 QualType CallReturnTy = OME->getCallReturnType(Ctx);
1277 if (OME->getType() != CallReturnTy)
1278 JOS.attribute("callReturnType", createQualType(CallReturnTy));
1279 }
1280
VisitObjCBoxedExpr(const ObjCBoxedExpr * OBE)1281 void 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("selector", Str);
1288 }
1289 }
1290
VisitObjCSelectorExpr(const ObjCSelectorExpr * OSE)1291 void 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("selector", Str);
1297 }
1298
VisitObjCProtocolExpr(const ObjCProtocolExpr * OPE)1299 void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {
1300 JOS.attribute("protocol", createBareDeclRef(OPE->getProtocol()));
1301 }
1302
VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr * OPRE)1303 void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {
1304 if (OPRE->isImplicitProperty()) {
1305 JOS.attribute("propertyKind", "implicit");
1306 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter())
1307 JOS.attribute("getter", createBareDeclRef(MD));
1308 if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter())
1309 JOS.attribute("setter", createBareDeclRef(MD));
1310 } else {
1311 JOS.attribute("propertyKind", "explicit");
1312 JOS.attribute("property", createBareDeclRef(OPRE->getExplicitProperty()));
1313 }
1314
1315 attributeOnlyIfTrue("isSuperReceiver", OPRE->isSuperReceiver());
1316 attributeOnlyIfTrue("isMessagingGetter", OPRE->isMessagingGetter());
1317 attributeOnlyIfTrue("isMessagingSetter", OPRE->isMessagingSetter());
1318 }
1319
VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr * OSRE)1320 void JSONNodeDumper::VisitObjCSubscriptRefExpr(
1321 const ObjCSubscriptRefExpr *OSRE) {
1322 JOS.attribute("subscriptKind",
1323 OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary");
1324
1325 if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl())
1326 JOS.attribute("getter", createBareDeclRef(MD));
1327 if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl())
1328 JOS.attribute("setter", createBareDeclRef(MD));
1329 }
1330
VisitObjCIvarRefExpr(const ObjCIvarRefExpr * OIRE)1331 void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {
1332 JOS.attribute("decl", createBareDeclRef(OIRE->getDecl()));
1333 attributeOnlyIfTrue("isFreeIvar", OIRE->isFreeIvar());
1334 JOS.attribute("isArrow", OIRE->isArrow());
1335 }
1336
VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr * OBLE)1337 void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) {
1338 JOS.attribute("value", OBLE->getValue() ? "__objc_yes" : "__objc_no");
1339 }
1340
VisitDeclRefExpr(const DeclRefExpr * DRE)1341 void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
1342 JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl()));
1343 if (DRE->getDecl() != DRE->getFoundDecl())
1344 JOS.attribute("foundReferencedDecl",
1345 createBareDeclRef(DRE->getFoundDecl()));
1346 switch (DRE->isNonOdrUse()) {
1347 case NOUR_None: break;
1348 case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;
1349 case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;
1350 case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
1351 }
1352 attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating());
1353 }
1354
VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr * E)1355 void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
1356 const SYCLUniqueStableNameExpr *E) {
1357 JOS.attribute("typeSourceInfo",
1358 createQualType(E->getTypeSourceInfo()->getType()));
1359 }
1360
VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr * E)1361 void JSONNodeDumper::VisitOpenACCAsteriskSizeExpr(
1362 const OpenACCAsteriskSizeExpr *E) {}
1363
VisitOpenACCDeclareDecl(const OpenACCDeclareDecl * D)1364 void JSONNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) {}
VisitOpenACCRoutineDecl(const OpenACCRoutineDecl * D)1365 void JSONNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) {}
1366
VisitPredefinedExpr(const PredefinedExpr * PE)1367 void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
1368 JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));
1369 }
1370
VisitUnaryOperator(const UnaryOperator * UO)1371 void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {
1372 JOS.attribute("isPostfix", UO->isPostfix());
1373 JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode()));
1374 if (!UO->canOverflow())
1375 JOS.attribute("canOverflow", false);
1376 }
1377
VisitBinaryOperator(const BinaryOperator * BO)1378 void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) {
1379 JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode()));
1380 }
1381
VisitCompoundAssignOperator(const CompoundAssignOperator * CAO)1382 void JSONNodeDumper::VisitCompoundAssignOperator(
1383 const CompoundAssignOperator *CAO) {
1384 VisitBinaryOperator(CAO);
1385 JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType()));
1386 JOS.attribute("computeResultType",
1387 createQualType(CAO->getComputationResultType()));
1388 }
1389
VisitMemberExpr(const MemberExpr * ME)1390 void 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("name", VD && VD->getDeclName() ? VD->getNameAsString() : "");
1395 JOS.attribute("isArrow", ME->isArrow());
1396 JOS.attribute("referencedMemberDecl", createPointerRepresentation(VD));
1397 switch (ME->isNonOdrUse()) {
1398 case NOUR_None: break;
1399 case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;
1400 case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;
1401 case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
1402 }
1403 }
1404
VisitCXXNewExpr(const CXXNewExpr * NE)1405 void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {
1406 attributeOnlyIfTrue("isGlobal", NE->isGlobalNew());
1407 attributeOnlyIfTrue("isArray", NE->isArray());
1408 attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0);
1409 switch (NE->getInitializationStyle()) {
1410 case CXXNewInitializationStyle::None:
1411 break;
1412 case CXXNewInitializationStyle::Parens:
1413 JOS.attribute("initStyle", "call");
1414 break;
1415 case CXXNewInitializationStyle::Braces:
1416 JOS.attribute("initStyle", "list");
1417 break;
1418 }
1419 if (const FunctionDecl *FD = NE->getOperatorNew())
1420 JOS.attribute("operatorNewDecl", createBareDeclRef(FD));
1421 if (const FunctionDecl *FD = NE->getOperatorDelete())
1422 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));
1423 }
VisitCXXDeleteExpr(const CXXDeleteExpr * DE)1424 void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {
1425 attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete());
1426 attributeOnlyIfTrue("isArray", DE->isArrayForm());
1427 attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten());
1428 if (const FunctionDecl *FD = DE->getOperatorDelete())
1429 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));
1430 }
1431
VisitCXXThisExpr(const CXXThisExpr * TE)1432 void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) {
1433 attributeOnlyIfTrue("implicit", TE->isImplicit());
1434 }
1435
VisitCastExpr(const CastExpr * CE)1436 void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) {
1437 JOS.attribute("castKind", CE->getCastKindName());
1438 llvm::json::Array Path = createCastPath(CE);
1439 if (!Path.empty())
1440 JOS.attribute("path", 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("conversionFunc", createBareDeclRef(ND));
1445 }
1446
VisitImplicitCastExpr(const ImplicitCastExpr * ICE)1447 void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
1448 VisitCastExpr(ICE);
1449 attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast());
1450 }
1451
VisitCallExpr(const CallExpr * CE)1452 void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {
1453 attributeOnlyIfTrue("adl", CE->usesADL());
1454 }
1455
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr * TTE)1456 void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
1457 const UnaryExprOrTypeTraitExpr *TTE) {
1458 JOS.attribute("name", getTraitSpelling(TTE->getKind()));
1459 if (TTE->isArgumentType())
1460 JOS.attribute("argType", createQualType(TTE->getArgumentType()));
1461 }
1462
VisitSizeOfPackExpr(const SizeOfPackExpr * SOPE)1463 void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) {
1464 VisitNamedDecl(SOPE->getPack());
1465 }
1466
VisitUnresolvedLookupExpr(const UnresolvedLookupExpr * ULE)1467 void JSONNodeDumper::VisitUnresolvedLookupExpr(
1468 const UnresolvedLookupExpr *ULE) {
1469 JOS.attribute("usesADL", ULE->requiresADL());
1470 JOS.attribute("name", ULE->getName().getAsString());
1471
1472 JOS.attributeArray("lookups", [this, ULE] {
1473 for (const NamedDecl *D : ULE->decls())
1474 JOS.value(createBareDeclRef(D));
1475 });
1476 }
1477
VisitAddrLabelExpr(const AddrLabelExpr * ALE)1478 void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) {
1479 JOS.attribute("name", ALE->getLabel()->getName());
1480 JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel()));
1481 }
1482
VisitCXXTypeidExpr(const CXXTypeidExpr * CTE)1483 void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
1484 if (CTE->isTypeOperand()) {
1485 QualType Adjusted = CTE->getTypeOperand(Ctx);
1486 QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType();
1487 JOS.attribute("typeArg", createQualType(Unadjusted));
1488 if (Adjusted != Unadjusted)
1489 JOS.attribute("adjustedTypeArg", createQualType(Adjusted));
1490 }
1491 }
1492
VisitConstantExpr(const ConstantExpr * CE)1493 void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
1494 if (CE->getResultAPValueKind() != APValue::None)
1495 Visit(CE->getAPValueResult(), CE->getType());
1496 }
1497
VisitInitListExpr(const InitListExpr * ILE)1498 void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
1499 if (const FieldDecl *FD = ILE->getInitializedFieldInUnion())
1500 JOS.attribute("field", createBareDeclRef(FD));
1501 }
1502
VisitGenericSelectionExpr(const GenericSelectionExpr * GSE)1503 void JSONNodeDumper::VisitGenericSelectionExpr(
1504 const GenericSelectionExpr *GSE) {
1505 attributeOnlyIfTrue("resultDependent", GSE->isResultDependent());
1506 }
1507
VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr * UCE)1508 void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(
1509 const CXXUnresolvedConstructExpr *UCE) {
1510 if (UCE->getType() != UCE->getTypeAsWritten())
1511 JOS.attribute("typeAsWritten", createQualType(UCE->getTypeAsWritten()));
1512 attributeOnlyIfTrue("list", UCE->isListInitialization());
1513 }
1514
VisitCXXConstructExpr(const CXXConstructExpr * CE)1515 void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) {
1516 CXXConstructorDecl *Ctor = CE->getConstructor();
1517 JOS.attribute("ctorType", createQualType(Ctor->getType()));
1518 attributeOnlyIfTrue("elidable", CE->isElidable());
1519 attributeOnlyIfTrue("list", CE->isListInitialization());
1520 attributeOnlyIfTrue("initializer_list", CE->isStdInitListInitialization());
1521 attributeOnlyIfTrue("zeroing", CE->requiresZeroInitialization());
1522 attributeOnlyIfTrue("hadMultipleCandidates", CE->hadMultipleCandidates());
1523 attributeOnlyIfTrue("isImmediateEscalating", CE->isImmediateEscalating());
1524
1525 switch (CE->getConstructionKind()) {
1526 case CXXConstructionKind::Complete:
1527 JOS.attribute("constructionKind", "complete");
1528 break;
1529 case CXXConstructionKind::Delegating:
1530 JOS.attribute("constructionKind", "delegating");
1531 break;
1532 case CXXConstructionKind::NonVirtualBase:
1533 JOS.attribute("constructionKind", "non-virtual base");
1534 break;
1535 case CXXConstructionKind::VirtualBase:
1536 JOS.attribute("constructionKind", "virtual base");
1537 break;
1538 }
1539 }
1540
VisitExprWithCleanups(const ExprWithCleanups * EWC)1541 void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {
1542 attributeOnlyIfTrue("cleanupsHaveSideEffects",
1543 EWC->cleanupsHaveSideEffects());
1544 if (EWC->getNumObjects()) {
1545 JOS.attributeArray("cleanups", [this, EWC] {
1546 for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())
1547 if (auto *BD = dyn_cast<BlockDecl *>(CO)) {
1548 JOS.value(createBareDeclRef(BD));
1549 } else if (auto *CLE = dyn_cast<CompoundLiteralExpr *>(CO)) {
1550 llvm::json::Object Obj;
1551 Obj["id"] = createPointerRepresentation(CLE);
1552 Obj["kind"] = CLE->getStmtClassName();
1553 JOS.value(std::move(Obj));
1554 } else {
1555 llvm_unreachable("unexpected cleanup object type");
1556 }
1557 });
1558 }
1559 }
1560
VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr * BTE)1561 void JSONNodeDumper::VisitCXXBindTemporaryExpr(
1562 const CXXBindTemporaryExpr *BTE) {
1563 const CXXTemporary *Temp = BTE->getTemporary();
1564 JOS.attribute("temp", createPointerRepresentation(Temp));
1565 if (const CXXDestructorDecl *Dtor = Temp->getDestructor())
1566 JOS.attribute("dtor", createBareDeclRef(Dtor));
1567 }
1568
VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr * MTE)1569 void JSONNodeDumper::VisitMaterializeTemporaryExpr(
1570 const MaterializeTemporaryExpr *MTE) {
1571 if (const ValueDecl *VD = MTE->getExtendingDecl())
1572 JOS.attribute("extendingDecl", createBareDeclRef(VD));
1573
1574 switch (MTE->getStorageDuration()) {
1575 case SD_Automatic:
1576 JOS.attribute("storageDuration", "automatic");
1577 break;
1578 case SD_Dynamic:
1579 JOS.attribute("storageDuration", "dynamic");
1580 break;
1581 case SD_FullExpression:
1582 JOS.attribute("storageDuration", "full expression");
1583 break;
1584 case SD_Static:
1585 JOS.attribute("storageDuration", "static");
1586 break;
1587 case SD_Thread:
1588 JOS.attribute("storageDuration", "thread");
1589 break;
1590 }
1591
1592 attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference());
1593 }
1594
VisitCXXDefaultArgExpr(const CXXDefaultArgExpr * Node)1595 void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
1596 attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());
1597 }
1598
VisitCXXDefaultInitExpr(const CXXDefaultInitExpr * Node)1599 void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
1600 attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());
1601 }
1602
VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr * DSME)1603 void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
1604 const CXXDependentScopeMemberExpr *DSME) {
1605 JOS.attribute("isArrow", DSME->isArrow());
1606 JOS.attribute("member", DSME->getMember().getAsString());
1607 attributeOnlyIfTrue("hasTemplateKeyword", DSME->hasTemplateKeyword());
1608 attributeOnlyIfTrue("hasExplicitTemplateArgs",
1609 DSME->hasExplicitTemplateArgs());
1610
1611 if (DSME->getNumTemplateArgs()) {
1612 JOS.attributeArray("explicitTemplateArgs", [DSME, this] {
1613 for (const TemplateArgumentLoc &TAL : DSME->template_arguments())
1614 JOS.object(
1615 [&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });
1616 });
1617 }
1618 }
1619
VisitRequiresExpr(const RequiresExpr * RE)1620 void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {
1621 if (!RE->isValueDependent())
1622 JOS.attribute("satisfied", RE->isSatisfied());
1623 }
1624
VisitIntegerLiteral(const IntegerLiteral * IL)1625 void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {
1626 llvm::SmallString<16> Buffer;
1627 IL->getValue().toString(Buffer,
1628 /*Radix=*/10, IL->getType()->isSignedIntegerType());
1629 JOS.attribute("value", Buffer);
1630 }
VisitCharacterLiteral(const CharacterLiteral * CL)1631 void 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("value", CL->getValue());
1637 }
VisitFixedPointLiteral(const FixedPointLiteral * FPL)1638 void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) {
1639 JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10));
1640 }
VisitFloatingLiteral(const FloatingLiteral * FL)1641 void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) {
1642 llvm::SmallString<16> Buffer;
1643 FL->getValue().toString(Buffer);
1644 JOS.attribute("value", Buffer);
1645 }
VisitStringLiteral(const StringLiteral * SL)1646 void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) {
1647 std::string Buffer;
1648 llvm::raw_string_ostream SS(Buffer);
1649 SL->outputString(SS);
1650 JOS.attribute("value", Buffer);
1651 }
VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr * BLE)1652 void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) {
1653 JOS.attribute("value", BLE->getValue());
1654 }
1655
VisitIfStmt(const IfStmt * IS)1656 void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) {
1657 attributeOnlyIfTrue("hasInit", IS->hasInitStorage());
1658 attributeOnlyIfTrue("hasVar", IS->hasVarStorage());
1659 attributeOnlyIfTrue("hasElse", IS->hasElseStorage());
1660 attributeOnlyIfTrue("isConstexpr", IS->isConstexpr());
1661 attributeOnlyIfTrue("isConsteval", IS->isConsteval());
1662 attributeOnlyIfTrue("constevalIsNegated", IS->isNegatedConsteval());
1663 }
1664
VisitSwitchStmt(const SwitchStmt * SS)1665 void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) {
1666 attributeOnlyIfTrue("hasInit", SS->hasInitStorage());
1667 attributeOnlyIfTrue("hasVar", SS->hasVarStorage());
1668 }
VisitCaseStmt(const CaseStmt * CS)1669 void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
1670 attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange());
1671 }
1672
VisitLabelStmt(const LabelStmt * LS)1673 void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
1674 JOS.attribute("name", LS->getName());
1675 JOS.attribute("declId", createPointerRepresentation(LS->getDecl()));
1676 attributeOnlyIfTrue("sideEntry", LS->isSideEntry());
1677 }
VisitGotoStmt(const GotoStmt * GS)1678 void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
1679 JOS.attribute("targetLabelDeclId",
1680 createPointerRepresentation(GS->getLabel()));
1681 }
1682
VisitWhileStmt(const WhileStmt * WS)1683 void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) {
1684 attributeOnlyIfTrue("hasVar", WS->hasVarStorage());
1685 }
1686
VisitObjCAtCatchStmt(const ObjCAtCatchStmt * OACS)1687 void 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("isCatchAll", OACS->getCatchParamDecl() == nullptr);
1692 }
1693
VisitNullTemplateArgument(const TemplateArgument & TA)1694 void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) {
1695 JOS.attribute("isNull", true);
1696 }
VisitTypeTemplateArgument(const TemplateArgument & TA)1697 void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
1698 JOS.attribute("type", createQualType(TA.getAsType()));
1699 }
VisitDeclarationTemplateArgument(const TemplateArgument & TA)1700 void JSONNodeDumper::VisitDeclarationTemplateArgument(
1701 const TemplateArgument &TA) {
1702 JOS.attribute("decl", createBareDeclRef(TA.getAsDecl()));
1703 }
VisitNullPtrTemplateArgument(const TemplateArgument & TA)1704 void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) {
1705 JOS.attribute("isNullptr", true);
1706 }
VisitIntegralTemplateArgument(const TemplateArgument & TA)1707 void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
1708 JOS.attribute("value", TA.getAsIntegral().getSExtValue());
1709 }
VisitStructuralValueTemplateArgument(const TemplateArgument & TA)1710 void JSONNodeDumper::VisitStructuralValueTemplateArgument(
1711 const TemplateArgument &TA) {
1712 Visit(TA.getAsStructuralValue(), TA.getStructuralValueType());
1713 }
VisitTemplateTemplateArgument(const TemplateArgument & TA)1714 void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
1715 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1716 // the output format.
1717 }
VisitTemplateExpansionTemplateArgument(const TemplateArgument & TA)1718 void 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 }
VisitExpressionTemplateArgument(const TemplateArgument & TA)1723 void JSONNodeDumper::VisitExpressionTemplateArgument(
1724 const TemplateArgument &TA) {
1725 JOS.attribute("isExpr", true);
1726 if (TA.isCanonicalExpr())
1727 JOS.attribute("isCanonical", true);
1728 }
VisitPackTemplateArgument(const TemplateArgument & TA)1729 void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
1730 JOS.attribute("isPack", true);
1731 }
1732
getCommentCommandName(unsigned CommandID) const1733 StringRef 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
visitTextComment(const comments::TextComment * C,const comments::FullComment *)1742 void JSONNodeDumper::visitTextComment(const comments::TextComment *C,
1743 const comments::FullComment *) {
1744 JOS.attribute("text", C->getText());
1745 }
1746
visitInlineCommandComment(const comments::InlineCommandComment * C,const comments::FullComment *)1747 void JSONNodeDumper::visitInlineCommandComment(
1748 const comments::InlineCommandComment *C, const comments::FullComment *) {
1749 JOS.attribute("name", getCommentCommandName(C->getCommandID()));
1750
1751 switch (C->getRenderKind()) {
1752 case comments::InlineCommandRenderKind::Normal:
1753 JOS.attribute("renderKind", "normal");
1754 break;
1755 case comments::InlineCommandRenderKind::Bold:
1756 JOS.attribute("renderKind", "bold");
1757 break;
1758 case comments::InlineCommandRenderKind::Emphasized:
1759 JOS.attribute("renderKind", "emphasized");
1760 break;
1761 case comments::InlineCommandRenderKind::Monospaced:
1762 JOS.attribute("renderKind", "monospaced");
1763 break;
1764 case comments::InlineCommandRenderKind::Anchor:
1765 JOS.attribute("renderKind", "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(C->getArgText(I));
1772
1773 if (!Args.empty())
1774 JOS.attribute("args", std::move(Args));
1775 }
1776
visitHTMLStartTagComment(const comments::HTMLStartTagComment * C,const comments::FullComment *)1777 void JSONNodeDumper::visitHTMLStartTagComment(
1778 const comments::HTMLStartTagComment *C, const comments::FullComment *) {
1779 JOS.attribute("name", C->getTagName());
1780 attributeOnlyIfTrue("selfClosing", C->isSelfClosing());
1781 attributeOnlyIfTrue("malformed", C->isMalformed());
1782
1783 llvm::json::Array Attrs;
1784 for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I)
1785 Attrs.push_back(
1786 {{"name", C->getAttr(I).Name}, {"value", C->getAttr(I).Value}});
1787
1788 if (!Attrs.empty())
1789 JOS.attribute("attrs", std::move(Attrs));
1790 }
1791
visitHTMLEndTagComment(const comments::HTMLEndTagComment * C,const comments::FullComment *)1792 void JSONNodeDumper::visitHTMLEndTagComment(
1793 const comments::HTMLEndTagComment *C, const comments::FullComment *) {
1794 JOS.attribute("name", C->getTagName());
1795 }
1796
visitBlockCommandComment(const comments::BlockCommandComment * C,const comments::FullComment *)1797 void JSONNodeDumper::visitBlockCommandComment(
1798 const comments::BlockCommandComment *C, const comments::FullComment *) {
1799 JOS.attribute("name", getCommentCommandName(C->getCommandID()));
1800
1801 llvm::json::Array Args;
1802 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
1803 Args.push_back(C->getArgText(I));
1804
1805 if (!Args.empty())
1806 JOS.attribute("args", std::move(Args));
1807 }
1808
visitParamCommandComment(const comments::ParamCommandComment * C,const comments::FullComment * FC)1809 void JSONNodeDumper::visitParamCommandComment(
1810 const comments::ParamCommandComment *C, const comments::FullComment *FC) {
1811 switch (C->getDirection()) {
1812 case comments::ParamCommandPassDirection::In:
1813 JOS.attribute("direction", "in");
1814 break;
1815 case comments::ParamCommandPassDirection::Out:
1816 JOS.attribute("direction", "out");
1817 break;
1818 case comments::ParamCommandPassDirection::InOut:
1819 JOS.attribute("direction", "in,out");
1820 break;
1821 }
1822 attributeOnlyIfTrue("explicit", C->isDirectionExplicit());
1823
1824 if (C->hasParamName())
1825 JOS.attribute("param", C->isParamIndexValid() ? C->getParamName(FC)
1826 : C->getParamNameAsWritten());
1827
1828 if (C->isParamIndexValid() && !C->isVarArgParam())
1829 JOS.attribute("paramIdx", C->getParamIndex());
1830 }
1831
visitTParamCommandComment(const comments::TParamCommandComment * C,const comments::FullComment * FC)1832 void JSONNodeDumper::visitTParamCommandComment(
1833 const comments::TParamCommandComment *C, const comments::FullComment *FC) {
1834 if (C->hasParamName())
1835 JOS.attribute("param", 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(C->getIndex(I));
1841
1842 if (!Positions.empty())
1843 JOS.attribute("positions", std::move(Positions));
1844 }
1845 }
1846
visitVerbatimBlockComment(const comments::VerbatimBlockComment * C,const comments::FullComment *)1847 void JSONNodeDumper::visitVerbatimBlockComment(
1848 const comments::VerbatimBlockComment *C, const comments::FullComment *) {
1849 JOS.attribute("name", getCommentCommandName(C->getCommandID()));
1850 JOS.attribute("closeName", C->getCloseName());
1851 }
1852
visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment * C,const comments::FullComment *)1853 void JSONNodeDumper::visitVerbatimBlockLineComment(
1854 const comments::VerbatimBlockLineComment *C,
1855 const comments::FullComment *) {
1856 JOS.attribute("text", C->getText());
1857 }
1858
visitVerbatimLineComment(const comments::VerbatimLineComment * C,const comments::FullComment *)1859 void JSONNodeDumper::visitVerbatimLineComment(
1860 const comments::VerbatimLineComment *C, const comments::FullComment *) {
1861 JOS.attribute("text", C->getText());
1862 }
1863
createFPOptions(FPOptionsOverride FPO)1864 llvm::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
VisitCompoundStmt(const CompoundStmt * S)1873 void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
1874 VisitStmt(S);
1875 if (S->hasStoredFPFeatures())
1876 JOS.attribute("fpoptions", createFPOptions(S->getStoredFPFeatures()));
1877 }
1878