ASTConsumers.cpp revision 203955
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/RecordLayout.h"
24#include "clang/AST/PrettyPrinter.h"
25#include "clang/CodeGen/ModuleBuilder.h"
26#include "llvm/Module.h"
27#include "llvm/Support/Format.h"
28#include "llvm/Support/Timer.h"
29#include "llvm/Support/raw_ostream.h"
30#include "llvm/System/Path.h"
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        Doc.PrintDecl(*D);
79      Doc.toParent();
80      Doc.finalize();
81    }
82  };
83} // end anonymous namespace
84
85
86ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
87  return new ASTPrinterXML(out ? *out : llvm::outs());
88}
89
90ASTConsumer *clang::CreateASTDumper() {
91  return new ASTPrinter(0, true);
92}
93
94//===----------------------------------------------------------------------===//
95/// ASTViewer - AST Visualization
96
97namespace {
98  class ASTViewer : public ASTConsumer {
99    ASTContext *Context;
100  public:
101    void Initialize(ASTContext &Context) {
102      this->Context = &Context;
103    }
104
105    virtual void HandleTopLevelDecl(DeclGroupRef D) {
106      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
107        HandleTopLevelSingleDecl(*I);
108    }
109
110    void HandleTopLevelSingleDecl(Decl *D);
111  };
112}
113
114void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
115  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
116    FD->print(llvm::errs());
117
118    if (Stmt *Body = FD->getBody()) {
119      llvm::errs() << '\n';
120      Body->viewAST();
121      llvm::errs() << '\n';
122    }
123    return;
124  }
125
126  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
127    MD->print(llvm::errs());
128
129    if (MD->getBody()) {
130      llvm::errs() << '\n';
131      MD->getBody()->viewAST();
132      llvm::errs() << '\n';
133    }
134  }
135}
136
137
138ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
139
140//===----------------------------------------------------------------------===//
141/// DeclContextPrinter - Decl and DeclContext Visualization
142
143namespace {
144
145class DeclContextPrinter : public ASTConsumer {
146  llvm::raw_ostream& Out;
147public:
148  DeclContextPrinter() : Out(llvm::errs()) {}
149
150  void HandleTranslationUnit(ASTContext &C) {
151    PrintDeclContext(C.getTranslationUnitDecl(), 4);
152  }
153
154  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
155};
156}  // end anonymous namespace
157
158void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
159                                          unsigned Indentation) {
160  // Print DeclContext name.
161  switch (DC->getDeclKind()) {
162  case Decl::TranslationUnit:
163    Out << "[translation unit] " << DC;
164    break;
165  case Decl::Namespace: {
166    Out << "[namespace] ";
167    const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
168    Out << ND->getNameAsString();
169    break;
170  }
171  case Decl::Enum: {
172    const EnumDecl* ED = cast<EnumDecl>(DC);
173    if (ED->isDefinition())
174      Out << "[enum] ";
175    else
176      Out << "<enum> ";
177    Out << ED->getNameAsString();
178    break;
179  }
180  case Decl::Record: {
181    const RecordDecl* RD = cast<RecordDecl>(DC);
182    if (RD->isDefinition())
183      Out << "[struct] ";
184    else
185      Out << "<struct> ";
186    Out << RD->getNameAsString();
187    break;
188  }
189  case Decl::CXXRecord: {
190    const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
191    if (RD->isDefinition())
192      Out << "[class] ";
193    else
194      Out << "<class> ";
195    Out << RD->getNameAsString() << " " << DC;
196    break;
197  }
198  case Decl::ObjCMethod:
199    Out << "[objc method]";
200    break;
201  case Decl::ObjCInterface:
202    Out << "[objc interface]";
203    break;
204  case Decl::ObjCCategory:
205    Out << "[objc category]";
206    break;
207  case Decl::ObjCProtocol:
208    Out << "[objc protocol]";
209    break;
210  case Decl::ObjCImplementation:
211    Out << "[objc implementation]";
212    break;
213  case Decl::ObjCCategoryImpl:
214    Out << "[objc categoryimpl]";
215    break;
216  case Decl::LinkageSpec:
217    Out << "[linkage spec]";
218    break;
219  case Decl::Block:
220    Out << "[block]";
221    break;
222  case Decl::Function: {
223    const FunctionDecl* FD = cast<FunctionDecl>(DC);
224    if (FD->isThisDeclarationADefinition())
225      Out << "[function] ";
226    else
227      Out << "<function> ";
228    Out << FD->getNameAsString();
229    // Print the parameters.
230    Out << "(";
231    bool PrintComma = false;
232    for (FunctionDecl::param_const_iterator I = FD->param_begin(),
233           E = FD->param_end(); I != E; ++I) {
234      if (PrintComma)
235        Out << ", ";
236      else
237        PrintComma = true;
238      Out << (*I)->getNameAsString();
239    }
240    Out << ")";
241    break;
242  }
243  case Decl::CXXMethod: {
244    const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
245    if (D->isOutOfLine())
246      Out << "[c++ method] ";
247    else if (D->isImplicit())
248      Out << "(c++ method) ";
249    else
250      Out << "<c++ method> ";
251    Out << D->getNameAsString();
252    // Print the parameters.
253    Out << "(";
254    bool PrintComma = false;
255    for (FunctionDecl::param_const_iterator I = D->param_begin(),
256           E = D->param_end(); I != E; ++I) {
257      if (PrintComma)
258        Out << ", ";
259      else
260        PrintComma = true;
261      Out << (*I)->getNameAsString();
262    }
263    Out << ")";
264
265    // Check the semantic DeclContext.
266    const DeclContext* SemaDC = D->getDeclContext();
267    const DeclContext* LexicalDC = D->getLexicalDeclContext();
268    if (SemaDC != LexicalDC)
269      Out << " [[" << SemaDC << "]]";
270
271    break;
272  }
273  case Decl::CXXConstructor: {
274    const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
275    if (D->isOutOfLine())
276      Out << "[c++ ctor] ";
277    else if (D->isImplicit())
278      Out << "(c++ ctor) ";
279    else
280      Out << "<c++ ctor> ";
281    Out << D->getNameAsString();
282    // Print the parameters.
283    Out << "(";
284    bool PrintComma = false;
285    for (FunctionDecl::param_const_iterator I = D->param_begin(),
286           E = D->param_end(); I != E; ++I) {
287      if (PrintComma)
288        Out << ", ";
289      else
290        PrintComma = true;
291      Out << (*I)->getNameAsString();
292    }
293    Out << ")";
294
295    // Check the semantic DC.
296    const DeclContext* SemaDC = D->getDeclContext();
297    const DeclContext* LexicalDC = D->getLexicalDeclContext();
298    if (SemaDC != LexicalDC)
299      Out << " [[" << SemaDC << "]]";
300    break;
301  }
302  case Decl::CXXDestructor: {
303    const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
304    if (D->isOutOfLine())
305      Out << "[c++ dtor] ";
306    else if (D->isImplicit())
307      Out << "(c++ dtor) ";
308    else
309      Out << "<c++ dtor> ";
310    Out << D->getNameAsString();
311    // Check the semantic DC.
312    const DeclContext* SemaDC = D->getDeclContext();
313    const DeclContext* LexicalDC = D->getLexicalDeclContext();
314    if (SemaDC != LexicalDC)
315      Out << " [[" << SemaDC << "]]";
316    break;
317  }
318  case Decl::CXXConversion: {
319    const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
320    if (D->isOutOfLine())
321      Out << "[c++ conversion] ";
322    else if (D->isImplicit())
323      Out << "(c++ conversion) ";
324    else
325      Out << "<c++ conversion> ";
326    Out << D->getNameAsString();
327    // Check the semantic DC.
328    const DeclContext* SemaDC = D->getDeclContext();
329    const DeclContext* LexicalDC = D->getLexicalDeclContext();
330    if (SemaDC != LexicalDC)
331      Out << " [[" << SemaDC << "]]";
332    break;
333  }
334
335  default:
336    assert(0 && "a decl that inherits DeclContext isn't handled");
337  }
338
339  Out << "\n";
340
341  // Print decls in the DeclContext.
342  for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
343       I != E; ++I) {
344    for (unsigned i = 0; i < Indentation; ++i)
345      Out << "  ";
346
347    Decl::Kind DK = I->getKind();
348    switch (DK) {
349    case Decl::Namespace:
350    case Decl::Enum:
351    case Decl::Record:
352    case Decl::CXXRecord:
353    case Decl::ObjCMethod:
354    case Decl::ObjCInterface:
355    case Decl::ObjCCategory:
356    case Decl::ObjCProtocol:
357    case Decl::ObjCImplementation:
358    case Decl::ObjCCategoryImpl:
359    case Decl::LinkageSpec:
360    case Decl::Block:
361    case Decl::Function:
362    case Decl::CXXMethod:
363    case Decl::CXXConstructor:
364    case Decl::CXXDestructor:
365    case Decl::CXXConversion:
366    {
367      DeclContext* DC = cast<DeclContext>(*I);
368      PrintDeclContext(DC, Indentation+2);
369      break;
370    }
371    case Decl::Field: {
372      FieldDecl* FD = cast<FieldDecl>(*I);
373      Out << "<field> " << FD->getNameAsString() << "\n";
374      break;
375    }
376    case Decl::Typedef: {
377      TypedefDecl* TD = cast<TypedefDecl>(*I);
378      Out << "<typedef> " << TD->getNameAsString() << "\n";
379      break;
380    }
381    case Decl::EnumConstant: {
382      EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
383      Out << "<enum constant> " << ECD->getNameAsString() << "\n";
384      break;
385    }
386    case Decl::Var: {
387      VarDecl* VD = cast<VarDecl>(*I);
388      Out << "<var> " << VD->getNameAsString() << "\n";
389      break;
390    }
391    case Decl::ImplicitParam: {
392      ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
393      Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
394      break;
395    }
396    case Decl::ParmVar: {
397      ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
398      Out << "<parameter> " << PVD->getNameAsString() << "\n";
399      break;
400    }
401    case Decl::ObjCProperty: {
402      ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
403      Out << "<objc property> " << OPD->getNameAsString() << "\n";
404      break;
405    }
406    case Decl::FunctionTemplate: {
407      FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
408      Out << "<function template> " << FTD->getNameAsString() << "\n";
409      break;
410    }
411    case Decl::FileScopeAsm: {
412      Out << "<file-scope asm>\n";
413      break;
414    }
415    case Decl::UsingDirective: {
416      Out << "<using directive>\n";
417      break;
418    }
419    case Decl::NamespaceAlias: {
420      NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
421      Out << "<namespace alias> " << NAD->getNameAsString() << "\n";
422      break;
423    }
424    case Decl::ClassTemplate: {
425      ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
426      Out << "<class template> " << CTD->getNameAsString() << '\n';
427      break;
428    }
429    default:
430      Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
431      assert(0 && "decl unhandled");
432    }
433  }
434}
435ASTConsumer *clang::CreateDeclContextPrinter() {
436  return new DeclContextPrinter();
437}
438
439//===----------------------------------------------------------------------===//
440/// RecordLayoutDumper - C++ Record Layout Dumping.
441namespace {
442class RecordLayoutDumper : public ASTConsumer {
443  llvm::raw_ostream& Out;
444
445  void PrintOffset(uint64_t Offset, unsigned IndentLevel) {
446    Out << llvm::format("%4d | ", Offset);
447    for (unsigned I = 0; I < IndentLevel * 2; ++I) Out << ' ';
448  }
449
450  void DumpRecordLayoutOffsets(const CXXRecordDecl *RD, ASTContext &C,
451                               uint64_t Offset,
452                               unsigned IndentLevel, const char* Description,
453                               bool IncludeVirtualBases) {
454    const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
455
456    PrintOffset(Offset, IndentLevel);
457    Out << C.getTypeDeclType((CXXRecordDecl *)RD).getAsString();
458    if (Description)
459      Out << ' ' << Description;
460    if (RD->isEmpty())
461      Out << " (empty)";
462    Out << '\n';
463
464    IndentLevel++;
465
466    const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase();
467
468    // Vtable pointer.
469    if (RD->isDynamicClass() && !PrimaryBase) {
470      PrintOffset(Offset, IndentLevel);
471      Out << '(' << RD->getNameAsString() << " vtable pointer)\n";
472    }
473    // Dump (non-virtual) bases
474    for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
475         E = RD->bases_end(); I != E; ++I) {
476      assert(!I->getType()->isDependentType() &&
477             "Cannot layout class with dependent bases.");
478      if (I->isVirtual())
479        continue;
480
481      const CXXRecordDecl *Base =
482        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
483
484      uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8;
485
486      DumpRecordLayoutOffsets(Base, C, BaseOffset, IndentLevel,
487                              Base == PrimaryBase ? "(primary base)" : "(base)",
488                              /*IncludeVirtualBases=*/false);
489    }
490
491    // Dump fields.
492    uint64_t FieldNo = 0;
493    for (CXXRecordDecl::field_iterator I = RD->field_begin(),
494         E = RD->field_end(); I != E; ++I, ++FieldNo) {
495      const FieldDecl *Field = *I;
496      uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8;
497
498      if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
499        if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
500          DumpRecordLayoutOffsets(D, C, FieldOffset, IndentLevel,
501                                  Field->getNameAsCString(),
502                                  /*IncludeVirtualBases=*/true);
503          continue;
504        }
505      }
506
507      PrintOffset(FieldOffset, IndentLevel);
508      Out << Field->getType().getAsString() << ' ';
509      Out << Field->getNameAsString() << '\n';
510    }
511
512    if (!IncludeVirtualBases)
513      return;
514
515    // Dump virtual bases.
516    for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
517         E = RD->vbases_end(); I != E; ++I) {
518      assert(I->isVirtual() && "Found non-virtual class!");
519      const CXXRecordDecl *VBase =
520        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
521
522      uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8;
523      DumpRecordLayoutOffsets(VBase, C, VBaseOffset, IndentLevel,
524                              VBase == PrimaryBase ?
525                              "(primary virtual base)" : "(virtual base)",
526                              /*IncludeVirtualBases=*/false);
527    }
528  }
529
530  // FIXME: Maybe this could be useful in ASTContext.cpp.
531  void DumpRecordLayout(const CXXRecordDecl *RD, ASTContext &C) {
532    const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
533
534    DumpRecordLayoutOffsets(RD, C, 0, 0, 0,
535                            /*IncludeVirtualBases=*/true);
536    Out << "  sizeof=" << Info.getSize() / 8;
537    Out << ", dsize=" << Info.getDataSize() / 8;
538    Out << ", align=" << Info.getAlignment() / 8 << '\n';
539    Out << "  nvsize=" << Info.getNonVirtualSize() / 8;
540    Out << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n';
541    Out << '\n';
542  }
543
544public:
545  RecordLayoutDumper() : Out(llvm::errs()) {}
546
547  void HandleTranslationUnit(ASTContext &C) {
548    for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end();
549         I != E; ++I) {
550      const RecordType *RT = dyn_cast<RecordType>(*I);
551      if (!RT)
552        continue;
553
554      const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
555      if (!RD)
556        continue;
557
558      if (RD->isImplicit())
559        continue;
560
561      if (RD->isDependentType())
562        continue;
563
564      if (RD->isInvalidDecl())
565        continue;
566
567      if (!RD->getDefinition())
568        continue;
569
570      // FIXME: Do we really need to hard code this?
571      if (RD->getQualifiedNameAsString() == "__va_list_tag")
572        continue;
573
574      DumpRecordLayout(RD, C);
575   }
576  }
577};
578} // end anonymous namespace
579ASTConsumer *clang::CreateRecordLayoutDumper() {
580  return new RecordLayoutDumper();
581}
582
583//===----------------------------------------------------------------------===//
584/// InheritanceViewer - C++ Inheritance Visualization
585
586namespace {
587class InheritanceViewer : public ASTConsumer {
588  const std::string clsname;
589public:
590  InheritanceViewer(const std::string& cname) : clsname(cname) {}
591
592  void HandleTranslationUnit(ASTContext &C) {
593    for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
594      if (RecordType *T = dyn_cast<RecordType>(*I)) {
595        if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) {
596          // FIXME: This lookup needs to be generalized to handle namespaces and
597          // (when we support them) templates.
598          if (D->getNameAsString() == clsname) {
599            D->viewInheritance(C);
600          }
601        }
602      }
603  }
604};
605}
606
607ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
608  return new InheritanceViewer(clsname);
609}
610