10b57cec5SDimitry Andric //===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===//
20b57cec5SDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements AST dumping of components of individual AST nodes to
100b57cec5SDimitry Andric // a JSON.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H
150b57cec5SDimitry Andric #define LLVM_CLANG_AST_JSONNODEDUMPER_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
180b57cec5SDimitry Andric #include "clang/AST/ASTDumperUtils.h"
19480093f4SDimitry Andric #include "clang/AST/ASTNodeTraverser.h"
200b57cec5SDimitry Andric #include "clang/AST/AttrVisitor.h"
210b57cec5SDimitry Andric #include "clang/AST/CommentCommandTraits.h"
220b57cec5SDimitry Andric #include "clang/AST/CommentVisitor.h"
23fe6060f1SDimitry Andric #include "clang/AST/ExprConcepts.h"
240b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
25480093f4SDimitry Andric #include "clang/AST/Mangle.h"
265ffd83dbSDimitry Andric #include "clang/AST/Type.h"
270b57cec5SDimitry Andric #include "llvm/Support/JSON.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace clang {
300b57cec5SDimitry Andric 
315ffd83dbSDimitry Andric class APValue;
325ffd83dbSDimitry Andric 
330b57cec5SDimitry Andric class NodeStreamer {
340b57cec5SDimitry Andric   bool FirstChild = true;
350b57cec5SDimitry Andric   bool TopLevel = true;
360b57cec5SDimitry Andric   llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric protected:
390b57cec5SDimitry Andric   llvm::json::OStream JOS;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric public:
420b57cec5SDimitry Andric   /// Add a child of the current node.  Calls DoAddChild without arguments
AddChild(Fn DoAddChild)430b57cec5SDimitry Andric   template <typename Fn> void AddChild(Fn DoAddChild) {
440b57cec5SDimitry Andric     return AddChild("", DoAddChild);
450b57cec5SDimitry Andric   }
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   /// Add a child of the current node with an optional label.
480b57cec5SDimitry Andric   /// Calls DoAddChild without arguments.
AddChild(StringRef Label,Fn DoAddChild)490b57cec5SDimitry Andric   template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) {
500b57cec5SDimitry Andric     // If we're at the top level, there's nothing interesting to do; just
510b57cec5SDimitry Andric     // run the dumper.
520b57cec5SDimitry Andric     if (TopLevel) {
530b57cec5SDimitry Andric       TopLevel = false;
540b57cec5SDimitry Andric       JOS.objectBegin();
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric       DoAddChild();
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric       while (!Pending.empty()) {
590b57cec5SDimitry Andric         Pending.back()(true);
600b57cec5SDimitry Andric         Pending.pop_back();
610b57cec5SDimitry Andric       }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric       JOS.objectEnd();
640b57cec5SDimitry Andric       TopLevel = true;
650b57cec5SDimitry Andric       return;
660b57cec5SDimitry Andric     }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric     // We need to capture an owning-string in the lambda because the lambda
690b57cec5SDimitry Andric     // is invoked in a deferred manner.
705ffd83dbSDimitry Andric     std::string LabelStr(!Label.empty() ? Label : "inner");
710b57cec5SDimitry Andric     bool WasFirstChild = FirstChild;
720b57cec5SDimitry Andric     auto DumpWithIndent = [=](bool IsLastChild) {
730b57cec5SDimitry Andric       if (WasFirstChild) {
740b57cec5SDimitry Andric         JOS.attributeBegin(LabelStr);
750b57cec5SDimitry Andric         JOS.arrayBegin();
760b57cec5SDimitry Andric       }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric       FirstChild = true;
790b57cec5SDimitry Andric       unsigned Depth = Pending.size();
800b57cec5SDimitry Andric       JOS.objectBegin();
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric       DoAddChild();
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric       // If any children are left, they're the last at their nesting level.
850b57cec5SDimitry Andric       // Dump those ones out now.
860b57cec5SDimitry Andric       while (Depth < Pending.size()) {
870b57cec5SDimitry Andric         Pending.back()(true);
880b57cec5SDimitry Andric         this->Pending.pop_back();
890b57cec5SDimitry Andric       }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric       JOS.objectEnd();
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric       if (IsLastChild) {
940b57cec5SDimitry Andric         JOS.arrayEnd();
950b57cec5SDimitry Andric         JOS.attributeEnd();
960b57cec5SDimitry Andric       }
970b57cec5SDimitry Andric     };
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric     if (FirstChild) {
1000b57cec5SDimitry Andric       Pending.push_back(std::move(DumpWithIndent));
1010b57cec5SDimitry Andric     } else {
1020b57cec5SDimitry Andric       Pending.back()(false);
1030b57cec5SDimitry Andric       Pending.back() = std::move(DumpWithIndent);
1040b57cec5SDimitry Andric     }
1050b57cec5SDimitry Andric     FirstChild = false;
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric 
NodeStreamer(raw_ostream & OS)1080b57cec5SDimitry Andric   NodeStreamer(raw_ostream &OS) : JOS(OS, 2) {}
1090b57cec5SDimitry Andric };
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric // Dumps AST nodes in JSON format. There is no implied stability for the
1120b57cec5SDimitry Andric // content or format of the dump between major releases of Clang, other than it
1130b57cec5SDimitry Andric // being valid JSON output. Further, there is no requirement that the
1140b57cec5SDimitry Andric // information dumped is a complete representation of the AST, only that the
1150b57cec5SDimitry Andric // information presented is correct.
1160b57cec5SDimitry Andric class JSONNodeDumper
1170b57cec5SDimitry Andric     : public ConstAttrVisitor<JSONNodeDumper>,
1180b57cec5SDimitry Andric       public comments::ConstCommentVisitor<JSONNodeDumper, void,
1190b57cec5SDimitry Andric                                            const comments::FullComment *>,
1200b57cec5SDimitry Andric       public ConstTemplateArgumentVisitor<JSONNodeDumper>,
1210b57cec5SDimitry Andric       public ConstStmtVisitor<JSONNodeDumper>,
1220b57cec5SDimitry Andric       public TypeVisitor<JSONNodeDumper>,
1230b57cec5SDimitry Andric       public ConstDeclVisitor<JSONNodeDumper>,
1240b57cec5SDimitry Andric       public NodeStreamer {
1250b57cec5SDimitry Andric   friend class JSONDumper;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   const SourceManager &SM;
1280b57cec5SDimitry Andric   ASTContext& Ctx;
129480093f4SDimitry Andric   ASTNameGenerator ASTNameGen;
1300b57cec5SDimitry Andric   PrintingPolicy PrintPolicy;
1310b57cec5SDimitry Andric   const comments::CommandTraits *Traits;
132480093f4SDimitry Andric   StringRef LastLocFilename, LastLocPresumedFilename;
1330b57cec5SDimitry Andric   unsigned LastLocLine, LastLocPresumedLine;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>;
1360b57cec5SDimitry Andric   using InnerCommentVisitor =
1370b57cec5SDimitry Andric       comments::ConstCommentVisitor<JSONNodeDumper, void,
1380b57cec5SDimitry Andric                                     const comments::FullComment *>;
1390b57cec5SDimitry Andric   using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor<JSONNodeDumper>;
1400b57cec5SDimitry Andric   using InnerStmtVisitor = ConstStmtVisitor<JSONNodeDumper>;
1410b57cec5SDimitry Andric   using InnerTypeVisitor = TypeVisitor<JSONNodeDumper>;
1420b57cec5SDimitry Andric   using InnerDeclVisitor = ConstDeclVisitor<JSONNodeDumper>;
1430b57cec5SDimitry Andric 
attributeOnlyIfTrue(StringRef Key,bool Value)1440b57cec5SDimitry Andric   void attributeOnlyIfTrue(StringRef Key, bool Value) {
1450b57cec5SDimitry Andric     if (Value)
1460b57cec5SDimitry Andric       JOS.attribute(Key, Value);
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
149a7dea167SDimitry Andric   void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false);
150a7dea167SDimitry Andric 
1510b57cec5SDimitry Andric   // Writes the attributes of a SourceLocation object without.
1520b57cec5SDimitry Andric   void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling);
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   // Writes the attributes of a SourceLocation to JSON based on its presumed
1550b57cec5SDimitry Andric   // spelling location. If the given location represents a macro invocation,
1560b57cec5SDimitry Andric   // this outputs two sub-objects: one for the spelling and one for the
1570b57cec5SDimitry Andric   // expansion location.
1580b57cec5SDimitry Andric   void writeSourceLocation(SourceLocation Loc);
1590b57cec5SDimitry Andric   void writeSourceRange(SourceRange R);
1600b57cec5SDimitry Andric   std::string createPointerRepresentation(const void *Ptr);
1610b57cec5SDimitry Andric   llvm::json::Object createQualType(QualType QT, bool Desugar = true);
1620b57cec5SDimitry Andric   llvm::json::Object createBareDeclRef(const Decl *D);
16381ad6265SDimitry Andric   llvm::json::Object createFPOptions(FPOptionsOverride FPO);
1640b57cec5SDimitry Andric   void writeBareDeclRef(const Decl *D);
1650b57cec5SDimitry Andric   llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD);
1660b57cec5SDimitry Andric   llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS);
1670b57cec5SDimitry Andric   std::string createAccessSpecifier(AccessSpecifier AS);
1680b57cec5SDimitry Andric   llvm::json::Array createCastPath(const CastExpr *C);
1690b57cec5SDimitry Andric 
writePreviousDeclImpl(...)1700b57cec5SDimitry Andric   void writePreviousDeclImpl(...) {}
1710b57cec5SDimitry Andric 
writePreviousDeclImpl(const Mergeable<T> * D)1720b57cec5SDimitry Andric   template <typename T> void writePreviousDeclImpl(const Mergeable<T> *D) {
1730b57cec5SDimitry Andric     const T *First = D->getFirstDecl();
1740b57cec5SDimitry Andric     if (First != D)
1750b57cec5SDimitry Andric       JOS.attribute("firstRedecl", createPointerRepresentation(First));
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric 
writePreviousDeclImpl(const Redeclarable<T> * D)1780b57cec5SDimitry Andric   template <typename T> void writePreviousDeclImpl(const Redeclarable<T> *D) {
1790b57cec5SDimitry Andric     const T *Prev = D->getPreviousDecl();
1800b57cec5SDimitry Andric     if (Prev)
1810b57cec5SDimitry Andric       JOS.attribute("previousDecl", createPointerRepresentation(Prev));
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric   void addPreviousDeclaration(const Decl *D);
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   StringRef getCommentCommandName(unsigned CommandID) const;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric public:
JSONNodeDumper(raw_ostream & OS,const SourceManager & SrcMgr,ASTContext & Ctx,const PrintingPolicy & PrintPolicy,const comments::CommandTraits * Traits)1880b57cec5SDimitry Andric   JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
1890b57cec5SDimitry Andric                  const PrintingPolicy &PrintPolicy,
1900b57cec5SDimitry Andric                  const comments::CommandTraits *Traits)
191480093f4SDimitry Andric       : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx),
192480093f4SDimitry Andric         PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0),
193480093f4SDimitry Andric         LastLocPresumedLine(0) {}
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   void Visit(const Attr *A);
1960b57cec5SDimitry Andric   void Visit(const Stmt *Node);
1970b57cec5SDimitry Andric   void Visit(const Type *T);
1980b57cec5SDimitry Andric   void Visit(QualType T);
1990b57cec5SDimitry Andric   void Visit(const Decl *D);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   void Visit(const comments::Comment *C, const comments::FullComment *FC);
2020b57cec5SDimitry Andric   void Visit(const TemplateArgument &TA, SourceRange R = {},
2030b57cec5SDimitry Andric              const Decl *From = nullptr, StringRef Label = {});
2040b57cec5SDimitry Andric   void Visit(const CXXCtorInitializer *Init);
2050b57cec5SDimitry Andric   void Visit(const OMPClause *C);
2060b57cec5SDimitry Andric   void Visit(const BlockDecl::Capture &C);
2070b57cec5SDimitry Andric   void Visit(const GenericSelectionExpr::ConstAssociation &A);
208fe6060f1SDimitry Andric   void Visit(const concepts::Requirement *R);
2095ffd83dbSDimitry Andric   void Visit(const APValue &Value, QualType Ty);
2100b57cec5SDimitry Andric 
2115f757f3fSDimitry Andric   void VisitAliasAttr(const AliasAttr *AA);
2125f757f3fSDimitry Andric   void VisitCleanupAttr(const CleanupAttr *CA);
2135f757f3fSDimitry Andric   void VisitDeprecatedAttr(const DeprecatedAttr *DA);
2145f757f3fSDimitry Andric   void VisitUnavailableAttr(const UnavailableAttr *UA);
2155f757f3fSDimitry Andric   void VisitSectionAttr(const SectionAttr *SA);
2165f757f3fSDimitry Andric   void VisitVisibilityAttr(const VisibilityAttr *VA);
2175f757f3fSDimitry Andric   void VisitTLSModelAttr(const TLSModelAttr *TA);
2185f757f3fSDimitry Andric 
2190b57cec5SDimitry Andric   void VisitTypedefType(const TypedefType *TT);
220bdd1243dSDimitry Andric   void VisitUsingType(const UsingType *TT);
2210b57cec5SDimitry Andric   void VisitFunctionType(const FunctionType *T);
2220b57cec5SDimitry Andric   void VisitFunctionProtoType(const FunctionProtoType *T);
2230b57cec5SDimitry Andric   void VisitRValueReferenceType(const ReferenceType *RT);
2240b57cec5SDimitry Andric   void VisitArrayType(const ArrayType *AT);
2250b57cec5SDimitry Andric   void VisitConstantArrayType(const ConstantArrayType *CAT);
2260b57cec5SDimitry Andric   void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *VT);
2270b57cec5SDimitry Andric   void VisitVectorType(const VectorType *VT);
2280b57cec5SDimitry Andric   void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT);
2290b57cec5SDimitry Andric   void VisitUnaryTransformType(const UnaryTransformType *UTT);
2300b57cec5SDimitry Andric   void VisitTagType(const TagType *TT);
2310b57cec5SDimitry Andric   void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
232bdd1243dSDimitry Andric   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
233bdd1243dSDimitry Andric   void
234bdd1243dSDimitry Andric   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
2350b57cec5SDimitry Andric   void VisitAutoType(const AutoType *AT);
2360b57cec5SDimitry Andric   void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
2370b57cec5SDimitry Andric   void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
2380b57cec5SDimitry Andric   void VisitObjCInterfaceType(const ObjCInterfaceType *OIT);
2390b57cec5SDimitry Andric   void VisitPackExpansionType(const PackExpansionType *PET);
2400b57cec5SDimitry Andric   void VisitElaboratedType(const ElaboratedType *ET);
2410b57cec5SDimitry Andric   void VisitMacroQualifiedType(const MacroQualifiedType *MQT);
2420b57cec5SDimitry Andric   void VisitMemberPointerType(const MemberPointerType *MPT);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   void VisitNamedDecl(const NamedDecl *ND);
2450b57cec5SDimitry Andric   void VisitTypedefDecl(const TypedefDecl *TD);
2460b57cec5SDimitry Andric   void VisitTypeAliasDecl(const TypeAliasDecl *TAD);
2470b57cec5SDimitry Andric   void VisitNamespaceDecl(const NamespaceDecl *ND);
2480b57cec5SDimitry Andric   void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD);
2490b57cec5SDimitry Andric   void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD);
2500b57cec5SDimitry Andric   void VisitUsingDecl(const UsingDecl *UD);
251fe6060f1SDimitry Andric   void VisitUsingEnumDecl(const UsingEnumDecl *UED);
2520b57cec5SDimitry Andric   void VisitUsingShadowDecl(const UsingShadowDecl *USD);
2530b57cec5SDimitry Andric   void VisitVarDecl(const VarDecl *VD);
2540b57cec5SDimitry Andric   void VisitFieldDecl(const FieldDecl *FD);
2550b57cec5SDimitry Andric   void VisitFunctionDecl(const FunctionDecl *FD);
2560b57cec5SDimitry Andric   void VisitEnumDecl(const EnumDecl *ED);
2570b57cec5SDimitry Andric   void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
2580b57cec5SDimitry Andric   void VisitRecordDecl(const RecordDecl *RD);
2590b57cec5SDimitry Andric   void VisitCXXRecordDecl(const CXXRecordDecl *RD);
260bdd1243dSDimitry Andric   void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
2610b57cec5SDimitry Andric   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
2620b57cec5SDimitry Andric   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
2630b57cec5SDimitry Andric   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
2640b57cec5SDimitry Andric   void VisitLinkageSpecDecl(const LinkageSpecDecl *LSD);
2650b57cec5SDimitry Andric   void VisitAccessSpecDecl(const AccessSpecDecl *ASD);
2660b57cec5SDimitry Andric   void VisitFriendDecl(const FriendDecl *FD);
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   void VisitObjCIvarDecl(const ObjCIvarDecl *D);
2690b57cec5SDimitry Andric   void VisitObjCMethodDecl(const ObjCMethodDecl *D);
2700b57cec5SDimitry Andric   void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
2710b57cec5SDimitry Andric   void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
2720b57cec5SDimitry Andric   void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
2730b57cec5SDimitry Andric   void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
2740b57cec5SDimitry Andric   void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
2750b57cec5SDimitry Andric   void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
2760b57cec5SDimitry Andric   void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
2770b57cec5SDimitry Andric   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
2780b57cec5SDimitry Andric   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
2790b57cec5SDimitry Andric   void VisitBlockDecl(const BlockDecl *D);
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   void VisitDeclRefExpr(const DeclRefExpr *DRE);
282fe6060f1SDimitry Andric   void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
2830b57cec5SDimitry Andric   void VisitPredefinedExpr(const PredefinedExpr *PE);
2840b57cec5SDimitry Andric   void VisitUnaryOperator(const UnaryOperator *UO);
2850b57cec5SDimitry Andric   void VisitBinaryOperator(const BinaryOperator *BO);
2860b57cec5SDimitry Andric   void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO);
2870b57cec5SDimitry Andric   void VisitMemberExpr(const MemberExpr *ME);
2885f757f3fSDimitry Andric   void VisitAtomicExpr(const AtomicExpr *AE);
2890b57cec5SDimitry Andric   void VisitCXXNewExpr(const CXXNewExpr *NE);
2900b57cec5SDimitry Andric   void VisitCXXDeleteExpr(const CXXDeleteExpr *DE);
2910b57cec5SDimitry Andric   void VisitCXXThisExpr(const CXXThisExpr *TE);
2920b57cec5SDimitry Andric   void VisitCastExpr(const CastExpr *CE);
2930b57cec5SDimitry Andric   void VisitImplicitCastExpr(const ImplicitCastExpr *ICE);
2940b57cec5SDimitry Andric   void VisitCallExpr(const CallExpr *CE);
2950b57cec5SDimitry Andric   void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *TTE);
2960b57cec5SDimitry Andric   void VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE);
2970b57cec5SDimitry Andric   void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE);
2980b57cec5SDimitry Andric   void VisitAddrLabelExpr(const AddrLabelExpr *ALE);
2990b57cec5SDimitry Andric   void VisitCXXTypeidExpr(const CXXTypeidExpr *CTE);
3000b57cec5SDimitry Andric   void VisitConstantExpr(const ConstantExpr *CE);
3010b57cec5SDimitry Andric   void VisitInitListExpr(const InitListExpr *ILE);
3020b57cec5SDimitry Andric   void VisitGenericSelectionExpr(const GenericSelectionExpr *GSE);
3030b57cec5SDimitry Andric   void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *UCE);
3040b57cec5SDimitry Andric   void VisitCXXConstructExpr(const CXXConstructExpr *CE);
3050b57cec5SDimitry Andric   void VisitExprWithCleanups(const ExprWithCleanups *EWC);
3060b57cec5SDimitry Andric   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE);
3070b57cec5SDimitry Andric   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
3080b57cec5SDimitry Andric   void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME);
309fe6060f1SDimitry Andric   void VisitRequiresExpr(const RequiresExpr *RE);
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE);
3120b57cec5SDimitry Andric   void VisitObjCMessageExpr(const ObjCMessageExpr *OME);
3130b57cec5SDimitry Andric   void VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE);
3140b57cec5SDimitry Andric   void VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE);
3150b57cec5SDimitry Andric   void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE);
3160b57cec5SDimitry Andric   void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE);
3170b57cec5SDimitry Andric   void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *OSRE);
3180b57cec5SDimitry Andric   void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE);
3190b57cec5SDimitry Andric   void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE);
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   void VisitIntegerLiteral(const IntegerLiteral *IL);
3220b57cec5SDimitry Andric   void VisitCharacterLiteral(const CharacterLiteral *CL);
3230b57cec5SDimitry Andric   void VisitFixedPointLiteral(const FixedPointLiteral *FPL);
3240b57cec5SDimitry Andric   void VisitFloatingLiteral(const FloatingLiteral *FL);
3250b57cec5SDimitry Andric   void VisitStringLiteral(const StringLiteral *SL);
3260b57cec5SDimitry Andric   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE);
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   void VisitIfStmt(const IfStmt *IS);
3290b57cec5SDimitry Andric   void VisitSwitchStmt(const SwitchStmt *SS);
3300b57cec5SDimitry Andric   void VisitCaseStmt(const CaseStmt *CS);
3310b57cec5SDimitry Andric   void VisitLabelStmt(const LabelStmt *LS);
3320b57cec5SDimitry Andric   void VisitGotoStmt(const GotoStmt *GS);
3330b57cec5SDimitry Andric   void VisitWhileStmt(const WhileStmt *WS);
3340b57cec5SDimitry Andric   void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS);
33581ad6265SDimitry Andric   void VisitCompoundStmt(const CompoundStmt *IS);
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   void VisitNullTemplateArgument(const TemplateArgument &TA);
3380b57cec5SDimitry Andric   void VisitTypeTemplateArgument(const TemplateArgument &TA);
3390b57cec5SDimitry Andric   void VisitDeclarationTemplateArgument(const TemplateArgument &TA);
3400b57cec5SDimitry Andric   void VisitNullPtrTemplateArgument(const TemplateArgument &TA);
3410b57cec5SDimitry Andric   void VisitIntegralTemplateArgument(const TemplateArgument &TA);
3420b57cec5SDimitry Andric   void VisitTemplateTemplateArgument(const TemplateArgument &TA);
3430b57cec5SDimitry Andric   void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA);
3440b57cec5SDimitry Andric   void VisitExpressionTemplateArgument(const TemplateArgument &TA);
3450b57cec5SDimitry Andric   void VisitPackTemplateArgument(const TemplateArgument &TA);
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   void visitTextComment(const comments::TextComment *C,
3480b57cec5SDimitry Andric                         const comments::FullComment *);
3490b57cec5SDimitry Andric   void visitInlineCommandComment(const comments::InlineCommandComment *C,
3500b57cec5SDimitry Andric                                  const comments::FullComment *);
3510b57cec5SDimitry Andric   void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C,
3520b57cec5SDimitry Andric                                 const comments::FullComment *);
3530b57cec5SDimitry Andric   void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C,
3540b57cec5SDimitry Andric                               const comments::FullComment *);
3550b57cec5SDimitry Andric   void visitBlockCommandComment(const comments::BlockCommandComment *C,
3560b57cec5SDimitry Andric                                 const comments::FullComment *);
3570b57cec5SDimitry Andric   void visitParamCommandComment(const comments::ParamCommandComment *C,
3580b57cec5SDimitry Andric                                 const comments::FullComment *FC);
3590b57cec5SDimitry Andric   void visitTParamCommandComment(const comments::TParamCommandComment *C,
3600b57cec5SDimitry Andric                                  const comments::FullComment *FC);
3610b57cec5SDimitry Andric   void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C,
3620b57cec5SDimitry Andric                                  const comments::FullComment *);
3630b57cec5SDimitry Andric   void
3640b57cec5SDimitry Andric   visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C,
3650b57cec5SDimitry Andric                                 const comments::FullComment *);
3660b57cec5SDimitry Andric   void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
3670b57cec5SDimitry Andric                                 const comments::FullComment *);
3680b57cec5SDimitry Andric };
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> {
3710b57cec5SDimitry Andric   JSONNodeDumper NodeDumper;
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric   template <typename SpecializationDecl>
writeTemplateDeclSpecialization(const SpecializationDecl * SD,bool DumpExplicitInst,bool DumpRefOnly)3740b57cec5SDimitry Andric   void writeTemplateDeclSpecialization(const SpecializationDecl *SD,
3750b57cec5SDimitry Andric                                        bool DumpExplicitInst,
3760b57cec5SDimitry Andric                                        bool DumpRefOnly) {
3770b57cec5SDimitry Andric     bool DumpedAny = false;
3780b57cec5SDimitry Andric     for (const auto *RedeclWithBadType : SD->redecls()) {
3790b57cec5SDimitry Andric       // FIXME: The redecls() range sometimes has elements of a less-specific
3800b57cec5SDimitry Andric       // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
3810b57cec5SDimitry Andric       // us TagDecls, and should give CXXRecordDecls).
3820b57cec5SDimitry Andric       const auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
3830b57cec5SDimitry Andric       if (!Redecl) {
3840b57cec5SDimitry Andric         // Found the injected-class-name for a class template. This will be
3850b57cec5SDimitry Andric         // dumped as part of its surrounding class so we don't need to dump it
3860b57cec5SDimitry Andric         // here.
3870b57cec5SDimitry Andric         assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
3880b57cec5SDimitry Andric                "expected an injected-class-name");
3890b57cec5SDimitry Andric         continue;
3900b57cec5SDimitry Andric       }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric       switch (Redecl->getTemplateSpecializationKind()) {
3930b57cec5SDimitry Andric       case TSK_ExplicitInstantiationDeclaration:
3940b57cec5SDimitry Andric       case TSK_ExplicitInstantiationDefinition:
3950b57cec5SDimitry Andric         if (!DumpExplicitInst)
3960b57cec5SDimitry Andric           break;
397bdd1243dSDimitry Andric         [[fallthrough]];
3980b57cec5SDimitry Andric       case TSK_Undeclared:
3990b57cec5SDimitry Andric       case TSK_ImplicitInstantiation:
4000b57cec5SDimitry Andric         if (DumpRefOnly)
4010b57cec5SDimitry Andric           NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(Redecl); });
4020b57cec5SDimitry Andric         else
4030b57cec5SDimitry Andric           Visit(Redecl);
4040b57cec5SDimitry Andric         DumpedAny = true;
4050b57cec5SDimitry Andric         break;
4060b57cec5SDimitry Andric       case TSK_ExplicitSpecialization:
4070b57cec5SDimitry Andric         break;
4080b57cec5SDimitry Andric       }
4090b57cec5SDimitry Andric     }
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     // Ensure we dump at least one decl for each specialization.
4120b57cec5SDimitry Andric     if (!DumpedAny)
4130b57cec5SDimitry Andric       NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(SD); });
4140b57cec5SDimitry Andric   }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   template <typename TemplateDecl>
writeTemplateDecl(const TemplateDecl * TD,bool DumpExplicitInst)4170b57cec5SDimitry Andric   void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) {
4180b57cec5SDimitry Andric     // FIXME: it would be nice to dump template parameters and specializations
4190b57cec5SDimitry Andric     // to their own named arrays rather than shoving them into the "inner"
4200b57cec5SDimitry Andric     // array. However, template declarations are currently being handled at the
4210b57cec5SDimitry Andric     // wrong "level" of the traversal hierarchy and so it is difficult to
4220b57cec5SDimitry Andric     // achieve without losing information elsewhere.
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric     dumpTemplateParameters(TD->getTemplateParameters());
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric     Visit(TD->getTemplatedDecl());
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric     for (const auto *Child : TD->specializations())
4290b57cec5SDimitry Andric       writeTemplateDeclSpecialization(Child, DumpExplicitInst,
4300b57cec5SDimitry Andric                                       !TD->isCanonicalDecl());
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric public:
JSONDumper(raw_ostream & OS,const SourceManager & SrcMgr,ASTContext & Ctx,const PrintingPolicy & PrintPolicy,const comments::CommandTraits * Traits)4340b57cec5SDimitry Andric   JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
4350b57cec5SDimitry Andric              const PrintingPolicy &PrintPolicy,
4360b57cec5SDimitry Andric              const comments::CommandTraits *Traits)
4370b57cec5SDimitry Andric       : NodeDumper(OS, SrcMgr, Ctx, PrintPolicy, Traits) {}
4380b57cec5SDimitry Andric 
doGetNodeDelegate()4390b57cec5SDimitry Andric   JSONNodeDumper &doGetNodeDelegate() { return NodeDumper; }
4400b57cec5SDimitry Andric 
VisitFunctionTemplateDecl(const FunctionTemplateDecl * FTD)4410b57cec5SDimitry Andric   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
4420b57cec5SDimitry Andric     writeTemplateDecl(FTD, true);
4430b57cec5SDimitry Andric   }
VisitClassTemplateDecl(const ClassTemplateDecl * CTD)4440b57cec5SDimitry Andric   void VisitClassTemplateDecl(const ClassTemplateDecl *CTD) {
4450b57cec5SDimitry Andric     writeTemplateDecl(CTD, false);
4460b57cec5SDimitry Andric   }
VisitVarTemplateDecl(const VarTemplateDecl * VTD)4470b57cec5SDimitry Andric   void VisitVarTemplateDecl(const VarTemplateDecl *VTD) {
4480b57cec5SDimitry Andric     writeTemplateDecl(VTD, false);
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric };
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric } // namespace clang
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric #endif // LLVM_CLANG_AST_JSONNODEDUMPER_H
455