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"
11 void JSONNodeDumper::addPreviousDeclaration(const Decl
*D
) {
12 switch (D
->getKind()) {
13 #define DECL(DERIVED, BASE) \
15 return writePreviousDeclImpl(cast<DERIVED##Decl>(D));
16 #define ABSTRACT_DECL(DECL)
17 #include "clang/AST/DeclNodes.inc"
21 llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
24 void JSONNodeDumper::Visit(const Attr
*A
) {
25 const char *AttrName
= nullptr;
26 switch (A
->getKind()) {
29 AttrName = #X"Attr"; \
31 #include "clang/Basic/AttrList.inc"
34 JOS
.attribute("id", createPointerRepresentation(A
));
35 JOS
.attribute("kind", AttrName
);
36 JOS
.attributeObject("range", [A
, this] { writeSourceRange(A
->getRange()); });
37 attributeOnlyIfTrue("inherited", A
->isInherited());
38 attributeOnlyIfTrue("implicit", A
->isImplicit());
40 // FIXME: it would be useful for us to output the spelling kind as well as
41 // the actual spelling. This would allow us to distinguish between the
42 // various attribute syntaxes, but we don't currently track that information
44 //JOS.attribute("spelling", A->getSpelling());
46 InnerAttrVisitor::Visit(A
);
49 void JSONNodeDumper::Visit(const Stmt
*S
) {
53 JOS
.attribute("id", createPointerRepresentation(S
));
54 JOS
.attribute("kind", S
->getStmtClassName());
55 JOS
.attributeObject("range",
56 [S
, this] { writeSourceRange(S
->getSourceRange()); });
58 if (const auto *E
= dyn_cast
<Expr
>(S
)) {
59 JOS
.attribute("type", createQualType(E
->getType()));
60 const char *Category
= nullptr;
61 switch (E
->getValueKind()) {
62 case VK_LValue
: Category
= "lvalue"; break;
63 case VK_XValue
: Category
= "xvalue"; break;
68 JOS
.attribute("valueCategory", Category
);
70 InnerStmtVisitor::Visit(S
);
73 void JSONNodeDumper::Visit(const Type
*T
) {
74 JOS
.attribute("id", createPointerRepresentation(T
));
79 JOS
.attribute("kind", (llvm::Twine(T
->getTypeClassName()) + "Type").str());
80 JOS
.attribute("type", createQualType(QualType(T
, 0), /*Desugar*/ false));
81 attributeOnlyIfTrue("containsErrors", T
->containsErrors());
82 attributeOnlyIfTrue("isDependent", T
->isDependentType());
83 attributeOnlyIfTrue("isInstantiationDependent",
84 T
->isInstantiationDependentType());
85 attributeOnlyIfTrue("isVariablyModified", T
->isVariablyModifiedType());
86 attributeOnlyIfTrue("containsUnexpandedPack",
87 T
->containsUnexpandedParameterPack());
88 attributeOnlyIfTrue("isImported", T
->isFromAST());
89 InnerTypeVisitor::Visit(T
);
92 void JSONNodeDumper::Visit(QualType T
) {
93 JOS
.attribute("id", createPointerRepresentation(T
.getAsOpaquePtr()));
94 JOS
.attribute("kind", "QualType");
95 JOS
.attribute("type", createQualType(T
));
96 JOS
.attribute("qualifiers", T
.split().Quals
.getAsString());
99 void JSONNodeDumper::Visit(const Decl
*D
) {
100 JOS
.attribute("id", createPointerRepresentation(D
));
105 JOS
.attribute("kind", (llvm::Twine(D
->getDeclKindName()) + "Decl").str());
106 JOS
.attributeObject("loc",
107 [D
, this] { writeSourceLocation(D
->getLocation()); });
108 JOS
.attributeObject("range",
109 [D
, this] { writeSourceRange(D
->getSourceRange()); });
110 attributeOnlyIfTrue("isImplicit", D
->isImplicit());
111 attributeOnlyIfTrue("isInvalid", D
->isInvalidDecl());
114 JOS
.attribute("isUsed", true);
115 else if (D
->isThisDeclarationReferenced())
116 JOS
.attribute("isReferenced", true);
118 if (const auto *ND
= dyn_cast
<NamedDecl
>(D
))
119 attributeOnlyIfTrue("isHidden", !ND
->isUnconditionallyVisible());
121 if (D
->getLexicalDeclContext() != D
->getDeclContext()) {
122 // Because of multiple inheritance, a DeclContext pointer does not produce
123 // the same pointer representation as a Decl pointer that references the
125 const auto *ParentDeclContextDecl
= dyn_cast
<Decl
>(D
->getDeclContext());
126 JOS
.attribute("parentDeclContextId",
127 createPointerRepresentation(ParentDeclContextDecl
));
130 addPreviousDeclaration(D
);
131 InnerDeclVisitor::Visit(D
);
134 void JSONNodeDumper::Visit(const comments::Comment
*C
,
135 const comments::FullComment
*FC
) {
139 JOS
.attribute("id", createPointerRepresentation(C
));
140 JOS
.attribute("kind", C
->getCommentKindName());
141 JOS
.attributeObject("loc",
142 [C
, this] { writeSourceLocation(C
->getLocation()); });
143 JOS
.attributeObject("range",
144 [C
, this] { writeSourceRange(C
->getSourceRange()); });
146 InnerCommentVisitor::visit(C
, FC
);
149 void JSONNodeDumper::Visit(const TemplateArgument
&TA
, SourceRange R
,
150 const Decl
*From
, StringRef Label
) {
151 JOS
.attribute("kind", "TemplateArgument");
153 JOS
.attributeObject("range", [R
, this] { writeSourceRange(R
); });
156 JOS
.attribute(Label
.empty() ? "fromDecl" : Label
, createBareDeclRef(From
));
158 InnerTemplateArgVisitor::Visit(TA
);
161 void JSONNodeDumper::Visit(const CXXCtorInitializer
*Init
) {
162 JOS
.attribute("kind", "CXXCtorInitializer");
163 if (Init
->isAnyMemberInitializer())
164 JOS
.attribute("anyInit", createBareDeclRef(Init
->getAnyMember()));
165 else if (Init
->isBaseInitializer())
166 JOS
.attribute("baseInit",
167 createQualType(QualType(Init
->getBaseClass(), 0)));
168 else if (Init
->isDelegatingInitializer())
169 JOS
.attribute("delegatingInit",
170 createQualType(Init
->getTypeSourceInfo()->getType()));
172 llvm_unreachable("Unknown initializer type");
175 void JSONNodeDumper::Visit(const OMPClause
*C
) {}
177 void JSONNodeDumper::Visit(const BlockDecl::Capture
&C
) {
178 JOS
.attribute("kind", "Capture");
179 attributeOnlyIfTrue("byref", C
.isByRef());
180 attributeOnlyIfTrue("nested", C
.isNested());
182 JOS
.attribute("var", createBareDeclRef(C
.getVariable()));
185 void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation
&A
) {
186 JOS
.attribute("associationKind", A
.getTypeSourceInfo() ? "case" : "default");
187 attributeOnlyIfTrue("selected", A
.isSelected());
190 void JSONNodeDumper::Visit(const concepts::Requirement
*R
) {
194 switch (R
->getKind()) {
195 case concepts::Requirement::RK_Type
:
196 JOS
.attribute("kind", "TypeRequirement");
198 case concepts::Requirement::RK_Simple
:
199 JOS
.attribute("kind", "SimpleRequirement");
201 case concepts::Requirement::RK_Compound
:
202 JOS
.attribute("kind", "CompoundRequirement");
204 case concepts::Requirement::RK_Nested
:
205 JOS
.attribute("kind", "NestedRequirement");
209 if (auto *ER
= dyn_cast
<concepts::ExprRequirement
>(R
))
210 attributeOnlyIfTrue("noexcept", ER
->hasNoexceptRequirement());
212 attributeOnlyIfTrue("isDependent", R
->isDependent());
213 if (!R
->isDependent())
214 JOS
.attribute("satisfied", R
->isSatisfied());
215 attributeOnlyIfTrue("containsUnexpandedPack",
216 R
->containsUnexpandedParameterPack());
219 void JSONNodeDumper::Visit(const APValue
&Value
, QualType Ty
) {
221 llvm::raw_string_ostream
OS(Str
);
222 Value
.printPretty(OS
, Ctx
, Ty
);
223 JOS
.attribute("value", OS
.str());
226 void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc
, bool JustFirst
) {
230 JOS
.attributeBegin("includedFrom");
234 // Walk the stack recursively, then print out the presumed location.
235 writeIncludeStack(SM
.getPresumedLoc(Loc
.getIncludeLoc()));
238 JOS
.attribute("file", Loc
.getFilename());
243 void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc
,
245 PresumedLoc Presumed
= SM
.getPresumedLoc(Loc
);
246 unsigned ActualLine
= IsSpelling
? SM
.getSpellingLineNumber(Loc
)
247 : SM
.getExpansionLineNumber(Loc
);
248 StringRef ActualFile
= SM
.getBufferName(Loc
);
250 if (Presumed
.isValid()) {
251 JOS
.attribute("offset", SM
.getDecomposedLoc(Loc
).second
);
252 if (LastLocFilename
!= ActualFile
) {
253 JOS
.attribute("file", ActualFile
);
254 JOS
.attribute("line", ActualLine
);
255 } else if (LastLocLine
!= ActualLine
)
256 JOS
.attribute("line", ActualLine
);
258 StringRef PresumedFile
= Presumed
.getFilename();
259 if (PresumedFile
!= ActualFile
&& LastLocPresumedFilename
!= PresumedFile
)
260 JOS
.attribute("presumedFile", PresumedFile
);
262 unsigned PresumedLine
= Presumed
.getLine();
263 if (ActualLine
!= PresumedLine
&& LastLocPresumedLine
!= PresumedLine
)
264 JOS
.attribute("presumedLine", PresumedLine
);
266 JOS
.attribute("col", Presumed
.getColumn());
267 JOS
.attribute("tokLen",
268 Lexer::MeasureTokenLength(Loc
, SM
, Ctx
.getLangOpts()));
269 LastLocFilename
= ActualFile
;
270 LastLocPresumedFilename
= PresumedFile
;
271 LastLocPresumedLine
= PresumedLine
;
272 LastLocLine
= ActualLine
;
274 // Orthogonal to the file, line, and column de-duplication is whether the
275 // given location was a result of an include. If so, print where the
276 // include location came from.
277 writeIncludeStack(SM
.getPresumedLoc(Presumed
.getIncludeLoc()),
282 void JSONNodeDumper::writeSourceLocation(SourceLocation Loc
) {
283 SourceLocation Spelling
= SM
.getSpellingLoc(Loc
);
284 SourceLocation Expansion
= SM
.getExpansionLoc(Loc
);
286 if (Expansion
!= Spelling
) {
287 // If the expansion and the spelling are different, output subobjects
288 // describing both locations.
289 JOS
.attributeObject("spellingLoc", [Spelling
, this] {
290 writeBareSourceLocation(Spelling
, /*IsSpelling*/ true);
292 JOS
.attributeObject("expansionLoc", [Expansion
, Loc
, this] {
293 writeBareSourceLocation(Expansion
, /*IsSpelling*/ false);
294 // If there is a macro expansion, add extra information if the interesting
295 // bit is the macro arg expansion.
296 if (SM
.isMacroArgExpansion(Loc
))
297 JOS
.attribute("isMacroArgExpansion", true);
300 writeBareSourceLocation(Spelling
, /*IsSpelling*/ true);
303 void JSONNodeDumper::writeSourceRange(SourceRange R
) {
304 JOS
.attributeObject("begin",
305 [R
, this] { writeSourceLocation(R
.getBegin()); });
306 JOS
.attributeObject("end", [R
, this] { writeSourceLocation(R
.getEnd()); });
309 std::string
JSONNodeDumper::createPointerRepresentation(const void *Ptr
) {
310 // Because JSON stores integer values as signed 64-bit integers, trying to
311 // represent them as such makes for very ugly pointer values in the resulting
312 // output. Instead, we convert the value to hex and treat it as a string.
313 return "0x" + llvm::utohexstr(reinterpret_cast<uint64_t>(Ptr
), true);
316 llvm::json::Object
JSONNodeDumper::createQualType(QualType QT
, bool Desugar
) {
317 SplitQualType SQT
= QT
.split();
318 std::string SQTS
= QualType::getAsString(SQT
, PrintPolicy
);
319 llvm::json::Object Ret
{{"qualType", SQTS
}};
321 if (Desugar
&& !QT
.isNull()) {
322 SplitQualType DSQT
= QT
.getSplitDesugaredType();
324 std::string DSQTS
= QualType::getAsString(DSQT
, PrintPolicy
);
326 Ret
["desugaredQualType"] = DSQTS
;
328 if (const auto *TT
= QT
->getAs
<TypedefType
>())
329 Ret
["typeAliasDeclId"] = createPointerRepresentation(TT
->getDecl());
334 void JSONNodeDumper::writeBareDeclRef(const Decl
*D
) {
335 JOS
.attribute("id", createPointerRepresentation(D
));
339 JOS
.attribute("kind", (llvm::Twine(D
->getDeclKindName()) + "Decl").str());
340 if (const auto *ND
= dyn_cast
<NamedDecl
>(D
))
341 JOS
.attribute("name", ND
->getDeclName().getAsString());
342 if (const auto *VD
= dyn_cast
<ValueDecl
>(D
))
343 JOS
.attribute("type", createQualType(VD
->getType()));
346 llvm::json::Object
JSONNodeDumper::createBareDeclRef(const Decl
*D
) {
347 llvm::json::Object Ret
{{"id", createPointerRepresentation(D
)}};
351 Ret
["kind"] = (llvm::Twine(D
->getDeclKindName()) + "Decl").str();
352 if (const auto *ND
= dyn_cast
<NamedDecl
>(D
))
353 Ret
["name"] = ND
->getDeclName().getAsString();
354 if (const auto *VD
= dyn_cast
<ValueDecl
>(D
))
355 Ret
["type"] = createQualType(VD
->getType());
359 llvm::json::Array
JSONNodeDumper::createCastPath(const CastExpr
*C
) {
360 llvm::json::Array Ret
;
364 for (auto I
= C
->path_begin(), E
= C
->path_end(); I
!= E
; ++I
) {
365 const CXXBaseSpecifier
*Base
= *I
;
367 cast
<CXXRecordDecl
>(Base
->getType()->castAs
<RecordType
>()->getDecl());
369 llvm::json::Object Val
{{"name", RD
->getName()}};
370 if (Base
->isVirtual())
371 Val
["isVirtual"] = true;
372 Ret
.push_back(std::move(Val
));
377 #define FIELD2(Name, Flag) if (RD->Flag()) Ret[Name] = true
378 #define FIELD1(Flag) FIELD2(#Flag, Flag)
380 static llvm::json::Object
381 createDefaultConstructorDefinitionData(const CXXRecordDecl
*RD
) {
382 llvm::json::Object Ret
;
384 FIELD2("exists", hasDefaultConstructor
);
385 FIELD2("trivial", hasTrivialDefaultConstructor
);
386 FIELD2("nonTrivial", hasNonTrivialDefaultConstructor
);
387 FIELD2("userProvided", hasUserProvidedDefaultConstructor
);
388 FIELD2("isConstexpr", hasConstexprDefaultConstructor
);
389 FIELD2("needsImplicit", needsImplicitDefaultConstructor
);
390 FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr
);
395 static llvm::json::Object
396 createCopyConstructorDefinitionData(const CXXRecordDecl
*RD
) {
397 llvm::json::Object Ret
;
399 FIELD2("simple", hasSimpleCopyConstructor
);
400 FIELD2("trivial", hasTrivialCopyConstructor
);
401 FIELD2("nonTrivial", hasNonTrivialCopyConstructor
);
402 FIELD2("userDeclared", hasUserDeclaredCopyConstructor
);
403 FIELD2("hasConstParam", hasCopyConstructorWithConstParam
);
404 FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam
);
405 FIELD2("needsImplicit", needsImplicitCopyConstructor
);
406 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor
);
407 if (!RD
->needsOverloadResolutionForCopyConstructor())
408 FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted
);
413 static llvm::json::Object
414 createMoveConstructorDefinitionData(const CXXRecordDecl
*RD
) {
415 llvm::json::Object Ret
;
417 FIELD2("exists", hasMoveConstructor
);
418 FIELD2("simple", hasSimpleMoveConstructor
);
419 FIELD2("trivial", hasTrivialMoveConstructor
);
420 FIELD2("nonTrivial", hasNonTrivialMoveConstructor
);
421 FIELD2("userDeclared", hasUserDeclaredMoveConstructor
);
422 FIELD2("needsImplicit", needsImplicitMoveConstructor
);
423 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor
);
424 if (!RD
->needsOverloadResolutionForMoveConstructor())
425 FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted
);
430 static llvm::json::Object
431 createCopyAssignmentDefinitionData(const CXXRecordDecl
*RD
) {
432 llvm::json::Object Ret
;
434 FIELD2("simple", hasSimpleCopyAssignment
);
435 FIELD2("trivial", hasTrivialCopyAssignment
);
436 FIELD2("nonTrivial", hasNonTrivialCopyAssignment
);
437 FIELD2("hasConstParam", hasCopyAssignmentWithConstParam
);
438 FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam
);
439 FIELD2("userDeclared", hasUserDeclaredCopyAssignment
);
440 FIELD2("needsImplicit", needsImplicitCopyAssignment
);
441 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment
);
446 static llvm::json::Object
447 createMoveAssignmentDefinitionData(const CXXRecordDecl
*RD
) {
448 llvm::json::Object Ret
;
450 FIELD2("exists", hasMoveAssignment
);
451 FIELD2("simple", hasSimpleMoveAssignment
);
452 FIELD2("trivial", hasTrivialMoveAssignment
);
453 FIELD2("nonTrivial", hasNonTrivialMoveAssignment
);
454 FIELD2("userDeclared", hasUserDeclaredMoveAssignment
);
455 FIELD2("needsImplicit", needsImplicitMoveAssignment
);
456 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment
);
461 static llvm::json::Object
462 createDestructorDefinitionData(const CXXRecordDecl
*RD
) {
463 llvm::json::Object Ret
;
465 FIELD2("simple", hasSimpleDestructor
);
466 FIELD2("irrelevant", hasIrrelevantDestructor
);
467 FIELD2("trivial", hasTrivialDestructor
);
468 FIELD2("nonTrivial", hasNonTrivialDestructor
);
469 FIELD2("userDeclared", hasUserDeclaredDestructor
);
470 FIELD2("needsImplicit", needsImplicitDestructor
);
471 FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor
);
472 if (!RD
->needsOverloadResolutionForDestructor())
473 FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted
);
479 JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl
*RD
) {
480 llvm::json::Object Ret
;
482 // This data is common to all C++ classes.
483 FIELD1(isGenericLambda
);
487 FIELD1(isStandardLayout
);
488 FIELD1(isTriviallyCopyable
);
491 FIELD1(isPolymorphic
);
494 FIELD1(canPassInRegisters
);
495 FIELD1(hasUserDeclaredConstructor
);
496 FIELD1(hasConstexprNonCopyMoveConstructor
);
497 FIELD1(hasMutableFields
);
498 FIELD1(hasVariantMembers
);
499 FIELD2("canConstDefaultInit", allowConstDefaultInit
);
501 Ret
["defaultCtor"] = createDefaultConstructorDefinitionData(RD
);
502 Ret
["copyCtor"] = createCopyConstructorDefinitionData(RD
);
503 Ret
["moveCtor"] = createMoveConstructorDefinitionData(RD
);
504 Ret
["copyAssign"] = createCopyAssignmentDefinitionData(RD
);
505 Ret
["moveAssign"] = createMoveAssignmentDefinitionData(RD
);
506 Ret
["dtor"] = createDestructorDefinitionData(RD
);
514 std::string
JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS
) {
515 const auto AccessSpelling
= getAccessSpelling(AS
);
516 if (AccessSpelling
.empty())
518 return AccessSpelling
.str();
522 JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier
&BS
) {
523 llvm::json::Object Ret
;
525 Ret
["type"] = createQualType(BS
.getType());
526 Ret
["access"] = createAccessSpecifier(BS
.getAccessSpecifier());
527 Ret
["writtenAccess"] =
528 createAccessSpecifier(BS
.getAccessSpecifierAsWritten());
530 Ret
["isVirtual"] = true;
531 if (BS
.isPackExpansion())
532 Ret
["isPackExpansion"] = true;
537 void JSONNodeDumper::VisitAliasAttr(const AliasAttr
*AA
) {
538 JOS
.attribute("aliasee", AA
->getAliasee());
541 void JSONNodeDumper::VisitCleanupAttr(const CleanupAttr
*CA
) {
542 JOS
.attribute("cleanup_function", createBareDeclRef(CA
->getFunctionDecl()));
545 void JSONNodeDumper::VisitDeprecatedAttr(const DeprecatedAttr
*DA
) {
546 if (!DA
->getMessage().empty())
547 JOS
.attribute("message", DA
->getMessage());
548 if (!DA
->getReplacement().empty())
549 JOS
.attribute("replacement", DA
->getReplacement());
552 void JSONNodeDumper::VisitUnavailableAttr(const UnavailableAttr
*UA
) {
553 if (!UA
->getMessage().empty())
554 JOS
.attribute("message", UA
->getMessage());
557 void JSONNodeDumper::VisitSectionAttr(const SectionAttr
*SA
) {
558 JOS
.attribute("section_name", SA
->getName());
561 void JSONNodeDumper::VisitVisibilityAttr(const VisibilityAttr
*VA
) {
562 JOS
.attribute("visibility", VisibilityAttr::ConvertVisibilityTypeToStr(
563 VA
->getVisibility()));
566 void JSONNodeDumper::VisitTLSModelAttr(const TLSModelAttr
*TA
) {
567 JOS
.attribute("tls_model", TA
->getModel());
570 void JSONNodeDumper::VisitTypedefType(const TypedefType
*TT
) {
571 JOS
.attribute("decl", createBareDeclRef(TT
->getDecl()));
572 if (!TT
->typeMatchesDecl())
573 JOS
.attribute("type", createQualType(TT
->desugar()));
576 void JSONNodeDumper::VisitUsingType(const UsingType
*TT
) {
577 JOS
.attribute("decl", createBareDeclRef(TT
->getFoundDecl()));
578 if (!TT
->typeMatchesDecl())
579 JOS
.attribute("type", createQualType(TT
->desugar()));
582 void JSONNodeDumper::VisitFunctionType(const FunctionType
*T
) {
583 FunctionType::ExtInfo E
= T
->getExtInfo();
584 attributeOnlyIfTrue("noreturn", E
.getNoReturn());
585 attributeOnlyIfTrue("producesResult", E
.getProducesResult());
586 if (E
.getHasRegParm())
587 JOS
.attribute("regParm", E
.getRegParm());
588 JOS
.attribute("cc", FunctionType::getNameForCallConv(E
.getCC()));
591 void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType
*T
) {
592 FunctionProtoType::ExtProtoInfo E
= T
->getExtProtoInfo();
593 attributeOnlyIfTrue("trailingReturn", E
.HasTrailingReturn
);
594 attributeOnlyIfTrue("const", T
->isConst());
595 attributeOnlyIfTrue("volatile", T
->isVolatile());
596 attributeOnlyIfTrue("restrict", T
->isRestrict());
597 attributeOnlyIfTrue("variadic", E
.Variadic
);
598 switch (E
.RefQualifier
) {
599 case RQ_LValue
: JOS
.attribute("refQualifier", "&"); break;
600 case RQ_RValue
: JOS
.attribute("refQualifier", "&&"); break;
603 switch (E
.ExceptionSpec
.Type
) {
604 case EST_DynamicNone
:
606 JOS
.attribute("exceptionSpec", "throw");
607 llvm::json::Array Types
;
608 for (QualType QT
: E
.ExceptionSpec
.Exceptions
)
609 Types
.push_back(createQualType(QT
));
610 JOS
.attribute("exceptionTypes", std::move(Types
));
613 JOS
.attribute("exceptionSpec", "throw");
614 JOS
.attribute("throwsAny", true);
616 case EST_BasicNoexcept
:
617 JOS
.attribute("exceptionSpec", "noexcept");
619 case EST_NoexceptTrue
:
620 case EST_NoexceptFalse
:
621 JOS
.attribute("exceptionSpec", "noexcept");
622 JOS
.attribute("conditionEvaluatesTo",
623 E
.ExceptionSpec
.Type
== EST_NoexceptTrue
);
624 //JOS.attributeWithCall("exceptionSpecExpr",
625 // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); });
628 JOS
.attribute("exceptionSpec", "nothrow");
630 // FIXME: I cannot find a way to trigger these cases while dumping the AST. I
631 // suspect you can only run into them when executing an AST dump from within
632 // the debugger, which is not a use case we worry about for the JSON dumping
634 case EST_DependentNoexcept
:
635 case EST_Unevaluated
:
636 case EST_Uninstantiated
:
638 case EST_None
: break;
640 VisitFunctionType(T
);
643 void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType
*RT
) {
644 attributeOnlyIfTrue("spelledAsLValue", RT
->isSpelledAsLValue());
647 void JSONNodeDumper::VisitArrayType(const ArrayType
*AT
) {
648 switch (AT
->getSizeModifier()) {
649 case ArraySizeModifier::Star
:
650 JOS
.attribute("sizeModifier", "*");
652 case ArraySizeModifier::Static
:
653 JOS
.attribute("sizeModifier", "static");
655 case ArraySizeModifier::Normal
:
659 std::string Str
= AT
->getIndexTypeQualifiers().getAsString();
661 JOS
.attribute("indexTypeQualifiers", Str
);
664 void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType
*CAT
) {
665 // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a
666 // narrowing conversion to int64_t so it cannot be expressed.
667 JOS
.attribute("size", CAT
->getSize().getSExtValue());
671 void JSONNodeDumper::VisitDependentSizedExtVectorType(
672 const DependentSizedExtVectorType
*VT
) {
674 "attrLoc", [VT
, this] { writeSourceLocation(VT
->getAttributeLoc()); });
677 void JSONNodeDumper::VisitVectorType(const VectorType
*VT
) {
678 JOS
.attribute("numElements", VT
->getNumElements());
679 switch (VT
->getVectorKind()) {
680 case VectorKind::Generic
:
682 case VectorKind::AltiVecVector
:
683 JOS
.attribute("vectorKind", "altivec");
685 case VectorKind::AltiVecPixel
:
686 JOS
.attribute("vectorKind", "altivec pixel");
688 case VectorKind::AltiVecBool
:
689 JOS
.attribute("vectorKind", "altivec bool");
691 case VectorKind::Neon
:
692 JOS
.attribute("vectorKind", "neon");
694 case VectorKind::NeonPoly
:
695 JOS
.attribute("vectorKind", "neon poly");
697 case VectorKind::SveFixedLengthData
:
698 JOS
.attribute("vectorKind", "fixed-length sve data vector");
700 case VectorKind::SveFixedLengthPredicate
:
701 JOS
.attribute("vectorKind", "fixed-length sve predicate vector");
703 case VectorKind::RVVFixedLengthData
:
704 JOS
.attribute("vectorKind", "fixed-length rvv data vector");
709 void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType
*UUT
) {
710 JOS
.attribute("decl", createBareDeclRef(UUT
->getDecl()));
713 void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType
*UTT
) {
714 switch (UTT
->getUTTKind()) {
715 #define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
716 case UnaryTransformType::Enum: \
717 JOS.attribute("transformKind", #Trait); \
719 #include "clang/Basic/TransformTypeTraits.def"
723 void JSONNodeDumper::VisitTagType(const TagType
*TT
) {
724 JOS
.attribute("decl", createBareDeclRef(TT
->getDecl()));
727 void JSONNodeDumper::VisitTemplateTypeParmType(
728 const TemplateTypeParmType
*TTPT
) {
729 JOS
.attribute("depth", TTPT
->getDepth());
730 JOS
.attribute("index", TTPT
->getIndex());
731 attributeOnlyIfTrue("isPack", TTPT
->isParameterPack());
732 JOS
.attribute("decl", createBareDeclRef(TTPT
->getDecl()));
735 void JSONNodeDumper::VisitSubstTemplateTypeParmType(
736 const SubstTemplateTypeParmType
*STTPT
) {
737 JOS
.attribute("index", STTPT
->getIndex());
738 if (auto PackIndex
= STTPT
->getPackIndex())
739 JOS
.attribute("pack_index", *PackIndex
);
742 void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
743 const SubstTemplateTypeParmPackType
*T
) {
744 JOS
.attribute("index", T
->getIndex());
747 void JSONNodeDumper::VisitAutoType(const AutoType
*AT
) {
748 JOS
.attribute("undeduced", !AT
->isDeduced());
749 switch (AT
->getKeyword()) {
750 case AutoTypeKeyword::Auto
:
751 JOS
.attribute("typeKeyword", "auto");
753 case AutoTypeKeyword::DecltypeAuto
:
754 JOS
.attribute("typeKeyword", "decltype(auto)");
756 case AutoTypeKeyword::GNUAutoType
:
757 JOS
.attribute("typeKeyword", "__auto_type");
762 void JSONNodeDumper::VisitTemplateSpecializationType(
763 const TemplateSpecializationType
*TST
) {
764 attributeOnlyIfTrue("isAlias", TST
->isTypeAlias());
767 llvm::raw_string_ostream
OS(Str
);
768 TST
->getTemplateName().print(OS
, PrintPolicy
);
769 JOS
.attribute("templateName", OS
.str());
772 void JSONNodeDumper::VisitInjectedClassNameType(
773 const InjectedClassNameType
*ICNT
) {
774 JOS
.attribute("decl", createBareDeclRef(ICNT
->getDecl()));
777 void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType
*OIT
) {
778 JOS
.attribute("decl", createBareDeclRef(OIT
->getDecl()));
781 void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType
*PET
) {
782 if (std::optional
<unsigned> N
= PET
->getNumExpansions())
783 JOS
.attribute("numExpansions", *N
);
786 void JSONNodeDumper::VisitElaboratedType(const ElaboratedType
*ET
) {
787 if (const NestedNameSpecifier
*NNS
= ET
->getQualifier()) {
789 llvm::raw_string_ostream
OS(Str
);
790 NNS
->print(OS
, PrintPolicy
, /*ResolveTemplateArgs*/ true);
791 JOS
.attribute("qualifier", OS
.str());
793 if (const TagDecl
*TD
= ET
->getOwnedTagDecl())
794 JOS
.attribute("ownedTagDecl", createBareDeclRef(TD
));
797 void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType
*MQT
) {
798 JOS
.attribute("macroName", MQT
->getMacroIdentifier()->getName());
801 void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType
*MPT
) {
802 attributeOnlyIfTrue("isData", MPT
->isMemberDataPointer());
803 attributeOnlyIfTrue("isFunction", MPT
->isMemberFunctionPointer());
806 void JSONNodeDumper::VisitNamedDecl(const NamedDecl
*ND
) {
807 if (ND
&& ND
->getDeclName()) {
808 JOS
.attribute("name", ND
->getNameAsString());
809 // FIXME: There are likely other contexts in which it makes no sense to ask
810 // for a mangled name.
811 if (isa
<RequiresExprBodyDecl
>(ND
->getDeclContext()))
814 // If the declaration is dependent or is in a dependent context, then the
815 // mangling is unlikely to be meaningful (and in some cases may cause
816 // "don't know how to mangle this" assertion failures.
817 if (ND
->isTemplated())
820 // Mangled names are not meaningful for locals, and may not be well-defined
821 // in the case of VLAs.
822 auto *VD
= dyn_cast
<VarDecl
>(ND
);
823 if (VD
&& VD
->hasLocalStorage())
826 std::string MangledName
= ASTNameGen
.getName(ND
);
827 if (!MangledName
.empty())
828 JOS
.attribute("mangledName", MangledName
);
832 void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl
*TD
) {
834 JOS
.attribute("type", createQualType(TD
->getUnderlyingType()));
837 void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl
*TAD
) {
839 JOS
.attribute("type", createQualType(TAD
->getUnderlyingType()));
842 void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl
*ND
) {
844 attributeOnlyIfTrue("isInline", ND
->isInline());
845 attributeOnlyIfTrue("isNested", ND
->isNested());
846 if (!ND
->isOriginalNamespace())
847 JOS
.attribute("originalNamespace",
848 createBareDeclRef(ND
->getOriginalNamespace()));
851 void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl
*UDD
) {
852 JOS
.attribute("nominatedNamespace",
853 createBareDeclRef(UDD
->getNominatedNamespace()));
856 void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl
*NAD
) {
858 JOS
.attribute("aliasedNamespace",
859 createBareDeclRef(NAD
->getAliasedNamespace()));
862 void JSONNodeDumper::VisitUsingDecl(const UsingDecl
*UD
) {
864 if (const NestedNameSpecifier
*NNS
= UD
->getQualifier()) {
865 llvm::raw_string_ostream
SOS(Name
);
866 NNS
->print(SOS
, UD
->getASTContext().getPrintingPolicy());
868 Name
+= UD
->getNameAsString();
869 JOS
.attribute("name", Name
);
872 void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl
*UED
) {
873 JOS
.attribute("target", createBareDeclRef(UED
->getEnumDecl()));
876 void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl
*USD
) {
877 JOS
.attribute("target", createBareDeclRef(USD
->getTargetDecl()));
880 void JSONNodeDumper::VisitVarDecl(const VarDecl
*VD
) {
882 JOS
.attribute("type", createQualType(VD
->getType()));
883 if (const auto *P
= dyn_cast
<ParmVarDecl
>(VD
))
884 attributeOnlyIfTrue("explicitObjectParameter",
885 P
->isExplicitObjectParameter());
887 StorageClass SC
= VD
->getStorageClass();
889 JOS
.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC
));
890 switch (VD
->getTLSKind()) {
891 case VarDecl::TLS_Dynamic
: JOS
.attribute("tls", "dynamic"); break;
892 case VarDecl::TLS_Static
: JOS
.attribute("tls", "static"); break;
893 case VarDecl::TLS_None
: break;
895 attributeOnlyIfTrue("nrvo", VD
->isNRVOVariable());
896 attributeOnlyIfTrue("inline", VD
->isInline());
897 attributeOnlyIfTrue("constexpr", VD
->isConstexpr());
898 attributeOnlyIfTrue("modulePrivate", VD
->isModulePrivate());
900 switch (VD
->getInitStyle()) {
901 case VarDecl::CInit
: JOS
.attribute("init", "c"); break;
902 case VarDecl::CallInit
: JOS
.attribute("init", "call"); break;
903 case VarDecl::ListInit
: JOS
.attribute("init", "list"); break;
904 case VarDecl::ParenListInit
:
905 JOS
.attribute("init", "paren-list");
909 attributeOnlyIfTrue("isParameterPack", VD
->isParameterPack());
912 void JSONNodeDumper::VisitFieldDecl(const FieldDecl
*FD
) {
914 JOS
.attribute("type", createQualType(FD
->getType()));
915 attributeOnlyIfTrue("mutable", FD
->isMutable());
916 attributeOnlyIfTrue("modulePrivate", FD
->isModulePrivate());
917 attributeOnlyIfTrue("isBitfield", FD
->isBitField());
918 attributeOnlyIfTrue("hasInClassInitializer", FD
->hasInClassInitializer());
921 void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl
*FD
) {
923 JOS
.attribute("type", createQualType(FD
->getType()));
924 StorageClass SC
= FD
->getStorageClass();
926 JOS
.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC
));
927 attributeOnlyIfTrue("inline", FD
->isInlineSpecified());
928 attributeOnlyIfTrue("virtual", FD
->isVirtualAsWritten());
929 attributeOnlyIfTrue("pure", FD
->isPure());
930 attributeOnlyIfTrue("explicitlyDeleted", FD
->isDeletedAsWritten());
931 attributeOnlyIfTrue("constexpr", FD
->isConstexpr());
932 attributeOnlyIfTrue("variadic", FD
->isVariadic());
933 attributeOnlyIfTrue("immediate", FD
->isImmediateFunction());
935 if (FD
->isDefaulted())
936 JOS
.attribute("explicitlyDefaulted",
937 FD
->isDeleted() ? "deleted" : "default");
940 void JSONNodeDumper::VisitEnumDecl(const EnumDecl
*ED
) {
943 JOS
.attribute("fixedUnderlyingType", createQualType(ED
->getIntegerType()));
945 JOS
.attribute("scopedEnumTag",
946 ED
->isScopedUsingClassTag() ? "class" : "struct");
948 void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl
*ECD
) {
950 JOS
.attribute("type", createQualType(ECD
->getType()));
953 void JSONNodeDumper::VisitRecordDecl(const RecordDecl
*RD
) {
955 JOS
.attribute("tagUsed", RD
->getKindName());
956 attributeOnlyIfTrue("completeDefinition", RD
->isCompleteDefinition());
958 void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl
*RD
) {
961 // All other information requires a complete definition.
962 if (!RD
->isCompleteDefinition())
965 JOS
.attribute("definitionData", createCXXRecordDefinitionData(RD
));
966 if (RD
->getNumBases()) {
967 JOS
.attributeArray("bases", [this, RD
] {
968 for (const auto &Spec
: RD
->bases())
969 JOS
.value(createCXXBaseSpecifier(Spec
));
974 void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl
*D
) {
976 JOS
.attribute("bufferKind", D
->isCBuffer() ? "cbuffer" : "tbuffer");
979 void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl
*D
) {
981 JOS
.attribute("tagUsed", D
->wasDeclaredWithTypename() ? "typename" : "class");
982 JOS
.attribute("depth", D
->getDepth());
983 JOS
.attribute("index", D
->getIndex());
984 attributeOnlyIfTrue("isParameterPack", D
->isParameterPack());
986 if (D
->hasDefaultArgument())
987 JOS
.attributeObject("defaultArg", [=] {
988 Visit(D
->getDefaultArgument(), SourceRange(),
989 D
->getDefaultArgStorage().getInheritedFrom(),
990 D
->defaultArgumentWasInherited() ? "inherited from" : "previous");
994 void JSONNodeDumper::VisitNonTypeTemplateParmDecl(
995 const NonTypeTemplateParmDecl
*D
) {
997 JOS
.attribute("type", createQualType(D
->getType()));
998 JOS
.attribute("depth", D
->getDepth());
999 JOS
.attribute("index", D
->getIndex());
1000 attributeOnlyIfTrue("isParameterPack", D
->isParameterPack());
1002 if (D
->hasDefaultArgument())
1003 JOS
.attributeObject("defaultArg", [=] {
1004 Visit(D
->getDefaultArgument(), SourceRange(),
1005 D
->getDefaultArgStorage().getInheritedFrom(),
1006 D
->defaultArgumentWasInherited() ? "inherited from" : "previous");
1010 void JSONNodeDumper::VisitTemplateTemplateParmDecl(
1011 const TemplateTemplateParmDecl
*D
) {
1013 JOS
.attribute("depth", D
->getDepth());
1014 JOS
.attribute("index", D
->getIndex());
1015 attributeOnlyIfTrue("isParameterPack", D
->isParameterPack());
1017 if (D
->hasDefaultArgument())
1018 JOS
.attributeObject("defaultArg", [=] {
1019 const auto *InheritedFrom
= D
->getDefaultArgStorage().getInheritedFrom();
1020 Visit(D
->getDefaultArgument().getArgument(),
1021 InheritedFrom
? InheritedFrom
->getSourceRange() : SourceLocation
{},
1023 D
->defaultArgumentWasInherited() ? "inherited from" : "previous");
1027 void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl
*LSD
) {
1029 switch (LSD
->getLanguage()) {
1030 case LinkageSpecLanguageIDs::C
:
1033 case LinkageSpecLanguageIDs::CXX
:
1037 JOS
.attribute("language", Lang
);
1038 attributeOnlyIfTrue("hasBraces", LSD
->hasBraces());
1041 void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl
*ASD
) {
1042 JOS
.attribute("access", createAccessSpecifier(ASD
->getAccess()));
1045 void JSONNodeDumper::VisitFriendDecl(const FriendDecl
*FD
) {
1046 if (const TypeSourceInfo
*T
= FD
->getFriendType())
1047 JOS
.attribute("type", createQualType(T
->getType()));
1050 void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl
*D
) {
1052 JOS
.attribute("type", createQualType(D
->getType()));
1053 attributeOnlyIfTrue("synthesized", D
->getSynthesize());
1054 switch (D
->getAccessControl()) {
1055 case ObjCIvarDecl::None
: JOS
.attribute("access", "none"); break;
1056 case ObjCIvarDecl::Private
: JOS
.attribute("access", "private"); break;
1057 case ObjCIvarDecl::Protected
: JOS
.attribute("access", "protected"); break;
1058 case ObjCIvarDecl::Public
: JOS
.attribute("access", "public"); break;
1059 case ObjCIvarDecl::Package
: JOS
.attribute("access", "package"); break;
1063 void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl
*D
) {
1065 JOS
.attribute("returnType", createQualType(D
->getReturnType()));
1066 JOS
.attribute("instance", D
->isInstanceMethod());
1067 attributeOnlyIfTrue("variadic", D
->isVariadic());
1070 void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl
*D
) {
1072 JOS
.attribute("type", createQualType(D
->getUnderlyingType()));
1073 attributeOnlyIfTrue("bounded", D
->hasExplicitBound());
1074 switch (D
->getVariance()) {
1075 case ObjCTypeParamVariance::Invariant
:
1077 case ObjCTypeParamVariance::Covariant
:
1078 JOS
.attribute("variance", "covariant");
1080 case ObjCTypeParamVariance::Contravariant
:
1081 JOS
.attribute("variance", "contravariant");
1086 void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl
*D
) {
1088 JOS
.attribute("interface", createBareDeclRef(D
->getClassInterface()));
1089 JOS
.attribute("implementation", createBareDeclRef(D
->getImplementation()));
1091 llvm::json::Array Protocols
;
1092 for (const auto* P
: D
->protocols())
1093 Protocols
.push_back(createBareDeclRef(P
));
1094 if (!Protocols
.empty())
1095 JOS
.attribute("protocols", std::move(Protocols
));
1098 void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl
*D
) {
1100 JOS
.attribute("interface", createBareDeclRef(D
->getClassInterface()));
1101 JOS
.attribute("categoryDecl", createBareDeclRef(D
->getCategoryDecl()));
1104 void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl
*D
) {
1107 llvm::json::Array Protocols
;
1108 for (const auto *P
: D
->protocols())
1109 Protocols
.push_back(createBareDeclRef(P
));
1110 if (!Protocols
.empty())
1111 JOS
.attribute("protocols", std::move(Protocols
));
1114 void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl
*D
) {
1116 JOS
.attribute("super", createBareDeclRef(D
->getSuperClass()));
1117 JOS
.attribute("implementation", createBareDeclRef(D
->getImplementation()));
1119 llvm::json::Array Protocols
;
1120 for (const auto* P
: D
->protocols())
1121 Protocols
.push_back(createBareDeclRef(P
));
1122 if (!Protocols
.empty())
1123 JOS
.attribute("protocols", std::move(Protocols
));
1126 void JSONNodeDumper::VisitObjCImplementationDecl(
1127 const ObjCImplementationDecl
*D
) {
1129 JOS
.attribute("super", createBareDeclRef(D
->getSuperClass()));
1130 JOS
.attribute("interface", createBareDeclRef(D
->getClassInterface()));
1133 void JSONNodeDumper::VisitObjCCompatibleAliasDecl(
1134 const ObjCCompatibleAliasDecl
*D
) {
1136 JOS
.attribute("interface", createBareDeclRef(D
->getClassInterface()));
1139 void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl
*D
) {
1141 JOS
.attribute("type", createQualType(D
->getType()));
1143 switch (D
->getPropertyImplementation()) {
1144 case ObjCPropertyDecl::None
: break;
1145 case ObjCPropertyDecl::Required
: JOS
.attribute("control", "required"); break;
1146 case ObjCPropertyDecl::Optional
: JOS
.attribute("control", "optional"); break;
1149 ObjCPropertyAttribute::Kind Attrs
= D
->getPropertyAttributes();
1150 if (Attrs
!= ObjCPropertyAttribute::kind_noattr
) {
1151 if (Attrs
& ObjCPropertyAttribute::kind_getter
)
1152 JOS
.attribute("getter", createBareDeclRef(D
->getGetterMethodDecl()));
1153 if (Attrs
& ObjCPropertyAttribute::kind_setter
)
1154 JOS
.attribute("setter", createBareDeclRef(D
->getSetterMethodDecl()));
1155 attributeOnlyIfTrue("readonly",
1156 Attrs
& ObjCPropertyAttribute::kind_readonly
);
1157 attributeOnlyIfTrue("assign", Attrs
& ObjCPropertyAttribute::kind_assign
);
1158 attributeOnlyIfTrue("readwrite",
1159 Attrs
& ObjCPropertyAttribute::kind_readwrite
);
1160 attributeOnlyIfTrue("retain", Attrs
& ObjCPropertyAttribute::kind_retain
);
1161 attributeOnlyIfTrue("copy", Attrs
& ObjCPropertyAttribute::kind_copy
);
1162 attributeOnlyIfTrue("nonatomic",
1163 Attrs
& ObjCPropertyAttribute::kind_nonatomic
);
1164 attributeOnlyIfTrue("atomic", Attrs
& ObjCPropertyAttribute::kind_atomic
);
1165 attributeOnlyIfTrue("weak", Attrs
& ObjCPropertyAttribute::kind_weak
);
1166 attributeOnlyIfTrue("strong", Attrs
& ObjCPropertyAttribute::kind_strong
);
1167 attributeOnlyIfTrue("unsafe_unretained",
1168 Attrs
& ObjCPropertyAttribute::kind_unsafe_unretained
);
1169 attributeOnlyIfTrue("class", Attrs
& ObjCPropertyAttribute::kind_class
);
1170 attributeOnlyIfTrue("direct", Attrs
& ObjCPropertyAttribute::kind_direct
);
1171 attributeOnlyIfTrue("nullability",
1172 Attrs
& ObjCPropertyAttribute::kind_nullability
);
1173 attributeOnlyIfTrue("null_resettable",
1174 Attrs
& ObjCPropertyAttribute::kind_null_resettable
);
1178 void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl
*D
) {
1179 VisitNamedDecl(D
->getPropertyDecl());
1180 JOS
.attribute("implKind", D
->getPropertyImplementation() ==
1181 ObjCPropertyImplDecl::Synthesize
1184 JOS
.attribute("propertyDecl", createBareDeclRef(D
->getPropertyDecl()));
1185 JOS
.attribute("ivarDecl", createBareDeclRef(D
->getPropertyIvarDecl()));
1188 void JSONNodeDumper::VisitBlockDecl(const BlockDecl
*D
) {
1189 attributeOnlyIfTrue("variadic", D
->isVariadic());
1190 attributeOnlyIfTrue("capturesThis", D
->capturesCXXThis());
1193 void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr
*AE
) {
1194 JOS
.attribute("name", AE
->getOpAsString());
1197 void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr
*OEE
) {
1198 JOS
.attribute("encodedType", createQualType(OEE
->getEncodedType()));
1201 void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr
*OME
) {
1203 llvm::raw_string_ostream
OS(Str
);
1205 OME
->getSelector().print(OS
);
1206 JOS
.attribute("selector", OS
.str());
1208 switch (OME
->getReceiverKind()) {
1209 case ObjCMessageExpr::Instance
:
1210 JOS
.attribute("receiverKind", "instance");
1212 case ObjCMessageExpr::Class
:
1213 JOS
.attribute("receiverKind", "class");
1214 JOS
.attribute("classType", createQualType(OME
->getClassReceiver()));
1216 case ObjCMessageExpr::SuperInstance
:
1217 JOS
.attribute("receiverKind", "super (instance)");
1218 JOS
.attribute("superType", createQualType(OME
->getSuperType()));
1220 case ObjCMessageExpr::SuperClass
:
1221 JOS
.attribute("receiverKind", "super (class)");
1222 JOS
.attribute("superType", createQualType(OME
->getSuperType()));
1226 QualType CallReturnTy
= OME
->getCallReturnType(Ctx
);
1227 if (OME
->getType() != CallReturnTy
)
1228 JOS
.attribute("callReturnType", createQualType(CallReturnTy
));
1231 void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr
*OBE
) {
1232 if (const ObjCMethodDecl
*MD
= OBE
->getBoxingMethod()) {
1234 llvm::raw_string_ostream
OS(Str
);
1236 MD
->getSelector().print(OS
);
1237 JOS
.attribute("selector", OS
.str());
1241 void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr
*OSE
) {
1243 llvm::raw_string_ostream
OS(Str
);
1245 OSE
->getSelector().print(OS
);
1246 JOS
.attribute("selector", OS
.str());
1249 void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr
*OPE
) {
1250 JOS
.attribute("protocol", createBareDeclRef(OPE
->getProtocol()));
1253 void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr
*OPRE
) {
1254 if (OPRE
->isImplicitProperty()) {
1255 JOS
.attribute("propertyKind", "implicit");
1256 if (const ObjCMethodDecl
*MD
= OPRE
->getImplicitPropertyGetter())
1257 JOS
.attribute("getter", createBareDeclRef(MD
));
1258 if (const ObjCMethodDecl
*MD
= OPRE
->getImplicitPropertySetter())
1259 JOS
.attribute("setter", createBareDeclRef(MD
));
1261 JOS
.attribute("propertyKind", "explicit");
1262 JOS
.attribute("property", createBareDeclRef(OPRE
->getExplicitProperty()));
1265 attributeOnlyIfTrue("isSuperReceiver", OPRE
->isSuperReceiver());
1266 attributeOnlyIfTrue("isMessagingGetter", OPRE
->isMessagingGetter());
1267 attributeOnlyIfTrue("isMessagingSetter", OPRE
->isMessagingSetter());
1270 void JSONNodeDumper::VisitObjCSubscriptRefExpr(
1271 const ObjCSubscriptRefExpr
*OSRE
) {
1272 JOS
.attribute("subscriptKind",
1273 OSRE
->isArraySubscriptRefExpr() ? "array" : "dictionary");
1275 if (const ObjCMethodDecl
*MD
= OSRE
->getAtIndexMethodDecl())
1276 JOS
.attribute("getter", createBareDeclRef(MD
));
1277 if (const ObjCMethodDecl
*MD
= OSRE
->setAtIndexMethodDecl())
1278 JOS
.attribute("setter", createBareDeclRef(MD
));
1281 void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr
*OIRE
) {
1282 JOS
.attribute("decl", createBareDeclRef(OIRE
->getDecl()));
1283 attributeOnlyIfTrue("isFreeIvar", OIRE
->isFreeIvar());
1284 JOS
.attribute("isArrow", OIRE
->isArrow());
1287 void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr
*OBLE
) {
1288 JOS
.attribute("value", OBLE
->getValue() ? "__objc_yes" : "__objc_no");
1291 void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr
*DRE
) {
1292 JOS
.attribute("referencedDecl", createBareDeclRef(DRE
->getDecl()));
1293 if (DRE
->getDecl() != DRE
->getFoundDecl())
1294 JOS
.attribute("foundReferencedDecl",
1295 createBareDeclRef(DRE
->getFoundDecl()));
1296 switch (DRE
->isNonOdrUse()) {
1297 case NOUR_None
: break;
1298 case NOUR_Unevaluated
: JOS
.attribute("nonOdrUseReason", "unevaluated"); break;
1299 case NOUR_Constant
: JOS
.attribute("nonOdrUseReason", "constant"); break;
1300 case NOUR_Discarded
: JOS
.attribute("nonOdrUseReason", "discarded"); break;
1302 attributeOnlyIfTrue("isImmediateEscalating", DRE
->isImmediateEscalating());
1305 void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
1306 const SYCLUniqueStableNameExpr
*E
) {
1307 JOS
.attribute("typeSourceInfo",
1308 createQualType(E
->getTypeSourceInfo()->getType()));
1311 void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr
*PE
) {
1312 JOS
.attribute("name", PredefinedExpr::getIdentKindName(PE
->getIdentKind()));
1315 void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator
*UO
) {
1316 JOS
.attribute("isPostfix", UO
->isPostfix());
1317 JOS
.attribute("opcode", UnaryOperator::getOpcodeStr(UO
->getOpcode()));
1318 if (!UO
->canOverflow())
1319 JOS
.attribute("canOverflow", false);
1322 void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator
*BO
) {
1323 JOS
.attribute("opcode", BinaryOperator::getOpcodeStr(BO
->getOpcode()));
1326 void JSONNodeDumper::VisitCompoundAssignOperator(
1327 const CompoundAssignOperator
*CAO
) {
1328 VisitBinaryOperator(CAO
);
1329 JOS
.attribute("computeLHSType", createQualType(CAO
->getComputationLHSType()));
1330 JOS
.attribute("computeResultType",
1331 createQualType(CAO
->getComputationResultType()));
1334 void JSONNodeDumper::VisitMemberExpr(const MemberExpr
*ME
) {
1335 // Note, we always write this Boolean field because the information it conveys
1336 // is critical to understanding the AST node.
1337 ValueDecl
*VD
= ME
->getMemberDecl();
1338 JOS
.attribute("name", VD
&& VD
->getDeclName() ? VD
->getNameAsString() : "");
1339 JOS
.attribute("isArrow", ME
->isArrow());
1340 JOS
.attribute("referencedMemberDecl", createPointerRepresentation(VD
));
1341 switch (ME
->isNonOdrUse()) {
1342 case NOUR_None
: break;
1343 case NOUR_Unevaluated
: JOS
.attribute("nonOdrUseReason", "unevaluated"); break;
1344 case NOUR_Constant
: JOS
.attribute("nonOdrUseReason", "constant"); break;
1345 case NOUR_Discarded
: JOS
.attribute("nonOdrUseReason", "discarded"); break;
1349 void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr
*NE
) {
1350 attributeOnlyIfTrue("isGlobal", NE
->isGlobalNew());
1351 attributeOnlyIfTrue("isArray", NE
->isArray());
1352 attributeOnlyIfTrue("isPlacement", NE
->getNumPlacementArgs() != 0);
1353 switch (NE
->getInitializationStyle()) {
1354 case CXXNewExpr::NoInit
: break;
1355 case CXXNewExpr::CallInit
: JOS
.attribute("initStyle", "call"); break;
1356 case CXXNewExpr::ListInit
: JOS
.attribute("initStyle", "list"); break;
1358 if (const FunctionDecl
*FD
= NE
->getOperatorNew())
1359 JOS
.attribute("operatorNewDecl", createBareDeclRef(FD
));
1360 if (const FunctionDecl
*FD
= NE
->getOperatorDelete())
1361 JOS
.attribute("operatorDeleteDecl", createBareDeclRef(FD
));
1363 void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr
*DE
) {
1364 attributeOnlyIfTrue("isGlobal", DE
->isGlobalDelete());
1365 attributeOnlyIfTrue("isArray", DE
->isArrayForm());
1366 attributeOnlyIfTrue("isArrayAsWritten", DE
->isArrayFormAsWritten());
1367 if (const FunctionDecl
*FD
= DE
->getOperatorDelete())
1368 JOS
.attribute("operatorDeleteDecl", createBareDeclRef(FD
));
1371 void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr
*TE
) {
1372 attributeOnlyIfTrue("implicit", TE
->isImplicit());
1375 void JSONNodeDumper::VisitCastExpr(const CastExpr
*CE
) {
1376 JOS
.attribute("castKind", CE
->getCastKindName());
1377 llvm::json::Array Path
= createCastPath(CE
);
1379 JOS
.attribute("path", std::move(Path
));
1380 // FIXME: This may not be useful information as it can be obtusely gleaned
1381 // from the inner[] array.
1382 if (const NamedDecl
*ND
= CE
->getConversionFunction())
1383 JOS
.attribute("conversionFunc", createBareDeclRef(ND
));
1386 void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr
*ICE
) {
1388 attributeOnlyIfTrue("isPartOfExplicitCast", ICE
->isPartOfExplicitCast());
1391 void JSONNodeDumper::VisitCallExpr(const CallExpr
*CE
) {
1392 attributeOnlyIfTrue("adl", CE
->usesADL());
1395 void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
1396 const UnaryExprOrTypeTraitExpr
*TTE
) {
1397 JOS
.attribute("name", getTraitSpelling(TTE
->getKind()));
1398 if (TTE
->isArgumentType())
1399 JOS
.attribute("argType", createQualType(TTE
->getArgumentType()));
1402 void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr
*SOPE
) {
1403 VisitNamedDecl(SOPE
->getPack());
1406 void JSONNodeDumper::VisitUnresolvedLookupExpr(
1407 const UnresolvedLookupExpr
*ULE
) {
1408 JOS
.attribute("usesADL", ULE
->requiresADL());
1409 JOS
.attribute("name", ULE
->getName().getAsString());
1411 JOS
.attributeArray("lookups", [this, ULE
] {
1412 for (const NamedDecl
*D
: ULE
->decls())
1413 JOS
.value(createBareDeclRef(D
));
1417 void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr
*ALE
) {
1418 JOS
.attribute("name", ALE
->getLabel()->getName());
1419 JOS
.attribute("labelDeclId", createPointerRepresentation(ALE
->getLabel()));
1422 void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr
*CTE
) {
1423 if (CTE
->isTypeOperand()) {
1424 QualType Adjusted
= CTE
->getTypeOperand(Ctx
);
1425 QualType Unadjusted
= CTE
->getTypeOperandSourceInfo()->getType();
1426 JOS
.attribute("typeArg", createQualType(Unadjusted
));
1427 if (Adjusted
!= Unadjusted
)
1428 JOS
.attribute("adjustedTypeArg", createQualType(Adjusted
));
1432 void JSONNodeDumper::VisitConstantExpr(const ConstantExpr
*CE
) {
1433 if (CE
->getResultAPValueKind() != APValue::None
)
1434 Visit(CE
->getAPValueResult(), CE
->getType());
1437 void JSONNodeDumper::VisitInitListExpr(const InitListExpr
*ILE
) {
1438 if (const FieldDecl
*FD
= ILE
->getInitializedFieldInUnion())
1439 JOS
.attribute("field", createBareDeclRef(FD
));
1442 void JSONNodeDumper::VisitGenericSelectionExpr(
1443 const GenericSelectionExpr
*GSE
) {
1444 attributeOnlyIfTrue("resultDependent", GSE
->isResultDependent());
1447 void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(
1448 const CXXUnresolvedConstructExpr
*UCE
) {
1449 if (UCE
->getType() != UCE
->getTypeAsWritten())
1450 JOS
.attribute("typeAsWritten", createQualType(UCE
->getTypeAsWritten()));
1451 attributeOnlyIfTrue("list", UCE
->isListInitialization());
1454 void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr
*CE
) {
1455 CXXConstructorDecl
*Ctor
= CE
->getConstructor();
1456 JOS
.attribute("ctorType", createQualType(Ctor
->getType()));
1457 attributeOnlyIfTrue("elidable", CE
->isElidable());
1458 attributeOnlyIfTrue("list", CE
->isListInitialization());
1459 attributeOnlyIfTrue("initializer_list", CE
->isStdInitListInitialization());
1460 attributeOnlyIfTrue("zeroing", CE
->requiresZeroInitialization());
1461 attributeOnlyIfTrue("hadMultipleCandidates", CE
->hadMultipleCandidates());
1462 attributeOnlyIfTrue("isImmediateEscalating", CE
->isImmediateEscalating());
1464 switch (CE
->getConstructionKind()) {
1465 case CXXConstructExpr::CK_Complete
:
1466 JOS
.attribute("constructionKind", "complete");
1468 case CXXConstructExpr::CK_Delegating
:
1469 JOS
.attribute("constructionKind", "delegating");
1471 case CXXConstructExpr::CK_NonVirtualBase
:
1472 JOS
.attribute("constructionKind", "non-virtual base");
1474 case CXXConstructExpr::CK_VirtualBase
:
1475 JOS
.attribute("constructionKind", "virtual base");
1480 void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups
*EWC
) {
1481 attributeOnlyIfTrue("cleanupsHaveSideEffects",
1482 EWC
->cleanupsHaveSideEffects());
1483 if (EWC
->getNumObjects()) {
1484 JOS
.attributeArray("cleanups", [this, EWC
] {
1485 for (const ExprWithCleanups::CleanupObject
&CO
: EWC
->getObjects())
1486 if (auto *BD
= CO
.dyn_cast
<BlockDecl
*>()) {
1487 JOS
.value(createBareDeclRef(BD
));
1488 } else if (auto *CLE
= CO
.dyn_cast
<CompoundLiteralExpr
*>()) {
1489 llvm::json::Object Obj
;
1490 Obj
["id"] = createPointerRepresentation(CLE
);
1491 Obj
["kind"] = CLE
->getStmtClassName();
1492 JOS
.value(std::move(Obj
));
1494 llvm_unreachable("unexpected cleanup object type");
1500 void JSONNodeDumper::VisitCXXBindTemporaryExpr(
1501 const CXXBindTemporaryExpr
*BTE
) {
1502 const CXXTemporary
*Temp
= BTE
->getTemporary();
1503 JOS
.attribute("temp", createPointerRepresentation(Temp
));
1504 if (const CXXDestructorDecl
*Dtor
= Temp
->getDestructor())
1505 JOS
.attribute("dtor", createBareDeclRef(Dtor
));
1508 void JSONNodeDumper::VisitMaterializeTemporaryExpr(
1509 const MaterializeTemporaryExpr
*MTE
) {
1510 if (const ValueDecl
*VD
= MTE
->getExtendingDecl())
1511 JOS
.attribute("extendingDecl", createBareDeclRef(VD
));
1513 switch (MTE
->getStorageDuration()) {
1515 JOS
.attribute("storageDuration", "automatic");
1518 JOS
.attribute("storageDuration", "dynamic");
1520 case SD_FullExpression
:
1521 JOS
.attribute("storageDuration", "full expression");
1524 JOS
.attribute("storageDuration", "static");
1527 JOS
.attribute("storageDuration", "thread");
1531 attributeOnlyIfTrue("boundToLValueRef", MTE
->isBoundToLvalueReference());
1534 void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
1535 const CXXDependentScopeMemberExpr
*DSME
) {
1536 JOS
.attribute("isArrow", DSME
->isArrow());
1537 JOS
.attribute("member", DSME
->getMember().getAsString());
1538 attributeOnlyIfTrue("hasTemplateKeyword", DSME
->hasTemplateKeyword());
1539 attributeOnlyIfTrue("hasExplicitTemplateArgs",
1540 DSME
->hasExplicitTemplateArgs());
1542 if (DSME
->getNumTemplateArgs()) {
1543 JOS
.attributeArray("explicitTemplateArgs", [DSME
, this] {
1544 for (const TemplateArgumentLoc
&TAL
: DSME
->template_arguments())
1546 [&TAL
, this] { Visit(TAL
.getArgument(), TAL
.getSourceRange()); });
1551 void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr
*RE
) {
1552 if (!RE
->isValueDependent())
1553 JOS
.attribute("satisfied", RE
->isSatisfied());
1556 void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral
*IL
) {
1557 llvm::SmallString
<16> Buffer
;
1558 IL
->getValue().toString(Buffer
,
1559 /*Radix=*/10, IL
->getType()->isSignedIntegerType());
1560 JOS
.attribute("value", Buffer
);
1562 void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral
*CL
) {
1563 // FIXME: This should probably print the character literal as a string,
1564 // rather than as a numerical value. It would be nice if the behavior matched
1565 // what we do to print a string literal; right now, it is impossible to tell
1566 // the difference between 'a' and L'a' in C from the JSON output.
1567 JOS
.attribute("value", CL
->getValue());
1569 void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral
*FPL
) {
1570 JOS
.attribute("value", FPL
->getValueAsString(/*Radix=*/10));
1572 void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral
*FL
) {
1573 llvm::SmallString
<16> Buffer
;
1574 FL
->getValue().toString(Buffer
);
1575 JOS
.attribute("value", Buffer
);
1577 void JSONNodeDumper::VisitStringLiteral(const StringLiteral
*SL
) {
1579 llvm::raw_string_ostream
SS(Buffer
);
1580 SL
->outputString(SS
);
1581 JOS
.attribute("value", SS
.str());
1583 void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr
*BLE
) {
1584 JOS
.attribute("value", BLE
->getValue());
1587 void JSONNodeDumper::VisitIfStmt(const IfStmt
*IS
) {
1588 attributeOnlyIfTrue("hasInit", IS
->hasInitStorage());
1589 attributeOnlyIfTrue("hasVar", IS
->hasVarStorage());
1590 attributeOnlyIfTrue("hasElse", IS
->hasElseStorage());
1591 attributeOnlyIfTrue("isConstexpr", IS
->isConstexpr());
1592 attributeOnlyIfTrue("isConsteval", IS
->isConsteval());
1593 attributeOnlyIfTrue("constevalIsNegated", IS
->isNegatedConsteval());
1596 void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt
*SS
) {
1597 attributeOnlyIfTrue("hasInit", SS
->hasInitStorage());
1598 attributeOnlyIfTrue("hasVar", SS
->hasVarStorage());
1600 void JSONNodeDumper::VisitCaseStmt(const CaseStmt
*CS
) {
1601 attributeOnlyIfTrue("isGNURange", CS
->caseStmtIsGNURange());
1604 void JSONNodeDumper::VisitLabelStmt(const LabelStmt
*LS
) {
1605 JOS
.attribute("name", LS
->getName());
1606 JOS
.attribute("declId", createPointerRepresentation(LS
->getDecl()));
1607 attributeOnlyIfTrue("sideEntry", LS
->isSideEntry());
1609 void JSONNodeDumper::VisitGotoStmt(const GotoStmt
*GS
) {
1610 JOS
.attribute("targetLabelDeclId",
1611 createPointerRepresentation(GS
->getLabel()));
1614 void JSONNodeDumper::VisitWhileStmt(const WhileStmt
*WS
) {
1615 attributeOnlyIfTrue("hasVar", WS
->hasVarStorage());
1618 void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt
* OACS
) {
1619 // FIXME: it would be nice for the ASTNodeTraverser would handle the catch
1620 // parameter the same way for C++ and ObjC rather. In this case, C++ gets a
1621 // null child node and ObjC gets no child node.
1622 attributeOnlyIfTrue("isCatchAll", OACS
->getCatchParamDecl() == nullptr);
1625 void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument
&TA
) {
1626 JOS
.attribute("isNull", true);
1628 void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument
&TA
) {
1629 JOS
.attribute("type", createQualType(TA
.getAsType()));
1631 void JSONNodeDumper::VisitDeclarationTemplateArgument(
1632 const TemplateArgument
&TA
) {
1633 JOS
.attribute("decl", createBareDeclRef(TA
.getAsDecl()));
1635 void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument
&TA
) {
1636 JOS
.attribute("isNullptr", true);
1638 void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument
&TA
) {
1639 JOS
.attribute("value", TA
.getAsIntegral().getSExtValue());
1641 void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument
&TA
) {
1642 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1643 // the output format.
1645 void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
1646 const TemplateArgument
&TA
) {
1647 // FIXME: cannot just call dump() on the argument, as that doesn't specify
1648 // the output format.
1650 void JSONNodeDumper::VisitExpressionTemplateArgument(
1651 const TemplateArgument
&TA
) {
1652 JOS
.attribute("isExpr", true);
1654 void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument
&TA
) {
1655 JOS
.attribute("isPack", true);
1658 StringRef
JSONNodeDumper::getCommentCommandName(unsigned CommandID
) const {
1660 return Traits
->getCommandInfo(CommandID
)->Name
;
1661 if (const comments::CommandInfo
*Info
=
1662 comments::CommandTraits::getBuiltinCommandInfo(CommandID
))
1667 void JSONNodeDumper::visitTextComment(const comments::TextComment
*C
,
1668 const comments::FullComment
*) {
1669 JOS
.attribute("text", C
->getText());
1672 void JSONNodeDumper::visitInlineCommandComment(
1673 const comments::InlineCommandComment
*C
, const comments::FullComment
*) {
1674 JOS
.attribute("name", getCommentCommandName(C
->getCommandID()));
1676 switch (C
->getRenderKind()) {
1677 case comments::InlineCommandComment::RenderNormal
:
1678 JOS
.attribute("renderKind", "normal");
1680 case comments::InlineCommandComment::RenderBold
:
1681 JOS
.attribute("renderKind", "bold");
1683 case comments::InlineCommandComment::RenderEmphasized
:
1684 JOS
.attribute("renderKind", "emphasized");
1686 case comments::InlineCommandComment::RenderMonospaced
:
1687 JOS
.attribute("renderKind", "monospaced");
1689 case comments::InlineCommandComment::RenderAnchor
:
1690 JOS
.attribute("renderKind", "anchor");
1694 llvm::json::Array Args
;
1695 for (unsigned I
= 0, E
= C
->getNumArgs(); I
< E
; ++I
)
1696 Args
.push_back(C
->getArgText(I
));
1699 JOS
.attribute("args", std::move(Args
));
1702 void JSONNodeDumper::visitHTMLStartTagComment(
1703 const comments::HTMLStartTagComment
*C
, const comments::FullComment
*) {
1704 JOS
.attribute("name", C
->getTagName());
1705 attributeOnlyIfTrue("selfClosing", C
->isSelfClosing());
1706 attributeOnlyIfTrue("malformed", C
->isMalformed());
1708 llvm::json::Array Attrs
;
1709 for (unsigned I
= 0, E
= C
->getNumAttrs(); I
< E
; ++I
)
1711 {{"name", C
->getAttr(I
).Name
}, {"value", C
->getAttr(I
).Value
}});
1714 JOS
.attribute("attrs", std::move(Attrs
));
1717 void JSONNodeDumper::visitHTMLEndTagComment(
1718 const comments::HTMLEndTagComment
*C
, const comments::FullComment
*) {
1719 JOS
.attribute("name", C
->getTagName());
1722 void JSONNodeDumper::visitBlockCommandComment(
1723 const comments::BlockCommandComment
*C
, const comments::FullComment
*) {
1724 JOS
.attribute("name", getCommentCommandName(C
->getCommandID()));
1726 llvm::json::Array Args
;
1727 for (unsigned I
= 0, E
= C
->getNumArgs(); I
< E
; ++I
)
1728 Args
.push_back(C
->getArgText(I
));
1731 JOS
.attribute("args", std::move(Args
));
1734 void JSONNodeDumper::visitParamCommandComment(
1735 const comments::ParamCommandComment
*C
, const comments::FullComment
*FC
) {
1736 switch (C
->getDirection()) {
1737 case comments::ParamCommandComment::In
:
1738 JOS
.attribute("direction", "in");
1740 case comments::ParamCommandComment::Out
:
1741 JOS
.attribute("direction", "out");
1743 case comments::ParamCommandComment::InOut
:
1744 JOS
.attribute("direction", "in,out");
1747 attributeOnlyIfTrue("explicit", C
->isDirectionExplicit());
1749 if (C
->hasParamName())
1750 JOS
.attribute("param", C
->isParamIndexValid() ? C
->getParamName(FC
)
1751 : C
->getParamNameAsWritten());
1753 if (C
->isParamIndexValid() && !C
->isVarArgParam())
1754 JOS
.attribute("paramIdx", C
->getParamIndex());
1757 void JSONNodeDumper::visitTParamCommandComment(
1758 const comments::TParamCommandComment
*C
, const comments::FullComment
*FC
) {
1759 if (C
->hasParamName())
1760 JOS
.attribute("param", C
->isPositionValid() ? C
->getParamName(FC
)
1761 : C
->getParamNameAsWritten());
1762 if (C
->isPositionValid()) {
1763 llvm::json::Array Positions
;
1764 for (unsigned I
= 0, E
= C
->getDepth(); I
< E
; ++I
)
1765 Positions
.push_back(C
->getIndex(I
));
1767 if (!Positions
.empty())
1768 JOS
.attribute("positions", std::move(Positions
));
1772 void JSONNodeDumper::visitVerbatimBlockComment(
1773 const comments::VerbatimBlockComment
*C
, const comments::FullComment
*) {
1774 JOS
.attribute("name", getCommentCommandName(C
->getCommandID()));
1775 JOS
.attribute("closeName", C
->getCloseName());
1778 void JSONNodeDumper::visitVerbatimBlockLineComment(
1779 const comments::VerbatimBlockLineComment
*C
,
1780 const comments::FullComment
*) {
1781 JOS
.attribute("text", C
->getText());
1784 void JSONNodeDumper::visitVerbatimLineComment(
1785 const comments::VerbatimLineComment
*C
, const comments::FullComment
*) {
1786 JOS
.attribute("text", C
->getText());
1789 llvm::json::Object
JSONNodeDumper::createFPOptions(FPOptionsOverride FPO
) {
1790 llvm::json::Object Ret
;
1791 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
1792 if (FPO.has##NAME##Override()) \
1793 Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override()));
1794 #include "clang/Basic/FPOptions.def"
1798 void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt
*S
) {
1800 if (S
->hasStoredFPFeatures())
1801 JOS
.attribute("fpoptions", createFPOptions(S
->getStoredFPFeatures()));