llvm-project

Форк
0
/
ASTDumper.cpp 
395 строк · 13.6 Кб
1
//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
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 the AST dump methods, which dump out the
10
// AST in a form that exposes type details and other fields.
11
//
12
//===----------------------------------------------------------------------===//
13

14
#include "clang/AST/ASTDumper.h"
15
#include "clang/AST/ASTConcept.h"
16
#include "clang/AST/ASTContext.h"
17
#include "clang/AST/DeclLookups.h"
18
#include "clang/AST/JSONNodeDumper.h"
19
#include "clang/Basic/Builtins.h"
20
#include "clang/Basic/SourceManager.h"
21
#include "llvm/Support/raw_ostream.h"
22

23
using namespace clang;
24
using namespace clang::comments;
25

26
void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {
27
  NodeDumper.AddChild([=] {
28
    if (!DC) {
29
      ColorScope Color(OS, ShowColors, NullColor);
30
      OS << "<<<NULL>>>";
31
      return;
32
    }
33
    // An invalid DeclContext is one for which a dyn_cast() from a DeclContext
34
    // pointer to a Decl pointer would fail an assertion or otherwise fall prey
35
    // to undefined behavior as a result of an invalid associated DeclKind.
36
    // Such invalidity is not supposed to happen of course, but, when it does,
37
    // the information provided below is intended to provide some hints about
38
    // what might have gone awry.
39
    {
40
      ColorScope Color(OS, ShowColors, DeclKindNameColor);
41
      OS << "DeclContext";
42
    }
43
    NodeDumper.dumpPointer(DC);
44
    OS << " <";
45
    {
46
      ColorScope Color(OS, ShowColors, DeclNameColor);
47
      OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();
48
    }
49
    OS << ">";
50
  });
51
}
52

53
void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
54
  NodeDumper.AddChild([=] {
55
    OS << "StoredDeclsMap ";
56
    NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
57

58
    const DeclContext *Primary = DC->getPrimaryContext();
59
    if (Primary != DC) {
60
      OS << " primary";
61
      NodeDumper.dumpPointer(cast<Decl>(Primary));
62
    }
63

64
    bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
65

66
    auto Range = getDeserialize()
67
                     ? Primary->lookups()
68
                     : Primary->noload_lookups(/*PreserveInternalState=*/true);
69
    for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
70
      DeclarationName Name = I.getLookupName();
71
      DeclContextLookupResult R = *I;
72

73
      NodeDumper.AddChild([=] {
74
        OS << "DeclarationName ";
75
        {
76
          ColorScope Color(OS, ShowColors, DeclNameColor);
77
          OS << '\'' << Name << '\'';
78
        }
79

80
        for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
81
             RI != RE; ++RI) {
82
          NodeDumper.AddChild([=] {
83
            NodeDumper.dumpBareDeclRef(*RI);
84

85
            if (!(*RI)->isUnconditionallyVisible())
86
              OS << " hidden";
87

88
            // If requested, dump the redecl chain for this lookup.
89
            if (DumpDecls) {
90
              // Dump earliest decl first.
91
              std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
92
                if (Decl *Prev = D->getPreviousDecl())
93
                  DumpWithPrev(Prev);
94
                Visit(D);
95
              };
96
              DumpWithPrev(*RI);
97
            }
98
          });
99
        }
100
      });
101
    }
102

103
    if (HasUndeserializedLookups) {
104
      NodeDumper.AddChild([=] {
105
        ColorScope Color(OS, ShowColors, UndeserializedColor);
106
        OS << "<undeserialized lookups>";
107
      });
108
    }
109
  });
110
}
111

112
template <typename SpecializationDecl>
113
void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
114
                                               bool DumpExplicitInst,
115
                                               bool DumpRefOnly) {
116
  bool DumpedAny = false;
117
  for (const auto *RedeclWithBadType : D->redecls()) {
118
    // FIXME: The redecls() range sometimes has elements of a less-specific
119
    // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
120
    // us TagDecls, and should give CXXRecordDecls).
121
    auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);
122
    switch (Redecl->getTemplateSpecializationKind()) {
123
    case TSK_ExplicitInstantiationDeclaration:
124
    case TSK_ExplicitInstantiationDefinition:
125
      if (!DumpExplicitInst)
126
        break;
127
      [[fallthrough]];
128
    case TSK_Undeclared:
129
    case TSK_ImplicitInstantiation:
130
      if (DumpRefOnly)
131
        NodeDumper.dumpDeclRef(Redecl);
132
      else
133
        Visit(Redecl);
134
      DumpedAny = true;
135
      break;
136
    case TSK_ExplicitSpecialization:
137
      break;
138
    }
139
  }
