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