ASTConsumers.cpp revision 202379
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    default:
425      Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
426      assert(0 && "decl unhandled");
427    }
428  }
429}
430ASTConsumer *clang::CreateDeclContextPrinter() {
431  return new DeclContextPrinter();
432}
433
434//===----------------------------------------------------------------------===//
435/// RecordLayoutDumper - C++ Record Layout Dumping.
436namespace {
437class RecordLayoutDumper : public ASTConsumer {
438  llvm::raw_ostream& Out;
439
440  void PrintOffset(uint64_t Offset, unsigned IndentLevel) {
441    Out << llvm::format("%4d | ", Offset);
442    for (unsigned I = 0; I < IndentLevel * 2; ++I) Out << ' ';
443  }
444
445  void DumpRecordLayoutOffsets(const CXXRecordDecl *RD, ASTContext &C,
446                               uint64_t Offset,
447                               unsigned IndentLevel, const char* Description,
448                               bool IncludeVirtualBases) {
449    const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
450
451    PrintOffset(Offset, IndentLevel);
452    Out << C.getTypeDeclType((CXXRecordDecl *)RD).getAsString();
453    if (Description)
454      Out << ' ' << Description;
455    if (RD->isEmpty())
456      Out << " (empty)";
457    Out << '\n';
458
459    IndentLevel++;
460
461    const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase();
462
463    // Vtable pointer.
464    if (RD->isDynamicClass() && !PrimaryBase) {
465      PrintOffset(Offset, IndentLevel);
466      Out << '(' << RD->getNameAsString() << " vtable pointer)\n";
467    }
468    // Dump (non-virtual) bases
469    for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
470         E = RD->bases_end(); I != E; ++I) {
471      assert(!I->getType()->isDependentType() &&
472             "Cannot layout class with dependent bases.");
473      if (I->isVirtual())
474        continue;
475
476      const CXXRecordDecl *Base =
477        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
478
479      uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8;
480
481      DumpRecordLayoutOffsets(Base, C, BaseOffset, IndentLevel,
482                              Base == PrimaryBase ? "(primary base)" : "(base)",
483                              /*IncludeVirtualBases=*/false);
484    }
485
486    // Dump fields.
487    uint64_t FieldNo = 0;
488    for (CXXRecordDecl::field_iterator I = RD->field_begin(),
489         E = RD->field_end(); I != E; ++I, ++FieldNo) {
490      const FieldDecl *Field = *I;
491      uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8;
492
493      if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
494        if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
495          DumpRecordLayoutOffsets(D, C, FieldOffset, IndentLevel,
496                                  Field->getNameAsCString(),
497                                  /*IncludeVirtualBases=*/true);
498          continue;
499        }
500      }
501
502      PrintOffset(FieldOffset, IndentLevel);
503      Out << Field->getType().getAsString() << ' ';
504      Out << Field->getNameAsString() << '\n';
505    }
506
507    if (!IncludeVirtualBases)
508      return;
509
510    // Dump virtual bases.
511    for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
512         E = RD->vbases_end(); I != E; ++I) {
513      assert(I->isVirtual() && "Found non-virtual class!");
514      const CXXRecordDecl *VBase =
515        cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
516
517      uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8;
518      DumpRecordLayoutOffsets(VBase, C, VBaseOffset, IndentLevel,
519                              VBase == PrimaryBase ?
520                              "(primary virtual base)" : "(virtual base)",
521                              /*IncludeVirtualBases=*/false);
522    }
523  }
524
525  // FIXME: Maybe this could be useful in ASTContext.cpp.
526  void DumpRecordLayout(const CXXRecordDecl *RD, ASTContext &C) {
527    const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
528
529    DumpRecordLayoutOffsets(RD, C, 0, 0, 0,
530                            /*IncludeVirtualBases=*/true);
531    Out << "  sizeof=" << Info.getSize() / 8;
532    Out << ", dsize=" << Info.getDataSize() / 8;
533    Out << ", align=" << Info.getAlignment() / 8 << '\n';
534    Out << "  nvsize=" << Info.getNonVirtualSize() / 8;
535    Out << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n';
536    Out << '\n';
537  }
538
539public:
540  RecordLayoutDumper() : Out(llvm::errs()) {}
541
542  void HandleTranslationUnit(ASTContext &C) {
543    for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end();
544         I != E; ++I) {
545      const RecordType *RT = dyn_cast<RecordType>(*I);
546      if (!RT)
547        continue;
548
549      const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
550      if (!RD)
551        continue;
552
553      if (RD->isImplicit())
554        continue;
555
556      if (RD->isDependentType())
557        continue;
558
559      if (RD->isInvalidDecl())
560        continue;
561
562      if (!RD->getDefinition(C))
563        continue;
564
565      // FIXME: Do we really need to hard code this?
566      if (RD->getQualifiedNameAsString() == "__va_list_tag")
567        continue;
568
569      DumpRecordLayout(RD, C);
570   }
571  }
572};
573} // end anonymous namespace
574ASTConsumer *clang::CreateRecordLayoutDumper() {
575  return new RecordLayoutDumper();
576}
577
578//===----------------------------------------------------------------------===//
579/// InheritanceViewer - C++ Inheritance Visualization
580
581namespace {
582class InheritanceViewer : public ASTConsumer {
583  const std::string clsname;
584public:
585  InheritanceViewer(const std::string& cname) : clsname(cname) {}
586
587  void HandleTranslationUnit(ASTContext &C) {
588    for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
589      if (RecordType *T = dyn_cast<RecordType>(*I)) {
590        if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) {
591          // FIXME: This lookup needs to be generalized to handle namespaces and
592          // (when we support them) templates.
593          if (D->getNameAsString() == clsname) {
594            D->viewInheritance(C);
595          }
596        }
597      }
598  }
599};
600}
601
602ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
603  return new InheritanceViewer(clsname);
604}
605