Index: include/clang/AST/ASTDumperUtils.h =================================================================== --- include/clang/AST/ASTDumperUtils.h +++ include/clang/AST/ASTDumperUtils.h @@ -17,6 +17,12 @@ namespace clang { +/// Used to specify the format for printing AST dump information. +enum ASTDumpOutputFormat { + ADOF_Default, + ADOF_JSON +}; + // Colors used for various parts of the AST dump // Do not use bold yellow for any text. It is hard to read on white screens. Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_DECLBASE_H #define LLVM_CLANG_AST_DECLBASE_H +#include "clang/AST/ASTDumperUtils.h" #include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" #include "clang/Basic/IdentifierTable.h" @@ -1134,7 +1135,8 @@ // Same as dump(), but forces color printing. void dumpColor() const; - void dump(raw_ostream &Out, bool Deserialize = false) const; + void dump(raw_ostream &Out, bool Deserialize = false, + ASTDumpOutputFormat OutputFormat = ADOF_Default) const; /// \return Unique reproducible object identifier int64_t getID() const; Index: include/clang/AST/JSONNodeDumper.h =================================================================== --- include/clang/AST/JSONNodeDumper.h +++ include/clang/AST/JSONNodeDumper.h @@ -0,0 +1,327 @@ +//===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements AST dumping of components of individual AST nodes to +// a JSON. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H +#define LLVM_CLANG_AST_JSONNODEDUMPER_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTNodeTraverser.h" +#include "clang/AST/ASTDumperUtils.h" +#include "clang/AST/AttrVisitor.h" +#include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/CommentVisitor.h" +#include "clang/AST/ExprCXX.h" +#include "llvm/Support/JSON.h" + +namespace clang { + +class NodeStreamer { + bool FirstChild = true; + bool TopLevel = true; + llvm::SmallVector, 32> Pending; + +protected: + llvm::json::OStream JOS; + +public: + /// Add a child of the current node. Calls DoAddChild without arguments + template void AddChild(Fn DoAddChild) { + return AddChild("", DoAddChild); + } + + /// Add a child of the current node with an optional label. + /// Calls DoAddChild without arguments. + template void AddChild(StringRef Label, Fn DoAddChild) { + // If we're at the top level, there's nothing interesting to do; just + // run the dumper. + if (TopLevel) { + TopLevel = false; + JOS.objectBegin(); + + DoAddChild(); + + while (!Pending.empty()) { + Pending.back()(true); + Pending.pop_back(); + } + + JOS.objectEnd(); + TopLevel = true; + return; + } + + // We need to capture an owning-string in the lambda because the lambda + // is invoked in a deferred manner. + std::string LabelStr = !Label.empty() ? Label : "inner"; + bool WasFirstChild = FirstChild; + auto DumpWithIndent = [=](bool IsLastChild) { + if (WasFirstChild) { + JOS.attributeBegin(LabelStr); + JOS.arrayBegin(); + } + + FirstChild = true; + unsigned Depth = Pending.size(); + JOS.objectBegin(); + + DoAddChild(); + + // If any children are left, they're the last at their nesting level. + // Dump those ones out now. + while (Depth < Pending.size()) { + Pending.back()(true); + this->Pending.pop_back(); + } + + JOS.objectEnd(); + + if (IsLastChild) { + JOS.arrayEnd(); + JOS.attributeEnd(); + } + }; + + if (FirstChild) { + Pending.push_back(std::move(DumpWithIndent)); + } else { + Pending.back()(false); + Pending.back() = std::move(DumpWithIndent); + } + FirstChild = false; + } + + NodeStreamer(raw_ostream &OS) : JOS(OS, 2) {} +}; + +// Dumps AST nodes in JSON format. This streams some of the JSON information +// out on demand to ensure that the +class JSONNodeDumper + : public ConstAttrVisitor, + public ConstTemplateArgumentVisitor, + public ConstStmtVisitor, + public TypeVisitor, + public ConstDeclVisitor, + public NodeStreamer { + friend class JSONDumper; + + raw_ostream &OS; + const SourceManager &SM; + PrintingPolicy PrintPolicy; + + using InnerAttrVisitor = ConstAttrVisitor; + using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor; + using InnerStmtVisitor = ConstStmtVisitor; + using InnerTypeVisitor = TypeVisitor; + using InnerDeclVisitor = ConstDeclVisitor; + + void attributeOnlyIfTrue(StringRef Key, bool Value) { + if (Value) + JOS.attribute(Key, Value); + } + + llvm::json::Object createSourceLocation(SourceLocation Loc); + llvm::json::Object createSourceRange(SourceRange R); + std::string createPointerRepresentation(const void *Ptr); + llvm::json::Object createQualType(QualType QT, bool Desugar = true); + llvm::json::Object createBareDeclRef(const Decl *D); + llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD); + llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS); + std::string createAccessSpecifier(AccessSpecifier AS); + llvm::json::Array createCastPath(const CastExpr *C); + + void writePreviousDeclImpl(...) {} + + template void writePreviousDeclImpl(const Mergeable *D) { + const T *First = D->getFirstDecl(); + if (First != D) + JOS.attribute("firstRedecl", createPointerRepresentation(First)); + } + + template void writePreviousDeclImpl(const Redeclarable *D) { + const T *Prev = D->getPreviousDecl(); + if (Prev) + JOS.attribute("previousDecl", createPointerRepresentation(Prev)); + } + void addPreviousDeclaration(const Decl *D); + +public: + JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, + const PrintingPolicy &PrintPolicy) + : NodeStreamer(OS), OS(OS), SM(SrcMgr), PrintPolicy(PrintPolicy) {} + + void Visit(const Attr *A); + void Visit(const Stmt *Node); + void Visit(const Type *T); + void Visit(QualType T); + void Visit(const Decl *D); + + void Visit(const comments::Comment *C, const comments::FullComment *FC); + void Visit(const TemplateArgument &TA, SourceRange R = {}, + const Decl *From = nullptr, StringRef Label = {}); + void Visit(const CXXCtorInitializer *Init); + void Visit(const OMPClause *C); + void Visit(const BlockDecl::Capture &C); + void Visit(const GenericSelectionExpr::ConstAssociation &A); + + void VisitTypedefType(const TypedefType *TT); + void VisitFunctionType(const FunctionType *T); + void VisitFunctionProtoType(const FunctionProtoType *T); + + void VisitNamedDecl(const NamedDecl *ND); + void VisitTypedefDecl(const TypedefDecl *TD); + void VisitTypeAliasDecl(const TypeAliasDecl *TAD); + void VisitNamespaceDecl(const NamespaceDecl *ND); + void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD); + void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD); + void VisitUsingDecl(const UsingDecl *UD); + void VisitUsingShadowDecl(const UsingShadowDecl *USD); + void VisitVarDecl(const VarDecl *VD); + void VisitFieldDecl(const FieldDecl *FD); + void VisitFunctionDecl(const FunctionDecl *FD); + void VisitEnumDecl(const EnumDecl *ED); + void VisitEnumConstantDecl(const EnumConstantDecl *ECD); + void VisitRecordDecl(const RecordDecl *RD); + void VisitCXXRecordDecl(const CXXRecordDecl *RD); + void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); + void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); + void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); + void VisitLinkageSpecDecl(const LinkageSpecDecl *LSD); + void VisitAccessSpecDecl(const AccessSpecDecl *ASD); + void VisitFriendDecl(const FriendDecl *FD); + + void VisitDeclRefExpr(const DeclRefExpr *DRE); + void VisitPredefinedExpr(const PredefinedExpr *PE); + void VisitUnaryOperator(const UnaryOperator *UO); + void VisitBinaryOperator(const BinaryOperator *BO); + void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); + void VisitMemberExpr(const MemberExpr *ME); + void VisitCXXNewExpr(const CXXNewExpr *NE); + void VisitCXXDeleteExpr(const CXXDeleteExpr *DE); + void VisitCXXThisExpr(const CXXThisExpr *TE); + void VisitCastExpr(const CastExpr *CE); + void VisitImplicitCastExpr(const ImplicitCastExpr *ICE); + void VisitCallExpr(const CallExpr *CE); + void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *TTE); + void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE); + void VisitAddrLabelExpr(const AddrLabelExpr *ALE); + + void VisitIntegerLiteral(const IntegerLiteral *IL); + void VisitCharacterLiteral(const CharacterLiteral *CL); + void VisitFixedPointLiteral(const FixedPointLiteral *FPL); + void VisitFloatingLiteral(const FloatingLiteral *FL); + void VisitStringLiteral(const StringLiteral *SL); + void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE); + + void VisitIfStmt(const IfStmt *IS); + void VisitSwitchStmt(const SwitchStmt *SS); + void VisitCaseStmt(const CaseStmt *CS); + void VisitLabelStmt(const LabelStmt *LS); + void VisitGotoStmt(const GotoStmt *GS); + void VisitWhileStmt(const WhileStmt *WS); +}; + +class JSONDumper : public ASTNodeTraverser { + JSONNodeDumper NodeDumper; + + template + void writeTemplateDeclSpecialization(const SpecializationDecl *SD, + bool DumpExplicitInst, + bool DumpRefOnly) { + bool DumpedAny = false; + for (const auto *RedeclWithBadType : SD->redecls()) { + // FIXME: The redecls() range sometimes has elements of a less-specific + // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives + // us TagDecls, and should give CXXRecordDecls). + const auto *Redecl = dyn_cast(RedeclWithBadType); + if (!Redecl) { + // Found the injected-class-name for a class template. This will be + // dumped as part of its surrounding class so we don't need to dump it + // here. + assert(isa(RedeclWithBadType) && + "expected an injected-class-name"); + continue; + } + + switch (Redecl->getTemplateSpecializationKind()) { + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + if (!DumpExplicitInst) + break; + LLVM_FALLTHROUGH; + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + if (DumpRefOnly) + NodeDumper.JOS.value(NodeDumper.createBareDeclRef(Redecl)); + else + // FIXME: this isn't quite right -- we want to call Visit() rather + // than NodeDumper.Visit() but that causes issues because it attempts + // to create a new array of child objects due to calling AddChild(), + // which messes up the JSON creation. + NodeDumper.JOS.object([this, Redecl] { NodeDumper.Visit(Redecl); }); + DumpedAny = true; + break; + case TSK_ExplicitSpecialization: + break; + } + } + + // Ensure we dump at least one decl for each specialization. + if (!DumpedAny) + NodeDumper.JOS.value(NodeDumper.createBareDeclRef(SD)); + } + + template + void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) { + if (const TemplateParameterList *TPL = TD->getTemplateParameters()) { + NodeDumper.JOS.attributeArray("templateParams", [this, TPL] { + for (const auto &TP : *TPL) { + NodeDumper.JOS.object([this, TP] { NodeDumper.Visit(TP); }); + } + }); + } + + Visit(TD->getTemplatedDecl()); + + auto spec_range = TD->specializations(); + if (!llvm::empty(spec_range)) { + NodeDumper.JOS.attributeArray( + "specializations", [this, spec_range, TD, DumpExplicitInst] { + for (const auto *Child : spec_range) + writeTemplateDeclSpecialization(Child, DumpExplicitInst, + !TD->isCanonicalDecl()); + }); + } + } + +public: + JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, + const PrintingPolicy &PrintPolicy) + : NodeDumper(OS, SrcMgr, PrintPolicy) {} + + JSONNodeDumper &doGetNodeDelegate() { return NodeDumper; } + + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *FTD) { + writeTemplateDecl(FTD, true); + } + void VisitClassTemplateDecl(const ClassTemplateDecl *CTD) { + writeTemplateDecl(CTD, false); + } + void VisitVarTemplateDecl(const VarTemplateDecl *VTD) { + writeTemplateDecl(VTD, false); + } +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_JSONNODEDUMPER_H Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -557,8 +557,14 @@ HelpText<"Build ASTs and print the list of declaration node qualified names">; def ast_dump : Flag<["-"], "ast-dump">, HelpText<"Build ASTs and then debug dump them">; +def ast_dump_EQ : Joined<["-"], "ast-dump=">, + HelpText<"Build ASTs and then debug dump them in the specified format. " + "Supported formats include: default, json">; def ast_dump_all : Flag<["-"], "ast-dump-all">, HelpText<"Build ASTs and then debug dump them, forcing deserialization">; +def ast_dump_all_EQ : Joined<["-"], "ast-dump-all=">, + HelpText<"Build ASTs and then debug dump them in the specified format, " + "forcing deserialization. Supported formats include: default, json">; def templight_dump : Flag<["-"], "templight-dump">, HelpText<"Dump templight information to stdout">; def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">, Index: include/clang/Frontend/ASTConsumers.h =================================================================== --- include/clang/Frontend/ASTConsumers.h +++ include/clang/Frontend/ASTConsumers.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_FRONTEND_ASTCONSUMERS_H #define LLVM_CLANG_FRONTEND_ASTCONSUMERS_H +#include "clang/AST/ASTDumperUtils.h" #include "clang/Basic/LLVM.h" #include @@ -35,10 +36,10 @@ // AST dumper: dumps the raw AST in human-readable form to the given output // stream, or stdout if OS is nullptr. -std::unique_ptr CreateASTDumper(std::unique_ptr OS, - StringRef FilterString, - bool DumpDecls, bool Deserialize, - bool DumpLookups); +std::unique_ptr +CreateASTDumper(std::unique_ptr OS, StringRef FilterString, + bool DumpDecls, bool Deserialize, bool DumpLookups, + ASTDumpOutputFormat Format); // AST Decl node lister: prints qualified names of all filterable AST Decl // nodes. Index: include/clang/Frontend/FrontendOptions.h =================================================================== --- include/clang/Frontend/FrontendOptions.h +++ include/clang/Frontend/FrontendOptions.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H #define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H +#include "clang/AST/ASTDumperUtils.h" #include "clang/Frontend/CommandLineSourceLoc.h" #include "clang/Serialization/ModuleFileExtension.h" #include "clang/Sema/CodeCompleteOptions.h" @@ -307,6 +308,9 @@ CodeCompleteOptions CodeCompleteOpts; + /// Specifies the output format of the AST. + ASTDumpOutputFormat ASTDumpFormat = ADOF_Default; + enum { ARCMT_None, ARCMT_Check, Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTNodeTraverser.h" #include "clang/AST/DeclLookups.h" +#include "clang/AST/JSONNodeDumper.h" #include "clang/AST/TextNodeDumper.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Module.h" @@ -222,13 +223,21 @@ LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); } -LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize) const { +LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize, + ASTDumpOutputFormat Format) const { const ASTContext &Ctx = getASTContext(); const SourceManager &SM = Ctx.getSourceManager(); - ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM, - SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy()); - P.setDeserialize(Deserialize); - P.Visit(this); + + if (ADOF_JSON == Format) { + JSONDumper P(OS, SM, Ctx.getPrintingPolicy()); + (void)Deserialize; // FIXME? + P.Visit(this); + } else { + ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM, + SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy()); + P.setDeserialize(Deserialize); + P.Visit(this); + } } LLVM_DUMP_METHOD void Decl::dumpColor() const { Index: lib/AST/CMakeLists.txt =================================================================== --- lib/AST/CMakeLists.txt +++ lib/AST/CMakeLists.txt @@ -44,6 +44,7 @@ InheritViz.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp + JSONNodeDumper.cpp Mangle.cpp MicrosoftCXXABI.cpp MicrosoftMangle.cpp Index: lib/AST/JSONNodeDumper.cpp =================================================================== --- lib/AST/JSONNodeDumper.cpp +++ lib/AST/JSONNodeDumper.cpp @@ -0,0 +1,781 @@ +#include "clang/AST/JSONNodeDumper.h" +#include "llvm/ADT/StringSwitch.h" + +using namespace clang; + +void JSONNodeDumper::addPreviousDeclaration(const Decl *D) { + switch (D->getKind()) { +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: \ + return writePreviousDeclImpl(cast(D)); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" +#undef ABSTRACT_DECL +#undef DECL + } + llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); +} + +void JSONNodeDumper::Visit(const Attr *A) { + const char *AttrName = nullptr; + switch (A->getKind()) { +#define ATTR(X) \ + case attr::X: \ + AttrName = #X"Attr"; \ + break; +#include "clang/Basic/AttrList.inc" +#undef ATTR + } + JOS.attribute("id", createPointerRepresentation(A)); + JOS.attribute("kind", AttrName); + JOS.attribute("range", createSourceRange(A->getRange())); + attributeOnlyIfTrue("inherited", A->isInherited()); + attributeOnlyIfTrue("implicit", A->isImplicit()); + + // FIXME: it would be useful for us to output the spelling kind as well as + // the actual spelling. This would allow us to distinguish between the + // various attribute syntaxes, but we don't currently track that information + // within the AST. + //JOS.attribute("spelling", A->getSpelling()); + + InnerAttrVisitor::Visit(A); +} + +void JSONNodeDumper::Visit(const Stmt *S) { + if (!S) + return; + + JOS.attribute("id", createPointerRepresentation(S)); + JOS.attribute("kind", S->getStmtClassName()); + JOS.attribute("range", createSourceRange(S->getSourceRange())); + + if (const auto *E = dyn_cast(S)) { + JOS.attribute("type", createQualType(E->getType())); + const char *Category = nullptr; + switch (E->getValueKind()) { + case VK_LValue: Category = "lvalue"; break; + case VK_XValue: Category = "xvalue"; break; + case VK_RValue: Category = "rvalue"; break; + } + JOS.attribute("valueCategory", Category); + } + InnerStmtVisitor::Visit(S); +} + +void JSONNodeDumper::Visit(const Type *T) { + JOS.attribute("id", createPointerRepresentation(T)); + JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str()); + JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar*/ false)); + attributeOnlyIfTrue("isDependent", T->isDependentType()); + attributeOnlyIfTrue("isInstantiationDependent", + T->isInstantiationDependentType()); + attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType()); + attributeOnlyIfTrue("containsUnexpandedPack", + T->containsUnexpandedParameterPack()); + attributeOnlyIfTrue("isImported", T->isFromAST()); + InnerTypeVisitor::Visit(T); +} + +void JSONNodeDumper::Visit(QualType T) { + JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr())); + JOS.attribute("type", createQualType(T)); + JOS.attribute("qualifiers", T.split().Quals.getAsString()); +} + +void JSONNodeDumper::Visit(const Decl *D) { + JOS.attribute("id", createPointerRepresentation(D)); + + if (!D) + return; + + JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str()); + JOS.attribute("loc", createSourceLocation(D->getLocation())); + JOS.attribute("range", createSourceRange(D->getSourceRange())); + attributeOnlyIfTrue("isImplicit", D->isImplicit()); + attributeOnlyIfTrue("isInvalid", D->isInvalidDecl()); + + if (D->isUsed()) + JOS.attribute("isUsed", true); + else if (D->isThisDeclarationReferenced()) + JOS.attribute("isReferenced", true); + + if (const auto *ND = dyn_cast(D)) + attributeOnlyIfTrue("isHidden", ND->isHidden()); + + if (D->getLexicalDeclContext() != D->getDeclContext()) + JOS.attribute("parentDeclContext", + createPointerRepresentation(D->getDeclContext())); + + addPreviousDeclaration(D); + InnerDeclVisitor::Visit(D); +} + +void JSONNodeDumper::Visit(const comments::Comment *C, + const comments::FullComment *FC) {} + +void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R, + const Decl *From, StringRef Label) { + JOS.attribute("kind", "TemplateArgument"); + if (R.isValid()) + JOS.attribute("range", createSourceRange(R)); + + if (From) + JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From)); + + InnerTemplateArgVisitor::Visit(TA); +} + +void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) { + JOS.attribute("kind", "CXXCtorInitializer"); + if (Init->isAnyMemberInitializer()) + JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember())); + else if (Init->isBaseInitializer()) + JOS.attribute("baseInit", + createQualType(QualType(Init->getBaseClass(), 0))); + else if (Init->isDelegatingInitializer()) + JOS.attribute("delegatingInit", + createQualType(Init->getTypeSourceInfo()->getType())); + else + llvm_unreachable("Unknown initializer type"); +} + +void JSONNodeDumper::Visit(const OMPClause *C) {} +void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {} +void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) { + JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default"); + attributeOnlyIfTrue("selected", A.isSelected()); +} + +llvm::json::Object JSONNodeDumper::createSourceLocation(SourceLocation Loc) { + SourceLocation Spelling = SM.getSpellingLoc(Loc); + PresumedLoc Presumed = SM.getPresumedLoc(Spelling); + + if (Presumed.isInvalid()) + return llvm::json::Object{}; + + return llvm::json::Object{{"file", Presumed.getFilename()}, + {"line", Presumed.getLine()}, + {"col", Presumed.getColumn()}}; +} + +llvm::json::Object JSONNodeDumper::createSourceRange(SourceRange R) { + return llvm::json::Object{{"begin", createSourceLocation(R.getBegin())}, + {"end", createSourceLocation(R.getEnd())}}; +} + +std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) { + // Because JSON stores integer values as signed 64-bit integers, trying to + // represent them as such makes for very ugly pointer values in the resulting + // output. Instead, we convert the value to hex and treat it as a string. + return "0x" + llvm::utohexstr(reinterpret_cast(Ptr), true); +} + +llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) { + SplitQualType SQT = QT.split(); + llvm::json::Object Ret{{"qualType", QualType::getAsString(SQT, PrintPolicy)}}; + + if (Desugar && !QT.isNull()) { + SplitQualType DSQT = QT.getSplitDesugaredType(); + if (DSQT != SQT) + Ret["desugaredQualType"] = QualType::getAsString(DSQT, PrintPolicy); + } + return Ret; +} + +llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) { + llvm::json::Object Ret{ + {"id", createPointerRepresentation(D)}, + {"kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str()}}; + if (const auto *ND = dyn_cast(D)) + Ret["name"] = ND->getDeclName().getAsString(); + if (const auto *VD = dyn_cast(D)) + Ret["type"] = createQualType(VD->getType()); + return Ret; +} + +llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) { + llvm::json::Array Ret; + if (C->path_empty()) + return Ret; + + for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) { + const CXXBaseSpecifier *Base = *I; + const auto *RD = + cast(Base->getType()->getAs()->getDecl()); + + llvm::json::Object Val{{"name", RD->getName()}}; + if (Base->isVirtual()) + Val["isVirtual"] = true; + Ret.push_back(std::move(Val)); + } + return Ret; +} + +#define FIELD2(Name, Flag) if (RD->Flag()) Ret[Name] = true +#define FIELD1(Flag) FIELD2(#Flag, Flag) + +static llvm::json::Object +createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) { + llvm::json::Object Ret; + + FIELD2("exists", hasDefaultConstructor); + FIELD2("trivial", hasTrivialDefaultConstructor); + FIELD2("nonTrivial", hasNonTrivialDefaultConstructor); + FIELD2("userProvided", hasUserProvidedDefaultConstructor); + FIELD2("isConstexpr", hasConstexprDefaultConstructor); + FIELD2("needsImplicit", needsImplicitDefaultConstructor); + FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr); + + return Ret; +} + +static llvm::json::Object +createCopyConstructorDefinitionData(const CXXRecordDecl *RD) { + llvm::json::Object Ret; + + FIELD2("simple", hasSimpleCopyConstructor); + FIELD2("trivial", hasTrivialCopyConstructor); + FIELD2("nonTrivial", hasNonTrivialCopyConstructor); + FIELD2("userDeclared", hasUserDeclaredCopyConstructor); + FIELD2("hasConstParam", hasCopyConstructorWithConstParam); + FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam); + FIELD2("needsImplicit", needsImplicitCopyConstructor); + FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor); + if (!RD->needsOverloadResolutionForCopyConstructor()) + FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted); + + return Ret; +} + +static llvm::json::Object +createMoveConstructorDefinitionData(const CXXRecordDecl *RD) { + llvm::json::Object Ret; + + FIELD2("exists", hasMoveConstructor); + FIELD2("simple", hasSimpleMoveConstructor); + FIELD2("trivial", hasTrivialMoveConstructor); + FIELD2("nonTrivial", hasNonTrivialMoveConstructor); + FIELD2("userDeclared", hasUserDeclaredMoveConstructor); + FIELD2("needsImplicit", needsImplicitMoveConstructor); + FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor); + if (!RD->needsOverloadResolutionForMoveConstructor()) + FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted); + + return Ret; +} + +static llvm::json::Object +createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) { + llvm::json::Object Ret; + + FIELD2("trivial", hasTrivialCopyAssignment); + FIELD2("nonTrivial", hasNonTrivialCopyAssignment); + FIELD2("hasConstParam", hasCopyAssignmentWithConstParam); + FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam); + FIELD2("userDeclared", hasUserDeclaredCopyAssignment); + FIELD2("needsImplicit", needsImplicitCopyAssignment); + FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment); + + return Ret; +} + +static llvm::json::Object +createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) { + llvm::json::Object Ret; + + FIELD2("exists", hasMoveAssignment); + FIELD2("simple", hasSimpleMoveAssignment); + FIELD2("trivial", hasTrivialMoveAssignment); + FIELD2("nonTrivial", hasNonTrivialMoveAssignment); + FIELD2("userDeclared", hasUserDeclaredMoveAssignment); + FIELD2("needsImplicit", needsImplicitMoveAssignment); + FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment); + + return Ret; +} + +static llvm::json::Object +createDestructorDefinitionData(const CXXRecordDecl *RD) { + llvm::json::Object Ret; + + FIELD2("simple", hasSimpleDestructor); + FIELD2("irrelevant", hasIrrelevantDestructor); + FIELD2("trivial", hasTrivialDestructor); + FIELD2("nonTrivial", hasNonTrivialDestructor); + FIELD2("userDeclared", hasUserDeclaredDestructor); + FIELD2("needsImplicit", needsImplicitDestructor); + FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor); + if (!RD->needsOverloadResolutionForDestructor()) + FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted); + + return Ret; +} + +llvm::json::Object +JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) { + llvm::json::Object Ret; + + // This data is common to all C++ classes. + FIELD1(isGenericLambda); + FIELD1(isLambda); + FIELD1(isEmpty); + FIELD1(isAggregate); + FIELD1(isStandardLayout); + FIELD1(isTriviallyCopyable); + FIELD1(isPOD); + FIELD1(isTrivial); + FIELD1(isPolymorphic); + FIELD1(isAbstract); + FIELD1(isLiteral); + FIELD1(canPassInRegisters); + FIELD1(hasUserDeclaredConstructor); + FIELD1(hasConstexprNonCopyMoveConstructor); + FIELD1(hasMutableFields); + FIELD1(hasVariantMembers); + FIELD2("canConstDefaultInit", allowConstDefaultInit); + + Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD); + Ret["copyCtor"] = createCopyConstructorDefinitionData(RD); + Ret["moveCtor"] = createMoveConstructorDefinitionData(RD); + Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD); + Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD); + Ret["dtor"] = createDestructorDefinitionData(RD); + + return Ret; +} + +#undef FIELD1 +#undef FIELD2 + +std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) { + switch (AS) { + case AS_none: return "none"; + case AS_private: return "private"; + case AS_protected: return "protected"; + case AS_public: return "public"; + } + llvm_unreachable("Unknown access specifier"); +} + +llvm::json::Object +JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) { + llvm::json::Object Ret; + + Ret["type"] = createQualType(BS.getType()); + Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier()); + Ret["writtenAccess"] = + createAccessSpecifier(BS.getAccessSpecifierAsWritten()); + if (BS.isVirtual()) + Ret["isVirtual"] = true; + if (BS.isPackExpansion()) + Ret["isPackExpansion"] = true; + + return Ret; +} + +void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) { + JOS.attribute("decl", createBareDeclRef(TT->getDecl())); +} + +void JSONNodeDumper::VisitFunctionType(const FunctionType *T) { + FunctionType::ExtInfo E = T->getExtInfo(); + attributeOnlyIfTrue("noreturn", E.getNoReturn()); + attributeOnlyIfTrue("producesResult", E.getProducesResult()); + if (E.getHasRegParm()) + JOS.attribute("regParm", E.getRegParm()); + JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC())); +} + +void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) { + FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo(); + attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn); + attributeOnlyIfTrue("const", T->isConst()); + attributeOnlyIfTrue("volatile", T->isVolatile()); + attributeOnlyIfTrue("restrict", T->isRestrict()); + attributeOnlyIfTrue("variadic", E.Variadic); + switch (E.RefQualifier) { + case RQ_LValue: JOS.attribute("refQualifier", "&"); break; + case RQ_RValue: JOS.attribute("refQualifier", "&&"); break; + case RQ_None: break; + } + switch (E.ExceptionSpec.Type) { + case EST_DynamicNone: + case EST_Dynamic: { + JOS.attribute("exceptionSpec", "throw"); + llvm::json::Array Types; + for (QualType QT : E.ExceptionSpec.Exceptions) + Types.push_back(createQualType(QT)); + JOS.attribute("exceptionTypes", std::move(Types)); + } break; + case EST_MSAny: + JOS.attribute("exceptionSpec", "throw"); + JOS.attribute("throwsAny", true); + break; + case EST_BasicNoexcept: + JOS.attribute("exceptionSpec", "noexcept"); + break; + case EST_NoexceptTrue: + case EST_NoexceptFalse: + JOS.attribute("exceptionSpec", "noexcept"); + JOS.attribute("conditionEvaluatesTo", + E.ExceptionSpec.Type == EST_NoexceptTrue); + //JOS.attributeWithCall("exceptionSpecExpr", + // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); }); + break; + + // FIXME: I cannot find a way to trigger these cases while dumping the AST. I + // suspect you can only run into them when executing an AST dump from within + // the debugger, which is not a use case we worry about for the JSON dumping + // feature. + case EST_DependentNoexcept: + case EST_Unevaluated: + case EST_Uninstantiated: + case EST_Unparsed: + case EST_None: break; + } + VisitFunctionType(T); +} + +void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) { + if (ND && ND->getDeclName()) + JOS.attribute("name", ND->getNameAsString()); +} + +void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) { + VisitNamedDecl(TD); + JOS.attribute("type", createQualType(TD->getUnderlyingType())); +} + +void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) { + VisitNamedDecl(TAD); + JOS.attribute("type", createQualType(TAD->getUnderlyingType())); +} + +void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) { + VisitNamedDecl(ND); + attributeOnlyIfTrue("isInline", ND->isInline()); + if (!ND->isOriginalNamespace()) + JOS.attribute("originalNamespace", + createBareDeclRef(ND->getOriginalNamespace())); +} + +void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) { + JOS.attribute("nominatedNamespace", + createBareDeclRef(UDD->getNominatedNamespace())); +} + +void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) { + VisitNamedDecl(NAD); + JOS.attribute("aliasedNamespace", + createBareDeclRef(NAD->getAliasedNamespace())); +} + +void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) { + std::string Name; + if (const NestedNameSpecifier *NNS = UD->getQualifier()) { + llvm::raw_string_ostream SOS(Name); + NNS->print(SOS, UD->getASTContext().getPrintingPolicy()); + } + Name += UD->getNameAsString(); + JOS.attribute("name", Name); +} + +void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) { + JOS.attribute("target", createBareDeclRef(USD->getTargetDecl())); +} + +void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) { + VisitNamedDecl(VD); + JOS.attribute("type", createQualType(VD->getType())); + + StorageClass SC = VD->getStorageClass(); + if (SC != SC_None) + JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); + switch (VD->getTLSKind()) { + case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break; + case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break; + case VarDecl::TLS_None: break; + } + attributeOnlyIfTrue("nrvo", VD->isNRVOVariable()); + attributeOnlyIfTrue("inline", VD->isInline()); + attributeOnlyIfTrue("constexpr", VD->isConstexpr()); + attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate()); + if (VD->hasInit()) { + switch (VD->getInitStyle()) { + case VarDecl::CInit: JOS.attribute("init", "c"); break; + case VarDecl::CallInit: JOS.attribute("init", "call"); break; + case VarDecl::ListInit: JOS.attribute("init", "list"); break; + } + } +} + +void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) { + VisitNamedDecl(FD); + JOS.attribute("type", createQualType(FD->getType())); + attributeOnlyIfTrue("mutable", FD->isMutable()); + attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate()); + attributeOnlyIfTrue("isBitfield", FD->isBitField()); + attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer()); +} + +void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) { + VisitNamedDecl(FD); + JOS.attribute("type", createQualType(FD->getType())); + StorageClass SC = FD->getStorageClass(); + if (SC != SC_None) + JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); + attributeOnlyIfTrue("inline", FD->isInlineSpecified()); + attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten()); + attributeOnlyIfTrue("pure", FD->isPure()); + attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten()); + attributeOnlyIfTrue("constexpr", FD->isConstexpr()); + if (FD->isDefaulted()) + JOS.attribute("explicitlyDefaulted", + FD->isDeleted() ? "deleted" : "default"); +} + +void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) { + VisitNamedDecl(ED); + if (ED->isFixed()) + JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType())); + if (ED->isScoped()) + JOS.attribute("scopedEnumTag", + ED->isScopedUsingClassTag() ? "class" : "struct"); +} +void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) { + VisitNamedDecl(ECD); + JOS.attribute("type", createQualType(ECD->getType())); +} + +void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) { + VisitNamedDecl(RD); + JOS.attribute("tagUsed", RD->getKindName()); + attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition()); +} +void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) { + VisitRecordDecl(RD); + + // All other information requires a complete definition. + if (!RD->isCompleteDefinition()) + return; + + JOS.attribute("definitionData", createCXXRecordDefinitionData(RD)); + if (RD->getNumBases()) { + JOS.attributeArray("bases", [this, RD] { + for (const auto &Spec : RD->bases()) + JOS.value(createCXXBaseSpecifier(Spec)); + }); + } +} + +void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + VisitNamedDecl(D); + JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class"); + JOS.attribute("depth", D->getDepth()); + JOS.attribute("index", D->getIndex()); + attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); +} + +void JSONNodeDumper::VisitNonTypeTemplateParmDecl( + const NonTypeTemplateParmDecl *D) { + VisitNamedDecl(D); + JOS.attribute("type", createQualType(D->getType())); + JOS.attribute("depth", D->getDepth()); + JOS.attribute("index", D->getIndex()); + attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); +} + +void JSONNodeDumper::VisitTemplateTemplateParmDecl( + const TemplateTemplateParmDecl *D) { + VisitNamedDecl(D); + JOS.attribute("depth", D->getDepth()); + JOS.attribute("index", D->getIndex()); + attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); +} + +void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) { + StringRef Lang; + switch (LSD->getLanguage()) { + case LinkageSpecDecl::lang_c: Lang = "C"; break; + case LinkageSpecDecl::lang_cxx: Lang = "C++"; break; + } + JOS.attribute("language", Lang); + attributeOnlyIfTrue("hasBraces", LSD->hasBraces()); +} + +void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) { + JOS.attribute("access", createAccessSpecifier(ASD->getAccess())); +} + +void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) { + if (const TypeSourceInfo *T = FD->getFriendType()) + JOS.attribute("type", createQualType(T->getType())); +} + +void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) { + JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl())); + if (DRE->getDecl() != DRE->getFoundDecl()) + JOS.attribute("foundReferencedDecl", + createBareDeclRef(DRE->getFoundDecl())); +} + +void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) { + JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind())); +} + +void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) { + JOS.attribute("isPostfix", UO->isPostfix()); + JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode())); + if (!UO->canOverflow()) + JOS.attribute("canOverflow", false); +} + +void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) { + JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode())); +} + +void JSONNodeDumper::VisitCompoundAssignOperator( + const CompoundAssignOperator *CAO) { + VisitBinaryOperator(CAO); + JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType())); + JOS.attribute("computeResultType", + createQualType(CAO->getComputationResultType())); +} + +void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) { + // Note, we always write this Boolean field because the information it conveys + // is critical to understanding the AST node. + JOS.attribute("isArrow", ME->isArrow()); + JOS.attribute("referencedMemberDecl", + createPointerRepresentation(ME->getMemberDecl())); +} + +void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { + attributeOnlyIfTrue("isGlobal", NE->isGlobalNew()); + attributeOnlyIfTrue("isArray", NE->isArray()); + attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0); + switch (NE->getInitializationStyle()) { + case CXXNewExpr::NoInit: break; + case CXXNewExpr::CallInit: JOS.attribute("initStyle", "call"); break; + case CXXNewExpr::ListInit: JOS.attribute("initStyle", "list"); break; + } + if (const FunctionDecl *FD = NE->getOperatorNew()) + JOS.attribute("operatorNewDecl", createBareDeclRef(FD)); + if (const FunctionDecl *FD = NE->getOperatorDelete()) + JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); +} +void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) { + attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete()); + attributeOnlyIfTrue("isArray", DE->isArrayForm()); + attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten()); + if (const FunctionDecl *FD = DE->getOperatorDelete()) + JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); +} + +void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) { + attributeOnlyIfTrue("implicit", TE->isImplicit()); +} + +void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) { + JOS.attribute("castKind", CE->getCastKindName()); + llvm::json::Array Path = createCastPath(CE); + if (!Path.empty()) + JOS.attribute("path", std::move(Path)); + // FIXME: This may not be useful information as it can be obtusely gleaned + // from the inner[] array. + if (const NamedDecl *ND = CE->getConversionFunction()) + JOS.attribute("conversionFunc", createBareDeclRef(ND)); +} + +void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) { + VisitCastExpr(ICE); + attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast()); +} + +void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) { + attributeOnlyIfTrue("adl", CE->usesADL()); +} + +void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr *TTE) { + switch (TTE->getKind()) { + case UETT_SizeOf: JOS.attribute("name", "sizeof"); break; + case UETT_AlignOf: JOS.attribute("name", "alignof"); break; + case UETT_VecStep: JOS.attribute("name", "vec_step"); break; + case UETT_PreferredAlignOf: JOS.attribute("name", "__alignof"); break; + case UETT_OpenMPRequiredSimdAlign: + JOS.attribute("name", "__builtin_omp_required_simd_align"); break; + } + if (TTE->isArgumentType()) + JOS.attribute("argType", createQualType(TTE->getArgumentType())); +} + +void JSONNodeDumper::VisitUnresolvedLookupExpr( + const UnresolvedLookupExpr *ULE) { + JOS.attribute("usesADL", ULE->requiresADL()); + JOS.attribute("name", ULE->getName().getAsString()); + + JOS.attributeArray("lookups", [this, ULE] { + for (const NamedDecl *D : ULE->decls()) + JOS.value(createBareDeclRef(D)); + }); +} + +void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) { + JOS.attribute("name", ALE->getLabel()->getName()); + JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel())); +} + +void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) { + JOS.attribute("value", + IL->getValue().toString( + /*Radix=*/10, IL->getType()->isSignedIntegerType())); +} +void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) { + // FIXME: This should probably print the character literal as a string, + // rather than as a numerical value. + JOS.attribute("value", CL->getValue()); +} +void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) { + JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10)); +} +void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) { + JOS.attribute("value", FL->getValueAsApproximateDouble()); +} +void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) { + std::string Buffer; + llvm::raw_string_ostream SS(Buffer); + SL->outputString(SS); + JOS.attribute("value", SS.str()); +} +void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) { + JOS.attribute("value", BLE->getValue()); +} + +void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) { + attributeOnlyIfTrue("hasInit", IS->hasInitStorage()); + attributeOnlyIfTrue("hasVar", IS->hasVarStorage()); + attributeOnlyIfTrue("hasElse", IS->hasElseStorage()); + attributeOnlyIfTrue("isConstexpr", IS->isConstexpr()); +} + +void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) { + attributeOnlyIfTrue("hasInit", SS->hasInitStorage()); + attributeOnlyIfTrue("hasVar", SS->hasVarStorage()); +} +void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) { + attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange()); +} + +void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) { + JOS.attribute("name", LS->getName()); + JOS.attribute("declId", createPointerRepresentation(LS->getDecl())); +} +void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) { + JOS.attribute("targetLabelDeclId", + createPointerRepresentation(GS->getLabel())); +} + +void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) { + attributeOnlyIfTrue("hasVar", WS->hasVarStorage()); +} Index: lib/Frontend/ASTConsumers.cpp =================================================================== --- lib/Frontend/ASTConsumers.cpp +++ lib/Frontend/ASTConsumers.cpp @@ -34,10 +34,12 @@ public: enum Kind { DumpFull, Dump, Print, None }; - ASTPrinter(std::unique_ptr Out, Kind K, StringRef FilterString, + ASTPrinter(std::unique_ptr Out, Kind K, + ASTDumpOutputFormat Format, StringRef FilterString, bool DumpLookups = false) : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), - OutputKind(K), FilterString(FilterString), DumpLookups(DumpLookups) {} + OutputKind(K), OutputFormat(Format), FilterString(FilterString), + DumpLookups(DumpLookups) {} void HandleTranslationUnit(ASTContext &Context) override { TranslationUnitDecl *D = Context.getTranslationUnitDecl(); @@ -90,7 +92,7 @@ PrintingPolicy Policy(D->getASTContext().getLangOpts()); D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); } else if (OutputKind != None) - D->dump(Out, OutputKind == DumpFull); + D->dump(Out, OutputKind == DumpFull, OutputFormat); } raw_ostream &Out; @@ -99,6 +101,9 @@ /// How to output individual declarations. Kind OutputKind; + /// What format should the output take? + ASTDumpOutputFormat OutputFormat; + /// Which declarations or DeclContexts to display. std::string FilterString; @@ -135,20 +140,18 @@ clang::CreateASTPrinter(std::unique_ptr Out, StringRef FilterString) { return llvm::make_unique(std::move(Out), ASTPrinter::Print, - FilterString); + ADOF_Default, FilterString); } std::unique_ptr -clang::CreateASTDumper(std::unique_ptr Out, - StringRef FilterString, - bool DumpDecls, - bool Deserialize, - bool DumpLookups) { +clang::CreateASTDumper(std::unique_ptr Out, StringRef FilterString, + bool DumpDecls, bool Deserialize, bool DumpLookups, + ASTDumpOutputFormat Format) { assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); return llvm::make_unique(std::move(Out), Deserialize ? ASTPrinter::DumpFull : DumpDecls ? ASTPrinter::Dump : - ASTPrinter::None, + ASTPrinter::None, Format, FilterString, DumpLookups); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1603,6 +1603,22 @@ llvm_unreachable("Invalid option in group!"); case OPT_ast_list: Opts.ProgramAction = frontend::ASTDeclList; break; + case OPT_ast_dump_all_EQ: + case OPT_ast_dump_EQ: { + unsigned Val = llvm::StringSwitch(A->getValue()) + .CaseLower("default", ADOF_Default) + .CaseLower("json", ADOF_JSON) + .Default(std::numeric_limits::max()); + + if (Val != std::numeric_limits::max()) + Opts.ASTDumpFormat = static_cast(Val); + else { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + Opts.ASTDumpFormat = ADOF_Default; + } + LLVM_FALLTHROUGH; + } case OPT_ast_dump: case OPT_ast_dump_all: case OPT_ast_dump_lookups: @@ -1725,8 +1741,8 @@ Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings); Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile); Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp); - Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump); - Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all); + Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ); + Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ); Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter); Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups); Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); Index: lib/Frontend/FrontendActions.cpp =================================================================== --- lib/Frontend/FrontendActions.cpp +++ lib/Frontend/FrontendActions.cpp @@ -73,11 +73,10 @@ std::unique_ptr ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return CreateASTDumper(nullptr /*Dump to stdout.*/, - CI.getFrontendOpts().ASTDumpFilter, - CI.getFrontendOpts().ASTDumpDecls, - CI.getFrontendOpts().ASTDumpAll, - CI.getFrontendOpts().ASTDumpLookups); + const FrontendOptions &Opts = CI.getFrontendOpts(); + return CreateASTDumper(nullptr /*Dump to stdout.*/, Opts.ASTDumpFilter, + Opts.ASTDumpDecls, Opts.ASTDumpAll, + Opts.ASTDumpLookups, Opts.ASTDumpFormat); } std::unique_ptr Index: test/AST/ast-dump-enum-json.cpp =================================================================== --- test/AST/ast-dump-enum-json.cpp +++ test/AST/ast-dump-enum-json.cpp @@ -0,0 +1,484 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++17 -ast-dump=json %s | FileCheck %s + +enum { + One, + Two +}; + +// CHECK: "kind": "EnumDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 6 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "One", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "(anonymous enum at {{.*}}:3:1)" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 5 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Two", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "(anonymous enum at {{.*}}:3:1)" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + +enum E { + Three, + Four +}; + +// CHECK: "kind": "EnumDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 80 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 80 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 83 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "E", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 81 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 81 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 81 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Three", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "E" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 82 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 82 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 82 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Four", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "E" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + +enum F : short { + Five, + Six +}; + +// CHECK: "kind": "EnumDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 158 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 158 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 161 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "F", +// CHECK-NEXT: "fixedUnderlyingType": { +// CHECK-NEXT: "qualType": "short" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 159 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 159 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 159 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Five", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "F" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 160 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 160 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 160 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Six", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "F" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + +enum struct G { + Seven, + Eight +}; + +// CHECK: "kind": "EnumDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 239 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 239 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 242 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "G", +// CHECK-NEXT: "fixedUnderlyingType": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "scopedEnumTag": "struct", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 240 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 240 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 240 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Seven", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "G" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 241 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 241 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 241 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Eight", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "G" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + +enum class H { + Nine, + Ten +}; + +// CHECK: "kind": "EnumDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 321 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 321 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 324 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "H", +// CHECK-NEXT: "fixedUnderlyingType": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "scopedEnumTag": "class", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 322 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 322 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 322 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Nine", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "H" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 323 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 323 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 323 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Ten", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "H" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + +enum class I : int { + Eleven, + Twelve +}; + +// CHECK: "kind": "EnumDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 403 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 403 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 406 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "I", +// CHECK-NEXT: "fixedUnderlyingType": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "scopedEnumTag": "class", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 404 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 404 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 404 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Eleven", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "I" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "EnumConstantDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 405 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 405 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 405 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "Twelve", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "I" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] Index: test/AST/ast-dump-if-json.cpp =================================================================== --- test/AST/ast-dump-if-json.cpp +++ test/AST/ast-dump-if-json.cpp @@ -0,0 +1,964 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++17 -ast-dump=json %s | FileCheck %s + +void func(int val) { + if (val) + ; + +// CHECK: "kind": "IfStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 5 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "IntegralToBoolean", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "name": "val", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 5 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + + if (val) + ; + else + ; + +// CHECK: "kind": "IfStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 114 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 117 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "hasElse": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 114 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 114 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "IntegralToBoolean", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 114 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 114 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 114 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 114 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue" +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "name": "val", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 115 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 115 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 117 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 117 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + + if (val) + ; + else if (val) + ; + else + ; + +// CHECK: "kind": "IfStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 243 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 248 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "hasElse": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 243 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 243 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "IntegralToBoolean", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 243 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 243 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 243 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 243 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue" +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "name": "val", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 244 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 244 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IfStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 245 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 248 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "hasElse": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 245 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 245 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "IntegralToBoolean", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 245 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 245 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 245 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 245 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue" +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "name": "val", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 246 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 246 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 248 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 248 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + + if constexpr(10 == 10) + ; + +// CHECK: "kind": "IfStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 484 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isConstexpr": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ConstantExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BinaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "opcode": "==", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "value": "10" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 483 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "value": "10" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 484 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 484 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + + if (int i = 12) + ; + +// CHECK: "kind": "IfStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 608 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "hasVar": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "i", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "value": "12" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "IntegralToBoolean", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 607 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue" +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "i", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 608 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 608 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + + if (int i = 12; i) + ; + +// CHECK: "kind": "IfStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 787 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "hasInit": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "i", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "value": "12" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "IntegralToBoolean", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "rvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 786 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue" +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "i", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NullStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 787 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 787 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +} Index: test/AST/ast-dump-namespace-json.cpp =================================================================== --- test/AST/ast-dump-namespace-json.cpp +++ test/AST/ast-dump-namespace-json.cpp @@ -0,0 +1,211 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++2a -ast-dump=json %s | FileCheck %s + +namespace foo { +} +// CHECK: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "foo" +// CHECK-NEXT: }, + + +namespace { +} +// CHECK: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 27 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 27 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 28 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "UsingDirectiveDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 27 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "nominatedNamespace": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NamespaceDecl", +// CHECK-NEXT: "name": "" +// CHECK-NEXT: } +// CHECK-NEXT: }, + +namespace bar { +inline namespace __1 { +} +} +// CHECK: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 68 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 68 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 71 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "bar", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 69 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 69 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 70 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "__1", +// CHECK-NEXT: "isInline": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + +namespace baz::quux { +} +// CHECK: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 118 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 118 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 119 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "baz", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 118 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 118 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 119 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "quux" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, + +namespace quux::inline frobble { +} +// CHECK: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 165 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 165 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 166 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "quux", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NamespaceDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "col": 24, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 165 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 165 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 166 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "frobble", +// CHECK-NEXT: "isInline": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } Index: tools/clang-check/ClangCheck.cpp =================================================================== --- tools/clang-check/ClangCheck.cpp +++ tools/clang-check/ClangCheck.cpp @@ -134,11 +134,11 @@ if (ASTList) return clang::CreateASTDeclNodeLister(); if (ASTDump) - return clang::CreateASTDumper(nullptr /*Dump to stdout.*/, - ASTDumpFilter, + return clang::CreateASTDumper(nullptr /*Dump to stdout.*/, ASTDumpFilter, /*DumpDecls=*/true, /*Deserialize=*/false, - /*DumpLookups=*/false); + /*DumpLookups=*/false, + clang::ADOF_Default); if (ASTPrint) return clang::CreateASTPrinter(nullptr, ASTDumpFilter); return llvm::make_unique(); Index: tools/clang-import-test/clang-import-test.cpp =================================================================== --- tools/clang-import-test/clang-import-test.cpp +++ tools/clang-import-test/clang-import-test.cpp @@ -316,8 +316,9 @@ auto &CG = *static_cast(ASTConsumers.back().get()); if (ShouldDumpAST) - ASTConsumers.push_back(CreateASTDumper(nullptr /*Dump to stdout.*/, - "", true, false, false)); + ASTConsumers.push_back( + CreateASTDumper(nullptr /*Dump to stdout.*/, "", true, false, false, + clang::ADOF_Default)); CI.getDiagnosticClient().BeginSourceFile( CI.getCompilerInstance().getLangOpts(),