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 attributeOnlyIfTrue("isParameterPack", VD->isParameterPack()); 543 } 544 545 void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) { 546 VisitNamedDecl(FD); 547 JOS.attribute("type", createQualType(FD->getType())); 548 attributeOnlyIfTrue("mutable", FD->isMutable()); 549 attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate()); 550 attributeOnlyIfTrue("isBitfield", FD->isBitField()); 551 attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer()); 552 } 553 554 void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) { 555 VisitNamedDecl(FD); 556 JOS.attribute("type", createQualType(FD->getType())); 557 StorageClass SC = FD->getStorageClass(); 558 if (SC != SC_None) 559 JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); 560 attributeOnlyIfTrue("inline", FD->isInlineSpecified()); 561 attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten()); 562 attributeOnlyIfTrue("pure", FD->isPure()); 563 attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten()); 564 attributeOnlyIfTrue("constexpr", FD->isConstexpr()); 565 if (FD->isDefaulted()) 566 JOS.attribute("explicitlyDefaulted", 567 FD->isDeleted() ? "deleted" : "default"); 568 } 569 570 void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) { 571 VisitNamedDecl(ED); 572 if (ED->isFixed()) 573 JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType())); 574 if (ED->isScoped()) 575 JOS.attribute("scopedEnumTag", 576 ED->isScopedUsingClassTag() ? "class" : "struct"); 577 } 578 void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) { 579 VisitNamedDecl(ECD); 580 JOS.attribute("type", createQualType(ECD->getType())); 581 } 582 583 void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) { 584 VisitNamedDecl(RD); 585 JOS.attribute("tagUsed", RD->getKindName()); 586 attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition()); 587 } 588 void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) { 589 VisitRecordDecl(RD); 590 591 // All other information requires a complete definition. 592 if (!RD->isCompleteDefinition()) 593 return; 594 595 JOS.attribute("definitionData", createCXXRecordDefinitionData(RD)); 596 if (RD->getNumBases()) { 597 JOS.attributeArray("bases", [this, RD] { 598 for (const auto &Spec : RD->bases()) 599 JOS.value(createCXXBaseSpecifier(Spec)); 600 }); 601 } 602 } 603 604 void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 605 VisitNamedDecl(D); 606 JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class"); 607 JOS.attribute("depth", D->getDepth()); 608 JOS.attribute("index", D->getIndex()); 609 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 610 } 611 612 void JSONNodeDumper::VisitNonTypeTemplateParmDecl( 613 const NonTypeTemplateParmDecl *D) { 614 VisitNamedDecl(D); 615 JOS.attribute("type", createQualType(D->getType())); 616 JOS.attribute("depth", D->getDepth()); 617 JOS.attribute("index", D->getIndex()); 618 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 619 } 620 621 void JSONNodeDumper::VisitTemplateTemplateParmDecl( 622 const TemplateTemplateParmDecl *D) { 623 VisitNamedDecl(D); 624 JOS.attribute("depth", D->getDepth()); 625 JOS.attribute("index", D->getIndex()); 626 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 627 } 628 629 void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) { 630 StringRef Lang; 631 switch (LSD->getLanguage()) { 632 case LinkageSpecDecl::lang_c: Lang = "C"; break; 633 case LinkageSpecDecl::lang_cxx: Lang = "C++"; break; 634 } 635 JOS.attribute("language", Lang); 636 attributeOnlyIfTrue("hasBraces", LSD->hasBraces()); 637 } 638 639 void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) { 640 JOS.attribute("access", createAccessSpecifier(ASD->getAccess())); 641 } 642 643 void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) { 644 if (const TypeSourceInfo *T = FD->getFriendType()) 645 JOS.attribute("type", createQualType(T->getType())); 646 } 647 648 void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) { 649 JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl())); 650 if (DRE->getDecl() != DRE->getFoundDecl()) 651 JOS.attribute("foundReferencedDecl", 652 createBareDeclRef(DRE->getFoundDecl())); 653 } 654 655 void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) { 656 JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind())); 657 } 658 659 void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) { 660 JOS.attribute("isPostfix", UO->isPostfix()); 661 JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode())); 662 if (!UO->canOverflow()) 663 JOS.attribute("canOverflow", false); 664 } 665 666 void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) { 667 JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode())); 668 } 669 670 void JSONNodeDumper::VisitCompoundAssignOperator( 671 const CompoundAssignOperator *CAO) { 672 VisitBinaryOperator(CAO); 673 JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType())); 674 JOS.attribute("computeResultType", 675 createQualType(CAO->getComputationResultType())); 676 } 677 678 void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) { 679 // Note, we always write this Boolean field because the information it conveys 680 // is critical to understanding the AST node. 681 JOS.attribute("isArrow", ME->isArrow()); 682 JOS.attribute("referencedMemberDecl", 683 createPointerRepresentation(ME->getMemberDecl())); 684 } 685 686 void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { 687 attributeOnlyIfTrue("isGlobal", NE->isGlobalNew()); 688 attributeOnlyIfTrue("isArray", NE->isArray()); 689 attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0); 690 switch (NE->getInitializationStyle()) { 691 case CXXNewExpr::NoInit: break; 692 case CXXNewExpr::CallInit: JOS.attribute("initStyle", "call"); break; 693 case CXXNewExpr::ListInit: JOS.attribute("initStyle", "list"); break; 694 } 695 if (const FunctionDecl *FD = NE->getOperatorNew()) 696 JOS.attribute("operatorNewDecl", createBareDeclRef(FD)); 697 if (const FunctionDecl *FD = NE->getOperatorDelete()) 698 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); 699 } 700 void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) { 701 attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete()); 702 attributeOnlyIfTrue("isArray", DE->isArrayForm()); 703 attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten()); 704 if (const FunctionDecl *FD = DE->getOperatorDelete()) 705 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); 706 } 707 708 void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) { 709 attributeOnlyIfTrue("implicit", TE->isImplicit()); 710 } 711 712 void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) { 713 JOS.attribute("castKind", CE->getCastKindName()); 714 llvm::json::Array Path = createCastPath(CE); 715 if (!Path.empty()) 716 JOS.attribute("path", std::move(Path)); 717 // FIXME: This may not be useful information as it can be obtusely gleaned 718 // from the inner[] array. 719 if (const NamedDecl *ND = CE->getConversionFunction()) 720 JOS.attribute("conversionFunc", createBareDeclRef(ND)); 721 } 722 723 void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) { 724 VisitCastExpr(ICE); 725 attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast()); 726 } 727 728 void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) { 729 attributeOnlyIfTrue("adl", CE->usesADL()); 730 } 731 732 void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr( 733 const UnaryExprOrTypeTraitExpr *TTE) { 734 switch (TTE->getKind()) { 735 case UETT_SizeOf: JOS.attribute("name", "sizeof"); break; 736 case UETT_AlignOf: JOS.attribute("name", "alignof"); break; 737 case UETT_VecStep: JOS.attribute("name", "vec_step"); break; 738 case UETT_PreferredAlignOf: JOS.attribute("name", "__alignof"); break; 739 case UETT_OpenMPRequiredSimdAlign: 740 JOS.attribute("name", "__builtin_omp_required_simd_align"); break; 741 } 742 if (TTE->isArgumentType()) 743 JOS.attribute("argType", createQualType(TTE->getArgumentType())); 744 } 745 746 void JSONNodeDumper::VisitUnresolvedLookupExpr( 747 const UnresolvedLookupExpr *ULE) { 748 JOS.attribute("usesADL", ULE->requiresADL()); 749 JOS.attribute("name", ULE->getName().getAsString()); 750 751 JOS.attributeArray("lookups", [this, ULE] { 752 for (const NamedDecl *D : ULE->decls()) 753 JOS.value(createBareDeclRef(D)); 754 }); 755 } 756 757 void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) { 758 JOS.attribute("name", ALE->getLabel()->getName()); 759 JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel())); 760 } 761 762 void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) { 763 JOS.attribute("value", 764 IL->getValue().toString( 765 /*Radix=*/10, IL->getType()->isSignedIntegerType())); 766 } 767 void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) { 768 // FIXME: This should probably print the character literal as a string, 769 // rather than as a numerical value. It would be nice if the behavior matched 770 // what we do to print a string literal; right now, it is impossible to tell 771 // the difference between 'a' and L'a' in C from the JSON output. 772 JOS.attribute("value", CL->getValue()); 773 } 774 void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) { 775 JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10)); 776 } 777 void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) { 778 JOS.attribute("value", FL->getValueAsApproximateDouble()); 779 } 780 void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) { 781 std::string Buffer; 782 llvm::raw_string_ostream SS(Buffer); 783 SL->outputString(SS); 784 JOS.attribute("value", SS.str()); 785 } 786 void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) { 787 JOS.attribute("value", BLE->getValue()); 788 } 789 790 void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) { 791 attributeOnlyIfTrue("hasInit", IS->hasInitStorage()); 792 attributeOnlyIfTrue("hasVar", IS->hasVarStorage()); 793 attributeOnlyIfTrue("hasElse", IS->hasElseStorage()); 794 attributeOnlyIfTrue("isConstexpr", IS->isConstexpr()); 795 } 796 797 void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) { 798 attributeOnlyIfTrue("hasInit", SS->hasInitStorage()); 799 attributeOnlyIfTrue("hasVar", SS->hasVarStorage()); 800 } 801 void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) { 802 attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange()); 803 } 804 805 void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) { 806 JOS.attribute("name", LS->getName()); 807 JOS.attribute("declId", createPointerRepresentation(LS->getDecl())); 808 } 809 void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) { 810 JOS.attribute("targetLabelDeclId", 811 createPointerRepresentation(GS->getLabel())); 812 } 813 814 void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) { 815 attributeOnlyIfTrue("hasVar", WS->hasVarStorage()); 816 } 817 818 StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const { 819 if (Traits) 820 return Traits->getCommandInfo(CommandID)->Name; 821 if (const comments::CommandInfo *Info = 822 comments::CommandTraits::getBuiltinCommandInfo(CommandID)) 823 return Info->Name; 824 return "<invalid>"; 825 } 826 827 void JSONNodeDumper::visitTextComment(const comments::TextComment *C, 828 const comments::FullComment *) { 829 JOS.attribute("text", C->getText()); 830 } 831 832 void JSONNodeDumper::visitInlineCommandComment( 833 const comments::InlineCommandComment *C, const comments::FullComment *) { 834 JOS.attribute("name", getCommentCommandName(C->getCommandID())); 835 836 switch (C->getRenderKind()) { 837 case comments::InlineCommandComment::RenderNormal: 838 JOS.attribute("renderKind", "normal"); 839 break; 840 case comments::InlineCommandComment::RenderBold: 841 JOS.attribute("renderKind", "bold"); 842 break; 843 case comments::InlineCommandComment::RenderEmphasized: 844 JOS.attribute("renderKind", "emphasized"); 845 break; 846 case comments::InlineCommandComment::RenderMonospaced: 847 JOS.attribute("renderKind", "monospaced"); 848 break; 849 } 850 851 llvm::json::Array Args; 852 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) 853 Args.push_back(C->getArgText(I)); 854 855 if (!Args.empty()) 856 JOS.attribute("args", std::move(Args)); 857 } 858 859 void JSONNodeDumper::visitHTMLStartTagComment( 860 const comments::HTMLStartTagComment *C, const comments::FullComment *) { 861 JOS.attribute("name", C->getTagName()); 862 attributeOnlyIfTrue("selfClosing", C->isSelfClosing()); 863 attributeOnlyIfTrue("malformed", C->isMalformed()); 864 865 llvm::json::Array Attrs; 866 for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) 867 Attrs.push_back( 868 {{"name", C->getAttr(I).Name}, {"value", C->getAttr(I).Value}}); 869 870 if (!Attrs.empty()) 871 JOS.attribute("attrs", std::move(Attrs)); 872 } 873 874 void JSONNodeDumper::visitHTMLEndTagComment( 875 const comments::HTMLEndTagComment *C, const comments::FullComment *) { 876 JOS.attribute("name", C->getTagName()); 877 } 878 879 void JSONNodeDumper::visitBlockCommandComment( 880 const comments::BlockCommandComment *C, const comments::FullComment *) { 881 JOS.attribute("name", getCommentCommandName(C->getCommandID())); 882 883 llvm::json::Array Args; 884 for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) 885 Args.push_back(C->getArgText(I)); 886 887 if (!Args.empty()) 888 JOS.attribute("args", std::move(Args)); 889 } 890 891 void JSONNodeDumper::visitParamCommandComment( 892 const comments::ParamCommandComment *C, const comments::FullComment *FC) { 893 switch (C->getDirection()) { 894 case comments::ParamCommandComment::In: 895 JOS.attribute("direction", "in"); 896 break; 897 case comments::ParamCommandComment::Out: 898 JOS.attribute("direction", "out"); 899 break; 900 case comments::ParamCommandComment::InOut: 901 JOS.attribute("direction", "in,out"); 902 break; 903 } 904 attributeOnlyIfTrue("explicit", C->isDirectionExplicit()); 905 906 if (C->hasParamName()) 907 JOS.attribute("param", C->isParamIndexValid() ? C->getParamName(FC) 908 : C->getParamNameAsWritten()); 909 910 if (C->isParamIndexValid() && !C->isVarArgParam()) 911 JOS.attribute("paramIdx", C->getParamIndex()); 912 } 913 914 void JSONNodeDumper::visitTParamCommandComment( 915 const comments::TParamCommandComment *C, const comments::FullComment *FC) { 916 if (C->hasParamName()) 917 JOS.attribute("param", C->isPositionValid() ? C->getParamName(FC) 918 : C->getParamNameAsWritten()); 919 if (C->isPositionValid()) { 920 llvm::json::Array Positions; 921 for (unsigned I = 0, E = C->getDepth(); I < E; ++I) 922 Positions.push_back(C->getIndex(I)); 923 924 if (!Positions.empty()) 925 JOS.attribute("positions", std::move(Positions)); 926 } 927 } 928 929 void JSONNodeDumper::visitVerbatimBlockComment( 930 const comments::VerbatimBlockComment *C, const comments::FullComment *) { 931 JOS.attribute("name", getCommentCommandName(C->getCommandID())); 932 JOS.attribute("closeName", C->getCloseName()); 933 } 934 935 void JSONNodeDumper::visitVerbatimBlockLineComment( 936 const comments::VerbatimBlockLineComment *C, 937 const comments::FullComment *) { 938 JOS.attribute("text", C->getText()); 939 } 940 941 void JSONNodeDumper::visitVerbatimLineComment( 942 const comments::VerbatimLineComment *C, const comments::FullComment *) { 943 JOS.attribute("text", C->getText()); 944 } 945