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