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