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/Basic/Diagnostic.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Basic/FileManager.h"
18 #include "clang/AST/AST.h"
19 #include "clang/AST/ASTConsumer.h"
20 #include "clang/AST/ASTContext.h"
21 #include "clang/AST/RecordLayout.h"
22 #include "clang/AST/PrettyPrinter.h"
23 #include "llvm/Module.h"
24 #include "llvm/Support/Timer.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Support/Path.h"
27 using namespace clang;
29 //===----------------------------------------------------------------------===//
30 /// ASTPrinter - Pretty-printer and dumper of ASTs
33 class ASTPrinter : public ASTConsumer {
38 ASTPrinter(raw_ostream* o = NULL, bool Dump = false)
39 : Out(o? *o : llvm::outs()), Dump(Dump) { }
41 virtual void HandleTranslationUnit(ASTContext &Context) {
42 PrintingPolicy Policy = Context.getPrintingPolicy();
44 Context.getTranslationUnitDecl()->print(Out, Policy, /*Indentation=*/0,
45 /*PrintInstantiation=*/true);
48 } // end anonymous namespace
50 ASTConsumer *clang::CreateASTPrinter(raw_ostream* out) {
51 return new ASTPrinter(out);
54 ASTConsumer *clang::CreateASTDumper() {
55 return new ASTPrinter(0, true);
58 //===----------------------------------------------------------------------===//
59 /// ASTViewer - AST Visualization
62 class ASTViewer : public ASTConsumer {
65 void Initialize(ASTContext &Context) {
66 this->Context = &Context;
69 virtual bool HandleTopLevelDecl(DeclGroupRef D) {
70 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
71 HandleTopLevelSingleDecl(*I);
75 void HandleTopLevelSingleDecl(Decl *D);
79 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
80 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
81 D->print(llvm::errs());
83 if (Stmt *Body = D->getBody()) {
92 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
94 //===----------------------------------------------------------------------===//
95 /// DeclContextPrinter - Decl and DeclContext Visualization
99 class DeclContextPrinter : public ASTConsumer {
102 DeclContextPrinter() : Out(llvm::errs()) {}
104 void HandleTranslationUnit(ASTContext &C) {
105 PrintDeclContext(C.getTranslationUnitDecl(), 4);
108 void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
110 } // end anonymous namespace
112 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
113 unsigned Indentation) {
114 // Print DeclContext name.
115 switch (DC->getDeclKind()) {
116 case Decl::TranslationUnit:
117 Out << "[translation unit] " << DC;
119 case Decl::Namespace: {
120 Out << "[namespace] ";
121 const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
126 const EnumDecl* ED = cast<EnumDecl>(DC);
127 if (ED->isCompleteDefinition())
135 const RecordDecl* RD = cast<RecordDecl>(DC);
136 if (RD->isCompleteDefinition())
143 case Decl::CXXRecord: {
144 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
145 if (RD->isCompleteDefinition())
149 Out << *RD << ' ' << DC;
152 case Decl::ObjCMethod:
153 Out << "[objc method]";
155 case Decl::ObjCInterface:
156 Out << "[objc interface]";
158 case Decl::ObjCCategory:
159 Out << "[objc category]";
161 case Decl::ObjCProtocol:
162 Out << "[objc protocol]";
164 case Decl::ObjCImplementation:
165 Out << "[objc implementation]";
167 case Decl::ObjCCategoryImpl:
168 Out << "[objc categoryimpl]";
170 case Decl::LinkageSpec:
171 Out << "[linkage spec]";
176 case Decl::Function: {
177 const FunctionDecl* FD = cast<FunctionDecl>(DC);
178 if (FD->doesThisDeclarationHaveABody())
179 Out << "[function] ";
181 Out << "<function> ";
183 // Print the parameters.
185 bool PrintComma = false;
186 for (FunctionDecl::param_const_iterator I = FD->param_begin(),
187 E = FD->param_end(); I != E; ++I) {
197 case Decl::CXXMethod: {
198 const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
199 if (D->isOutOfLine())
200 Out << "[c++ method] ";
201 else if (D->isImplicit())
202 Out << "(c++ method) ";
204 Out << "<c++ method> ";
206 // Print the parameters.
208 bool PrintComma = false;
209 for (FunctionDecl::param_const_iterator I = D->param_begin(),
210 E = D->param_end(); I != E; ++I) {
219 // Check the semantic DeclContext.
220 const DeclContext* SemaDC = D->getDeclContext();
221 const DeclContext* LexicalDC = D->getLexicalDeclContext();
222 if (SemaDC != LexicalDC)
223 Out << " [[" << SemaDC << "]]";
227 case Decl::CXXConstructor: {
228 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
229 if (D->isOutOfLine())
230 Out << "[c++ ctor] ";
231 else if (D->isImplicit())
232 Out << "(c++ ctor) ";
234 Out << "<c++ ctor> ";
236 // Print the parameters.
238 bool PrintComma = false;
239 for (FunctionDecl::param_const_iterator I = D->param_begin(),
240 E = D->param_end(); I != E; ++I) {
249 // Check the semantic DC.
250 const DeclContext* SemaDC = D->getDeclContext();
251 const DeclContext* LexicalDC = D->getLexicalDeclContext();
252 if (SemaDC != LexicalDC)
253 Out << " [[" << SemaDC << "]]";
256 case Decl::CXXDestructor: {
257 const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
258 if (D->isOutOfLine())
259 Out << "[c++ dtor] ";
260 else if (D->isImplicit())
261 Out << "(c++ dtor) ";
263 Out << "<c++ dtor> ";
265 // Check the semantic DC.
266 const DeclContext* SemaDC = D->getDeclContext();
267 const DeclContext* LexicalDC = D->getLexicalDeclContext();
268 if (SemaDC != LexicalDC)
269 Out << " [[" << SemaDC << "]]";
272 case Decl::CXXConversion: {
273 const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
274 if (D->isOutOfLine())
275 Out << "[c++ conversion] ";
276 else if (D->isImplicit())
277 Out << "(c++ conversion) ";
279 Out << "<c++ conversion> ";
281 // Check the semantic DC.
282 const DeclContext* SemaDC = D->getDeclContext();
283 const DeclContext* LexicalDC = D->getLexicalDeclContext();
284 if (SemaDC != LexicalDC)
285 Out << " [[" << SemaDC << "]]";
290 llvm_unreachable("a decl that inherits DeclContext isn't handled");
295 // Print decls in the DeclContext.
296 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
298 for (unsigned i = 0; i < Indentation; ++i)
301 Decl::Kind DK = I->getKind();
303 case Decl::Namespace:
306 case Decl::CXXRecord:
307 case Decl::ObjCMethod:
308 case Decl::ObjCInterface:
309 case Decl::ObjCCategory:
310 case Decl::ObjCProtocol:
311 case Decl::ObjCImplementation:
312 case Decl::ObjCCategoryImpl:
313 case Decl::LinkageSpec:
316 case Decl::CXXMethod:
317 case Decl::CXXConstructor:
318 case Decl::CXXDestructor:
319 case Decl::CXXConversion:
321 DeclContext* DC = cast<DeclContext>(*I);
322 PrintDeclContext(DC, Indentation+2);
325 case Decl::IndirectField: {
326 IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
327 Out << "<IndirectField> " << *IFD << '\n';
331 LabelDecl *LD = cast<LabelDecl>(*I);
332 Out << "<Label> " << *LD << '\n';
336 FieldDecl *FD = cast<FieldDecl>(*I);
337 Out << "<field> " << *FD << '\n';
341 case Decl::TypeAlias: {
342 TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
343 Out << "<typedef> " << *TD << '\n';
346 case Decl::EnumConstant: {
347 EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
348 Out << "<enum constant> " << *ECD << '\n';
352 VarDecl* VD = cast<VarDecl>(*I);
353 Out << "<var> " << *VD << '\n';
356 case Decl::ImplicitParam: {
357 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
358 Out << "<implicit parameter> " << *IPD << '\n';
361 case Decl::ParmVar: {
362 ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
363 Out << "<parameter> " << *PVD << '\n';
366 case Decl::ObjCProperty: {
367 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
368 Out << "<objc property> " << *OPD << '\n';
371 case Decl::FunctionTemplate: {
372 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
373 Out << "<function template> " << *FTD << '\n';
376 case Decl::FileScopeAsm: {
377 Out << "<file-scope asm>\n";
380 case Decl::UsingDirective: {
381 Out << "<using directive>\n";
384 case Decl::NamespaceAlias: {
385 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
386 Out << "<namespace alias> " << *NAD << '\n';
389 case Decl::ClassTemplate: {
390 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
391 Out << "<class template> " << *CTD << '\n';
395 Out << "DeclKind: " << DK << '"' << *I << "\"\n";
396 llvm_unreachable("decl unhandled");
400 ASTConsumer *clang::CreateDeclContextPrinter() {
401 return new DeclContextPrinter();
404 //===----------------------------------------------------------------------===//
405 /// ASTDumperXML - In-depth XML dumping.
408 class ASTDumpXML : public ASTConsumer {
412 ASTDumpXML(raw_ostream &OS) : OS(OS) {}
414 void HandleTranslationUnit(ASTContext &C) {
415 C.getTranslationUnitDecl()->dumpXML(OS);
420 ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) {
421 return new ASTDumpXML(OS);