clang  7.0.0svn
ASTConsumers.cpp
Go to the documentation of this file.
1 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // AST Consumer Implementations.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/AST.h"
16 #include "clang/AST/ASTConsumer.h"
17 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/RecordLayout.h"
21 #include "clang/Basic/Diagnostic.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/Timer.h"
25 #include "llvm/Support/raw_ostream.h"
26 using namespace clang;
27 
28 //===----------------------------------------------------------------------===//
29 /// ASTPrinter - Pretty-printer and dumper of ASTs
30 
31 namespace {
32  class ASTPrinter : public ASTConsumer,
33  public RecursiveASTVisitor<ASTPrinter> {
35 
36  public:
37  enum Kind { DumpFull, Dump, Print, None };
38  ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K, StringRef FilterString,
39  bool DumpLookups = false)
40  : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
41  OutputKind(K), FilterString(FilterString), DumpLookups(DumpLookups) {}
42 
43  void HandleTranslationUnit(ASTContext &Context) override {
45 
46  if (FilterString.empty())
47  return print(D);
48 
49  TraverseDecl(D);
50  }
51 
52  bool shouldWalkTypesOfTypeLocs() const { return false; }
53 
54  bool TraverseDecl(Decl *D) {
55  if (D && filterMatches(D)) {
56  bool ShowColors = Out.has_colors();
57  if (ShowColors)
58  Out.changeColor(raw_ostream::BLUE);
59  Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
60  << ":\n";
61  if (ShowColors)
62  Out.resetColor();
63  print(D);
64  Out << "\n";
65  // Don't traverse child nodes to avoid output duplication.
66  return true;
67  }
68  return base::TraverseDecl(D);
69  }
70 
71  private:
72  std::string getName(Decl *D) {
73  if (isa<NamedDecl>(D))
74  return cast<NamedDecl>(D)->getQualifiedNameAsString();
75  return "";
76  }
77  bool filterMatches(Decl *D) {
78  return getName(D).find(FilterString) != std::string::npos;
79  }
80  void print(Decl *D) {
81  if (DumpLookups) {
82  if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
83  if (DC == DC->getPrimaryContext())
84  DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
85  else
86  Out << "Lookup map is in primary DeclContext "
87  << DC->getPrimaryContext() << "\n";
88  } else
89  Out << "Not a DeclContext\n";
90  } else if (OutputKind == Print) {
92  D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
93  } else if (OutputKind != None)
94  D->dump(Out, OutputKind == DumpFull);
95  }
96 
97  raw_ostream &Out;
98  std::unique_ptr<raw_ostream> OwnedOut;
99 
100  /// How to output individual declarations.
101  Kind OutputKind;
102 
103  /// Which declarations or DeclContexts to display.
104  std::string FilterString;
105 
106  /// Whether the primary output is lookup results or declarations. Individual
107  /// results will be output with a format determined by OutputKind. This is
108  /// incompatible with OutputKind == Print.
109  bool DumpLookups;
110  };
111 
112  class ASTDeclNodeLister : public ASTConsumer,
113  public RecursiveASTVisitor<ASTDeclNodeLister> {
114  public:
115  ASTDeclNodeLister(raw_ostream *Out = nullptr)
116  : Out(Out ? *Out : llvm::outs()) {}
117 
118  void HandleTranslationUnit(ASTContext &Context) override {
119  TraverseDecl(Context.getTranslationUnitDecl());
120  }
121 
122  bool shouldWalkTypesOfTypeLocs() const { return false; }
123 
124  bool VisitNamedDecl(NamedDecl *D) {
125  D->printQualifiedName(Out);
126  Out << '\n';
127  return true;
128  }
129 
130  private:
131  raw_ostream &Out;
132  };
133 } // end anonymous namespace
134 
135 std::unique_ptr<ASTConsumer>
136 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
137  StringRef FilterString) {
138  return llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
139  FilterString);
140 }
141 
142 std::unique_ptr<ASTConsumer>
143 clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out,
144  StringRef FilterString,
145  bool DumpDecls,
146  bool Deserialize,
147  bool DumpLookups) {
148  assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
149  return llvm::make_unique<ASTPrinter>(std::move(Out),
150  Deserialize ? ASTPrinter::DumpFull :
151  DumpDecls ? ASTPrinter::Dump :
153  FilterString, DumpLookups);
154 }
155 
156 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
157  return llvm::make_unique<ASTDeclNodeLister>(nullptr);
158 }
159 
160 //===----------------------------------------------------------------------===//
161 /// ASTViewer - AST Visualization
162 
163 namespace {
164  class ASTViewer : public ASTConsumer {
165  ASTContext *Context;
166  public:
167  void Initialize(ASTContext &Context) override {
168  this->Context = &Context;
169  }
170 
171  bool HandleTopLevelDecl(DeclGroupRef D) override {
172  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
173  HandleTopLevelSingleDecl(*I);
174  return true;
175  }
176 
177  void HandleTopLevelSingleDecl(Decl *D);
178  };
179 }
180 
181 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
182  if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
183  D->print(llvm::errs());
184 
185  if (Stmt *Body = D->getBody()) {
186  llvm::errs() << '\n';
187  Body->viewAST();
188  llvm::errs() << '\n';
189  }
190  }
191 }
192 
193 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
194  return llvm::make_unique<ASTViewer>();
195 }
196 
197 //===----------------------------------------------------------------------===//
198 /// DeclContextPrinter - Decl and DeclContext Visualization
199 
200 namespace {
201 
202 class DeclContextPrinter : public ASTConsumer {
203  raw_ostream& Out;
204 public:
205  DeclContextPrinter() : Out(llvm::errs()) {}
206 
207  void HandleTranslationUnit(ASTContext &C) override {
209  }
210 
211  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
212 };
213 } // end anonymous namespace
214 
216  unsigned Indentation) {
217  // Print DeclContext name.
218  switch (DC->getDeclKind()) {
219  case Decl::TranslationUnit:
220  Out << "[translation unit] " << DC;
221  break;
222  case Decl::Namespace: {
223  Out << "[namespace] ";
224  const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
225  Out << *ND;
226  break;
227  }
228  case Decl::Enum: {
229  const EnumDecl* ED = cast<EnumDecl>(DC);
230  if (ED->isCompleteDefinition())
231  Out << "[enum] ";
232  else
233  Out << "<enum> ";
234  Out << *ED;
235  break;
236  }
237  case Decl::Record: {
238  const RecordDecl* RD = cast<RecordDecl>(DC);
239  if (RD->isCompleteDefinition())
240  Out << "[struct] ";
241  else
242  Out << "<struct> ";
243  Out << *RD;
244  break;
245  }
246  case Decl::CXXRecord: {
247  const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
248  if (RD->isCompleteDefinition())
249  Out << "[class] ";
250  else
251  Out << "<class> ";
252  Out << *RD << ' ' << DC;
253  break;
254  }
255  case Decl::ObjCMethod:
256  Out << "[objc method]";
257  break;
258  case Decl::ObjCInterface:
259  Out << "[objc interface]";
260  break;
261  case Decl::ObjCCategory:
262  Out << "[objc category]";
263  break;
264  case Decl::ObjCProtocol:
265  Out << "[objc protocol]";
266  break;
267  case Decl::ObjCImplementation:
268  Out << "[objc implementation]";
269  break;
270  case Decl::ObjCCategoryImpl:
271  Out << "[objc categoryimpl]";
272  break;
273  case Decl::LinkageSpec:
274  Out << "[linkage spec]";
275  break;
276  case Decl::Block:
277  Out << "[block]";
278  break;
279  case Decl::Function: {
280  const FunctionDecl* FD = cast<FunctionDecl>(DC);
282  Out << "[function] ";
283  else
284  Out << "<function> ";
285  Out << *FD;
286  // Print the parameters.
287  Out << "(";
288  bool PrintComma = false;
289  for (auto I : FD->parameters()) {
290  if (PrintComma)
291  Out << ", ";
292  else
293  PrintComma = true;
294  Out << *I;
295  }
296  Out << ")";
297  break;
298  }
299  case Decl::CXXMethod: {
300  const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
301  if (D->isOutOfLine())
302  Out << "[c++ method] ";
303  else if (D->isImplicit())
304  Out << "(c++ method) ";
305  else
306  Out << "<c++ method> ";
307  Out << *D;
308  // Print the parameters.
309  Out << "(";
310  bool PrintComma = false;
311  for (ParmVarDecl *Parameter : D->parameters()) {
312  if (PrintComma)
313  Out << ", ";
314  else
315  PrintComma = true;
316  Out << *Parameter;
317  }
318  Out << ")";
319 
320  // Check the semantic DeclContext.
321  const DeclContext* SemaDC = D->getDeclContext();
322  const DeclContext* LexicalDC = D->getLexicalDeclContext();
323  if (SemaDC != LexicalDC)
324  Out << " [[" << SemaDC << "]]";
325 
326  break;
327  }
328  case Decl::CXXConstructor: {
329  const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
330  if (D->isOutOfLine())
331  Out << "[c++ ctor] ";
332  else if (D->isImplicit())
333  Out << "(c++ ctor) ";
334  else
335  Out << "<c++ ctor> ";
336  Out << *D;
337  // Print the parameters.
338  Out << "(";
339  bool PrintComma = false;
340  for (ParmVarDecl *Parameter : D->parameters()) {
341  if (PrintComma)
342  Out << ", ";
343  else
344  PrintComma = true;
345  Out << *Parameter;
346  }
347  Out << ")";
348 
349  // Check the semantic DC.
350  const DeclContext* SemaDC = D->getDeclContext();
351  const DeclContext* LexicalDC = D->getLexicalDeclContext();
352  if (SemaDC != LexicalDC)
353  Out << " [[" << SemaDC << "]]";
354  break;
355  }
356  case Decl::CXXDestructor: {
357  const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
358  if (D->isOutOfLine())
359  Out << "[c++ dtor] ";
360  else if (D->isImplicit())
361  Out << "(c++ dtor) ";
362  else
363  Out << "<c++ dtor> ";
364  Out << *D;
365  // Check the semantic DC.
366  const DeclContext* SemaDC = D->getDeclContext();
367  const DeclContext* LexicalDC = D->getLexicalDeclContext();
368  if (SemaDC != LexicalDC)
369  Out << " [[" << SemaDC << "]]";
370  break;
371  }
372  case Decl::CXXConversion: {
373  const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
374  if (D->isOutOfLine())
375  Out << "[c++ conversion] ";
376  else if (D->isImplicit())
377  Out << "(c++ conversion) ";
378  else
379  Out << "<c++ conversion> ";
380  Out << *D;
381  // Check the semantic DC.
382  const DeclContext* SemaDC = D->getDeclContext();
383  const DeclContext* LexicalDC = D->getLexicalDeclContext();
384  if (SemaDC != LexicalDC)
385  Out << " [[" << SemaDC << "]]";
386  break;
387  }
388 
389  case Decl::ClassTemplateSpecialization: {
390  const auto *CTSD = cast<ClassTemplateSpecializationDecl>(DC);
391  if (CTSD->isCompleteDefinition())
392  Out << "[class template specialization] ";
393  else
394  Out << "<class template specialization> ";
395  Out << *CTSD;
396  break;
397  }
398 
399  case Decl::ClassTemplatePartialSpecialization: {
400  const auto *CTPSD = cast<ClassTemplatePartialSpecializationDecl>(DC);
401  if (CTPSD->isCompleteDefinition())
402  Out << "[class template partial specialization] ";
403  else
404  Out << "<class template partial specialization> ";
405  Out << *CTPSD;
406  break;
407  }
408 
409  default:
410  llvm_unreachable("a decl that inherits DeclContext isn't handled");
411  }
412 
413  Out << "\n";
414 
415  // Print decls in the DeclContext.
416  for (auto *I : DC->decls()) {
417  for (unsigned i = 0; i < Indentation; ++i)
418  Out << " ";
419 
420  Decl::Kind DK = I->getKind();
421  switch (DK) {
422  case Decl::Namespace:
423  case Decl::Enum:
424  case Decl::Record:
425  case Decl::CXXRecord:
426  case Decl::ObjCMethod:
427  case Decl::ObjCInterface:
428  case Decl::ObjCCategory:
429  case Decl::ObjCProtocol:
430  case Decl::ObjCImplementation:
431  case Decl::ObjCCategoryImpl:
432  case Decl::LinkageSpec:
433  case Decl::Block:
434  case Decl::Function:
435  case Decl::CXXMethod:
436  case Decl::CXXConstructor:
437  case Decl::CXXDestructor:
438  case Decl::CXXConversion:
439  case Decl::ClassTemplateSpecialization:
440  case Decl::ClassTemplatePartialSpecialization: {
441  DeclContext* DC = cast<DeclContext>(I);
442  PrintDeclContext(DC, Indentation+2);
443  break;
444  }
445  case Decl::IndirectField: {
446  IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I);
447  Out << "<IndirectField> " << *IFD << '\n';
448  break;
449  }
450  case Decl::Label: {
451  LabelDecl *LD = cast<LabelDecl>(I);
452  Out << "<Label> " << *LD << '\n';
453  break;
454  }
455  case Decl::Field: {
456  FieldDecl *FD = cast<FieldDecl>(I);
457  Out << "<field> " << *FD << '\n';
458  break;
459  }
460  case Decl::Typedef:
461  case Decl::TypeAlias: {
462  TypedefNameDecl* TD = cast<TypedefNameDecl>(I);
463  Out << "<typedef> " << *TD << '\n';
464  break;
465  }
466  case Decl::EnumConstant: {
467  EnumConstantDecl* ECD = cast<EnumConstantDecl>(I);
468  Out << "<enum constant> " << *ECD << '\n';
469  break;
470  }
471  case Decl::Var: {
472  VarDecl* VD = cast<VarDecl>(I);
473  Out << "<var> " << *VD << '\n';
474  break;
475  }
476  case Decl::ImplicitParam: {
477  ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I);
478  Out << "<implicit parameter> " << *IPD << '\n';
479  break;
480  }
481  case Decl::ParmVar: {
482  ParmVarDecl* PVD = cast<ParmVarDecl>(I);
483  Out << "<parameter> " << *PVD << '\n';
484  break;
485  }
486  case Decl::ObjCProperty: {
487  ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I);
488  Out << "<objc property> " << *OPD << '\n';
489  break;
490  }
491  case Decl::FunctionTemplate: {
492  FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I);
493  Out << "<function template> " << *FTD << '\n';
494  break;
495  }
496  case Decl::FileScopeAsm: {
497  Out << "<file-scope asm>\n";
498  break;
499  }
500  case Decl::UsingDirective: {
501  Out << "<using directive>\n";
502  break;
503  }
504  case Decl::NamespaceAlias: {
505  NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I);
506  Out << "<namespace alias> " << *NAD << '\n';
507  break;
508  }
509  case Decl::ClassTemplate: {
510  ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I);
511  Out << "<class template> " << *CTD << '\n';
512  break;
513  }
514  case Decl::OMPThreadPrivate: {
515  Out << "<omp threadprivate> " << '"' << I << "\"\n";
516  break;
517  }
518  case Decl::Friend: {
519  Out << "<friend>";
520  if (const NamedDecl *ND = cast<FriendDecl>(I)->getFriendDecl())
521  Out << ' ' << *ND;
522  Out << "\n";
523  break;
524  }
525  case Decl::Using: {
526  Out << "<using> " << *cast<UsingDecl>(I) << "\n";
527  break;
528  }
529  case Decl::UsingShadow: {
530  Out << "<using shadow> " << *cast<UsingShadowDecl>(I) << "\n";
531  break;
532  }
533  case Decl::Empty: {
534  Out << "<empty>\n";
535  break;
536  }
537  case Decl::AccessSpec: {
538  Out << "<access specifier>\n";
539  break;
540  }
541  case Decl::VarTemplate: {
542  Out << "<var template> " << *cast<VarTemplateDecl>(I) << "\n";
543  break;
544  }
545  case Decl::StaticAssert: {
546  Out << "<static assert>\n";
547  break;
548  }
549  default:
550  Out << "DeclKind: " << DK << '"' << I << "\"\n";
551  llvm_unreachable("decl unhandled");
552  }
553  }
554 }
555 std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() {
556  return llvm::make_unique<DeclContextPrinter>();
557 }
Defines the clang::ASTContext interface.
Represents a function declaration or definition.
Definition: Decl.h:1714
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Definition: ASTConsumer.h:34
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:984
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:30
Stmt - This represents one statement.
Definition: Stmt.h:66
bool isOutOfLine() const override
Determine whether this is or was instantiated from an out-of-line definition of a member function...
Definition: Decl.cpp:3539
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:2728
Defines the SourceManager interface.
iterator end()
Definition: DeclGroup.h:106
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Represent a C++ namespace.
Definition: Decl.h:514
constexpr XRayInstrMask Function
Definition: XRayInstr.h:39
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2463
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition: Decl.h:3157
Represents a variable declaration or definition.
Definition: Decl.h:812
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:1586
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:38
Represents a parameter to a function.
Definition: Decl.h:1533
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
Represents a struct/union/class.
Definition: Decl.h:3548
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:150
Represents a member of a struct/union/class.
Definition: Decl.h:2521
Definition: Format.h:2022
Print DeclContext and their Decls.
iterator begin()
Definition: DeclGroup.h:100
Defines the Diagnostic-related interfaces.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
std::unique_ptr< ASTConsumer > CreateASTDumper(std::unique_ptr< raw_ostream > OS, StringRef FilterString, bool DumpDecls, bool Deserialize, bool DumpLookups)
std::string Label
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2686
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:552
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
Definition: Decl.cpp:1507
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2748
Decl::Kind getDeclKind() const
Definition: DeclBase.h:1334
Kind
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:376
Represents the declaration of a label.
Definition: Decl.h:468
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2031
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:746
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2858
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1262
Represents a field injected from an anonymous union/struct into the parent scope. ...
Definition: Decl.h:2767
Represents an enum.
Definition: Decl.h:3299
std::unique_ptr< ASTConsumer > CreateDeclContextPrinter()
std::unique_ptr< ASTConsumer > CreateASTViewer()
std::unique_ptr< ASTConsumer > CreateASTDeclNodeLister()
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:990
Represents a C++ struct/union/class.
Definition: DeclCXX.h:300
The parameter type of a method or function.
Declaration of a class template.
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
Definition: Decl.h:2023
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:89
void dump() const
Definition: ASTDumper.cpp:2731
The top declaration context.
Definition: Decl.h:107
std::unique_ptr< ASTConsumer > CreateASTPrinter(std::unique_ptr< raw_ostream > OS, StringRef FilterString)
This represents a decl that may have a name.
Definition: Decl.h:248
Represents a C++ namespace alias.
Definition: DeclCXX.h:3013
const LangOptions & getLangOpts() const
Definition: ASTContext.h:689
Declaration of a template function.
Definition: DeclTemplate.h:968