]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / 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/Basic/Diagnostic.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Basic/FileManager.h"
18 #include "clang/AST/AST.h"
19 #include "clang/AST/ASTConsumer.h"
20 #include "clang/AST/ASTContext.h"
21 #include "clang/AST/RecordLayout.h"
22 #include "clang/AST/PrettyPrinter.h"
23 #include "llvm/Module.h"
24 #include "llvm/Support/Timer.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Support/Path.h"
27 using namespace clang;
28
29 //===----------------------------------------------------------------------===//
30 /// ASTPrinter - Pretty-printer and dumper of ASTs
31
32 namespace {
33   class ASTPrinter : public ASTConsumer {
34     llvm::raw_ostream &Out;
35     bool Dump;
36
37   public:
38     ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
39       : Out(o? *o : llvm::outs()), Dump(Dump) { }
40
41     virtual void HandleTranslationUnit(ASTContext &Context) {
42       PrintingPolicy Policy = Context.PrintingPolicy;
43       Policy.Dump = Dump;
44       Context.getTranslationUnitDecl()->print(Out, Policy);
45     }
46   };
47 } // end anonymous namespace
48
49 ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
50   return new ASTPrinter(out);
51 }
52
53 ASTConsumer *clang::CreateASTDumper() {
54   return new ASTPrinter(0, true);
55 }
56
57 //===----------------------------------------------------------------------===//
58 /// ASTViewer - AST Visualization
59
60 namespace {
61   class ASTViewer : public ASTConsumer {
62     ASTContext *Context;
63   public:
64     void Initialize(ASTContext &Context) {
65       this->Context = &Context;
66     }
67
68     virtual void HandleTopLevelDecl(DeclGroupRef D) {
69       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
70         HandleTopLevelSingleDecl(*I);
71     }
72
73     void HandleTopLevelSingleDecl(Decl *D);
74   };
75 }
76
77 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
78   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
79     D->print(llvm::errs());
80   
81     if (Stmt *Body = D->getBody()) {
82       llvm::errs() << '\n';
83       Body->viewAST();
84       llvm::errs() << '\n';
85     }
86   }
87 }
88
89
90 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
91
92 //===----------------------------------------------------------------------===//
93 /// DeclContextPrinter - Decl and DeclContext Visualization
94
95 namespace {
96
97 class DeclContextPrinter : public ASTConsumer {
98   llvm::raw_ostream& Out;
99 public:
100   DeclContextPrinter() : Out(llvm::errs()) {}
101
102   void HandleTranslationUnit(ASTContext &C) {
103     PrintDeclContext(C.getTranslationUnitDecl(), 4);
104   }
105
106   void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
107 };
108 }  // end anonymous namespace
109
110 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
111                                           unsigned Indentation) {
112   // Print DeclContext name.
113   switch (DC->getDeclKind()) {
114   case Decl::TranslationUnit:
115     Out << "[translation unit] " << DC;
116     break;
117   case Decl::Namespace: {
118     Out << "[namespace] ";
119     const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
120     Out << ND;
121     break;
122   }
123   case Decl::Enum: {
124     const EnumDecl* ED = cast<EnumDecl>(DC);
125     if (ED->isDefinition())
126       Out << "[enum] ";
127     else
128       Out << "<enum> ";
129     Out << ED;
130     break;
131   }
132   case Decl::Record: {
133     const RecordDecl* RD = cast<RecordDecl>(DC);
134     if (RD->isDefinition())
135       Out << "[struct] ";
136     else
137       Out << "<struct> ";
138     Out << RD;
139     break;
140   }
141   case Decl::CXXRecord: {
142     const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
143     if (RD->isDefinition())
144       Out << "[class] ";
145     else
146       Out << "<class> ";
147     Out << RD << ' ' << DC;
148     break;
149   }
150   case Decl::ObjCMethod:
151     Out << "[objc method]";
152     break;
153   case Decl::ObjCInterface:
154     Out << "[objc interface]";
155     break;
156   case Decl::ObjCCategory:
157     Out << "[objc category]";
158     break;
159   case Decl::ObjCProtocol:
160     Out << "[objc protocol]";
161     break;
162   case Decl::ObjCImplementation:
163     Out << "[objc implementation]";
164     break;
165   case Decl::ObjCCategoryImpl:
166     Out << "[objc categoryimpl]";
167     break;
168   case Decl::LinkageSpec:
169     Out << "[linkage spec]";
170     break;
171   case Decl::Block:
172     Out << "[block]";
173     break;
174   case Decl::Function: {
175     const FunctionDecl* FD = cast<FunctionDecl>(DC);
176     if (FD->doesThisDeclarationHaveABody())
177       Out << "[function] ";
178     else
179       Out << "<function> ";
180     Out << FD;
181     // Print the parameters.
182     Out << "(";
183     bool PrintComma = false;
184     for (FunctionDecl::param_const_iterator I = FD->param_begin(),
185            E = FD->param_end(); I != E; ++I) {
186       if (PrintComma)
187         Out << ", ";
188       else
189         PrintComma = true;
190       Out << *I;
191     }
192     Out << ")";
193     break;
194   }
195   case Decl::CXXMethod: {
196     const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
197     if (D->isOutOfLine())
198       Out << "[c++ method] ";
199     else if (D->isImplicit())
200       Out << "(c++ method) ";
201     else
202       Out << "<c++ method> ";
203     Out << D;
204     // Print the parameters.
205     Out << "(";
206     bool PrintComma = false;
207     for (FunctionDecl::param_const_iterator I = D->param_begin(),
208            E = D->param_end(); I != E; ++I) {
209       if (PrintComma)
210         Out << ", ";
211       else
212         PrintComma = true;
213       Out << *I;
214     }
215     Out << ")";
216
217     // Check the semantic DeclContext.
218     const DeclContext* SemaDC = D->getDeclContext();
219     const DeclContext* LexicalDC = D->getLexicalDeclContext();
220     if (SemaDC != LexicalDC)
221       Out << " [[" << SemaDC << "]]";
222
223     break;
224   }
225   case Decl::CXXConstructor: {
226     const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
227     if (D->isOutOfLine())
228       Out << "[c++ ctor] ";
229     else if (D->isImplicit())
230       Out << "(c++ ctor) ";
231     else
232       Out << "<c++ ctor> ";
233     Out << D;
234     // Print the parameters.
235     Out << "(";
236     bool PrintComma = false;
237     for (FunctionDecl::param_const_iterator I = D->param_begin(),
238            E = D->param_end(); I != E; ++I) {
239       if (PrintComma)
240         Out << ", ";
241       else
242         PrintComma = true;
243       Out << *I;
244     }
245     Out << ")";
246
247     // Check the semantic DC.
248     const DeclContext* SemaDC = D->getDeclContext();
249     const DeclContext* LexicalDC = D->getLexicalDeclContext();
250     if (SemaDC != LexicalDC)
251       Out << " [[" << SemaDC << "]]";
252     break;
253   }
254   case Decl::CXXDestructor: {
255     const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
256     if (D->isOutOfLine())
257       Out << "[c++ dtor] ";
258     else if (D->isImplicit())
259       Out << "(c++ dtor) ";
260     else
261       Out << "<c++ dtor> ";
262     Out << D;
263     // Check the semantic DC.
264     const DeclContext* SemaDC = D->getDeclContext();
265     const DeclContext* LexicalDC = D->getLexicalDeclContext();
266     if (SemaDC != LexicalDC)
267       Out << " [[" << SemaDC << "]]";
268     break;
269   }
270   case Decl::CXXConversion: {
271     const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
272     if (D->isOutOfLine())
273       Out << "[c++ conversion] ";
274     else if (D->isImplicit())
275       Out << "(c++ conversion) ";
276     else
277       Out << "<c++ conversion> ";
278     Out << D;
279     // Check the semantic DC.
280     const DeclContext* SemaDC = D->getDeclContext();
281     const DeclContext* LexicalDC = D->getLexicalDeclContext();
282     if (SemaDC != LexicalDC)
283       Out << " [[" << SemaDC << "]]";
284     break;
285   }
286
287   default:
288     assert(0 && "a decl that inherits DeclContext isn't handled");
289   }
290
291   Out << "\n";
292
293   // Print decls in the DeclContext.
294   for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
295        I != E; ++I) {
296     for (unsigned i = 0; i < Indentation; ++i)
297       Out << "  ";
298
299     Decl::Kind DK = I->getKind();
300     switch (DK) {
301     case Decl::Namespace:
302     case Decl::Enum:
303     case Decl::Record:
304     case Decl::CXXRecord:
305     case Decl::ObjCMethod:
306     case Decl::ObjCInterface:
307     case Decl::ObjCCategory:
308     case Decl::ObjCProtocol:
309     case Decl::ObjCImplementation:
310     case Decl::ObjCCategoryImpl:
311     case Decl::LinkageSpec:
312     case Decl::Block:
313     case Decl::Function:
314     case Decl::CXXMethod:
315     case Decl::CXXConstructor:
316     case Decl::CXXDestructor:
317     case Decl::CXXConversion:
318     {
319       DeclContext* DC = cast<DeclContext>(*I);
320       PrintDeclContext(DC, Indentation+2);
321       break;
322     }
323     case Decl::IndirectField: {
324       IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
325       Out << "<IndirectField> " << IFD << '\n';
326       break;
327     }
328     case Decl::Label: {
329       LabelDecl *LD = cast<LabelDecl>(*I);
330       Out << "<Label> " << LD << '\n';
331       break;
332     }
333     case Decl::Field: {
334       FieldDecl *FD = cast<FieldDecl>(*I);
335       Out << "<field> " << FD << '\n';
336       break;
337     }
338     case Decl::Typedef:
339     case Decl::TypeAlias: {
340       TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
341       Out << "<typedef> " << TD << '\n';
342       break;
343     }
344     case Decl::EnumConstant: {
345       EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
346       Out << "<enum constant> " << ECD << '\n';
347       break;
348     }
349     case Decl::Var: {
350       VarDecl* VD = cast<VarDecl>(*I);
351       Out << "<var> " << VD << '\n';
352       break;
353     }
354     case Decl::ImplicitParam: {
355       ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
356       Out << "<implicit parameter> " << IPD << '\n';
357       break;
358     }
359     case Decl::ParmVar: {
360       ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
361       Out << "<parameter> " << PVD << '\n';
362       break;
363     }
364     case Decl::ObjCProperty: {
365       ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
366       Out << "<objc property> " << OPD << '\n';
367       break;
368     }
369     case Decl::FunctionTemplate: {
370       FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
371       Out << "<function template> " << FTD << '\n';
372       break;
373     }
374     case Decl::FileScopeAsm: {
375       Out << "<file-scope asm>\n";
376       break;
377     }
378     case Decl::UsingDirective: {
379       Out << "<using directive>\n";
380       break;
381     }
382     case Decl::NamespaceAlias: {
383       NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
384       Out << "<namespace alias> " << NAD << '\n';
385       break;
386     }
387     case Decl::ClassTemplate: {
388       ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
389       Out << "<class template> " << CTD << '\n';
390       break;
391     }
392     default:
393       Out << "DeclKind: " << DK << '"' << *I << "\"\n";
394       assert(0 && "decl unhandled");
395     }
396   }
397 }
398 ASTConsumer *clang::CreateDeclContextPrinter() {
399   return new DeclContextPrinter();
400 }
401
402 //===----------------------------------------------------------------------===//
403 /// ASTDumperXML - In-depth XML dumping.
404
405 namespace {
406 class ASTDumpXML : public ASTConsumer {
407   llvm::raw_ostream &OS;
408
409 public:
410   ASTDumpXML(llvm::raw_ostream &OS) : OS(OS) {}
411
412   void HandleTranslationUnit(ASTContext &C) {
413     C.getTranslationUnitDecl()->dumpXML(OS);
414   }  
415 };
416 }
417
418 ASTConsumer *clang::CreateASTDumperXML(llvm::raw_ostream &OS) {
419   return new ASTDumpXML(OS);
420 }