Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:38

0001 //===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file implements AST dumping of components of individual AST nodes to
0010 // a JSON.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H
0015 #define LLVM_CLANG_AST_JSONNODEDUMPER_H
0016 
0017 #include "clang/AST/ASTContext.h"
0018 #include "clang/AST/ASTDumperUtils.h"
0019 #include "clang/AST/ASTNodeTraverser.h"
0020 #include "clang/AST/AttrVisitor.h"
0021 #include "clang/AST/CommentCommandTraits.h"
0022 #include "clang/AST/CommentVisitor.h"
0023 #include "clang/AST/ExprConcepts.h"
0024 #include "clang/AST/ExprCXX.h"
0025 #include "clang/AST/Mangle.h"
0026 #include "clang/AST/Type.h"
0027 #include "llvm/Support/JSON.h"
0028 
0029 namespace clang {
0030 
0031 class APValue;
0032 
0033 class NodeStreamer {
0034   bool FirstChild = true;
0035   bool TopLevel = true;
0036   llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
0037 
0038 protected:
0039   llvm::json::OStream JOS;
0040 
0041 public:
0042   /// Add a child of the current node.  Calls DoAddChild without arguments
0043   template <typename Fn> void AddChild(Fn DoAddChild) {
0044     return AddChild("", DoAddChild);
0045   }
0046 
0047   /// Add a child of the current node with an optional label.
0048   /// Calls DoAddChild without arguments.
0049   template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) {
0050     // If we're at the top level, there's nothing interesting to do; just
0051     // run the dumper.
0052     if (TopLevel) {
0053       TopLevel = false;
0054       JOS.objectBegin();
0055 
0056       DoAddChild();
0057 
0058       while (!Pending.empty()) {
0059         Pending.back()(true);
0060         Pending.pop_back();
0061       }
0062 
0063       JOS.objectEnd();
0064       TopLevel = true;
0065       return;
0066     }
0067 
0068     // We need to capture an owning-string in the lambda because the lambda
0069     // is invoked in a deferred manner.
0070     std::string LabelStr(!Label.empty() ? Label : "inner");
0071     bool WasFirstChild = FirstChild;
0072     auto DumpWithIndent = [=](bool IsLastChild) {
0073       if (WasFirstChild) {
0074         JOS.attributeBegin(LabelStr);
0075         JOS.arrayBegin();
0076       }
0077 
0078       FirstChild = true;
0079       unsigned Depth = Pending.size();
0080       JOS.objectBegin();
0081 
0082       DoAddChild();
0083 
0084       // If any children are left, they're the last at their nesting level.
0085       // Dump those ones out now.
0086       while (Depth < Pending.size()) {
0087         Pending.back()(true);
0088         this->Pending.pop_back();
0089       }
0090 
0091       JOS.objectEnd();
0092 
0093       if (IsLastChild) {
0094         JOS.arrayEnd();
0095         JOS.attributeEnd();
0096       }
0097     };
0098 
0099     if (FirstChild) {
0100       Pending.push_back(std::move(DumpWithIndent));
0101     } else {
0102       Pending.back()(false);
0103       Pending.back() = std::move(DumpWithIndent);
0104     }
0105     FirstChild = false;
0106   }
0107 
0108   NodeStreamer(raw_ostream &OS) : JOS(OS, 2) {}
0109 };
0110 
0111 // Dumps AST nodes in JSON format. There is no implied stability for the
0112 // content or format of the dump between major releases of Clang, other than it
0113 // being valid JSON output. Further, there is no requirement that the
0114 // information dumped is a complete representation of the AST, only that the
0115 // information presented is correct.
0116 class JSONNodeDumper
0117     : public ConstAttrVisitor<JSONNodeDumper>,
0118       public comments::ConstCommentVisitor<JSONNodeDumper, void,
0119                                            const comments::FullComment *>,
0120       public ConstTemplateArgumentVisitor<JSONNodeDumper>,
0121       public ConstStmtVisitor<JSONNodeDumper>,
0122       public TypeVisitor<JSONNodeDumper>,
0123       public ConstDeclVisitor<JSONNodeDumper>,
0124       public NodeStreamer {
0125   friend class JSONDumper;
0126 
0127   const SourceManager &SM;
0128   ASTContext& Ctx;
0129   ASTNameGenerator ASTNameGen;
0130   PrintingPolicy PrintPolicy;
0131   const comments::CommandTraits *Traits;
0132   StringRef LastLocFilename, LastLocPresumedFilename;
0133   unsigned LastLocLine, LastLocPresumedLine;
0134 
0135   using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>;
0136   using InnerCommentVisitor =
0137       comments::ConstCommentVisitor<JSONNodeDumper, void,
0138                                     const comments::FullComment *>;
0139   using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor<JSONNodeDumper>;
0140   using InnerStmtVisitor = ConstStmtVisitor<JSONNodeDumper>;
0141   using InnerTypeVisitor = TypeVisitor<JSONNodeDumper>;
0142   using InnerDeclVisitor = ConstDeclVisitor<JSONNodeDumper>;
0143 
0144   void attributeOnlyIfTrue(StringRef Key, bool Value) {
0145     if (Value)
0146       JOS.attribute(Key, Value);
0147   }
0148 
0149   void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false);
0150 
0151   // Writes the attributes of a SourceLocation object without.
0152   void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling);
0153 
0154   // Writes the attributes of a SourceLocation to JSON based on its presumed
0155   // spelling location. If the given location represents a macro invocation,
0156   // this outputs two sub-objects: one for the spelling and one for the
0157   // expansion location.
0158   void writeSourceLocation(SourceLocation Loc);
0159   void writeSourceRange(SourceRange R);
0160   std::string createPointerRepresentation(const void *Ptr);
0161   llvm::json::Object createQualType(QualType QT, bool Desugar = true);
0162   llvm::json::Object createBareDeclRef(const Decl *D);
0163   llvm::json::Object createFPOptions(FPOptionsOverride FPO);
0164   void writeBareDeclRef(const Decl *D);
0165   llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD);
0166   llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS);
0167   std::string createAccessSpecifier(AccessSpecifier AS);
0168   llvm::json::Array createCastPath(const CastExpr *C);
0169 
0170   void writePreviousDeclImpl(...) {}
0171 
0172   template <typename T> void writePreviousDeclImpl(const Mergeable<T> *D) {
0173     const T *First = D->getFirstDecl();
0174     if (First != D)
0175       JOS.attribute("firstRedecl", createPointerRepresentation(First));
0176   }
0177 
0178   template <typename T> void writePreviousDeclImpl(const Redeclarable<T> *D) {
0179     const T *Prev = D->getPreviousDecl();
0180     if (Prev)
0181       JOS.attribute("previousDecl", createPointerRepresentation(Prev));
0182   }
0183   void addPreviousDeclaration(const Decl *D);
0184 
0185   StringRef getCommentCommandName(unsigned CommandID) const;
0186 
0187 public:
0188   JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
0189                  const PrintingPolicy &PrintPolicy,
0190                  const comments::CommandTraits *Traits)
0191       : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx),
0192         PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0),
0193         LastLocPresumedLine(0) {}
0194 
0195   void Visit(const Attr *A);
0196   void Visit(const Stmt *Node);
0197   void Visit(const Type *T);
0198   void Visit(QualType T);
0199   void Visit(const Decl *D);
0200   void Visit(TypeLoc TL);
0201 
0202   void Visit(const comments::Comment *C, const comments::FullComment *FC);
0203   void Visit(const TemplateArgument &TA, SourceRange R = {},
0204              const Decl *From = nullptr, StringRef Label = {});
0205   void Visit(const CXXCtorInitializer *Init);
0206   void Visit(const OpenACCClause *C);
0207   void Visit(const OMPClause *C);
0208   void Visit(const BlockDecl::Capture &C);
0209   void Visit(const GenericSelectionExpr::ConstAssociation &A);
0210   void Visit(const concepts::Requirement *R);
0211   void Visit(const APValue &Value, QualType Ty);
0212   void Visit(const ConceptReference *);
0213 
0214   void VisitAliasAttr(const AliasAttr *AA);
0215   void VisitCleanupAttr(const CleanupAttr *CA);
0216   void VisitDeprecatedAttr(const DeprecatedAttr *DA);
0217   void VisitUnavailableAttr(const UnavailableAttr *UA);
0218   void VisitSectionAttr(const SectionAttr *SA);
0219   void VisitVisibilityAttr(const VisibilityAttr *VA);
0220   void VisitTLSModelAttr(const TLSModelAttr *TA);
0221 
0222   void VisitTypedefType(const TypedefType *TT);
0223   void VisitUsingType(const UsingType *TT);
0224   void VisitFunctionType(const FunctionType *T);
0225   void VisitFunctionProtoType(const FunctionProtoType *T);
0226   void VisitRValueReferenceType(const ReferenceType *RT);
0227   void VisitArrayType(const ArrayType *AT);
0228   void VisitConstantArrayType(const ConstantArrayType *CAT);
0229   void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *VT);
0230   void VisitVectorType(const VectorType *VT);
0231   void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT);
0232   void VisitUnaryTransformType(const UnaryTransformType *UTT);
0233   void VisitTagType(const TagType *TT);
0234   void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
0235   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
0236   void
0237   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
0238   void VisitAutoType(const AutoType *AT);
0239   void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
0240   void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
0241   void VisitObjCInterfaceType(const ObjCInterfaceType *OIT);
0242   void VisitPackExpansionType(const PackExpansionType *PET);
0243   void VisitElaboratedType(const ElaboratedType *ET);
0244   void VisitMacroQualifiedType(const MacroQualifiedType *MQT);
0245   void VisitMemberPointerType(const MemberPointerType *MPT);
0246 
0247   void VisitNamedDecl(const NamedDecl *ND);
0248   void VisitTypedefDecl(const TypedefDecl *TD);
0249   void VisitTypeAliasDecl(const TypeAliasDecl *TAD);
0250   void VisitNamespaceDecl(const NamespaceDecl *ND);
0251   void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD);
0252   void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD);
0253   void VisitUsingDecl(const UsingDecl *UD);
0254   void VisitUsingEnumDecl(const UsingEnumDecl *UED);
0255   void VisitUsingShadowDecl(const UsingShadowDecl *USD);
0256   void VisitVarDecl(const VarDecl *VD);
0257   void VisitFieldDecl(const FieldDecl *FD);
0258   void VisitFunctionDecl(const FunctionDecl *FD);
0259   void VisitEnumDecl(const EnumDecl *ED);
0260   void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
0261   void VisitRecordDecl(const RecordDecl *RD);
0262   void VisitCXXRecordDecl(const CXXRecordDecl *RD);
0263   void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
0264   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
0265   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
0266   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
0267   void VisitLinkageSpecDecl(const LinkageSpecDecl *LSD);
0268   void VisitAccessSpecDecl(const AccessSpecDecl *ASD);
0269   void VisitFriendDecl(const FriendDecl *FD);
0270 
0271   void VisitObjCIvarDecl(const ObjCIvarDecl *D);
0272   void VisitObjCMethodDecl(const ObjCMethodDecl *D);
0273   void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
0274   void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
0275   void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
0276   void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
0277   void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
0278   void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
0279   void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
0280   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
0281   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
0282   void VisitBlockDecl(const BlockDecl *D);
0283 
0284   void VisitDeclRefExpr(const DeclRefExpr *DRE);
0285   void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
0286   void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *E);
0287   void VisitPredefinedExpr(const PredefinedExpr *PE);
0288   void VisitUnaryOperator(const UnaryOperator *UO);
0289   void VisitBinaryOperator(const BinaryOperator *BO);
0290   void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO);
0291   void VisitMemberExpr(const MemberExpr *ME);
0292   void VisitAtomicExpr(const AtomicExpr *AE);
0293   void VisitCXXNewExpr(const CXXNewExpr *NE);
0294   void VisitCXXDeleteExpr(const CXXDeleteExpr *DE);
0295   void VisitCXXThisExpr(const CXXThisExpr *TE);
0296   void VisitCastExpr(const CastExpr *CE);
0297   void VisitImplicitCastExpr(const ImplicitCastExpr *ICE);
0298   void VisitCallExpr(const CallExpr *CE);
0299   void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *TTE);
0300   void VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE);
0301   void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE);
0302   void VisitAddrLabelExpr(const AddrLabelExpr *ALE);
0303   void VisitCXXTypeidExpr(const CXXTypeidExpr *CTE);
0304   void VisitConstantExpr(const ConstantExpr *CE);
0305   void VisitInitListExpr(const InitListExpr *ILE);
0306   void VisitGenericSelectionExpr(const GenericSelectionExpr *GSE);
0307   void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *UCE);
0308   void VisitCXXConstructExpr(const CXXConstructExpr *CE);
0309   void VisitExprWithCleanups(const ExprWithCleanups *EWC);
0310   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE);
0311   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
0312   void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME);
0313   void VisitRequiresExpr(const RequiresExpr *RE);
0314   void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node);
0315   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node);
0316 
0317   void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE);
0318   void VisitObjCMessageExpr(const ObjCMessageExpr *OME);
0319   void VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE);
0320   void VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE);
0321   void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE);
0322   void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE);
0323   void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *OSRE);
0324   void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE);
0325   void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE);
0326 
0327   void VisitIntegerLiteral(const IntegerLiteral *IL);
0328   void VisitCharacterLiteral(const CharacterLiteral *CL);
0329   void VisitFixedPointLiteral(const FixedPointLiteral *FPL);
0330   void VisitFloatingLiteral(const FloatingLiteral *FL);
0331   void VisitStringLiteral(const StringLiteral *SL);
0332   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE);
0333 
0334   void VisitIfStmt(const IfStmt *IS);
0335   void VisitSwitchStmt(const SwitchStmt *SS);
0336   void VisitCaseStmt(const CaseStmt *CS);
0337   void VisitLabelStmt(const LabelStmt *LS);
0338   void VisitGotoStmt(const GotoStmt *GS);
0339   void VisitWhileStmt(const WhileStmt *WS);
0340   void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS);
0341   void VisitCompoundStmt(const CompoundStmt *IS);
0342 
0343   void VisitNullTemplateArgument(const TemplateArgument &TA);
0344   void VisitTypeTemplateArgument(const TemplateArgument &TA);
0345   void VisitDeclarationTemplateArgument(const TemplateArgument &TA);
0346   void VisitNullPtrTemplateArgument(const TemplateArgument &TA);
0347   void VisitIntegralTemplateArgument(const TemplateArgument &TA);
0348   void VisitTemplateTemplateArgument(const TemplateArgument &TA);
0349   void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA);
0350   void VisitExpressionTemplateArgument(const TemplateArgument &TA);
0351   void VisitPackTemplateArgument(const TemplateArgument &TA);
0352 
0353   void visitTextComment(const comments::TextComment *C,
0354                         const comments::FullComment *);
0355   void visitInlineCommandComment(const comments::InlineCommandComment *C,
0356                                  const comments::FullComment *);
0357   void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C,
0358                                 const comments::FullComment *);
0359   void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C,
0360                               const comments::FullComment *);
0361   void visitBlockCommandComment(const comments::BlockCommandComment *C,
0362                                 const comments::FullComment *);
0363   void visitParamCommandComment(const comments::ParamCommandComment *C,
0364                                 const comments::FullComment *FC);
0365   void visitTParamCommandComment(const comments::TParamCommandComment *C,
0366                                  const comments::FullComment *FC);
0367   void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C,
0368                                  const comments::FullComment *);
0369   void
0370   visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C,
0371                                 const comments::FullComment *);
0372   void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
0373                                 const comments::FullComment *);
0374 };
0375 
0376 class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> {
0377   JSONNodeDumper NodeDumper;
0378 
0379   template <typename SpecializationDecl>
0380   void writeTemplateDeclSpecialization(const SpecializationDecl *SD,
0381                                        bool DumpExplicitInst,
0382                                        bool DumpRefOnly) {
0383     bool DumpedAny = false;
0384     for (const auto *RedeclWithBadType : SD->redecls()) {
0385       // FIXME: The redecls() range sometimes has elements of a less-specific
0386       // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
0387       // us TagDecls, and should give CXXRecordDecls).
0388       const auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
0389       if (!Redecl) {
0390         // Found the injected-class-name for a class template. This will be
0391         // dumped as part of its surrounding class so we don't need to dump it
0392         // here.
0393         assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
0394                "expected an injected-class-name");
0395         continue;
0396       }
0397 
0398       switch (Redecl->getTemplateSpecializationKind()) {
0399       case TSK_ExplicitInstantiationDeclaration:
0400       case TSK_ExplicitInstantiationDefinition:
0401         if (!DumpExplicitInst)
0402           break;
0403         [[fallthrough]];
0404       case TSK_Undeclared:
0405       case TSK_ImplicitInstantiation:
0406         if (DumpRefOnly)
0407           NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(Redecl); });
0408         else
0409           Visit(Redecl);
0410         DumpedAny = true;
0411         break;
0412       case TSK_ExplicitSpecialization:
0413         break;
0414       }
0415     }
0416 
0417     // Ensure we dump at least one decl for each specialization.
0418     if (!DumpedAny)
0419       NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(SD); });
0420   }
0421 
0422   template <typename TemplateDecl>
0423   void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) {
0424     // FIXME: it would be nice to dump template parameters and specializations
0425     // to their own named arrays rather than shoving them into the "inner"
0426     // array. However, template declarations are currently being handled at the
0427     // wrong "level" of the traversal hierarchy and so it is difficult to
0428     // achieve without losing information elsewhere.
0429 
0430     dumpTemplateParameters(TD->getTemplateParameters());
0431 
0432     Visit(TD->getTemplatedDecl());
0433 
0434     for (const auto *Child : TD->specializations())
0435       writeTemplateDeclSpecialization(Child, DumpExplicitInst,
0436                                       !TD->isCanonicalDecl());
0437   }
0438 
0439 public:
0440   JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
0441              const PrintingPolicy &PrintPolicy,
0442              const comments::CommandTraits *Traits)
0443       : NodeDumper(OS, SrcMgr, Ctx, PrintPolicy, Traits) {}
0444 
0445   JSONNodeDumper &doGetNodeDelegate() { return NodeDumper; }
0446 
0447   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
0448     writeTemplateDecl(FTD, true);
0449   }
0450   void VisitClassTemplateDecl(const ClassTemplateDecl *CTD) {
0451     writeTemplateDecl(CTD, false);
0452   }
0453   void VisitVarTemplateDecl(const VarTemplateDecl *VTD) {
0454     writeTemplateDecl(VTD, false);
0455   }
0456 };
0457 
0458 } // namespace clang
0459 
0460 #endif // LLVM_CLANG_AST_JSONNODEDUMPER_H