1 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // AST Consumer Implementations.
12 //===----------------------------------------------------------------------===//
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;
30 //===----------------------------------------------------------------------===//
31 /// ASTPrinter - Pretty-printer and dumper of ASTs
34 class ASTPrinter : public ASTConsumer {
35 llvm::raw_ostream &Out;
39 ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
40 : Out(o? *o : llvm::outs()), Dump(Dump) { }
42 virtual void HandleTranslationUnit(ASTContext &Context) {
43 PrintingPolicy Policy = Context.PrintingPolicy;
45 Context.getTranslationUnitDecl()->print(Out, Policy);
48 } // end anonymous namespace
50 ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
51 return new ASTPrinter(out);
54 //===----------------------------------------------------------------------===//
55 /// ASTPrinterXML - XML-printer of ASTs
58 class ASTPrinterXML : public ASTConsumer {
62 ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
64 void Initialize(ASTContext &Context) {
65 Doc.initialize(Context);
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();
80 } // end anonymous namespace
83 ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
84 return new ASTPrinterXML(out ? *out : llvm::outs());
87 ASTConsumer *clang::CreateASTDumper() {
88 return new ASTPrinter(0, true);
91 //===----------------------------------------------------------------------===//
92 /// ASTViewer - AST Visualization
95 class ASTViewer : public ASTConsumer {
98 void Initialize(ASTContext &Context) {
99 this->Context = &Context;
102 virtual void HandleTopLevelDecl(DeclGroupRef D) {
103 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
104 HandleTopLevelSingleDecl(*I);
107 void HandleTopLevelSingleDecl(Decl *D);
111 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
112 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
113 D->print(llvm::errs());
115 if (Stmt *Body = D->getBody()) {
116 llvm::errs() << '\n';
118 llvm::errs() << '\n';
124 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
126 //===----------------------------------------------------------------------===//
127 /// DeclContextPrinter - Decl and DeclContext Visualization
131 class DeclContextPrinter : public ASTConsumer {
132 llvm::raw_ostream& Out;
134 DeclContextPrinter() : Out(llvm::errs()) {}
136 void HandleTranslationUnit(ASTContext &C) {
137 PrintDeclContext(C.getTranslationUnitDecl(), 4);
140 void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
142 } // end anonymous namespace
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;
151 case Decl::Namespace: {
152 Out << "[namespace] ";
153 const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
158 const EnumDecl* ED = cast<EnumDecl>(DC);
159 if (ED->isDefinition())
167 const RecordDecl* RD = cast<RecordDecl>(DC);
168 if (RD->isDefinition())
175 case Decl::CXXRecord: {
176 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
177 if (RD->isDefinition())
181 Out << RD << ' ' << DC;
184 case Decl::ObjCMethod:
185 Out << "[objc method]";
187 case Decl::ObjCInterface:
188 Out << "[objc interface]";
190 case Decl::ObjCCategory:
191 Out << "[objc category]";
193 case Decl::ObjCProtocol:
194 Out << "[objc protocol]";
196 case Decl::ObjCImplementation:
197 Out << "[objc implementation]";
199 case Decl::ObjCCategoryImpl:
200 Out << "[objc categoryimpl]";
202 case Decl::LinkageSpec:
203 Out << "[linkage spec]";
208 case Decl::Function: {
209 const FunctionDecl* FD = cast<FunctionDecl>(DC);
210 if (FD->isThisDeclarationADefinition())
211 Out << "[function] ";
213 Out << "<function> ";
215 // Print the parameters.
217 bool PrintComma = false;
218 for (FunctionDecl::param_const_iterator I = FD->param_begin(),
219 E = FD->param_end(); I != E; ++I) {
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) ";
236 Out << "<c++ method> ";
238 // Print the parameters.
240 bool PrintComma = false;
241 for (FunctionDecl::param_const_iterator I = D->param_begin(),
242 E = D->param_end(); I != E; ++I) {
251 // Check the semantic DeclContext.
252 const DeclContext* SemaDC = D->getDeclContext();
253 const DeclContext* LexicalDC = D->getLexicalDeclContext();
254 if (SemaDC != LexicalDC)
255 Out << " [[" << SemaDC << "]]";
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) ";
266 Out << "<c++ ctor> ";
268 // Print the parameters.
270 bool PrintComma = false;
271 for (FunctionDecl::param_const_iterator I = D->param_begin(),
272 E = D->param_end(); I != E; ++I) {
281 // Check the semantic DC.
282 const DeclContext* SemaDC = D->getDeclContext();
283 const DeclContext* LexicalDC = D->getLexicalDeclContext();
284 if (SemaDC != LexicalDC)
285 Out << " [[" << SemaDC << "]]";
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) ";
295 Out << "<c++ dtor> ";
297 // Check the semantic DC.
298 const DeclContext* SemaDC = D->getDeclContext();
299 const DeclContext* LexicalDC = D->getLexicalDeclContext();
300 if (SemaDC != LexicalDC)
301 Out << " [[" << SemaDC << "]]";
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) ";
311 Out << "<c++ conversion> ";
313 // Check the semantic DC.
314 const DeclContext* SemaDC = D->getDeclContext();
315 const DeclContext* LexicalDC = D->getLexicalDeclContext();
316 if (SemaDC != LexicalDC)
317 Out << " [[" << SemaDC << "]]";
322 assert(0 && "a decl that inherits DeclContext isn't handled");
327 // Print decls in the DeclContext.
328 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
330 for (unsigned i = 0; i < Indentation; ++i)
333 Decl::Kind DK = I->getKind();
335 case Decl::Namespace:
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:
348 case Decl::CXXMethod:
349 case Decl::CXXConstructor:
350 case Decl::CXXDestructor:
351 case Decl::CXXConversion:
353 DeclContext* DC = cast<DeclContext>(*I);
354 PrintDeclContext(DC, Indentation+2);
358 FieldDecl* FD = cast<FieldDecl>(*I);
359 Out << "<field> " << FD << '\n';
362 case Decl::Typedef: {
363 TypedefDecl* TD = cast<TypedefDecl>(*I);
364 Out << "<typedef> " << TD << '\n';
367 case Decl::EnumConstant: {
368 EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
369 Out << "<enum constant> " << ECD << '\n';
373 VarDecl* VD = cast<VarDecl>(*I);
374 Out << "<var> " << VD << '\n';
377 case Decl::ImplicitParam: {
378 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
379 Out << "<implicit parameter> " << IPD << '\n';
382 case Decl::ParmVar: {
383 ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
384 Out << "<parameter> " << PVD << '\n';
387 case Decl::ObjCProperty: {
388 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
389 Out << "<objc property> " << OPD << '\n';
392 case Decl::FunctionTemplate: {
393 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
394 Out << "<function template> " << FTD << '\n';
397 case Decl::FileScopeAsm: {
398 Out << "<file-scope asm>\n";
401 case Decl::UsingDirective: {
402 Out << "<using directive>\n";
405 case Decl::NamespaceAlias: {
406 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
407 Out << "<namespace alias> " << NAD << '\n';
410 case Decl::ClassTemplate: {
411 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
412 Out << "<class template> " << CTD << '\n';
416 Out << "DeclKind: " << DK << '"' << *I << "\"\n";
417 assert(0 && "decl unhandled");
421 ASTConsumer *clang::CreateDeclContextPrinter() {
422 return new DeclContextPrinter();
425 //===----------------------------------------------------------------------===//
426 /// InheritanceViewer - C++ Inheritance Visualization
429 class InheritanceViewer : public ASTConsumer {
430 const std::string clsname;
432 InheritanceViewer(const std::string& cname) : clsname(cname) {}
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);
449 ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
450 return new InheritanceViewer(clsname);