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(llvm::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       Out << D->getQualifiedNameAsString() << "\n";
108       return true;
109     }
110 
111   private:
112     raw_ostream &Out;
113   };
114 } // end anonymous namespace
115 
116 ASTConsumer *clang::CreateASTPrinter(raw_ostream *Out,
117                                      StringRef FilterString) {
118   return new ASTPrinter(Out, /*Dump=*/ false, FilterString);
119 }
120 
121 ASTConsumer *clang::CreateASTDumper(StringRef FilterString) {
122   return new ASTPrinter(0, /*Dump=*/ true, FilterString);
123 }
124 
125 ASTConsumer *clang::CreateASTDeclNodeLister() {
126   return new ASTDeclNodeLister(0);
127 }
128 
129 //===----------------------------------------------------------------------===//
130 /// ASTViewer - AST Visualization
131 
132 namespace {
133   class ASTViewer : public ASTConsumer {
134     ASTContext *Context;
135   public:
136     void Initialize(ASTContext &Context) {
137       this->Context = &Context;
138     }
139 
140     virtual bool HandleTopLevelDecl(DeclGroupRef D) {
141       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
142         HandleTopLevelSingleDecl(*I);
143       return true;
144     }
145 
146     void HandleTopLevelSingleDecl(Decl *D);
147   };
148 }
149 
150 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
151   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
152     D->print(llvm::errs());
153 
154     if (Stmt *Body = D->getBody()) {
155       llvm::errs() << '\n';
156       Body->viewAST();
157       llvm::errs() << '\n';
158     }
159   }
160 }
161 
162 
163 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
164 
165 //===----------------------------------------------------------------------===//
166 /// DeclContextPrinter - Decl and DeclContext Visualization
167 
168 namespace {
169 
170 class DeclContextPrinter : public ASTConsumer {
171   raw_ostream& Out;
172 public:
173   DeclContextPrinter() : Out(llvm::errs()) {}
174 
175   void HandleTranslationUnit(ASTContext &C) {
176     PrintDeclContext(C.getTranslationUnitDecl(), 4);
177   }
178 
179   void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
180 };
181 }  // end anonymous namespace
182 
183 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
184                                           unsigned Indentation) {
185   // Print DeclContext name.
186   switch (DC->getDeclKind()) {
187   case Decl::TranslationUnit:
188     Out << "[translation unit] " << DC;
189     break;
190   case Decl::Namespace: {
191     Out << "[namespace] ";
192     const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
193     Out << *ND;
194     break;
195   }
196   case Decl::Enum: {
197     const EnumDecl* ED = cast<EnumDecl>(DC);
198     if (ED->isCompleteDefinition())
199       Out << "[enum] ";
200     else
201       Out << "<enum> ";
202     Out << *ED;
203     break;
204   }
205   case Decl::Record: {
206     const RecordDecl* RD = cast<RecordDecl>(DC);
207     if (RD->isCompleteDefinition())
208       Out << "[struct] ";
209     else
210       Out << "<struct> ";
211     Out << *RD;
212     break;
213   }
214   case Decl::CXXRecord: {
215     const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
216     if (RD->isCompleteDefinition())
217       Out << "[class] ";
218     else
219       Out << "<class> ";
220     Out << *RD << ' ' << DC;
221     break;
222   }
223   case Decl::ObjCMethod:
224     Out << "[objc method]";
225     break;
226   case Decl::ObjCInterface:
227     Out << "[objc interface]";
228     break;
229   case Decl::ObjCCategory:
230     Out << "[objc category]";
231     break;
232   case Decl::ObjCProtocol:
233     Out << "[objc protocol]";
234     break;
235   case Decl::ObjCImplementation:
236     Out << "[objc implementation]";
237     break;
238   case Decl::ObjCCategoryImpl:
239     Out << "[objc categoryimpl]";
240     break;
241   case Decl::LinkageSpec:
242     Out << "[linkage spec]";
243     break;
244   case Decl::Block:
245     Out << "[block]";
246     break;
247   case Decl::Function: {
248     const FunctionDecl* FD = cast<FunctionDecl>(DC);
249     if (FD->doesThisDeclarationHaveABody())
250       Out << "[function] ";
251     else
252       Out << "<function> ";
253     Out << *FD;
254     // Print the parameters.
255     Out << "(";
256     bool PrintComma = false;
257     for (FunctionDecl::param_const_iterator I = FD->param_begin(),
258            E = FD->param_end(); I != E; ++I) {
259       if (PrintComma)
260         Out << ", ";
261       else
262         PrintComma = true;
263       Out << **I;
264     }
265     Out << ")";
266     break;
267   }
268   case Decl::CXXMethod: {
269     const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
270     if (D->isOutOfLine())
271       Out << "[c++ method] ";
272     else if (D->isImplicit())
273       Out << "(c++ method) ";
274     else
275       Out << "<c++ method> ";
276     Out << *D;
277     // Print the parameters.
278     Out << "(";
279     bool PrintComma = false;
280     for (FunctionDecl::param_const_iterator I = D->param_begin(),
281            E = D->param_end(); I != E; ++I) {
282       if (PrintComma)
283         Out << ", ";
284       else
285         PrintComma = true;
286       Out << **I;
287     }
288     Out << ")";
289 
290     // Check the semantic DeclContext.
291     const DeclContext* SemaDC = D->getDeclContext();
292     const DeclContext* LexicalDC = D->getLexicalDeclContext();
293     if (SemaDC != LexicalDC)
294       Out << " [[" << SemaDC << "]]";
295 
296     break;
297   }
298   case Decl::CXXConstructor: {
299     const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
300     if (D->isOutOfLine())
301       Out << "[c++ ctor] ";
302     else if (D->isImplicit())
303       Out << "(c++ ctor) ";
304     else
305       Out << "<c++ ctor> ";
306     Out << *D;
307     // Print the parameters.
308     Out << "(";
309     bool PrintComma = false;
310     for (FunctionDecl::param_const_iterator I = D->param_begin(),
311            E = D->param_end(); I != E; ++I) {
312       if (PrintComma)
313         Out << ", ";
314       else
315         PrintComma = true;
316       Out << **I;
317     }
318     Out << ")";
319 
320     // Check the semantic DC.
321     const DeclContext* SemaDC = D->getDeclContext();
322     const DeclContext* LexicalDC = D->getLexicalDeclContext();
323     if (SemaDC != LexicalDC)
324       Out << " [[" << SemaDC << "]]";
325     break;
326   }
327   case Decl::CXXDestructor: {
328     const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
329     if (D->isOutOfLine())
330       Out << "[c++ dtor] ";
331     else if (D->isImplicit())
332       Out << "(c++ dtor) ";
333     else
334       Out << "<c++ dtor> ";
335     Out << *D;
336     // Check the semantic DC.
337     const DeclContext* SemaDC = D->getDeclContext();
338     const DeclContext* LexicalDC = D->getLexicalDeclContext();
339     if (SemaDC != LexicalDC)
340       Out << " [[" << SemaDC << "]]";
341     break;
342   }
343   case Decl::CXXConversion: {
344     const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
345     if (D->isOutOfLine())
346       Out << "[c++ conversion] ";
347     else if (D->isImplicit())
348       Out << "(c++ conversion) ";
349     else
350       Out << "<c++ conversion> ";
351     Out << *D;
352     // Check the semantic DC.
353     const DeclContext* SemaDC = D->getDeclContext();
354     const DeclContext* LexicalDC = D->getLexicalDeclContext();
355     if (SemaDC != LexicalDC)
356       Out << " [[" << SemaDC << "]]";
357     break;
358   }
359 
360   default:
361     llvm_unreachable("a decl that inherits DeclContext isn't handled");
362   }
363 
364   Out << "\n";
365 
366   // Print decls in the DeclContext.
367   for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
368        I != E; ++I) {
369     for (unsigned i = 0; i < Indentation; ++i)
370       Out << "  ";
371 
372     Decl::Kind DK = I->getKind();
373     switch (DK) {
374     case Decl::Namespace:
375     case Decl::Enum:
376     case Decl::Record:
377     case Decl::CXXRecord:
378     case Decl::ObjCMethod:
379     case Decl::ObjCInterface:
380     case Decl::ObjCCategory:
381     case Decl::ObjCProtocol:
382     case Decl::ObjCImplementation:
383     case Decl::ObjCCategoryImpl:
384     case Decl::LinkageSpec:
385     case Decl::Block:
386     case Decl::Function:
387     case Decl::CXXMethod:
388     case Decl::CXXConstructor:
389     case Decl::CXXDestructor:
390     case Decl::CXXConversion:
391     {
392       DeclContext* DC = cast<DeclContext>(*I);
393       PrintDeclContext(DC, Indentation+2);
394       break;
395     }
396     case Decl::IndirectField: {
397       IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
398       Out << "<IndirectField> " << *IFD << '\n';
399       break;
400     }
401     case Decl::Label: {
402       LabelDecl *LD = cast<LabelDecl>(*I);
403       Out << "<Label> " << *LD << '\n';
404       break;
405     }
406     case Decl::Field: {
407       FieldDecl *FD = cast<FieldDecl>(*I);
408       Out << "<field> " << *FD << '\n';
409       break;
410     }
411     case Decl::Typedef:
412     case Decl::TypeAlias: {
413       TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
414       Out << "<typedef> " << *TD << '\n';
415       break;
416     }
417     case Decl::EnumConstant: {
418       EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
419       Out << "<enum constant> " << *ECD << '\n';
420       break;
421     }
422     case Decl::Var: {
423       VarDecl* VD = cast<VarDecl>(*I);
424       Out << "<var> " << *VD << '\n';
425       break;
426     }
427     case Decl::ImplicitParam: {
428       ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
429       Out << "<implicit parameter> " << *IPD << '\n';
430       break;
431     }
432     case Decl::ParmVar: {
433       ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
434       Out << "<parameter> " << *PVD << '\n';
435       break;
436     }
437     case Decl::ObjCProperty: {
438       ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
439       Out << "<objc property> " << *OPD << '\n';
440       break;
441     }
442     case Decl::FunctionTemplate: {
443       FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
444       Out << "<function template> " << *FTD << '\n';
445       break;
446     }
447     case Decl::FileScopeAsm: {
448       Out << "<file-scope asm>\n";
449       break;
450     }
451     case Decl::UsingDirective: {
452       Out << "<using directive>\n";
453       break;
454     }
455     case Decl::NamespaceAlias: {
456       NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
457       Out << "<namespace alias> " << *NAD << '\n';
458       break;
459     }
460     case Decl::ClassTemplate: {
461       ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
462       Out << "<class template> " << *CTD << '\n';
463       break;
464     }
465     default:
466       Out << "DeclKind: " << DK << '"' << *I << "\"\n";
467       llvm_unreachable("decl unhandled");
468     }
469   }
470 }
471 ASTConsumer *clang::CreateDeclContextPrinter() {
472   return new DeclContextPrinter();
473 }
474 
475 //===----------------------------------------------------------------------===//
476 /// ASTDumperXML - In-depth XML dumping.
477 
478 namespace {
479 class ASTDumpXML : public ASTConsumer {
480   raw_ostream &OS;
481 
482 public:
483   ASTDumpXML(raw_ostream &OS) : OS(OS) {}
484 
485   void HandleTranslationUnit(ASTContext &C) {
486     C.getTranslationUnitDecl()->dumpXML(OS);
487   }
488 };
489 }
490 
491 ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) {
492   return new ASTDumpXML(OS);
493 }
494