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/Frontend/DocumentXML.h"
16 #include "clang/Frontend/PathDiagnosticClients.h"
17 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Basic/SourceManager.h"
19 #include "clang/Basic/FileManager.h"
20 #include "clang/AST/AST.h"
21 #include "clang/AST/ASTConsumer.h"
22 #include "clang/AST/ASTContext.h"
23 #include "clang/AST/PrettyPrinter.h"
24 #include "clang/CodeGen/ModuleBuilder.h"
25 #include "llvm/Module.h"
26 #include "llvm/Support/Streams.h"
27 #include "llvm/Support/Timer.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/System/Path.h"
30 using namespace clang;
31 
32 //===----------------------------------------------------------------------===//
33 /// ASTPrinter - Pretty-printer and dumper of ASTs
34 
35 namespace {
36   class ASTPrinter : public ASTConsumer {
37     llvm::raw_ostream &Out;
38     bool Dump;
39 
40   public:
41     ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
42       : Out(o? *o : llvm::errs()), Dump(Dump) { }
43 
44     virtual void HandleTranslationUnit(ASTContext &Context) {
45       PrintingPolicy Policy = Context.PrintingPolicy;
46       Policy.Dump = Dump;
47       Context.getTranslationUnitDecl()->print(Out, Policy);
48     }
49   };
50 } // end anonymous namespace
51 
52 ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
53   return new ASTPrinter(out);
54 }
55 
56 //===----------------------------------------------------------------------===//
57 /// ASTPrinterXML - XML-printer of ASTs
58 
59 namespace {
60   class ASTPrinterXML : public ASTConsumer {
61     DocumentXML         Doc;
62 
63   public:
64     ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
65 
66     void Initialize(ASTContext &Context) {
67       Doc.initialize(Context);
68     }
69 
70     virtual void HandleTranslationUnit(ASTContext &Ctx) {
71       Doc.addSubNode("TranslationUnit");
72       for (DeclContext::decl_iterator
73              D = Ctx.getTranslationUnitDecl()->decls_begin(),
74              DEnd = Ctx.getTranslationUnitDecl()->decls_end();
75            D != DEnd;
76            ++D)
77       {
78         Doc.PrintDecl(*D);
79       }
80       Doc.toParent();
81       Doc.finalize();
82     }
83   };
84 } // end anonymous namespace
85 
86 
87 ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
88   return new ASTPrinterXML(out ? *out : llvm::outs());
89 }
90 
91 ASTConsumer *clang::CreateASTDumper() {
92   return new ASTPrinter(0, true);
93 }
94 
95 //===----------------------------------------------------------------------===//
96 /// ASTViewer - AST Visualization
97 
98 namespace {
99   class ASTViewer : public ASTConsumer {
100     ASTContext *Context;
101   public:
102     void Initialize(ASTContext &Context) {
103       this->Context = &Context;
104     }
105 
106     virtual void HandleTopLevelDecl(DeclGroupRef D) {
107       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
108         HandleTopLevelSingleDecl(*I);
109     }
110 
111     void HandleTopLevelSingleDecl(Decl *D);
112   };
113 }
114 
115 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
116   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
117     FD->print(llvm::errs());
118 
119     if (FD->getBodyIfAvailable()) {
120       llvm::cerr << '\n';
121       FD->getBodyIfAvailable()->viewAST();
122       llvm::cerr << '\n';
123     }
124     return;
125   }
126 
127   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
128     MD->print(llvm::errs());
129 
130     if (MD->getBody()) {
131       llvm::cerr << '\n';
132       MD->getBody()->viewAST();
133       llvm::cerr << '\n';
134     }
135   }
136 }
137 
138 
139 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
140 
141 //===----------------------------------------------------------------------===//
142 /// DeclContextPrinter - Decl and DeclContext Visualization
143 
144 namespace {
145 
146 class DeclContextPrinter : public ASTConsumer {
147   llvm::raw_ostream& Out;
148 public:
149   DeclContextPrinter() : Out(llvm::errs()) {}
150 
151   void HandleTranslationUnit(ASTContext &C) {
152     PrintDeclContext(C.getTranslationUnitDecl(), 4);
153   }
154 
155   void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
156 };
157 }  // end anonymous namespace
158 
159 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
160                                           unsigned Indentation) {
161   // Print DeclContext name.
162   switch (DC->getDeclKind()) {
163   case Decl::TranslationUnit:
164     Out << "[translation unit] " << DC;
165     break;
166   case Decl::Namespace: {
167     Out << "[namespace] ";
168     const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
169     Out << ND->getNameAsString();
170     break;
171   }
172   case Decl::Enum: {
173     const EnumDecl* ED = cast<EnumDecl>(DC);
174     if (ED->isDefinition())
175       Out << "[enum] ";
176     else
177       Out << "<enum> ";
178     Out << ED->getNameAsString();
179     break;
180   }
181   case Decl::Record: {
182     const RecordDecl* RD = cast<RecordDecl>(DC);
183     if (RD->isDefinition())
184       Out << "[struct] ";
185     else
186       Out << "<struct> ";
187     Out << RD->getNameAsString();
188     break;
189   }
190   case Decl::CXXRecord: {
191     const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
192     if (RD->isDefinition())
193       Out << "[class] ";
194     else
195       Out << "<class> ";
196     Out << RD->getNameAsString() << " " << DC;
197     break;
198   }
199   case Decl::ObjCMethod:
200     Out << "[objc method]";
201     break;
202   case Decl::ObjCInterface:
203     Out << "[objc interface]";
204     break;
205   case Decl::ObjCCategory:
206     Out << "[objc category]";
207     break;
208   case Decl::ObjCProtocol:
209     Out << "[objc protocol]";
210     break;
211   case Decl::ObjCImplementation:
212     Out << "[objc implementation]";
213     break;
214   case Decl::ObjCCategoryImpl:
215     Out << "[objc categoryimpl]";
216     break;
217   case Decl::LinkageSpec:
218     Out << "[linkage spec]";
219     break;
220   case Decl::Block:
221     Out << "[block]";
222     break;
223   case Decl::Function: {
224     const FunctionDecl* FD = cast<FunctionDecl>(DC);
225     if (FD->isThisDeclarationADefinition())
226       Out << "[function] ";
227     else
228       Out << "<function> ";
229     Out << FD->getNameAsString();
230     // Print the parameters.
231     Out << "(";
232     bool PrintComma = false;
233     for (FunctionDecl::param_const_iterator I = FD->param_begin(),
234            E = FD->param_end(); I != E; ++I) {
235       if (PrintComma)
236         Out << ", ";
237       else
238         PrintComma = true;
239       Out << (*I)->getNameAsString();
240     }
241     Out << ")";
242     break;
243   }
244   case Decl::CXXMethod: {
245     const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
246     if (D->isOutOfLine())
247       Out << "[c++ method] ";
248     else if (D->isImplicit())
249       Out << "(c++ method) ";
250     else
251       Out << "<c++ method> ";
252     Out << D->getNameAsString();
253     // Print the parameters.
254     Out << "(";
255     bool PrintComma = false;
256     for (FunctionDecl::param_const_iterator I = D->param_begin(),
257            E = D->param_end(); I != E; ++I) {
258       if (PrintComma)
259         Out << ", ";
260       else
261         PrintComma = true;
262       Out << (*I)->getNameAsString();
263     }
264     Out << ")";
265 
266     // Check the semantic DeclContext.
267     const DeclContext* SemaDC = D->getDeclContext();
268     const DeclContext* LexicalDC = D->getLexicalDeclContext();
269     if (SemaDC != LexicalDC)
270       Out << " [[" << SemaDC << "]]";
271 
272     break;
273   }
274   case Decl::CXXConstructor: {
275     const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
276     if (D->isOutOfLine())
277       Out << "[c++ ctor] ";
278     else if (D->isImplicit())
279       Out << "(c++ ctor) ";
280     else
281       Out << "<c++ ctor> ";
282     Out << D->getNameAsString();
283     // Print the parameters.
284     Out << "(";
285     bool PrintComma = false;
286     for (FunctionDecl::param_const_iterator I = D->param_begin(),
287            E = D->param_end(); I != E; ++I) {
288       if (PrintComma)
289         Out << ", ";
290       else
291         PrintComma = true;
292       Out << (*I)->getNameAsString();
293     }
294     Out << ")";
295 
296     // Check the semantic DC.
297     const DeclContext* SemaDC = D->getDeclContext();
298     const DeclContext* LexicalDC = D->getLexicalDeclContext();
299     if (SemaDC != LexicalDC)
300       Out << " [[" << SemaDC << "]]";
301     break;
302   }
303   case Decl::CXXDestructor: {
304     const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
305     if (D->isOutOfLine())
306       Out << "[c++ dtor] ";
307     else if (D->isImplicit())
308       Out << "(c++ dtor) ";
309     else
310       Out << "<c++ dtor> ";
311     Out << D->getNameAsString();
312     // Check the semantic DC.
313     const DeclContext* SemaDC = D->getDeclContext();
314     const DeclContext* LexicalDC = D->getLexicalDeclContext();
315     if (SemaDC != LexicalDC)
316       Out << " [[" << SemaDC << "]]";
317     break;
318   }
319   case Decl::CXXConversion: {
320     const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
321     if (D->isOutOfLine())
322       Out << "[c++ conversion] ";
323     else if (D->isImplicit())
324       Out << "(c++ conversion) ";
325     else
326       Out << "<c++ conversion> ";
327     Out << D->getNameAsString();
328     // Check the semantic DC.
329     const DeclContext* SemaDC = D->getDeclContext();
330     const DeclContext* LexicalDC = D->getLexicalDeclContext();
331     if (SemaDC != LexicalDC)
332       Out << " [[" << SemaDC << "]]";
333     break;
334   }
335 
336   default:
337     assert(0 && "a decl that inherits DeclContext isn't handled");
338   }
339 
340   Out << "\n";
341 
342   // Print decls in the DeclContext.
343   for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
344        I != E; ++I) {
345     for (unsigned i = 0; i < Indentation; ++i)
346       Out << "  ";
347 
348     Decl::Kind DK = I->getKind();
349     switch (DK) {
350     case Decl::Namespace:
351     case Decl::Enum:
352     case Decl::Record:
353     case Decl::CXXRecord:
354     case Decl::ObjCMethod:
355     case Decl::ObjCInterface:
356     case Decl::ObjCCategory:
357     case Decl::ObjCProtocol:
358     case Decl::ObjCImplementation:
359     case Decl::ObjCCategoryImpl:
360     case Decl::LinkageSpec:
361     case Decl::Block:
362     case Decl::Function:
363     case Decl::CXXMethod:
364     case Decl::CXXConstructor:
365     case Decl::CXXDestructor:
366     case Decl::CXXConversion:
367     {
368       DeclContext* DC = cast<DeclContext>(*I);
369       PrintDeclContext(DC, Indentation+2);
370       break;
371     }
372     case Decl::Field: {
373       FieldDecl* FD = cast<FieldDecl>(*I);
374       Out << "<field> " << FD->getNameAsString() << "\n";
375       break;
376     }
377     case Decl::Typedef: {
378       TypedefDecl* TD = cast<TypedefDecl>(*I);
379       Out << "<typedef> " << TD->getNameAsString() << "\n";
380       break;
381     }
382     case Decl::EnumConstant: {
383       EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
384       Out << "<enum constant> " << ECD->getNameAsString() << "\n";
385       break;
386     }
387     case Decl::Var: {
388       VarDecl* VD = cast<VarDecl>(*I);
389       Out << "<var> " << VD->getNameAsString() << "\n";
390       break;
391     }
392     case Decl::ImplicitParam: {
393       ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
394       Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
395       break;
396     }
397     case Decl::ParmVar: {
398       ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
399       Out << "<parameter> " << PVD->getNameAsString() << "\n";
400       break;
401     }
402     case Decl::OriginalParmVar: {
403       OriginalParmVarDecl* OPVD = cast<OriginalParmVarDecl>(*I);
404       Out << "<original parameter> " << OPVD->getNameAsString() << "\n";
405       break;
406     }
407     case Decl::ObjCProperty: {
408       ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
409       Out << "<objc property> " << OPD->getNameAsString() << "\n";
410       break;
411     }
412     default:
413       fprintf(stderr, "DeclKind: %d \"%s\"\n", DK, I->getDeclKindName());
414       assert(0 && "decl unhandled");
415     }
416   }
417 }
418 ASTConsumer *clang::CreateDeclContextPrinter() {
419   return new DeclContextPrinter();
420 }
421 
422 //===----------------------------------------------------------------------===//
423 /// InheritanceViewer - C++ Inheritance Visualization
424 
425 namespace {
426 class InheritanceViewer : public ASTConsumer {
427   const std::string clsname;
428 public:
429   InheritanceViewer(const std::string& cname) : clsname(cname) {}
430 
431   void HandleTranslationUnit(ASTContext &C) {
432     for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
433       if (RecordType *T = dyn_cast<RecordType>(*I)) {
434         if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) {
435           // FIXME: This lookup needs to be generalized to handle namespaces and
436           // (when we support them) templates.
437           if (D->getNameAsString() == clsname) {
438             D->viewInheritance(C);
439           }
440         }
441       }
442   }
443 };
444 }
445 
446 ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
447   return new InheritanceViewer(clsname);
448 }
449