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