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