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