- //===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // 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/ASTDumperUtils.h" 
- #include "clang/AST/ASTNodeTraverser.h" 
- #include "clang/AST/AttrVisitor.h" 
- #include "clang/AST/CommentCommandTraits.h" 
- #include "clang/AST/CommentVisitor.h" 
- #include "clang/AST/ExprConcepts.h" 
- #include "clang/AST/ExprCXX.h" 
- #include "clang/AST/Mangle.h" 
- #include "clang/AST/Type.h" 
- #include "llvm/Support/JSON.h" 
-   
- namespace clang { 
-   
- class APValue; 
-   
- class NodeStreamer { 
-   bool FirstChild = true; 
-   bool TopLevel = true; 
-   llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending; 
-   
- protected: 
-   llvm::json::OStream JOS; 
-   
- public: 
-   /// Add a child of the current node.  Calls DoAddChild without arguments 
-   template <typename Fn> void AddChild(Fn DoAddChild) { 
-     return AddChild("", DoAddChild); 
-   } 
-   
-   /// Add a child of the current node with an optional label. 
-   /// Calls DoAddChild without arguments. 
-   template <typename Fn> 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. There is no implied stability for the 
- // content or format of the dump between major releases of Clang, other than it 
- // being valid JSON output. Further, there is no requirement that the 
- // information dumped is a complete representation of the AST, only that the 
- // information presented is correct. 
- class JSONNodeDumper 
-     : public ConstAttrVisitor<JSONNodeDumper>, 
-       public comments::ConstCommentVisitor<JSONNodeDumper, void, 
-                                            const comments::FullComment *>, 
-       public ConstTemplateArgumentVisitor<JSONNodeDumper>, 
-       public ConstStmtVisitor<JSONNodeDumper>, 
-       public TypeVisitor<JSONNodeDumper>, 
-       public ConstDeclVisitor<JSONNodeDumper>, 
-       public NodeStreamer { 
-   friend class JSONDumper; 
-   
-   const SourceManager &SM; 
-   ASTContext& Ctx; 
-   ASTNameGenerator ASTNameGen; 
-   PrintingPolicy PrintPolicy; 
-   const comments::CommandTraits *Traits; 
-   StringRef LastLocFilename, LastLocPresumedFilename; 
-   unsigned LastLocLine, LastLocPresumedLine; 
-   
-   using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>; 
-   using InnerCommentVisitor = 
-       comments::ConstCommentVisitor<JSONNodeDumper, void, 
-                                     const comments::FullComment *>; 
-   using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor<JSONNodeDumper>; 
-   using InnerStmtVisitor = ConstStmtVisitor<JSONNodeDumper>; 
-   using InnerTypeVisitor = TypeVisitor<JSONNodeDumper>; 
-   using InnerDeclVisitor = ConstDeclVisitor<JSONNodeDumper>; 
-   
-   void attributeOnlyIfTrue(StringRef Key, bool Value) { 
-     if (Value) 
-       JOS.attribute(Key, Value); 
-   } 
-   
-   void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false); 
-   
-   // Writes the attributes of a SourceLocation object without. 
-   void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling); 
-   
-   // Writes the attributes of a SourceLocation to JSON based on its presumed 
-   // spelling location. If the given location represents a macro invocation, 
-   // this outputs two sub-objects: one for the spelling and one for the 
-   // expansion location. 
-   void writeSourceLocation(SourceLocation Loc); 
-   void writeSourceRange(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 createFPOptions(FPOptionsOverride FPO); 
-   void writeBareDeclRef(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 <typename T> void writePreviousDeclImpl(const Mergeable<T> *D) { 
-     const T *First = D->getFirstDecl(); 
-     if (First != D) 
-       JOS.attribute("firstRedecl", createPointerRepresentation(First)); 
-   } 
-   
-   template <typename T> void writePreviousDeclImpl(const Redeclarable<T> *D) { 
-     const T *Prev = D->getPreviousDecl(); 
-     if (Prev) 
-       JOS.attribute("previousDecl", createPointerRepresentation(Prev)); 
-   } 
-   void addPreviousDeclaration(const Decl *D); 
-   
-   StringRef getCommentCommandName(unsigned CommandID) const; 
-   
- public: 
-   JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx, 
-                  const PrintingPolicy &PrintPolicy, 
-                  const comments::CommandTraits *Traits) 
-       : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx), 
-         PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0), 
-         LastLocPresumedLine(0) {} 
-   
-   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 Visit(const concepts::Requirement *R); 
-   void Visit(const APValue &Value, QualType Ty); 
-   
-   void VisitTypedefType(const TypedefType *TT); 
-   void VisitUsingType(const UsingType *TT); 
-   void VisitFunctionType(const FunctionType *T); 
-   void VisitFunctionProtoType(const FunctionProtoType *T); 
-   void VisitRValueReferenceType(const ReferenceType *RT); 
-   void VisitArrayType(const ArrayType *AT); 
-   void VisitConstantArrayType(const ConstantArrayType *CAT); 
-   void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *VT); 
-   void VisitVectorType(const VectorType *VT); 
-   void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT); 
-   void VisitUnaryTransformType(const UnaryTransformType *UTT); 
-   void VisitTagType(const TagType *TT); 
-   void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT); 
-   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT); 
-   void 
-   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T); 
-   void VisitAutoType(const AutoType *AT); 
-   void VisitTemplateSpecializationType(const TemplateSpecializationType *TST); 
-   void VisitInjectedClassNameType(const InjectedClassNameType *ICNT); 
-   void VisitObjCInterfaceType(const ObjCInterfaceType *OIT); 
-   void VisitPackExpansionType(const PackExpansionType *PET); 
-   void VisitElaboratedType(const ElaboratedType *ET); 
-   void VisitMacroQualifiedType(const MacroQualifiedType *MQT); 
-   void VisitMemberPointerType(const MemberPointerType *MPT); 
-   
-   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 VisitUsingEnumDecl(const UsingEnumDecl *UED); 
-   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 VisitHLSLBufferDecl(const HLSLBufferDecl *D); 
-   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 VisitObjCIvarDecl(const ObjCIvarDecl *D); 
-   void VisitObjCMethodDecl(const ObjCMethodDecl *D); 
-   void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D); 
-   void VisitObjCCategoryDecl(const ObjCCategoryDecl *D); 
-   void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D); 
-   void VisitObjCProtocolDecl(const ObjCProtocolDecl *D); 
-   void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); 
-   void VisitObjCImplementationDecl(const ObjCImplementationDecl *D); 
-   void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D); 
-   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); 
-   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); 
-   void VisitBlockDecl(const BlockDecl *D); 
-   
-   void VisitDeclRefExpr(const DeclRefExpr *DRE); 
-   void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E); 
-   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 VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE); 
-   void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE); 
-   void VisitAddrLabelExpr(const AddrLabelExpr *ALE); 
-   void VisitCXXTypeidExpr(const CXXTypeidExpr *CTE); 
-   void VisitConstantExpr(const ConstantExpr *CE); 
-   void VisitInitListExpr(const InitListExpr *ILE); 
-   void VisitGenericSelectionExpr(const GenericSelectionExpr *GSE); 
-   void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *UCE); 
-   void VisitCXXConstructExpr(const CXXConstructExpr *CE); 
-   void VisitExprWithCleanups(const ExprWithCleanups *EWC); 
-   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE); 
-   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE); 
-   void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME); 
-   void VisitRequiresExpr(const RequiresExpr *RE); 
-   
-   void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE); 
-   void VisitObjCMessageExpr(const ObjCMessageExpr *OME); 
-   void VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE); 
-   void VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE); 
-   void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE); 
-   void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE); 
-   void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *OSRE); 
-   void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE); 
-   void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE); 
-   
-   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); 
-   void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS); 
-   void VisitCompoundStmt(const CompoundStmt *IS); 
-   
-   void VisitNullTemplateArgument(const TemplateArgument &TA); 
-   void VisitTypeTemplateArgument(const TemplateArgument &TA); 
-   void VisitDeclarationTemplateArgument(const TemplateArgument &TA); 
-   void VisitNullPtrTemplateArgument(const TemplateArgument &TA); 
-   void VisitIntegralTemplateArgument(const TemplateArgument &TA); 
-   void VisitTemplateTemplateArgument(const TemplateArgument &TA); 
-   void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA); 
-   void VisitExpressionTemplateArgument(const TemplateArgument &TA); 
-   void VisitPackTemplateArgument(const TemplateArgument &TA); 
-   
-   void visitTextComment(const comments::TextComment *C, 
-                         const comments::FullComment *); 
-   void visitInlineCommandComment(const comments::InlineCommandComment *C, 
-                                  const comments::FullComment *); 
-   void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C, 
-                                 const comments::FullComment *); 
-   void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C, 
-                               const comments::FullComment *); 
-   void visitBlockCommandComment(const comments::BlockCommandComment *C, 
-                                 const comments::FullComment *); 
-   void visitParamCommandComment(const comments::ParamCommandComment *C, 
-                                 const comments::FullComment *FC); 
-   void visitTParamCommandComment(const comments::TParamCommandComment *C, 
-                                  const comments::FullComment *FC); 
-   void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C, 
-                                  const comments::FullComment *); 
-   void 
-   visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C, 
-                                 const comments::FullComment *); 
-   void visitVerbatimLineComment(const comments::VerbatimLineComment *C, 
-                                 const comments::FullComment *); 
- }; 
-   
- class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> { 
-   JSONNodeDumper NodeDumper; 
-   
-   template <typename SpecializationDecl> 
-   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<SpecializationDecl>(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<CXXRecordDecl>(RedeclWithBadType) && 
-                "expected an injected-class-name"); 
-         continue; 
-       } 
-   
-       switch (Redecl->getTemplateSpecializationKind()) { 
-       case TSK_ExplicitInstantiationDeclaration: 
-       case TSK_ExplicitInstantiationDefinition: 
-         if (!DumpExplicitInst) 
-           break; 
-         [[fallthrough]]; 
-       case TSK_Undeclared: 
-       case TSK_ImplicitInstantiation: 
-         if (DumpRefOnly) 
-           NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(Redecl); }); 
-         else 
-           Visit(Redecl); 
-         DumpedAny = true; 
-         break; 
-       case TSK_ExplicitSpecialization: 
-         break; 
-       } 
-     } 
-   
-     // Ensure we dump at least one decl for each specialization. 
-     if (!DumpedAny) 
-       NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(SD); }); 
-   } 
-   
-   template <typename TemplateDecl> 
-   void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) { 
-     // FIXME: it would be nice to dump template parameters and specializations 
-     // to their own named arrays rather than shoving them into the "inner" 
-     // array. However, template declarations are currently being handled at the 
-     // wrong "level" of the traversal hierarchy and so it is difficult to 
-     // achieve without losing information elsewhere. 
-   
-     dumpTemplateParameters(TD->getTemplateParameters()); 
-   
-     Visit(TD->getTemplatedDecl()); 
-   
-     for (const auto *Child : TD->specializations()) 
-       writeTemplateDeclSpecialization(Child, DumpExplicitInst, 
-                                       !TD->isCanonicalDecl()); 
-   } 
-   
- public: 
-   JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx, 
-              const PrintingPolicy &PrintPolicy, 
-              const comments::CommandTraits *Traits) 
-       : NodeDumper(OS, SrcMgr, Ctx, PrintPolicy, Traits) {} 
-   
-   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 
-