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 116 void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R, 117 const Decl *From, StringRef Label) { 118 JOS.attribute("kind", "TemplateArgument"); 119 if (R.isValid()) 120 JOS.attribute("range", createSourceRange(R)); 121 122 if (From) 123 JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From)); 124 125 InnerTemplateArgVisitor::Visit(TA); 126 } 127 128 void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) { 129 JOS.attribute("kind", "CXXCtorInitializer"); 130 if (Init->isAnyMemberInitializer()) 131 JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember())); 132 else if (Init->isBaseInitializer()) 133 JOS.attribute("baseInit", 134 createQualType(QualType(Init->getBaseClass(), 0))); 135 else if (Init->isDelegatingInitializer()) 136 JOS.attribute("delegatingInit", 137 createQualType(Init->getTypeSourceInfo()->getType())); 138 else 139 llvm_unreachable("Unknown initializer type"); 140 } 141 142 void JSONNodeDumper::Visit(const OMPClause *C) {} 143 void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {} 144 void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) { 145 JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default"); 146 attributeOnlyIfTrue("selected", A.isSelected()); 147 } 148 149 llvm::json::Object JSONNodeDumper::createSourceLocation(SourceLocation Loc) { 150 SourceLocation Spelling = SM.getSpellingLoc(Loc); 151 PresumedLoc Presumed = SM.getPresumedLoc(Spelling); 152 153 if (Presumed.isInvalid()) 154 return llvm::json::Object{}; 155 156 return llvm::json::Object{{"file", Presumed.getFilename()}, 157 {"line", Presumed.getLine()}, 158 {"col", Presumed.getColumn()}}; 159 } 160 161 llvm::json::Object JSONNodeDumper::createSourceRange(SourceRange R) { 162 return llvm::json::Object{{"begin", createSourceLocation(R.getBegin())}, 163 {"end", createSourceLocation(R.getEnd())}}; 164 } 165 166 std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) { 167 // Because JSON stores integer values as signed 64-bit integers, trying to 168 // represent them as such makes for very ugly pointer values in the resulting 169 // output. Instead, we convert the value to hex and treat it as a string. 170 return "0x" + llvm::utohexstr(reinterpret_cast<uint64_t>(Ptr), true); 171 } 172 173 llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) { 174 SplitQualType SQT = QT.split(); 175 llvm::json::Object Ret{{"qualType", QualType::getAsString(SQT, PrintPolicy)}}; 176 177 if (Desugar && !QT.isNull()) { 178 SplitQualType DSQT = QT.getSplitDesugaredType(); 179 if (DSQT != SQT) 180 Ret["desugaredQualType"] = QualType::getAsString(DSQT, PrintPolicy); 181 } 182 return Ret; 183 } 184 185 llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) { 186 llvm::json::Object Ret{ 187 {"id", createPointerRepresentation(D)}, 188 {"kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str()}}; 189 if (const auto *ND = dyn_cast<NamedDecl>(D)) 190 Ret["name"] = ND->getDeclName().getAsString(); 191 if (const auto *VD = dyn_cast<ValueDecl>(D)) 192 Ret["type"] = createQualType(VD->getType()); 193 return Ret; 194 } 195 196 llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) { 197 llvm::json::Array Ret; 198 if (C->path_empty()) 199 return Ret; 200 201 for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) { 202 const CXXBaseSpecifier *Base = *I; 203 const auto *RD = 204 cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 205 206 llvm::json::Object Val{{"name", RD->getName()}}; 207 if (Base->isVirtual()) 208 Val["isVirtual"] = true; 209 Ret.push_back(std::move(Val)); 210 } 211 return Ret; 212 } 213 214 #define FIELD2(Name, Flag) if (RD->Flag()) Ret[Name] = true 215 #define FIELD1(Flag) FIELD2(#Flag, Flag) 216 217 static llvm::json::Object 218 createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) { 219 llvm::json::Object Ret; 220 221 FIELD2("exists", hasDefaultConstructor); 222 FIELD2("trivial", hasTrivialDefaultConstructor); 223 FIELD2("nonTrivial", hasNonTrivialDefaultConstructor); 224 FIELD2("userProvided", hasUserProvidedDefaultConstructor); 225 FIELD2("isConstexpr", hasConstexprDefaultConstructor); 226 FIELD2("needsImplicit", needsImplicitDefaultConstructor); 227 FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr); 228 229 return Ret; 230 } 231 232 static llvm::json::Object 233 createCopyConstructorDefinitionData(const CXXRecordDecl *RD) { 234 llvm::json::Object Ret; 235 236 FIELD2("simple", hasSimpleCopyConstructor); 237 FIELD2("trivial", hasTrivialCopyConstructor); 238 FIELD2("nonTrivial", hasNonTrivialCopyConstructor); 239 FIELD2("userDeclared", hasUserDeclaredCopyConstructor); 240 FIELD2("hasConstParam", hasCopyConstructorWithConstParam); 241 FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam); 242 FIELD2("needsImplicit", needsImplicitCopyConstructor); 243 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor); 244 if (!RD->needsOverloadResolutionForCopyConstructor()) 245 FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted); 246 247 return Ret; 248 } 249 250 static llvm::json::Object 251 createMoveConstructorDefinitionData(const CXXRecordDecl *RD) { 252 llvm::json::Object Ret; 253 254 FIELD2("exists", hasMoveConstructor); 255 FIELD2("simple", hasSimpleMoveConstructor); 256 FIELD2("trivial", hasTrivialMoveConstructor); 257 FIELD2("nonTrivial", hasNonTrivialMoveConstructor); 258 FIELD2("userDeclared", hasUserDeclaredMoveConstructor); 259 FIELD2("needsImplicit", needsImplicitMoveConstructor); 260 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor); 261 if (!RD->needsOverloadResolutionForMoveConstructor()) 262 FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted); 263 264 return Ret; 265 } 266 267 static llvm::json::Object 268 createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) { 269 llvm::json::Object Ret; 270 271 FIELD2("trivial", hasTrivialCopyAssignment); 272 FIELD2("nonTrivial", hasNonTrivialCopyAssignment); 273 FIELD2("hasConstParam", hasCopyAssignmentWithConstParam); 274 FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam); 275 FIELD2("userDeclared", hasUserDeclaredCopyAssignment); 276 FIELD2("needsImplicit", needsImplicitCopyAssignment); 277 FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment); 278 279 return Ret; 280 } 281 282 static llvm::json::Object 283 createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) { 284 llvm::json::Object Ret; 285 286 FIELD2("exists", hasMoveAssignment); 287 FIELD2("simple", hasSimpleMoveAssignment); 288 FIELD2("trivial", hasTrivialMoveAssignment); 289 FIELD2("nonTrivial", hasNonTrivialMoveAssignment); 290 FIELD2("userDeclared", hasUserDeclaredMoveAssignment); 291 FIELD2("needsImplicit", needsImplicitMoveAssignment); 292 FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment); 293 294 return Ret; 295 } 296 297 static llvm::json::Object 298 createDestructorDefinitionData(const CXXRecordDecl *RD) { 299 llvm::json::Object Ret; 300 301 FIELD2("simple", hasSimpleDestructor); 302 FIELD2("irrelevant", hasIrrelevantDestructor); 303 FIELD2("trivial", hasTrivialDestructor); 304 FIELD2("nonTrivial", hasNonTrivialDestructor); 305 FIELD2("userDeclared", hasUserDeclaredDestructor); 306 FIELD2("needsImplicit", needsImplicitDestructor); 307 FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor); 308 if (!RD->needsOverloadResolutionForDestructor()) 309 FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted); 310 311 return Ret; 312 } 313 314 llvm::json::Object 315 JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) { 316 llvm::json::Object Ret; 317 318 // This data is common to all C++ classes. 319 FIELD1(isGenericLambda); 320 FIELD1(isLambda); 321 FIELD1(isEmpty); 322 FIELD1(isAggregate); 323 FIELD1(isStandardLayout); 324 FIELD1(isTriviallyCopyable); 325 FIELD1(isPOD); 326 FIELD1(isTrivial); 327 FIELD1(isPolymorphic); 328 FIELD1(isAbstract); 329 FIELD1(isLiteral); 330 FIELD1(canPassInRegisters); 331 FIELD1(hasUserDeclaredConstructor); 332 FIELD1(hasConstexprNonCopyMoveConstructor); 333 FIELD1(hasMutableFields); 334 FIELD1(hasVariantMembers); 335 FIELD2("canConstDefaultInit", allowConstDefaultInit); 336 337 Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD); 338 Ret["copyCtor"] = createCopyConstructorDefinitionData(RD); 339 Ret["moveCtor"] = createMoveConstructorDefinitionData(RD); 340 Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD); 341 Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD); 342 Ret["dtor"] = createDestructorDefinitionData(RD); 343 344 return Ret; 345 } 346 347 #undef FIELD1 348 #undef FIELD2 349 350 std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) { 351 switch (AS) { 352 case AS_none: return "none"; 353 case AS_private: return "private"; 354 case AS_protected: return "protected"; 355 case AS_public: return "public"; 356 } 357 llvm_unreachable("Unknown access specifier"); 358 } 359 360 llvm::json::Object 361 JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) { 362 llvm::json::Object Ret; 363 364 Ret["type"] = createQualType(BS.getType()); 365 Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier()); 366 Ret["writtenAccess"] = 367 createAccessSpecifier(BS.getAccessSpecifierAsWritten()); 368 if (BS.isVirtual()) 369 Ret["isVirtual"] = true; 370 if (BS.isPackExpansion()) 371 Ret["isPackExpansion"] = true; 372 373 return Ret; 374 } 375 376 void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) { 377 JOS.attribute("decl", createBareDeclRef(TT->getDecl())); 378 } 379 380 void JSONNodeDumper::VisitFunctionType(const FunctionType *T) { 381 FunctionType::ExtInfo E = T->getExtInfo(); 382 attributeOnlyIfTrue("noreturn", E.getNoReturn()); 383 attributeOnlyIfTrue("producesResult", E.getProducesResult()); 384 if (E.getHasRegParm()) 385 JOS.attribute("regParm", E.getRegParm()); 386 JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC())); 387 } 388 389 void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) { 390 FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo(); 391 attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn); 392 attributeOnlyIfTrue("const", T->isConst()); 393 attributeOnlyIfTrue("volatile", T->isVolatile()); 394 attributeOnlyIfTrue("restrict", T->isRestrict()); 395 attributeOnlyIfTrue("variadic", E.Variadic); 396 switch (E.RefQualifier) { 397 case RQ_LValue: JOS.attribute("refQualifier", "&"); break; 398 case RQ_RValue: JOS.attribute("refQualifier", "&&"); break; 399 case RQ_None: break; 400 } 401 switch (E.ExceptionSpec.Type) { 402 case EST_DynamicNone: 403 case EST_Dynamic: { 404 JOS.attribute("exceptionSpec", "throw"); 405 llvm::json::Array Types; 406 for (QualType QT : E.ExceptionSpec.Exceptions) 407 Types.push_back(createQualType(QT)); 408 JOS.attribute("exceptionTypes", std::move(Types)); 409 } break; 410 case EST_MSAny: 411 JOS.attribute("exceptionSpec", "throw"); 412 JOS.attribute("throwsAny", true); 413 break; 414 case EST_BasicNoexcept: 415 JOS.attribute("exceptionSpec", "noexcept"); 416 break; 417 case EST_NoexceptTrue: 418 case EST_NoexceptFalse: 419 JOS.attribute("exceptionSpec", "noexcept"); 420 JOS.attribute("conditionEvaluatesTo", 421 E.ExceptionSpec.Type == EST_NoexceptTrue); 422 //JOS.attributeWithCall("exceptionSpecExpr", 423 // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); }); 424 break; 425 426 // FIXME: I cannot find a way to trigger these cases while dumping the AST. I 427 // suspect you can only run into them when executing an AST dump from within 428 // the debugger, which is not a use case we worry about for the JSON dumping 429 // feature. 430 case EST_DependentNoexcept: 431 case EST_Unevaluated: 432 case EST_Uninstantiated: 433 case EST_Unparsed: 434 case EST_None: break; 435 } 436 VisitFunctionType(T); 437 } 438 439 void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) { 440 if (ND && ND->getDeclName()) 441 JOS.attribute("name", ND->getNameAsString()); 442 } 443 444 void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) { 445 VisitNamedDecl(TD); 446 JOS.attribute("type", createQualType(TD->getUnderlyingType())); 447 } 448 449 void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) { 450 VisitNamedDecl(TAD); 451 JOS.attribute("type", createQualType(TAD->getUnderlyingType())); 452 } 453 454 void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) { 455 VisitNamedDecl(ND); 456 attributeOnlyIfTrue("isInline", ND->isInline()); 457 if (!ND->isOriginalNamespace()) 458 JOS.attribute("originalNamespace", 459 createBareDeclRef(ND->getOriginalNamespace())); 460 } 461 462 void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) { 463 JOS.attribute("nominatedNamespace", 464 createBareDeclRef(UDD->getNominatedNamespace())); 465 } 466 467 void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) { 468 VisitNamedDecl(NAD); 469 JOS.attribute("aliasedNamespace", 470 createBareDeclRef(NAD->getAliasedNamespace())); 471 } 472 473 void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) { 474 std::string Name; 475 if (const NestedNameSpecifier *NNS = UD->getQualifier()) { 476 llvm::raw_string_ostream SOS(Name); 477 NNS->print(SOS, UD->getASTContext().getPrintingPolicy()); 478 } 479 Name += UD->getNameAsString(); 480 JOS.attribute("name", Name); 481 } 482 483 void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) { 484 JOS.attribute("target", createBareDeclRef(USD->getTargetDecl())); 485 } 486 487 void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) { 488 VisitNamedDecl(VD); 489 JOS.attribute("type", createQualType(VD->getType())); 490 491 StorageClass SC = VD->getStorageClass(); 492 if (SC != SC_None) 493 JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); 494 switch (VD->getTLSKind()) { 495 case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break; 496 case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break; 497 case VarDecl::TLS_None: break; 498 } 499 attributeOnlyIfTrue("nrvo", VD->isNRVOVariable()); 500 attributeOnlyIfTrue("inline", VD->isInline()); 501 attributeOnlyIfTrue("constexpr", VD->isConstexpr()); 502 attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate()); 503 if (VD->hasInit()) { 504 switch (VD->getInitStyle()) { 505 case VarDecl::CInit: JOS.attribute("init", "c"); break; 506 case VarDecl::CallInit: JOS.attribute("init", "call"); break; 507 case VarDecl::ListInit: JOS.attribute("init", "list"); break; 508 } 509 } 510 } 511 512 void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) { 513 VisitNamedDecl(FD); 514 JOS.attribute("type", createQualType(FD->getType())); 515 attributeOnlyIfTrue("mutable", FD->isMutable()); 516 attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate()); 517 attributeOnlyIfTrue("isBitfield", FD->isBitField()); 518 attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer()); 519 } 520 521 void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) { 522 VisitNamedDecl(FD); 523 JOS.attribute("type", createQualType(FD->getType())); 524 StorageClass SC = FD->getStorageClass(); 525 if (SC != SC_None) 526 JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); 527 attributeOnlyIfTrue("inline", FD->isInlineSpecified()); 528 attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten()); 529 attributeOnlyIfTrue("pure", FD->isPure()); 530 attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten()); 531 attributeOnlyIfTrue("constexpr", FD->isConstexpr()); 532 if (FD->isDefaulted()) 533 JOS.attribute("explicitlyDefaulted", 534 FD->isDeleted() ? "deleted" : "default"); 535 } 536 537 void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) { 538 VisitNamedDecl(ED); 539 if (ED->isFixed()) 540 JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType())); 541 if (ED->isScoped()) 542 JOS.attribute("scopedEnumTag", 543 ED->isScopedUsingClassTag() ? "class" : "struct"); 544 } 545 void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) { 546 VisitNamedDecl(ECD); 547 JOS.attribute("type", createQualType(ECD->getType())); 548 } 549 550 void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) { 551 VisitNamedDecl(RD); 552 JOS.attribute("tagUsed", RD->getKindName()); 553 attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition()); 554 } 555 void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) { 556 VisitRecordDecl(RD); 557 558 // All other information requires a complete definition. 559 if (!RD->isCompleteDefinition()) 560 return; 561 562 JOS.attribute("definitionData", createCXXRecordDefinitionData(RD)); 563 if (RD->getNumBases()) { 564 JOS.attributeArray("bases", [this, RD] { 565 for (const auto &Spec : RD->bases()) 566 JOS.value(createCXXBaseSpecifier(Spec)); 567 }); 568 } 569 } 570 571 void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 572 VisitNamedDecl(D); 573 JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class"); 574 JOS.attribute("depth", D->getDepth()); 575 JOS.attribute("index", D->getIndex()); 576 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 577 } 578 579 void JSONNodeDumper::VisitNonTypeTemplateParmDecl( 580 const NonTypeTemplateParmDecl *D) { 581 VisitNamedDecl(D); 582 JOS.attribute("type", createQualType(D->getType())); 583 JOS.attribute("depth", D->getDepth()); 584 JOS.attribute("index", D->getIndex()); 585 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 586 } 587 588 void JSONNodeDumper::VisitTemplateTemplateParmDecl( 589 const TemplateTemplateParmDecl *D) { 590 VisitNamedDecl(D); 591 JOS.attribute("depth", D->getDepth()); 592 JOS.attribute("index", D->getIndex()); 593 attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); 594 } 595 596 void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) { 597 StringRef Lang; 598 switch (LSD->getLanguage()) { 599 case LinkageSpecDecl::lang_c: Lang = "C"; break; 600 case LinkageSpecDecl::lang_cxx: Lang = "C++"; break; 601 } 602 JOS.attribute("language", Lang); 603 attributeOnlyIfTrue("hasBraces", LSD->hasBraces()); 604 } 605 606 void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) { 607 JOS.attribute("access", createAccessSpecifier(ASD->getAccess())); 608 } 609 610 void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) { 611 if (const TypeSourceInfo *T = FD->getFriendType()) 612 JOS.attribute("type", createQualType(T->getType())); 613 } 614 615 void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) { 616 JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl())); 617 if (DRE->getDecl() != DRE->getFoundDecl()) 618 JOS.attribute("foundReferencedDecl", 619 createBareDeclRef(DRE->getFoundDecl())); 620 } 621 622 void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) { 623 JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind())); 624 } 625 626 void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) { 627 JOS.attribute("isPostfix", UO->isPostfix()); 628 JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode())); 629 if (!UO->canOverflow()) 630 JOS.attribute("canOverflow", false); 631 } 632 633 void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) { 634 JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode())); 635 } 636 637 void JSONNodeDumper::VisitCompoundAssignOperator( 638 const CompoundAssignOperator *CAO) { 639 VisitBinaryOperator(CAO); 640 JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType())); 641 JOS.attribute("computeResultType", 642 createQualType(CAO->getComputationResultType())); 643 } 644 645 void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) { 646 // Note, we always write this Boolean field because the information it conveys 647 // is critical to understanding the AST node. 648 JOS.attribute("isArrow", ME->isArrow()); 649 JOS.attribute("referencedMemberDecl", 650 createPointerRepresentation(ME->getMemberDecl())); 651 } 652 653 void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { 654 attributeOnlyIfTrue("isGlobal", NE->isGlobalNew()); 655 attributeOnlyIfTrue("isArray", NE->isArray()); 656 attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0); 657 switch (NE->getInitializationStyle()) { 658 case CXXNewExpr::NoInit: break; 659 case CXXNewExpr::CallInit: JOS.attribute("initStyle", "call"); break; 660 case CXXNewExpr::ListInit: JOS.attribute("initStyle", "list"); break; 661 } 662 if (const FunctionDecl *FD = NE->getOperatorNew()) 663 JOS.attribute("operatorNewDecl", createBareDeclRef(FD)); 664 if (const FunctionDecl *FD = NE->getOperatorDelete()) 665 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); 666 } 667 void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) { 668 attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete()); 669 attributeOnlyIfTrue("isArray", DE->isArrayForm()); 670 attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten()); 671 if (const FunctionDecl *FD = DE->getOperatorDelete()) 672 JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); 673 } 674 675 void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) { 676 attributeOnlyIfTrue("implicit", TE->isImplicit()); 677 } 678 679 void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) { 680 JOS.attribute("castKind", CE->getCastKindName()); 681 llvm::json::Array Path = createCastPath(CE); 682 if (!Path.empty()) 683 JOS.attribute("path", std::move(Path)); 684 // FIXME: This may not be useful information as it can be obtusely gleaned 685 // from the inner[] array. 686 if (const NamedDecl *ND = CE->getConversionFunction()) 687 JOS.attribute("conversionFunc", createBareDeclRef(ND)); 688 } 689 690 void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) { 691 VisitCastExpr(ICE); 692 attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast()); 693 } 694 695 void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) { 696 attributeOnlyIfTrue("adl", CE->usesADL()); 697 } 698 699 void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr( 700 const UnaryExprOrTypeTraitExpr *TTE) { 701 switch (TTE->getKind()) { 702 case UETT_SizeOf: JOS.attribute("name", "sizeof"); break; 703 case UETT_AlignOf: JOS.attribute("name", "alignof"); break; 704 case UETT_VecStep: JOS.attribute("name", "vec_step"); break; 705 case UETT_PreferredAlignOf: JOS.attribute("name", "__alignof"); break; 706 case UETT_OpenMPRequiredSimdAlign: 707 JOS.attribute("name", "__builtin_omp_required_simd_align"); break; 708 } 709 if (TTE->isArgumentType()) 710 JOS.attribute("argType", createQualType(TTE->getArgumentType())); 711 } 712 713 void JSONNodeDumper::VisitUnresolvedLookupExpr( 714 const UnresolvedLookupExpr *ULE) { 715 JOS.attribute("usesADL", ULE->requiresADL()); 716 JOS.attribute("name", ULE->getName().getAsString()); 717 718 JOS.attributeArray("lookups", [this, ULE] { 719 for (const NamedDecl *D : ULE->decls()) 720 JOS.value(createBareDeclRef(D)); 721 }); 722 } 723 724 void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) { 725 JOS.attribute("name", ALE->getLabel()->getName()); 726 JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel())); 727 } 728 729 void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) { 730 JOS.attribute("value", 731 IL->getValue().toString( 732 /*Radix=*/10, IL->getType()->isSignedIntegerType())); 733 } 734 void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) { 735 // FIXME: This should probably print the character literal as a string, 736 // rather than as a numerical value. 737 JOS.attribute("value", CL->getValue()); 738 } 739 void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) { 740 JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10)); 741 } 742 void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) { 743 JOS.attribute("value", FL->getValueAsApproximateDouble()); 744 } 745 void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) { 746 std::string Buffer; 747 llvm::raw_string_ostream SS(Buffer); 748 SL->outputString(SS); 749 JOS.attribute("value", SS.str()); 750 } 751 void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) { 752 JOS.attribute("value", BLE->getValue()); 753 } 754 755 void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) { 756 attributeOnlyIfTrue("hasInit", IS->hasInitStorage()); 757 attributeOnlyIfTrue("hasVar", IS->hasVarStorage()); 758 attributeOnlyIfTrue("hasElse", IS->hasElseStorage()); 759 attributeOnlyIfTrue("isConstexpr", IS->isConstexpr()); 760 } 761 762 void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) { 763 attributeOnlyIfTrue("hasInit", SS->hasInitStorage()); 764 attributeOnlyIfTrue("hasVar", SS->hasVarStorage()); 765 } 766 void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) { 767 attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange()); 768 } 769 770 void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) { 771 JOS.attribute("name", LS->getName()); 772 JOS.attribute("declId", createPointerRepresentation(LS->getDecl())); 773 } 774 void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) { 775 JOS.attribute("targetLabelDeclId", 776 createPointerRepresentation(GS->getLabel())); 777 } 778 779 void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) { 780 attributeOnlyIfTrue("hasVar", WS->hasVarStorage()); 781 } 782