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