]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Frontend/ASTConsumers.cpp
Import Clang, at r72732.
[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/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"
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, Context, 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(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
87 ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
88   return new ASTPrinterXML(out ? *out : llvm::outs());
89 }
90  
91 ASTConsumer *clang::CreateASTDumper() { 
92   return new ASTPrinter(0, true); 
93 }
94
95 //===----------------------------------------------------------------------===//
96 /// ASTViewer - AST Visualization
97
98 namespace {
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
115 void 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
139 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
140
141 //===----------------------------------------------------------------------===//
142 /// DeclContextPrinter - Decl and DeclContext Visualization
143
144 namespace {
145
146 class DeclContextPrinter : public ASTConsumer {
147   llvm::raw_ostream& Out;
148 public:
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
159 void 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->isOutOfLineDefinition())
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->isOutOfLineDefinition())
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->isOutOfLineDefinition())
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->isOutOfLineDefinition())
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 }
421 ASTConsumer *clang::CreateDeclContextPrinter() { 
422   return new DeclContextPrinter(); 
423 }
424
425 //===----------------------------------------------------------------------===//
426 /// InheritanceViewer - C++ Inheritance Visualization
427
428 namespace {
429 class InheritanceViewer : public ASTConsumer {
430   const std::string clsname;
431 public:
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
449 ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
450   return new InheritanceViewer(clsname);
451 }