clang  3.7.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(raw_ostream *Out = nullptr, bool Dump = false,
39  StringRef FilterString = "", bool DumpLookups = false)
40  : Out(Out ? *Out : llvm::outs()), 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  bool Dump;
98  std::string FilterString;
99  bool DumpLookups;
100  };
101 
102  class ASTDeclNodeLister : public ASTConsumer,
103  public RecursiveASTVisitor<ASTDeclNodeLister> {
104  public:
105  ASTDeclNodeLister(raw_ostream *Out = nullptr)
106  : Out(Out ? *Out : llvm::outs()) {}
107 
108  void HandleTranslationUnit(ASTContext &Context) override {
109  TraverseDecl(Context.getTranslationUnitDecl());
110  }
111 
112  bool shouldWalkTypesOfTypeLocs() const { return false; }
113 
114  bool VisitNamedDecl(NamedDecl *D) {
115  D->printQualifiedName(Out);
116  Out << '\n';
117  return true;
118  }
119 
120  private:
121  raw_ostream &Out;
122  };
123 } // end anonymous namespace
124 
125 std::unique_ptr<ASTConsumer> clang::CreateASTPrinter(raw_ostream *Out,
126  StringRef FilterString) {
127  return llvm::make_unique<ASTPrinter>(Out, /*Dump=*/false, FilterString);
128 }
129 
130 std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
131  bool DumpDecls,
132  bool DumpLookups) {
133  assert((DumpDecls || DumpLookups) && "nothing to dump");
134  return llvm::make_unique<ASTPrinter>(nullptr, DumpDecls, FilterString,
135  DumpLookups);
136 }
137 
138 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
139  return llvm::make_unique<ASTDeclNodeLister>(nullptr);
140 }
141 
142 //===----------------------------------------------------------------------===//
143 /// ASTViewer - AST Visualization
144 
145 namespace {
146  class ASTViewer : public ASTConsumer {
148  public:
149  void Initialize(ASTContext &Context) override {
150  this->Context = &Context;
151  }
152 
153  bool HandleTopLevelDecl(DeclGroupRef D) override {
154  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
155  HandleTopLevelSingleDecl(*I);
156  return true;
157  }
158 
159  void HandleTopLevelSingleDecl(Decl *D);
160  };
161 }
162 
163 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
164  if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
165  D->print(llvm::errs());
166 
167  if (Stmt *Body = D->getBody()) {
168  llvm::errs() << '\n';
169  Body->viewAST();
170  llvm::errs() << '\n';
171  }
172  }
173 }
174 
175 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
176  return llvm::make_unique<ASTViewer>();
177 }
178 
179 //===----------------------------------------------------------------------===//
180 /// DeclContextPrinter - Decl and DeclContext Visualization
181 
182 namespace {
183 
184 class DeclContextPrinter : public ASTConsumer {
185  raw_ostream& Out;
186 public:
187  DeclContextPrinter() : Out(llvm::errs()) {}
188 
189  void HandleTranslationUnit(ASTContext &C) override {
191  }
192 
193  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
194 };
195 } // end anonymous namespace
196 
198  unsigned Indentation) {
199  // Print DeclContext name.
200  switch (DC->getDeclKind()) {
201  case Decl::TranslationUnit:
202  Out << "[translation unit] " << DC;
203  break;
204  case Decl::Namespace: {
205  Out << "[namespace] ";
206  const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
207  Out << *ND;
208  break;
209  }
210  case Decl::Enum: {
211  const EnumDecl* ED = cast<EnumDecl>(DC);
212  if (ED->isCompleteDefinition())
213  Out << "[enum] ";
214  else
215  Out << "<enum> ";
216  Out << *ED;
217  break;
218  }
219  case Decl::Record: {
220  const RecordDecl* RD = cast<RecordDecl>(DC);
221  if (RD->isCompleteDefinition())
222  Out << "[struct] ";
223  else
224  Out << "<struct> ";
225  Out << *RD;
226  break;
227  }
228  case Decl::CXXRecord: {
229  const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
230  if (RD->isCompleteDefinition())
231  Out << "[class] ";
232  else
233  Out << "<class> ";
234  Out << *RD << ' ' << DC;
235  break;
236  }
237  case Decl::ObjCMethod:
238  Out << "[objc method]";
239  break;
240  case Decl::ObjCInterface:
241  Out << "[objc interface]";
242  break;
243  case Decl::ObjCCategory:
244  Out << "[objc category]";
245  break;
246  case Decl::ObjCProtocol:
247  Out << "[objc protocol]";
248  break;
249  case Decl::ObjCImplementation:
250  Out << "[objc implementation]";
251  break;
252  case Decl::ObjCCategoryImpl:
253  Out << "[objc categoryimpl]";
254  break;
255  case Decl::LinkageSpec:
256  Out << "[linkage spec]";
257  break;
258  case Decl::Block:
259  Out << "[block]";
260  break;
261  case Decl::Function: {
262  const FunctionDecl* FD = cast<FunctionDecl>(DC);
264  Out << "[function] ";
265  else
266  Out << "<function> ";
267  Out << *FD;
268  // Print the parameters.
269  Out << "(";
270  bool PrintComma = false;
271  for (auto I : FD->params()) {
272  if (PrintComma)
273  Out << ", ";
274  else
275  PrintComma = true;
276  Out << *I;
277  }
278  Out << ")";
279  break;
280  }
281  case Decl::CXXMethod: {
282  const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
283  if (D->isOutOfLine())
284  Out << "[c++ method] ";
285  else if (D->isImplicit())
286  Out << "(c++ method) ";
287  else
288  Out << "<c++ method> ";
289  Out << *D;
290  // Print the parameters.
291  Out << "(";
292  bool PrintComma = false;
293  for (FunctionDecl::param_const_iterator I = D->param_begin(),
294  E = D->param_end(); I != E; ++I) {
295  if (PrintComma)
296  Out << ", ";
297  else
298  PrintComma = true;
299  Out << **I;
300  }
301  Out << ")";
302 
303  // Check the semantic DeclContext.
304  const DeclContext* SemaDC = D->getDeclContext();
305  const DeclContext* LexicalDC = D->getLexicalDeclContext();
306  if (SemaDC != LexicalDC)
307  Out << " [[" << SemaDC << "]]";
308 
309  break;
310  }
311  case Decl::CXXConstructor: {
312  const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
313  if (D->isOutOfLine())
314  Out << "[c++ ctor] ";
315  else if (D->isImplicit())
316  Out << "(c++ ctor) ";
317  else
318  Out << "<c++ ctor> ";
319  Out << *D;
320  // Print the parameters.
321  Out << "(";
322  bool PrintComma = false;
323  for (FunctionDecl::param_const_iterator I = D->param_begin(),
324  E = D->param_end(); I != E; ++I) {
325  if (PrintComma)
326  Out << ", ";
327  else
328  PrintComma = true;
329  Out << **I;
330  }
331  Out << ")";
332 
333  // Check the semantic DC.
334  const DeclContext* SemaDC = D->getDeclContext();
335  const DeclContext* LexicalDC = D->getLexicalDeclContext();
336  if (SemaDC != LexicalDC)
337  Out << " [[" << SemaDC << "]]";
338  break;
339  }
340  case Decl::CXXDestructor: {
341  const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
342  if (D->isOutOfLine())
343  Out << "[c++ dtor] ";
344  else if (D->isImplicit())
345  Out << "(c++ dtor) ";
346  else
347  Out << "<c++ dtor> ";
348  Out << *D;
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::CXXConversion: {
357  const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
358  if (D->isOutOfLine())
359  Out << "[c++ conversion] ";
360  else if (D->isImplicit())
361  Out << "(c++ conversion) ";
362  else
363  Out << "<c++ conversion> ";
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 
373  default:
374  llvm_unreachable("a decl that inherits DeclContext isn't handled");
375  }
376 
377  Out << "\n";
378 
379  // Print decls in the DeclContext.
380  for (auto *I : DC->decls()) {
381  for (unsigned i = 0; i < Indentation; ++i)
382  Out << " ";
383 
384  Decl::Kind DK = I->getKind();
385  switch (DK) {
386  case Decl::Namespace:
387  case Decl::Enum:
388  case Decl::Record:
389  case Decl::CXXRecord:
390  case Decl::ObjCMethod:
391  case Decl::ObjCInterface:
392  case Decl::ObjCCategory:
393  case Decl::ObjCProtocol:
394  case Decl::ObjCImplementation:
395  case Decl::ObjCCategoryImpl:
396  case Decl::LinkageSpec:
397  case Decl::Block:
398  case Decl::Function:
399  case Decl::CXXMethod:
400  case Decl::CXXConstructor:
401  case Decl::CXXDestructor:
402  case Decl::CXXConversion:
403  {
404  DeclContext* DC = cast<DeclContext>(I);
405  PrintDeclContext(DC, Indentation+2);
406  break;
407  }
408  case Decl::IndirectField: {
409  IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I);
410  Out << "<IndirectField> " << *IFD << '\n';
411  break;
412  }
413  case Decl::Label: {
414  LabelDecl *LD = cast<LabelDecl>(I);
415  Out << "<Label> " << *LD << '\n';
416  break;
417  }
418  case Decl::Field: {
419  FieldDecl *FD = cast<FieldDecl>(I);
420  Out << "<field> " << *FD << '\n';
421  break;
422  }
423  case Decl::Typedef:
424  case Decl::TypeAlias: {
425  TypedefNameDecl* TD = cast<TypedefNameDecl>(I);
426  Out << "<typedef> " << *TD << '\n';
427  break;
428  }
429  case Decl::EnumConstant: {
430  EnumConstantDecl* ECD = cast<EnumConstantDecl>(I);
431  Out << "<enum constant> " << *ECD << '\n';
432  break;
433  }
434  case Decl::Var: {
435  VarDecl* VD = cast<VarDecl>(I);
436  Out << "<var> " << *VD << '\n';
437  break;
438  }
439  case Decl::ImplicitParam: {
440  ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I);
441  Out << "<implicit parameter> " << *IPD << '\n';
442  break;
443  }
444  case Decl::ParmVar: {
445  ParmVarDecl* PVD = cast<ParmVarDecl>(I);
446  Out << "<parameter> " << *PVD << '\n';
447  break;
448  }
449  case Decl::ObjCProperty: {
450  ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I);
451  Out << "<objc property> " << *OPD << '\n';
452  break;
453  }
454  case Decl::FunctionTemplate: {
455  FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I);
456  Out << "<function template> " << *FTD << '\n';
457  break;
458  }
459  case Decl::FileScopeAsm: {
460  Out << "<file-scope asm>\n";
461  break;
462  }
463  case Decl::UsingDirective: {
464  Out << "<using directive>\n";
465  break;
466  }
467  case Decl::NamespaceAlias: {
468  NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I);
469  Out << "<namespace alias> " << *NAD << '\n';
470  break;
471  }
472  case Decl::ClassTemplate: {
473  ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I);
474  Out << "<class template> " << *CTD << '\n';
475  break;
476  }
477  case Decl::OMPThreadPrivate: {
478  Out << "<omp threadprivate> " << '"' << I << "\"\n";
479  break;
480  }
481  default:
482  Out << "DeclKind: " << DK << '"' << I << "\"\n";
483  llvm_unreachable("decl unhandled");
484  }
485  }
486 }
487 std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() {
488  return llvm::make_unique<DeclContextPrinter>();
489 }
Defines the clang::ASTContext interface.
ParmVarDecl *const * param_const_iterator
Definition: Decl.h:1943
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:3199
Defines the SourceManager interface.
iterator end()
Definition: DeclGroup.h:109
NamespaceDecl - Represent a C++ namespace.
Definition: Decl.h:400
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2147
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1334
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:89
bool isCompleteDefinition() const
Definition: Decl.h:2838
Print DeclContext and their Decls.
bool isImplicit() const
Definition: DeclBase.h:503
iterator begin()
Definition: DeclGroup.h:103
A class that does preorder depth-first traversal on the entire Clang AST and visits each node...
ASTContext * Context
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2358
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:812
virtual void HandleTranslationUnit(ASTContext &Ctx)
Definition: ASTConsumer.h:69
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2405
void dump() const
Definition: ASTDumper.cpp:2303
bool doesThisDeclarationHaveABody() const
Definition: Decl.h:1773
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1717
virtual Stmt * getBody() const
Definition: DeclBase.h:840
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:2424
void printQualifiedName(raw_ostream &OS) const
Definition: Decl.cpp:1367
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2576
std::unique_ptr< ASTConsumer > CreateASTPrinter(raw_ostream *OS, StringRef FilterString)
Defines the Diagnostic-related interfaces.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
std::unique_ptr< ASTConsumer > CreateDeclContextPrinter()
Decl::Kind getDeclKind() const
Definition: DeclBase.h:1168
std::unique_ptr< ASTConsumer > CreateASTViewer()
std::unique_ptr< ASTConsumer > CreateASTDeclNodeLister()
Represents a C++ struct/union/class.
Definition: DeclCXX.h:285
Declaration of a class template.
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:76
TranslationUnitDecl - The top declaration context.
Definition: Decl.h:78
std::unique_ptr< ASTConsumer > CreateASTDumper(StringRef FilterString, bool DumpDecls, bool DumpLookups)
Represents a C++ namespace alias.
Definition: DeclCXX.h:2662
Declaration of a template function.
Definition: DeclTemplate.h:821