10b57cec5SDimitry Andric #include "clang/AST/JSONNodeDumper.h"
2bdd1243dSDimitry Andric #include "clang/AST/Type.h"
35ffd83dbSDimitry Andric #include "clang/Basic/SourceManager.h"
45ffd83dbSDimitry Andric #include "clang/Basic/Specifiers.h"
50b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
606c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
7bdd1243dSDimitry Andric #include <optional>
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric using namespace clang;
100b57cec5SDimitry Andric 
addPreviousDeclaration(const Decl * D)110b57cec5SDimitry Andric void JSONNodeDumper::addPreviousDeclaration(const Decl *D) {
120b57cec5SDimitry Andric   switch (D->getKind()) {
130b57cec5SDimitry Andric #define DECL(DERIVED, BASE)                                                    \
140b57cec5SDimitry Andric   case Decl::DERIVED:                                                          \
150b57cec5SDimitry Andric     return writePreviousDeclImpl(cast<DERIVED##Decl>(D));
160b57cec5SDimitry Andric #define ABSTRACT_DECL(DECL)
170b57cec5SDimitry Andric #include "clang/AST/DeclNodes.inc"
180b57cec5SDimitry Andric #undef ABSTRACT_DECL
190b57cec5SDimitry Andric #undef DECL
200b57cec5SDimitry Andric   }
210b57cec5SDimitry Andric   llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
220b57cec5SDimitry Andric }
230b57cec5SDimitry Andric 
Visit(const Attr * A)240b57cec5SDimitry Andric void JSONNodeDumper::Visit(const Attr *A) {
250b57cec5SDimitry Andric   const char *AttrName = nullptr;
260b57cec5SDimitry Andric   switch (A->getKind()) {
270b57cec5SDimitry Andric #define ATTR(X)                                                                \
280b57cec5SDimitry Andric   case attr::X:                                                                \
290b57cec5SDimitry Andric     AttrName = #X"Attr";                                                       \
300b57cec5SDimitry Andric     break;
310b57cec5SDimitry Andric #include "clang/Basic/AttrList.inc"
320b57cec5SDimitry Andric #undef ATTR
330b57cec5SDimitry Andric   }
340b57cec5SDimitry Andric   JOS.attribute("id", createPointerRepresentation(A));
350b57cec5SDimitry Andric   JOS.attribute("kind", AttrName);
360b57cec5SDimitry Andric   JOS.attributeObject("range", [A, this] { writeSourceRange(A->getRange()); });
370b57cec5SDimitry Andric   attributeOnlyIfTrue("inherited", A->isInherited());
380b57cec5SDimitry Andric   attributeOnlyIfTrue("implicit", A->isImplicit());
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   // FIXME: it would be useful for us to output the spelling kind as well as
410b57cec5SDimitry Andric   // the actual spelling. This would allow us to distinguish between the
420b57cec5SDimitry Andric   // various attribute syntaxes, but we don't currently track that information
430b57cec5SDimitry Andric   // within the AST.
440b57cec5SDimitry Andric   //JOS.attribute("spelling", A->getSpelling());
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   InnerAttrVisitor::Visit(A);
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
Visit(const Stmt * S)490b57cec5SDimitry Andric void JSONNodeDumper::Visit(const Stmt *S) {
500b57cec5SDimitry Andric   if (!S)
510b57cec5SDimitry Andric     return;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   JOS.attribute("id", createPointerRepresentation(S));
540b57cec5SDimitry Andric   JOS.attribute("kind", S->getStmtClassName());
550b57cec5SDimitry Andric   JOS.attributeObject("range",
560b57cec5SDimitry Andric                       [S, this] { writeSourceRange(S->getSourceRange()); });
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   if (const auto *E = dyn_cast<Expr>(S)) {
590b57cec5SDimitry Andric     JOS.attribute("type", createQualType(E->getType()));
600b57cec5SDimitry Andric     const char *Category = nullptr;
610b57cec5SDimitry Andric     switch (E->getValueKind()) {
620b57cec5SDimitry Andric     case VK_LValue: Category = "lvalue"; break;
630b57cec5SDimitry Andric     case VK_XValue: Category = "xvalue"; break;
64fe6060f1SDimitry Andric     case VK_PRValue:
65fe6060f1SDimitry Andric       Category = "prvalue";
66fe6060f1SDimitry Andric       break;
670b57cec5SDimitry Andric     }
680b57cec5SDimitry Andric     JOS.attribute("valueCategory", Category);
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric   InnerStmtVisitor::Visit(S);
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
Visit(const Type * T)730b57cec5SDimitry Andric void JSONNodeDumper::Visit(const Type *T) {
740b57cec5SDimitry Andric   JOS.attribute("id", createPointerRepresentation(T));
75a7dea167SDimitry Andric 
76a7dea167SDimitry Andric   if (!T)
77a7dea167SDimitry Andric     return;
78a7dea167SDimitry Andric 
790b57cec5SDimitry Andric   JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str());
800b57cec5SDimitry Andric   JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar*/ false));
815ffd83dbSDimitry Andric   attributeOnlyIfTrue("containsErrors", T->containsErrors());
820b57cec5SDimitry Andric   attributeOnlyIfTrue("isDependent", T->isDependentType());
830b57cec5SDimitry Andric   attributeOnlyIfTrue("isInstantiationDependent",
840b57cec5SDimitry Andric                       T->isInstantiationDependentType());
850b57cec5SDimitry Andric   attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType());
860b57cec5SDimitry Andric   attributeOnlyIfTrue("containsUnexpandedPack",
870b57cec5SDimitry Andric                       T->containsUnexpandedParameterPack());
880b57cec5SDimitry Andric   attributeOnlyIfTrue("isImported", T->isFromAST());
890b57cec5SDimitry Andric   InnerTypeVisitor::Visit(T);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
Visit(QualType T)920b57cec5SDimitry Andric void JSONNodeDumper::Visit(QualType T) {
930b57cec5SDimitry Andric   JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
940b57cec5SDimitry Andric   JOS.attribute("kind", "QualType");
950b57cec5SDimitry Andric   JOS.attribute("type", createQualType(T));
960b57cec5SDimitry Andric   JOS.attribute("qualifiers", T.split().Quals.getAsString());
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
Visit(const Decl * D)990b57cec5SDimitry Andric void JSONNodeDumper::Visit(const Decl *D) {
1000b57cec5SDimitry Andric   JOS.attribute("id", createPointerRepresentation(D));
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   if (!D)
1030b57cec5SDimitry Andric     return;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
1060b57cec5SDimitry Andric   JOS.attributeObject("loc",
1070b57cec5SDimitry Andric                       [D, this] { writeSourceLocation(D->getLocation()); });
1080b57cec5SDimitry Andric   JOS.attributeObject("range",
1090b57cec5SDimitry Andric                       [D, this] { writeSourceRange(D->getSourceRange()); });
1100b57cec5SDimitry Andric   attributeOnlyIfTrue("isImplicit", D->isImplicit());
1110b57cec5SDimitry Andric   attributeOnlyIfTrue("isInvalid", D->isInvalidDecl());
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   if (D->isUsed())
1140b57cec5SDimitry Andric     JOS.attribute("isUsed", true);
1150b57cec5SDimitry Andric   else if (D->isThisDeclarationReferenced())
1160b57cec5SDimitry Andric     JOS.attribute("isReferenced", true);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   if (const auto *ND = dyn_cast<NamedDecl>(D))
1195ffd83dbSDimitry Andric     attributeOnlyIfTrue("isHidden", !ND->isUnconditionallyVisible());
1200b57cec5SDimitry Andric 
121a7dea167SDimitry Andric   if (D->getLexicalDeclContext() != D->getDeclContext()) {
122a7dea167SDimitry Andric     // Because of multiple inheritance, a DeclContext pointer does not produce
123a7dea167SDimitry Andric     // the same pointer representation as a Decl pointer that references the
124a7dea167SDimitry Andric     // same AST Node.
125a7dea167SDimitry Andric     const auto *ParentDeclContextDecl = dyn_cast<Decl>(D->getDeclContext());
126a7dea167SDimitry Andric     JOS.attribute("parentDeclContextId",
127a7dea167SDimitry Andric                   createPointerRepresentation(ParentDeclContextDecl));
128a7dea167SDimitry Andric   }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   addPreviousDeclaration(D);
1310b57cec5SDimitry Andric   InnerDeclVisitor::Visit(D);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
Visit(const comments::Comment * C,const comments::FullComment * FC)1340b57cec5SDimitry Andric void JSONNodeDumper::Visit(const comments::Comment *C,
1350b57cec5SDimitry Andric                            const comments::FullComment *FC) {
1360b57cec5SDimitry Andric   if (!C)
1370b57cec5SDimitry Andric     return;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   JOS.attribute("id", createPointerRepresentation(C));
1400b57cec5SDimitry Andric   JOS.attribute("kind", C->getCommentKindName());
1410b57cec5SDimitry Andric   JOS.attributeObject("loc",
1420b57cec5SDimitry Andric                       [C, this] { writeSourceLocation(C->getLocation()); });
1430b57cec5SDimitry Andric   JOS.attributeObject("range",
1440b57cec5SDimitry Andric                       [C, this] { writeSourceRange(C->getSourceRange()); });
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   InnerCommentVisitor::visit(C, FC);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
Visit(const TemplateArgument & TA,SourceRange R,const Decl * From,StringRef Label)1490b57cec5SDimitry Andric void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
1500b57cec5SDimitry Andric                            const Decl *From, StringRef Label) {
1510b57cec5SDimitry Andric   JOS.attribute("kind", "TemplateArgument");
1520b57cec5SDimitry Andric   if (R.isValid())
1530b57cec5SDimitry Andric     JOS.attributeObject("range", [R, this] { writeSourceRange(R); });
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   if (From)
1560b57cec5SDimitry Andric     JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From));
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   InnerTemplateArgVisitor::Visit(TA);
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
Visit(const CXXCtorInitializer * Init)1610b57cec5SDimitry Andric void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
1620b57cec5SDimitry Andric   JOS.attribute("kind", "CXXCtorInitializer");
1630b57cec5SDimitry Andric   if (Init->isAnyMemberInitializer())
1640b57cec5SDimitry Andric     JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember()));
1650b57cec5SDimitry Andric   else if (Init->isBaseInitializer())
1660b57cec5SDimitry Andric     JOS.attribute("baseInit",
1670b57cec5SDimitry Andric                   createQualType(QualType(Init->getBaseClass(), 0)));
1680b57cec5SDimitry Andric   else if (Init->isDelegatingInitializer())
1690b57cec5SDimitry Andric     JOS.attribute("delegatingInit",
1700b57cec5SDimitry Andric                   createQualType(Init->getTypeSourceInfo()->getType()));
1710b57cec5SDimitry Andric   else
1720b57cec5SDimitry Andric     llvm_unreachable("Unknown initializer type");
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
Visit(const OMPClause * C)1750b57cec5SDimitry Andric void JSONNodeDumper::Visit(const OMPClause *C) {}
1760b57cec5SDimitry Andric 
Visit(const BlockDecl::Capture & C)1770b57cec5SDimitry Andric void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {
1780b57cec5SDimitry Andric   JOS.attribute("kind", "Capture");
1790b57cec5SDimitry Andric   attributeOnlyIfTrue("byref", C.isByRef());
1800b57cec5SDimitry Andric   attributeOnlyIfTrue("nested", C.isNested());
1810b57cec5SDimitry Andric   if (C.getVariable())
1820b57cec5SDimitry Andric     JOS.attribute("var", createBareDeclRef(C.getVariable()));
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
Visit(const GenericSelectionExpr::ConstAssociation & A)1850b57cec5SDimitry Andric void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
1860b57cec5SDimitry Andric   JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default");
1870b57cec5SDimitry Andric   attributeOnlyIfTrue("selected", A.isSelected());
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
Visit(const concepts::Requirement * R)190fe6060f1SDimitry Andric void JSONNodeDumper::Visit(const concepts::Requirement *R) {
191fe6060f1SDimitry Andric   if (!R)
192fe6060f1SDimitry Andric     return;
193fe6060f1SDimitry Andric 
194fe6060f1SDimitry Andric   switch (R->getKind()) {
195fe6060f1SDimitry Andric   case concepts::Requirement::RK_Type:
196fe6060f1SDimitry Andric     JOS.attribute("kind", "TypeRequirement");
197fe6060f1SDimitry Andric     break;
198fe6060f1SDimitry Andric   case concepts::Requirement::RK_Simple:
199fe6060f1SDimitry Andric     JOS.attribute("kind", "SimpleRequirement");
200fe6060f1SDimitry Andric     break;
201fe6060f1SDimitry Andric   case concepts::Requirement::RK_Compound:
202fe6060f1SDimitry Andric     JOS.attribute("kind", "CompoundRequirement");
203fe6060f1SDimitry Andric     break;
204fe6060f1SDimitry Andric   case concepts::Requirement::RK_Nested:
205fe6060f1SDimitry Andric     JOS.attribute("kind", "NestedRequirement");
206fe6060f1SDimitry Andric     break;
207fe6060f1SDimitry Andric   }
208fe6060f1SDimitry Andric 
209fe6060f1SDimitry Andric   if (auto *ER = dyn_cast<concepts::ExprRequirement>(R))
210fe6060f1SDimitry Andric     attributeOnlyIfTrue("noexcept", ER->hasNoexceptRequirement());
211fe6060f1SDimitry Andric 
212fe6060f1SDimitry Andric   attributeOnlyIfTrue("isDependent", R->isDependent());
213fe6060f1SDimitry Andric   if (!R->isDependent())
214fe6060f1SDimitry Andric     JOS.attribute("satisfied", R->isSatisfied());
215fe6060f1SDimitry Andric   attributeOnlyIfTrue("containsUnexpandedPack",
216fe6060f1SDimitry Andric                       R->containsUnexpandedParameterPack());
217fe6060f1SDimitry Andric }
218fe6060f1SDimitry Andric 
Visit(const APValue & Value,QualType Ty)2195ffd83dbSDimitry Andric void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {
2205ffd83dbSDimitry Andric   std::string Str;
2215ffd83dbSDimitry Andric   llvm::raw_string_ostream OS(Str);
2225ffd83dbSDimitry Andric   Value.printPretty(OS, Ctx, Ty);
2235ffd83dbSDimitry Andric   JOS.attribute("value", OS.str());
2245ffd83dbSDimitry Andric }
2255ffd83dbSDimitry Andric 
writeIncludeStack(PresumedLoc Loc,bool JustFirst)226a7dea167SDimitry Andric void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
227a7dea167SDimitry Andric   if (Loc.isInvalid())
228a7dea167SDimitry Andric     return;
229a7dea167SDimitry Andric 
230a7dea167SDimitry Andric   JOS.attributeBegin("includedFrom");
231a7dea167SDimitry Andric   JOS.objectBegin();
232a7dea167SDimitry Andric 
233a7dea167SDimitry Andric   if (!JustFirst) {
234a7dea167SDimitry Andric     // Walk the stack recursively, then print out the presumed location.
235a7dea167SDimitry Andric     writeIncludeStack(SM.getPresumedLoc(Loc.getIncludeLoc()));
236a7dea167SDimitry Andric   }
237a7dea167SDimitry Andric 
238a7dea167SDimitry Andric   JOS.attribute("file", Loc.getFilename());
239a7dea167SDimitry Andric   JOS.objectEnd();
240a7dea167SDimitry Andric   JOS.attributeEnd();
241a7dea167SDimitry Andric }
242a7dea167SDimitry Andric 
writeBareSourceLocation(SourceLocation Loc,bool IsSpelling)2430b57cec5SDimitry Andric void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc,
2440b57cec5SDimitry Andric                                              bool IsSpelling) {
2450b57cec5SDimitry Andric   PresumedLoc Presumed = SM.getPresumedLoc(Loc);
2460b57cec5SDimitry Andric   unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc)
2470b57cec5SDimitry Andric                                    : SM.getExpansionLineNumber(Loc);
248480093f4SDimitry Andric   StringRef ActualFile = SM.getBufferName(Loc);
249480093f4SDimitry Andric 
2500b57cec5SDimitry Andric   if (Presumed.isValid()) {
251a7dea167SDimitry Andric     JOS.attribute("offset", SM.getDecomposedLoc(Loc).second);
252480093f4SDimitry Andric     if (LastLocFilename != ActualFile) {
253480093f4SDimitry Andric       JOS.attribute("file", ActualFile);
2540b57cec5SDimitry Andric       JOS.attribute("line", ActualLine);
2550b57cec5SDimitry Andric     } else if (LastLocLine != ActualLine)
2560b57cec5SDimitry Andric       JOS.attribute("line", ActualLine);
2570b57cec5SDimitry Andric 
258480093f4SDimitry Andric     StringRef PresumedFile = Presumed.getFilename();
259480093f4SDimitry Andric     if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile)
260480093f4SDimitry Andric       JOS.attribute("presumedFile", PresumedFile);
261480093f4SDimitry Andric 
2620b57cec5SDimitry Andric     unsigned PresumedLine = Presumed.getLine();
2630b57cec5SDimitry Andric     if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine)
2640b57cec5SDimitry Andric       JOS.attribute("presumedLine", PresumedLine);
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric     JOS.attribute("col", Presumed.getColumn());
2670b57cec5SDimitry Andric     JOS.attribute("tokLen",
2680b57cec5SDimitry Andric                   Lexer::MeasureTokenLength(Loc, SM, Ctx.getLangOpts()));
269480093f4SDimitry Andric     LastLocFilename = ActualFile;
270480093f4SDimitry Andric     LastLocPresumedFilename = PresumedFile;
2710b57cec5SDimitry Andric     LastLocPresumedLine = PresumedLine;
2720b57cec5SDimitry Andric     LastLocLine = ActualLine;
273a7dea167SDimitry Andric 
274a7dea167SDimitry Andric     // Orthogonal to the file, line, and column de-duplication is whether the
275a7dea167SDimitry Andric     // given location was a result of an include. If so, print where the
276a7dea167SDimitry Andric     // include location came from.
277a7dea167SDimitry Andric     writeIncludeStack(SM.getPresumedLoc(Presumed.getIncludeLoc()),
278a7dea167SDimitry Andric                       /*JustFirst*/ true);
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
writeSourceLocation(SourceLocation Loc)2820b57cec5SDimitry Andric void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) {
2830b57cec5SDimitry Andric   SourceLocation Spelling = SM.getSpellingLoc(Loc);
2840b57cec5SDimitry Andric   SourceLocation Expansion = SM.getExpansionLoc(Loc);
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   if (Expansion != Spelling) {
2870b57cec5SDimitry Andric     // If the expansion and the spelling are different, output subobjects
2880b57cec5SDimitry Andric     // describing both locations.
2890b57cec5SDimitry Andric     JOS.attributeObject("spellingLoc", [Spelling, this] {
2900b57cec5SDimitry Andric       writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
2910b57cec5SDimitry Andric     });
2920b57cec5SDimitry Andric     JOS.attributeObject("expansionLoc", [Expansion, Loc, this] {
2930b57cec5SDimitry Andric       writeBareSourceLocation(Expansion, /*IsSpelling*/ false);
2940b57cec5SDimitry Andric       // If there is a macro expansion, add extra information if the interesting
2950b57cec5SDimitry Andric       // bit is the macro arg expansion.
2960b57cec5SDimitry Andric       if (SM.isMacroArgExpansion(Loc))
2970b57cec5SDimitry Andric         JOS.attribute("isMacroArgExpansion", true);
2980b57cec5SDimitry Andric     });
2990b57cec5SDimitry Andric   } else
3000b57cec5SDimitry Andric     writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
writeSourceRange(SourceRange R)3030b57cec5SDimitry Andric void JSONNodeDumper::writeSourceRange(SourceRange R) {
3040b57cec5SDimitry Andric   JOS.attributeObject("begin",
3050b57cec5SDimitry Andric                       [R, this] { writeSourceLocation(R.getBegin()); });
3060b57cec5SDimitry Andric   JOS.attributeObject("end", [R, this] { writeSourceLocation(R.getEnd()); });
3070b57cec5SDimitry Andric }
3080b57cec5SDimitry Andric 
createPointerRepresentation(const void * Ptr)3090b57cec5SDimitry Andric std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) {
3100b57cec5SDimitry Andric   // Because JSON stores integer values as signed 64-bit integers, trying to
3110b57cec5SDimitry Andric   // represent them as such makes for very ugly pointer values in the resulting
3120b57cec5SDimitry Andric   // output. Instead, we convert the value to hex and treat it as a string.
3130b57cec5SDimitry Andric   return "0x" + llvm::utohexstr(reinterpret_cast<uint64_t>(Ptr), true);
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
createQualType(QualType QT,bool Desugar)3160b57cec5SDimitry Andric llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) {
3170b57cec5SDimitry Andric   SplitQualType SQT = QT.split();
3185f757f3fSDimitry Andric   std::string SQTS = QualType::getAsString(SQT, PrintPolicy);
3195f757f3fSDimitry Andric   llvm::json::Object Ret{{"qualType", SQTS}};
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   if (Desugar && !QT.isNull()) {
3220b57cec5SDimitry Andric     SplitQualType DSQT = QT.getSplitDesugaredType();
3235f757f3fSDimitry Andric     if (DSQT != SQT) {
3245f757f3fSDimitry Andric       std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);
3255f757f3fSDimitry Andric       if (DSQTS != SQTS)
3265f757f3fSDimitry Andric         Ret["desugaredQualType"] = DSQTS;
3275f757f3fSDimitry Andric     }
328a7dea167SDimitry Andric     if (const auto *TT = QT->getAs<TypedefType>())
329a7dea167SDimitry Andric       Ret["typeAliasDeclId"] = createPointerRepresentation(TT->getDecl());
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric   return Ret;
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
writeBareDeclRef(const Decl * D)3340b57cec5SDimitry Andric void JSONNodeDumper::writeBareDeclRef(const Decl *D) {
3350b57cec5SDimitry Andric   JOS.attribute("id", createPointerRepresentation(D));
3360b57cec5SDimitry Andric   if (!D)
3370b57cec5SDimitry Andric     return;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
3400b57cec5SDimitry Andric   if (const auto *ND = dyn_cast<NamedDecl>(D))
3410b57cec5SDimitry Andric     JOS.attribute("name", ND->getDeclName().getAsString());
3420b57cec5SDimitry Andric   if (const auto *VD = dyn_cast<ValueDecl>(D))
3430b57cec5SDimitry Andric     JOS.attribute("type", createQualType(VD->getType()));
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
createBareDeclRef(const Decl * D)3460b57cec5SDimitry Andric llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) {
3470b57cec5SDimitry Andric   llvm::json::Object Ret{{"id", createPointerRepresentation(D)}};
3480b57cec5SDimitry Andric   if (!D)
3490b57cec5SDimitry Andric     return Ret;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   Ret["kind"] = (llvm::Twine(D->getDeclKindName()) + "Decl").str();
3520b57cec5SDimitry Andric   if (const auto *ND = dyn_cast<NamedDecl>(D))
3530b57cec5SDimitry Andric     Ret["name"] = ND->getDeclName().getAsString();
3540b57cec5SDimitry Andric   if (const auto *VD = dyn_cast<ValueDecl>(D))
3550b57cec5SDimitry Andric     Ret["type"] = createQualType(VD->getType());
3560b57cec5SDimitry Andric   return Ret;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
createCastPath(const CastExpr * C)3590b57cec5SDimitry Andric llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) {
3600b57cec5SDimitry Andric   llvm::json::Array Ret;
3610b57cec5SDimitry Andric   if (C->path_empty())
3620b57cec5SDimitry Andric     return Ret;
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) {
3650b57cec5SDimitry Andric     const CXXBaseSpecifier *Base = *I;
3660b57cec5SDimitry Andric     const auto *RD =
367a7dea167SDimitry Andric         cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric     llvm::json::Object Val{{"name", RD->getName()}};
3700b57cec5SDimitry Andric     if (Base->isVirtual())
3710b57cec5SDimitry Andric       Val["isVirtual"] = true;
3720b57cec5SDimitry Andric     Ret.push_back(std::move(Val));
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric   return Ret;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric #define FIELD2(Name, Flag)  if (RD->Flag()) Ret[Name] = true
3780b57cec5SDimitry Andric #define FIELD1(Flag)        FIELD2(#Flag, Flag)
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric static llvm::json::Object
createDefaultConstructorDefinitionData(const CXXRecordDecl * RD)3810b57cec5SDimitry Andric createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) {
3820b57cec5SDimitry Andric   llvm::json::Object Ret;
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   FIELD2("exists", hasDefaultConstructor);
3850b57cec5SDimitry Andric   FIELD2("trivial", hasTrivialDefaultConstructor);
3860b57cec5SDimitry Andric   FIELD2("nonTrivial", hasNonTrivialDefaultConstructor);
3870b57cec5SDimitry Andric   FIELD2("userProvided", hasUserProvidedDefaultConstructor);
3880b57cec5SDimitry Andric   FIELD2("isConstexpr", hasConstexprDefaultConstructor);
3890b57cec5SDimitry Andric   FIELD2("needsImplicit", needsImplicitDefaultConstructor);
3900b57cec5SDimitry Andric   FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr);
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   return Ret;
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric static llvm::json::Object
createCopyConstructorDefinitionData(const CXXRecordDecl * RD)3960b57cec5SDimitry Andric createCopyConstructorDefinitionData(const CXXRecordDecl *RD) {
3970b57cec5SDimitry Andric   llvm::json::Object Ret;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   FIELD2("simple", hasSimpleCopyConstructor);
4000b57cec5SDimitry Andric   FIELD2("trivial", hasTrivialCopyConstructor);
4010b57cec5SDimitry Andric   FIELD2("nonTrivial", hasNonTrivialCopyConstructor);
4020b57cec5SDimitry Andric   FIELD2("userDeclared", hasUserDeclaredCopyConstructor);
4030b57cec5SDimitry Andric   FIELD2("hasConstParam", hasCopyConstructorWithConstParam);
4040b57cec5SDimitry Andric   FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam);
4050b57cec5SDimitry Andric   FIELD2("needsImplicit", needsImplicitCopyConstructor);
4060b57cec5SDimitry Andric   FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor);
4070b57cec5SDimitry Andric   if (!RD->needsOverloadResolutionForCopyConstructor())
4080b57cec5SDimitry Andric     FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted);
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   return Ret;
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric static llvm::json::Object
createMoveConstructorDefinitionData(const CXXRecordDecl * RD)4140b57cec5SDimitry Andric createMoveConstructorDefinitionData(const CXXRecordDecl *RD) {
4150b57cec5SDimitry Andric   llvm::json::Object Ret;
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   FIELD2("exists", hasMoveConstructor);
4180b57cec5SDimitry Andric   FIELD2("simple", hasSimpleMoveConstructor);
4190b57cec5SDimitry Andric   FIELD2("trivial", hasTrivialMoveConstructor);
4200b57cec5SDimitry Andric   FIELD2("nonTrivial", hasNonTrivialMoveConstructor);
4210b57cec5SDimitry Andric   FIELD2("userDeclared", hasUserDeclaredMoveConstructor);
4220b57cec5SDimitry Andric   FIELD2("needsImplicit", needsImplicitMoveConstructor);
4230b57cec5SDimitry Andric   FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor);
4240b57cec5SDimitry Andric   if (!RD->needsOverloadResolutionForMoveConstructor())
4250b57cec5SDimitry Andric     FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted);
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   return Ret;
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric static llvm::json::Object
createCopyAssignmentDefinitionData(const CXXRecordDecl * RD)4310b57cec5SDimitry Andric createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) {
4320b57cec5SDimitry Andric   llvm::json::Object Ret;
4330b57cec5SDimitry Andric 
4345ffd83dbSDimitry Andric   FIELD2("simple", hasSimpleCopyAssignment);
4350b57cec5SDimitry Andric   FIELD2("trivial", hasTrivialCopyAssignment);
4360b57cec5SDimitry Andric   FIELD2("nonTrivial", hasNonTrivialCopyAssignment);
4370b57cec5SDimitry Andric   FIELD2("hasConstParam", hasCopyAssignmentWithConstParam);
4380b57cec5SDimitry Andric   FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam);
4390b57cec5SDimitry Andric   FIELD2("userDeclared", hasUserDeclaredCopyAssignment);
4400b57cec5SDimitry Andric   FIELD2("needsImplicit", needsImplicitCopyAssignment);
4410b57cec5SDimitry Andric   FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment);
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   return Ret;
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric static llvm::json::Object
createMoveAssignmentDefinitionData(const CXXRecordDecl * RD)4470b57cec5SDimitry Andric createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) {
4480b57cec5SDimitry Andric   llvm::json::Object Ret;
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   FIELD2("exists", hasMoveAssignment);
4510b57cec5SDimitry Andric   FIELD2("simple", hasSimpleMoveAssignment);
4520b57cec5SDimitry Andric   FIELD2("trivial", hasTrivialMoveAssignment);
4530b57cec5SDimitry Andric   FIELD2("nonTrivial", hasNonTrivialMoveAssignment);
4540b57cec5SDimitry Andric   FIELD2("userDeclared", hasUserDeclaredMoveAssignment);
4550b57cec5SDimitry Andric   FIELD2("needsImplicit", needsImplicitMoveAssignment);
4560b57cec5SDimitry Andric   FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment);
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   return Ret;
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric static llvm::json::Object
createDestructorDefinitionData(const CXXRecordDecl * RD)4620b57cec5SDimitry Andric createDestructorDefinitionData(const CXXRecordDecl *RD) {
4630b57cec5SDimitry Andric   llvm::json::Object Ret;
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   FIELD2("simple", hasSimpleDestructor);
4660b57cec5SDimitry Andric   FIELD2("irrelevant", hasIrrelevantDestructor);
4670b57cec5SDimitry Andric   FIELD2("trivial", hasTrivialDestructor);
4680b57cec5SDimitry Andric   FIELD2("nonTrivial", hasNonTrivialDestructor);
4690b57cec5SDimitry Andric   FIELD2("userDeclared", hasUserDeclaredDestructor);
4700b57cec5SDimitry Andric   FIELD2("needsImplicit", needsImplicitDestructor);
4710b57cec5SDimitry Andric   FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor);
4720b57cec5SDimitry Andric   if (!RD->needsOverloadResolutionForDestructor())
4730b57cec5SDimitry Andric     FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted);
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   return Ret;
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric llvm::json::Object
createCXXRecordDefinitionData(const CXXRecordDecl * RD)4790b57cec5SDimitry Andric JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) {
4800b57cec5SDimitry Andric   llvm::json::Object Ret;
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   // This data is common to all C++ classes.
4830b57cec5SDimitry Andric   FIELD1(isGenericLambda);
4840b57cec5SDimitry Andric   FIELD1(isLambda);
4850b57cec5SDimitry Andric   FIELD1(isEmpty);
4860b57cec5SDimitry Andric   FIELD1(isAggregate);
4870b57cec5SDimitry Andric   FIELD1(isStandardLayout);
4880b57cec5SDimitry Andric   FIELD1(isTriviallyCopyable);
4890b57cec5SDimitry Andric   FIELD1(isPOD);
4900b57cec5SDimitry Andric   FIELD1(isTrivial);
4910b57cec5SDimitry Andric   FIELD1(isPolymorphic);
4920b57cec5SDimitry Andric   FIELD1(isAbstract);
4930b57cec5SDimitry Andric   FIELD1(isLiteral);
4940b57cec5SDimitry Andric   FIELD1(canPassInRegisters);
4950b57cec5SDimitry Andric   FIELD1(hasUserDeclaredConstructor);
4960b57cec5SDimitry Andric   FIELD1(hasConstexprNonCopyMoveConstructor);
4970b57cec5SDimitry Andric   FIELD1(hasMutableFields);
4980b57cec5SDimitry Andric   FIELD1(hasVariantMembers);
4990b57cec5SDimitry Andric   FIELD2("canConstDefaultInit", allowConstDefaultInit);
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD);
5020b57cec5SDimitry Andric   Ret["copyCtor"] = createCopyConstructorDefinitionData(RD);
5030b57cec5SDimitry Andric   Ret["moveCtor"] = createMoveConstructorDefinitionData(RD);
5040b57cec5SDimitry Andric   Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD);
5050b57cec5SDimitry Andric   Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD);
5060b57cec5SDimitry Andric   Ret["dtor"] = createDestructorDefinitionData(RD);
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   return Ret;
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric #undef FIELD1
5120b57cec5SDimitry Andric #undef FIELD2
5130b57cec5SDimitry Andric 
createAccessSpecifier(AccessSpecifier AS)5140b57cec5SDimitry Andric std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) {
5155ffd83dbSDimitry Andric   const auto AccessSpelling = getAccessSpelling(AS);
5165ffd83dbSDimitry Andric   if (AccessSpelling.empty())
5175ffd83dbSDimitry Andric     return "none";
5185ffd83dbSDimitry Andric   return AccessSpelling.str();
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric llvm::json::Object
createCXXBaseSpecifier(const CXXBaseSpecifier & BS)5220b57cec5SDimitry Andric JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) {
5230b57cec5SDimitry Andric   llvm::json::Object Ret;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   Ret["type"] = createQualType(BS.getType());
5260b57cec5SDimitry Andric   Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier());
5270b57cec5SDimitry Andric   Ret["writtenAccess"] =
5280b57cec5SDimitry Andric       createAccessSpecifier(BS.getAccessSpecifierAsWritten());
5290b57cec5SDimitry Andric   if (BS.isVirtual())
5300b57cec5SDimitry Andric     Ret["isVirtual"] = true;
5310b57cec5SDimitry Andric   if (BS.isPackExpansion())
5320b57cec5SDimitry Andric     Ret["isPackExpansion"] = true;
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   return Ret;
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
VisitAliasAttr(const AliasAttr * AA)5375f757f3fSDimitry Andric void JSONNodeDumper::VisitAliasAttr(const AliasAttr *AA) {
5385f757f3fSDimitry Andric   JOS.attribute("aliasee", AA->getAliasee());
5395f757f3fSDimitry Andric }
5405f757f3fSDimitry Andric 
VisitCleanupAttr(const CleanupAttr * CA)5415f757f3fSDimitry Andric void JSONNodeDumper::VisitCleanupAttr(const CleanupAttr *CA) {
5425f757f3fSDimitry Andric   JOS.attribute("cleanup_function", createBareDeclRef(CA->getFunctionDecl()));
5435f757f3fSDimitry Andric }
5445f757f3fSDimitry Andric 
VisitDeprecatedAttr(const DeprecatedAttr * DA)5455f757f3fSDimitry Andric void JSONNodeDumper::VisitDeprecatedAttr(const DeprecatedAttr *DA) {
5465f757f3fSDimitry Andric   if (!DA->getMessage().empty())
5475f757f3fSDimitry Andric     JOS.attribute("message", DA->getMessage());
5485f757f3fSDimitry Andric   if (!DA->getReplacement().empty())
5495f757f3fSDimitry Andric     JOS.attribute("replacement", DA->getReplacement());
5505f757f3fSDimitry Andric }
5515f757f3fSDimitry Andric 
VisitUnavailableAttr(const UnavailableAttr * UA)5525f757f3fSDimitry Andric void JSONNodeDumper::VisitUnavailableAttr(const UnavailableAttr *UA) {
5535f757f3fSDimitry Andric   if (!UA->getMessage().empty())
5545f757f3fSDimitry Andric     JOS.attribute("message", UA->getMessage());
5555f757f3fSDimitry Andric }
5565f757f3fSDimitry Andric 
VisitSectionAttr(const SectionAttr * SA)5575f757f3fSDimitry Andric void JSONNodeDumper::VisitSectionAttr(const SectionAttr *SA) {
5585f757f3fSDimitry Andric   JOS.attribute("section_name", SA->getName());
5595f757f3fSDimitry Andric }
5605f757f3fSDimitry Andric 
VisitVisibilityAttr(const VisibilityAttr * VA)5615f757f3fSDimitry Andric void JSONNodeDumper::VisitVisibilityAttr(const VisibilityAttr *VA) {
5625f757f3fSDimitry Andric   JOS.attribute("visibility", VisibilityAttr::ConvertVisibilityTypeToStr(
5635f757f3fSDimitry Andric                                   VA->getVisibility()));
5645f757f3fSDimitry Andric }
5655f757f3fSDimitry Andric 
VisitTLSModelAttr(const TLSModelAttr * TA)5665f757f3fSDimitry Andric void JSONNodeDumper::VisitTLSModelAttr(const TLSModelAttr *TA) {
5675f757f3fSDimitry Andric   JOS.attribute("tls_model", TA->getModel());
5685f757f3fSDimitry Andric }
5695f757f3fSDimitry Andric 
VisitTypedefType(const TypedefType * TT)5700b57cec5SDimitry Andric void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {
5710b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
572bdd1243dSDimitry Andric   if (!TT->typeMatchesDecl())
573bdd1243dSDimitry Andric     JOS.attribute("type", createQualType(TT->desugar()));
574bdd1243dSDimitry Andric }
575bdd1243dSDimitry Andric 
VisitUsingType(const UsingType * TT)576bdd1243dSDimitry Andric void JSONNodeDumper::VisitUsingType(const UsingType *TT) {
577bdd1243dSDimitry Andric   JOS.attribute("decl", createBareDeclRef(TT->getFoundDecl()));
578bdd1243dSDimitry Andric   if (!TT->typeMatchesDecl())
579bdd1243dSDimitry Andric     JOS.attribute("type", createQualType(TT->desugar()));
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric 
VisitFunctionType(const FunctionType * T)5820b57cec5SDimitry Andric void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {
5830b57cec5SDimitry Andric   FunctionType::ExtInfo E = T->getExtInfo();
5840b57cec5SDimitry Andric   attributeOnlyIfTrue("noreturn", E.getNoReturn());
5850b57cec5SDimitry Andric   attributeOnlyIfTrue("producesResult", E.getProducesResult());
5860b57cec5SDimitry Andric   if (E.getHasRegParm())
5870b57cec5SDimitry Andric     JOS.attribute("regParm", E.getRegParm());
5880b57cec5SDimitry Andric   JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC()));
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
VisitFunctionProtoType(const FunctionProtoType * T)5910b57cec5SDimitry Andric void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
5920b57cec5SDimitry Andric   FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo();
5930b57cec5SDimitry Andric   attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn);
5940b57cec5SDimitry Andric   attributeOnlyIfTrue("const", T->isConst());
5950b57cec5SDimitry Andric   attributeOnlyIfTrue("volatile", T->isVolatile());
5960b57cec5SDimitry Andric   attributeOnlyIfTrue("restrict", T->isRestrict());
5970b57cec5SDimitry Andric   attributeOnlyIfTrue("variadic", E.Variadic);
5980b57cec5SDimitry Andric   switch (E.RefQualifier) {
5990b57cec5SDimitry Andric   case RQ_LValue: JOS.attribute("refQualifier", "&"); break;
6000b57cec5SDimitry Andric   case RQ_RValue: JOS.attribute("refQualifier", "&&"); break;
6010b57cec5SDimitry Andric   case RQ_None: break;
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric   switch (E.ExceptionSpec.Type) {
6040b57cec5SDimitry Andric   case EST_DynamicNone:
6050b57cec5SDimitry Andric   case EST_Dynamic: {
6060b57cec5SDimitry Andric     JOS.attribute("exceptionSpec", "throw");
6070b57cec5SDimitry Andric     llvm::json::Array Types;
6080b57cec5SDimitry Andric     for (QualType QT : E.ExceptionSpec.Exceptions)
6090b57cec5SDimitry Andric       Types.push_back(createQualType(QT));
6100b57cec5SDimitry Andric     JOS.attribute("exceptionTypes", std::move(Types));
6110b57cec5SDimitry Andric   } break;
6120b57cec5SDimitry Andric   case EST_MSAny:
6130b57cec5SDimitry Andric     JOS.attribute("exceptionSpec", "throw");
6140b57cec5SDimitry Andric     JOS.attribute("throwsAny", true);
6150b57cec5SDimitry Andric     break;
6160b57cec5SDimitry Andric   case EST_BasicNoexcept:
6170b57cec5SDimitry Andric     JOS.attribute("exceptionSpec", "noexcept");
6180b57cec5SDimitry Andric     break;
6190b57cec5SDimitry Andric   case EST_NoexceptTrue:
6200b57cec5SDimitry Andric   case EST_NoexceptFalse:
6210b57cec5SDimitry Andric     JOS.attribute("exceptionSpec", "noexcept");
6220b57cec5SDimitry Andric     JOS.attribute("conditionEvaluatesTo",
6230b57cec5SDimitry Andric                 E.ExceptionSpec.Type == EST_NoexceptTrue);
6240b57cec5SDimitry Andric     //JOS.attributeWithCall("exceptionSpecExpr",
6250b57cec5SDimitry Andric     //                    [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); });
6260b57cec5SDimitry Andric     break;
6270b57cec5SDimitry Andric   case EST_NoThrow:
6280b57cec5SDimitry Andric     JOS.attribute("exceptionSpec", "nothrow");
6290b57cec5SDimitry Andric     break;
6300b57cec5SDimitry Andric   // FIXME: I cannot find a way to trigger these cases while dumping the AST. I
6310b57cec5SDimitry Andric   // suspect you can only run into them when executing an AST dump from within
6320b57cec5SDimitry Andric   // the debugger, which is not a use case we worry about for the JSON dumping
6330b57cec5SDimitry Andric   // feature.
6340b57cec5SDimitry Andric   case EST_DependentNoexcept:
6350b57cec5SDimitry Andric   case EST_Unevaluated:
6360b57cec5SDimitry Andric   case EST_Uninstantiated:
6370b57cec5SDimitry Andric   case EST_Unparsed:
6380b57cec5SDimitry Andric   case EST_None: break;
6390b57cec5SDimitry Andric   }
6400b57cec5SDimitry Andric   VisitFunctionType(T);
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric 
VisitRValueReferenceType(const ReferenceType * RT)6430b57cec5SDimitry Andric void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType *RT) {
6440b57cec5SDimitry Andric   attributeOnlyIfTrue("spelledAsLValue", RT->isSpelledAsLValue());
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric 
VisitArrayType(const ArrayType * AT)6470b57cec5SDimitry Andric void JSONNodeDumper::VisitArrayType(const ArrayType *AT) {
6480b57cec5SDimitry Andric   switch (AT->getSizeModifier()) {
6495f757f3fSDimitry Andric   case ArraySizeModifier::Star:
6500b57cec5SDimitry Andric     JOS.attribute("sizeModifier", "*");
6510b57cec5SDimitry Andric     break;
6525f757f3fSDimitry Andric   case ArraySizeModifier::Static:
6530b57cec5SDimitry Andric     JOS.attribute("sizeModifier", "static");
6540b57cec5SDimitry Andric     break;
6555f757f3fSDimitry Andric   case ArraySizeModifier::Normal:
6560b57cec5SDimitry Andric     break;
6570b57cec5SDimitry Andric   }
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   std::string Str = AT->getIndexTypeQualifiers().getAsString();
6600b57cec5SDimitry Andric   if (!Str.empty())
6610b57cec5SDimitry Andric     JOS.attribute("indexTypeQualifiers", Str);
6620b57cec5SDimitry Andric }
6630b57cec5SDimitry Andric 
VisitConstantArrayType(const ConstantArrayType * CAT)6640b57cec5SDimitry Andric void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) {
6650b57cec5SDimitry Andric   // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a
6660b57cec5SDimitry Andric   // narrowing conversion to int64_t so it cannot be expressed.
6670b57cec5SDimitry Andric   JOS.attribute("size", CAT->getSize().getSExtValue());
6680b57cec5SDimitry Andric   VisitArrayType(CAT);
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
VisitDependentSizedExtVectorType(const DependentSizedExtVectorType * VT)6710b57cec5SDimitry Andric void JSONNodeDumper::VisitDependentSizedExtVectorType(
6720b57cec5SDimitry Andric     const DependentSizedExtVectorType *VT) {
6730b57cec5SDimitry Andric   JOS.attributeObject(
6740b57cec5SDimitry Andric       "attrLoc", [VT, this] { writeSourceLocation(VT->getAttributeLoc()); });
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric 
VisitVectorType(const VectorType * VT)6770b57cec5SDimitry Andric void JSONNodeDumper::VisitVectorType(const VectorType *VT) {
6780b57cec5SDimitry Andric   JOS.attribute("numElements", VT->getNumElements());
6790b57cec5SDimitry Andric   switch (VT->getVectorKind()) {
6805f757f3fSDimitry Andric   case VectorKind::Generic:
6810b57cec5SDimitry Andric     break;
6825f757f3fSDimitry Andric   case VectorKind::AltiVecVector:
6830b57cec5SDimitry Andric     JOS.attribute("vectorKind", "altivec");
6840b57cec5SDimitry Andric     break;
6855f757f3fSDimitry Andric   case VectorKind::AltiVecPixel:
6860b57cec5SDimitry Andric     JOS.attribute("vectorKind", "altivec pixel");
6870b57cec5SDimitry Andric     break;
6885f757f3fSDimitry Andric   case VectorKind::AltiVecBool:
6890b57cec5SDimitry Andric     JOS.attribute("vectorKind", "altivec bool");
6900b57cec5SDimitry Andric     break;
6915f757f3fSDimitry Andric   case VectorKind::Neon:
6920b57cec5SDimitry Andric     JOS.attribute("vectorKind", "neon");
6930b57cec5SDimitry Andric     break;
6945f757f3fSDimitry Andric   case VectorKind::NeonPoly:
6950b57cec5SDimitry Andric     JOS.attribute("vectorKind", "neon poly");
6960b57cec5SDimitry Andric     break;
6975f757f3fSDimitry Andric   case VectorKind::SveFixedLengthData:
698e8d8bef9SDimitry Andric     JOS.attribute("vectorKind", "fixed-length sve data vector");
699e8d8bef9SDimitry Andric     break;
7005f757f3fSDimitry Andric   case VectorKind::SveFixedLengthPredicate:
701e8d8bef9SDimitry Andric     JOS.attribute("vectorKind", "fixed-length sve predicate vector");
702e8d8bef9SDimitry Andric     break;
7035f757f3fSDimitry Andric   case VectorKind::RVVFixedLengthData:
70406c3fb27SDimitry Andric     JOS.attribute("vectorKind", "fixed-length rvv data vector");
70506c3fb27SDimitry Andric     break;
706b3edf446SDimitry Andric   case VectorKind::RVVFixedLengthMask:
707b3edf446SDimitry Andric     JOS.attribute("vectorKind", "fixed-length rvv mask vector");
708b3edf446SDimitry Andric     break;
7090b57cec5SDimitry Andric   }
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
VisitUnresolvedUsingType(const UnresolvedUsingType * UUT)7120b57cec5SDimitry Andric void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {
7130b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(UUT->getDecl()));
7140b57cec5SDimitry Andric }
7150b57cec5SDimitry Andric 
VisitUnaryTransformType(const UnaryTransformType * UTT)7160b57cec5SDimitry Andric void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) {
7170b57cec5SDimitry Andric   switch (UTT->getUTTKind()) {
718bdd1243dSDimitry Andric #define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait)                                  \
719bdd1243dSDimitry Andric   case UnaryTransformType::Enum:                                               \
720bdd1243dSDimitry Andric     JOS.attribute("transformKind", #Trait);                                    \
7210b57cec5SDimitry Andric     break;
722bdd1243dSDimitry Andric #include "clang/Basic/TransformTypeTraits.def"
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric }
7250b57cec5SDimitry Andric 
VisitTagType(const TagType * TT)7260b57cec5SDimitry Andric void JSONNodeDumper::VisitTagType(const TagType *TT) {
7270b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric 
VisitTemplateTypeParmType(const TemplateTypeParmType * TTPT)7300b57cec5SDimitry Andric void JSONNodeDumper::VisitTemplateTypeParmType(
7310b57cec5SDimitry Andric     const TemplateTypeParmType *TTPT) {
7320b57cec5SDimitry Andric   JOS.attribute("depth", TTPT->getDepth());
7330b57cec5SDimitry Andric   JOS.attribute("index", TTPT->getIndex());
7340b57cec5SDimitry Andric   attributeOnlyIfTrue("isPack", TTPT->isParameterPack());
7350b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(TTPT->getDecl()));
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType * STTPT)738bdd1243dSDimitry Andric void JSONNodeDumper::VisitSubstTemplateTypeParmType(
739bdd1243dSDimitry Andric     const SubstTemplateTypeParmType *STTPT) {
740bdd1243dSDimitry Andric   JOS.attribute("index", STTPT->getIndex());
741bdd1243dSDimitry Andric   if (auto PackIndex = STTPT->getPackIndex())
742bdd1243dSDimitry Andric     JOS.attribute("pack_index", *PackIndex);
743bdd1243dSDimitry Andric }
744bdd1243dSDimitry Andric 
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType * T)745bdd1243dSDimitry Andric void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
746bdd1243dSDimitry Andric     const SubstTemplateTypeParmPackType *T) {
747bdd1243dSDimitry Andric   JOS.attribute("index", T->getIndex());
748bdd1243dSDimitry Andric }
749bdd1243dSDimitry Andric 
VisitAutoType(const AutoType * AT)7500b57cec5SDimitry Andric void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
7510b57cec5SDimitry Andric   JOS.attribute("undeduced", !AT->isDeduced());
7520b57cec5SDimitry Andric   switch (AT->getKeyword()) {
7530b57cec5SDimitry Andric   case AutoTypeKeyword::Auto:
7540b57cec5SDimitry Andric     JOS.attribute("typeKeyword", "auto");
7550b57cec5SDimitry Andric     break;
7560b57cec5SDimitry Andric   case AutoTypeKeyword::DecltypeAuto:
7570b57cec5SDimitry Andric     JOS.attribute("typeKeyword", "decltype(auto)");
7580b57cec5SDimitry Andric     break;
7590b57cec5SDimitry Andric   case AutoTypeKeyword::GNUAutoType:
7600b57cec5SDimitry Andric     JOS.attribute("typeKeyword", "__auto_type");
7610b57cec5SDimitry Andric     break;
7620b57cec5SDimitry Andric   }
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric 
VisitTemplateSpecializationType(const TemplateSpecializationType * TST)7650b57cec5SDimitry Andric void JSONNodeDumper::VisitTemplateSpecializationType(
7660b57cec5SDimitry Andric     const TemplateSpecializationType *TST) {
7670b57cec5SDimitry Andric   attributeOnlyIfTrue("isAlias", TST->isTypeAlias());
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   std::string Str;
7700b57cec5SDimitry Andric   llvm::raw_string_ostream OS(Str);
7710b57cec5SDimitry Andric   TST->getTemplateName().print(OS, PrintPolicy);
7720b57cec5SDimitry Andric   JOS.attribute("templateName", OS.str());
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric 
VisitInjectedClassNameType(const InjectedClassNameType * ICNT)7750b57cec5SDimitry Andric void JSONNodeDumper::VisitInjectedClassNameType(
7760b57cec5SDimitry Andric     const InjectedClassNameType *ICNT) {
7770b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(ICNT->getDecl()));
7780b57cec5SDimitry Andric }
7790b57cec5SDimitry Andric 
VisitObjCInterfaceType(const ObjCInterfaceType * OIT)7800b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {
7810b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(OIT->getDecl()));
7820b57cec5SDimitry Andric }
7830b57cec5SDimitry Andric 
VisitPackExpansionType(const PackExpansionType * PET)7840b57cec5SDimitry Andric void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) {
785bdd1243dSDimitry Andric   if (std::optional<unsigned> N = PET->getNumExpansions())
7860b57cec5SDimitry Andric     JOS.attribute("numExpansions", *N);
7870b57cec5SDimitry Andric }
7880b57cec5SDimitry Andric 
VisitElaboratedType(const ElaboratedType * ET)7890b57cec5SDimitry Andric void JSONNodeDumper::VisitElaboratedType(const ElaboratedType *ET) {
7900b57cec5SDimitry Andric   if (const NestedNameSpecifier *NNS = ET->getQualifier()) {
7910b57cec5SDimitry Andric     std::string Str;
7920b57cec5SDimitry Andric     llvm::raw_string_ostream OS(Str);
7930b57cec5SDimitry Andric     NNS->print(OS, PrintPolicy, /*ResolveTemplateArgs*/ true);
7940b57cec5SDimitry Andric     JOS.attribute("qualifier", OS.str());
7950b57cec5SDimitry Andric   }
7960b57cec5SDimitry Andric   if (const TagDecl *TD = ET->getOwnedTagDecl())
7970b57cec5SDimitry Andric     JOS.attribute("ownedTagDecl", createBareDeclRef(TD));
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric 
VisitMacroQualifiedType(const MacroQualifiedType * MQT)8000b57cec5SDimitry Andric void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) {
8010b57cec5SDimitry Andric   JOS.attribute("macroName", MQT->getMacroIdentifier()->getName());
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric 
VisitMemberPointerType(const MemberPointerType * MPT)8040b57cec5SDimitry Andric void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) {
8050b57cec5SDimitry Andric   attributeOnlyIfTrue("isData", MPT->isMemberDataPointer());
8060b57cec5SDimitry Andric   attributeOnlyIfTrue("isFunction", MPT->isMemberFunctionPointer());
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric 
VisitNamedDecl(const NamedDecl * ND)8090b57cec5SDimitry Andric void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {
810480093f4SDimitry Andric   if (ND && ND->getDeclName()) {
8110b57cec5SDimitry Andric     JOS.attribute("name", ND->getNameAsString());
812fe6060f1SDimitry Andric     // FIXME: There are likely other contexts in which it makes no sense to ask
813fe6060f1SDimitry Andric     // for a mangled name.
8140eae32dcSDimitry Andric     if (isa<RequiresExprBodyDecl>(ND->getDeclContext()))
8150eae32dcSDimitry Andric       return;
8160eae32dcSDimitry Andric 
81706c3fb27SDimitry Andric     // If the declaration is dependent or is in a dependent context, then the
81806c3fb27SDimitry Andric     // mangling is unlikely to be meaningful (and in some cases may cause
81906c3fb27SDimitry Andric     // "don't know how to mangle this" assertion failures.
82006c3fb27SDimitry Andric     if (ND->isTemplated())
82106c3fb27SDimitry Andric       return;
82206c3fb27SDimitry Andric 
8230eae32dcSDimitry Andric     // Mangled names are not meaningful for locals, and may not be well-defined
8240eae32dcSDimitry Andric     // in the case of VLAs.
8250eae32dcSDimitry Andric     auto *VD = dyn_cast<VarDecl>(ND);
8260eae32dcSDimitry Andric     if (VD && VD->hasLocalStorage())
8270eae32dcSDimitry Andric       return;
8280eae32dcSDimitry Andric 
8295f757f3fSDimitry Andric     // Do not mangle template deduction guides.
8305f757f3fSDimitry Andric     if (isa<CXXDeductionGuideDecl>(ND))
8315f757f3fSDimitry Andric       return;
8325f757f3fSDimitry Andric 
833480093f4SDimitry Andric     std::string MangledName = ASTNameGen.getName(ND);
834480093f4SDimitry Andric     if (!MangledName.empty())
835480093f4SDimitry Andric       JOS.attribute("mangledName", MangledName);
836480093f4SDimitry Andric   }
8370b57cec5SDimitry Andric }
8380b57cec5SDimitry Andric 
VisitTypedefDecl(const TypedefDecl * TD)8390b57cec5SDimitry Andric void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) {
8400b57cec5SDimitry Andric   VisitNamedDecl(TD);
8410b57cec5SDimitry Andric   JOS.attribute("type", createQualType(TD->getUnderlyingType()));
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric 
VisitTypeAliasDecl(const TypeAliasDecl * TAD)8440b57cec5SDimitry Andric void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) {
8450b57cec5SDimitry Andric   VisitNamedDecl(TAD);
8460b57cec5SDimitry Andric   JOS.attribute("type", createQualType(TAD->getUnderlyingType()));
8470b57cec5SDimitry Andric }
8480b57cec5SDimitry Andric 
VisitNamespaceDecl(const NamespaceDecl * ND)8490b57cec5SDimitry Andric void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {
8500b57cec5SDimitry Andric   VisitNamedDecl(ND);
8510b57cec5SDimitry Andric   attributeOnlyIfTrue("isInline", ND->isInline());
852bdd1243dSDimitry Andric   attributeOnlyIfTrue("isNested", ND->isNested());
8530b57cec5SDimitry Andric   if (!ND->isOriginalNamespace())
8540b57cec5SDimitry Andric     JOS.attribute("originalNamespace",
8550b57cec5SDimitry Andric                   createBareDeclRef(ND->getOriginalNamespace()));
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric 
VisitUsingDirectiveDecl(const UsingDirectiveDecl * UDD)8580b57cec5SDimitry Andric void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {
8590b57cec5SDimitry Andric   JOS.attribute("nominatedNamespace",
8600b57cec5SDimitry Andric                 createBareDeclRef(UDD->getNominatedNamespace()));
8610b57cec5SDimitry Andric }
8620b57cec5SDimitry Andric 
VisitNamespaceAliasDecl(const NamespaceAliasDecl * NAD)8630b57cec5SDimitry Andric void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {
8640b57cec5SDimitry Andric   VisitNamedDecl(NAD);
8650b57cec5SDimitry Andric   JOS.attribute("aliasedNamespace",
8660b57cec5SDimitry Andric                 createBareDeclRef(NAD->getAliasedNamespace()));
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric 
VisitUsingDecl(const UsingDecl * UD)8690b57cec5SDimitry Andric void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) {
8700b57cec5SDimitry Andric   std::string Name;
8710b57cec5SDimitry Andric   if (const NestedNameSpecifier *NNS = UD->getQualifier()) {
8720b57cec5SDimitry Andric     llvm::raw_string_ostream SOS(Name);
8730b57cec5SDimitry Andric     NNS->print(SOS, UD->getASTContext().getPrintingPolicy());
8740b57cec5SDimitry Andric   }
8750b57cec5SDimitry Andric   Name += UD->getNameAsString();
8760b57cec5SDimitry Andric   JOS.attribute("name", Name);
8770b57cec5SDimitry Andric }
8780b57cec5SDimitry Andric 
VisitUsingEnumDecl(const UsingEnumDecl * UED)879fe6060f1SDimitry Andric void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) {
880fe6060f1SDimitry Andric   JOS.attribute("target", createBareDeclRef(UED->getEnumDecl()));
881fe6060f1SDimitry Andric }
882fe6060f1SDimitry Andric 
VisitUsingShadowDecl(const UsingShadowDecl * USD)8830b57cec5SDimitry Andric void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) {
8840b57cec5SDimitry Andric   JOS.attribute("target", createBareDeclRef(USD->getTargetDecl()));
8850b57cec5SDimitry Andric }
8860b57cec5SDimitry Andric 
VisitVarDecl(const VarDecl * VD)8870b57cec5SDimitry Andric void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) {
8880b57cec5SDimitry Andric   VisitNamedDecl(VD);
8890b57cec5SDimitry Andric   JOS.attribute("type", createQualType(VD->getType()));
8905f757f3fSDimitry Andric   if (const auto *P = dyn_cast<ParmVarDecl>(VD))
8915f757f3fSDimitry Andric     attributeOnlyIfTrue("explicitObjectParameter",
8925f757f3fSDimitry Andric                         P->isExplicitObjectParameter());
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric   StorageClass SC = VD->getStorageClass();
8950b57cec5SDimitry Andric   if (SC != SC_None)
8960b57cec5SDimitry Andric     JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));
8970b57cec5SDimitry Andric   switch (VD->getTLSKind()) {
8980b57cec5SDimitry Andric   case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break;
8990b57cec5SDimitry Andric   case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break;
9000b57cec5SDimitry Andric   case VarDecl::TLS_None: break;
9010b57cec5SDimitry Andric   }
9020b57cec5SDimitry Andric   attributeOnlyIfTrue("nrvo", VD->isNRVOVariable());
9030b57cec5SDimitry Andric   attributeOnlyIfTrue("inline", VD->isInline());
9040b57cec5SDimitry Andric   attributeOnlyIfTrue("constexpr", VD->isConstexpr());
9050b57cec5SDimitry Andric   attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate());
9060b57cec5SDimitry Andric   if (VD->hasInit()) {
9070b57cec5SDimitry Andric     switch (VD->getInitStyle()) {
9080b57cec5SDimitry Andric     case VarDecl::CInit: JOS.attribute("init", "c");  break;
9090b57cec5SDimitry Andric     case VarDecl::CallInit: JOS.attribute("init", "call"); break;
9100b57cec5SDimitry Andric     case VarDecl::ListInit: JOS.attribute("init", "list"); break;
911bdd1243dSDimitry Andric     case VarDecl::ParenListInit:
912bdd1243dSDimitry Andric       JOS.attribute("init", "paren-list");
913bdd1243dSDimitry Andric       break;
9140b57cec5SDimitry Andric     }
9150b57cec5SDimitry Andric   }
9160b57cec5SDimitry Andric   attributeOnlyIfTrue("isParameterPack", VD->isParameterPack());
9170b57cec5SDimitry Andric }
9180b57cec5SDimitry Andric 
VisitFieldDecl(const FieldDecl * FD)9190b57cec5SDimitry Andric void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {
9200b57cec5SDimitry Andric   VisitNamedDecl(FD);
9210b57cec5SDimitry Andric   JOS.attribute("type", createQualType(FD->getType()));
9220b57cec5SDimitry Andric   attributeOnlyIfTrue("mutable", FD->isMutable());
9230b57cec5SDimitry Andric   attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate());
9240b57cec5SDimitry Andric   attributeOnlyIfTrue("isBitfield", FD->isBitField());
9250b57cec5SDimitry Andric   attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer());
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric 
VisitFunctionDecl(const FunctionDecl * FD)9280b57cec5SDimitry Andric void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
9290b57cec5SDimitry Andric   VisitNamedDecl(FD);
9300b57cec5SDimitry Andric   JOS.attribute("type", createQualType(FD->getType()));
9310b57cec5SDimitry Andric   StorageClass SC = FD->getStorageClass();
9320b57cec5SDimitry Andric   if (SC != SC_None)
9330b57cec5SDimitry Andric     JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));
9340b57cec5SDimitry Andric   attributeOnlyIfTrue("inline", FD->isInlineSpecified());
9350b57cec5SDimitry Andric   attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten());
9367a6dacacSDimitry Andric   attributeOnlyIfTrue("pure", FD->isPureVirtual());
9370b57cec5SDimitry Andric   attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten());
9380b57cec5SDimitry Andric   attributeOnlyIfTrue("constexpr", FD->isConstexpr());
9390b57cec5SDimitry Andric   attributeOnlyIfTrue("variadic", FD->isVariadic());
94006c3fb27SDimitry Andric   attributeOnlyIfTrue("immediate", FD->isImmediateFunction());
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   if (FD->isDefaulted())
9430b57cec5SDimitry Andric     JOS.attribute("explicitlyDefaulted",
9440b57cec5SDimitry Andric                   FD->isDeleted() ? "deleted" : "default");
9450b57cec5SDimitry Andric }
9460b57cec5SDimitry Andric 
VisitEnumDecl(const EnumDecl * ED)9470b57cec5SDimitry Andric void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) {
9480b57cec5SDimitry Andric   VisitNamedDecl(ED);
9490b57cec5SDimitry Andric   if (ED->isFixed())
9500b57cec5SDimitry Andric     JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType()));
9510b57cec5SDimitry Andric   if (ED->isScoped())
9520b57cec5SDimitry Andric     JOS.attribute("scopedEnumTag",
9530b57cec5SDimitry Andric                   ED->isScopedUsingClassTag() ? "class" : "struct");
9540b57cec5SDimitry Andric }
VisitEnumConstantDecl(const EnumConstantDecl * ECD)9550b57cec5SDimitry Andric void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) {
9560b57cec5SDimitry Andric   VisitNamedDecl(ECD);
9570b57cec5SDimitry Andric   JOS.attribute("type", createQualType(ECD->getType()));
9580b57cec5SDimitry Andric }
9590b57cec5SDimitry Andric 
VisitRecordDecl(const RecordDecl * RD)9600b57cec5SDimitry Andric void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
9610b57cec5SDimitry Andric   VisitNamedDecl(RD);
9620b57cec5SDimitry Andric   JOS.attribute("tagUsed", RD->getKindName());
9630b57cec5SDimitry Andric   attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition());
9640b57cec5SDimitry Andric }
VisitCXXRecordDecl(const CXXRecordDecl * RD)9650b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
9660b57cec5SDimitry Andric   VisitRecordDecl(RD);
9670b57cec5SDimitry Andric 
9680b57cec5SDimitry Andric   // All other information requires a complete definition.
9690b57cec5SDimitry Andric   if (!RD->isCompleteDefinition())
9700b57cec5SDimitry Andric     return;
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   JOS.attribute("definitionData", createCXXRecordDefinitionData(RD));
9730b57cec5SDimitry Andric   if (RD->getNumBases()) {
9740b57cec5SDimitry Andric     JOS.attributeArray("bases", [this, RD] {
9750b57cec5SDimitry Andric       for (const auto &Spec : RD->bases())
9760b57cec5SDimitry Andric         JOS.value(createCXXBaseSpecifier(Spec));
9770b57cec5SDimitry Andric     });
9780b57cec5SDimitry Andric   }
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
VisitHLSLBufferDecl(const HLSLBufferDecl * D)981bdd1243dSDimitry Andric void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
982bdd1243dSDimitry Andric   VisitNamedDecl(D);
983bdd1243dSDimitry Andric   JOS.attribute("bufferKind", D->isCBuffer() ? "cbuffer" : "tbuffer");
984bdd1243dSDimitry Andric }
985bdd1243dSDimitry Andric 
VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)9860b57cec5SDimitry Andric void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
9870b57cec5SDimitry Andric   VisitNamedDecl(D);
9880b57cec5SDimitry Andric   JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class");
9890b57cec5SDimitry Andric   JOS.attribute("depth", D->getDepth());
9900b57cec5SDimitry Andric   JOS.attribute("index", D->getIndex());
9910b57cec5SDimitry Andric   attributeOnlyIfTrue("isParameterPack", D->isParameterPack());
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric   if (D->hasDefaultArgument())
9940b57cec5SDimitry Andric     JOS.attributeObject("defaultArg", [=] {
9950b57cec5SDimitry Andric       Visit(D->getDefaultArgument(), SourceRange(),
9960b57cec5SDimitry Andric             D->getDefaultArgStorage().getInheritedFrom(),
9970b57cec5SDimitry Andric             D->defaultArgumentWasInherited() ? "inherited from" : "previous");
9980b57cec5SDimitry Andric     });
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric 
VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)10010b57cec5SDimitry Andric void JSONNodeDumper::VisitNonTypeTemplateParmDecl(
10020b57cec5SDimitry Andric     const NonTypeTemplateParmDecl *D) {
10030b57cec5SDimitry Andric   VisitNamedDecl(D);
10040b57cec5SDimitry Andric   JOS.attribute("type", createQualType(D->getType()));
10050b57cec5SDimitry Andric   JOS.attribute("depth", D->getDepth());
10060b57cec5SDimitry Andric   JOS.attribute("index", D->getIndex());
10070b57cec5SDimitry Andric   attributeOnlyIfTrue("isParameterPack", D->isParameterPack());
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   if (D->hasDefaultArgument())
10100b57cec5SDimitry Andric     JOS.attributeObject("defaultArg", [=] {
10110b57cec5SDimitry Andric       Visit(D->getDefaultArgument(), SourceRange(),
10120b57cec5SDimitry Andric             D->getDefaultArgStorage().getInheritedFrom(),
10130b57cec5SDimitry Andric             D->defaultArgumentWasInherited() ? "inherited from" : "previous");
10140b57cec5SDimitry Andric     });
10150b57cec5SDimitry Andric }
10160b57cec5SDimitry Andric 
VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)10170b57cec5SDimitry Andric void JSONNodeDumper::VisitTemplateTemplateParmDecl(
10180b57cec5SDimitry Andric     const TemplateTemplateParmDecl *D) {
10190b57cec5SDimitry Andric   VisitNamedDecl(D);
10200b57cec5SDimitry Andric   JOS.attribute("depth", D->getDepth());
10210b57cec5SDimitry Andric   JOS.attribute("index", D->getIndex());
10220b57cec5SDimitry Andric   attributeOnlyIfTrue("isParameterPack", D->isParameterPack());
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   if (D->hasDefaultArgument())
10250b57cec5SDimitry Andric     JOS.attributeObject("defaultArg", [=] {
1026fe6060f1SDimitry Andric       const auto *InheritedFrom = D->getDefaultArgStorage().getInheritedFrom();
10270b57cec5SDimitry Andric       Visit(D->getDefaultArgument().getArgument(),
1028fe6060f1SDimitry Andric             InheritedFrom ? InheritedFrom->getSourceRange() : SourceLocation{},
1029fe6060f1SDimitry Andric             InheritedFrom,
10300b57cec5SDimitry Andric             D->defaultArgumentWasInherited() ? "inherited from" : "previous");
10310b57cec5SDimitry Andric     });
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
VisitLinkageSpecDecl(const LinkageSpecDecl * LSD)10340b57cec5SDimitry Andric void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) {
10350b57cec5SDimitry Andric   StringRef Lang;
10360b57cec5SDimitry Andric   switch (LSD->getLanguage()) {
10375f757f3fSDimitry Andric   case LinkageSpecLanguageIDs::C:
10385f757f3fSDimitry Andric     Lang = "C";
10395f757f3fSDimitry Andric     break;
10405f757f3fSDimitry Andric   case LinkageSpecLanguageIDs::CXX:
10415f757f3fSDimitry Andric     Lang = "C++";
10425f757f3fSDimitry Andric     break;
10430b57cec5SDimitry Andric   }
10440b57cec5SDimitry Andric   JOS.attribute("language", Lang);
10450b57cec5SDimitry Andric   attributeOnlyIfTrue("hasBraces", LSD->hasBraces());
10460b57cec5SDimitry Andric }
10470b57cec5SDimitry Andric 
VisitAccessSpecDecl(const AccessSpecDecl * ASD)10480b57cec5SDimitry Andric void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) {
10490b57cec5SDimitry Andric   JOS.attribute("access", createAccessSpecifier(ASD->getAccess()));
10500b57cec5SDimitry Andric }
10510b57cec5SDimitry Andric 
VisitFriendDecl(const FriendDecl * FD)10520b57cec5SDimitry Andric void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) {
10530b57cec5SDimitry Andric   if (const TypeSourceInfo *T = FD->getFriendType())
10540b57cec5SDimitry Andric     JOS.attribute("type", createQualType(T->getType()));
10550b57cec5SDimitry Andric }
10560b57cec5SDimitry Andric 
VisitObjCIvarDecl(const ObjCIvarDecl * D)10570b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
10580b57cec5SDimitry Andric   VisitNamedDecl(D);
10590b57cec5SDimitry Andric   JOS.attribute("type", createQualType(D->getType()));
10600b57cec5SDimitry Andric   attributeOnlyIfTrue("synthesized", D->getSynthesize());
10610b57cec5SDimitry Andric   switch (D->getAccessControl()) {
10620b57cec5SDimitry Andric   case ObjCIvarDecl::None: JOS.attribute("access", "none"); break;
10630b57cec5SDimitry Andric   case ObjCIvarDecl::Private: JOS.attribute("access", "private"); break;
10640b57cec5SDimitry Andric   case ObjCIvarDecl::Protected: JOS.attribute("access", "protected"); break;
10650b57cec5SDimitry Andric   case ObjCIvarDecl::Public: JOS.attribute("access", "public"); break;
10660b57cec5SDimitry Andric   case ObjCIvarDecl::Package: JOS.attribute("access", "package"); break;
10670b57cec5SDimitry Andric   }
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
VisitObjCMethodDecl(const ObjCMethodDecl * D)10700b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
10710b57cec5SDimitry Andric   VisitNamedDecl(D);
10720b57cec5SDimitry Andric   JOS.attribute("returnType", createQualType(D->getReturnType()));
10730b57cec5SDimitry Andric   JOS.attribute("instance", D->isInstanceMethod());
10740b57cec5SDimitry Andric   attributeOnlyIfTrue("variadic", D->isVariadic());
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric 
VisitObjCTypeParamDecl(const ObjCTypeParamDecl * D)10770b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
10780b57cec5SDimitry Andric   VisitNamedDecl(D);
10790b57cec5SDimitry Andric   JOS.attribute("type", createQualType(D->getUnderlyingType()));
10800b57cec5SDimitry Andric   attributeOnlyIfTrue("bounded", D->hasExplicitBound());
10810b57cec5SDimitry Andric   switch (D->getVariance()) {
10820b57cec5SDimitry Andric   case ObjCTypeParamVariance::Invariant:
10830b57cec5SDimitry Andric     break;
10840b57cec5SDimitry Andric   case ObjCTypeParamVariance::Covariant:
10850b57cec5SDimitry Andric     JOS.attribute("variance", "covariant");
10860b57cec5SDimitry Andric     break;
10870b57cec5SDimitry Andric   case ObjCTypeParamVariance::Contravariant:
10880b57cec5SDimitry Andric     JOS.attribute("variance", "contravariant");
10890b57cec5SDimitry Andric     break;
10900b57cec5SDimitry Andric   }
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric 
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)10930b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
10940b57cec5SDimitry Andric   VisitNamedDecl(D);
10950b57cec5SDimitry Andric   JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
10960b57cec5SDimitry Andric   JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric   llvm::json::Array Protocols;
10990b57cec5SDimitry Andric   for (const auto* P : D->protocols())
11000b57cec5SDimitry Andric     Protocols.push_back(createBareDeclRef(P));
11010b57cec5SDimitry Andric   if (!Protocols.empty())
11020b57cec5SDimitry Andric     JOS.attribute("protocols", std::move(Protocols));
11030b57cec5SDimitry Andric }
11040b57cec5SDimitry Andric 
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)11050b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
11060b57cec5SDimitry Andric   VisitNamedDecl(D);
11070b57cec5SDimitry Andric   JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
11080b57cec5SDimitry Andric   JOS.attribute("categoryDecl", createBareDeclRef(D->getCategoryDecl()));
11090b57cec5SDimitry Andric }
11100b57cec5SDimitry Andric 
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)11110b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
11120b57cec5SDimitry Andric   VisitNamedDecl(D);
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric   llvm::json::Array Protocols;
11150b57cec5SDimitry Andric   for (const auto *P : D->protocols())
11160b57cec5SDimitry Andric     Protocols.push_back(createBareDeclRef(P));
11170b57cec5SDimitry Andric   if (!Protocols.empty())
11180b57cec5SDimitry Andric     JOS.attribute("protocols", std::move(Protocols));
11190b57cec5SDimitry Andric }
11200b57cec5SDimitry Andric 
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)11210b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
11220b57cec5SDimitry Andric   VisitNamedDecl(D);
11230b57cec5SDimitry Andric   JOS.attribute("super", createBareDeclRef(D->getSuperClass()));
11240b57cec5SDimitry Andric   JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric   llvm::json::Array Protocols;
11270b57cec5SDimitry Andric   for (const auto* P : D->protocols())
11280b57cec5SDimitry Andric     Protocols.push_back(createBareDeclRef(P));
11290b57cec5SDimitry Andric   if (!Protocols.empty())
11300b57cec5SDimitry Andric     JOS.attribute("protocols", std::move(Protocols));
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric 
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)11330b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCImplementationDecl(
11340b57cec5SDimitry Andric     const ObjCImplementationDecl *D) {
11350b57cec5SDimitry Andric   VisitNamedDecl(D);
11360b57cec5SDimitry Andric   JOS.attribute("super", createBareDeclRef(D->getSuperClass()));
11370b57cec5SDimitry Andric   JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric 
VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl * D)11400b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCCompatibleAliasDecl(
11410b57cec5SDimitry Andric     const ObjCCompatibleAliasDecl *D) {
11420b57cec5SDimitry Andric   VisitNamedDecl(D);
11430b57cec5SDimitry Andric   JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric 
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)11460b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
11470b57cec5SDimitry Andric   VisitNamedDecl(D);
11480b57cec5SDimitry Andric   JOS.attribute("type", createQualType(D->getType()));
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric   switch (D->getPropertyImplementation()) {
11510b57cec5SDimitry Andric   case ObjCPropertyDecl::None: break;
11520b57cec5SDimitry Andric   case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break;
11530b57cec5SDimitry Andric   case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break;
11540b57cec5SDimitry Andric   }
11550b57cec5SDimitry Andric 
11565ffd83dbSDimitry Andric   ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
11575ffd83dbSDimitry Andric   if (Attrs != ObjCPropertyAttribute::kind_noattr) {
11585ffd83dbSDimitry Andric     if (Attrs & ObjCPropertyAttribute::kind_getter)
11590b57cec5SDimitry Andric       JOS.attribute("getter", createBareDeclRef(D->getGetterMethodDecl()));
11605ffd83dbSDimitry Andric     if (Attrs & ObjCPropertyAttribute::kind_setter)
11610b57cec5SDimitry Andric       JOS.attribute("setter", createBareDeclRef(D->getSetterMethodDecl()));
11625ffd83dbSDimitry Andric     attributeOnlyIfTrue("readonly",
11635ffd83dbSDimitry Andric                         Attrs & ObjCPropertyAttribute::kind_readonly);
11645ffd83dbSDimitry Andric     attributeOnlyIfTrue("assign", Attrs & ObjCPropertyAttribute::kind_assign);
11650b57cec5SDimitry Andric     attributeOnlyIfTrue("readwrite",
11665ffd83dbSDimitry Andric                         Attrs & ObjCPropertyAttribute::kind_readwrite);
11675ffd83dbSDimitry Andric     attributeOnlyIfTrue("retain", Attrs & ObjCPropertyAttribute::kind_retain);
11685ffd83dbSDimitry Andric     attributeOnlyIfTrue("copy", Attrs & ObjCPropertyAttribute::kind_copy);
11690b57cec5SDimitry Andric     attributeOnlyIfTrue("nonatomic",
11705ffd83dbSDimitry Andric                         Attrs & ObjCPropertyAttribute::kind_nonatomic);
11715ffd83dbSDimitry Andric     attributeOnlyIfTrue("atomic", Attrs & ObjCPropertyAttribute::kind_atomic);
11725ffd83dbSDimitry Andric     attributeOnlyIfTrue("weak", Attrs & ObjCPropertyAttribute::kind_weak);
11735ffd83dbSDimitry Andric     attributeOnlyIfTrue("strong", Attrs & ObjCPropertyAttribute::kind_strong);
11740b57cec5SDimitry Andric     attributeOnlyIfTrue("unsafe_unretained",
11755ffd83dbSDimitry Andric                         Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);
11765ffd83dbSDimitry Andric     attributeOnlyIfTrue("class", Attrs & ObjCPropertyAttribute::kind_class);
11775ffd83dbSDimitry Andric     attributeOnlyIfTrue("direct", Attrs & ObjCPropertyAttribute::kind_direct);
11780b57cec5SDimitry Andric     attributeOnlyIfTrue("nullability",
11795ffd83dbSDimitry Andric                         Attrs & ObjCPropertyAttribute::kind_nullability);
11800b57cec5SDimitry Andric     attributeOnlyIfTrue("null_resettable",
11815ffd83dbSDimitry Andric                         Attrs & ObjCPropertyAttribute::kind_null_resettable);
11820b57cec5SDimitry Andric   }
11830b57cec5SDimitry Andric }
11840b57cec5SDimitry Andric 
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)11850b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
11860b57cec5SDimitry Andric   VisitNamedDecl(D->getPropertyDecl());
11870b57cec5SDimitry Andric   JOS.attribute("implKind", D->getPropertyImplementation() ==
11880b57cec5SDimitry Andric                                     ObjCPropertyImplDecl::Synthesize
11890b57cec5SDimitry Andric                                 ? "synthesize"
11900b57cec5SDimitry Andric                                 : "dynamic");
11910b57cec5SDimitry Andric   JOS.attribute("propertyDecl", createBareDeclRef(D->getPropertyDecl()));
11920b57cec5SDimitry Andric   JOS.attribute("ivarDecl", createBareDeclRef(D->getPropertyIvarDecl()));
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric 
VisitBlockDecl(const BlockDecl * D)11950b57cec5SDimitry Andric void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) {
11960b57cec5SDimitry Andric   attributeOnlyIfTrue("variadic", D->isVariadic());
11970b57cec5SDimitry Andric   attributeOnlyIfTrue("capturesThis", D->capturesCXXThis());
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric 
VisitAtomicExpr(const AtomicExpr * AE)12005f757f3fSDimitry Andric void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
12015f757f3fSDimitry Andric   JOS.attribute("name", AE->getOpAsString());
12025f757f3fSDimitry Andric }
12035f757f3fSDimitry Andric 
VisitObjCEncodeExpr(const ObjCEncodeExpr * OEE)12040b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) {
12050b57cec5SDimitry Andric   JOS.attribute("encodedType", createQualType(OEE->getEncodedType()));
12060b57cec5SDimitry Andric }
12070b57cec5SDimitry Andric 
VisitObjCMessageExpr(const ObjCMessageExpr * OME)12080b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *OME) {
12090b57cec5SDimitry Andric   std::string Str;
12100b57cec5SDimitry Andric   llvm::raw_string_ostream OS(Str);
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric   OME->getSelector().print(OS);
12130b57cec5SDimitry Andric   JOS.attribute("selector", OS.str());
12140b57cec5SDimitry Andric 
12150b57cec5SDimitry Andric   switch (OME->getReceiverKind()) {
12160b57cec5SDimitry Andric   case ObjCMessageExpr::Instance:
12170b57cec5SDimitry Andric     JOS.attribute("receiverKind", "instance");
12180b57cec5SDimitry Andric     break;
12190b57cec5SDimitry Andric   case ObjCMessageExpr::Class:
12200b57cec5SDimitry Andric     JOS.attribute("receiverKind", "class");
12210b57cec5SDimitry Andric     JOS.attribute("classType", createQualType(OME->getClassReceiver()));
12220b57cec5SDimitry Andric     break;
12230b57cec5SDimitry Andric   case ObjCMessageExpr::SuperInstance:
12240b57cec5SDimitry Andric     JOS.attribute("receiverKind", "super (instance)");
12250b57cec5SDimitry Andric     JOS.attribute("superType", createQualType(OME->getSuperType()));
12260b57cec5SDimitry Andric     break;
12270b57cec5SDimitry Andric   case ObjCMessageExpr::SuperClass:
12280b57cec5SDimitry Andric     JOS.attribute("receiverKind", "super (class)");
12290b57cec5SDimitry Andric     JOS.attribute("superType", createQualType(OME->getSuperType()));
12300b57cec5SDimitry Andric     break;
12310b57cec5SDimitry Andric   }
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   QualType CallReturnTy = OME->getCallReturnType(Ctx);
12340b57cec5SDimitry Andric   if (OME->getType() != CallReturnTy)
12350b57cec5SDimitry Andric     JOS.attribute("callReturnType", createQualType(CallReturnTy));
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric 
VisitObjCBoxedExpr(const ObjCBoxedExpr * OBE)12380b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE) {
12390b57cec5SDimitry Andric   if (const ObjCMethodDecl *MD = OBE->getBoxingMethod()) {
12400b57cec5SDimitry Andric     std::string Str;
12410b57cec5SDimitry Andric     llvm::raw_string_ostream OS(Str);
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric     MD->getSelector().print(OS);
12440b57cec5SDimitry Andric     JOS.attribute("selector", OS.str());
12450b57cec5SDimitry Andric   }
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric 
VisitObjCSelectorExpr(const ObjCSelectorExpr * OSE)12480b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE) {
12490b57cec5SDimitry Andric   std::string Str;
12500b57cec5SDimitry Andric   llvm::raw_string_ostream OS(Str);
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric   OSE->getSelector().print(OS);
12530b57cec5SDimitry Andric   JOS.attribute("selector", OS.str());
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
VisitObjCProtocolExpr(const ObjCProtocolExpr * OPE)12560b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {
12570b57cec5SDimitry Andric   JOS.attribute("protocol", createBareDeclRef(OPE->getProtocol()));
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr * OPRE)12600b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {
12610b57cec5SDimitry Andric   if (OPRE->isImplicitProperty()) {
12620b57cec5SDimitry Andric     JOS.attribute("propertyKind", "implicit");
12630b57cec5SDimitry Andric     if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter())
12640b57cec5SDimitry Andric       JOS.attribute("getter", createBareDeclRef(MD));
12650b57cec5SDimitry Andric     if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter())
12660b57cec5SDimitry Andric       JOS.attribute("setter", createBareDeclRef(MD));
12670b57cec5SDimitry Andric   } else {
12680b57cec5SDimitry Andric     JOS.attribute("propertyKind", "explicit");
12690b57cec5SDimitry Andric     JOS.attribute("property", createBareDeclRef(OPRE->getExplicitProperty()));
12700b57cec5SDimitry Andric   }
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric   attributeOnlyIfTrue("isSuperReceiver", OPRE->isSuperReceiver());
12730b57cec5SDimitry Andric   attributeOnlyIfTrue("isMessagingGetter", OPRE->isMessagingGetter());
12740b57cec5SDimitry Andric   attributeOnlyIfTrue("isMessagingSetter", OPRE->isMessagingSetter());
12750b57cec5SDimitry Andric }
12760b57cec5SDimitry Andric 
VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr * OSRE)12770b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCSubscriptRefExpr(
12780b57cec5SDimitry Andric     const ObjCSubscriptRefExpr *OSRE) {
12790b57cec5SDimitry Andric   JOS.attribute("subscriptKind",
12800b57cec5SDimitry Andric                 OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary");
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric   if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl())
12830b57cec5SDimitry Andric     JOS.attribute("getter", createBareDeclRef(MD));
12840b57cec5SDimitry Andric   if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl())
12850b57cec5SDimitry Andric     JOS.attribute("setter", createBareDeclRef(MD));
12860b57cec5SDimitry Andric }
12870b57cec5SDimitry Andric 
VisitObjCIvarRefExpr(const ObjCIvarRefExpr * OIRE)12880b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {
12890b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(OIRE->getDecl()));
12900b57cec5SDimitry Andric   attributeOnlyIfTrue("isFreeIvar", OIRE->isFreeIvar());
12910b57cec5SDimitry Andric   JOS.attribute("isArrow", OIRE->isArrow());
12920b57cec5SDimitry Andric }
12930b57cec5SDimitry Andric 
VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr * OBLE)12940b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) {
12950b57cec5SDimitry Andric   JOS.attribute("value", OBLE->getValue() ? "__objc_yes" : "__objc_no");
12960b57cec5SDimitry Andric }
12970b57cec5SDimitry Andric 
VisitDeclRefExpr(const DeclRefExpr * DRE)12980b57cec5SDimitry Andric void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
12990b57cec5SDimitry Andric   JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl()));
13000b57cec5SDimitry Andric   if (DRE->getDecl() != DRE->getFoundDecl())
13010b57cec5SDimitry Andric     JOS.attribute("foundReferencedDecl",
13020b57cec5SDimitry Andric                   createBareDeclRef(DRE->getFoundDecl()));
13030b57cec5SDimitry Andric   switch (DRE->isNonOdrUse()) {
13040b57cec5SDimitry Andric   case NOUR_None: break;
13050b57cec5SDimitry Andric   case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;
13060b57cec5SDimitry Andric   case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;
13070b57cec5SDimitry Andric   case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
13080b57cec5SDimitry Andric   }
130906c3fb27SDimitry Andric   attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating());
13100b57cec5SDimitry Andric }
13110b57cec5SDimitry Andric 
VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr * E)1312fe6060f1SDimitry Andric void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
1313fe6060f1SDimitry Andric     const SYCLUniqueStableNameExpr *E) {
1314fe6060f1SDimitry Andric   JOS.attribute("typeSourceInfo",
1315fe6060f1SDimitry Andric                 createQualType(E->getTypeSourceInfo()->getType()));
1316fe6060f1SDimitry Andric }
1317fe6060f1SDimitry Andric 
VisitPredefinedExpr(const PredefinedExpr * PE)13180b57cec5SDimitry Andric void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
13190b57cec5SDimitry Andric   JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));
13200b57cec5SDimitry Andric }
13210b57cec5SDimitry Andric 
VisitUnaryOperator(const UnaryOperator * UO)13220b57cec5SDimitry Andric void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {
13230b57cec5SDimitry Andric   JOS.attribute("isPostfix", UO->isPostfix());
13240b57cec5SDimitry Andric   JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode()));
13250b57cec5SDimitry Andric   if (!UO->canOverflow())
13260b57cec5SDimitry Andric     JOS.attribute("canOverflow", false);
13270b57cec5SDimitry Andric }
13280b57cec5SDimitry Andric 
VisitBinaryOperator(const BinaryOperator * BO)13290b57cec5SDimitry Andric void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) {
13300b57cec5SDimitry Andric   JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode()));
13310b57cec5SDimitry Andric }
13320b57cec5SDimitry Andric 
VisitCompoundAssignOperator(const CompoundAssignOperator * CAO)13330b57cec5SDimitry Andric void JSONNodeDumper::VisitCompoundAssignOperator(
13340b57cec5SDimitry Andric     const CompoundAssignOperator *CAO) {
13350b57cec5SDimitry Andric   VisitBinaryOperator(CAO);
13360b57cec5SDimitry Andric   JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType()));
13370b57cec5SDimitry Andric   JOS.attribute("computeResultType",
13380b57cec5SDimitry Andric                 createQualType(CAO->getComputationResultType()));
13390b57cec5SDimitry Andric }
13400b57cec5SDimitry Andric 
VisitMemberExpr(const MemberExpr * ME)13410b57cec5SDimitry Andric void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) {
13420b57cec5SDimitry Andric   // Note, we always write this Boolean field because the information it conveys
13430b57cec5SDimitry Andric   // is critical to understanding the AST node.
13440b57cec5SDimitry Andric   ValueDecl *VD = ME->getMemberDecl();
13450b57cec5SDimitry Andric   JOS.attribute("name", VD && VD->getDeclName() ? VD->getNameAsString() : "");
13460b57cec5SDimitry Andric   JOS.attribute("isArrow", ME->isArrow());
13470b57cec5SDimitry Andric   JOS.attribute("referencedMemberDecl", createPointerRepresentation(VD));
13480b57cec5SDimitry Andric   switch (ME->isNonOdrUse()) {
13490b57cec5SDimitry Andric   case NOUR_None: break;
13500b57cec5SDimitry Andric   case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;
13510b57cec5SDimitry Andric   case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;
13520b57cec5SDimitry Andric   case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
13530b57cec5SDimitry Andric   }
13540b57cec5SDimitry Andric }
13550b57cec5SDimitry Andric 
VisitCXXNewExpr(const CXXNewExpr * NE)13560b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {
13570b57cec5SDimitry Andric   attributeOnlyIfTrue("isGlobal", NE->isGlobalNew());
13580b57cec5SDimitry Andric   attributeOnlyIfTrue("isArray", NE->isArray());
13590b57cec5SDimitry Andric   attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0);
13600b57cec5SDimitry Andric   switch (NE->getInitializationStyle()) {
13615f757f3fSDimitry Andric   case CXXNewInitializationStyle::None:
13625f757f3fSDimitry Andric     break;
13637a6dacacSDimitry Andric   case CXXNewInitializationStyle::Parens:
13645f757f3fSDimitry Andric     JOS.attribute("initStyle", "call");
13655f757f3fSDimitry Andric     break;
13667a6dacacSDimitry Andric   case CXXNewInitializationStyle::Braces:
13675f757f3fSDimitry Andric     JOS.attribute("initStyle", "list");
13685f757f3fSDimitry Andric     break;
13690b57cec5SDimitry Andric   }
13700b57cec5SDimitry Andric   if (const FunctionDecl *FD = NE->getOperatorNew())
13710b57cec5SDimitry Andric     JOS.attribute("operatorNewDecl", createBareDeclRef(FD));
13720b57cec5SDimitry Andric   if (const FunctionDecl *FD = NE->getOperatorDelete())
13730b57cec5SDimitry Andric     JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));
13740b57cec5SDimitry Andric }
VisitCXXDeleteExpr(const CXXDeleteExpr * DE)13750b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {
13760b57cec5SDimitry Andric   attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete());
13770b57cec5SDimitry Andric   attributeOnlyIfTrue("isArray", DE->isArrayForm());
13780b57cec5SDimitry Andric   attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten());
13790b57cec5SDimitry Andric   if (const FunctionDecl *FD = DE->getOperatorDelete())
13800b57cec5SDimitry Andric     JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));
13810b57cec5SDimitry Andric }
13820b57cec5SDimitry Andric 
VisitCXXThisExpr(const CXXThisExpr * TE)13830b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) {
13840b57cec5SDimitry Andric   attributeOnlyIfTrue("implicit", TE->isImplicit());
13850b57cec5SDimitry Andric }
13860b57cec5SDimitry Andric 
VisitCastExpr(const CastExpr * CE)13870b57cec5SDimitry Andric void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) {
13880b57cec5SDimitry Andric   JOS.attribute("castKind", CE->getCastKindName());
13890b57cec5SDimitry Andric   llvm::json::Array Path = createCastPath(CE);
13900b57cec5SDimitry Andric   if (!Path.empty())
13910b57cec5SDimitry Andric     JOS.attribute("path", std::move(Path));
13920b57cec5SDimitry Andric   // FIXME: This may not be useful information as it can be obtusely gleaned
13930b57cec5SDimitry Andric   // from the inner[] array.
13940b57cec5SDimitry Andric   if (const NamedDecl *ND = CE->getConversionFunction())
13950b57cec5SDimitry Andric     JOS.attribute("conversionFunc", createBareDeclRef(ND));
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric 
VisitImplicitCastExpr(const ImplicitCastExpr * ICE)13980b57cec5SDimitry Andric void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
13990b57cec5SDimitry Andric   VisitCastExpr(ICE);
14000b57cec5SDimitry Andric   attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast());
14010b57cec5SDimitry Andric }
14020b57cec5SDimitry Andric 
VisitCallExpr(const CallExpr * CE)14030b57cec5SDimitry Andric void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {
14040b57cec5SDimitry Andric   attributeOnlyIfTrue("adl", CE->usesADL());
14050b57cec5SDimitry Andric }
14060b57cec5SDimitry Andric 
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr * TTE)14070b57cec5SDimitry Andric void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
14080b57cec5SDimitry Andric     const UnaryExprOrTypeTraitExpr *TTE) {
14095ffd83dbSDimitry Andric   JOS.attribute("name", getTraitSpelling(TTE->getKind()));
14100b57cec5SDimitry Andric   if (TTE->isArgumentType())
14110b57cec5SDimitry Andric     JOS.attribute("argType", createQualType(TTE->getArgumentType()));
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
VisitSizeOfPackExpr(const SizeOfPackExpr * SOPE)14140b57cec5SDimitry Andric void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) {
14150b57cec5SDimitry Andric   VisitNamedDecl(SOPE->getPack());
14160b57cec5SDimitry Andric }
14170b57cec5SDimitry Andric 
VisitUnresolvedLookupExpr(const UnresolvedLookupExpr * ULE)14180b57cec5SDimitry Andric void JSONNodeDumper::VisitUnresolvedLookupExpr(
14190b57cec5SDimitry Andric     const UnresolvedLookupExpr *ULE) {
14200b57cec5SDimitry Andric   JOS.attribute("usesADL", ULE->requiresADL());
14210b57cec5SDimitry Andric   JOS.attribute("name", ULE->getName().getAsString());
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric   JOS.attributeArray("lookups", [this, ULE] {
14240b57cec5SDimitry Andric     for (const NamedDecl *D : ULE->decls())
14250b57cec5SDimitry Andric       JOS.value(createBareDeclRef(D));
14260b57cec5SDimitry Andric   });
14270b57cec5SDimitry Andric }
14280b57cec5SDimitry Andric 
VisitAddrLabelExpr(const AddrLabelExpr * ALE)14290b57cec5SDimitry Andric void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) {
14300b57cec5SDimitry Andric   JOS.attribute("name", ALE->getLabel()->getName());
14310b57cec5SDimitry Andric   JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel()));
14320b57cec5SDimitry Andric }
14330b57cec5SDimitry Andric 
VisitCXXTypeidExpr(const CXXTypeidExpr * CTE)14340b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
14350b57cec5SDimitry Andric   if (CTE->isTypeOperand()) {
14360b57cec5SDimitry Andric     QualType Adjusted = CTE->getTypeOperand(Ctx);
14370b57cec5SDimitry Andric     QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType();
14380b57cec5SDimitry Andric     JOS.attribute("typeArg", createQualType(Unadjusted));
14390b57cec5SDimitry Andric     if (Adjusted != Unadjusted)
14400b57cec5SDimitry Andric       JOS.attribute("adjustedTypeArg", createQualType(Adjusted));
14410b57cec5SDimitry Andric   }
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric 
VisitConstantExpr(const ConstantExpr * CE)14440b57cec5SDimitry Andric void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
14455ffd83dbSDimitry Andric   if (CE->getResultAPValueKind() != APValue::None)
14465ffd83dbSDimitry Andric     Visit(CE->getAPValueResult(), CE->getType());
14470b57cec5SDimitry Andric }
14480b57cec5SDimitry Andric 
VisitInitListExpr(const InitListExpr * ILE)14490b57cec5SDimitry Andric void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
14500b57cec5SDimitry Andric   if (const FieldDecl *FD = ILE->getInitializedFieldInUnion())
14510b57cec5SDimitry Andric     JOS.attribute("field", createBareDeclRef(FD));
14520b57cec5SDimitry Andric }
14530b57cec5SDimitry Andric 
VisitGenericSelectionExpr(const GenericSelectionExpr * GSE)14540b57cec5SDimitry Andric void JSONNodeDumper::VisitGenericSelectionExpr(
14550b57cec5SDimitry Andric     const GenericSelectionExpr *GSE) {
14560b57cec5SDimitry Andric   attributeOnlyIfTrue("resultDependent", GSE->isResultDependent());
14570b57cec5SDimitry Andric }
14580b57cec5SDimitry Andric 
VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr * UCE)14590b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(
14600b57cec5SDimitry Andric     const CXXUnresolvedConstructExpr *UCE) {
14610b57cec5SDimitry Andric   if (UCE->getType() != UCE->getTypeAsWritten())
14620b57cec5SDimitry Andric     JOS.attribute("typeAsWritten", createQualType(UCE->getTypeAsWritten()));
14630b57cec5SDimitry Andric   attributeOnlyIfTrue("list", UCE->isListInitialization());
14640b57cec5SDimitry Andric }
14650b57cec5SDimitry Andric 
VisitCXXConstructExpr(const CXXConstructExpr * CE)14660b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) {
14670b57cec5SDimitry Andric   CXXConstructorDecl *Ctor = CE->getConstructor();
14680b57cec5SDimitry Andric   JOS.attribute("ctorType", createQualType(Ctor->getType()));
14690b57cec5SDimitry Andric   attributeOnlyIfTrue("elidable", CE->isElidable());
14700b57cec5SDimitry Andric   attributeOnlyIfTrue("list", CE->isListInitialization());
14710b57cec5SDimitry Andric   attributeOnlyIfTrue("initializer_list", CE->isStdInitListInitialization());
14720b57cec5SDimitry Andric   attributeOnlyIfTrue("zeroing", CE->requiresZeroInitialization());
14730b57cec5SDimitry Andric   attributeOnlyIfTrue("hadMultipleCandidates", CE->hadMultipleCandidates());
147406c3fb27SDimitry Andric   attributeOnlyIfTrue("isImmediateEscalating", CE->isImmediateEscalating());
14750b57cec5SDimitry Andric 
14760b57cec5SDimitry Andric   switch (CE->getConstructionKind()) {
14775f757f3fSDimitry Andric   case CXXConstructionKind::Complete:
14780b57cec5SDimitry Andric     JOS.attribute("constructionKind", "complete");
14790b57cec5SDimitry Andric     break;
14805f757f3fSDimitry Andric   case CXXConstructionKind::Delegating:
14810b57cec5SDimitry Andric     JOS.attribute("constructionKind", "delegating");
14820b57cec5SDimitry Andric     break;
14835f757f3fSDimitry Andric   case CXXConstructionKind::NonVirtualBase:
14840b57cec5SDimitry Andric     JOS.attribute("constructionKind", "non-virtual base");
14850b57cec5SDimitry Andric     break;
14865f757f3fSDimitry Andric   case CXXConstructionKind::VirtualBase:
14870b57cec5SDimitry Andric     JOS.attribute("constructionKind", "virtual base");
14880b57cec5SDimitry Andric     break;
14890b57cec5SDimitry Andric   }
14900b57cec5SDimitry Andric }
14910b57cec5SDimitry Andric 
VisitExprWithCleanups(const ExprWithCleanups * EWC)14920b57cec5SDimitry Andric void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {
14930b57cec5SDimitry Andric   attributeOnlyIfTrue("cleanupsHaveSideEffects",
14940b57cec5SDimitry Andric                       EWC->cleanupsHaveSideEffects());
14950b57cec5SDimitry Andric   if (EWC->getNumObjects()) {
14960b57cec5SDimitry Andric     JOS.attributeArray("cleanups", [this, EWC] {
14970b57cec5SDimitry Andric       for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())
14985ffd83dbSDimitry Andric         if (auto *BD = CO.dyn_cast<BlockDecl *>()) {
14995ffd83dbSDimitry Andric           JOS.value(createBareDeclRef(BD));
15005ffd83dbSDimitry Andric         } else if (auto *CLE = CO.dyn_cast<CompoundLiteralExpr *>()) {
15015ffd83dbSDimitry Andric           llvm::json::Object Obj;
15025ffd83dbSDimitry Andric           Obj["id"] = createPointerRepresentation(CLE);
15035ffd83dbSDimitry Andric           Obj["kind"] = CLE->getStmtClassName();
15045ffd83dbSDimitry Andric           JOS.value(std::move(Obj));
15055ffd83dbSDimitry Andric         } else {
15065ffd83dbSDimitry Andric           llvm_unreachable("unexpected cleanup object type");
15075ffd83dbSDimitry Andric         }
15080b57cec5SDimitry Andric     });
15090b57cec5SDimitry Andric   }
15100b57cec5SDimitry Andric }
15110b57cec5SDimitry Andric 
VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr * BTE)15120b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXBindTemporaryExpr(
15130b57cec5SDimitry Andric     const CXXBindTemporaryExpr *BTE) {
15140b57cec5SDimitry Andric   const CXXTemporary *Temp = BTE->getTemporary();
15150b57cec5SDimitry Andric   JOS.attribute("temp", createPointerRepresentation(Temp));
15160b57cec5SDimitry Andric   if (const CXXDestructorDecl *Dtor = Temp->getDestructor())
15170b57cec5SDimitry Andric     JOS.attribute("dtor", createBareDeclRef(Dtor));
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric 
VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr * MTE)15200b57cec5SDimitry Andric void JSONNodeDumper::VisitMaterializeTemporaryExpr(
15210b57cec5SDimitry Andric     const MaterializeTemporaryExpr *MTE) {
15220b57cec5SDimitry Andric   if (const ValueDecl *VD = MTE->getExtendingDecl())
15230b57cec5SDimitry Andric     JOS.attribute("extendingDecl", createBareDeclRef(VD));
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric   switch (MTE->getStorageDuration()) {
15260b57cec5SDimitry Andric   case SD_Automatic:
15270b57cec5SDimitry Andric     JOS.attribute("storageDuration", "automatic");
15280b57cec5SDimitry Andric     break;
15290b57cec5SDimitry Andric   case SD_Dynamic:
15300b57cec5SDimitry Andric     JOS.attribute("storageDuration", "dynamic");
15310b57cec5SDimitry Andric     break;
15320b57cec5SDimitry Andric   case SD_FullExpression:
15330b57cec5SDimitry Andric     JOS.attribute("storageDuration", "full expression");
15340b57cec5SDimitry Andric     break;
15350b57cec5SDimitry Andric   case SD_Static:
15360b57cec5SDimitry Andric     JOS.attribute("storageDuration", "static");
15370b57cec5SDimitry Andric     break;
15380b57cec5SDimitry Andric   case SD_Thread:
15390b57cec5SDimitry Andric     JOS.attribute("storageDuration", "thread");
15400b57cec5SDimitry Andric     break;
15410b57cec5SDimitry Andric   }
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric   attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference());
15440b57cec5SDimitry Andric }
15450b57cec5SDimitry Andric 
VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr * DSME)15460b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
15470b57cec5SDimitry Andric     const CXXDependentScopeMemberExpr *DSME) {
15480b57cec5SDimitry Andric   JOS.attribute("isArrow", DSME->isArrow());
15490b57cec5SDimitry Andric   JOS.attribute("member", DSME->getMember().getAsString());
15500b57cec5SDimitry Andric   attributeOnlyIfTrue("hasTemplateKeyword", DSME->hasTemplateKeyword());
15510b57cec5SDimitry Andric   attributeOnlyIfTrue("hasExplicitTemplateArgs",
15520b57cec5SDimitry Andric                       DSME->hasExplicitTemplateArgs());
15530b57cec5SDimitry Andric 
15540b57cec5SDimitry Andric   if (DSME->getNumTemplateArgs()) {
15550b57cec5SDimitry Andric     JOS.attributeArray("explicitTemplateArgs", [DSME, this] {
15560b57cec5SDimitry Andric       for (const TemplateArgumentLoc &TAL : DSME->template_arguments())
15570b57cec5SDimitry Andric         JOS.object(
15580b57cec5SDimitry Andric             [&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });
15590b57cec5SDimitry Andric     });
15600b57cec5SDimitry Andric   }
15610b57cec5SDimitry Andric }
15620b57cec5SDimitry Andric 
VisitRequiresExpr(const RequiresExpr * RE)1563fe6060f1SDimitry Andric void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {
1564fe6060f1SDimitry Andric   if (!RE->isValueDependent())
1565fe6060f1SDimitry Andric     JOS.attribute("satisfied", RE->isSatisfied());
1566fe6060f1SDimitry Andric }
1567fe6060f1SDimitry Andric 
VisitIntegerLiteral(const IntegerLiteral * IL)15680b57cec5SDimitry Andric void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {
1569fe6060f1SDimitry Andric   llvm::SmallString<16> Buffer;
1570fe6060f1SDimitry Andric   IL->getValue().toString(Buffer,
1571fe6060f1SDimitry Andric                           /*Radix=*/10, IL->getType()->isSignedIntegerType());
1572fe6060f1SDimitry Andric   JOS.attribute("value", Buffer);
15730b57cec5SDimitry Andric }
VisitCharacterLiteral(const CharacterLiteral * CL)15740b57cec5SDimitry Andric void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) {
15750b57cec5SDimitry Andric   // FIXME: This should probably print the character literal as a string,
15760b57cec5SDimitry Andric   // rather than as a numerical value. It would be nice if the behavior matched
15770b57cec5SDimitry Andric   // what we do to print a string literal; right now, it is impossible to tell
15780b57cec5SDimitry Andric   // the difference between 'a' and L'a' in C from the JSON output.
15790b57cec5SDimitry Andric   JOS.attribute("value", CL->getValue());
15800b57cec5SDimitry Andric }
VisitFixedPointLiteral(const FixedPointLiteral * FPL)15810b57cec5SDimitry Andric void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) {
15820b57cec5SDimitry Andric   JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10));
15830b57cec5SDimitry Andric }
VisitFloatingLiteral(const FloatingLiteral * FL)15840b57cec5SDimitry Andric void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) {
1585e8d8bef9SDimitry Andric   llvm::SmallString<16> Buffer;
15860b57cec5SDimitry Andric   FL->getValue().toString(Buffer);
15870b57cec5SDimitry Andric   JOS.attribute("value", Buffer);
15880b57cec5SDimitry Andric }
VisitStringLiteral(const StringLiteral * SL)15890b57cec5SDimitry Andric void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) {
15900b57cec5SDimitry Andric   std::string Buffer;
15910b57cec5SDimitry Andric   llvm::raw_string_ostream SS(Buffer);
15920b57cec5SDimitry Andric   SL->outputString(SS);
15930b57cec5SDimitry Andric   JOS.attribute("value", SS.str());
15940b57cec5SDimitry Andric }
VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr * BLE)15950b57cec5SDimitry Andric void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) {
15960b57cec5SDimitry Andric   JOS.attribute("value", BLE->getValue());
15970b57cec5SDimitry Andric }
15980b57cec5SDimitry Andric 
VisitIfStmt(const IfStmt * IS)15990b57cec5SDimitry Andric void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) {
16000b57cec5SDimitry Andric   attributeOnlyIfTrue("hasInit", IS->hasInitStorage());
16010b57cec5SDimitry Andric   attributeOnlyIfTrue("hasVar", IS->hasVarStorage());
16020b57cec5SDimitry Andric   attributeOnlyIfTrue("hasElse", IS->hasElseStorage());
16030b57cec5SDimitry Andric   attributeOnlyIfTrue("isConstexpr", IS->isConstexpr());
1604349cc55cSDimitry Andric   attributeOnlyIfTrue("isConsteval", IS->isConsteval());
1605349cc55cSDimitry Andric   attributeOnlyIfTrue("constevalIsNegated", IS->isNegatedConsteval());
16060b57cec5SDimitry Andric }
16070b57cec5SDimitry Andric 
VisitSwitchStmt(const SwitchStmt * SS)16080b57cec5SDimitry Andric void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) {
16090b57cec5SDimitry Andric   attributeOnlyIfTrue("hasInit", SS->hasInitStorage());
16100b57cec5SDimitry Andric   attributeOnlyIfTrue("hasVar", SS->hasVarStorage());
16110b57cec5SDimitry Andric }
VisitCaseStmt(const CaseStmt * CS)16120b57cec5SDimitry Andric void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
16130b57cec5SDimitry Andric   attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange());
16140b57cec5SDimitry Andric }
16150b57cec5SDimitry Andric 
VisitLabelStmt(const LabelStmt * LS)16160b57cec5SDimitry Andric void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
16170b57cec5SDimitry Andric   JOS.attribute("name", LS->getName());
16180b57cec5SDimitry Andric   JOS.attribute("declId", createPointerRepresentation(LS->getDecl()));
1619fe6060f1SDimitry Andric   attributeOnlyIfTrue("sideEntry", LS->isSideEntry());
16200b57cec5SDimitry Andric }
VisitGotoStmt(const GotoStmt * GS)16210b57cec5SDimitry Andric void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
16220b57cec5SDimitry Andric   JOS.attribute("targetLabelDeclId",
16230b57cec5SDimitry Andric                 createPointerRepresentation(GS->getLabel()));
16240b57cec5SDimitry Andric }
16250b57cec5SDimitry Andric 
VisitWhileStmt(const WhileStmt * WS)16260b57cec5SDimitry Andric void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) {
16270b57cec5SDimitry Andric   attributeOnlyIfTrue("hasVar", WS->hasVarStorage());
16280b57cec5SDimitry Andric }
16290b57cec5SDimitry Andric 
VisitObjCAtCatchStmt(const ObjCAtCatchStmt * OACS)16300b57cec5SDimitry Andric void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) {
16310b57cec5SDimitry Andric   // FIXME: it would be nice for the ASTNodeTraverser would handle the catch
16320b57cec5SDimitry Andric   // parameter the same way for C++ and ObjC rather. In this case, C++ gets a
16330b57cec5SDimitry Andric   // null child node and ObjC gets no child node.
16340b57cec5SDimitry Andric   attributeOnlyIfTrue("isCatchAll", OACS->getCatchParamDecl() == nullptr);
16350b57cec5SDimitry Andric }
16360b57cec5SDimitry Andric 
VisitNullTemplateArgument(const TemplateArgument & TA)16370b57cec5SDimitry Andric void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) {
16380b57cec5SDimitry Andric   JOS.attribute("isNull", true);
16390b57cec5SDimitry Andric }
VisitTypeTemplateArgument(const TemplateArgument & TA)16400b57cec5SDimitry Andric void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
16410b57cec5SDimitry Andric   JOS.attribute("type", createQualType(TA.getAsType()));
16420b57cec5SDimitry Andric }
VisitDeclarationTemplateArgument(const TemplateArgument & TA)16430b57cec5SDimitry Andric void JSONNodeDumper::VisitDeclarationTemplateArgument(
16440b57cec5SDimitry Andric     const TemplateArgument &TA) {
16450b57cec5SDimitry Andric   JOS.attribute("decl", createBareDeclRef(TA.getAsDecl()));
16460b57cec5SDimitry Andric }
VisitNullPtrTemplateArgument(const TemplateArgument & TA)16470b57cec5SDimitry Andric void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) {
16480b57cec5SDimitry Andric   JOS.attribute("isNullptr", true);
16490b57cec5SDimitry Andric }
VisitIntegralTemplateArgument(const TemplateArgument & TA)16500b57cec5SDimitry Andric void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
16510b57cec5SDimitry Andric   JOS.attribute("value", TA.getAsIntegral().getSExtValue());
16520b57cec5SDimitry Andric }
VisitTemplateTemplateArgument(const TemplateArgument & TA)16530b57cec5SDimitry Andric void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
16540b57cec5SDimitry Andric   // FIXME: cannot just call dump() on the argument, as that doesn't specify
16550b57cec5SDimitry Andric   // the output format.
16560b57cec5SDimitry Andric }
VisitTemplateExpansionTemplateArgument(const TemplateArgument & TA)16570b57cec5SDimitry Andric void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
16580b57cec5SDimitry Andric     const TemplateArgument &TA) {
16590b57cec5SDimitry Andric   // FIXME: cannot just call dump() on the argument, as that doesn't specify
16600b57cec5SDimitry Andric   // the output format.
16610b57cec5SDimitry Andric }
VisitExpressionTemplateArgument(const TemplateArgument & TA)16620b57cec5SDimitry Andric void JSONNodeDumper::VisitExpressionTemplateArgument(
16630b57cec5SDimitry Andric     const TemplateArgument &TA) {
16640b57cec5SDimitry Andric   JOS.attribute("isExpr", true);
16650b57cec5SDimitry Andric }
VisitPackTemplateArgument(const TemplateArgument & TA)16660b57cec5SDimitry Andric void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
16670b57cec5SDimitry Andric   JOS.attribute("isPack", true);
16680b57cec5SDimitry Andric }
16690b57cec5SDimitry Andric 
getCommentCommandName(unsigned CommandID) const16700b57cec5SDimitry Andric StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const {
16710b57cec5SDimitry Andric   if (Traits)
16720b57cec5SDimitry Andric     return Traits->getCommandInfo(CommandID)->Name;
16730b57cec5SDimitry Andric   if (const comments::CommandInfo *Info =
16740b57cec5SDimitry Andric           comments::CommandTraits::getBuiltinCommandInfo(CommandID))
16750b57cec5SDimitry Andric     return Info->Name;
16760b57cec5SDimitry Andric   return "<invalid>";
16770b57cec5SDimitry Andric }
16780b57cec5SDimitry Andric 
visitTextComment(const comments::TextComment * C,const comments::FullComment *)16790b57cec5SDimitry Andric void JSONNodeDumper::visitTextComment(const comments::TextComment *C,
16800b57cec5SDimitry Andric                                       const comments::FullComment *) {
16810b57cec5SDimitry Andric   JOS.attribute("text", C->getText());
16820b57cec5SDimitry Andric }
16830b57cec5SDimitry Andric 
visitInlineCommandComment(const comments::InlineCommandComment * C,const comments::FullComment *)16840b57cec5SDimitry Andric void JSONNodeDumper::visitInlineCommandComment(
16850b57cec5SDimitry Andric     const comments::InlineCommandComment *C, const comments::FullComment *) {
16860b57cec5SDimitry Andric   JOS.attribute("name", getCommentCommandName(C->getCommandID()));
16870b57cec5SDimitry Andric 
16880b57cec5SDimitry Andric   switch (C->getRenderKind()) {
16895f757f3fSDimitry Andric   case comments::InlineCommandRenderKind::Normal:
16900b57cec5SDimitry Andric     JOS.attribute("renderKind", "normal");
16910b57cec5SDimitry Andric     break;
16925f757f3fSDimitry Andric   case comments::InlineCommandRenderKind::Bold:
16930b57cec5SDimitry Andric     JOS.attribute("renderKind", "bold");
16940b57cec5SDimitry Andric     break;
16955f757f3fSDimitry Andric   case comments::InlineCommandRenderKind::Emphasized:
16960b57cec5SDimitry Andric     JOS.attribute("renderKind", "emphasized");
16970b57cec5SDimitry Andric     break;
16985f757f3fSDimitry Andric   case comments::InlineCommandRenderKind::Monospaced:
16990b57cec5SDimitry Andric     JOS.attribute("renderKind", "monospaced");
17000b57cec5SDimitry Andric     break;
17015f757f3fSDimitry Andric   case comments::InlineCommandRenderKind::Anchor:
1702480093f4SDimitry Andric     JOS.attribute("renderKind", "anchor");
1703480093f4SDimitry Andric     break;
17040b57cec5SDimitry Andric   }
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   llvm::json::Array Args;
17070b57cec5SDimitry Andric   for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
17080b57cec5SDimitry Andric     Args.push_back(C->getArgText(I));
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric   if (!Args.empty())
17110b57cec5SDimitry Andric     JOS.attribute("args", std::move(Args));
17120b57cec5SDimitry Andric }
17130b57cec5SDimitry Andric 
visitHTMLStartTagComment(const comments::HTMLStartTagComment * C,const comments::FullComment *)17140b57cec5SDimitry Andric void JSONNodeDumper::visitHTMLStartTagComment(
17150b57cec5SDimitry Andric     const comments::HTMLStartTagComment *C, const comments::FullComment *) {
17160b57cec5SDimitry Andric   JOS.attribute("name", C->getTagName());
17170b57cec5SDimitry Andric   attributeOnlyIfTrue("selfClosing", C->isSelfClosing());
17180b57cec5SDimitry Andric   attributeOnlyIfTrue("malformed", C->isMalformed());
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric   llvm::json::Array Attrs;
17210b57cec5SDimitry Andric   for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I)
17220b57cec5SDimitry Andric     Attrs.push_back(
17230b57cec5SDimitry Andric         {{"name", C->getAttr(I).Name}, {"value", C->getAttr(I).Value}});
17240b57cec5SDimitry Andric 
17250b57cec5SDimitry Andric   if (!Attrs.empty())
17260b57cec5SDimitry Andric     JOS.attribute("attrs", std::move(Attrs));
17270b57cec5SDimitry Andric }
17280b57cec5SDimitry Andric 
visitHTMLEndTagComment(const comments::HTMLEndTagComment * C,const comments::FullComment *)17290b57cec5SDimitry Andric void JSONNodeDumper::visitHTMLEndTagComment(
17300b57cec5SDimitry Andric     const comments::HTMLEndTagComment *C, const comments::FullComment *) {
17310b57cec5SDimitry Andric   JOS.attribute("name", C->getTagName());
17320b57cec5SDimitry Andric }
17330b57cec5SDimitry Andric 
visitBlockCommandComment(const comments::BlockCommandComment * C,const comments::FullComment *)17340b57cec5SDimitry Andric void JSONNodeDumper::visitBlockCommandComment(
17350b57cec5SDimitry Andric     const comments::BlockCommandComment *C, const comments::FullComment *) {
17360b57cec5SDimitry Andric   JOS.attribute("name", getCommentCommandName(C->getCommandID()));
17370b57cec5SDimitry Andric 
17380b57cec5SDimitry Andric   llvm::json::Array Args;
17390b57cec5SDimitry Andric   for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
17400b57cec5SDimitry Andric     Args.push_back(C->getArgText(I));
17410b57cec5SDimitry Andric 
17420b57cec5SDimitry Andric   if (!Args.empty())
17430b57cec5SDimitry Andric     JOS.attribute("args", std::move(Args));
17440b57cec5SDimitry Andric }
17450b57cec5SDimitry Andric 
visitParamCommandComment(const comments::ParamCommandComment * C,const comments::FullComment * FC)17460b57cec5SDimitry Andric void JSONNodeDumper::visitParamCommandComment(
17470b57cec5SDimitry Andric     const comments::ParamCommandComment *C, const comments::FullComment *FC) {
17480b57cec5SDimitry Andric   switch (C->getDirection()) {
17495f757f3fSDimitry Andric   case comments::ParamCommandPassDirection::In:
17500b57cec5SDimitry Andric     JOS.attribute("direction", "in");
17510b57cec5SDimitry Andric     break;
17525f757f3fSDimitry Andric   case comments::ParamCommandPassDirection::Out:
17530b57cec5SDimitry Andric     JOS.attribute("direction", "out");
17540b57cec5SDimitry Andric     break;
17555f757f3fSDimitry Andric   case comments::ParamCommandPassDirection::InOut:
17560b57cec5SDimitry Andric     JOS.attribute("direction", "in,out");
17570b57cec5SDimitry Andric     break;
17580b57cec5SDimitry Andric   }
17590b57cec5SDimitry Andric   attributeOnlyIfTrue("explicit", C->isDirectionExplicit());
17600b57cec5SDimitry Andric 
17610b57cec5SDimitry Andric   if (C->hasParamName())
17620b57cec5SDimitry Andric     JOS.attribute("param", C->isParamIndexValid() ? C->getParamName(FC)
17630b57cec5SDimitry Andric                                                   : C->getParamNameAsWritten());
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric   if (C->isParamIndexValid() && !C->isVarArgParam())
17660b57cec5SDimitry Andric     JOS.attribute("paramIdx", C->getParamIndex());
17670b57cec5SDimitry Andric }
17680b57cec5SDimitry Andric 
visitTParamCommandComment(const comments::TParamCommandComment * C,const comments::FullComment * FC)17690b57cec5SDimitry Andric void JSONNodeDumper::visitTParamCommandComment(
17700b57cec5SDimitry Andric     const comments::TParamCommandComment *C, const comments::FullComment *FC) {
17710b57cec5SDimitry Andric   if (C->hasParamName())
17720b57cec5SDimitry Andric     JOS.attribute("param", C->isPositionValid() ? C->getParamName(FC)
17730b57cec5SDimitry Andric                                                 : C->getParamNameAsWritten());
17740b57cec5SDimitry Andric   if (C->isPositionValid()) {
17750b57cec5SDimitry Andric     llvm::json::Array Positions;
17760b57cec5SDimitry Andric     for (unsigned I = 0, E = C->getDepth(); I < E; ++I)
17770b57cec5SDimitry Andric       Positions.push_back(C->getIndex(I));
17780b57cec5SDimitry Andric 
17790b57cec5SDimitry Andric     if (!Positions.empty())
17800b57cec5SDimitry Andric       JOS.attribute("positions", std::move(Positions));
17810b57cec5SDimitry Andric   }
17820b57cec5SDimitry Andric }
17830b57cec5SDimitry Andric 
visitVerbatimBlockComment(const comments::VerbatimBlockComment * C,const comments::FullComment *)17840b57cec5SDimitry Andric void JSONNodeDumper::visitVerbatimBlockComment(
17850b57cec5SDimitry Andric     const comments::VerbatimBlockComment *C, const comments::FullComment *) {
17860b57cec5SDimitry Andric   JOS.attribute("name", getCommentCommandName(C->getCommandID()));
17870b57cec5SDimitry Andric   JOS.attribute("closeName", C->getCloseName());
17880b57cec5SDimitry Andric }
17890b57cec5SDimitry Andric 
visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment * C,const comments::FullComment *)17900b57cec5SDimitry Andric void JSONNodeDumper::visitVerbatimBlockLineComment(
17910b57cec5SDimitry Andric     const comments::VerbatimBlockLineComment *C,
17920b57cec5SDimitry Andric     const comments::FullComment *) {
17930b57cec5SDimitry Andric   JOS.attribute("text", C->getText());
17940b57cec5SDimitry Andric }
17950b57cec5SDimitry Andric 
visitVerbatimLineComment(const comments::VerbatimLineComment * C,const comments::FullComment *)17960b57cec5SDimitry Andric void JSONNodeDumper::visitVerbatimLineComment(
17970b57cec5SDimitry Andric     const comments::VerbatimLineComment *C, const comments::FullComment *) {
17980b57cec5SDimitry Andric   JOS.attribute("text", C->getText());
17990b57cec5SDimitry Andric }
180081ad6265SDimitry Andric 
createFPOptions(FPOptionsOverride FPO)180181ad6265SDimitry Andric llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) {
180281ad6265SDimitry Andric   llvm::json::Object Ret;
180381ad6265SDimitry Andric #define OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                    \
180481ad6265SDimitry Andric   if (FPO.has##NAME##Override())                                               \
180581ad6265SDimitry Andric     Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override()));
180681ad6265SDimitry Andric #include "clang/Basic/FPOptions.def"
180781ad6265SDimitry Andric   return Ret;
180881ad6265SDimitry Andric }
180981ad6265SDimitry Andric 
VisitCompoundStmt(const CompoundStmt * S)181081ad6265SDimitry Andric void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
181181ad6265SDimitry Andric   VisitStmt(S);
181281ad6265SDimitry Andric   if (S->hasStoredFPFeatures())
181381ad6265SDimitry Andric     JOS.attribute("fpoptions", createFPOptions(S->getStoredFPFeatures()));
181481ad6265SDimitry Andric }
1815