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