Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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