blob: 22863411b1a1b8c63506a2f10a94ca5ce123ae89 [file] [log] [blame]
Chris Lattnereb8c9632007-10-07 06:04:32 +00001//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
Chris Lattner4b009652007-07-25 00:24:17 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattnereb8c9632007-10-07 06:04:32 +00005// This file was developed by Chris Lattner and is distributed under the
Chris Lattner4b009652007-07-25 00:24:17 +00006// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattnereb8c9632007-10-07 06:04:32 +000010// AST Consumer Implementations.
Chris Lattner4b009652007-07-25 00:24:17 +000011//
12//===----------------------------------------------------------------------===//
13
Chris Lattnereb8c9632007-10-07 06:04:32 +000014#include "ASTConsumers.h"
Chris Lattner4b009652007-07-25 00:24:17 +000015#include "clang/AST/AST.h"
Chris Lattnerb73abd52007-09-15 23:02:28 +000016#include "clang/AST/ASTConsumer.h"
Ted Kremenek97f75312007-08-21 21:42:03 +000017#include "clang/AST/CFG.h"
Ted Kremenekaa04c512007-09-06 00:17:54 +000018#include "clang/Analysis/LiveVariables.h"
Ted Kremeneke805c4a2007-09-06 23:00:42 +000019#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000020#include "llvm/Support/Streams.h"
Ted Kremeneke09391a2007-11-27 21:46:50 +000021
Chris Lattner95578782007-08-08 22:51:59 +000022using namespace clang;
Chris Lattner4b009652007-07-25 00:24:17 +000023
Ted Kremeneke09391a2007-11-27 21:46:50 +000024//===----------------------------------------------------------------------===//
25/// DeclPrinter - Utility class for printing top-level decls.
Chris Lattner95578782007-08-08 22:51:59 +000026
Ted Kremeneke09391a2007-11-27 21:46:50 +000027namespace {
28 class DeclPrinter {
29 public:
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000030 std::ostream& Out;
Ted Kremeneke09391a2007-11-27 21:46:50 +000031
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000032 DeclPrinter(std::ostream* out) : Out(out ? *out : *llvm::cerr.stream()) {}
33 DeclPrinter() : Out(*llvm::cerr.stream()) {}
Ted Kremeneke09391a2007-11-27 21:46:50 +000034
35 void PrintFunctionDeclStart(FunctionDecl *FD);
36 void PrintTypeDefDecl(TypedefDecl *TD);
37 void PrintObjcMethodDecl(ObjcMethodDecl *OMD);
38 void PrintObjcImplementationDecl(ObjcImplementationDecl *OID);
39 void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID);
40 void PrintObjcProtocolDecl(ObjcProtocolDecl *PID);
41 void PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID);
42 void PrintObjcCategoryDecl(ObjcCategoryDecl *PID);
43 void PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID);
44 };
45} // end anonymous namespace
46
47void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
Chris Lattner4b009652007-07-25 00:24:17 +000048 bool HasBody = FD->getBody();
49
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000050 Out << '\n';
Chris Lattner987058a2007-08-26 04:02:13 +000051
52 switch (FD->getStorageClass()) {
53 default: assert(0 && "Unknown storage class");
54 case FunctionDecl::None: break;
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000055 case FunctionDecl::Extern: Out << "extern "; break;
56 case FunctionDecl::Static: Out << "static "; break;
Chris Lattner987058a2007-08-26 04:02:13 +000057 }
58
59 if (FD->isInline())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000060 Out << "inline ";
Chris Lattner987058a2007-08-26 04:02:13 +000061
Chris Lattner4b009652007-07-25 00:24:17 +000062 std::string Proto = FD->getName();
Chris Lattner934fff62007-12-03 21:43:25 +000063 const FunctionType *AFT = FD->getType()->getAsFunctionType();
Chris Lattner4b009652007-07-25 00:24:17 +000064
Chris Lattner934fff62007-12-03 21:43:25 +000065 if (const FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
Chris Lattner4b009652007-07-25 00:24:17 +000066 Proto += "(";
67 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
68 if (i) Proto += ", ";
69 std::string ParamStr;
70 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
71
72 FT->getArgType(i).getAsStringInternal(ParamStr);
73 Proto += ParamStr;
74 }
75
76 if (FT->isVariadic()) {
77 if (FD->getNumParams()) Proto += ", ";
78 Proto += "...";
79 }
80 Proto += ")";
81 } else {
82 assert(isa<FunctionTypeNoProto>(AFT));
83 Proto += "()";
84 }
85
86 AFT->getResultType().getAsStringInternal(Proto);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000087 Out << Proto;
Chris Lattner4b009652007-07-25 00:24:17 +000088
Chris Lattner95578782007-08-08 22:51:59 +000089 if (!FD->getBody())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000090 Out << ";\n";
Chris Lattner95578782007-08-08 22:51:59 +000091 // Doesn't print the body.
Chris Lattner4b009652007-07-25 00:24:17 +000092}
93
Ted Kremeneke09391a2007-11-27 21:46:50 +000094void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattner4b009652007-07-25 00:24:17 +000095 std::string S = TD->getName();
96 TD->getUnderlyingType().getAsStringInternal(S);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000097 Out << "typedef " << S << ";\n";
Chris Lattner4b009652007-07-25 00:24:17 +000098}
99
Ted Kremeneke09391a2007-11-27 21:46:50 +0000100void DeclPrinter::PrintObjcMethodDecl(ObjcMethodDecl *OMD) {
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000101 if (OMD->isInstance())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000102 Out << "\n- ";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000103 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000104 Out << "\n+ ";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000105 if (!OMD->getResultType().isNull())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000106 Out << '(' << OMD->getResultType().getAsString() << ") ";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000107 // FIXME: just print original selector name!
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000108 Out << OMD->getSelector().getName();
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000109
110 for (int i = 0; i < OMD->getNumParams(); i++) {
111 ParmVarDecl *PDecl = OMD->getParamDecl(i);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000112 // FIXME: selector is missing here!
113 Out << " :(" << PDecl->getType().getAsString() << ") " << PDecl->getName();
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000114 }
115}
116
Ted Kremeneke09391a2007-11-27 21:46:50 +0000117void DeclPrinter::PrintObjcImplementationDecl(ObjcImplementationDecl *OID) {
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000118 std::string I = OID->getName();
119 ObjcInterfaceDecl *SID = OID->getSuperClass();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000120
121 if (SID)
122 Out << "@implementation " << I << " : " << SID->getName();
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000123 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000124 Out << "@implementation " << I;
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000125
Chris Lattnerdea5bec2007-12-12 07:46:12 +0000126 for (ObjcImplementationDecl::instmeth_iterator I = OID->instmeth_begin(),
127 E = OID->instmeth_end(); I != E; ++I) {
128 ObjcMethodDecl *OMD = *I;
129 PrintObjcMethodDecl(OMD);
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000130 if (OMD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000131 Out << ' ';
132 OMD->getBody()->printPretty(Out);
133 Out << '\n';
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000134 }
135 }
136
Chris Lattnerdea5bec2007-12-12 07:46:12 +0000137 for (ObjcImplementationDecl::classmeth_iterator I = OID->classmeth_begin(),
138 E = OID->classmeth_end(); I != E; ++I) {
139 ObjcMethodDecl *OMD = *I;
140 PrintObjcMethodDecl(OMD);
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000141 if (OMD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000142 Out << ' ';
143 OMD->getBody()->printPretty(Out);
144 Out << '\n';
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000145 }
146 }
147
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000148 Out << "@end\n";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000149}
150
151
Ted Kremeneke09391a2007-11-27 21:46:50 +0000152void DeclPrinter::PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000153 std::string I = OID->getName();
154 ObjcInterfaceDecl *SID = OID->getSuperClass();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000155
156 if (SID)
157 Out << "@interface " << I << " : " << SID->getName();
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000158 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000159 Out << "@interface " << I;
160
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000161 // Protocols?
162 int count = OID->getNumIntfRefProtocols();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000163
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000164 if (count > 0) {
165 ObjcProtocolDecl **refProtocols = OID->getReferencedProtocols();
166 for (int i = 0; i < count; i++)
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000167 Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName();
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000168 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000169
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000170 if (count > 0)
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000171 Out << ">\n";
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000172 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000173 Out << '\n';
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000174
Steve Naroffdd2e26c2007-11-12 13:56:41 +0000175 int NumIvars = OID->getNumInstanceVariables();
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000176 if (NumIvars > 0) {
Steve Naroffdd2e26c2007-11-12 13:56:41 +0000177 ObjcIvarDecl **Ivars = OID->getInstanceVariables();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000178 Out << '{';
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000179 for (int i = 0; i < NumIvars; i++) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000180 Out << '\t' << Ivars[i]->getType().getAsString()
181 << ' ' << Ivars[i]->getName()
182 << ";\n";
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000183 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000184 Out << "}\n";
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000185 }
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000186
187 int NumProperties = OID->getNumPropertyDecl();
188 if (NumProperties > 0) {
189 for (int i = 0; i < NumProperties; i++) {
190 ObjcPropertyDecl *PDecl = OID->getPropertyDecl()[i];
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000191 Out << "@property";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000192 if (PDecl->getPropertyAttributes() != ObjcPropertyDecl::OBJC_PR_noattr) {
193 bool first = true;
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000194 Out << " (";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000195 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readonly)
196 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000197 Out << (first ? ' ' : ',') << "readonly";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000198 first = false;
199 }
200
201 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_getter)
202 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000203 Out << (first ? ' ' : ',') << "getter = "
204 << PDecl->getGetterName()->getName();
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000205 first = false;
206 }
207 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_setter)
208 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000209 Out << (first ? ' ' : ',') << "setter = "
210 << PDecl->getSetterName()->getName();
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000211 first = false;
212 }
213
214 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_assign)
215 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000216 Out << (first ? ' ' : ',') << "assign";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000217 first = false;
218 }
219
220 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readwrite)
221 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000222 Out << (first ? ' ' : ',') << "readwrite";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000223 first = false;
224 }
225
226 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_retain)
227 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000228 Out << (first ? ' ' : ',') << "retain";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000229 first = false;
230 }
231
232 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_copy)
233 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000234 Out << (first ? ' ' : ',') << "copy";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000235 first = false;
236 }
237
238 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_nonatomic)
239 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000240 Out << (first ? ' ' : ',') << "nonatomic";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000241 first = false;
242 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000243 Out << " )";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000244 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000245
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000246 ObjcIvarDecl **IDecl = PDecl->getPropertyDecls();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000247
248 Out << ' ' << IDecl[0]->getType().getAsString()
249 << ' ' << IDecl[0]->getName();
250
251 for (int j = 1; j < PDecl->getNumPropertyDecls(); j++)
252 Out << ", " << IDecl[j]->getName();
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000253
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000254 Out << ";\n";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000255 }
256 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000257
258 Out << "@end\n";
Steve Narofffaed3bf2007-09-10 20:51:04 +0000259 // FIXME: implement the rest...
260}
261
Ted Kremeneke09391a2007-11-27 21:46:50 +0000262void DeclPrinter::PrintObjcProtocolDecl(ObjcProtocolDecl *PID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000263 Out << "@protocol " << PID->getName() << '\n';
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000264 // FIXME: implement the rest...
265}
266
Ted Kremeneke09391a2007-11-27 21:46:50 +0000267void DeclPrinter::PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000268 Out << "@implementation "
269 << PID->getClassInterface()->getName()
270 << '(' << PID->getName() << ");\n";
271
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000272 // FIXME: implement the rest...
273}
274
Ted Kremeneke09391a2007-11-27 21:46:50 +0000275void DeclPrinter::PrintObjcCategoryDecl(ObjcCategoryDecl *PID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000276 Out << "@interface "
277 << PID->getClassInterface()->getName()
278 << '(' << PID->getName() << ");\n";
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000279 // FIXME: implement the rest...
280}
281
Ted Kremeneke09391a2007-11-27 21:46:50 +0000282void DeclPrinter::PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000283 Out << "@compatibility_alias " << AID->getName()
284 << ' ' << AID->getClassInterface()->getName() << ";\n";
Fariborz Jahanian05d212a2007-10-11 23:42:27 +0000285}
286
Ted Kremeneke09391a2007-11-27 21:46:50 +0000287//===----------------------------------------------------------------------===//
288/// ASTPrinter - Pretty-printer of ASTs
289
Chris Lattnerb73abd52007-09-15 23:02:28 +0000290namespace {
Ted Kremeneke09391a2007-11-27 21:46:50 +0000291 class ASTPrinter : public ASTConsumer, public DeclPrinter {
292 public:
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000293 ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}
Ted Kremeneke09391a2007-11-27 21:46:50 +0000294
Chris Lattnerb73abd52007-09-15 23:02:28 +0000295 virtual void HandleTopLevelDecl(Decl *D) {
296 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
297 PrintFunctionDeclStart(FD);
298
299 if (FD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000300 Out << ' ';
301 FD->getBody()->printPretty(Out);
302 Out << '\n';
Chris Lattnerb73abd52007-09-15 23:02:28 +0000303 }
Steve Naroff3a3a0cb2007-11-13 23:48:03 +0000304 } else if (isa<ObjcMethodDecl>(D)) {
305 // Do nothing, methods definitions are printed in
306 // PrintObjcImplementationDecl.
Chris Lattnerb73abd52007-09-15 23:02:28 +0000307 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
308 PrintTypeDefDecl(TD);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000309 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
310 PrintObjcInterfaceDecl(OID);
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000311 } else if (ObjcProtocolDecl *PID = dyn_cast<ObjcProtocolDecl>(D)) {
312 PrintObjcProtocolDecl(PID);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000313 } else if (ObjcForwardProtocolDecl *OFPD =
314 dyn_cast<ObjcForwardProtocolDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000315 Out << "@protocol ";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000316 for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
317 const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000318 if (i) Out << ", ";
319 Out << D->getName();
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000320 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000321 Out << ";\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000322 } else if (ObjcImplementationDecl *OID =
323 dyn_cast<ObjcImplementationDecl>(D)) {
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000324 PrintObjcImplementationDecl(OID);
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000325 } else if (ObjcCategoryImplDecl *OID =
326 dyn_cast<ObjcCategoryImplDecl>(D)) {
327 PrintObjcCategoryImplDecl(OID);
328 } else if (ObjcCategoryDecl *OID =
329 dyn_cast<ObjcCategoryDecl>(D)) {
330 PrintObjcCategoryDecl(OID);
Fariborz Jahanian05d212a2007-10-11 23:42:27 +0000331 } else if (ObjcCompatibleAliasDecl *OID =
332 dyn_cast<ObjcCompatibleAliasDecl>(D)) {
333 PrintObjcCompatibleAliasDecl(OID);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000334 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000335 Out << "@class [printing todo]\n";
Steve Naroff6fd865b2007-11-28 22:54:11 +0000336 } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
337 Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000338 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000339 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000340 } else {
341 assert(0 && "Unknown decl type!");
Chris Lattner95578782007-08-08 22:51:59 +0000342 }
Chris Lattner4b009652007-07-25 00:24:17 +0000343 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000344 };
Chris Lattner4b009652007-07-25 00:24:17 +0000345}
Chris Lattner95578782007-08-08 22:51:59 +0000346
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000347ASTConsumer *clang::CreateASTPrinter(std::ostream* out) {
348 return new ASTPrinter(out);
349}
Ted Kremeneke09391a2007-11-27 21:46:50 +0000350
351//===----------------------------------------------------------------------===//
352/// ASTDumper - Low-level dumper of ASTs
Chris Lattnerb73abd52007-09-15 23:02:28 +0000353
354namespace {
Ted Kremeneke09391a2007-11-27 21:46:50 +0000355 class ASTDumper : public ASTConsumer, public DeclPrinter {
Chris Lattnerb73abd52007-09-15 23:02:28 +0000356 SourceManager *SM;
357 public:
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000358 ASTDumper() : DeclPrinter() {}
Ted Kremeneke09391a2007-11-27 21:46:50 +0000359
Chris Lattnerb73abd52007-09-15 23:02:28 +0000360 void Initialize(ASTContext &Context, unsigned MainFileID) {
Ted Kremenekb3ee1932007-12-11 21:27:55 +0000361 SM = &Context.getSourceManager();
Chris Lattner95578782007-08-08 22:51:59 +0000362 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000363
364 virtual void HandleTopLevelDecl(Decl *D) {
365 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
366 PrintFunctionDeclStart(FD);
367
368 if (FD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000369 Out << '\n';
370 // FIXME: convert dumper to use std::ostream?
Chris Lattnerb73abd52007-09-15 23:02:28 +0000371 FD->getBody()->dumpAll(*SM);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000372 Out << '\n';
Chris Lattnerb73abd52007-09-15 23:02:28 +0000373 }
374 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
375 PrintTypeDefDecl(TD);
376 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000377 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000378 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000379 Out << "Read objc interface '" << OID->getName() << "'\n";
Steve Naroffd5d18732007-10-14 17:03:01 +0000380 } else if (ObjcProtocolDecl *OPD = dyn_cast<ObjcProtocolDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000381 Out << "Read objc protocol '" << OPD->getName() << "'\n";
Steve Naroffd5d18732007-10-14 17:03:01 +0000382 } else if (ObjcCategoryDecl *OCD = dyn_cast<ObjcCategoryDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000383 Out << "Read objc category '" << OCD->getName() << "'\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000384 } else if (isa<ObjcForwardProtocolDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000385 Out << "Read objc fwd protocol decl\n";
Steve Naroffd5d18732007-10-14 17:03:01 +0000386 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000387 Out << "Read objc fwd class decl\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000388 } else {
389 assert(0 && "Unknown decl type!");
Chris Lattnerb73abd52007-09-15 23:02:28 +0000390 }
391 }
392 };
Chris Lattner95578782007-08-08 22:51:59 +0000393}
394
Chris Lattnerb73abd52007-09-15 23:02:28 +0000395ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
396
Ted Kremeneke09391a2007-11-27 21:46:50 +0000397//===----------------------------------------------------------------------===//
398/// ASTViewer - AST Visualization
399
Ted Kremenekb6976a22007-09-19 21:29:43 +0000400namespace {
401 class ASTViewer : public ASTConsumer {
402 SourceManager *SM;
403 public:
404 void Initialize(ASTContext &Context, unsigned MainFileID) {
Ted Kremenekb3ee1932007-12-11 21:27:55 +0000405 SM = &Context.getSourceManager();
Ted Kremenekb6976a22007-09-19 21:29:43 +0000406 }
407
408 virtual void HandleTopLevelDecl(Decl *D) {
409 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000410 DeclPrinter().PrintFunctionDeclStart(FD);
Ted Kremenekb6976a22007-09-19 21:29:43 +0000411
412 if (FD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000413 llvm::cerr << '\n';
Ted Kremenekb6976a22007-09-19 21:29:43 +0000414 FD->getBody()->viewAST();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000415 llvm::cerr << '\n';
Ted Kremenekb6976a22007-09-19 21:29:43 +0000416 }
417 }
418 }
419 };
420}
421
422ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
423
424
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000425//===----------------------------------------------------------------------===//
426// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
427// the CFGs for all function definitions.
428
429namespace {
430
Chris Lattner52332d02007-09-15 23:21:08 +0000431class CFGVisitor : public ASTConsumer {
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000432public:
Chris Lattner52332d02007-09-15 23:21:08 +0000433 // CFG Visitor interface to be implemented by subclass.
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000434 virtual void VisitCFG(CFG& C) = 0;
435 virtual bool printFuncDeclStart() { return true; }
Chris Lattner52332d02007-09-15 23:21:08 +0000436
437 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000438};
439
440} // end anonymous namespace
441
Chris Lattner52332d02007-09-15 23:21:08 +0000442void CFGVisitor::HandleTopLevelDecl(Decl *D) {
443 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
444 if (!FD || !FD->getBody())
445 return;
446
447 if (printFuncDeclStart()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000448 DeclPrinter().PrintFunctionDeclStart(FD);
449 llvm::cerr << '\n';
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000450 }
Chris Lattner52332d02007-09-15 23:21:08 +0000451
Ted Kremenek3e88d752007-09-17 17:10:02 +0000452 CFG *C = CFG::buildCFG(FD->getBody());
453 VisitCFG(*C);
454 delete C;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000455}
456
457//===----------------------------------------------------------------------===//
458// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
459
460namespace {
461 class CFGDumper : public CFGVisitor {
462 const bool UseGraphviz;
463 public:
464 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
465
Chris Lattner52332d02007-09-15 23:21:08 +0000466 virtual void VisitCFG(CFG &C) {
467 if (UseGraphviz)
468 C.viewCFG();
469 else
470 C.dump();
471 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000472 };
473} // end anonymous namespace
474
Chris Lattner52332d02007-09-15 23:21:08 +0000475ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
476 return new CFGDumper(ViewGraphs);
Ted Kremenek97f75312007-08-21 21:42:03 +0000477}
478
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000479//===----------------------------------------------------------------------===//
480// AnalyzeLiveVariables - perform live variable analysis and dump results
481
482namespace {
483 class LivenessVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000484 SourceManager *SM;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000485 public:
Chris Lattner52332d02007-09-15 23:21:08 +0000486 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
Ted Kremenekb3ee1932007-12-11 21:27:55 +0000487 SM = &Context.getSourceManager();
Chris Lattner52332d02007-09-15 23:21:08 +0000488 }
489
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000490 virtual void VisitCFG(CFG& C) {
Ted Kremenek8ce772b2007-10-01 20:33:52 +0000491 LiveVariables L(C);
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000492 L.runOnCFG(C);
Ted Kremenekd7a2f812007-09-25 04:31:27 +0000493 L.dumpBlockLiveness(*SM);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000494 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000495 };
496} // end anonymous namespace
497
Chris Lattner52332d02007-09-15 23:21:08 +0000498ASTConsumer *clang::CreateLiveVarAnalyzer() {
499 return new LivenessVisitor();
Ted Kremenekaa04c512007-09-06 00:17:54 +0000500}
501
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000502//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000503// DeadStores - run checker to locate dead stores in a function
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000504
505namespace {
506 class DeadStoreVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000507 Diagnostic &Diags;
508 ASTContext *Ctx;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000509 public:
Chris Lattner52332d02007-09-15 23:21:08 +0000510 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
511 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
512 Ctx = &Context;
513 }
514
515 virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000516 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000517 };
518} // end anonymous namespace
519
Chris Lattner52332d02007-09-15 23:21:08 +0000520ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
521 return new DeadStoreVisitor(Diags);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000522}
Chris Lattner129758d2007-09-16 19:46:59 +0000523
524//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000525// Unitialized Values - run checker to flag potential uses of uninitalized
526// variables.
527
528namespace {
529 class UninitValsVisitor : public CFGVisitor {
530 Diagnostic &Diags;
531 ASTContext *Ctx;
532 public:
533 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
534 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
535 Ctx = &Context;
536 }
537
538 virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
539 virtual bool printFuncDeclStart() { return false; }
540 };
541} // end anonymous namespace
542
543ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
544 return new UninitValsVisitor(Diags);
545}
546
547//===----------------------------------------------------------------------===//
Chris Lattner129758d2007-09-16 19:46:59 +0000548// LLVM Emitter
549
550#include "clang/Basic/Diagnostic.h"
Devang Patela8fccb82007-10-31 20:01:01 +0000551#include "clang/Basic/TargetInfo.h"
Chris Lattner129758d2007-09-16 19:46:59 +0000552#include "clang/CodeGen/ModuleBuilder.h"
553#include "llvm/Module.h"
Devang Patela8fccb82007-10-31 20:01:01 +0000554#include "llvm/Target/TargetData.h"
555#include "llvm/Target/TargetMachine.h"
Chris Lattner129758d2007-09-16 19:46:59 +0000556#include <iostream>
557
558namespace {
559 class LLVMEmitter : public ASTConsumer {
560 Diagnostic &Diags;
561 llvm::Module *M;
Devang Patela8fccb82007-10-31 20:01:01 +0000562 const llvm::TargetData *TD;
Chris Lattner129758d2007-09-16 19:46:59 +0000563 ASTContext *Ctx;
Chris Lattnerdb6be562007-11-28 05:34:05 +0000564 const LangOptions &Features;
Chris Lattner07f44dc2007-11-13 18:16:41 +0000565 CodeGen::CodeGenModule *Builder;
Chris Lattner129758d2007-09-16 19:46:59 +0000566 public:
Chris Lattnerdb6be562007-11-28 05:34:05 +0000567 LLVMEmitter(Diagnostic &diags, const LangOptions &LO)
568 : Diags(diags)
569 , Features(LO) {}
Chris Lattner129758d2007-09-16 19:46:59 +0000570 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
571 Ctx = &Context;
572 M = new llvm::Module("foo");
Devang Patela8fccb82007-10-31 20:01:01 +0000573 M->setTargetTriple(Ctx->Target.getTargetTriple());
574 TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
Chris Lattner22595b82007-12-02 01:40:18 +0000575 Builder = CodeGen::Init(Context, Features, *M, *TD, Diags);
Chris Lattner129758d2007-09-16 19:46:59 +0000576 }
577
578 virtual void HandleTopLevelDecl(Decl *D) {
579 // If an error occurred, stop code generation, but continue parsing and
580 // semantic analysis (to ensure all warnings and errors are emitted).
581 if (Diags.hasErrorOccurred())
582 return;
583
584 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
585 CodeGen::CodeGenFunction(Builder, FD);
586 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
587 CodeGen::CodeGenGlobalVar(Builder, FVD);
588 } else {
Steve Naroff3340c232007-11-17 21:21:01 +0000589 assert(isa<TypeDecl>(D) && "Only expected type decls here");
Chris Lattner129758d2007-09-16 19:46:59 +0000590 // don't codegen for now, eventually pass down for debug info.
591 //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n";
592 }
593 }
594
595 ~LLVMEmitter() {
596 CodeGen::Terminate(Builder);
597
598 // Print the generated code.
599 M->print(std::cout);
600 delete M;
601 }
602 };
603} // end anonymous namespace
604
Chris Lattnerdb6be562007-11-28 05:34:05 +0000605ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features) {
606 return new LLVMEmitter(Diags, Features);
Chris Lattner129758d2007-09-16 19:46:59 +0000607}
608