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