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