Path: blob/main/contrib/llvm-project/clang/lib/AST/JSONNodeDumper.cpp
35260 views
#include "clang/AST/JSONNodeDumper.h"1#include "clang/AST/Type.h"2#include "clang/Basic/SourceManager.h"3#include "clang/Basic/Specifiers.h"4#include "clang/Lex/Lexer.h"5#include "llvm/ADT/StringExtras.h"6#include <optional>78using namespace clang;910void JSONNodeDumper::addPreviousDeclaration(const Decl *D) {11switch (D->getKind()) {12#define DECL(DERIVED, BASE) \13case Decl::DERIVED: \14return writePreviousDeclImpl(cast<DERIVED##Decl>(D));15#define ABSTRACT_DECL(DECL)16#include "clang/AST/DeclNodes.inc"17#undef ABSTRACT_DECL18#undef DECL19}20llvm_unreachable("Decl that isn't part of DeclNodes.inc!");21}2223void JSONNodeDumper::Visit(const Attr *A) {24const char *AttrName = nullptr;25switch (A->getKind()) {26#define ATTR(X) \27case attr::X: \28AttrName = #X"Attr"; \29break;30#include "clang/Basic/AttrList.inc"31#undef ATTR32}33JOS.attribute("id", createPointerRepresentation(A));34JOS.attribute("kind", AttrName);35JOS.attributeObject("range", [A, this] { writeSourceRange(A->getRange()); });36attributeOnlyIfTrue("inherited", A->isInherited());37attributeOnlyIfTrue("implicit", A->isImplicit());3839// FIXME: it would be useful for us to output the spelling kind as well as40// the actual spelling. This would allow us to distinguish between the41// various attribute syntaxes, but we don't currently track that information42// within the AST.43//JOS.attribute("spelling", A->getSpelling());4445InnerAttrVisitor::Visit(A);46}4748void JSONNodeDumper::Visit(const Stmt *S) {49if (!S)50return;5152JOS.attribute("id", createPointerRepresentation(S));53JOS.attribute("kind", S->getStmtClassName());54JOS.attributeObject("range",55[S, this] { writeSourceRange(S->getSourceRange()); });5657if (const auto *E = dyn_cast<Expr>(S)) {58JOS.attribute("type", createQualType(E->getType()));59const char *Category = nullptr;60switch (E->getValueKind()) {61case VK_LValue: Category = "lvalue"; break;62case VK_XValue: Category = "xvalue"; break;63case VK_PRValue:64Category = "prvalue";65break;66}67JOS.attribute("valueCategory", Category);68}69InnerStmtVisitor::Visit(S);70}7172void JSONNodeDumper::Visit(const Type *T) {73JOS.attribute("id", createPointerRepresentation(T));7475if (!T)76return;7778JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str());79JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar=*/false));80attributeOnlyIfTrue("containsErrors", T->containsErrors());81attributeOnlyIfTrue("isDependent", T->isDependentType());82attributeOnlyIfTrue("isInstantiationDependent",83T->isInstantiationDependentType());84attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType());85attributeOnlyIfTrue("containsUnexpandedPack",86T->containsUnexpandedParameterPack());87attributeOnlyIfTrue("isImported", T->isFromAST());88InnerTypeVisitor::Visit(T);89}9091void JSONNodeDumper::Visit(QualType T) {92JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));93JOS.attribute("kind", "QualType");94JOS.attribute("type", createQualType(T));95JOS.attribute("qualifiers", T.split().Quals.getAsString());96}9798void JSONNodeDumper::Visit(TypeLoc TL) {99if (TL.isNull())100return;101JOS.attribute("kind",102(llvm::Twine(TL.getTypeLocClass() == TypeLoc::Qualified103? "Qualified"104: TL.getTypePtr()->getTypeClassName()) +105"TypeLoc")106.str());107JOS.attribute("type",108createQualType(QualType(TL.getType()), /*Desugar=*/false));109JOS.attributeObject("range",110[TL, this] { writeSourceRange(TL.getSourceRange()); });111}112113void JSONNodeDumper::Visit(const Decl *D) {114JOS.attribute("id", createPointerRepresentation(D));115116if (!D)117return;118119JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());120JOS.attributeObject("loc",121[D, this] { writeSourceLocation(D->getLocation()); });122JOS.attributeObject("range",123[D, this] { writeSourceRange(D->getSourceRange()); });124attributeOnlyIfTrue("isImplicit", D->isImplicit());125attributeOnlyIfTrue("isInvalid", D->isInvalidDecl());126127if (D->isUsed())128JOS.attribute("isUsed", true);129else if (D->isThisDeclarationReferenced())130JOS.attribute("isReferenced", true);131132if (const auto *ND = dyn_cast<NamedDecl>(D))133attributeOnlyIfTrue("isHidden", !ND->isUnconditionallyVisible());134135if (D->getLexicalDeclContext() != D->getDeclContext()) {136// Because of multiple inheritance, a DeclContext pointer does not produce137// the same pointer representation as a Decl pointer that references the138// same AST Node.139const auto *ParentDeclContextDecl = dyn_cast<Decl>(D->getDeclContext());140JOS.attribute("parentDeclContextId",141createPointerRepresentation(ParentDeclContextDecl));142}143144addPreviousDeclaration(D);145InnerDeclVisitor::Visit(D);146}147148void JSONNodeDumper::Visit(const comments::Comment *C,149const comments::FullComment *FC) {150if (!C)151return;152153JOS.attribute("id", createPointerRepresentation(C));154JOS.attribute("kind", C->getCommentKindName());155JOS.attributeObject("loc",156[C, this] { writeSourceLocation(C->getLocation()); });157JOS.attributeObject("range",158[C, this] { writeSourceRange(C->getSourceRange()); });159160InnerCommentVisitor::visit(C, FC);161}162163void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,164const Decl *From, StringRef Label) {165JOS.attribute("kind", "TemplateArgument");166if (R.isValid())167JOS.attributeObject("range", [R, this] { writeSourceRange(R); });168169if (From)170JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From));171172InnerTemplateArgVisitor::Visit(TA);173}174175void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {176JOS.attribute("kind", "CXXCtorInitializer");177if (Init->isAnyMemberInitializer())178JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember()));179else if (Init->isBaseInitializer())180JOS.attribute("baseInit",181createQualType(QualType(Init->getBaseClass(), 0)));182else if (Init->isDelegatingInitializer())183JOS.attribute("delegatingInit",184createQualType(Init->getTypeSourceInfo()->getType()));185else186llvm_unreachable("Unknown initializer type");187}188189void JSONNodeDumper::Visit(const OpenACCClause *C) {}190191void JSONNodeDumper::Visit(const OMPClause *C) {}192193void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {194JOS.attribute("kind", "Capture");195attributeOnlyIfTrue("byref", C.isByRef());196attributeOnlyIfTrue("nested", C.isNested());197if (C.getVariable())198JOS.attribute("var", createBareDeclRef(C.getVariable()));199}200201void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {202JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default");203attributeOnlyIfTrue("selected", A.isSelected());204}205206void JSONNodeDumper::Visit(const concepts::Requirement *R) {207if (!R)208return;209210switch (R->getKind()) {211case concepts::Requirement::RK_Type:212JOS.attribute("kind", "TypeRequirement");213break;214case concepts::Requirement::RK_Simple:215JOS.attribute("kind", "SimpleRequirement");216break;217case concepts::Requirement::RK_Compound:218JOS.attribute("kind", "CompoundRequirement");219break;220case concepts::Requirement::RK_Nested:221JOS.attribute("kind", "NestedRequirement");222break;223}224225if (auto *ER = dyn_cast<concepts::ExprRequirement>(R))226attributeOnlyIfTrue("noexcept", ER->hasNoexceptRequirement());227228attributeOnlyIfTrue("isDependent", R->isDependent());229if (!R->isDependent())230JOS.attribute("satisfied", R->isSatisfied());231attributeOnlyIfTrue("containsUnexpandedPack",232R->containsUnexpandedParameterPack());233}234235void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {236std::string Str;237llvm::raw_string_ostream OS(Str);238Value.printPretty(OS, Ctx, Ty);239JOS.attribute("value", Str);240}241242void JSONNodeDumper::Visit(const ConceptReference *CR) {243JOS.attribute("kind", "ConceptReference");244JOS.attribute("id", createPointerRepresentation(CR->getNamedConcept()));245if (const auto *Args = CR->getTemplateArgsAsWritten()) {246JOS.attributeArray("templateArgsAsWritten", [Args, this] {247for (const TemplateArgumentLoc &TAL : Args->arguments())248JOS.object(249[&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });250});251}252JOS.attributeObject("loc",253[CR, this] { writeSourceLocation(CR->getLocation()); });254JOS.attributeObject("range",255[CR, this] { writeSourceRange(CR->getSourceRange()); });256}257258void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {259if (Loc.isInvalid())260return;261262JOS.attributeBegin("includedFrom");263JOS.objectBegin();264265if (!JustFirst) {266// Walk the stack recursively, then print out the presumed location.267writeIncludeStack(SM.getPresumedLoc(Loc.getIncludeLoc()));268}269270JOS.attribute("file", Loc.getFilename());271JOS.objectEnd();272JOS.attributeEnd();273}274275void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc,276bool IsSpelling) {277PresumedLoc Presumed = SM.getPresumedLoc(Loc);278unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc)279: SM.getExpansionLineNumber(Loc);280StringRef ActualFile = SM.getBufferName(Loc);281282if (Presumed.isValid()) {283JOS.attribute("offset", SM.getDecomposedLoc(Loc).second);284if (LastLocFilename != ActualFile) {285JOS.attribute("file", ActualFile);286JOS.attribute("line", ActualLine);287} else if (LastLocLine != ActualLine)288JOS.attribute("line", ActualLine);289290StringRef PresumedFile = Presumed.getFilename();291if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile)292JOS.attribute("presumedFile", PresumedFile);293294unsigned PresumedLine = Presumed.getLine();295if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine)296JOS.attribute("presumedLine", PresumedLine);297298JOS.attribute("col", Presumed.getColumn());299JOS.attribute("tokLen",300Lexer::MeasureTokenLength(Loc, SM, Ctx.getLangOpts()));301LastLocFilename = ActualFile;302LastLocPresumedFilename = PresumedFile;303LastLocPresumedLine = PresumedLine;304LastLocLine = ActualLine;305306// Orthogonal to the file, line, and column de-duplication is whether the307// given location was a result of an include. If so, print where the308// include location came from.309writeIncludeStack(SM.getPresumedLoc(Presumed.getIncludeLoc()),310/*JustFirst*/ true);311}312}313314void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) {315SourceLocation Spelling = SM.getSpellingLoc(Loc);316SourceLocation Expansion = SM.getExpansionLoc(Loc);317318if (Expansion != Spelling) {319// If the expansion and the spelling are different, output subobjects320// describing both locations.321JOS.attributeObject("spellingLoc", [Spelling, this] {322writeBareSourceLocation(Spelling, /*IsSpelling*/ true);323});324JOS.attributeObject("expansionLoc", [Expansion, Loc, this] {325writeBareSourceLocation(Expansion, /*IsSpelling*/ false);326// If there is a macro expansion, add extra information if the interesting327// bit is the macro arg expansion.328if (SM.isMacroArgExpansion(Loc))329JOS.attribute("isMacroArgExpansion", true);330});331} else332writeBareSourceLocation(Spelling, /*IsSpelling*/ true);333}334335void JSONNodeDumper::writeSourceRange(SourceRange R) {336JOS.attributeObject("begin",337[R, this] { writeSourceLocation(R.getBegin()); });338JOS.attributeObject("end", [R, this] { writeSourceLocation(R.getEnd()); });339}340341std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) {342// Because JSON stores integer values as signed 64-bit integers, trying to343// represent them as such makes for very ugly pointer values in the resulting344// output. Instead, we convert the value to hex and treat it as a string.345return "0x" + llvm::utohexstr(reinterpret_cast<uint64_t>(Ptr), true);346}347348llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) {349SplitQualType SQT = QT.split();350std::string SQTS = QualType::getAsString(SQT, PrintPolicy);351llvm::json::Object Ret{{"qualType", SQTS}};352353if (Desugar && !QT.isNull()) {354SplitQualType DSQT = QT.getSplitDesugaredType();355if (DSQT != SQT) {356std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);357if (DSQTS != SQTS)358Ret["desugaredQualType"] = DSQTS;359}360if (const auto *TT = QT->getAs<TypedefType>())361Ret["typeAliasDeclId"] = createPointerRepresentation(TT->getDecl());362}363return Ret;364}365366void JSONNodeDumper::writeBareDeclRef(const Decl *D) {367JOS.attribute("id", createPointerRepresentation(D));368if (!D)369return;370371JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());372if (const auto *ND = dyn_cast<NamedDecl>(D))373JOS.attribute("name", ND->getDeclName().getAsString());374if (const auto *VD = dyn_cast<ValueDecl>(D))375JOS.attribute("type", createQualType(VD->getType()));376}377378llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) {379llvm::json::Object Ret{{"id", createPointerRepresentation(D)}};380if (!D)381return Ret;382383Ret["kind"] = (llvm::Twine(D->getDeclKindName()) + "Decl").str();384if (const auto *ND = dyn_cast<NamedDecl>(D))385Ret["name"] = ND->getDeclName().getAsString();386if (const auto *VD = dyn_cast<ValueDecl>(D))387Ret["type"] = createQualType(VD->getType());388return Ret;389}390391llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) {392llvm::json::Array Ret;393if (C->path_empty())394return Ret;395396for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) {397const CXXBaseSpecifier *Base = *I;398const auto *RD =399cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());400401llvm::json::Object Val{{"name", RD->getName()}};402if (Base->isVirtual())403Val["isVirtual"] = true;404Ret.push_back(std::move(Val));405}406return Ret;407}408409#define FIELD2(Name, Flag) if (RD->Flag()) Ret[Name] = true410#define FIELD1(Flag) FIELD2(#Flag, Flag)411412static llvm::json::Object413createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) {414llvm::json::Object Ret;415416FIELD2("exists", hasDefaultConstructor);417FIELD2("trivial", hasTrivialDefaultConstructor);418FIELD2("nonTrivial", hasNonTrivialDefaultConstructor);419FIELD2("userProvided", hasUserProvidedDefaultConstructor);420FIELD2("isConstexpr", hasConstexprDefaultConstructor);421FIELD2("needsImplicit", needsImplicitDefaultConstructor);422FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr);423424return Ret;425}426427static llvm::json::Object428createCopyConstructorDefinitionData(const CXXRecordDecl *RD) {429llvm::json::Object Ret;430431FIELD2("simple", hasSimpleCopyConstructor);432FIELD2("trivial", hasTrivialCopyConstructor);433FIELD2("nonTrivial", hasNonTrivialCopyConstructor);434FIELD2("userDeclared", hasUserDeclaredCopyConstructor);435FIELD2("hasConstParam", hasCopyConstructorWithConstParam);436FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam);437FIELD2("needsImplicit", needsImplicitCopyConstructor);438FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor);439if (!RD->needsOverloadResolutionForCopyConstructor())440FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted);441442return Ret;443}444445static llvm::json::Object446createMoveConstructorDefinitionData(const CXXRecordDecl *RD) {447llvm::json::Object Ret;448449FIELD2("exists", hasMoveConstructor);450FIELD2("simple", hasSimpleMoveConstructor);451FIELD2("trivial", hasTrivialMoveConstructor);452FIELD2("nonTrivial", hasNonTrivialMoveConstructor);453FIELD2("userDeclared", hasUserDeclaredMoveConstructor);454FIELD2("needsImplicit", needsImplicitMoveConstructor);455FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor);456if (!RD->needsOverloadResolutionForMoveConstructor())457FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted);458459return Ret;460}461462static llvm::json::Object463createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) {464llvm::json::Object Ret;465466FIELD2("simple", hasSimpleCopyAssignment);467FIELD2("trivial", hasTrivialCopyAssignment);468FIELD2("nonTrivial", hasNonTrivialCopyAssignment);469FIELD2("hasConstParam", hasCopyAssignmentWithConstParam);470FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam);471FIELD2("userDeclared", hasUserDeclaredCopyAssignment);472FIELD2("needsImplicit", needsImplicitCopyAssignment);473FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment);474475return Ret;476}477478static llvm::json::Object479createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) {480llvm::json::Object Ret;481482FIELD2("exists", hasMoveAssignment);483FIELD2("simple", hasSimpleMoveAssignment);484FIELD2("trivial", hasTrivialMoveAssignment);485FIELD2("nonTrivial", hasNonTrivialMoveAssignment);486FIELD2("userDeclared", hasUserDeclaredMoveAssignment);487FIELD2("needsImplicit", needsImplicitMoveAssignment);488FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment);489490return Ret;491}492493static llvm::json::Object494createDestructorDefinitionData(const CXXRecordDecl *RD) {495llvm::json::Object Ret;496497FIELD2("simple", hasSimpleDestructor);498FIELD2("irrelevant", hasIrrelevantDestructor);499FIELD2("trivial", hasTrivialDestructor);500FIELD2("nonTrivial", hasNonTrivialDestructor);501FIELD2("userDeclared", hasUserDeclaredDestructor);502FIELD2("needsImplicit", needsImplicitDestructor);503FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor);504if (!RD->needsOverloadResolutionForDestructor())505FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted);506507return Ret;508}509510llvm::json::Object511JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) {512llvm::json::Object Ret;513514// This data is common to all C++ classes.515FIELD1(isGenericLambda);516FIELD1(isLambda);517FIELD1(isEmpty);518FIELD1(isAggregate);519FIELD1(isStandardLayout);520FIELD1(isTriviallyCopyable);521FIELD1(isPOD);522FIELD1(isTrivial);523FIELD1(isPolymorphic);524FIELD1(isAbstract);525FIELD1(isLiteral);526FIELD1(canPassInRegisters);527FIELD1(hasUserDeclaredConstructor);528FIELD1(hasConstexprNonCopyMoveConstructor);529FIELD1(hasMutableFields);530FIELD1(hasVariantMembers);531FIELD2("canConstDefaultInit", allowConstDefaultInit);532533Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD);534Ret["copyCtor"] = createCopyConstructorDefinitionData(RD);535Ret["moveCtor"] = createMoveConstructorDefinitionData(RD);536Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD);537Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD);538Ret["dtor"] = createDestructorDefinitionData(RD);539540return Ret;541}542543#undef FIELD1544#undef FIELD2545546std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) {547const auto AccessSpelling = getAccessSpelling(AS);548if (AccessSpelling.empty())549return "none";550return AccessSpelling.str();551}552553llvm::json::Object554JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) {555llvm::json::Object Ret;556557Ret["type"] = createQualType(BS.getType());558Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier());559Ret["writtenAccess"] =560createAccessSpecifier(BS.getAccessSpecifierAsWritten());561if (BS.isVirtual())562Ret["isVirtual"] = true;563if (BS.isPackExpansion())564Ret["isPackExpansion"] = true;565566return Ret;567}568569void JSONNodeDumper::VisitAliasAttr(const AliasAttr *AA) {570JOS.attribute("aliasee", AA->getAliasee());571}572573void JSONNodeDumper::VisitCleanupAttr(const CleanupAttr *CA) {574JOS.attribute("cleanup_function", createBareDeclRef(CA->getFunctionDecl()));575}576577void JSONNodeDumper::VisitDeprecatedAttr(const DeprecatedAttr *DA) {578if (!DA->getMessage().empty())579JOS.attribute("message", DA->getMessage());580if (!DA->getReplacement().empty())581JOS.attribute("replacement", DA->getReplacement());582}583584void JSONNodeDumper::VisitUnavailableAttr(const UnavailableAttr *UA) {585if (!UA->getMessage().empty())586JOS.attribute("message", UA->getMessage());587}588589void JSONNodeDumper::VisitSectionAttr(const SectionAttr *SA) {590JOS.attribute("section_name", SA->getName());591}592593void JSONNodeDumper::VisitVisibilityAttr(const VisibilityAttr *VA) {594JOS.attribute("visibility", VisibilityAttr::ConvertVisibilityTypeToStr(595VA->getVisibility()));596}597598void JSONNodeDumper::VisitTLSModelAttr(const TLSModelAttr *TA) {599JOS.attribute("tls_model", TA->getModel());600}601602void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {603JOS.attribute("decl", createBareDeclRef(TT->getDecl()));604if (!TT->typeMatchesDecl())605JOS.attribute("type", createQualType(TT->desugar()));606}607608void JSONNodeDumper::VisitUsingType(const UsingType *TT) {609JOS.attribute("decl", createBareDeclRef(TT->getFoundDecl()));610if (!TT->typeMatchesDecl())611JOS.attribute("type", createQualType(TT->desugar()));612}613614void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {615FunctionType::ExtInfo E = T->getExtInfo();616attributeOnlyIfTrue("noreturn", E.getNoReturn());617attributeOnlyIfTrue("producesResult", E.getProducesResult());618if (E.getHasRegParm())619JOS.attribute("regParm", E.getRegParm());620JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC()));621}622623void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {624FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo();625attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn);626attributeOnlyIfTrue("const", T->isConst());627attributeOnlyIfTrue("volatile", T->isVolatile());628attributeOnlyIfTrue("restrict", T->isRestrict());629attributeOnlyIfTrue("variadic", E.Variadic);630switch (E.RefQualifier) {631case RQ_LValue: JOS.attribute("refQualifier", "&"); break;632case RQ_RValue: JOS.attribute("refQualifier", "&&"); break;633case RQ_None: break;634}635switch (E.ExceptionSpec.Type) {636case EST_DynamicNone:637case EST_Dynamic: {638JOS.attribute("exceptionSpec", "throw");639llvm::json::Array Types;640for (QualType QT : E.ExceptionSpec.Exceptions)641Types.push_back(createQualType(QT));642JOS.attribute("exceptionTypes", std::move(Types));643} break;644case EST_MSAny:645JOS.attribute("exceptionSpec", "throw");646JOS.attribute("throwsAny", true);647break;648case EST_BasicNoexcept:649JOS.attribute("exceptionSpec", "noexcept");650break;651case EST_NoexceptTrue:652case EST_NoexceptFalse:653JOS.attribute("exceptionSpec", "noexcept");654JOS.attribute("conditionEvaluatesTo",655E.ExceptionSpec.Type == EST_NoexceptTrue);656//JOS.attributeWithCall("exceptionSpecExpr",657// [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); });658break;659case EST_NoThrow:660JOS.attribute("exceptionSpec", "nothrow");661break;662// FIXME: I cannot find a way to trigger these cases while dumping the AST. I663// suspect you can only run into them when executing an AST dump from within664// the debugger, which is not a use case we worry about for the JSON dumping665// feature.666case EST_DependentNoexcept:667case EST_Unevaluated:668case EST_Uninstantiated:669case EST_Unparsed:670case EST_None: break;671}672VisitFunctionType(T);673}674675void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType *RT) {676attributeOnlyIfTrue("spelledAsLValue", RT->isSpelledAsLValue());677}678679void JSONNodeDumper::VisitArrayType(const ArrayType *AT) {680switch (AT->getSizeModifier()) {681case ArraySizeModifier::Star:682JOS.attribute("sizeModifier", "*");683break;684case ArraySizeModifier::Static:685JOS.attribute("sizeModifier", "static");686break;687case ArraySizeModifier::Normal:688break;689}690691std::string Str = AT->getIndexTypeQualifiers().getAsString();692if (!Str.empty())693JOS.attribute("indexTypeQualifiers", Str);694}695696void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) {697// FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a698// narrowing conversion to int64_t so it cannot be expressed.699JOS.attribute("size", CAT->getSExtSize());700VisitArrayType(CAT);701}702703void JSONNodeDumper::VisitDependentSizedExtVectorType(704const DependentSizedExtVectorType *VT) {705JOS.attributeObject(706"attrLoc", [VT, this] { writeSourceLocation(VT->getAttributeLoc()); });707}708709void JSONNodeDumper::VisitVectorType(const VectorType *VT) {710JOS.attribute("numElements", VT->getNumElements());711switch (VT->getVectorKind()) {712case VectorKind::Generic:713break;714case VectorKind::AltiVecVector:715JOS.attribute("vectorKind", "altivec");716break;717case VectorKind::AltiVecPixel:718JOS.attribute("vectorKind", "altivec pixel");719break;720case VectorKind::AltiVecBool:721JOS.attribute("vectorKind", "altivec bool");722break;723case VectorKind::Neon:724JOS.attribute("vectorKind", "neon");725break;726case VectorKind::NeonPoly:727JOS.attribute("vectorKind", "neon poly");728break;729case VectorKind::SveFixedLengthData:730JOS.attribute("vectorKind", "fixed-length sve data vector");731break;732case VectorKind::SveFixedLengthPredicate:733JOS.attribute("vectorKind", "fixed-length sve predicate vector");734break;735case VectorKind::RVVFixedLengthData:736JOS.attribute("vectorKind", "fixed-length rvv data vector");737break;738case VectorKind::RVVFixedLengthMask:739JOS.attribute("vectorKind", "fixed-length rvv mask vector");740break;741}742}743744void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {745JOS.attribute("decl", createBareDeclRef(UUT->getDecl()));746}747748void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) {749switch (UTT->getUTTKind()) {750#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \751case UnaryTransformType::Enum: \752JOS.attribute("transformKind", #Trait); \753break;754#include "clang/Basic/TransformTypeTraits.def"755}756}757758void JSONNodeDumper::VisitTagType(const TagType *TT) {759JOS.attribute("decl", createBareDeclRef(TT->getDecl()));760}761762void JSONNodeDumper::VisitTemplateTypeParmType(763const TemplateTypeParmType *TTPT) {764JOS.attribute("depth", TTPT->getDepth());765JOS.attribute("index", TTPT->getIndex());766attributeOnlyIfTrue("isPack", TTPT->isParameterPack());767JOS.attribute("decl", createBareDeclRef(TTPT->getDecl()));768}769770void JSONNodeDumper::VisitSubstTemplateTypeParmType(771const SubstTemplateTypeParmType *STTPT) {772JOS.attribute("index", STTPT->getIndex());773if (auto PackIndex = STTPT->getPackIndex())774JOS.attribute("pack_index", *PackIndex);775}776777void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(778const SubstTemplateTypeParmPackType *T) {779JOS.attribute("index", T->getIndex());780}781782void JSONNodeDumper::VisitAutoType(const AutoType *AT) {783JOS.attribute("undeduced", !AT->isDeduced());784switch (AT->getKeyword()) {785case AutoTypeKeyword::Auto:786JOS.attribute("typeKeyword", "auto");787break;788case AutoTypeKeyword::DecltypeAuto:789JOS.attribute("typeKeyword", "decltype(auto)");790break;791case AutoTypeKeyword::GNUAutoType:792JOS.attribute("typeKeyword", "__auto_type");793break;794}795}796797void JSONNodeDumper::VisitTemplateSpecializationType(798const TemplateSpecializationType *TST) {799attributeOnlyIfTrue("isAlias", TST->isTypeAlias());800801std::string Str;802llvm::raw_string_ostream OS(Str);803TST->getTemplateName().print(OS, PrintPolicy);804JOS.attribute("templateName", Str);805}806807void JSONNodeDumper::VisitInjectedClassNameType(808const InjectedClassNameType *ICNT) {809JOS.attribute("decl", createBareDeclRef(ICNT->getDecl()));810}811812void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {813JOS.attribute("decl", createBareDeclRef(OIT->getDecl()));814}815816void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) {817if (std::optional<unsigned> N = PET->getNumExpansions())818JOS.attribute("numExpansions", *N);819}820821void JSONNodeDumper::VisitElaboratedType(const ElaboratedType *ET) {822if (const NestedNameSpecifier *NNS = ET->getQualifier()) {823std::string Str;824llvm::raw_string_ostream OS(Str);825NNS->print(OS, PrintPolicy, /*ResolveTemplateArgs*/ true);826JOS.attribute("qualifier", Str);827}828if (const TagDecl *TD = ET->getOwnedTagDecl())829JOS.attribute("ownedTagDecl", createBareDeclRef(TD));830}831832void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) {833JOS.attribute("macroName", MQT->getMacroIdentifier()->getName());834}835836void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) {837attributeOnlyIfTrue("isData", MPT->isMemberDataPointer());838attributeOnlyIfTrue("isFunction", MPT->isMemberFunctionPointer());839}840841void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {842if (ND && ND->getDeclName()) {843JOS.attribute("name", ND->getNameAsString());844// FIXME: There are likely other contexts in which it makes no sense to ask845// for a mangled name.846if (isa<RequiresExprBodyDecl>(ND->getDeclContext()))847return;848849// If the declaration is dependent or is in a dependent context, then the850// mangling is unlikely to be meaningful (and in some cases may cause851// "don't know how to mangle this" assertion failures.852if (ND->isTemplated())853return;854855// Mangled names are not meaningful for locals, and may not be well-defined856// in the case of VLAs.857auto *VD = dyn_cast<VarDecl>(ND);858if (VD && VD->hasLocalStorage())859return;860861// Do not mangle template deduction guides.862if (isa<CXXDeductionGuideDecl>(ND))863return;864865std::string MangledName = ASTNameGen.getName(ND);866if (!MangledName.empty())867JOS.attribute("mangledName", MangledName);868}869}870871void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) {872VisitNamedDecl(TD);873JOS.attribute("type", createQualType(TD->getUnderlyingType()));874}875876void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) {877VisitNamedDecl(TAD);878JOS.attribute("type", createQualType(TAD->getUnderlyingType()));879}880881void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {882VisitNamedDecl(ND);883attributeOnlyIfTrue("isInline", ND->isInline());884attributeOnlyIfTrue("isNested", ND->isNested());885if (!ND->isFirstDecl())886JOS.attribute("originalNamespace", createBareDeclRef(ND->getFirstDecl()));887}888889void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {890JOS.attribute("nominatedNamespace",891createBareDeclRef(UDD->getNominatedNamespace()));892}893894void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {895VisitNamedDecl(NAD);896JOS.attribute("aliasedNamespace",897createBareDeclRef(NAD->getAliasedNamespace()));898}899900void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) {901std::string Name;902if (const NestedNameSpecifier *NNS = UD->getQualifier()) {903llvm::raw_string_ostream SOS(Name);904NNS->print(SOS, UD->getASTContext().getPrintingPolicy());905}906Name += UD->getNameAsString();907JOS.attribute("name", Name);908}909910void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) {911JOS.attribute("target", createBareDeclRef(UED->getEnumDecl()));912}913914void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) {915JOS.attribute("target", createBareDeclRef(USD->getTargetDecl()));916}917918void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) {919VisitNamedDecl(VD);920JOS.attribute("type", createQualType(VD->getType()));921if (const auto *P = dyn_cast<ParmVarDecl>(VD))922attributeOnlyIfTrue("explicitObjectParameter",923P->isExplicitObjectParameter());924925StorageClass SC = VD->getStorageClass();926if (SC != SC_None)927JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));928switch (VD->getTLSKind()) {929case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break;930case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break;931case VarDecl::TLS_None: break;932}933attributeOnlyIfTrue("nrvo", VD->isNRVOVariable());934attributeOnlyIfTrue("inline", VD->isInline());935attributeOnlyIfTrue("constexpr", VD->isConstexpr());936attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate());937if (VD->hasInit()) {938switch (VD->getInitStyle()) {939case VarDecl::CInit: JOS.attribute("init", "c"); break;940case VarDecl::CallInit: JOS.attribute("init", "call"); break;941case VarDecl::ListInit: JOS.attribute("init", "list"); break;942case VarDecl::ParenListInit:943JOS.attribute("init", "paren-list");944break;945}946}947attributeOnlyIfTrue("isParameterPack", VD->isParameterPack());948}949950void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {951VisitNamedDecl(FD);952JOS.attribute("type", createQualType(FD->getType()));953attributeOnlyIfTrue("mutable", FD->isMutable());954attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate());955attributeOnlyIfTrue("isBitfield", FD->isBitField());956attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer());957}958959void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {960VisitNamedDecl(FD);961JOS.attribute("type", createQualType(FD->getType()));962StorageClass SC = FD->getStorageClass();963if (SC != SC_None)964JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));965attributeOnlyIfTrue("inline", FD->isInlineSpecified());966attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten());967attributeOnlyIfTrue("pure", FD->isPureVirtual());968attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten());969attributeOnlyIfTrue("constexpr", FD->isConstexpr());970attributeOnlyIfTrue("variadic", FD->isVariadic());971attributeOnlyIfTrue("immediate", FD->isImmediateFunction());972973if (FD->isDefaulted())974JOS.attribute("explicitlyDefaulted",975FD->isDeleted() ? "deleted" : "default");976977if (StringLiteral *Msg = FD->getDeletedMessage())978JOS.attribute("deletedMessage", Msg->getString());979}980981void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) {982VisitNamedDecl(ED);983if (ED->isFixed())984JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType()));985if (ED->isScoped())986JOS.attribute("scopedEnumTag",987ED->isScopedUsingClassTag() ? "class" : "struct");988}989void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) {990VisitNamedDecl(ECD);991JOS.attribute("type", createQualType(ECD->getType()));992}993994void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {995VisitNamedDecl(RD);996JOS.attribute("tagUsed", RD->getKindName());997attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition());998}999void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {1000VisitRecordDecl(RD);10011002// All other information requires a complete definition.1003if (!RD->isCompleteDefinition())1004return;10051006JOS.attribute("definitionData", createCXXRecordDefinitionData(RD));1007if (RD->getNumBases()) {1008JOS.attributeArray("bases", [this, RD] {1009for (const auto &Spec : RD->bases())1010JOS.value(createCXXBaseSpecifier(Spec));1011});1012}1013}10141015void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {1016VisitNamedDecl(D);1017JOS.attribute("bufferKind", D->isCBuffer() ? "cbuffer" : "tbuffer");1018}10191020void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {1021VisitNamedDecl(D);1022JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class");1023JOS.attribute("depth", D->getDepth());1024JOS.attribute("index", D->getIndex());1025attributeOnlyIfTrue("isParameterPack", D->isParameterPack());10261027if (D->hasDefaultArgument())1028JOS.attributeObject("defaultArg", [=] {1029Visit(D->getDefaultArgument().getArgument(), SourceRange(),1030D->getDefaultArgStorage().getInheritedFrom(),1031D->defaultArgumentWasInherited() ? "inherited from" : "previous");1032});1033}10341035void JSONNodeDumper::VisitNonTypeTemplateParmDecl(1036const NonTypeTemplateParmDecl *D) {1037VisitNamedDecl(D);1038JOS.attribute("type", createQualType(D->getType()));1039JOS.attribute("depth", D->getDepth());1040JOS.attribute("index", D->getIndex());1041attributeOnlyIfTrue("isParameterPack", D->isParameterPack());10421043if (D->hasDefaultArgument())1044JOS.attributeObject("defaultArg", [=] {1045Visit(D->getDefaultArgument().getArgument(), SourceRange(),1046D->getDefaultArgStorage().getInheritedFrom(),1047D->defaultArgumentWasInherited() ? "inherited from" : "previous");1048});1049}10501051void JSONNodeDumper::VisitTemplateTemplateParmDecl(1052const TemplateTemplateParmDecl *D) {1053VisitNamedDecl(D);1054JOS.attribute("depth", D->getDepth());1055JOS.attribute("index", D->getIndex());1056attributeOnlyIfTrue("isParameterPack", D->isParameterPack());10571058if (D->hasDefaultArgument())1059JOS.attributeObject("defaultArg", [=] {1060const auto *InheritedFrom = D->getDefaultArgStorage().getInheritedFrom();1061Visit(D->getDefaultArgument().getArgument(),1062InheritedFrom ? InheritedFrom->getSourceRange() : SourceLocation{},1063InheritedFrom,1064D->defaultArgumentWasInherited() ? "inherited from" : "previous");1065});1066}10671068void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) {1069StringRef Lang;1070switch (LSD->getLanguage()) {1071case LinkageSpecLanguageIDs::C:1072Lang = "C";1073break;1074case LinkageSpecLanguageIDs::CXX:1075Lang = "C++";1076break;1077}1078JOS.attribute("language", Lang);1079attributeOnlyIfTrue("hasBraces", LSD->hasBraces());1080}10811082void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) {1083JOS.attribute("access", createAccessSpecifier(ASD->getAccess()));1084}10851086void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) {1087if (const TypeSourceInfo *T = FD->getFriendType())1088JOS.attribute("type", createQualType(T->getType()));1089}10901091void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {1092VisitNamedDecl(D);1093JOS.attribute("type", createQualType(D->getType()));1094attributeOnlyIfTrue("synthesized", D->getSynthesize());1095switch (D->getAccessControl()) {1096case ObjCIvarDecl::None: JOS.attribute("access", "none"); break;1097case ObjCIvarDecl::Private: JOS.attribute("access", "private"); break;1098case ObjCIvarDecl::Protected: JOS.attribute("access", "protected"); break;1099case ObjCIvarDecl::Public: JOS.attribute("access", "public"); break;1100case ObjCIvarDecl::Package: JOS.attribute("access", "package"); break;1101}1102}11031104void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {1105VisitNamedDecl(D);1106JOS.attribute("returnType", createQualType(D->getReturnType()));1107JOS.attribute("instance", D->isInstanceMethod());1108attributeOnlyIfTrue("variadic", D->isVariadic());1109}11101111void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {1112VisitNamedDecl(D);1113JOS.attribute("type", createQualType(D->getUnderlyingType()));1114attributeOnlyIfTrue("bounded", D->hasExplicitBound());1115switch (D->getVariance()) {1116case ObjCTypeParamVariance::Invariant:1117break;1118case ObjCTypeParamVariance::Covariant:1119JOS.attribute("variance", "covariant");1120break;1121case ObjCTypeParamVariance::Contravariant:1122JOS.attribute("variance", "contravariant");1123break;1124}1125}11261127void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {1128VisitNamedDecl(D);1129JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));1130JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));11311132llvm::json::Array Protocols;1133for (const auto* P : D->protocols())1134Protocols.push_back(createBareDeclRef(P));1135if (!Protocols.empty())1136JOS.attribute("protocols", std::move(Protocols));1137}11381139void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {1140VisitNamedDecl(D);1141JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));1142JOS.attribute("categoryDecl", createBareDeclRef(D->getCategoryDecl()));1143}11441145void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {1146VisitNamedDecl(D);11471148llvm::json::Array Protocols;1149for (const auto *P : D->protocols())1150Protocols.push_back(createBareDeclRef(P));1151if (!Protocols.empty())1152JOS.attribute("protocols", std::move(Protocols));1153}11541155void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {1156VisitNamedDecl(D);1157JOS.attribute("super", createBareDeclRef(D->getSuperClass()));1158JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));11591160llvm::json::Array Protocols;1161for (const auto* P : D->protocols())1162Protocols.push_back(createBareDeclRef(P));1163if (!Protocols.empty())1164JOS.attribute("protocols", std::move(Protocols));1165}11661167void JSONNodeDumper::VisitObjCImplementationDecl(1168const ObjCImplementationDecl *D) {1169VisitNamedDecl(D);1170JOS.attribute("super", createBareDeclRef(D->getSuperClass()));1171JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));1172}11731174void JSONNodeDumper::VisitObjCCompatibleAliasDecl(1175const ObjCCompatibleAliasDecl *D) {1176VisitNamedDecl(D);1177JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));1178}11791180void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {1181VisitNamedDecl(D);1182JOS.attribute("type", createQualType(D->getType()));11831184switch (D->getPropertyImplementation()) {1185case ObjCPropertyDecl::None: break;1186case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break;1187case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break;1188}11891190ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();1191if (Attrs != ObjCPropertyAttribute::kind_noattr) {1192if (Attrs & ObjCPropertyAttribute::kind_getter)1193JOS.attribute("getter", createBareDeclRef(D->getGetterMethodDecl()));1194if (Attrs & ObjCPropertyAttribute::kind_setter)1195JOS.attribute("setter", createBareDeclRef(D->getSetterMethodDecl()));1196attributeOnlyIfTrue("readonly",1197Attrs & ObjCPropertyAttribute::kind_readonly);1198attributeOnlyIfTrue("assign", Attrs & ObjCPropertyAttribute::kind_assign);1199attributeOnlyIfTrue("readwrite",1200Attrs & ObjCPropertyAttribute::kind_readwrite);1201attributeOnlyIfTrue("retain", Attrs & ObjCPropertyAttribute::kind_retain);1202attributeOnlyIfTrue("copy", Attrs & ObjCPropertyAttribute::kind_copy);1203attributeOnlyIfTrue("nonatomic",1204Attrs & ObjCPropertyAttribute::kind_nonatomic);1205attributeOnlyIfTrue("atomic", Attrs & ObjCPropertyAttribute::kind_atomic);1206attributeOnlyIfTrue("weak", Attrs & ObjCPropertyAttribute::kind_weak);1207attributeOnlyIfTrue("strong", Attrs & ObjCPropertyAttribute::kind_strong);1208attributeOnlyIfTrue("unsafe_unretained",1209Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);1210attributeOnlyIfTrue("class", Attrs & ObjCPropertyAttribute::kind_class);1211attributeOnlyIfTrue("direct", Attrs & ObjCPropertyAttribute::kind_direct);1212attributeOnlyIfTrue("nullability",1213Attrs & ObjCPropertyAttribute::kind_nullability);1214attributeOnlyIfTrue("null_resettable",1215Attrs & ObjCPropertyAttribute::kind_null_resettable);1216}1217}12181219void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {1220VisitNamedDecl(D->getPropertyDecl());1221JOS.attribute("implKind", D->getPropertyImplementation() ==1222ObjCPropertyImplDecl::Synthesize1223? "synthesize"1224: "dynamic");1225JOS.attribute("propertyDecl", createBareDeclRef(D->getPropertyDecl()));1226JOS.attribute("ivarDecl", createBareDeclRef(D->getPropertyIvarDecl()));1227}12281229void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) {1230attributeOnlyIfTrue("variadic", D->isVariadic());1231attributeOnlyIfTrue("capturesThis", D->capturesCXXThis());1232}12331234void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {1235JOS.attribute("name", AE->getOpAsString());1236}12371238void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) {1239JOS.attribute("encodedType", createQualType(OEE->getEncodedType()));1240}12411242void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *OME) {1243std::string Str;1244llvm::raw_string_ostream OS(Str);12451246OME->getSelector().print(OS);1247JOS.attribute("selector", Str);12481249switch (OME->getReceiverKind()) {1250case ObjCMessageExpr::Instance:1251JOS.attribute("receiverKind", "instance");1252break;1253case ObjCMessageExpr::Class:1254JOS.attribute("receiverKind", "class");1255JOS.attribute("classType", createQualType(OME->getClassReceiver()));1256break;1257case ObjCMessageExpr::SuperInstance:1258JOS.attribute("receiverKind", "super (instance)");1259JOS.attribute("superType", createQualType(OME->getSuperType()));1260break;1261case ObjCMessageExpr::SuperClass:1262JOS.attribute("receiverKind", "super (class)");1263JOS.attribute("superType", createQualType(OME->getSuperType()));1264break;1265}12661267QualType CallReturnTy = OME->getCallReturnType(Ctx);1268if (OME->getType() != CallReturnTy)1269JOS.attribute("callReturnType", createQualType(CallReturnTy));1270}12711272void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE) {1273if (const ObjCMethodDecl *MD = OBE->getBoxingMethod()) {1274std::string Str;1275llvm::raw_string_ostream OS(Str);12761277MD->getSelector().print(OS);1278JOS.attribute("selector", Str);1279}1280}12811282void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE) {1283std::string Str;1284llvm::raw_string_ostream OS(Str);12851286OSE->getSelector().print(OS);1287JOS.attribute("selector", Str);1288}12891290void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {1291JOS.attribute("protocol", createBareDeclRef(OPE->getProtocol()));1292}12931294void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {1295if (OPRE->isImplicitProperty()) {1296JOS.attribute("propertyKind", "implicit");1297if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter())1298JOS.attribute("getter", createBareDeclRef(MD));1299if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter())1300JOS.attribute("setter", createBareDeclRef(MD));1301} else {1302JOS.attribute("propertyKind", "explicit");1303JOS.attribute("property", createBareDeclRef(OPRE->getExplicitProperty()));1304}13051306attributeOnlyIfTrue("isSuperReceiver", OPRE->isSuperReceiver());1307attributeOnlyIfTrue("isMessagingGetter", OPRE->isMessagingGetter());1308attributeOnlyIfTrue("isMessagingSetter", OPRE->isMessagingSetter());1309}13101311void JSONNodeDumper::VisitObjCSubscriptRefExpr(1312const ObjCSubscriptRefExpr *OSRE) {1313JOS.attribute("subscriptKind",1314OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary");13151316if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl())1317JOS.attribute("getter", createBareDeclRef(MD));1318if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl())1319JOS.attribute("setter", createBareDeclRef(MD));1320}13211322void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {1323JOS.attribute("decl", createBareDeclRef(OIRE->getDecl()));1324attributeOnlyIfTrue("isFreeIvar", OIRE->isFreeIvar());1325JOS.attribute("isArrow", OIRE->isArrow());1326}13271328void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) {1329JOS.attribute("value", OBLE->getValue() ? "__objc_yes" : "__objc_no");1330}13311332void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {1333JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl()));1334if (DRE->getDecl() != DRE->getFoundDecl())1335JOS.attribute("foundReferencedDecl",1336createBareDeclRef(DRE->getFoundDecl()));1337switch (DRE->isNonOdrUse()) {1338case NOUR_None: break;1339case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;1340case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;1341case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;1342}1343attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating());1344}13451346void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(1347const SYCLUniqueStableNameExpr *E) {1348JOS.attribute("typeSourceInfo",1349createQualType(E->getTypeSourceInfo()->getType()));1350}13511352void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {1353JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));1354}13551356void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {1357JOS.attribute("isPostfix", UO->isPostfix());1358JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode()));1359if (!UO->canOverflow())1360JOS.attribute("canOverflow", false);1361}13621363void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) {1364JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode()));1365}13661367void JSONNodeDumper::VisitCompoundAssignOperator(1368const CompoundAssignOperator *CAO) {1369VisitBinaryOperator(CAO);1370JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType()));1371JOS.attribute("computeResultType",1372createQualType(CAO->getComputationResultType()));1373}13741375void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) {1376// Note, we always write this Boolean field because the information it conveys1377// is critical to understanding the AST node.1378ValueDecl *VD = ME->getMemberDecl();1379JOS.attribute("name", VD && VD->getDeclName() ? VD->getNameAsString() : "");1380JOS.attribute("isArrow", ME->isArrow());1381JOS.attribute("referencedMemberDecl", createPointerRepresentation(VD));1382switch (ME->isNonOdrUse()) {1383case NOUR_None: break;1384case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;1385case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;1386case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;1387}1388}13891390void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {1391attributeOnlyIfTrue("isGlobal", NE->isGlobalNew());1392attributeOnlyIfTrue("isArray", NE->isArray());1393attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0);1394switch (NE->getInitializationStyle()) {1395case CXXNewInitializationStyle::None:1396break;1397case CXXNewInitializationStyle::Parens:1398JOS.attribute("initStyle", "call");1399break;1400case CXXNewInitializationStyle::Braces:1401JOS.attribute("initStyle", "list");1402break;1403}1404if (const FunctionDecl *FD = NE->getOperatorNew())1405JOS.attribute("operatorNewDecl", createBareDeclRef(FD));1406if (const FunctionDecl *FD = NE->getOperatorDelete())1407JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));1408}1409void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {1410attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete());1411attributeOnlyIfTrue("isArray", DE->isArrayForm());1412attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten());1413if (const FunctionDecl *FD = DE->getOperatorDelete())1414JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));1415}14161417void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) {1418attributeOnlyIfTrue("implicit", TE->isImplicit());1419}14201421void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) {1422JOS.attribute("castKind", CE->getCastKindName());1423llvm::json::Array Path = createCastPath(CE);1424if (!Path.empty())1425JOS.attribute("path", std::move(Path));1426// FIXME: This may not be useful information as it can be obtusely gleaned1427// from the inner[] array.1428if (const NamedDecl *ND = CE->getConversionFunction())1429JOS.attribute("conversionFunc", createBareDeclRef(ND));1430}14311432void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {1433VisitCastExpr(ICE);1434attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast());1435}14361437void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {1438attributeOnlyIfTrue("adl", CE->usesADL());1439}14401441void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(1442const UnaryExprOrTypeTraitExpr *TTE) {1443JOS.attribute("name", getTraitSpelling(TTE->getKind()));1444if (TTE->isArgumentType())1445JOS.attribute("argType", createQualType(TTE->getArgumentType()));1446}14471448void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) {1449VisitNamedDecl(SOPE->getPack());1450}14511452void JSONNodeDumper::VisitUnresolvedLookupExpr(1453const UnresolvedLookupExpr *ULE) {1454JOS.attribute("usesADL", ULE->requiresADL());1455JOS.attribute("name", ULE->getName().getAsString());14561457JOS.attributeArray("lookups", [this, ULE] {1458for (const NamedDecl *D : ULE->decls())1459JOS.value(createBareDeclRef(D));1460});1461}14621463void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) {1464JOS.attribute("name", ALE->getLabel()->getName());1465JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel()));1466}14671468void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {1469if (CTE->isTypeOperand()) {1470QualType Adjusted = CTE->getTypeOperand(Ctx);1471QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType();1472JOS.attribute("typeArg", createQualType(Unadjusted));1473if (Adjusted != Unadjusted)1474JOS.attribute("adjustedTypeArg", createQualType(Adjusted));1475}1476}14771478void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {1479if (CE->getResultAPValueKind() != APValue::None)1480Visit(CE->getAPValueResult(), CE->getType());1481}14821483void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {1484if (const FieldDecl *FD = ILE->getInitializedFieldInUnion())1485JOS.attribute("field", createBareDeclRef(FD));1486}14871488void JSONNodeDumper::VisitGenericSelectionExpr(1489const GenericSelectionExpr *GSE) {1490attributeOnlyIfTrue("resultDependent", GSE->isResultDependent());1491}14921493void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(1494const CXXUnresolvedConstructExpr *UCE) {1495if (UCE->getType() != UCE->getTypeAsWritten())1496JOS.attribute("typeAsWritten", createQualType(UCE->getTypeAsWritten()));1497attributeOnlyIfTrue("list", UCE->isListInitialization());1498}14991500void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) {1501CXXConstructorDecl *Ctor = CE->getConstructor();1502JOS.attribute("ctorType", createQualType(Ctor->getType()));1503attributeOnlyIfTrue("elidable", CE->isElidable());1504attributeOnlyIfTrue("list", CE->isListInitialization());1505attributeOnlyIfTrue("initializer_list", CE->isStdInitListInitialization());1506attributeOnlyIfTrue("zeroing", CE->requiresZeroInitialization());1507attributeOnlyIfTrue("hadMultipleCandidates", CE->hadMultipleCandidates());1508attributeOnlyIfTrue("isImmediateEscalating", CE->isImmediateEscalating());15091510switch (CE->getConstructionKind()) {1511case CXXConstructionKind::Complete:1512JOS.attribute("constructionKind", "complete");1513break;1514case CXXConstructionKind::Delegating:1515JOS.attribute("constructionKind", "delegating");1516break;1517case CXXConstructionKind::NonVirtualBase:1518JOS.attribute("constructionKind", "non-virtual base");1519break;1520case CXXConstructionKind::VirtualBase:1521JOS.attribute("constructionKind", "virtual base");1522break;1523}1524}15251526void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {1527attributeOnlyIfTrue("cleanupsHaveSideEffects",1528EWC->cleanupsHaveSideEffects());1529if (EWC->getNumObjects()) {1530JOS.attributeArray("cleanups", [this, EWC] {1531for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())1532if (auto *BD = CO.dyn_cast<BlockDecl *>()) {1533JOS.value(createBareDeclRef(BD));1534} else if (auto *CLE = CO.dyn_cast<CompoundLiteralExpr *>()) {1535llvm::json::Object Obj;1536Obj["id"] = createPointerRepresentation(CLE);1537Obj["kind"] = CLE->getStmtClassName();1538JOS.value(std::move(Obj));1539} else {1540llvm_unreachable("unexpected cleanup object type");1541}1542});1543}1544}15451546void JSONNodeDumper::VisitCXXBindTemporaryExpr(1547const CXXBindTemporaryExpr *BTE) {1548const CXXTemporary *Temp = BTE->getTemporary();1549JOS.attribute("temp", createPointerRepresentation(Temp));1550if (const CXXDestructorDecl *Dtor = Temp->getDestructor())1551JOS.attribute("dtor", createBareDeclRef(Dtor));1552}15531554void JSONNodeDumper::VisitMaterializeTemporaryExpr(1555const MaterializeTemporaryExpr *MTE) {1556if (const ValueDecl *VD = MTE->getExtendingDecl())1557JOS.attribute("extendingDecl", createBareDeclRef(VD));15581559switch (MTE->getStorageDuration()) {1560case SD_Automatic:1561JOS.attribute("storageDuration", "automatic");1562break;1563case SD_Dynamic:1564JOS.attribute("storageDuration", "dynamic");1565break;1566case SD_FullExpression:1567JOS.attribute("storageDuration", "full expression");1568break;1569case SD_Static:1570JOS.attribute("storageDuration", "static");1571break;1572case SD_Thread:1573JOS.attribute("storageDuration", "thread");1574break;1575}15761577attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference());1578}15791580void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {1581attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());1582}15831584void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {1585attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());1586}15871588void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(1589const CXXDependentScopeMemberExpr *DSME) {1590JOS.attribute("isArrow", DSME->isArrow());1591JOS.attribute("member", DSME->getMember().getAsString());1592attributeOnlyIfTrue("hasTemplateKeyword", DSME->hasTemplateKeyword());1593attributeOnlyIfTrue("hasExplicitTemplateArgs",1594DSME->hasExplicitTemplateArgs());15951596if (DSME->getNumTemplateArgs()) {1597JOS.attributeArray("explicitTemplateArgs", [DSME, this] {1598for (const TemplateArgumentLoc &TAL : DSME->template_arguments())1599JOS.object(1600[&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });1601});1602}1603}16041605void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {1606if (!RE->isValueDependent())1607JOS.attribute("satisfied", RE->isSatisfied());1608}16091610void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {1611llvm::SmallString<16> Buffer;1612IL->getValue().toString(Buffer,1613/*Radix=*/10, IL->getType()->isSignedIntegerType());1614JOS.attribute("value", Buffer);1615}1616void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) {1617// FIXME: This should probably print the character literal as a string,1618// rather than as a numerical value. It would be nice if the behavior matched1619// what we do to print a string literal; right now, it is impossible to tell1620// the difference between 'a' and L'a' in C from the JSON output.1621JOS.attribute("value", CL->getValue());1622}1623void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) {1624JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10));1625}1626void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) {1627llvm::SmallString<16> Buffer;1628FL->getValue().toString(Buffer);1629JOS.attribute("value", Buffer);1630}1631void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) {1632std::string Buffer;1633llvm::raw_string_ostream SS(Buffer);1634SL->outputString(SS);1635JOS.attribute("value", Buffer);1636}1637void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) {1638JOS.attribute("value", BLE->getValue());1639}16401641void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) {1642attributeOnlyIfTrue("hasInit", IS->hasInitStorage());1643attributeOnlyIfTrue("hasVar", IS->hasVarStorage());1644attributeOnlyIfTrue("hasElse", IS->hasElseStorage());1645attributeOnlyIfTrue("isConstexpr", IS->isConstexpr());1646attributeOnlyIfTrue("isConsteval", IS->isConsteval());1647attributeOnlyIfTrue("constevalIsNegated", IS->isNegatedConsteval());1648}16491650void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) {1651attributeOnlyIfTrue("hasInit", SS->hasInitStorage());1652attributeOnlyIfTrue("hasVar", SS->hasVarStorage());1653}1654void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {1655attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange());1656}16571658void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {1659JOS.attribute("name", LS->getName());1660JOS.attribute("declId", createPointerRepresentation(LS->getDecl()));1661attributeOnlyIfTrue("sideEntry", LS->isSideEntry());1662}1663void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {1664JOS.attribute("targetLabelDeclId",1665createPointerRepresentation(GS->getLabel()));1666}16671668void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) {1669attributeOnlyIfTrue("hasVar", WS->hasVarStorage());1670}16711672void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) {1673// FIXME: it would be nice for the ASTNodeTraverser would handle the catch1674// parameter the same way for C++ and ObjC rather. In this case, C++ gets a1675// null child node and ObjC gets no child node.1676attributeOnlyIfTrue("isCatchAll", OACS->getCatchParamDecl() == nullptr);1677}16781679void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) {1680JOS.attribute("isNull", true);1681}1682void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {1683JOS.attribute("type", createQualType(TA.getAsType()));1684}1685void JSONNodeDumper::VisitDeclarationTemplateArgument(1686const TemplateArgument &TA) {1687JOS.attribute("decl", createBareDeclRef(TA.getAsDecl()));1688}1689void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) {1690JOS.attribute("isNullptr", true);1691}1692void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {1693JOS.attribute("value", TA.getAsIntegral().getSExtValue());1694}1695void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {1696// FIXME: cannot just call dump() on the argument, as that doesn't specify1697// the output format.1698}1699void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(1700const TemplateArgument &TA) {1701// FIXME: cannot just call dump() on the argument, as that doesn't specify1702// the output format.1703}1704void JSONNodeDumper::VisitExpressionTemplateArgument(1705const TemplateArgument &TA) {1706JOS.attribute("isExpr", true);1707}1708void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {1709JOS.attribute("isPack", true);1710}17111712StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const {1713if (Traits)1714return Traits->getCommandInfo(CommandID)->Name;1715if (const comments::CommandInfo *Info =1716comments::CommandTraits::getBuiltinCommandInfo(CommandID))1717return Info->Name;1718return "<invalid>";1719}17201721void JSONNodeDumper::visitTextComment(const comments::TextComment *C,1722const comments::FullComment *) {1723JOS.attribute("text", C->getText());1724}17251726void JSONNodeDumper::visitInlineCommandComment(1727const comments::InlineCommandComment *C, const comments::FullComment *) {1728JOS.attribute("name", getCommentCommandName(C->getCommandID()));17291730switch (C->getRenderKind()) {1731case comments::InlineCommandRenderKind::Normal:1732JOS.attribute("renderKind", "normal");1733break;1734case comments::InlineCommandRenderKind::Bold:1735JOS.attribute("renderKind", "bold");1736break;1737case comments::InlineCommandRenderKind::Emphasized:1738JOS.attribute("renderKind", "emphasized");1739break;1740case comments::InlineCommandRenderKind::Monospaced:1741JOS.attribute("renderKind", "monospaced");1742break;1743case comments::InlineCommandRenderKind::Anchor:1744JOS.attribute("renderKind", "anchor");1745break;1746}17471748llvm::json::Array Args;1749for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)1750Args.push_back(C->getArgText(I));17511752if (!Args.empty())1753JOS.attribute("args", std::move(Args));1754}17551756void JSONNodeDumper::visitHTMLStartTagComment(1757const comments::HTMLStartTagComment *C, const comments::FullComment *) {1758JOS.attribute("name", C->getTagName());1759attributeOnlyIfTrue("selfClosing", C->isSelfClosing());1760attributeOnlyIfTrue("malformed", C->isMalformed());17611762llvm::json::Array Attrs;1763for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I)1764Attrs.push_back(1765{{"name", C->getAttr(I).Name}, {"value", C->getAttr(I).Value}});17661767if (!Attrs.empty())1768JOS.attribute("attrs", std::move(Attrs));1769}17701771void JSONNodeDumper::visitHTMLEndTagComment(1772const comments::HTMLEndTagComment *C, const comments::FullComment *) {1773JOS.attribute("name", C->getTagName());1774}17751776void JSONNodeDumper::visitBlockCommandComment(1777const comments::BlockCommandComment *C, const comments::FullComment *) {1778JOS.attribute("name", getCommentCommandName(C->getCommandID()));17791780llvm::json::Array Args;1781for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)1782Args.push_back(C->getArgText(I));17831784if (!Args.empty())1785JOS.attribute("args", std::move(Args));1786}17871788void JSONNodeDumper::visitParamCommandComment(1789const comments::ParamCommandComment *C, const comments::FullComment *FC) {1790switch (C->getDirection()) {1791case comments::ParamCommandPassDirection::In:1792JOS.attribute("direction", "in");1793break;1794case comments::ParamCommandPassDirection::Out:1795JOS.attribute("direction", "out");1796break;1797case comments::ParamCommandPassDirection::InOut:1798JOS.attribute("direction", "in,out");1799break;1800}1801attributeOnlyIfTrue("explicit", C->isDirectionExplicit());18021803if (C->hasParamName())1804JOS.attribute("param", C->isParamIndexValid() ? C->getParamName(FC)1805: C->getParamNameAsWritten());18061807if (C->isParamIndexValid() && !C->isVarArgParam())1808JOS.attribute("paramIdx", C->getParamIndex());1809}18101811void JSONNodeDumper::visitTParamCommandComment(1812const comments::TParamCommandComment *C, const comments::FullComment *FC) {1813if (C->hasParamName())1814JOS.attribute("param", C->isPositionValid() ? C->getParamName(FC)1815: C->getParamNameAsWritten());1816if (C->isPositionValid()) {1817llvm::json::Array Positions;1818for (unsigned I = 0, E = C->getDepth(); I < E; ++I)1819Positions.push_back(C->getIndex(I));18201821if (!Positions.empty())1822JOS.attribute("positions", std::move(Positions));1823}1824}18251826void JSONNodeDumper::visitVerbatimBlockComment(1827const comments::VerbatimBlockComment *C, const comments::FullComment *) {1828JOS.attribute("name", getCommentCommandName(C->getCommandID()));1829JOS.attribute("closeName", C->getCloseName());1830}18311832void JSONNodeDumper::visitVerbatimBlockLineComment(1833const comments::VerbatimBlockLineComment *C,1834const comments::FullComment *) {1835JOS.attribute("text", C->getText());1836}18371838void JSONNodeDumper::visitVerbatimLineComment(1839const comments::VerbatimLineComment *C, const comments::FullComment *) {1840JOS.attribute("text", C->getText());1841}18421843llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) {1844llvm::json::Object Ret;1845#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \1846if (FPO.has##NAME##Override()) \1847Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override()));1848#include "clang/Basic/FPOptions.def"1849return Ret;1850}18511852void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {1853VisitStmt(S);1854if (S->hasStoredFPFeatures())1855JOS.attribute("fpoptions", createFPOptions(S->getStoredFPFeatures()));1856}185718581859