blob: ba482b049a5c288e3027c9443dc1066a3d3c3e48 [file] [log] [blame]
Chris Lattner97e8b6f2007-10-07 06:04:32 +00001//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
Reid Spencer5f016e22007-07-11 17:01:13 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner97e8b6f2007-10-07 06:04:32 +000010// AST Consumer Implementations.
Reid Spencer5f016e22007-07-11 17:01:13 +000011//
12//===----------------------------------------------------------------------===//
13
Eli Friedman39d7c4d2009-05-18 22:50:54 +000014#include "clang/Frontend/ASTConsumers.h"
Douglas Gregoree75c052009-05-21 20:55:50 +000015#include "clang/Frontend/DocumentXML.h"
Daniel Dunbare1bd4e62009-03-02 06:16:29 +000016#include "clang/Frontend/PathDiagnosticClients.h"
Nico Weberdae86962008-08-09 18:32:11 +000017#include "clang/Basic/Diagnostic.h"
Ted Kremenek54117722007-12-20 00:34:58 +000018#include "clang/Basic/SourceManager.h"
19#include "clang/Basic/FileManager.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000020#include "clang/AST/AST.h"
Chris Lattner3d4997d2007-09-15 23:02:28 +000021#include "clang/AST/ASTConsumer.h"
Chris Lattner557c5b12009-03-28 04:27:18 +000022#include "clang/AST/ASTContext.h"
Ted Kremenek815c78f2008-08-05 18:50:11 +000023#include "clang/CodeGen/ModuleBuilder.h"
24#include "llvm/Module.h"
Daniel Dunbard46075f2008-10-21 23:54:00 +000025#include "llvm/Support/Streams.h"
Ted Kremenekcb330932008-02-18 21:21:23 +000026#include "llvm/Support/Timer.h"
Ted Kremeneka95d3752008-09-13 05:16:45 +000027#include "llvm/Support/raw_ostream.h"
Chris Lattner557c5b12009-03-28 04:27:18 +000028#include "llvm/System/Path.h"
Chris Lattner6000dac2007-08-08 22:51:59 +000029using namespace clang;
Reid Spencer5f016e22007-07-11 17:01:13 +000030
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000031//===----------------------------------------------------------------------===//
32/// DeclPrinter - Utility class for printing top-level decls.
Chris Lattner6000dac2007-08-08 22:51:59 +000033
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000034namespace {
35 class DeclPrinter {
36 public:
Ted Kremeneka95d3752008-09-13 05:16:45 +000037 llvm::raw_ostream& Out;
Mike Stump071e4da2009-02-10 20:16:46 +000038 unsigned Indentation;
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000039
Mike Stump071e4da2009-02-10 20:16:46 +000040 DeclPrinter(llvm::raw_ostream* out) : Out(out ? *out : llvm::errs()),
41 Indentation(0) {}
42 DeclPrinter() : Out(llvm::errs()), Indentation(0) {}
Ted Kremeneka95d3752008-09-13 05:16:45 +000043 virtual ~DeclPrinter();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000044
Mike Stump071e4da2009-02-10 20:16:46 +000045 void ChangeIndent(int I) {
46 Indentation += I;
47 }
48
49 llvm::raw_ostream& Indent() {
50 for (unsigned i = 0; i < Indentation; ++i)
51 Out << " ";
52 return Out;
53 }
54
Chris Lattneref5a85d2008-01-02 21:04:16 +000055 void PrintDecl(Decl *D);
Mike Stump071e4da2009-02-10 20:16:46 +000056 void Print(NamedDecl *ND);
57 void Print(NamespaceDecl *NS);
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000058 void PrintFunctionDeclStart(FunctionDecl *FD);
59 void PrintTypeDefDecl(TypedefDecl *TD);
Chris Lattnerc6fdc342008-01-12 07:05:38 +000060 void PrintLinkageSpec(LinkageSpecDecl *LS);
Ted Kremeneka526c5c2008-01-07 19:49:32 +000061 void PrintObjCMethodDecl(ObjCMethodDecl *OMD);
62 void PrintObjCImplementationDecl(ObjCImplementationDecl *OID);
63 void PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID);
64 void PrintObjCProtocolDecl(ObjCProtocolDecl *PID);
65 void PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID);
66 void PrintObjCCategoryDecl(ObjCCategoryDecl *PID);
67 void PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID);
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +000068 void PrintObjCPropertyDecl(ObjCPropertyDecl *PD);
Fariborz Jahanian628b96f2008-04-23 00:06:01 +000069 void PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID);
Douglas Gregoraaba5e32009-02-04 19:02:06 +000070
71 void PrintTemplateDecl(TemplateDecl *TD);
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000072 };
73} // end anonymous namespace
74
Ted Kremeneka95d3752008-09-13 05:16:45 +000075DeclPrinter::~DeclPrinter() {
76 Out.flush();
77}
78
Chris Lattneref5a85d2008-01-02 21:04:16 +000079void DeclPrinter:: PrintDecl(Decl *D) {
Mike Stump071e4da2009-02-10 20:16:46 +000080 Indent();
Chris Lattneref5a85d2008-01-02 21:04:16 +000081 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
82 PrintFunctionDeclStart(FD);
83
Douglas Gregor72971342009-04-18 00:02:19 +000084 // FIXME: Pass a context here so we can use getBody()
85 if (FD->getBodyIfAvailable()) {
Chris Lattneref5a85d2008-01-02 21:04:16 +000086 Out << ' ';
Douglas Gregor72971342009-04-18 00:02:19 +000087 FD->getBodyIfAvailable()->printPretty(Out, 0, Indentation, true);
Chris Lattneref5a85d2008-01-02 21:04:16 +000088 Out << '\n';
89 }
Ted Kremeneka526c5c2008-01-07 19:49:32 +000090 } else if (isa<ObjCMethodDecl>(D)) {
Chris Lattneref5a85d2008-01-02 21:04:16 +000091 // Do nothing, methods definitions are printed in
Ted Kremeneka526c5c2008-01-07 19:49:32 +000092 // PrintObjCImplementationDecl.
Chris Lattneref5a85d2008-01-02 21:04:16 +000093 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
94 PrintTypeDefDecl(TD);
Ted Kremeneka526c5c2008-01-07 19:49:32 +000095 } else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
96 PrintObjCInterfaceDecl(OID);
97 } else if (ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(D)) {
98 PrintObjCProtocolDecl(PID);
99 } else if (ObjCForwardProtocolDecl *OFPD =
Chris Lattnerc81c8142008-02-25 21:04:36 +0000100 dyn_cast<ObjCForwardProtocolDecl>(D)) {
Chris Lattneref5a85d2008-01-02 21:04:16 +0000101 Out << "@protocol ";
Steve Naroff30833f82009-04-21 15:12:33 +0000102 for (ObjCForwardProtocolDecl::protocol_iterator I = OFPD->protocol_begin(),
103 E = OFPD->protocol_end();
Chris Lattner07fa7742009-02-20 18:10:37 +0000104 I != E; ++I) {
Steve Naroff30833f82009-04-21 15:12:33 +0000105 if (I != OFPD->protocol_begin()) Out << ", ";
Chris Lattner07fa7742009-02-20 18:10:37 +0000106 Out << (*I)->getNameAsString();
Chris Lattneref5a85d2008-01-02 21:04:16 +0000107 }
108 Out << ";\n";
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000109 } else if (ObjCImplementationDecl *OID =
Chris Lattnerc81c8142008-02-25 21:04:36 +0000110 dyn_cast<ObjCImplementationDecl>(D)) {
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000111 PrintObjCImplementationDecl(OID);
112 } else if (ObjCCategoryImplDecl *OID =
Chris Lattnerc81c8142008-02-25 21:04:36 +0000113 dyn_cast<ObjCCategoryImplDecl>(D)) {
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000114 PrintObjCCategoryImplDecl(OID);
115 } else if (ObjCCategoryDecl *OID =
Chris Lattnerc81c8142008-02-25 21:04:36 +0000116 dyn_cast<ObjCCategoryDecl>(D)) {
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000117 PrintObjCCategoryDecl(OID);
118 } else if (ObjCCompatibleAliasDecl *OID =
Chris Lattnerc81c8142008-02-25 21:04:36 +0000119 dyn_cast<ObjCCompatibleAliasDecl>(D)) {
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000120 PrintObjCCompatibleAliasDecl(OID);
Chris Lattner23a0e452008-06-21 21:40:20 +0000121 } else if (ObjCClassDecl *OFCD = dyn_cast<ObjCClassDecl>(D)) {
122 Out << "@class ";
Chris Lattner67956052009-02-20 18:04:31 +0000123 for (ObjCClassDecl::iterator I = OFCD->begin(), E = OFCD->end();
124 I != E; ++I) {
125 if (I != OFCD->begin()) Out << ", ";
126 Out << (*I)->getNameAsString();
Chris Lattner23a0e452008-06-21 21:40:20 +0000127 }
128 Out << ";\n";
Douglas Gregor45579f52008-12-17 02:04:30 +0000129 } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
130 Out << "enum " << ED->getNameAsString() << " {\n";
Douglas Gregor6ab35242009-04-09 21:40:53 +0000131 // FIXME: Shouldn't pass a NULL context
132 ASTContext *Context = 0;
133 for (EnumDecl::enumerator_iterator E = ED->enumerator_begin(*Context),
134 EEnd = ED->enumerator_end(*Context);
Douglas Gregor45579f52008-12-17 02:04:30 +0000135 E != EEnd; ++E)
136 Out << " " << (*E)->getNameAsString() << ",\n";
137 Out << "};\n";
Chris Lattneref5a85d2008-01-02 21:04:16 +0000138 } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
Mike Stump071e4da2009-02-10 20:16:46 +0000139 // print a free standing tag decl (e.g. "struct x;").
140 Out << TD->getKindName();
141 Out << " ";
142 if (const IdentifierInfo *II = TD->getIdentifier())
143 Out << II->getName();
144
Eli Friedmanb3e22962009-05-17 01:05:34 +0000145 if (TD->isDefinition()) {
146 Out << " {\n";
147 ChangeIndent(1);
148 // FIXME: Shouldn't pass a NULL context
149 ASTContext *Context = 0;
150 for (DeclContext::decl_iterator i = TD->decls_begin(*Context);
151 i != TD->decls_end(*Context);
152 ++i)
153 PrintDecl(*i);
154 ChangeIndent(-1);
155 Indent();
156 Out << "}";
157 }
158 Out << ";\n";
Douglas Gregoraaba5e32009-02-04 19:02:06 +0000159 } else if (TemplateDecl *TempD = dyn_cast<TemplateDecl>(D)) {
160 PrintTemplateDecl(TempD);
Chris Lattnerc6fdc342008-01-12 07:05:38 +0000161 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
162 PrintLinkageSpec(LSD);
Anders Carlssondfab6cb2008-02-08 00:33:21 +0000163 } else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) {
164 Out << "asm(";
165 AD->getAsmString()->printPretty(Out);
166 Out << ")\n";
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000167 } else if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
Mike Stump071e4da2009-02-10 20:16:46 +0000168 Print(ND);
Chris Lattneref5a85d2008-01-02 21:04:16 +0000169 } else {
170 assert(0 && "Unknown decl type!");
171 }
172}
173
Mike Stump071e4da2009-02-10 20:16:46 +0000174void DeclPrinter::Print(NamedDecl *ND) {
175 switch (ND->getKind()) {
176 default:
177 // FIXME: Handle the rest of the NamedDecls.
178 Out << "### NamedDecl " << ND->getNameAsString() << "\n";
179 break;
180 case Decl::Field:
181 case Decl::Var: {
182 // Emit storage class for vardecls.
183 if (VarDecl *V = dyn_cast<VarDecl>(ND)) {
184 switch (V->getStorageClass()) {
185 default: assert(0 && "Unknown storage class!");
Mike Stumpc5840c02009-02-10 23:49:50 +0000186 case VarDecl::None: break;
187 case VarDecl::Auto: Out << "auto "; break;
188 case VarDecl::Register: Out << "register "; break;
189 case VarDecl::Extern: Out << "extern "; break;
190 case VarDecl::Static: Out << "static "; break;
Daniel Dunbar7ab41f72009-02-13 22:49:34 +0000191 case VarDecl::PrivateExtern: Out << "__private_extern__ "; break;
Mike Stump071e4da2009-02-10 20:16:46 +0000192 }
193 }
194 std::string Name = ND->getNameAsString();
195 // This forms: "int a".
196 dyn_cast<ValueDecl>(ND)->getType().getAsStringInternal(Name);
Douglas Gregor087fd532009-04-14 23:32:43 +0000197 Out << Name;
198 if (VarDecl *Var = dyn_cast<VarDecl>(ND)) {
199 if (Var->getInit()) {
200 Out << " = ";
201 Var->getInit()->printPretty(Out);
202 }
203 }
204 Out << ";\n";
Mike Stump071e4da2009-02-10 20:16:46 +0000205 break;
206 }
207 case Decl::Namespace:
208 Print(dyn_cast<NamespaceDecl>(ND));
209 break;
210 }
211}
212
213void DeclPrinter::Print(NamespaceDecl *NS) {
214 Out << "namespace " << NS->getNameAsString() << " {\n";
215 ChangeIndent(1);
Douglas Gregor6ab35242009-04-09 21:40:53 +0000216 // FIXME: Shouldn't pass a NULL context
217 ASTContext *Context = 0;
218 for (DeclContext::decl_iterator i = NS->decls_begin(*Context);
219 i != NS->decls_end(*Context);
Mike Stump071e4da2009-02-10 20:16:46 +0000220 ++i)
221 PrintDecl(*i);
222 ChangeIndent(-1);
223 Indent();
224 Out << "}\n";
225}
226
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000227void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
Douglas Gregor72971342009-04-18 00:02:19 +0000228 // FIXME: pass a context so that we can use getBody.
229 bool HasBody = FD->getBodyIfAvailable();
Reid Spencer5f016e22007-07-11 17:01:13 +0000230
Ted Kremenekea75c552007-11-28 21:32:21 +0000231 Out << '\n';
Chris Lattner70c8b2e2007-08-26 04:02:13 +0000232
Mike Stump071e4da2009-02-10 20:16:46 +0000233 Indent();
Chris Lattner70c8b2e2007-08-26 04:02:13 +0000234 switch (FD->getStorageClass()) {
235 default: assert(0 && "Unknown storage class");
236 case FunctionDecl::None: break;
Ted Kremenekea75c552007-11-28 21:32:21 +0000237 case FunctionDecl::Extern: Out << "extern "; break;
238 case FunctionDecl::Static: Out << "static "; break;
Ted Kremenek24bd3c42008-04-15 03:57:09 +0000239 case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
Chris Lattner70c8b2e2007-08-26 04:02:13 +0000240 }
241
242 if (FD->isInline())
Ted Kremenekea75c552007-11-28 21:32:21 +0000243 Out << "inline ";
Chris Lattner70c8b2e2007-08-26 04:02:13 +0000244
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000245 std::string Proto = FD->getNameAsString();
Chris Lattner0d6ca112007-12-03 21:43:25 +0000246 const FunctionType *AFT = FD->getType()->getAsFunctionType();
Reid Spencer5f016e22007-07-11 17:01:13 +0000247
Douglas Gregor72564e72009-02-26 23:50:07 +0000248 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000249 Proto += "(";
250 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
251 if (i) Proto += ", ";
252 std::string ParamStr;
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000253 if (HasBody) ParamStr = FD->getParamDecl(i)->getNameAsString();
Reid Spencer5f016e22007-07-11 17:01:13 +0000254
255 FT->getArgType(i).getAsStringInternal(ParamStr);
256 Proto += ParamStr;
257 }
258
259 if (FT->isVariadic()) {
260 if (FD->getNumParams()) Proto += ", ";
261 Proto += "...";
262 }
263 Proto += ")";
264 } else {
Douglas Gregor72564e72009-02-26 23:50:07 +0000265 assert(isa<FunctionNoProtoType>(AFT));
Reid Spencer5f016e22007-07-11 17:01:13 +0000266 Proto += "()";
267 }
268
269 AFT->getResultType().getAsStringInternal(Proto);
Ted Kremenekea75c552007-11-28 21:32:21 +0000270 Out << Proto;
Reid Spencer5f016e22007-07-11 17:01:13 +0000271
Douglas Gregor72971342009-04-18 00:02:19 +0000272 if (!FD->getBodyIfAvailable())
Ted Kremenekea75c552007-11-28 21:32:21 +0000273 Out << ";\n";
Chris Lattner6000dac2007-08-08 22:51:59 +0000274 // Doesn't print the body.
Reid Spencer5f016e22007-07-11 17:01:13 +0000275}
276
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000277void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000278 std::string S = TD->getNameAsString();
Reid Spencer5f016e22007-07-11 17:01:13 +0000279 TD->getUnderlyingType().getAsStringInternal(S);
Ted Kremenekea75c552007-11-28 21:32:21 +0000280 Out << "typedef " << S << ";\n";
Reid Spencer5f016e22007-07-11 17:01:13 +0000281}
282
Chris Lattnerc6fdc342008-01-12 07:05:38 +0000283void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
284 const char *l;
285 if (LS->getLanguage() == LinkageSpecDecl::lang_c)
286 l = "C";
Chris Lattner06767512008-04-08 05:52:18 +0000287 else {
288 assert(LS->getLanguage() == LinkageSpecDecl::lang_cxx &&
289 "unknown language in linkage specification");
Chris Lattnerc6fdc342008-01-12 07:05:38 +0000290 l = "C++";
Chris Lattner06767512008-04-08 05:52:18 +0000291 }
Douglas Gregorf44515a2008-12-16 22:23:02 +0000292
293 Out << "extern \"" << l << "\" ";
Mike Stump071e4da2009-02-10 20:16:46 +0000294 if (LS->hasBraces()) {
Douglas Gregorf44515a2008-12-16 22:23:02 +0000295 Out << "{\n";
Mike Stump071e4da2009-02-10 20:16:46 +0000296 ChangeIndent(1);
297 }
Douglas Gregorf44515a2008-12-16 22:23:02 +0000298
Douglas Gregor6ab35242009-04-09 21:40:53 +0000299 // FIXME: Should not use a NULL DeclContext!
300 ASTContext *Context = 0;
301 for (LinkageSpecDecl::decl_iterator D = LS->decls_begin(*Context),
302 DEnd = LS->decls_end(*Context);
Douglas Gregorf44515a2008-12-16 22:23:02 +0000303 D != DEnd; ++D)
304 PrintDecl(*D);
305
Mike Stump071e4da2009-02-10 20:16:46 +0000306 if (LS->hasBraces()) {
307 ChangeIndent(-1);
308 Indent() << "}";
309 }
Douglas Gregorf44515a2008-12-16 22:23:02 +0000310 Out << "\n";
Chris Lattnerc6fdc342008-01-12 07:05:38 +0000311}
312
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000313void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
Douglas Gregorf8d49f62009-01-09 17:18:27 +0000314 if (OMD->isInstanceMethod())
Ted Kremenekea75c552007-11-28 21:32:21 +0000315 Out << "\n- ";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000316 else
Ted Kremenekea75c552007-11-28 21:32:21 +0000317 Out << "\n+ ";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000318 if (!OMD->getResultType().isNull())
Chris Lattnerefe8a962008-08-22 06:59:15 +0000319 Out << '(' << OMD->getResultType().getAsString() << ")";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000320
Chris Lattner077bf5e2008-11-24 03:33:13 +0000321 std::string name = OMD->getSelector().getAsString();
Chris Lattnerefe8a962008-08-22 06:59:15 +0000322 std::string::size_type pos, lastPos = 0;
Chris Lattner89951a82009-02-20 18:43:26 +0000323 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
324 E = OMD->param_end(); PI != E; ++PI) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000325 // FIXME: selector is missing here!
Chris Lattnerefe8a962008-08-22 06:59:15 +0000326 pos = name.find_first_of(":", lastPos);
327 Out << " " << name.substr(lastPos, pos - lastPos);
Chris Lattner89951a82009-02-20 18:43:26 +0000328 Out << ":(" << (*PI)->getType().getAsString() << ")"
329 << (*PI)->getNameAsString();
Chris Lattnerefe8a962008-08-22 06:59:15 +0000330 lastPos = pos + 1;
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000331 }
Chris Lattnerefe8a962008-08-22 06:59:15 +0000332
Chris Lattner89951a82009-02-20 18:43:26 +0000333 if (OMD->param_begin() == OMD->param_end())
Chris Lattnerefe8a962008-08-22 06:59:15 +0000334 Out << " " << name;
335
336 if (OMD->isVariadic())
337 Out << ", ...";
338
339 Out << ";";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000340}
341
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000342void DeclPrinter::PrintObjCImplementationDecl(ObjCImplementationDecl *OID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000343 std::string I = OID->getNameAsString();
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000344 ObjCInterfaceDecl *SID = OID->getSuperClass();
Ted Kremenekea75c552007-11-28 21:32:21 +0000345
346 if (SID)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000347 Out << "@implementation " << I << " : " << SID->getNameAsString();
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000348 else
Ted Kremenekea75c552007-11-28 21:32:21 +0000349 Out << "@implementation " << I;
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000350
Douglas Gregor653f1b12009-04-23 01:02:12 +0000351 // FIXME: Don't use a NULL context
352 ASTContext *Context = 0;
353 for (ObjCImplementationDecl::instmeth_iterator
354 I = OID->instmeth_begin(*Context),
355 E = OID->instmeth_end(*Context);
356 I != E; ++I) {
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000357 ObjCMethodDecl *OMD = *I;
358 PrintObjCMethodDecl(OMD);
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000359 if (OMD->getBody()) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000360 Out << ' ';
361 OMD->getBody()->printPretty(Out);
362 Out << '\n';
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000363 }
364 }
365
Douglas Gregor653f1b12009-04-23 01:02:12 +0000366 for (ObjCImplementationDecl::classmeth_iterator
367 I = OID->classmeth_begin(*Context),
368 E = OID->classmeth_end(*Context);
369 I != E; ++I) {
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000370 ObjCMethodDecl *OMD = *I;
371 PrintObjCMethodDecl(OMD);
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000372 if (OMD->getBody()) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000373 Out << ' ';
374 OMD->getBody()->printPretty(Out);
375 Out << '\n';
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000376 }
377 }
378
Douglas Gregor653f1b12009-04-23 01:02:12 +0000379 for (ObjCImplementationDecl::propimpl_iterator
380 I = OID->propimpl_begin(*Context),
381 E = OID->propimpl_end(*Context); I != E; ++I)
Fariborz Jahanian628b96f2008-04-23 00:06:01 +0000382 PrintObjCPropertyImplDecl(*I);
383
Ted Kremenekea75c552007-11-28 21:32:21 +0000384 Out << "@end\n";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000385}
386
387
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000388void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000389 std::string I = OID->getNameAsString();
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000390 ObjCInterfaceDecl *SID = OID->getSuperClass();
Ted Kremenekea75c552007-11-28 21:32:21 +0000391
392 if (SID)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000393 Out << "@interface " << I << " : " << SID->getNameAsString();
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000394 else
Ted Kremenekea75c552007-11-28 21:32:21 +0000395 Out << "@interface " << I;
396
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000397 // Protocols?
Chris Lattner3db6cae2008-07-21 18:19:38 +0000398 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
399 if (!Protocols.empty()) {
400 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
401 E = Protocols.end(); I != E; ++I)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000402 Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getNameAsString();
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000403 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000404
Chris Lattner3db6cae2008-07-21 18:19:38 +0000405 if (!Protocols.empty())
406 Out << ">";
407 Out << '\n';
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000408
Chris Lattnerf3a7af92008-03-16 21:08:55 +0000409 if (OID->ivar_size() > 0) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000410 Out << '{';
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000411 for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
Chris Lattnerbe6df082007-12-12 07:56:42 +0000412 E = OID->ivar_end(); I != E; ++I) {
413 Out << '\t' << (*I)->getType().getAsString()
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000414 << ' ' << (*I)->getNameAsString() << ";\n";
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000415 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000416 Out << "}\n";
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000417 }
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000418
Douglas Gregor6ab35242009-04-09 21:40:53 +0000419 // FIXME: Should not use a NULL DeclContext!
420 ASTContext *Context = 0;
421 for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(*Context),
422 E = OID->prop_end(*Context); I != E; ++I)
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000423 PrintObjCPropertyDecl(*I);
Fariborz Jahanian33de3f02008-05-07 17:43:59 +0000424 bool eol_needed = false;
Douglas Gregor6ab35242009-04-09 21:40:53 +0000425 for (ObjCInterfaceDecl::classmeth_iterator I = OID->classmeth_begin(*Context),
426 E = OID->classmeth_end(*Context); I != E; ++I)
Fariborz Jahanian33de3f02008-05-07 17:43:59 +0000427 eol_needed = true, PrintObjCMethodDecl(*I);
Fariborz Jahanianb89ca232008-05-06 23:14:25 +0000428
Douglas Gregor6ab35242009-04-09 21:40:53 +0000429 for (ObjCInterfaceDecl::instmeth_iterator I = OID->instmeth_begin(*Context),
430 E = OID->instmeth_end(*Context); I != E; ++I)
Fariborz Jahanian33de3f02008-05-07 17:43:59 +0000431 eol_needed = true, PrintObjCMethodDecl(*I);
Fariborz Jahanianb89ca232008-05-06 23:14:25 +0000432
Fariborz Jahanian33de3f02008-05-07 17:43:59 +0000433 Out << (eol_needed ? "\n@end\n" : "@end\n");
Steve Naroff2bd42fa2007-09-10 20:51:04 +0000434 // FIXME: implement the rest...
435}
436
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000437void DeclPrinter::PrintObjCProtocolDecl(ObjCProtocolDecl *PID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000438 Out << "@protocol " << PID->getNameAsString() << '\n';
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000439
Douglas Gregor6ab35242009-04-09 21:40:53 +0000440 // FIXME: Should not use a NULL DeclContext!
441 ASTContext *Context = 0;
442 for (ObjCProtocolDecl::prop_iterator I = PID->prop_begin(*Context),
443 E = PID->prop_end(*Context); I != E; ++I)
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000444 PrintObjCPropertyDecl(*I);
445 Out << "@end\n";
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000446 // FIXME: implement the rest...
447}
448
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000449void DeclPrinter::PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000450 Out << "@implementation "
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000451 << PID->getClassInterface()->getNameAsString()
452 << '(' << PID->getNameAsString() << ");\n";
Douglas Gregor653f1b12009-04-23 01:02:12 +0000453
454 // FIXME: Don't use a NULL context here
455 ASTContext *Context = 0;
456 for (ObjCCategoryImplDecl::propimpl_iterator
457 I = PID->propimpl_begin(*Context),
458 E = PID->propimpl_end(*Context); I != E; ++I)
Fariborz Jahanian628b96f2008-04-23 00:06:01 +0000459 PrintObjCPropertyImplDecl(*I);
460 Out << "@end\n";
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000461 // FIXME: implement the rest...
462}
463
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000464void DeclPrinter::PrintObjCCategoryDecl(ObjCCategoryDecl *PID) {
Douglas Gregor6ab35242009-04-09 21:40:53 +0000465 // FIXME: Should not use a NULL DeclContext!
466 ASTContext *Context = 0;
Ted Kremenekea75c552007-11-28 21:32:21 +0000467 Out << "@interface "
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000468 << PID->getClassInterface()->getNameAsString()
469 << '(' << PID->getNameAsString() << ");\n";
Fariborz Jahanian7e7e3872008-04-16 21:08:45 +0000470 // Output property declarations.
Douglas Gregor6ab35242009-04-09 21:40:53 +0000471 for (ObjCCategoryDecl::prop_iterator I = PID->prop_begin(*Context),
472 E = PID->prop_end(*Context); I != E; ++I)
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000473 PrintObjCPropertyDecl(*I);
Fariborz Jahanian7e7e3872008-04-16 21:08:45 +0000474 Out << "@end\n";
475
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000476 // FIXME: implement the rest...
477}
478
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000479void DeclPrinter::PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000480 Out << "@compatibility_alias " << AID->getNameAsString()
481 << ' ' << AID->getClassInterface()->getNameAsString() << ";\n";
Fariborz Jahanian243b64b2007-10-11 23:42:27 +0000482}
483
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000484/// PrintObjCPropertyDecl - print a property declaration.
485///
486void DeclPrinter::PrintObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
Fariborz Jahanian46b55e52008-05-05 18:51:55 +0000487 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
488 Out << "@required\n";
489 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
490 Out << "@optional\n";
491
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000492 Out << "@property";
493 if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
494 bool first = true;
495 Out << " (";
496 if (PDecl->getPropertyAttributes() &
497 ObjCPropertyDecl::OBJC_PR_readonly) {
498 Out << (first ? ' ' : ',') << "readonly";
499 first = false;
500 }
501
502 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
503 Out << (first ? ' ' : ',') << "getter = "
Chris Lattner077bf5e2008-11-24 03:33:13 +0000504 << PDecl->getGetterName().getAsString();
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000505 first = false;
506 }
507 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
508 Out << (first ? ' ' : ',') << "setter = "
Chris Lattner077bf5e2008-11-24 03:33:13 +0000509 << PDecl->getSetterName().getAsString();
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000510 first = false;
511 }
512
513 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
514 Out << (first ? ' ' : ',') << "assign";
515 first = false;
516 }
517
518 if (PDecl->getPropertyAttributes() &
519 ObjCPropertyDecl::OBJC_PR_readwrite) {
520 Out << (first ? ' ' : ',') << "readwrite";
521 first = false;
522 }
523
524 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
525 Out << (first ? ' ' : ',') << "retain";
526 first = false;
527 }
528
529 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
530 Out << (first ? ' ' : ',') << "copy";
531 first = false;
532 }
533
534 if (PDecl->getPropertyAttributes() &
535 ObjCPropertyDecl::OBJC_PR_nonatomic) {
536 Out << (first ? ' ' : ',') << "nonatomic";
537 first = false;
538 }
539 Out << " )";
540 }
541 Out << ' ' << PDecl->getType().getAsString()
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000542 << ' ' << PDecl->getNameAsString();
Fariborz Jahanian3dd4ba42008-04-17 18:25:18 +0000543
544 Out << ";\n";
545}
Fariborz Jahanian628b96f2008-04-23 00:06:01 +0000546
547/// PrintObjCPropertyImplDecl - Print an objective-c property implementation
548/// declaration syntax.
549///
550void DeclPrinter::PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
Daniel Dunbar9f0afd42008-08-26 04:47:31 +0000551 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
Fariborz Jahanian628b96f2008-04-23 00:06:01 +0000552 Out << "\n@synthesize ";
553 else
554 Out << "\n@dynamic ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000555 Out << PID->getPropertyDecl()->getNameAsString();
Fariborz Jahanian628b96f2008-04-23 00:06:01 +0000556 if (PID->getPropertyIvarDecl())
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000557 Out << "=" << PID->getPropertyIvarDecl()->getNameAsString();
Fariborz Jahanian628b96f2008-04-23 00:06:01 +0000558 Out << ";\n";
559}
Douglas Gregoraaba5e32009-02-04 19:02:06 +0000560
561/// PrintTemplateParams - Print a template parameter list and recursively print
562/// it's underlying top-level definition.
563void DeclPrinter::PrintTemplateDecl(TemplateDecl *TD) {
564 // TODO: Write template parameters.
565 Out << "template <...> ";
566 PrintDecl(TD->getTemplatedDecl());
567}
568
569
570
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000571//===----------------------------------------------------------------------===//
572/// ASTPrinter - Pretty-printer of ASTs
573
Chris Lattner3d4997d2007-09-15 23:02:28 +0000574namespace {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000575 class ASTPrinter : public ASTConsumer, public DeclPrinter {
576 public:
Ted Kremeneka95d3752008-09-13 05:16:45 +0000577 ASTPrinter(llvm::raw_ostream* o = NULL) : DeclPrinter(o) {}
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000578
Chris Lattner682bf922009-03-29 16:50:03 +0000579 virtual void HandleTopLevelDecl(DeclGroupRef D) {
580 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
581 PrintDecl(*I);
Reid Spencer5f016e22007-07-11 17:01:13 +0000582 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000583 };
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000584} // end anonymous namespace
Chris Lattner6000dac2007-08-08 22:51:59 +0000585
Ted Kremeneka95d3752008-09-13 05:16:45 +0000586ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000587 return new ASTPrinter(out);
588}
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000589
590//===----------------------------------------------------------------------===//
Douglas Gregoree75c052009-05-21 20:55:50 +0000591/// ASTPrinterXML - XML-printer of ASTs
592
593namespace {
594 class ASTPrinterXML : public ASTConsumer {
595 DocumentXML Doc;
596
597 public:
598 ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
599
600 void Initialize(ASTContext &Context) {
601 Doc.initialize(Context);
602 }
603
604 virtual void HandleTranslationUnit(ASTContext &Ctx) {
605 Doc.addSubNode("TranslationUnit");
606 for (DeclContext::decl_iterator
607 D = Ctx.getTranslationUnitDecl()->decls_begin(Ctx),
608 DEnd = Ctx.getTranslationUnitDecl()->decls_end(Ctx);
609 D != DEnd;
610 ++D)
611 {
612 Doc.PrintDecl(*D);
613 }
614 Doc.toParent();
615 Doc.finalize();
616 }
617 };
618} // end anonymous namespace
619
620
621ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
622 return new ASTPrinterXML(out ? *out : llvm::outs());
623}
624
625//===----------------------------------------------------------------------===//
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000626/// ASTDumper - Low-level dumper of ASTs
Chris Lattner3d4997d2007-09-15 23:02:28 +0000627
628namespace {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000629 class ASTDumper : public ASTConsumer, public DeclPrinter {
Chris Lattnerc50a2802009-04-25 23:31:28 +0000630 ASTContext *Ctx;
Douglas Gregor609e72f2009-04-26 02:02:08 +0000631 bool FullDump;
632
Chris Lattner3d4997d2007-09-15 23:02:28 +0000633 public:
Douglas Gregor609e72f2009-04-26 02:02:08 +0000634 explicit ASTDumper(bool FullDump) : DeclPrinter(), FullDump(FullDump) {}
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000635
Ted Kremenek95041a22007-12-19 22:51:13 +0000636 void Initialize(ASTContext &Context) {
Chris Lattnerc50a2802009-04-25 23:31:28 +0000637 Ctx = &Context;
Chris Lattner6000dac2007-08-08 22:51:59 +0000638 }
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000639
Chris Lattner682bf922009-03-29 16:50:03 +0000640 virtual void HandleTopLevelDecl(DeclGroupRef D) {
Douglas Gregor609e72f2009-04-26 02:02:08 +0000641 if (FullDump)
642 return;
Chris Lattner682bf922009-03-29 16:50:03 +0000643 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
644 HandleTopLevelSingleDecl(*I);
645 }
646 void HandleTopLevelSingleDecl(Decl *D);
Douglas Gregor609e72f2009-04-26 02:02:08 +0000647
648 virtual void HandleTranslationUnit(ASTContext &Ctx) {
649 if (!FullDump)
650 return;
651
652 for (DeclContext::decl_iterator
653 D = Ctx.getTranslationUnitDecl()->decls_begin(Ctx),
654 DEnd = Ctx.getTranslationUnitDecl()->decls_end(Ctx);
655 D != DEnd;
656 ++D)
657 HandleTopLevelSingleDecl(*D);
658 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000659 };
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000660} // end anonymous namespace
661
Chris Lattner682bf922009-03-29 16:50:03 +0000662void ASTDumper::HandleTopLevelSingleDecl(Decl *D) {
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000663 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
664 PrintFunctionDeclStart(FD);
665
Chris Lattnerc50a2802009-04-25 23:31:28 +0000666 if (Stmt *Body = FD->getBody(*Ctx)) {
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000667 Out << '\n';
Chris Lattnerc50a2802009-04-25 23:31:28 +0000668 // FIXME: convert dumper to use raw_ostream.
669 Body->dumpAll(Ctx->getSourceManager());
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000670 Out << '\n';
671 }
672 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
673 PrintTypeDefDecl(TD);
674 } else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
675 Out << "Read objc interface '" << OID->getNameAsString() << "'\n";
676 } else if (ObjCProtocolDecl *OPD = dyn_cast<ObjCProtocolDecl>(D)) {
677 Out << "Read objc protocol '" << OPD->getNameAsString() << "'\n";
678 } else if (ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(D)) {
679 Out << "Read objc category '" << OCD->getNameAsString() << "'\n";
680 } else if (isa<ObjCForwardProtocolDecl>(D)) {
681 Out << "Read objc fwd protocol decl\n";
682 } else if (isa<ObjCClassDecl>(D)) {
683 Out << "Read objc fwd class decl\n";
684 } else if (isa<FileScopeAsmDecl>(D)) {
685 Out << "Read file scope asm decl\n";
686 } else if (ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) {
687 Out << "Read objc method decl: '" << MD->getSelector().getAsString()
688 << "'\n";
Chris Lattnerc50a2802009-04-25 23:31:28 +0000689 if (Stmt *S = MD->getBody()) {
690 // FIXME: convert dumper to use raw_ostream.
691 S->dumpAll(Ctx->getSourceManager());
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000692 Out << '\n';
693 }
694 } else if (isa<ObjCImplementationDecl>(D)) {
695 Out << "Read objc implementation decl\n";
696 } else if (isa<ObjCCategoryImplDecl>(D)) {
697 Out << "Read objc category implementation decl\n";
698 } else if (isa<LinkageSpecDecl>(D)) {
699 Out << "Read linkage spec decl\n";
700 } else if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
701 Out << "Read top-level variable decl: '" << ND->getNameAsString()
702 << "'\n";
703 } else {
704 assert(0 && "Unknown decl type!");
705 }
Chris Lattner6000dac2007-08-08 22:51:59 +0000706}
707
Douglas Gregor609e72f2009-04-26 02:02:08 +0000708ASTConsumer *clang::CreateASTDumper(bool FullDump) {
709 return new ASTDumper(FullDump);
710}
Chris Lattner3d4997d2007-09-15 23:02:28 +0000711
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000712//===----------------------------------------------------------------------===//
713/// ASTViewer - AST Visualization
714
Ted Kremenek80de08f2007-09-19 21:29:43 +0000715namespace {
716 class ASTViewer : public ASTConsumer {
717 SourceManager *SM;
718 public:
Ted Kremenek95041a22007-12-19 22:51:13 +0000719 void Initialize(ASTContext &Context) {
Ted Kremenek7a9d49f2007-12-11 21:27:55 +0000720 SM = &Context.getSourceManager();
Ted Kremenek80de08f2007-09-19 21:29:43 +0000721 }
Chris Lattner682bf922009-03-29 16:50:03 +0000722
723 virtual void HandleTopLevelDecl(DeclGroupRef D) {
724 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
725 HandleTopLevelSingleDecl(*I);
726 }
Ted Kremenek80de08f2007-09-19 21:29:43 +0000727
Chris Lattner682bf922009-03-29 16:50:03 +0000728 void HandleTopLevelSingleDecl(Decl *D);
Ted Kremenek80de08f2007-09-19 21:29:43 +0000729 };
730}
731
Chris Lattner682bf922009-03-29 16:50:03 +0000732void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000733 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
734 DeclPrinter().PrintFunctionDeclStart(FD);
735
Douglas Gregor72971342009-04-18 00:02:19 +0000736 if (FD->getBodyIfAvailable()) {
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000737 llvm::cerr << '\n';
Douglas Gregor72971342009-04-18 00:02:19 +0000738 FD->getBodyIfAvailable()->viewAST();
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000739 llvm::cerr << '\n';
740 }
741 return;
742 }
743
744 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
745 DeclPrinter().PrintObjCMethodDecl(MD);
746
747 if (MD->getBody()) {
748 llvm::cerr << '\n';
749 MD->getBody()->viewAST();
750 llvm::cerr << '\n';
751 }
752 }
753}
754
755
Ted Kremenek80de08f2007-09-19 21:29:43 +0000756ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
757
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000758//===----------------------------------------------------------------------===//
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000759/// DeclContextPrinter - Decl and DeclContext Visualization
760
761namespace {
762
763class DeclContextPrinter : public ASTConsumer {
764 llvm::raw_ostream& Out;
765public:
766 DeclContextPrinter() : Out(llvm::errs()) {}
767
Chris Lattnerdacbc5d2009-03-28 04:11:33 +0000768 void HandleTranslationUnit(ASTContext &C) {
769 PrintDeclContext(C.getTranslationUnitDecl(), 4);
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000770 }
771
772 void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
773};
Chris Lattnerb23ff6b2009-03-28 05:44:17 +0000774} // end anonymous namespace
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000775
776void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
777 unsigned Indentation) {
778 // Print DeclContext name.
Argyrios Kyrtzidis9b9ca012009-01-13 13:11:58 +0000779 switch (DC->getDeclKind()) {
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000780 case Decl::TranslationUnit:
781 Out << "[translation unit] " << DC;
782 break;
783 case Decl::Namespace: {
784 Out << "[namespace] ";
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000785 const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000786 Out << ND->getNameAsString();
787 break;
788 }
Zhongxing Xu867c39e2009-01-13 02:41:08 +0000789 case Decl::Enum: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000790 const EnumDecl* ED = cast<EnumDecl>(DC);
Zhongxing Xu867c39e2009-01-13 02:41:08 +0000791 if (ED->isDefinition())
792 Out << "[enum] ";
793 else
794 Out << "<enum> ";
795 Out << ED->getNameAsString();
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000796 break;
Zhongxing Xu867c39e2009-01-13 02:41:08 +0000797 }
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000798 case Decl::Record: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000799 const RecordDecl* RD = cast<RecordDecl>(DC);
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000800 if (RD->isDefinition())
801 Out << "[struct] ";
802 else
803 Out << "<struct> ";
804 Out << RD->getNameAsString();
805 break;
806 }
807 case Decl::CXXRecord: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000808 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000809 if (RD->isDefinition())
810 Out << "[class] ";
811 else
812 Out << "<class> ";
813 Out << RD->getNameAsString() << " " << DC;
814 break;
815 }
816 case Decl::ObjCMethod:
817 Out << "[objc method]";
818 break;
819 case Decl::ObjCInterface:
820 Out << "[objc interface]";
821 break;
822 case Decl::ObjCCategory:
823 Out << "[objc category]";
824 break;
825 case Decl::ObjCProtocol:
826 Out << "[objc protocol]";
827 break;
828 case Decl::ObjCImplementation:
829 Out << "[objc implementation]";
830 break;
831 case Decl::ObjCCategoryImpl:
832 Out << "[objc categoryimpl]";
833 break;
834 case Decl::LinkageSpec:
835 Out << "[linkage spec]";
836 break;
837 case Decl::Block:
838 Out << "[block]";
839 break;
840 case Decl::Function: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000841 const FunctionDecl* FD = cast<FunctionDecl>(DC);
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000842 if (FD->isThisDeclarationADefinition())
843 Out << "[function] ";
844 else
845 Out << "<function> ";
846 Out << FD->getNameAsString();
Zhongxing Xuca04ce42009-01-13 06:25:33 +0000847 // Print the parameters.
848 Out << "(";
849 bool PrintComma = false;
850 for (FunctionDecl::param_const_iterator I = FD->param_begin(),
851 E = FD->param_end(); I != E; ++I) {
852 if (PrintComma)
853 Out << ", ";
854 else
855 PrintComma = true;
856 Out << (*I)->getNameAsString();
857 }
858 Out << ")";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000859 break;
860 }
861 case Decl::CXXMethod: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000862 const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000863 if (D->isOutOfLineDefinition())
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000864 Out << "[c++ method] ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000865 else if (D->isImplicit())
866 Out << "(c++ method) ";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000867 else
868 Out << "<c++ method> ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000869 Out << D->getNameAsString();
Zhongxing Xuca04ce42009-01-13 06:25:33 +0000870 // Print the parameters.
871 Out << "(";
872 bool PrintComma = false;
873 for (FunctionDecl::param_const_iterator I = D->param_begin(),
874 E = D->param_end(); I != E; ++I) {
875 if (PrintComma)
876 Out << ", ";
877 else
878 PrintComma = true;
879 Out << (*I)->getNameAsString();
880 }
881 Out << ")";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000882
883 // Check the semantic DeclContext.
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000884 const DeclContext* SemaDC = D->getDeclContext();
885 const DeclContext* LexicalDC = D->getLexicalDeclContext();
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000886 if (SemaDC != LexicalDC)
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000887 Out << " [[" << SemaDC << "]]";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000888
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000889 break;
890 }
891 case Decl::CXXConstructor: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000892 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000893 if (D->isOutOfLineDefinition())
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000894 Out << "[c++ ctor] ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000895 else if (D->isImplicit())
896 Out << "(c++ ctor) ";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000897 else
898 Out << "<c++ ctor> ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000899 Out << D->getNameAsString();
Zhongxing Xuca04ce42009-01-13 06:25:33 +0000900 // Print the parameters.
901 Out << "(";
902 bool PrintComma = false;
903 for (FunctionDecl::param_const_iterator I = D->param_begin(),
904 E = D->param_end(); I != E; ++I) {
905 if (PrintComma)
906 Out << ", ";
907 else
908 PrintComma = true;
909 Out << (*I)->getNameAsString();
910 }
911 Out << ")";
912
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000913 // Check the semantic DC.
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000914 const DeclContext* SemaDC = D->getDeclContext();
915 const DeclContext* LexicalDC = D->getLexicalDeclContext();
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000916 if (SemaDC != LexicalDC)
917 Out << " [[" << SemaDC << "]]";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000918 break;
919 }
920 case Decl::CXXDestructor: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000921 const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000922 if (D->isOutOfLineDefinition())
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000923 Out << "[c++ dtor] ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000924 else if (D->isImplicit())
925 Out << "(c++ dtor) ";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000926 else
927 Out << "<c++ dtor> ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000928 Out << D->getNameAsString();
929 // Check the semantic DC.
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000930 const DeclContext* SemaDC = D->getDeclContext();
931 const DeclContext* LexicalDC = D->getLexicalDeclContext();
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000932 if (SemaDC != LexicalDC)
933 Out << " [[" << SemaDC << "]]";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000934 break;
935 }
936 case Decl::CXXConversion: {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000937 const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000938 if (D->isOutOfLineDefinition())
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000939 Out << "[c++ conversion] ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000940 else if (D->isImplicit())
941 Out << "(c++ conversion) ";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000942 else
943 Out << "<c++ conversion> ";
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000944 Out << D->getNameAsString();
945 // Check the semantic DC.
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000946 const DeclContext* SemaDC = D->getDeclContext();
947 const DeclContext* LexicalDC = D->getLexicalDeclContext();
Zhongxing Xu2a3eb0e2009-01-13 03:26:38 +0000948 if (SemaDC != LexicalDC)
949 Out << " [[" << SemaDC << "]]";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000950 break;
951 }
952
953 default:
954 assert(0 && "a decl that inherits DeclContext isn't handled");
955 }
956
957 Out << "\n";
958
959 // Print decls in the DeclContext.
Douglas Gregor6ab35242009-04-09 21:40:53 +0000960 // FIXME: Should not use a NULL DeclContext!
961 ASTContext *Context = 0;
962 for (DeclContext::decl_iterator I = DC->decls_begin(*Context),
963 E = DC->decls_end(*Context);
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000964 I != E; ++I) {
965 for (unsigned i = 0; i < Indentation; ++i)
Mike Stump071e4da2009-02-10 20:16:46 +0000966 Out << " ";
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000967
968 Decl::Kind DK = I->getKind();
969 switch (DK) {
970 case Decl::Namespace:
971 case Decl::Enum:
972 case Decl::Record:
973 case Decl::CXXRecord:
974 case Decl::ObjCMethod:
975 case Decl::ObjCInterface:
976 case Decl::ObjCCategory:
977 case Decl::ObjCProtocol:
978 case Decl::ObjCImplementation:
979 case Decl::ObjCCategoryImpl:
980 case Decl::LinkageSpec:
981 case Decl::Block:
982 case Decl::Function:
983 case Decl::CXXMethod:
984 case Decl::CXXConstructor:
985 case Decl::CXXDestructor:
986 case Decl::CXXConversion:
987 {
Argyrios Kyrtzidis7ad5bf32009-02-16 14:29:59 +0000988 DeclContext* DC = cast<DeclContext>(*I);
Mike Stump071e4da2009-02-10 20:16:46 +0000989 PrintDeclContext(DC, Indentation+2);
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +0000990 break;
991 }
992 case Decl::Field: {
993 FieldDecl* FD = cast<FieldDecl>(*I);
994 Out << "<field> " << FD->getNameAsString() << "\n";
995 break;
996 }
997 case Decl::Typedef: {
998 TypedefDecl* TD = cast<TypedefDecl>(*I);
999 Out << "<typedef> " << TD->getNameAsString() << "\n";
1000 break;
1001 }
1002 case Decl::EnumConstant: {
1003 EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
1004 Out << "<enum constant> " << ECD->getNameAsString() << "\n";
1005 break;
1006 }
1007 case Decl::Var: {
1008 VarDecl* VD = cast<VarDecl>(*I);
1009 Out << "<var> " << VD->getNameAsString() << "\n";
1010 break;
1011 }
1012 case Decl::ImplicitParam: {
1013 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
1014 Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
1015 break;
1016 }
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +00001017 case Decl::ParmVar: {
1018 ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
1019 Out << "<parameter> " << PVD->getNameAsString() << "\n";
1020 break;
1021 }
Zhongxing Xuba16be92009-04-05 02:04:38 +00001022 case Decl::OriginalParmVar: {
1023 OriginalParmVarDecl* OPVD = cast<OriginalParmVarDecl>(*I);
1024 Out << "<original parameter> " << OPVD->getNameAsString() << "\n";
1025 break;
1026 }
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +00001027 case Decl::ObjCProperty: {
1028 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
1029 Out << "<objc property> " << OPD->getNameAsString() << "\n";
1030 break;
1031 }
1032 default:
Zhongxing Xuba16be92009-04-05 02:04:38 +00001033 fprintf(stderr, "DeclKind: %d \"%s\"\n", DK, I->getDeclKindName());
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +00001034 assert(0 && "decl unhandled");
1035 }
1036 }
1037}
Zhongxing Xu2d75d6f2009-01-13 01:29:24 +00001038ASTConsumer *clang::CreateDeclContextPrinter() {
1039 return new DeclContextPrinter();
1040}
1041
1042//===----------------------------------------------------------------------===//
Ted Kremenek7cae2f62008-10-23 23:36:29 +00001043/// InheritanceViewer - C++ Inheritance Visualization
1044
1045namespace {
1046class InheritanceViewer : public ASTConsumer {
1047 const std::string clsname;
1048public:
1049 InheritanceViewer(const std::string& cname) : clsname(cname) {}
1050
Chris Lattnerdacbc5d2009-03-28 04:11:33 +00001051 void HandleTranslationUnit(ASTContext &C) {
Ted Kremenek7cae2f62008-10-23 23:36:29 +00001052 for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
Douglas Gregorc1efaec2009-02-28 01:32:25 +00001053 if (RecordType *T = dyn_cast<RecordType>(*I)) {
1054 if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) {
1055 // FIXME: This lookup needs to be generalized to handle namespaces and
1056 // (when we support them) templates.
1057 if (D->getNameAsString() == clsname) {
1058 D->viewInheritance(C);
1059 }
Ted Kremenek7cae2f62008-10-23 23:36:29 +00001060 }
1061 }
1062 }
1063};
1064}
1065
1066ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
1067 return new InheritanceViewer(clsname);
1068}