]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Frontend/ASTConsumers.cpp
Update clang to r94309.
[FreeBSD/FreeBSD.git] / lib / Frontend / ASTConsumers.cpp
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"
31 using namespace clang;
32
33 //===----------------------------------------------------------------------===//
34 /// ASTPrinter - Pretty-printer and dumper of ASTs
35
36 namespace {
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
53 ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
54   return new ASTPrinter(out);
55 }
56
57 //===----------------------------------------------------------------------===//
58 /// ASTPrinterXML - XML-printer of ASTs
59
60 namespace {
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
86 ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
87   return new ASTPrinterXML(out ? *out : llvm::outs());
88 }
89
90 ASTConsumer *clang::CreateASTDumper() {
91   return new ASTPrinter(0, true);
92 }
93
94 //===----------------------------------------------------------------------===//
95 /// ASTViewer - AST Visualization
96
97 namespace {
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
114 void 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
138 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
139
140 //===----------------------------------------------------------------------===//
141 /// DeclContextPrinter - Decl and DeclContext Visualization
142
143 namespace {
144
145 class DeclContextPrinter : public ASTConsumer {
146   llvm::raw_ostream& Out;
147 public:
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
158 void 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 }
435 ASTConsumer *clang::CreateDeclContextPrinter() {
436   return new DeclContextPrinter();
437 }
438
439 //===----------------------------------------------------------------------===//
440 /// RecordLayoutDumper - C++ Record Layout Dumping.
441 namespace {
442 class 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   
544 public:
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(C))
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
579 ASTConsumer *clang::CreateRecordLayoutDumper() {
580   return new RecordLayoutDumper();
581 }
582
583 //===----------------------------------------------------------------------===//
584 /// InheritanceViewer - C++ Inheritance Visualization
585
586 namespace {
587 class InheritanceViewer : public ASTConsumer {
588   const std::string clsname;
589 public:
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
607 ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
608   return new InheritanceViewer(clsname);
609 }