ASTConsumers.cpp revision 256281
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
14#include "clang/Frontend/ASTConsumers.h"
15#include "clang/AST/AST.h"
16#include "clang/AST/ASTConsumer.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/PrettyPrinter.h"
19#include "clang/AST/RecordLayout.h"
20#include "clang/AST/RecursiveASTVisitor.h"
21#include "clang/Basic/Diagnostic.h"
22#include "clang/Basic/FileManager.h"
23#include "clang/Basic/SourceManager.h"
24#include "llvm/IR/Module.h"
25#include "llvm/Support/Path.h"
26#include "llvm/Support/Timer.h"
27#include "llvm/Support/raw_ostream.h"
28using namespace clang;
29
30//===----------------------------------------------------------------------===//
31/// ASTPrinter - Pretty-printer and dumper of ASTs
32
33namespace {
34  class ASTPrinter : public ASTConsumer,
35                     public RecursiveASTVisitor<ASTPrinter> {
36    typedef RecursiveASTVisitor<ASTPrinter> base;
37
38  public:
39    ASTPrinter(raw_ostream *Out = NULL, bool Dump = false,
40               StringRef FilterString = "")
41        : Out(Out ? *Out : llvm::outs()), Dump(Dump),
42          FilterString(FilterString) {}
43
44    virtual void HandleTranslationUnit(ASTContext &Context) {
45      TranslationUnitDecl *D = Context.getTranslationUnitDecl();
46
47      if (FilterString.empty()) {
48        if (Dump)
49          D->dump(Out);
50        else
51          D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
52        return;
53      }
54
55      TraverseDecl(D);
56    }
57
58    bool shouldWalkTypesOfTypeLocs() const { return false; }
59
60    bool TraverseDecl(Decl *D) {
61      if (D != NULL && filterMatches(D)) {
62        bool ShowColors = Out.has_colors();
63        if (ShowColors)
64          Out.changeColor(raw_ostream::BLUE);
65        Out << (Dump ? "Dumping " : "Printing ") << getName(D) << ":\n";
66        if (ShowColors)
67          Out.resetColor();
68        if (Dump)
69          D->dump(Out);
70        else
71          D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
72        Out << "\n";
73        // Don't traverse child nodes to avoid output duplication.
74        return true;
75      }
76      return base::TraverseDecl(D);
77    }
78
79  private:
80    std::string getName(Decl *D) {
81      if (isa<NamedDecl>(D))
82        return cast<NamedDecl>(D)->getQualifiedNameAsString();
83      return "";
84    }
85    bool filterMatches(Decl *D) {
86      return getName(D).find(FilterString) != std::string::npos;
87    }
88
89    raw_ostream &Out;
90    bool Dump;
91    std::string FilterString;
92  };
93
94  class ASTDeclNodeLister : public ASTConsumer,
95                     public RecursiveASTVisitor<ASTDeclNodeLister> {
96  public:
97    ASTDeclNodeLister(raw_ostream *Out = NULL)
98        : Out(Out ? *Out : llvm::outs()) {}
99
100    virtual void HandleTranslationUnit(ASTContext &Context) {
101      TraverseDecl(Context.getTranslationUnitDecl());
102    }
103
104    bool shouldWalkTypesOfTypeLocs() const { return false; }
105
106    virtual bool VisitNamedDecl(NamedDecl *D) {
107      D->printQualifiedName(Out);
108      Out << '\n';
109      return true;
110    }
111
112  private:
113    raw_ostream &Out;
114  };
115} // end anonymous namespace
116
117ASTConsumer *clang::CreateASTPrinter(raw_ostream *Out,
118                                     StringRef FilterString) {
119  return new ASTPrinter(Out, /*Dump=*/ false, FilterString);
120}
121
122ASTConsumer *clang::CreateASTDumper(StringRef FilterString) {
123  return new ASTPrinter(0, /*Dump=*/ true, FilterString);
124}
125
126ASTConsumer *clang::CreateASTDeclNodeLister() {
127  return new ASTDeclNodeLister(0);
128}
129
130//===----------------------------------------------------------------------===//
131/// ASTViewer - AST Visualization
132
133namespace {
134  class ASTViewer : public ASTConsumer {
135    ASTContext *Context;
136  public:
137    void Initialize(ASTContext &Context) {
138      this->Context = &Context;
139    }
140
141    virtual bool HandleTopLevelDecl(DeclGroupRef D) {
142      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
143        HandleTopLevelSingleDecl(*I);
144      return true;
145    }
146
147    void HandleTopLevelSingleDecl(Decl *D);
148  };
149}
150
151void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
152  if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
153    D->print(llvm::errs());
154
155    if (Stmt *Body = D->getBody()) {
156      llvm::errs() << '\n';
157      Body->viewAST();
158      llvm::errs() << '\n';
159    }
160  }
161}
162
163
164ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
165
166//===----------------------------------------------------------------------===//
167/// DeclContextPrinter - Decl and DeclContext Visualization
168
169namespace {
170
171class DeclContextPrinter : public ASTConsumer {
172  raw_ostream& Out;
173public:
174  DeclContextPrinter() : Out(llvm::errs()) {}
175
176  void HandleTranslationUnit(ASTContext &C) {
177    PrintDeclContext(C.getTranslationUnitDecl(), 4);
178  }
179
180  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
181};
182}  // end anonymous namespace
183
184void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
185                                          unsigned Indentation) {
186  // Print DeclContext name.
187  switch (DC->getDeclKind()) {
188  case Decl::TranslationUnit:
189    Out << "[translation unit] " << DC;
190    break;
191  case Decl::Namespace: {
192    Out << "[namespace] ";
193    const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
194    Out << *ND;
195    break;
196  }
197  case Decl::Enum: {
198    const EnumDecl* ED = cast<EnumDecl>(DC);
199    if (ED->isCompleteDefinition())
200      Out << "[enum] ";
201    else
202      Out << "<enum> ";
203    Out << *ED;
204    break;
205  }
206  case Decl::Record: {
207    const RecordDecl* RD = cast<RecordDecl>(DC);
208    if (RD->isCompleteDefinition())
209      Out << "[struct] ";
210    else
211      Out << "<struct> ";
212    Out << *RD;
213    break;
214  }
215  case Decl::CXXRecord: {
216    const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
217    if (RD->isCompleteDefinition())
218      Out << "[class] ";
219    else
220      Out << "<class> ";
221    Out << *RD << ' ' << DC;
222    break;
223  }
224  case Decl::ObjCMethod:
225    Out << "[objc method]";
226    break;
227  case Decl::ObjCInterface:
228    Out << "[objc interface]";
229    break;
230  case Decl::ObjCCategory:
231    Out << "[objc category]";
232    break;
233  case Decl::ObjCProtocol:
234    Out << "[objc protocol]";
235    break;
236  case Decl::ObjCImplementation:
237    Out << "[objc implementation]";
238    break;
239  case Decl::ObjCCategoryImpl:
240    Out << "[objc categoryimpl]";
241    break;
242  case Decl::LinkageSpec:
243    Out << "[linkage spec]";
244    break;
245  case Decl::Block:
246    Out << "[block]";
247    break;
248  case Decl::Function: {
249    const FunctionDecl* FD = cast<FunctionDecl>(DC);
250    if (FD->doesThisDeclarationHaveABody())
251      Out << "[function] ";
252    else
253      Out << "<function> ";
254    Out << *FD;
255    // Print the parameters.
256    Out << "(";
257    bool PrintComma = false;
258    for (FunctionDecl::param_const_iterator I = FD->param_begin(),
259           E = FD->param_end(); I != E; ++I) {
260      if (PrintComma)
261        Out << ", ";
262      else
263        PrintComma = true;
264      Out << **I;
265    }
266    Out << ")";
267    break;
268  }
269  case Decl::CXXMethod: {
270    const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
271    if (D->isOutOfLine())
272      Out << "[c++ method] ";
273    else if (D->isImplicit())
274      Out << "(c++ method) ";
275    else
276      Out << "<c++ method> ";
277    Out << *D;
278    // Print the parameters.
279    Out << "(";
280    bool PrintComma = false;
281    for (FunctionDecl::param_const_iterator I = D->param_begin(),
282           E = D->param_end(); I != E; ++I) {
283      if (PrintComma)
284        Out << ", ";
285      else
286        PrintComma = true;
287      Out << **I;
288    }
289    Out << ")";
290
291    // Check the semantic DeclContext.
292    const DeclContext* SemaDC = D->getDeclContext();
293    const DeclContext* LexicalDC = D->getLexicalDeclContext();
294    if (SemaDC != LexicalDC)
295      Out << " [[" << SemaDC << "]]";
296
297    break;
298  }
299  case Decl::CXXConstructor: {
300    const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
301    if (D->isOutOfLine())
302      Out << "[c++ ctor] ";
303    else if (D->isImplicit())
304      Out << "(c++ ctor) ";
305    else
306      Out << "<c++ ctor> ";
307    Out << *D;
308    // Print the parameters.
309    Out << "(";
310    bool PrintComma = false;
311    for (FunctionDecl::param_const_iterator I = D->param_begin(),
312           E = D->param_end(); I != E; ++I) {
313      if (PrintComma)
314        Out << ", ";
315      else
316        PrintComma = true;
317      Out << **I;
318    }
319    Out << ")";
320
321    // Check the semantic DC.
322    const DeclContext* SemaDC = D->getDeclContext();
323    const DeclContext* LexicalDC = D->getLexicalDeclContext();
324    if (SemaDC != LexicalDC)
325      Out << " [[" << SemaDC << "]]";
326    break;
327  }
328  case Decl::CXXDestructor: {
329    const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
330    if (D->isOutOfLine())
331      Out << "[c++ dtor] ";
332    else if (D->isImplicit())
333      Out << "(c++ dtor) ";
334    else
335      Out << "<c++ dtor> ";
336    Out << *D;
337    // Check the semantic DC.
338    const DeclContext* SemaDC = D->getDeclContext();
339    const DeclContext* LexicalDC = D->getLexicalDeclContext();
340    if (SemaDC != LexicalDC)
341      Out << " [[" << SemaDC << "]]";
342    break;
343  }
344  case Decl::CXXConversion: {
345    const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
346    if (D->isOutOfLine())
347      Out << "[c++ conversion] ";
348    else if (D->isImplicit())
349      Out << "(c++ conversion) ";
350    else
351      Out << "<c++ conversion> ";
352    Out << *D;
353    // Check the semantic DC.
354    const DeclContext* SemaDC = D->getDeclContext();
355    const DeclContext* LexicalDC = D->getLexicalDeclContext();
356    if (SemaDC != LexicalDC)
357      Out << " [[" << SemaDC << "]]";
358    break;
359  }
360
361  default:
362    llvm_unreachable("a decl that inherits DeclContext isn't handled");
363  }
364
365  Out << "\n";
366
367  // Print decls in the DeclContext.
368  for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
369       I != E; ++I) {
370    for (unsigned i = 0; i < Indentation; ++i)
371      Out << "  ";
372
373    Decl::Kind DK = I->getKind();
374    switch (DK) {
375    case Decl::Namespace:
376    case Decl::Enum:
377    case Decl::Record:
378    case Decl::CXXRecord:
379    case Decl::ObjCMethod:
380    case Decl::ObjCInterface:
381    case Decl::ObjCCategory:
382    case Decl::ObjCProtocol:
383    case Decl::ObjCImplementation:
384    case Decl::ObjCCategoryImpl:
385    case Decl::LinkageSpec:
386    case Decl::Block:
387    case Decl::Function:
388    case Decl::CXXMethod:
389    case Decl::CXXConstructor:
390    case Decl::CXXDestructor:
391    case Decl::CXXConversion:
392    {
393      DeclContext* DC = cast<DeclContext>(*I);
394      PrintDeclContext(DC, Indentation+2);
395      break;
396    }
397    case Decl::IndirectField: {
398      IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
399      Out << "<IndirectField> " << *IFD << '\n';
400      break;
401    }
402    case Decl::Label: {
403      LabelDecl *LD = cast<LabelDecl>(*I);
404      Out << "<Label> " << *LD << '\n';
405      break;
406    }
407    case Decl::Field: {
408      FieldDecl *FD = cast<FieldDecl>(*I);
409      Out << "<field> " << *FD << '\n';
410      break;
411    }
412    case Decl::Typedef:
413    case Decl::TypeAlias: {
414      TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
415      Out << "<typedef> " << *TD << '\n';
416      break;
417    }
418    case Decl::EnumConstant: {
419      EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
420      Out << "<enum constant> " << *ECD << '\n';
421      break;
422    }
423    case Decl::Var: {
424      VarDecl* VD = cast<VarDecl>(*I);
425      Out << "<var> " << *VD << '\n';
426      break;
427    }
428    case Decl::ImplicitParam: {
429      ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
430      Out << "<implicit parameter> " << *IPD << '\n';
431      break;
432    }
433    case Decl::ParmVar: {
434      ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
435      Out << "<parameter> " << *PVD << '\n';
436      break;
437    }
438    case Decl::ObjCProperty: {
439      ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
440      Out << "<objc property> " << *OPD << '\n';
441      break;
442    }
443    case Decl::FunctionTemplate: {
444      FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
445      Out << "<function template> " << *FTD << '\n';
446      break;
447    }
448    case Decl::FileScopeAsm: {
449      Out << "<file-scope asm>\n";
450      break;
451    }
452    case Decl::UsingDirective: {
453      Out << "<using directive>\n";
454      break;
455    }
456    case Decl::NamespaceAlias: {
457      NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
458      Out << "<namespace alias> " << *NAD << '\n';
459      break;
460    }
461    case Decl::ClassTemplate: {
462      ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
463      Out << "<class template> " << *CTD << '\n';
464      break;
465    }
466    case Decl::OMPThreadPrivate: {
467      Out << "<omp threadprivate> " << '"' << *I << "\"\n";
468      break;
469    }
470    default:
471      Out << "DeclKind: " << DK << '"' << *I << "\"\n";
472      llvm_unreachable("decl unhandled");
473    }
474  }
475}
476ASTConsumer *clang::CreateDeclContextPrinter() {
477  return new DeclContextPrinter();
478}
479
480//===----------------------------------------------------------------------===//
481/// ASTDumperXML - In-depth XML dumping.
482
483namespace {
484class ASTDumpXML : public ASTConsumer {
485  raw_ostream &OS;
486
487public:
488  ASTDumpXML(raw_ostream &OS) : OS(OS) {}
489
490  void HandleTranslationUnit(ASTContext &C) {
491    C.getTranslationUnitDecl()->dumpXML(OS);
492  }
493};
494}
495
496ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) {
497  return new ASTDumpXML(OS);
498}
499