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