1 #include "clang/AST/JSONNodeDumper.h" 2 #include "llvm/ADT/StringSwitch.h" 3 4 using namespace clang; 5 6 void JSONNodeDumper::addPreviousDeclaration(const Decl *D) { 7 switch (D->getKind()) { 8 #define DECL(DERIVED, BASE) \ 9 case Decl::DERIVED: \ 10 return writePreviousDeclImpl(cast<DERIVED##Decl>(D)); 11 #define ABSTRACT_DECL(DECL) 12 #include "clang/AST/DeclNodes.inc" 13 #undef ABSTRACT_DECL 14 #undef DECL 15 } 16 llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); 17 } 18 19 void JSONNodeDumper::Visit(const Attr *A) { 20 const char *AttrName = nullptr; 21 switch (A->getKind()) { 22 #define ATTR(X) \ 23 case attr::X: \ 24 AttrName = #X"Attr"; \ 25 break; 26 #include "clang/Basic/AttrList.inc" 27 #undef ATTR 28 } 29 JOS.attribute("id", createPointerRepresentation(A)); 30 JOS.attribute("kind", AttrName); 31 JOS.attribute("range", createSourceRange(A->getRange())); 32 attributeOnlyIfTrue("inherited", A->isInherited()); 33 attributeOnlyIfTrue("implicit", A->isImplicit()); 34 35 // FIXME: it would be useful for us to output the spelling kind as well as 36 // the actual spelling. This would allow us to distinguish between the 37 // various attribute syntaxes, but we don't currently track that information 38 // within the AST. 39 //JOS.attribute("spelling", A->getSpelling()); 40 41 InnerAttrVisitor::Visit(A); 42 } 43 44 void JSONNodeDumper::Visit(const Stmt *S) { 45 if (!S) 46 return; 47 48 JOS.attribute("id", createPointerRepresentation(S)); 49 JOS.attribute("kind", S->getStmtClassName()); 50 JOS.attribute("range", createSourceRange(S->getSourceRange())); 51 52 if (const auto *E = dyn_cast<Expr>(S)) { 53 JOS.attribute("type", createQualType(E->getType())); 54 const char *Category = nullptr; 55 switch (E->getValueKind()) { 56 case VK_LValue: Category = "lvalue"; break; 57 case VK_XValue: Category = "xvalue"; break; 58 case VK_RValue: Category = "rvalue"; break; 59 } 60 JOS.attribute("valueCategory", Category); 61 } 62 InnerStmtVisitor::Visit(S); 63 } 64 65 void JSONNodeDumper::Visit(const Type *T) { 66 JOS.attribute("id", createPointerRepresentation(T)); 67 JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str()); 68 JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar*/ false)); 69 attributeOnlyIfTrue("isDependent", T->isDependentType()); 70 attributeOnlyIfTrue("isInstantiationDependent", 71 T->isInstantiationDependentType()); 72 attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType()); 73 attributeOnlyIfTrue("containsUnexpandedPack", 74 T->containsUnexpandedParameterPack()); 75 attributeOnlyIfTrue("isImported", T->isFromAST()); 76 InnerTypeVisitor::Visit(T); 77 } 78 79 void JSONNodeDumper::Visit(QualType T) { 80 JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr())); 81 JOS.attribute("type", createQualType(T)); 82 JOS.attribute("qualifiers", T.split().Quals.getAsString()); 83 } 84 85 void JSONNodeDumper::Visit(const Decl *D) { 86 JOS.attribute("id", createPointerRepresentation(D)); 87 88 if (!D) 89 return; 90 91 JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str()); 92 JOS.attribute("loc", createSourceLocation(D->getLocation())); 93 JOS.attribute("range", createSourceRange(D->getSourceRange())); 94 attributeOnlyIfTrue("isImplicit", D->isImplicit()); 95 attributeOnlyIfTrue("isInvalid", D->isInvalidDecl()); 96 97 if (D->isUsed()) 98 JOS.attribute("isUsed", true); 99 else if (D->isThisDeclarationReferenced()) 100 JOS.attribute("isReferenced", true); 101 102 if (const auto *ND = dyn_cast<NamedDecl>(D)) 103 attributeOnlyIfTrue("isHidden", ND->isHidden()); 104 105 if (D->getLexicalDeclContext() != D->getDeclContext()) 106 JOS.attribute("parentDeclContext", 107 createPointerRepresentation(D->getDeclContext())); 108 109 addPreviousDeclaration(D); 110 InnerDeclVisitor::Visit(D); 111 } 112 113 void JSONNodeDumper::Visit(const comments::Comment *C, 114 const comments::FullComment *FC) { 115 if (!C) 116 return; 117 118 JOS.attribute("id", createPointerRepresentation(C)); 119 JOS.attribute("kind", C->getCommentKindName()); 120 JOS.attribute("loc", createSourceLocation(C->getLocation())); 121 JOS.attribute("range", createSourceRange(C->getSourceRange())); 122 123 InnerCommentVisitor::visit(C, FC); 124 } 125 126 void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R, 127 const Decl *From, StringRef Label) { 128 JOS.attribute("kind", "TemplateArgument"); 129 if (R.isValid()) 130 JOS.attribute("range", createSourceRange(R)); 131 132 if (From) 133 JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From)); 134 135 InnerTemplateArgVisitor::Visit(TA); 136 } 137 138 void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) { 139 JOS.attribute("kind", "CXXCtorInitializer"); 140 if (Init->isAnyMemberInitializer()) 141 JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember())); 142 else if (Init->isBaseInitializer()) 143 JOS.attribute("baseInit", 144 createQualType(QualType(Init->getBaseClass(), 0))); 145 else if (Init->isDelegatingInitializer()) 146 JOS.attribute("delegatingInit", 147 createQualType(Init->getTypeSourceInfo()->getType())); 148 else 149 llvm_unreachable("Unknown initializer type"); 150 } 151 152 void JSONNodeDumper::Visit(const OMPClause *C) {} 153 void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {} 154 void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) { 155 JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default"); 156 attributeOnlyIfTrue("selected", A.isSelected()); 157 } 158 159 llvm::json::Object 160 JSONNodeDumper::createBareSourceLocation(SourceLocation Loc) { 161 PresumedLoc Presumed = SM.getPresumedLoc(Loc); 162 163 if (Presumed.isInvalid()) 164 return llvm::json::Object{}; 165 166 return llvm::json::Object{{"file", Presumed.getFilename()}, 167 {"line", Presumed.getLine()}, 168 {"col", Presumed.getColumn()}}; 169 } 170 171 llvm::json::Object JSONNodeDumper::createSourceLocation(SourceLocation Loc) { 172 SourceLocation Spelling = SM.getSpellingLoc(Loc); 173 SourceLocation Expansion = SM.getExpansionLoc(Loc); 174 175 llvm::json::Object SLoc = createBareSourceLocation(Spelling); 176 if (Expansion != Spelling) { 177 // If the expansion and the spelling are different, output subobjects 178 // describing both locations. 179 llvm::json::Object ELoc = createBareSourceLocation(Expansion); 180 181 // If there is a macro expansion, add extra information if the interesting 182 // bit is the macro arg expansion. 183 if (SM.isMacroArgExpansion(Loc)) 184 ELoc["isMacroArgExpansion"] = true; 185 186 return llvm::json::Object{{"spellingLoc", std::move(SLoc)}, 187 {"expansionLoc", std::move(ELoc)}}; 188 } 189 190 return SLoc; 191 } 192 193 llvm::json::Object JSONNodeDumper::createSourceRange(SourceRange R) { 194 return llvm::json::Object{{"begin", createSourceLocation(R.getBegin())}, 195 {"end", createSourceLocation(R.getEnd())}}; 196 } 197 198 std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) { 199 // Because JSON stores integer values as signed 64-bit integers, trying to 200 // represent them as such makes for very ugly pointer values in the resulting 201 // output. Instead, we convert the value to hex and treat it as a string. 202 return "0x" + llvm::utohexstr(reinterpret_cast<uint64_t>(Ptr), true); 203 } 204 205 llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) { 206 SplitQualType SQT = QT.split(); 207 llvm::json::Object Ret{{"qualType", QualType::getAsString(SQT, PrintPolicy)}}; 208 209 if (Desugar && !QT.isNull()) { 210 SplitQualType DSQT = QT.getSplitDesugaredType(); 211 if (DSQT != SQT) 212 Ret["desugaredQualType"] = QualType::getAsString(DSQT, PrintPolicy); 213 } 214 return Ret; 215 } 216 217 llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) { 218 llvm::json::Object Ret{ 219 {"id", createPointerRepresentation(D)}, 220 {"kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str()}}; 221 if (const auto *ND = dyn_cast<NamedDecl>(D)) 222 Ret["name"] = ND->getDeclName().getAsString(); 223 if (const auto *VD = dyn_cast<ValueDecl>(D)) 224 Ret["type"] = createQualType(VD->getType()); 225 return Ret; 226 } 227 228 llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) { 229 llvm::json::Array Ret; 230 if (C->path_empty()) 231 return Ret; 232 233 for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) { 234 const CXXBaseSpecifier *Base = *I; 235 const auto *RD = 236 cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 237 238 llvm::json::Object Val{{"name", RD->getName()}}; 239 if (Base->isVirtual()) 240 Val["isVirtual"] = true; 241 Ret.push_back(std::move(Val)); 242 } 243 return Ret; 244 } 245 246 #define FIELD2(Name, Flag) if (RD->Flag()) Ret[Name] = true 247 #define FIELD1(Flag) FIELD2(#Flag, Flag) 248 249 static llvm::json::Object 250 createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) { 251 llvm::json::Object Ret; 252 253 FIELD2("exists", hasDefaultConstructor); 254 FIELD2("trivial", hasTrivialDefaultConstructor); 255 FIELD2("nonTrivial", hasNonTrivialDefaultConstructor); 256 FIELD2("userProvided", hasUserProvidedDefaultConstructor); 257 FIELD2("isConstexpr", hasConstexprDefaultConstructor); 258 FIELD2("needsImplicit", needsImplicitDefaultConstructor); 259 FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr); 260 261 return Ret; 262 } 263 264 static llvm::json::Object 265 createCopyConstructorDefinitionData(const CXXRecordDecl *RD) { 266 llvm::json::Object Ret; 267 268 FIELD2("simple", hasSimpleCopyConstructor); 269 FIELD2("trivial", hasTrivialCopyConstructor); 270 FIELD2("nonTrivial", hasNonTrivialCopyConstructor); 271 FIELD2("userDeclared", hasUserDeclaredCopyConstructor); 272 FIELD2("hasConstParam", hasCopyConstructorWithConstParam); 273 FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam); 274 FIELD2("needsImplicit", needsImplicitCopyConstructor); 275 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor); 276 if (!RD->needsOverloadResolutionForCopyConstructor()) 277 FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted); 278 279 return Ret; 280 } 281 282 static llvm::json::Object 283 createMoveConstructorDefinitionData(const CXXRecordDecl *RD) { 284 llvm::json::Object Ret; 285 286 FIELD2("exists", hasMoveConstructor); 287 FIELD2("simple", hasSimpleMoveConstructor); 288 FIELD2("trivial", hasTrivialMoveConstructor); 289 FIELD2("nonTrivial", hasNonTrivialMoveConstructor); 290 FIELD2("userDeclared", hasUserDeclaredMoveConstructor); 291 FIELD2("needsImplicit", needsImplicitMoveConstructor); 292 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor); 293 if (!RD->needsOverloadResolutionForMoveConstructor()) 294 FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted); 295 296 return Ret; 297 } 298 299 static llvm::json::Object 300 createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) { 301 llvm::json::Object Ret; 302 303 FIELD2("trivial", hasTrivialCopyAssignment); 304 FIELD2("nonTrivial", hasNonTrivialCopyAssignment); 305 FIELD2("hasConstParam", hasCopyAssignmentWithConstParam); 306 FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam); 307 FIELD2("userDeclared", hasUserDeclaredCopyAssignment); 308 FIELD2("needsImplicit", needsImplicitCopyAssignment); 309 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment); 310 311 return Ret; 312 } 313 314 static llvm::json::Object 315 createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) { 316 llvm::json::Object Ret; 317 318 FIELD2("exists", hasMoveAssignment); 319 FIELD2("simple", hasSimpleMoveAssignment); 320 FIELD2("trivial", hasTrivialMoveAssignment); 321 FIELD2("nonTrivial", hasNonTrivialMoveAssignment); 322 FIELD2("userDeclared", hasUserDeclaredMoveAssignment); 323 FIELD2("needsImplicit", needsImplicitMoveAssignment); 324 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment); 325 326 return Ret; 327 } 328 329 static llvm::json::Object 330 createDestructorDefinitionData(const CXXRecordDecl *RD) { 331 llvm::json::Object Ret; 332 333 FIELD2("simple", hasSimpleDestructor); 334 FIELD2("irrelevant", hasIrrelevantDestructor); 335 FIELD2("trivial", hasTrivialDestructor); 336 FIELD2("nonTrivial", hasNonTrivialDestructor); 337 FIELD2("userDeclared", hasUserDeclaredDestructor); 338 FIELD2("needsImplicit", needsImplicitDestructor); 339 FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor); 340 if (!RD->needsOverloadResolutionForDestructor()) 341 FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted); 342 343 return Ret; 344 } 345 346 llvm::json::Object 347 JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) { 348 llvm::json::Object Ret; 349 350 // This data is common to all C++ classes. 351 FIELD1(isGenericLambda); 352 FIELD1(isLambda); 353 FIELD1(isEmpty); 354 FIELD1(isAggregate); 355 FIELD1(isStandardLayout); 356 FIELD1(isTriviallyCopyable); 357 FIELD1(isPOD); 358 FIELD1(isTrivial); 359 FIELD1(isPolymorphic); 360 FIELD1(isAbstract); 361 FIELD1(isLiteral); 362 FIELD1(canPassInRegisters); 363 FIELD1(hasUserDeclaredConstructor); 364 FIELD1(hasConstexprNonCopyMoveConstructor); 365 FIELD1(hasMutableFields); 366 FIELD1(hasVariantMembers); 367 FIELD2("canConstDefaultInit", allowConstDefaultInit); 368 369 Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD); 370 Ret["copyCtor"] = createCopyConstructorDefinitionData(RD); 371 Ret["moveCtor"] = createMoveConstructorDefinitionData(RD); 372 Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD); 373 Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD); 374 Ret["dtor"] = createDestructorDefinitionData(RD); 375 376 return Ret; 377 } 378 379 #undef FIELD1 380 #undef FIELD2 381 382 std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) { 383 switch (AS) { 384 case AS_none: return "none"; 385 case AS_private: return "private"; 386 case AS_protected: return "protected"; 387 case AS_public: return "public"; 388 } 389 llvm_unreachable("Unknown access specifier"); 390 } 391 392 llvm::json::Object 393 JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) { 394 llvm::json::Object Ret; 395 396 Ret["type"] = createQualType(BS.getType()); 397 Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier()); 398 Ret["writtenAccess"] = 399 createAccessSpecifier(BS.getAccessSpecifierAsWritten()); 400 if (BS.isVirtual()) 401 Ret["isVirtual"] = true; 402 if (BS.isPackExpansion()) 403 Ret["isPackExpansion"] = true; 404 405 return Ret; 406 } 407 408 void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) { 409 JOS.attribute("decl", createBareDeclRef(TT->getDecl())); 410 } 411 412 void JSONNodeDumper::VisitFunctionType(const FunctionType *T) { 413 FunctionType::ExtInfo E = T->getExtInfo(); 414 attributeOnlyIfTrue("noreturn", E.getNoReturn()); 415 attributeOnlyIfTrue("producesResult", E.getProducesResult()); 416 if (E.getHasRegParm()) 417 JOS.attribute("regParm", E.getRegParm()); 418 JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC())); 419 } 420 421 void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) { 422 FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo(); 423 attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn); 424 attributeOnlyIfTrue("const", T->isConst()); 425 attributeOnlyIfTrue("volatile", T->isVolatile()); 426 attributeOnlyIfTrue("restrict", T->isRestrict()); 427 attributeOnlyIfTrue("variadic", E.Variadic); 428 switch (E.RefQualifier) { 429 case RQ_LValue: JOS.attribute("refQualifier", "&"); break; 430 case RQ_RValue: JOS.attribute("refQualifier", "&&"); break; 431 case RQ_None: break; 432 } 433 switch (E.ExceptionSpec.Type) { 434 case EST_DynamicNone: 435 case EST_Dynamic: { 436 JOS.attribute("exceptionSpec", "throw"); 437 llvm::json::Array Types; 438 for (QualType QT : E.ExceptionSpec.Exceptions) 439 Types.push_back(createQualType(QT)); 440 JOS.attribute("exceptionTypes", std::move(Types)); 441 } break; 442 case EST_MSAny: 443 JOS.attribute("exceptionSpec", "throw"); 444 JOS.attribute("throwsAny", true); 445 break; 446 case EST_BasicNoexcept: 447 JOS.attribute("exceptionSpec", "noexcept"); 448 break; 449 case EST_NoexceptTrue: 450 case EST_NoexceptFalse: 451 JOS.attribute("exceptionSpec", "noexcept"); 452 JOS.attribute("conditionEvaluatesTo", 453 E.ExceptionSpec.Type == EST_NoexceptTrue); 454 //JOS.attributeWithCall("exceptionSpecExpr", 455 // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); }); 456 break; 457 458 // FIXME: I cannot find a way to trigger these cases while dumping the AST. I 459 // suspect you can only run into them when executing an AST dump from within 460 // the debugger, which is not a use case we worry about for the JSON dumping 461 // feature. 462 case EST_DependentNoexcept: 463 case EST_Unevaluated: 464 case EST_Uninstantiated: 465 case EST_Unparsed: 466 case EST_None: break; 467 } 468 VisitFunctionType(T); 469 } 470 471 void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) { 472 if (ND && ND->getDeclName()) 473 JOS.attribute("name", ND->getNameAsString()); 474 } 475 476 void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) { 477 VisitNamedDecl(TD); 478 JOS.attribute("type", createQualType(TD->getUnderlyingType())); 479 } 480 481 void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) { 482 VisitNamedDecl(TAD); 483 JOS.attribute("type", createQualType(TAD->getUnderlyingType())); 484 } 485 486 void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) { 487 VisitNamedDecl(ND); 488 attributeOnlyIfTrue("isInline", ND->isInline()); 489 if (!ND->isOriginalNamespace()) 490 JOS.attribute("originalNamespace", 491 createBareDeclRef(ND->getOriginalNamespace())); 492 } 493 494 void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) { 495 JOS.attribute("nominatedNamespace", 496 createBareDeclRef(UDD->getNominatedNamespace())); 497 } 498 499 void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) { 500 VisitNamedDecl(NAD); 501 JOS.attribute("aliasedNamespace", 502 createBareDeclRef(NAD->getAliasedNamespace())); 503 } 504 505 void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) { 506 std::string Name; 507 if (const NestedNameSpecifier *NNS = UD->getQualifier()) { 508 llvm::raw_string_ostream SOS(Name); 509 NNS->print(SOS, UD->getASTContext().getPrintingPolicy()); 510 } 511 Name += UD->getNameAsString(); 512 JOS.attribute("name", Name); 513 } 514 515 void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) { 516 JOS.attribute("target", createBareDeclRef(USD->getTargetDecl())); 517 } 518 519 void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) { 520 VisitNamedDecl(VD); 521 JOS.attribute("type", createQualType(VD->getType())); 522 523 StorageClass SC = VD->getStorageClass(); 524 if (SC != SC_None) 525 JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); 526 switch (VD->getTLSKind()) { 527 case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break; 528 case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break; 529 case VarDecl::TLS_None: break; 530 } 531 attributeOnlyIfTrue("nrvo", VD->isNRVOVariable()); 532 attributeOnlyIfTrue("inline", VD->isInline()); 533 attributeOnlyIfTrue("constexpr", VD->isConstexpr()); 534 attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate()); 535 if (VD->hasInit()) { 536 switch (VD->getInitStyle()) { 537 case VarDecl::CInit: JOS.attribute("init", "c"); break; 538 case VarDecl::CallInit: JOS.attribute("init", "call"); break; 539 case VarDecl::ListInit: JOS.attribute("init", "list"); break; 540 } 541 } 542 } 543 544 void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) { 545 VisitNamedDecl(FD); 546 JOS.attribute("type", createQualType(FD->getType())); 547 attributeOnlyIfTrue("mutable", FD->isMutable()); 548 attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate()); 549 attributeOnlyIfTrue("isBitfield", FD->isBitField()); 550 attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer()); 551 } 552 553 void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) { 554 VisitNamedDecl(FD); 555 JOS.attribute("type", createQualType(FD->getType())); 556 StorageClass SC = FD->getStorageClass(); 557 if (SC != SC_None) 558 JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); 559 attributeOnlyIfTrue("inline", FD->isInlineSpecified()); 560 attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten()); 561 attributeOnlyIfTrue("pure", FD->isPure()); 562 attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten()); 563 attributeOnlyIfTrue("constexpr", FD->isConstexpr()); 564 if (FD->isDefaulted()) 565 JOS.attribute("explicitlyDefaulted", 566 FD->isDeleted() ? "deleted" : "default"); 567 } 568 569 void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) { 570 VisitNamedDecl(ED); 571 if (ED->isFixed()) 572 JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType())); 573 if (ED->isScoped()) 574 JOS.attribute("scopedEnumTag", 575 ED->isScopedUsingClassTag() ? "class" : "struct"); 576 } 577 void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) { 578 VisitNamedDecl(ECD); 579 JOS.attribute("type", createQualType(ECD->getType())); 580 } 581 582 void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) { 583 VisitNamedDecl(RD); 584 JOS.attribute("tagUsed", RD->getKindName()); 585 attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition()); 586 } 587 void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) { 588 VisitRecordDecl(RD); 589 590 // All other information requires a complete definition. 591 if (!RD->isCompleteDefinition()) 592 return; 593 594 JOS.attribute("definitionData", createCXXRecordDefinitionData(RD)); 595 if (RD->getNumBases()) { 596 JOS.attributeArray("bases", [this, RD] { 597 for (const auto &Spec : RD->bases()) 598 JOS.value(createCXXBaseSpecifier(Spec)); 599 }); 600 } 601 } 602 603 void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 604 VisitNamedDecl(D); 605 JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class"); 606 JOS.attribute("depth", D->getDepth()); 607 JOS.attribute("index", D->getIndex()); 608 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 609 } 610 611 void JSONNodeDumper::VisitNonTypeTemplateParmDecl( 612 const NonTypeTemplateParmDecl *D) { 613 VisitNamedDecl(D); 614 JOS.attribute("type", createQualType(D->getType())); 615 JOS.attribute("depth", D->getDepth()); 616 JOS.attribute("index", D->getIndex()); 617 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 618 } 619 620 void JSONNodeDumper::VisitTemplateTemplateParmDecl( 621 const TemplateTemplateParmDecl *D) { 622 VisitNamedDecl(D); 623 JOS.attribute("depth", D->getDepth()); 624 JOS.attribute("index", D->getIndex()); 625 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 626 } 627 628 void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) { 629 StringRef Lang; 630 switch (LSD->getLanguage()) { 631 case LinkageSpecDecl::lang_c: Lang = "C"; break; 632 case LinkageSpecDecl::lang_cxx: Lang = "C++"; break; 633 } 634 JOS.attribute("language", Lang); 635 attributeOnlyIfTrue("hasBraces", LSD->hasBraces()); 636 } 637 638 void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) { 639 JOS.attribute("access", createAccessSpecifier(ASD->getAccess())); 640 } 641 642 void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) { 643 if (const TypeSourceInfo *T = FD->getFriendType()) 644 JOS.attribute("type", createQualType(T->getType())); 645 } 646 647 void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) { 648 JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl())); 649 if (DRE->getDecl() != DRE->getFoundDecl()) 650 JOS.attribute("foundReferencedDecl", 651 createBareDeclRef(DRE->getFoundDecl())); 652 } 653 654 void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) { 655 JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind())); 656 } 657 658 void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) { 659 JOS.attribute("isPostfix", UO->isPostfix()); 660 JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode())); 661 if (!UO->canOverflow()) 662 JOS.attribute("canOverflow", false); 663 } 664 665 void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) { 666 JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode())); 667 } 668 669 void JSONNodeDumper::VisitCompoundAssignOperator( 670 const CompoundAssignOperator *CAO) { 671 VisitBinaryOperator(CAO); 672 JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType())); 673 JOS.attribute("computeResultType", 674 createQualType(CAO->getComputationResultType())); 675 } 676 677 void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) { 678 // Note, we always write this Boolean field because the information it conveys 679 // is critical to understanding the AST node. 680 JOS.attribute("isArrow", ME->isArrow()); 681 JOS.attribute("referencedMemberDecl", 682 createPointerRepresentation(ME->getMemberDecl())); 683 } 684 685 void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { 686 attributeOnlyIfTrue("isGlobal", NE->isGlobalNew()); 687 attributeOnlyIfTrue("isArray", NE->isArray()); 688 attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0); 689 switch (NE->getInitializationStyle()) { 690 case CXXNewExpr::NoInit: break; 691 case CXXNewExpr::CallInit: JOS.attribute("initStyle", "call"); break; 692 case CXXNewExpr::ListInit: JOS.attribute("initStyle", "list"); break; 693 } 694 if (const FunctionDecl *FD = NE->getOperatorNew()) 695 JOS.attribute("operatorNewDecl", createBareDeclRef(FD)); 696 if (const FunctionDecl *FD = NE->getOperatorDelete()) 697 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); 698 } 699 void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) { 700 attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete()); 701 attributeOnlyIfTrue("isArray", DE->isArrayForm()); 702 attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten()); 703 if (const FunctionDecl *FD = DE->getOperatorDelete()) 704 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); 705 } 706 707 void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) { 708 attributeOnlyIfTrue("implicit", TE->isImplicit()); 709 } 710 711 void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) { 712 JOS.attribute("castKind", CE->getCastKindName()); 713 llvm::json::Array Path = createCastPath(CE); 714 if (!Path.empty()) 715 JOS.attribute("path", std::move(Path)); 716 // FIXME: This may not be useful information as it can be obtusely gleaned 717 // from the inner[] array. 718 if (const NamedDecl *ND = CE->getConversionFunction()) 719 JOS.attribute("conversionFunc", createBareDeclRef(ND)); 720 } 721 722 void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) { 723 VisitCastExpr(ICE); 724 attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast()); 725 } 726 727 void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) { 728 attributeOnlyIfTrue("adl", CE->usesADL()); 729 } 730 731 void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr( 732 const UnaryExprOrTypeTraitExpr *TTE) { 733 switch (TTE->getKind()) { 734 case UETT_SizeOf: JOS.attribute("name", "sizeof"); break; 735 case UETT_AlignOf: JOS.attribute("name", "alignof"); break; 736 case UETT_VecStep: JOS.attribute("name", "vec_step"); break; 737 case UETT_PreferredAlignOf: JOS.attribute("name", "__alignof"); break; 738 case UETT_OpenMPRequiredSimdAlign: 739 JOS.attribute("name", "__builtin_omp_required_simd_align"); break; 740 } 741 if (TTE->isArgumentType()) 742 JOS.attribute("argType", createQualType(TTE->getArgumentType())); 743 } 744 745 void JSONNodeDumper::VisitUnresolvedLookupExpr( 746 const UnresolvedLookupExpr *ULE) { 747 JOS.attribute("usesADL", ULE->requiresADL()); 748 JOS.attribute("name", ULE->getName().getAsString()); 749 750 JOS.attributeArray("lookups", [this, ULE] { 751 for (const NamedDecl *D : ULE->decls()) 752 JOS.value(createBareDeclRef(D)); 753 }); 754 } 755 756 void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) { 757 JOS.attribute("name", ALE->getLabel()->getName()); 758 JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel())); 759 } 760 761 void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) { 762 JOS.attribute("value", 763 IL->getValue().toString( 764 /*Radix=*/10, IL->getType()->isSignedIntegerType())); 765 } 766 void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) { 767 // FIXME: This should probably print the character literal as a string, 768 // rather than as a numerical value. It would be nice if the behavior matched 769 // what we do to print a string literal; right now, it is impossible to tell 770 // the difference between 'a' and L'a' in C from the JSON output. 771 JOS.attribute("value", CL->getValue()); 772 } 773 void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) { 774 JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10)); 775 } 776 void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) { 777 JOS.attribute("value", FL->getValueAsApproximateDouble()); 778 } 779 void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) { 780 std::string Buffer; 781 llvm::raw_string_ostream SS(Buffer); 782 SL->outputString(SS); 783 JOS.attribute("value", SS.str()); 784 } 785 void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) { 786 JOS.attribute("value", BLE->getValue()); 787 } 788 789 void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) { 790 attributeOnlyIfTrue("hasInit", IS->hasInitStorage()); 791 attributeOnlyIfTrue("hasVar", IS->hasVarStorage()); 792 attributeOnlyIfTrue("hasElse", IS->hasElseStorage()); 793 attributeOnlyIfTrue("isConstexpr", IS->isConstexpr()); 794 } 795 796 void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) { 797 attributeOnlyIfTrue("hasInit", SS->hasInitStorage()); 798 attributeOnlyIfTrue("hasVar", SS->hasVarStorage()); 799 } 800 void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) { 801 attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange()); 802 } 803 804 void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) { 805 JOS.attribute("name", LS->getName()); 806 JOS.attribute("declId", createPointerRepresentation(LS->getDecl())); 807 } 808 void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) { 809 JOS.attribute("targetLabelDeclId", 810 createPointerRepresentation(GS->getLabel())); 811 } 812 813 void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) { 814 attributeOnlyIfTrue("hasVar", WS->hasVarStorage()); 815 } 816 817 StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const { 818 if (Traits) 819 return Traits->getCommandInfo(CommandID)->Name; 820 if (const comments::CommandInfo *Info = 821 comments::CommandTraits::getBuiltinCommandInfo(CommandID)) 822 return Info->Name; 823 return "<invalid>"; 824 } 825 826 void JSONNodeDumper::visitTextComment(const comments::TextComment *C, 827 const comments::FullComment *) { 828 JOS.attribute("text", C->getText()); 829 } 830 831 void JSONNodeDumper::visitInlineCommandComment( 832 const comments::InlineCommandComment *C, const comments::FullComment *) { 833 JOS.attribute("name", getCommentCommandName(C->getCommandID())); 834 835 switch (C->getRenderKind()) { 836 case comments::InlineCommandComment::RenderNormal: 837 JOS.attribute("renderKind", "normal"); 838 break; 839 case comments::InlineCommandComment::RenderBold: 840 JOS.attribute("renderKind", "bold"); 841 break; 842 case comments::InlineCommandComment::RenderEmphasized: 843 JOS.attribute("renderKind", "emphasized"); 844 break; 845 case comments::InlineCommandComment::RenderMonospaced: 846 JOS.attribute("renderKind", "monospaced"); 847 break; 848 } 849 850 llvm::json::Array Args; 851 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) 852 Args.push_back(C->getArgText(I)); 853 854 if (!Args.empty()) 855 JOS.attribute("args", std::move(Args)); 856 } 857 858 void JSONNodeDumper::visitHTMLStartTagComment( 859 const comments::HTMLStartTagComment *C, const comments::FullComment *) { 860 JOS.attribute("name", C->getTagName()); 861 attributeOnlyIfTrue("selfClosing", C->isSelfClosing()); 862 attributeOnlyIfTrue("malformed", C->isMalformed()); 863 864 llvm::json::Array Attrs; 865 for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) 866 Attrs.push_back( 867 {{"name", C->getAttr(I).Name}, {"value", C->getAttr(I).Value}}); 868 869 if (!Attrs.empty()) 870 JOS.attribute("attrs", std::move(Attrs)); 871 } 872 873 void JSONNodeDumper::visitHTMLEndTagComment( 874 const comments::HTMLEndTagComment *C, const comments::FullComment *) { 875 JOS.attribute("name", C->getTagName()); 876 } 877 878 void JSONNodeDumper::visitBlockCommandComment( 879 const comments::BlockCommandComment *C, const comments::FullComment *) { 880 JOS.attribute("name", getCommentCommandName(C->getCommandID())); 881 882 llvm::json::Array Args; 883 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) 884 Args.push_back(C->getArgText(I)); 885 886 if (!Args.empty()) 887 JOS.attribute("args", std::move(Args)); 888 } 889 890 void JSONNodeDumper::visitParamCommandComment( 891 const comments::ParamCommandComment *C, const comments::FullComment *FC) { 892 switch (C->getDirection()) { 893 case comments::ParamCommandComment::In: 894 JOS.attribute("direction", "in"); 895 break; 896 case comments::ParamCommandComment::Out: 897 JOS.attribute("direction", "out"); 898 break; 899 case comments::ParamCommandComment::InOut: 900 JOS.attribute("direction", "in,out"); 901 break; 902 } 903 attributeOnlyIfTrue("explicit", C->isDirectionExplicit()); 904 905 if (C->hasParamName()) 906 JOS.attribute("param", C->isParamIndexValid() ? C->getParamName(FC) 907 : C->getParamNameAsWritten()); 908 909 if (C->isParamIndexValid() && !C->isVarArgParam()) 910 JOS.attribute("paramIdx", C->getParamIndex()); 911 } 912 913 void JSONNodeDumper::visitTParamCommandComment( 914 const comments::TParamCommandComment *C, const comments::FullComment *FC) { 915 if (C->hasParamName()) 916 JOS.attribute("param", C->isPositionValid() ? C->getParamName(FC) 917 : C->getParamNameAsWritten()); 918 if (C->isPositionValid()) { 919 llvm::json::Array Positions; 920 for (unsigned I = 0, E = C->getDepth(); I < E; ++I) 921 Positions.push_back(C->getIndex(I)); 922 923 if (!Positions.empty()) 924 JOS.attribute("positions", std::move(Positions)); 925 } 926 } 927 928 void JSONNodeDumper::visitVerbatimBlockComment( 929 const comments::VerbatimBlockComment *C, const comments::FullComment *) { 930 JOS.attribute("name", getCommentCommandName(C->getCommandID())); 931 JOS.attribute("closeName", C->getCloseName()); 932 } 933 934 void JSONNodeDumper::visitVerbatimBlockLineComment( 935 const comments::VerbatimBlockLineComment *C, 936 const comments::FullComment *) { 937 JOS.attribute("text", C->getText()); 938 } 939 940 void JSONNodeDumper::visitVerbatimLineComment( 941 const comments::VerbatimLineComment *C, const comments::FullComment *) { 942 JOS.attribute("text", C->getText()); 943 } 944