Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements AST dumping of components of individual AST nodes to
  10. // a JSON.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H
  15. #define LLVM_CLANG_AST_JSONNODEDUMPER_H
  16.  
  17. #include "clang/AST/ASTContext.h"
  18. #include "clang/AST/ASTDumperUtils.h"
  19. #include "clang/AST/ASTNodeTraverser.h"
  20. #include "clang/AST/AttrVisitor.h"
  21. #include "clang/AST/CommentCommandTraits.h"
  22. #include "clang/AST/CommentVisitor.h"
  23. #include "clang/AST/ExprConcepts.h"
  24. #include "clang/AST/ExprCXX.h"
  25. #include "clang/AST/Mangle.h"
  26. #include "clang/AST/Type.h"
  27. #include "llvm/Support/JSON.h"
  28.  
  29. namespace clang {
  30.  
  31. class APValue;
  32.  
  33. class NodeStreamer {
  34.   bool FirstChild = true;
  35.   bool TopLevel = true;
  36.   llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
  37.  
  38. protected:
  39.   llvm::json::OStream JOS;
  40.  
  41. public:
  42.   /// Add a child of the current node.  Calls DoAddChild without arguments
  43.   template <typename Fn> void AddChild(Fn DoAddChild) {
  44.     return AddChild("", DoAddChild);
  45.   }
  46.  
  47.   /// Add a child of the current node with an optional label.
  48.   /// Calls DoAddChild without arguments.
  49.   template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) {
  50.     // If we're at the top level, there's nothing interesting to do; just
  51.     // run the dumper.
  52.     if (TopLevel) {
  53.       TopLevel = false;
  54.       JOS.objectBegin();
  55.  
  56.       DoAddChild();
  57.  
  58.       while (!Pending.empty()) {
  59.         Pending.back()(true);
  60.         Pending.pop_back();
  61.       }
  62.  
  63.       JOS.objectEnd();
  64.       TopLevel = true;
  65.       return;
  66.     }
  67.  
  68.     // We need to capture an owning-string in the lambda because the lambda
  69.     // is invoked in a deferred manner.
  70.     std::string LabelStr(!Label.empty() ? Label : "inner");
  71.     bool WasFirstChild = FirstChild;
  72.     auto DumpWithIndent = [=](bool IsLastChild) {
  73.       if (WasFirstChild) {
  74.         JOS.attributeBegin(LabelStr);
  75.         JOS.arrayBegin();
  76.       }
  77.  
  78.       FirstChild = true;
  79.       unsigned Depth = Pending.size();
  80.       JOS.objectBegin();
  81.  
  82.       DoAddChild();
  83.  
  84.       // If any children are left, they're the last at their nesting level.
  85.       // Dump those ones out now.
  86.       while (Depth < Pending.size()) {
  87.         Pending.back()(true);
  88.         this->Pending.pop_back();
  89.       }
  90.  
  91.       JOS.objectEnd();
  92.  
  93.       if (IsLastChild) {
  94.         JOS.arrayEnd();
  95.         JOS.attributeEnd();
  96.       }
  97.     };
  98.  
  99.     if (FirstChild) {
  100.       Pending.push_back(std::move(DumpWithIndent));
  101.     } else {
  102.       Pending.back()(false);
  103.       Pending.back() = std::move(DumpWithIndent);
  104.     }
  105.     FirstChild = false;
  106.   }
  107.  
  108.   NodeStreamer(raw_ostream &OS) : JOS(OS, 2) {}
  109. };
  110.  
  111. // Dumps AST nodes in JSON format. There is no implied stability for the
  112. // content or format of the dump between major releases of Clang, other than it
  113. // being valid JSON output. Further, there is no requirement that the
  114. // information dumped is a complete representation of the AST, only that the
  115. // information presented is correct.
  116. class JSONNodeDumper
  117.     : public ConstAttrVisitor<JSONNodeDumper>,
  118.       public comments::ConstCommentVisitor<JSONNodeDumper, void,
  119.                                            const comments::FullComment *>,
  120.       public ConstTemplateArgumentVisitor<JSONNodeDumper>,
  121.       public ConstStmtVisitor<JSONNodeDumper>,
  122.       public TypeVisitor<JSONNodeDumper>,
  123.       public ConstDeclVisitor<JSONNodeDumper>,
  124.       public NodeStreamer {
  125.   friend class JSONDumper;
  126.  
  127.   const SourceManager &SM;
  128.   ASTContext& Ctx;
  129.   ASTNameGenerator ASTNameGen;
  130.   PrintingPolicy PrintPolicy;
  131.   const comments::CommandTraits *Traits;
  132.   StringRef LastLocFilename, LastLocPresumedFilename;
  133.   unsigned LastLocLine, LastLocPresumedLine;
  134.  
  135.   using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>;
  136.   using InnerCommentVisitor =
  137.       comments::ConstCommentVisitor<JSONNodeDumper, void,
  138.                                     const comments::FullComment *>;
  139.   using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor<JSONNodeDumper>;
  140.   using InnerStmtVisitor = ConstStmtVisitor<JSONNodeDumper>;
  141.   using InnerTypeVisitor = TypeVisitor<JSONNodeDumper>;
  142.   using InnerDeclVisitor = ConstDeclVisitor<JSONNodeDumper>;
  143.  
  144.   void attributeOnlyIfTrue(StringRef Key, bool Value) {
  145.     if (Value)
  146.       JOS.attribute(Key, Value);
  147.   }
  148.  
  149.   void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false);
  150.  
  151.   // Writes the attributes of a SourceLocation object without.
  152.   void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling);
  153.  
  154.   // Writes the attributes of a SourceLocation to JSON based on its presumed
  155.   // spelling location. If the given location represents a macro invocation,
  156.   // this outputs two sub-objects: one for the spelling and one for the
  157.   // expansion location.
  158.   void writeSourceLocation(SourceLocation Loc);
  159.   void writeSourceRange(SourceRange R);
  160.   std::string createPointerRepresentation(const void *Ptr);
  161.   llvm::json::Object createQualType(QualType QT, bool Desugar = true);
  162.   llvm::json::Object createBareDeclRef(const Decl *D);
  163.   llvm::json::Object createFPOptions(FPOptionsOverride FPO);
  164.   void writeBareDeclRef(const Decl *D);
  165.   llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD);
  166.   llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS);
  167.   std::string createAccessSpecifier(AccessSpecifier AS);
  168.   llvm::json::Array createCastPath(const CastExpr *C);
  169.  
  170.   void writePreviousDeclImpl(...) {}
  171.  
  172.   template <typename T> void writePreviousDeclImpl(const Mergeable<T> *D) {
  173.     const T *First = D->getFirstDecl();
  174.     if (First != D)
  175.       JOS.attribute("firstRedecl", createPointerRepresentation(First));
  176.   }
  177.  
  178.   template <typename T> void writePreviousDeclImpl(const Redeclarable<T> *D) {
  179.     const T *Prev = D->getPreviousDecl();
  180.     if (Prev)
  181.       JOS.attribute("previousDecl", createPointerRepresentation(Prev));
  182.   }
  183.   void addPreviousDeclaration(const Decl *D);
  184.  
  185.   StringRef getCommentCommandName(unsigned CommandID) const;
  186.  
  187. public:
  188.   JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
  189.                  const PrintingPolicy &PrintPolicy,
  190.                  const comments::CommandTraits *Traits)
  191.       : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx),
  192.         PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0),
  193.         LastLocPresumedLine(0) {}
  194.  
  195.   void Visit(const Attr *A);
  196.   void Visit(const Stmt *Node);
  197.   void Visit(const Type *T);
  198.   void Visit(QualType T);
  199.   void Visit(const Decl *D);
  200.  
  201.   void Visit(const comments::Comment *C, const comments::FullComment *FC);
  202.   void Visit(const TemplateArgument &TA, SourceRange R = {},
  203.              const Decl *From = nullptr, StringRef Label = {});
  204.   void Visit(const CXXCtorInitializer *Init);
  205.   void Visit(const OMPClause *C);
  206.   void Visit(const BlockDecl::Capture &C);
  207.   void Visit(const GenericSelectionExpr::ConstAssociation &A);
  208.   void Visit(const concepts::Requirement *R);
  209.   void Visit(const APValue &Value, QualType Ty);
  210.  
  211.   void VisitTypedefType(const TypedefType *TT);
  212.   void VisitUsingType(const UsingType *TT);
  213.   void VisitFunctionType(const FunctionType *T);
  214.   void VisitFunctionProtoType(const FunctionProtoType *T);
  215.   void VisitRValueReferenceType(const ReferenceType *RT);
  216.   void VisitArrayType(const ArrayType *AT);
  217.   void VisitConstantArrayType(const ConstantArrayType *CAT);
  218.   void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *VT);
  219.   void VisitVectorType(const VectorType *VT);
  220.   void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT);
  221.   void VisitUnaryTransformType(const UnaryTransformType *UTT);
  222.   void VisitTagType(const TagType *TT);
  223.   void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
  224.   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
  225.   void
  226.   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
  227.   void VisitAutoType(const AutoType *AT);
  228.   void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
  229.   void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
  230.   void VisitObjCInterfaceType(const ObjCInterfaceType *OIT);
  231.   void VisitPackExpansionType(const PackExpansionType *PET);
  232.   void VisitElaboratedType(const ElaboratedType *ET);
  233.   void VisitMacroQualifiedType(const MacroQualifiedType *MQT);
  234.   void VisitMemberPointerType(const MemberPointerType *MPT);
  235.  
  236.   void VisitNamedDecl(const NamedDecl *ND);
  237.   void VisitTypedefDecl(const TypedefDecl *TD);
  238.   void VisitTypeAliasDecl(const TypeAliasDecl *TAD);
  239.   void VisitNamespaceDecl(const NamespaceDecl *ND);
  240.   void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD);
  241.   void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD);
  242.   void VisitUsingDecl(const UsingDecl *UD);
  243.   void VisitUsingEnumDecl(const UsingEnumDecl *UED);
  244.   void VisitUsingShadowDecl(const UsingShadowDecl *USD);
  245.   void VisitVarDecl(const VarDecl *VD);
  246.   void VisitFieldDecl(const FieldDecl *FD);
  247.   void VisitFunctionDecl(const FunctionDecl *FD);
  248.   void VisitEnumDecl(const EnumDecl *ED);
  249.   void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
  250.   void VisitRecordDecl(const RecordDecl *RD);
  251.   void VisitCXXRecordDecl(const CXXRecordDecl *RD);
  252.   void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
  253.   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
  254.   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
  255.   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
  256.   void VisitLinkageSpecDecl(const LinkageSpecDecl *LSD);
  257.   void VisitAccessSpecDecl(const AccessSpecDecl *ASD);
  258.   void VisitFriendDecl(const FriendDecl *FD);
  259.  
  260.   void VisitObjCIvarDecl(const ObjCIvarDecl *D);
  261.   void VisitObjCMethodDecl(const ObjCMethodDecl *D);
  262.   void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
  263.   void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
  264.   void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
  265.   void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
  266.   void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
  267.   void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
  268.   void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
  269.   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
  270.   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
  271.   void VisitBlockDecl(const BlockDecl *D);
  272.  
  273.   void VisitDeclRefExpr(const DeclRefExpr *DRE);
  274.   void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
  275.   void VisitPredefinedExpr(const PredefinedExpr *PE);
  276.   void VisitUnaryOperator(const UnaryOperator *UO);
  277.   void VisitBinaryOperator(const BinaryOperator *BO);
  278.   void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO);
  279.   void VisitMemberExpr(const MemberExpr *ME);
  280.   void VisitCXXNewExpr(const CXXNewExpr *NE);
  281.   void VisitCXXDeleteExpr(const CXXDeleteExpr *DE);
  282.   void VisitCXXThisExpr(const CXXThisExpr *TE);
  283.   void VisitCastExpr(const CastExpr *CE);
  284.   void VisitImplicitCastExpr(const ImplicitCastExpr *ICE);
  285.   void VisitCallExpr(const CallExpr *CE);
  286.   void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *TTE);
  287.   void VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE);
  288.   void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE);
  289.   void VisitAddrLabelExpr(const AddrLabelExpr *ALE);
  290.   void VisitCXXTypeidExpr(const CXXTypeidExpr *CTE);
  291.   void VisitConstantExpr(const ConstantExpr *CE);
  292.   void VisitInitListExpr(const InitListExpr *ILE);
  293.   void VisitGenericSelectionExpr(const GenericSelectionExpr *GSE);
  294.   void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *UCE);
  295.   void VisitCXXConstructExpr(const CXXConstructExpr *CE);
  296.   void VisitExprWithCleanups(const ExprWithCleanups *EWC);
  297.   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE);
  298.   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
  299.   void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME);
  300.   void VisitRequiresExpr(const RequiresExpr *RE);
  301.  
  302.   void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE);
  303.   void VisitObjCMessageExpr(const ObjCMessageExpr *OME);
  304.   void VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE);
  305.   void VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE);
  306.   void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE);
  307.   void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE);
  308.   void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *OSRE);
  309.   void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE);
  310.   void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE);
  311.  
  312.   void VisitIntegerLiteral(const IntegerLiteral *IL);
  313.   void VisitCharacterLiteral(const CharacterLiteral *CL);
  314.   void VisitFixedPointLiteral(const FixedPointLiteral *FPL);
  315.   void VisitFloatingLiteral(const FloatingLiteral *FL);
  316.   void VisitStringLiteral(const StringLiteral *SL);
  317.   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE);
  318.  
  319.   void VisitIfStmt(const IfStmt *IS);
  320.   void VisitSwitchStmt(const SwitchStmt *SS);
  321.   void VisitCaseStmt(const CaseStmt *CS);
  322.   void VisitLabelStmt(const LabelStmt *LS);
  323.   void VisitGotoStmt(const GotoStmt *GS);
  324.   void VisitWhileStmt(const WhileStmt *WS);
  325.   void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS);
  326.   void VisitCompoundStmt(const CompoundStmt *IS);
  327.  
  328.   void VisitNullTemplateArgument(const TemplateArgument &TA);
  329.   void VisitTypeTemplateArgument(const TemplateArgument &TA);
  330.   void VisitDeclarationTemplateArgument(const TemplateArgument &TA);
  331.   void VisitNullPtrTemplateArgument(const TemplateArgument &TA);
  332.   void VisitIntegralTemplateArgument(const TemplateArgument &TA);
  333.   void VisitTemplateTemplateArgument(const TemplateArgument &TA);
  334.   void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA);
  335.   void VisitExpressionTemplateArgument(const TemplateArgument &TA);
  336.   void VisitPackTemplateArgument(const TemplateArgument &TA);
  337.  
  338.   void visitTextComment(const comments::TextComment *C,
  339.                         const comments::FullComment *);
  340.   void visitInlineCommandComment(const comments::InlineCommandComment *C,
  341.                                  const comments::FullComment *);
  342.   void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C,
  343.                                 const comments::FullComment *);
  344.   void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C,
  345.                               const comments::FullComment *);
  346.   void visitBlockCommandComment(const comments::BlockCommandComment *C,
  347.                                 const comments::FullComment *);
  348.   void visitParamCommandComment(const comments::ParamCommandComment *C,
  349.                                 const comments::FullComment *FC);
  350.   void visitTParamCommandComment(const comments::TParamCommandComment *C,
  351.                                  const comments::FullComment *FC);
  352.   void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C,
  353.                                  const comments::FullComment *);
  354.   void
  355.   visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C,
  356.                                 const comments::FullComment *);
  357.   void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
  358.                                 const comments::FullComment *);
  359. };
  360.  
  361. class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> {
  362.   JSONNodeDumper NodeDumper;
  363.  
  364.   template <typename SpecializationDecl>
  365.   void writeTemplateDeclSpecialization(const SpecializationDecl *SD,
  366.                                        bool DumpExplicitInst,
  367.                                        bool DumpRefOnly) {
  368.     bool DumpedAny = false;
  369.     for (const auto *RedeclWithBadType : SD->redecls()) {
  370.       // FIXME: The redecls() range sometimes has elements of a less-specific
  371.       // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
  372.       // us TagDecls, and should give CXXRecordDecls).
  373.       const auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
  374.       if (!Redecl) {
  375.         // Found the injected-class-name for a class template. This will be
  376.         // dumped as part of its surrounding class so we don't need to dump it
  377.         // here.
  378.         assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
  379.                "expected an injected-class-name");
  380.         continue;
  381.       }
  382.  
  383.       switch (Redecl->getTemplateSpecializationKind()) {
  384.       case TSK_ExplicitInstantiationDeclaration:
  385.       case TSK_ExplicitInstantiationDefinition:
  386.         if (!DumpExplicitInst)
  387.           break;
  388.         [[fallthrough]];
  389.       case TSK_Undeclared:
  390.       case TSK_ImplicitInstantiation:
  391.         if (DumpRefOnly)
  392.           NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(Redecl); });
  393.         else
  394.           Visit(Redecl);
  395.         DumpedAny = true;
  396.         break;
  397.       case TSK_ExplicitSpecialization:
  398.         break;
  399.       }
  400.     }
  401.  
  402.     // Ensure we dump at least one decl for each specialization.
  403.     if (!DumpedAny)
  404.       NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(SD); });
  405.   }
  406.  
  407.   template <typename TemplateDecl>
  408.   void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) {
  409.     // FIXME: it would be nice to dump template parameters and specializations
  410.     // to their own named arrays rather than shoving them into the "inner"
  411.     // array. However, template declarations are currently being handled at the
  412.     // wrong "level" of the traversal hierarchy and so it is difficult to
  413.     // achieve without losing information elsewhere.
  414.  
  415.     dumpTemplateParameters(TD->getTemplateParameters());
  416.  
  417.     Visit(TD->getTemplatedDecl());
  418.  
  419.     for (const auto *Child : TD->specializations())
  420.       writeTemplateDeclSpecialization(Child, DumpExplicitInst,
  421.                                       !TD->isCanonicalDecl());
  422.   }
  423.  
  424. public:
  425.   JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
  426.              const PrintingPolicy &PrintPolicy,
  427.              const comments::CommandTraits *Traits)
  428.       : NodeDumper(OS, SrcMgr, Ctx, PrintPolicy, Traits) {}
  429.  
  430.   JSONNodeDumper &doGetNodeDelegate() { return NodeDumper; }
  431.  
  432.   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
  433.     writeTemplateDecl(FTD, true);
  434.   }
  435.   void VisitClassTemplateDecl(const ClassTemplateDecl *CTD) {
  436.     writeTemplateDecl(CTD, false);
  437.   }
  438.   void VisitVarTemplateDecl(const VarTemplateDecl *VTD) {
  439.     writeTemplateDecl(VTD, false);
  440.   }
  441. };
  442.  
  443. } // namespace clang
  444.  
  445. #endif // LLVM_CLANG_AST_JSONNODEDUMPER_H
  446.