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