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/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;
28
29 //===----------------------------------------------------------------------===//
30 /// ASTPrinter - Pretty-printer and dumper of ASTs
31
32 namespace {
33 class ASTPrinter : public ASTConsumer {
34 raw_ostream &Out;
35 bool Dump;
36
37 public:
ASTPrinter(raw_ostream * o=NULL,bool Dump=false)38 ASTPrinter(raw_ostream* o = NULL, bool Dump = false)
39 : Out(o? *o : llvm::outs()), Dump(Dump) { }
40
HandleTranslationUnit(ASTContext & Context)41 virtual void HandleTranslationUnit(ASTContext &Context) {
42 PrintingPolicy Policy = Context.getPrintingPolicy();
43 Policy.Dump = Dump;
44 Context.getTranslationUnitDecl()->print(Out, Policy, /*Indentation=*/0,
45 /*PrintInstantiation=*/true);
46 }
47 };
48 } // end anonymous namespace
49
CreateASTPrinter(raw_ostream * out)50 ASTConsumer *clang::CreateASTPrinter(raw_ostream* out) {
51 return new ASTPrinter(out);
52 }
53
CreateASTDumper()54 ASTConsumer *clang::CreateASTDumper() {
55 return new ASTPrinter(0, true);
56 }
57
58 //===----------------------------------------------------------------------===//
59 /// ASTViewer - AST Visualization
60
61 namespace {
62 class ASTViewer : public ASTConsumer {
63 ASTContext *Context;
64 public:
Initialize(ASTContext & Context)65 void Initialize(ASTContext &Context) {
66 this->Context = &Context;
67 }
68
HandleTopLevelDecl(DeclGroupRef D)69 virtual bool HandleTopLevelDecl(DeclGroupRef D) {
70 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
71 HandleTopLevelSingleDecl(*I);
72 return true;
73 }
74
75 void HandleTopLevelSingleDecl(Decl *D);
76 };
77 }
78
HandleTopLevelSingleDecl(Decl * D)79 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
80 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
81 D->print(llvm::errs());
82
83 if (Stmt *Body = D->getBody()) {
84 llvm::errs() << '\n';
85 Body->viewAST();
86 llvm::errs() << '\n';
87 }
88 }
89 }
90
91
CreateASTViewer()92 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
93
94 //===----------------------------------------------------------------------===//
95 /// DeclContextPrinter - Decl and DeclContext Visualization
96
97 namespace {
98
99 class DeclContextPrinter : public ASTConsumer {
100 raw_ostream& Out;
101 public:
DeclContextPrinter()102 DeclContextPrinter() : Out(llvm::errs()) {}
103
HandleTranslationUnit(ASTContext & C)104 void HandleTranslationUnit(ASTContext &C) {
105 PrintDeclContext(C.getTranslationUnitDecl(), 4);
106 }
107
108 void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
109 };
110 } // end anonymous namespace
111
PrintDeclContext(const DeclContext * DC,unsigned Indentation)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;
118 break;
119 case Decl::Namespace: {
120 Out << "[namespace] ";
121 const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
122 Out << *ND;
123 break;
124 }
125 case Decl::Enum: {
126 const EnumDecl* ED = cast<EnumDecl>(DC);
127 if (ED->isCompleteDefinition())
128 Out << "[enum] ";
129 else
130 Out << "<enum> ";
131 Out << *ED;
132 break;
133 }
134 case Decl::Record: {
135 const RecordDecl* RD = cast<RecordDecl>(DC);
136 if (RD->isCompleteDefinition())
137 Out << "[struct] ";
138 else
139 Out << "<struct> ";
140 Out << *RD;
141 break;
142 }
143 case Decl::CXXRecord: {
144 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
145 if (RD->isCompleteDefinition())
146 Out << "[class] ";
147 else
148 Out << "<class> ";
149 Out << *RD << ' ' << DC;
150 break;
151 }
152 case Decl::ObjCMethod:
153 Out << "[objc method]";
154 break;
155 case Decl::ObjCInterface:
156 Out << "[objc interface]";
157 break;
158 case Decl::ObjCCategory:
159 Out << "[objc category]";
160 break;
161 case Decl::ObjCProtocol:
162 Out << "[objc protocol]";
163 break;
164 case Decl::ObjCImplementation:
165 Out << "[objc implementation]";
166 break;
167 case Decl::ObjCCategoryImpl:
168 Out << "[objc categoryimpl]";
169 break;
170 case Decl::LinkageSpec:
171 Out << "[linkage spec]";
172 break;
173 case Decl::Block:
174 Out << "[block]";
175 break;
176 case Decl::Function: {
177 const FunctionDecl* FD = cast<FunctionDecl>(DC);
178 if (FD->doesThisDeclarationHaveABody())
179 Out << "[function] ";
180 else
181 Out << "<function> ";
182 Out << *FD;
183 // Print the parameters.
184 Out << "(";
185 bool PrintComma = false;
186 for (FunctionDecl::param_const_iterator I = FD->param_begin(),
187 E = FD->param_end(); I != E; ++I) {
188 if (PrintComma)
189 Out << ", ";
190 else
191 PrintComma = true;
192 Out << **I;
193 }
194 Out << ")";
195 break;
196 }
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) ";
203 else
204 Out << "<c++ method> ";
205 Out << *D;
206 // Print the parameters.
207 Out << "(";
208 bool PrintComma = false;
209 for (FunctionDecl::param_const_iterator I = D->param_begin(),
210 E = D->param_end(); I != E; ++I) {
211 if (PrintComma)
212 Out << ", ";
213 else
214 PrintComma = true;
215 Out << **I;
216 }
217 Out << ")";
218
219 // Check the semantic DeclContext.
220 const DeclContext* SemaDC = D->getDeclContext();
221 const DeclContext* LexicalDC = D->getLexicalDeclContext();
222 if (SemaDC != LexicalDC)
223 Out << " [[" << SemaDC << "]]";
224
225 break;
226 }
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) ";
233 else
234 Out << "<c++ ctor> ";
235 Out << *D;
236 // Print the parameters.
237 Out << "(";
238 bool PrintComma = false;
239 for (FunctionDecl::param_const_iterator I = D->param_begin(),
240 E = D->param_end(); I != E; ++I) {
241 if (PrintComma)
242 Out << ", ";
243 else
244 PrintComma = true;
245 Out << **I;
246 }
247 Out << ")";
248
249 // Check the semantic DC.
250 const DeclContext* SemaDC = D->getDeclContext();
251 const DeclContext* LexicalDC = D->getLexicalDeclContext();
252 if (SemaDC != LexicalDC)
253 Out << " [[" << SemaDC << "]]";
254 break;
255 }
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) ";
262 else
263 Out << "<c++ dtor> ";
264 Out << *D;
265 // Check the semantic DC.
266 const DeclContext* SemaDC = D->getDeclContext();
267 const DeclContext* LexicalDC = D->getLexicalDeclContext();
268 if (SemaDC != LexicalDC)
269 Out << " [[" << SemaDC << "]]";
270 break;
271 }
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) ";
278 else
279 Out << "<c++ conversion> ";
280 Out << *D;
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
289 default:
290 llvm_unreachable("a decl that inherits DeclContext isn't handled");
291 }
292
293 Out << "\n";
294
295 // Print decls in the DeclContext.
296 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
297 I != E; ++I) {
298 for (unsigned i = 0; i < Indentation; ++i)
299 Out << " ";
300
301 Decl::Kind DK = I->getKind();
302 switch (DK) {
303 case Decl::Namespace:
304 case Decl::Enum:
305 case Decl::Record:
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:
314 case Decl::Block:
315 case Decl::Function:
316 case Decl::CXXMethod:
317 case Decl::CXXConstructor:
318 case Decl::CXXDestructor:
319 case Decl::CXXConversion:
320 {
321 DeclContext* DC = cast<DeclContext>(*I);
322 PrintDeclContext(DC, Indentation+2);
323 break;
324 }
325 case Decl::IndirectField: {
326 IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
327 Out << "<IndirectField> " << *IFD << '\n';
328 break;
329 }
330 case Decl::Label: {
331 LabelDecl *LD = cast<LabelDecl>(*I);
332 Out << "<Label> " << *LD << '\n';
333 break;
334 }
335 case Decl::Field: {
336 FieldDecl *FD = cast<FieldDecl>(*I);
337 Out << "<field> " << *FD << '\n';
338 break;
339 }
340 case Decl::Typedef:
341 case Decl::TypeAlias: {
342 TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
343 Out << "<typedef> " << *TD << '\n';
344 break;
345 }
346 case Decl::EnumConstant: {
347 EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
348 Out << "<enum constant> " << *ECD << '\n';
349 break;
350 }
351 case Decl::Var: {
352 VarDecl* VD = cast<VarDecl>(*I);
353 Out << "<var> " << *VD << '\n';
354 break;
355 }
356 case Decl::ImplicitParam: {
357 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
358 Out << "<implicit parameter> " << *IPD << '\n';
359 break;
360 }
361 case Decl::ParmVar: {
362 ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
363 Out << "<parameter> " << *PVD << '\n';
364 break;
365 }
366 case Decl::ObjCProperty: {
367 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
368 Out << "<objc property> " << *OPD << '\n';
369 break;
370 }
371 case Decl::FunctionTemplate: {
372 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
373 Out << "<function template> " << *FTD << '\n';
374 break;
375 }
376 case Decl::FileScopeAsm: {
377 Out << "<file-scope asm>\n";
378 break;
379 }
380 case Decl::UsingDirective: {
381 Out << "<using directive>\n";
382 break;
383 }
384 case Decl::NamespaceAlias: {
385 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
386 Out << "<namespace alias> " << *NAD << '\n';
387 break;
388 }
389 case Decl::ClassTemplate: {
390 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
391 Out << "<class template> " << *CTD << '\n';
392 break;
393 }
394 default:
395 Out << "DeclKind: " << DK << '"' << *I << "\"\n";
396 llvm_unreachable("decl unhandled");
397 }
398 }
399 }
CreateDeclContextPrinter()400 ASTConsumer *clang::CreateDeclContextPrinter() {
401 return new DeclContextPrinter();
402 }
403
404 //===----------------------------------------------------------------------===//
405 /// ASTDumperXML - In-depth XML dumping.
406
407 namespace {
408 class ASTDumpXML : public ASTConsumer {
409 raw_ostream &OS;
410
411 public:
ASTDumpXML(raw_ostream & OS)412 ASTDumpXML(raw_ostream &OS) : OS(OS) {}
413
HandleTranslationUnit(ASTContext & C)414 void HandleTranslationUnit(ASTContext &C) {
415 C.getTranslationUnitDecl()->dumpXML(OS);
416 }
417 };
418 }
419
CreateASTDumperXML(raw_ostream & OS)420 ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) {
421 return new ASTDumpXML(OS);
422 }
423