140

141
  // Ensure we dump at least one decl for each specialization.
142
  if (!DumpedAny)
143
    NodeDumper.dumpDeclRef(D);
144
}
145

146
template <typename TemplateDecl>
147
void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
148
  dumpTemplateParameters(D->getTemplateParameters());
149

150
  Visit(D->getTemplatedDecl());
151

152
  if (GetTraversalKind() == TK_AsIs) {
153
    for (const auto *Child : D->specializations())
154
      dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
155
                                     !D->isCanonicalDecl());
156
  }
157
}
158

159
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
160
  // FIXME: We don't add a declaration of a function template specialization
161
  // to its context when it's explicitly instantiated, so dump explicit
162
  // instantiations when we dump the template itself.
163
  dumpTemplateDecl(D, true);
164
}
165

166
void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
167
  dumpTemplateDecl(D, false);
168
}
169

170
void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
171
  dumpTemplateDecl(D, false);
172
}
173

174
//===----------------------------------------------------------------------===//
175
// Type method implementations
176
//===----------------------------------------------------------------------===//
177

178
void QualType::dump(const char *msg) const {
179
  if (msg)
180
    llvm::errs() << msg << ": ";
181
  dump();
182
}
183

184
LLVM_DUMP_METHOD void QualType::dump() const {
185
  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
186
  Dumper.Visit(*this);
187
}
188

189
LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
190
                                     const ASTContext &Context) const {
191
  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
192
  Dumper.Visit(*this);
193
}
194

195
LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
196

197
LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
198
                                 const ASTContext &Context) const {
199
  QualType(this, 0).dump(OS, Context);
200
}
201

202
//===----------------------------------------------------------------------===//
203
// TypeLoc method implementations
204
//===----------------------------------------------------------------------===//
205

206
LLVM_DUMP_METHOD void TypeLoc::dump() const {
207
  ASTDumper(llvm::errs(), /*ShowColors=*/false).Visit(*this);
208
}
209

210
LLVM_DUMP_METHOD void TypeLoc::dump(llvm::raw_ostream &OS,
211
                                    const ASTContext &Context) const {
212
  ASTDumper(OS, Context, Context.getDiagnostics().getShowColors()).Visit(*this);
213
}
214

215
//===----------------------------------------------------------------------===//
216
// Decl method implementations
217
//===----------------------------------------------------------------------===//
218

219
LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
220

221
LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
222
                                 ASTDumpOutputFormat Format) const {
223
  ASTContext &Ctx = getASTContext();
224
  const SourceManager &SM = Ctx.getSourceManager();
225

226
  if (ADOF_JSON == Format) {
227
    JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
228
                 &Ctx.getCommentCommandTraits());
229
    (void)Deserialize; // FIXME?
230
    P.Visit(this);
231
  } else {
232
    ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
233
    P.setDeserialize(Deserialize);
234
    P.Visit(this);
235
  }
236
}
237

238
LLVM_DUMP_METHOD void Decl::dumpColor() const {
239
  const ASTContext &Ctx = getASTContext();
240
  ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
241
  P.Visit(this);
242
}
243

244
LLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {
245
  dumpAsDecl(nullptr);
246
}
247

248
LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {
249
  // By design, DeclContext is required to be a base class of some class that
250
  // derives from Decl. Thus, it should always be possible to dyn_cast() from
251
  // a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()
252
  // asserts that to be the case. Since this function is intended for use in a
253
  // debugger, it performs an additional check in order to prevent a failed
254
  // cast and assertion. If that check fails, then the (invalid) DeclContext
255
  // is dumped with an indication of its invalidity.
256
  if (hasValidDeclKind()) {
257
    const auto *D = cast<Decl>(this);
258
    D->dump();
259
  } else {
260
    // If an ASTContext is not available, a less capable ASTDumper is
261
    // constructed for which color diagnostics are, regrettably, disabled.
262
    ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,
263
                                  Ctx->getDiagnostics().getShowColors())
264
                      : ASTDumper(llvm::errs(), /*ShowColors*/ false);
265
    P.dumpInvalidDeclContext(this);
266
  }
