clang  6.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)
91  D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
92  else if (OutputKind != None)
93  D->dump(Out, OutputKind == DumpFull);
94  }
95 
96  raw_ostream &Out;
97  std::unique_ptr<raw_ostream> OwnedOut;
98 
99  /// How to output individual declarations.
100  Kind OutputKind;
101 
102  /// Which declarations or DeclContexts to display.
103  std::string FilterString;
104 
105  /// Whether the primary output is lookup results or declarations. Individual
106  /// results will be output with a format determined by OutputKind. This is
107  /// incompatible with OutputKind == Print.
108  bool DumpLookups;
109  };
110 
111  class ASTDeclNodeLister : public ASTConsumer,
112  public RecursiveASTVisitor<ASTDeclNodeLister> {
113  public:
114  ASTDeclNodeLister(raw_ostream *Out = nullptr)
115  : Out(Out ? *Out : llvm::outs()) {}
116 
117  void HandleTranslationUnit(ASTContext &Context) override {
118  TraverseDecl(Context.getTranslationUnitDecl());
119  }
120 
121  bool shouldWalkTypesOfTypeLocs() const { return false; }
122 
123  bool VisitNamedDecl(NamedDecl *D) {
124  D->printQualifiedName(Out);
125  Out << '\n';
126  return true;
127  }
128 
129  private:
130  raw_ostream &Out;
131  };
132 } // end anonymous namespace
133 
134 std::unique_ptr<ASTConsumer>
135 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
136  StringRef FilterString) {
137  return llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
138  FilterString);
139 }
140 
141 std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
142  bool DumpDecls,
143  bool Deserialize,
144  bool DumpLookups) {
145  assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
146  return llvm::make_unique<ASTPrinter>(nullptr,
147  Deserialize ? ASTPrinter::DumpFull :
148  DumpDecls ? ASTPrinter::Dump :
150  FilterString, DumpLookups);
151 }
152 
153 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
154  return llvm::make_unique<ASTDeclNodeLister>(nullptr);
155 }
156 
157 //===----------------------------------------------------------------------===//
158 /// ASTViewer - AST Visualization
159 
160 namespace {
161  class ASTViewer : public ASTConsumer {
162  ASTContext *Context;
163  public:
164  void Initialize(ASTContext &Context) override {
165  this->Context = &Context;
166  }
167 
168  bool HandleTopLevelDecl(DeclGroupRef D) override {
169  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
170  HandleTopLevelSingleDecl(*I);
171  return true;
172  }
173 
174  void HandleTopLevelSingleDecl(Decl *D);
175  };
176 }
177 
178 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
179  if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
180  D->print(llvm::errs());
181 
182  if (Stmt *Body = D->getBody()) {
183  llvm::errs() << '\n';
184  Body->viewAST();
185  llvm::errs() << '\n';
186  }
187  }
188 }
189 
190 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
191  return llvm::make_unique<ASTViewer>();
192 }
193 
194 //===----------------------------------------------------------------------===//
195 /// DeclContextPrinter - Decl and DeclContext Visualization
196 
197 namespace {
198 
199 class DeclContextPrinter : public ASTConsumer {
200  raw_ostream& Out;
201 public:
202  DeclContextPrinter() : Out(llvm::errs()) {}
203 
204  void HandleTranslationUnit(ASTContext &C) override {
206  }
207 
208  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
209 };
210 } // end anonymous namespace
211 
213  unsigned Indentation) {
214  // Print DeclContext name.
215  switch (DC->getDeclKind()) {
216  case Decl::TranslationUnit:
217  Out << "[translation unit] " << DC;
218  break;
219  case Decl::Namespace: {
220  Out << "[namespace] ";
221  const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
222  Out << *ND;
223  break;
224  }
225  case Decl::Enum: {
226  const EnumDecl* ED = cast<EnumDecl>(DC);
227  if (ED->isCompleteDefinition())
228  Out << "[enum] ";
229  else
230  Out << "<enum> ";
231  Out << *ED;
232  break;
233  }
234  case Decl::Record: {
235  const RecordDecl* RD = cast<RecordDecl>(DC);
236  if (RD->isCompleteDefinition())
237  Out << "[struct] ";
238  else
239  Out << "<struct> ";
240  Out << *RD;
241  break;
242  }
243  case Decl::CXXRecord: {
244  const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
245  if (RD->isCompleteDefinition())
246  Out << "[class] ";
247  else
248  Out << "<class> ";
249  Out << *RD << ' ' << DC;
250  break;
251  }
252  case Decl::ObjCMethod:
253  Out << "[objc method]";
254  break;
255  case Decl::ObjCInterface:
256  Out << "[objc interface]";
257  break;
258  case Decl::ObjCCategory:
259  Out << "[objc category]";
260  break;
261  case Decl::ObjCProtocol:
262  Out << "[objc protocol]";
263  break;
264  case Decl::ObjCImplementation:
265  Out << "[objc implementation]";
266  break;
267  case Decl::ObjCCategoryImpl:
268  Out << "[objc categoryimpl]";
269  break;
270  case Decl::LinkageSpec:
271  Out << "[linkage spec]";
272  break;
273  case Decl::Block:
274  Out << "[block]";
275  break;
276  case Decl::Function: {
277  const FunctionDecl* FD = cast<FunctionDecl>(DC);
279  Out << "[function] ";
280  else
281  Out << "<function> ";
282  Out << *FD;
283  // Print the parameters.
284  Out << "(";
285  bool PrintComma = false;
286  for (auto I : FD->parameters()) {
287  if (PrintComma)
288  Out << ", ";
289  else
290  PrintComma = true;
291  Out << *I;
292  }
293  Out << ")";
294  break;
295  }
296  case Decl::CXXMethod: {
297  const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
298  if (D->isOutOfLine())
299  Out << "[c++ method] ";
300  else if (D->isImplicit())
301  Out << "(c++ method) ";
302  else
303  Out << "<c++ method> ";
304  Out << *D;
305  // Print the parameters.
306  Out << "(";
307  bool PrintComma = false;
308  for (ParmVarDecl *Parameter : D->parameters()) {
309  if (PrintComma)
310  Out << ", ";
311  else
312  PrintComma = true;
313  Out << *Parameter;
314  }
315  Out << ")";
316 
317  // Check the semantic DeclContext.
318  const DeclContext* SemaDC = D->getDeclContext();
319  const DeclContext* LexicalDC = D->getLexicalDeclContext();
320  if (SemaDC != LexicalDC)
321  Out << " [[" << SemaDC << "]]";
322 
323  break;
324  }
325  case Decl::CXXConstructor: {
326  const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
327  if (D->isOutOfLine())
328  Out << "[c++ ctor] ";
329  else if (D->isImplicit())
330  Out << "(c++ ctor) ";
331  else
332  Out << "<c++ ctor> ";
333  Out << *D;
334  // Print the parameters.
335  Out << "(";
336  bool PrintComma = false;
337  for (ParmVarDecl *Parameter : D->parameters()) {
338  if (PrintComma)
339  Out << ", ";
340  else
341  PrintComma = true;
342  Out << *Parameter;
343  }
344  Out << ")";
345 
346  // Check the semantic DC.
347  const DeclContext* SemaDC = D->getDeclContext();
348  const DeclContext* LexicalDC = D->getLexicalDeclContext();
349  if (SemaDC != LexicalDC)
350  Out << " [[" << SemaDC << "]]";
351  break;
352  }
353  case Decl::CXXDestructor: {
354  const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
355  if (D->isOutOfLine())
356  Out << "[c++ dtor] ";
357  else if (D->isImplicit())
358  Out << "(c++ dtor) ";
359  else
360  Out << "<c++ dtor> ";
361  Out << *D;
362  // Check the semantic DC.
363  const DeclContext* SemaDC = D->getDeclContext();
364  const DeclContext* LexicalDC = D->getLexicalDeclContext();
365  if (SemaDC != LexicalDC)
366  Out << " [[" << SemaDC << "]]";
367  break;
368  }
369  case Decl::CXXConversion: {
370  const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
371  if (D->isOutOfLine())
372  Out << "[c++ conversion] ";
373  else if (D->isImplicit())
374  Out << "(c++ conversion) ";
375  else
376  Out << "<c++ conversion> ";
377  Out << *D;
378  // Check the semantic DC.
379  const DeclContext* SemaDC = D->getDeclContext();
380  const DeclContext* LexicalDC = D->getLexicalDeclContext();
381  if (SemaDC != LexicalDC)
382  Out << " [[" << SemaDC << "]]";
383  break;
384  }
385 
386  case Decl::ClassTemplateSpecialization: {
387  const auto *CTSD = cast<ClassTemplateSpecializationDecl>(DC);
388  if (CTSD->isCompleteDefinition())
389  Out << "[class template specialization] ";
390  else
391  Out << "<class template specialization> ";
392  Out << *CTSD;
393  break;
394  }
395 
396  case Decl::ClassTemplatePartialSpecialization: {
397  const auto *CTPSD = cast<ClassTemplatePartialSpecializationDecl>(DC);
398  if (CTPSD->isCompleteDefinition())
399  Out << "[class template partial specialization] ";
400  else
401  Out << "<class template partial specialization> ";
402  Out << *CTPSD;
403  break;
404  }
405 
406  default:
407  llvm_unreachable("a decl that inherits DeclContext isn't handled");
408  }
409 
410  Out << "\n";
411 
412  // Print decls in the DeclContext.
413  for (auto *I : DC->decls()) {
414  for (unsigned i = 0; i < Indentation; ++i)
415  Out << " ";
416 
417  Decl::Kind DK = I->getKind();
418  switch (DK) {
419  case Decl::Namespace:
420  case Decl::Enum:
421  case Decl::Record:
422  case Decl::CXXRecord:
423  case Decl::ObjCMethod:
424  case Decl::ObjCInterface:
425  case Decl::ObjCCategory:
426  case Decl::ObjCProtocol:
427  case Decl::ObjCImplementation:
428  case Decl::ObjCCategoryImpl:
429  case Decl::LinkageSpec:
430  case Decl::Block:
431  case Decl::Function:
432  case Decl::CXXMethod:
433  case Decl::CXXConstructor:
434  case Decl::CXXDestructor:
435  case Decl::CXXConversion:
436  case Decl::ClassTemplateSpecialization:
437  case Decl::ClassTemplatePartialSpecialization: {
438  DeclContext* DC = cast<DeclContext>(I);
439  PrintDeclContext(DC, Indentation+2);
440  break;
441  }
442  case Decl::IndirectField: {
443  IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I);
444  Out << "<IndirectField> " << *IFD << '\n';
445  break;
446  }
447  case Decl::Label: {
448  LabelDecl *LD = cast<LabelDecl>(I);
449  Out << "<Label> " << *LD << '\n';
450  break;
451  }
452  case Decl::Field: {
453  FieldDecl *FD = cast<FieldDecl>(I);
454  Out << "<field> " << *FD << '\n';
455  break;
456  }
457  case Decl::Typedef:
458  case Decl::TypeAlias: {
459  TypedefNameDecl* TD = cast<TypedefNameDecl>(I);
460  Out << "<typedef> " << *TD << '\n';
461  break;
462  }
463  case Decl::EnumConstant: {
464  EnumConstantDecl* ECD = cast<EnumConstantDecl>(I);
465  Out << "<enum constant> " << *ECD << '\n';
466  break;
467  }
468  case Decl::Var: {
469  VarDecl* VD = cast<VarDecl>(I);
470  Out << "<var> " << *VD << '\n';
471  break;
472  }
473  case Decl::ImplicitParam: {
474  ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I);
475  Out << "<implicit parameter> " << *IPD << '\n';
476  break;
477  }
478  case Decl::ParmVar: {
479  ParmVarDecl* PVD = cast<ParmVarDecl>(I);
480  Out << "<parameter> " << *PVD << '\n';
481  break;
482  }
483  case Decl::ObjCProperty: {
484  ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I);
485  Out << "<objc property> " << *OPD << '\n';
486  break;
487  }
488  case Decl::FunctionTemplate: {
489  FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I);
490  Out << "<function template> " << *FTD << '\n';
491  break;
492  }
493  case Decl::FileScopeAsm: {
494  Out << "<file-scope asm>\n";
495  break;
496  }
497  case Decl::UsingDirective: {
498  Out << "<using directive>\n";
499  break;
500  }
501  case Decl::NamespaceAlias: {
502  NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I);
503  Out << "<namespace alias> " << *NAD << '\n';
504  break;
505  }
506  case Decl::ClassTemplate: {
507  ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I);
508  Out << "<class template> " << *CTD << '\n';
509  break;
510  }
511  case Decl::OMPThreadPrivate: {
512  Out << "<omp threadprivate> " << '"' << I << "\"\n";
513  break;
514  }
515  case Decl::Friend: {
516  Out << "<friend>";
517  if (const NamedDecl *ND = cast<FriendDecl>(I)->getFriendDecl())
518  Out << ' ' << *ND;
519  Out << "\n";
520  break;
521  }
522  case Decl::Using: {
523  Out << "<using> " << *cast<UsingDecl>(I) << "\n";
524  break;
525  }
526  case Decl::UsingShadow: {
527  Out << "<using shadow> " << *cast<UsingShadowDecl>(I) << "\n";
528  break;
529  }
530  case Decl::Empty: {
531  Out << "<empty>\n";
532  break;
533  }
534  case Decl::AccessSpec: {
535  Out << "<access specifier>\n";
536  break;
537  }
538  case Decl::VarTemplate: {
539  Out << "<var template> " << *cast<VarTemplateDecl>(I) << "\n";
540  break;
541  }
542  case Decl::StaticAssert: {
543  Out << "<static assert>\n";
544  break;
545  }
546  default:
547  Out << "DeclKind: " << DK << '"' << I << "\"\n";
548  llvm_unreachable("decl unhandled");
549  }
550  }
551 }
552 std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() {
553  return llvm::make_unique<DeclContextPrinter>();
554 }
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1698
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:974
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:26
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:3482
EnumConstantDecl - An instance of this object exists for each enum constant that is defined...
Definition: Decl.h:2665
Defines the SourceManager interface.
iterator end()
Definition: DeclGroup.h:106
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
NamespaceDecl - Represent a C++ namespace.
Definition: Decl.h:506
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2397
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
Definition: Decl.h:3091
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:807
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:1576
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1514
std::unique_ptr< ASTConsumer > CreateASTDumper(StringRef FilterString, bool DumpDecls, bool Deserialize, bool DumpLookups)
RecordDecl - Represents a struct/union/class.
Definition: Decl.h:3482
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:149
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
Definition: Decl.h:2461
Definition: Format.h:1900
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::string Label
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2620
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:551
void printQualifiedName(raw_ostream &OS) const
printQualifiedName - Returns human-readable qualified name for declaration, like A::B::i, for i being member of namespace A::B.
Definition: Decl.cpp:1478
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2682
Decl::Kind getDeclKind() const
Definition: DeclBase.h:1324
Kind
LabelDecl - Represents the declaration of a label.
Definition: Decl.h:460
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1964
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:2796
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:1252
IndirectFieldDecl - An instance of this class is created to represent a field injected from an anonym...
Definition: Decl.h:2705
EnumDecl - Represents an enum.
Definition: Decl.h:3233
std::unique_ptr< ASTConsumer > CreateDeclContextPrinter()
std::unique_ptr< ASTConsumer > CreateASTViewer()
std::unique_ptr< ASTConsumer > CreateASTDeclNodeLister()
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:989
Represents a C++ struct/union/class.
Definition: DeclCXX.h:299
The parameter type of a method or function.
Declaration of a class template.
bool doesThisDeclarationHaveABody() const
doesThisDeclarationHaveABody - Returns whether this specific declaration of the function has a body -...
Definition: Decl.h:1977
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:89
void dump() const
Definition: ASTDumper.cpp:2683
TranslationUnitDecl - The top declaration context.
Definition: Decl.h:107
std::unique_ptr< ASTConsumer > CreateASTPrinter(std::unique_ptr< raw_ostream > OS, StringRef FilterString)
NamedDecl - This represents a decl with a name.
Definition: Decl.h:245
Represents a C++ namespace alias.
Definition: DeclCXX.h:2947
Declaration of a template function.
Definition: DeclTemplate.h:958