clang  3.9.0
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"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/Timer.h"
26 #include "llvm/Support/raw_ostream.h"
27 using namespace clang;
28 
29 //===----------------------------------------------------------------------===//
30 /// ASTPrinter - Pretty-printer and dumper of ASTs
31 
32 namespace {
33  class ASTPrinter : public ASTConsumer,
34  public RecursiveASTVisitor<ASTPrinter> {
36 
37  public:
38  ASTPrinter(std::unique_ptr<raw_ostream> Out = nullptr, bool Dump = false,
39  StringRef FilterString = "", bool DumpLookups = false)
40  : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), Dump(Dump),
41  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 << ((Dump || DumpLookups) ? "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, Dump);
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 (Dump)
91  D->dump(Out);
92  else
93  D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
94  }
95 
96  raw_ostream &Out;
97  std::unique_ptr<raw_ostream> OwnedOut;
98  bool Dump;
99  std::string FilterString;
100  bool DumpLookups;
101  };
102 
103  class ASTDeclNodeLister : public ASTConsumer,
104  public RecursiveASTVisitor<ASTDeclNodeLister> {
105  public:
106  ASTDeclNodeLister(raw_ostream *Out = nullptr)
107  : Out(Out ? *Out : llvm::outs()) {}
108 
109  void HandleTranslationUnit(ASTContext &Context) override {
110  TraverseDecl(Context.getTranslationUnitDecl());
111  }
112 
113  bool shouldWalkTypesOfTypeLocs() const { return false; }
114 
115  bool VisitNamedDecl(NamedDecl *D) {
116  D->printQualifiedName(Out);
117  Out << '\n';
118  return true;
119  }
120 
121  private:
122  raw_ostream &Out;
123  };
124 } // end anonymous namespace
125 
126 std::unique_ptr<ASTConsumer>
127 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
128  StringRef FilterString) {
129  return llvm::make_unique<ASTPrinter>(std::move(Out), /*Dump=*/false,
130  FilterString);
131 }
132 
133 std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
134  bool DumpDecls,
135  bool DumpLookups) {
136  assert((DumpDecls || DumpLookups) && "nothing to dump");
137  return llvm::make_unique<ASTPrinter>(nullptr, DumpDecls, FilterString,
138  DumpLookups);
139 }
140 
141 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
142  return llvm::make_unique<ASTDeclNodeLister>(nullptr);
143 }
144 
145 //===----------------------------------------------------------------------===//
146 /// ASTViewer - AST Visualization
147 
148 namespace {
149  class ASTViewer : public ASTConsumer {
151  public:
152  void Initialize(ASTContext &Context) override {
153  this->Context = &Context;
154  }
155 
156  bool HandleTopLevelDecl(DeclGroupRef D) override {
157  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
158  HandleTopLevelSingleDecl(*I);
159  return true;
160  }
161 
162  void HandleTopLevelSingleDecl(Decl *D);
163  };
164 }
165 
166 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
167  if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
168  D->print(llvm::errs());
169 
170  if (Stmt *Body = D->getBody()) {
171  llvm::errs() << '\n';
172  Body->viewAST();
173  llvm::errs() << '\n';
174  }
175  }
176 }
177 
178 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
179  return llvm::make_unique<ASTViewer>();
180 }
181 
182 //===----------------------------------------------------------------------===//
183 /// DeclContextPrinter - Decl and DeclContext Visualization
184 
185 namespace {
186 
187 class DeclContextPrinter : public ASTConsumer {
188  raw_ostream& Out;
189 public:
190  DeclContextPrinter() : Out(llvm::errs()) {}
191 
192  void HandleTranslationUnit(ASTContext &C) override {
194  }
195 
196  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
197 };
198 } // end anonymous namespace
199 
201  unsigned Indentation) {
202  // Print DeclContext name.
203  switch (DC->getDeclKind()) {
204  case Decl::TranslationUnit:
205  Out << "[translation unit] " << DC;
206  break;
207  case Decl::Namespace: {
208  Out << "[namespace] ";
209  const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
210  Out << *ND;
211  break;
212  }
213  case Decl::Enum: {
214  const EnumDecl* ED = cast<EnumDecl>(DC);
215  if (ED->isCompleteDefinition())
216  Out << "[enum] ";
217  else
218  Out << "<enum> ";
219  Out << *ED;
220  break;
221  }
222  case Decl::Record: {
223  const RecordDecl* RD = cast<RecordDecl>(DC);
224  if (RD->isCompleteDefinition())
225  Out << "[struct] ";
226  else
227  Out << "<struct> ";
228  Out << *RD;
229  break;
230  }
231  case Decl::CXXRecord: {
232  const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
233  if (RD->isCompleteDefinition())
234  Out << "[class] ";
235  else
236  Out << "<class> ";
237  Out << *RD << ' ' << DC;
238  break;
239  }
240  case Decl::ObjCMethod:
241  Out << "[objc method]";
242  break;
243  case Decl::ObjCInterface:
244  Out << "[objc interface]";
245  break;
246  case Decl::ObjCCategory:
247  Out << "[objc category]";
248  break;
249  case Decl::ObjCProtocol:
250  Out << "[objc protocol]";
251  break;
252  case Decl::ObjCImplementation:
253  Out << "[objc implementation]";
254  break;
255  case Decl::ObjCCategoryImpl:
256  Out << "[objc categoryimpl]";
257  break;
258  case Decl::LinkageSpec:
259  Out << "[linkage spec]";
260  break;
261  case Decl::Block:
262  Out << "[block]";
263  break;
264  case Decl::Function: {
265  const FunctionDecl* FD = cast<FunctionDecl>(DC);
267  Out << "[function] ";
268  else
269  Out << "<function> ";
270  Out << *FD;
271  // Print the parameters.
272  Out << "(";
273  bool PrintComma = false;
274  for (auto I : FD->parameters()) {
275  if (PrintComma)
276  Out << ", ";
277  else
278  PrintComma = true;
279  Out << *I;
280  }
281  Out << ")";
282  break;
283  }
284  case Decl::CXXMethod: {
285  const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
286  if (D->isOutOfLine())
287  Out << "[c++ method] ";
288  else if (D->isImplicit())
289  Out << "(c++ method) ";
290  else
291  Out << "<c++ method> ";
292  Out << *D;
293  // Print the parameters.
294  Out << "(";
295  bool PrintComma = false;
296  for (ParmVarDecl *Parameter : D->parameters()) {
297  if (PrintComma)
298  Out << ", ";
299  else
300  PrintComma = true;
301  Out << *Parameter;
302  }
303  Out << ")";
304 
305  // Check the semantic DeclContext.
306  const DeclContext* SemaDC = D->getDeclContext();
307  const DeclContext* LexicalDC = D->getLexicalDeclContext();
308  if (SemaDC != LexicalDC)
309  Out << " [[" << SemaDC << "]]";
310 
311  break;
312  }
313  case Decl::CXXConstructor: {
314  const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
315  if (D->isOutOfLine())
316  Out << "[c++ ctor] ";
317  else if (D->isImplicit())
318  Out << "(c++ ctor) ";
319  else
320  Out << "<c++ ctor> ";
321  Out << *D;
322  // Print the parameters.
323  Out << "(";
324  bool PrintComma = false;
325  for (ParmVarDecl *Parameter : D->parameters()) {
326  if (PrintComma)
327  Out << ", ";
328  else
329  PrintComma = true;
330  Out << *Parameter;
331  }
332  Out << ")";
333 
334  // Check the semantic DC.
335  const DeclContext* SemaDC = D->getDeclContext();
336  const DeclContext* LexicalDC = D->getLexicalDeclContext();
337  if (SemaDC != LexicalDC)
338  Out << " [[" << SemaDC << "]]";
339  break;
340  }
341  case Decl::CXXDestructor: {
342  const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
343  if (D->isOutOfLine())
344  Out << "[c++ dtor] ";
345  else if (D->isImplicit())
346  Out << "(c++ dtor) ";
347  else
348  Out << "<c++ dtor> ";
349  Out << *D;
350  // Check the semantic DC.
351  const DeclContext* SemaDC = D->getDeclContext();
352  const DeclContext* LexicalDC = D->getLexicalDeclContext();
353  if (SemaDC != LexicalDC)
354  Out << " [[" << SemaDC << "]]";
355  break;
356  }
357  case Decl::CXXConversion: {
358  const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
359  if (D->isOutOfLine())
360  Out << "[c++ conversion] ";
361  else if (D->isImplicit())
362  Out << "(c++ conversion) ";
363  else
364  Out << "<c++ conversion> ";
365  Out << *D;
366  // Check the semantic DC.
367  const DeclContext* SemaDC = D->getDeclContext();
368  const DeclContext* LexicalDC = D->getLexicalDeclContext();
369  if (SemaDC != LexicalDC)
370  Out << " [[" << SemaDC << "]]";
371  break;
372  }
373 
374  default:
375  llvm_unreachable("a decl that inherits DeclContext isn't handled");
376  }
377 
378  Out << "\n";
379 
380  // Print decls in the DeclContext.
381  for (auto *I : DC->decls()) {
382  for (unsigned i = 0; i < Indentation; ++i)
383  Out << " ";
384 
385  Decl::Kind DK = I->getKind();
386  switch (DK) {
387  case Decl::Namespace:
388  case Decl::Enum:
389  case Decl::Record:
390  case Decl::CXXRecord:
391  case Decl::ObjCMethod:
392  case Decl::ObjCInterface:
393  case Decl::ObjCCategory:
394  case Decl::ObjCProtocol:
395  case Decl::ObjCImplementation:
396  case Decl::ObjCCategoryImpl:
397  case Decl::LinkageSpec:
398  case Decl::Block:
399  case Decl::Function:
400  case Decl::CXXMethod:
401  case Decl::CXXConstructor:
402  case Decl::CXXDestructor:
403  case Decl::CXXConversion:
404  {
405  DeclContext* DC = cast<DeclContext>(I);
406  PrintDeclContext(DC, Indentation+2);
407  break;
408  }
409  case Decl::IndirectField: {
410  IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I);
411  Out << "<IndirectField> " << *IFD << '\n';
412  break;
413  }
414  case Decl::Label: {
415  LabelDecl *LD = cast<LabelDecl>(I);
416  Out << "<Label> " << *LD << '\n';
417  break;
418  }
419  case Decl::Field: {
420  FieldDecl *FD = cast<FieldDecl>(I);
421  Out << "<field> " << *FD << '\n';
422  break;
423  }
424  case Decl::Typedef:
425  case Decl::TypeAlias: {
426  TypedefNameDecl* TD = cast<TypedefNameDecl>(I);
427  Out << "<typedef> " << *TD << '\n';
428  break;
429  }
430  case Decl::EnumConstant: {
431  EnumConstantDecl* ECD = cast<EnumConstantDecl>(I);
432  Out << "<enum constant> " << *ECD << '\n';
433  break;
434  }
435  case Decl::Var: {
436  VarDecl* VD = cast<VarDecl>(I);
437  Out << "<var> " << *VD << '\n';
438  break;
439  }
440  case Decl::ImplicitParam: {
441  ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I);
442  Out << "<implicit parameter> " << *IPD << '\n';
443  break;
444  }
445  case Decl::ParmVar: {
446  ParmVarDecl* PVD = cast<ParmVarDecl>(I);
447  Out << "<parameter> " << *PVD << '\n';
448  break;
449  }
450  case Decl::ObjCProperty: {
451  ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I);
452  Out << "<objc property> " << *OPD << '\n';
453  break;
454  }
455  case Decl::FunctionTemplate: {
456  FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I);
457  Out << "<function template> " << *FTD << '\n';
458  break;
459  }
460  case Decl::FileScopeAsm: {
461  Out << "<file-scope asm>\n";
462  break;
463  }
464  case Decl::UsingDirective: {
465  Out << "<using directive>\n";
466  break;
467  }
468  case Decl::NamespaceAlias: {
469  NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I);
470  Out << "<namespace alias> " << *NAD << '\n';
471  break;
472  }
473  case Decl::ClassTemplate: {
474  ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I);
475  Out << "<class template> " << *CTD << '\n';
476  break;
477  }
478  case Decl::OMPThreadPrivate: {
479  Out << "<omp threadprivate> " << '"' << I << "\"\n";
480  break;
481  }
482  default:
483  Out << "DeclKind: " << DK << '"' << I << "\"\n";
484  llvm_unreachable("decl unhandled");
485  }
486  }
487 }
488 std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() {
489  return llvm::make_unique<DeclContextPrinter>();
490 }
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1561
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Definition: ASTConsumer.h:36
Defines the clang::FileManager interface and associated types.
bool isOutOfLine() const override
Determine whether this is or was instantiated from an out-of-line definition of a member function...
Definition: Decl.cpp:3323
EnumConstantDecl - An instance of this object exists for each enum constant that is defined...
Definition: Decl.h:2481
Defines the SourceManager interface.
iterator end()
Definition: DeclGroup.h:108
NamespaceDecl - Represent a C++ namespace.
Definition: Decl.h:471
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2187
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:768
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1377
RecordDecl - Represents a struct/union/class.
Definition: Decl.h:3253
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:92
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
Definition: Decl.h:2293
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
Definition: Decl.h:2871
Print DeclContext and their Decls.
iterator begin()
Definition: DeclGroup.h:102
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
detail::InMemoryDirectory::const_iterator I
ASTContext * Context
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2414
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:886
virtual void HandleTranslationUnit(ASTContext &Ctx)
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
Definition: ASTConsumer.h:69
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2461
bool doesThisDeclarationHaveABody() const
doesThisDeclarationHaveABody - Returns whether this specific declaration of the function has a body -...
Definition: Decl.h:1821
Kind
LabelDecl - Represents the declaration of a label.
Definition: Decl.h:424
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1736
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:699
unsigned TypeAlias
Whether this template specialization type is a substituted type alias.
Definition: Type.h:4171
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:1405
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2609
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1135
IndirectFieldDecl - An instance of this class is created to represent a field injected from an anonym...
Definition: Decl.h:2521
EnumDecl - Represents an enum.
Definition: Decl.h:3013
detail::InMemoryDirectory::const_iterator E
Defines the Diagnostic-related interfaces.
std::unique_ptr< ASTConsumer > CreateDeclContextPrinter()
Decl::Kind getDeclKind() const
Definition: DeclBase.h:1208
std::unique_ptr< ASTConsumer > CreateASTViewer()
std::unique_ptr< ASTConsumer > CreateASTDeclNodeLister()
Represents a C++ struct/union/class.
Definition: DeclCXX.h:263
The parameter type of a method or function.
Declaration of a class template.
TranslationUnitDecl - The top declaration context.
Definition: Decl.h:80
std::unique_ptr< ASTConsumer > CreateASTDumper(StringRef FilterString, bool DumpDecls, bool DumpLookups)
std::unique_ptr< ASTConsumer > CreateASTPrinter(std::unique_ptr< raw_ostream > OS, StringRef FilterString)
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
Represents a C++ namespace alias.
Definition: DeclCXX.h:2718
Declaration of a template function.
Definition: DeclTemplate.h:838