267
}
268

269
LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
270
  dumpLookups(llvm::errs());
271
}
272

273
LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
274
                                               bool DumpDecls,
275
                                               bool Deserialize) const {
276
  const DeclContext *DC = this;
277
  while (!DC->isTranslationUnit())
278
    DC = DC->getParent();
279
  const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
280
  ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
281
  P.setDeserialize(Deserialize);
282
  P.dumpLookups(this, DumpDecls);
283
}
284

285
//===----------------------------------------------------------------------===//
286
// Stmt method implementations
287
//===----------------------------------------------------------------------===//
288

289
LLVM_DUMP_METHOD void Stmt::dump() const {
290
  ASTDumper P(llvm::errs(), /*ShowColors=*/false);
291
  P.Visit(this);
292
}
293

294
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
295
                                 const ASTContext &Context) const {
296
  ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
297
  P.Visit(this);
298
}
299

300
LLVM_DUMP_METHOD void Stmt::dumpColor() const {
301
  ASTDumper P(llvm::errs(), /*ShowColors=*/true);
302
  P.Visit(this);
303
}
304

305
//===----------------------------------------------------------------------===//
306
// Comment method implementations
307
//===----------------------------------------------------------------------===//
308

309
LLVM_DUMP_METHOD void Comment::dump() const {
310
  const auto *FC = dyn_cast<FullComment>(this);
311
  if (!FC)
312
    return;
313
  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
314
  Dumper.Visit(FC, FC);
315
}
316

317
LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
318
                                    const ASTContext &Context) const {
319
  const auto *FC = dyn_cast<FullComment>(this);
320
  if (!FC)
321
    return;
322
  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
323
  Dumper.Visit(FC, FC);
324
}
325

326
LLVM_DUMP_METHOD void Comment::dumpColor() const {
327
  const auto *FC = dyn_cast<FullComment>(this);
328
  if (!FC)
329
    return;
330
  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
331
  Dumper.Visit(FC, FC);
332
}
333

334
//===----------------------------------------------------------------------===//
335
// APValue method implementations
336
//===----------------------------------------------------------------------===//
337

338
LLVM_DUMP_METHOD void APValue::dump() const {
339
  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
340
  Dumper.Visit(*this, /*Ty=*/QualType());
341
}
342

343
LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
344
                                    const ASTContext &Context) const {
345
  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
346
  Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
347
}
348

349
//===----------------------------------------------------------------------===//
350
// ConceptReference method implementations
351
//===----------------------------------------------------------------------===//
352

353
LLVM_DUMP_METHOD void ConceptReference::dump() const {
354
  dump(llvm::errs());
355
}
356

357
LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const {
358
  auto &Ctx = getNamedConcept()->getASTContext();
359
  ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
360
  P.Visit(this);
361
}
362

363
//===----------------------------------------------------------------------===//
364
// TemplateName method implementations
365
//===----------------------------------------------------------------------===//
366

367
// FIXME: These are actually using the TemplateArgument dumper, through
368
// an implicit conversion. The dump will claim this is a template argument,
369
// which is misleading.
370

371
LLVM_DUMP_METHOD void TemplateName::dump() const {
372
  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
373
  Dumper.Visit(*this);
374
}
375

376
LLVM_DUMP_METHOD void TemplateName::dump(llvm::raw_ostream &OS,
377
                                         const ASTContext &Context) const {
378
  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
379
  Dumper.Visit(*this);
380
}
381

382
//===----------------------------------------------------------------------===//
383
// TemplateArgument method implementations
384
//===----------------------------------------------------------------------===//
385

386
LLVM_DUMP_METHOD void TemplateArgument::dump() const {
387
  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
388
  Dumper.Visit(*this);
389
}
390

391
LLVM_DUMP_METHOD void TemplateArgument::dump(llvm::raw_ostream &OS,
392
                                             const ASTContext &Context) const {
393
  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
394
  Dumper.Visit(*this);
395
}
396

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.