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