blob: 7a843210e582c4e0c4dd67656a1d00516a628a9c [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"
Ted Kremenekac881932007-12-18 21:34:28 +000015#include "clang/AST/TranslationUnit.h"
Ted Kremenekfc17b8a2007-12-20 00:34:58 +000016#include "clang/Basic/SourceManager.h"
17#include "clang/Basic/FileManager.h"
Chris Lattner4b009652007-07-25 00:24:17 +000018#include "clang/AST/AST.h"
Chris Lattnerb73abd52007-09-15 23:02:28 +000019#include "clang/AST/ASTConsumer.h"
Ted Kremenek97f75312007-08-21 21:42:03 +000020#include "clang/AST/CFG.h"
Ted Kremenekaa04c512007-09-06 00:17:54 +000021#include "clang/Analysis/LiveVariables.h"
Ted Kremeneke805c4a2007-09-06 23:00:42 +000022#include "clang/Analysis/LocalCheckers.h"
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000023#include "llvm/Support/Streams.h"
Ted Kremeneke09391a2007-11-27 21:46:50 +000024
Chris Lattner95578782007-08-08 22:51:59 +000025using namespace clang;
Chris Lattner4b009652007-07-25 00:24:17 +000026
Ted Kremeneke09391a2007-11-27 21:46:50 +000027//===----------------------------------------------------------------------===//
28/// DeclPrinter - Utility class for printing top-level decls.
Chris Lattner95578782007-08-08 22:51:59 +000029
Ted Kremeneke09391a2007-11-27 21:46:50 +000030namespace {
31 class DeclPrinter {
32 public:
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000033 std::ostream& Out;
Ted Kremeneke09391a2007-11-27 21:46:50 +000034
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000035 DeclPrinter(std::ostream* out) : Out(out ? *out : *llvm::cerr.stream()) {}
36 DeclPrinter() : Out(*llvm::cerr.stream()) {}
Ted Kremeneke09391a2007-11-27 21:46:50 +000037
38 void PrintFunctionDeclStart(FunctionDecl *FD);
39 void PrintTypeDefDecl(TypedefDecl *TD);
40 void PrintObjcMethodDecl(ObjcMethodDecl *OMD);
41 void PrintObjcImplementationDecl(ObjcImplementationDecl *OID);
42 void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID);
43 void PrintObjcProtocolDecl(ObjcProtocolDecl *PID);
44 void PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID);
45 void PrintObjcCategoryDecl(ObjcCategoryDecl *PID);
46 void PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID);
47 };
48} // end anonymous namespace
49
50void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
Chris Lattner4b009652007-07-25 00:24:17 +000051 bool HasBody = FD->getBody();
52
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000053 Out << '\n';
Chris Lattner987058a2007-08-26 04:02:13 +000054
55 switch (FD->getStorageClass()) {
56 default: assert(0 && "Unknown storage class");
57 case FunctionDecl::None: break;
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000058 case FunctionDecl::Extern: Out << "extern "; break;
59 case FunctionDecl::Static: Out << "static "; break;
Chris Lattner987058a2007-08-26 04:02:13 +000060 }
61
62 if (FD->isInline())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000063 Out << "inline ";
Chris Lattner987058a2007-08-26 04:02:13 +000064
Chris Lattner4b009652007-07-25 00:24:17 +000065 std::string Proto = FD->getName();
Chris Lattner934fff62007-12-03 21:43:25 +000066 const FunctionType *AFT = FD->getType()->getAsFunctionType();
Chris Lattner4b009652007-07-25 00:24:17 +000067
Chris Lattner934fff62007-12-03 21:43:25 +000068 if (const FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
Chris Lattner4b009652007-07-25 00:24:17 +000069 Proto += "(";
70 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
71 if (i) Proto += ", ";
72 std::string ParamStr;
73 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
74
75 FT->getArgType(i).getAsStringInternal(ParamStr);
76 Proto += ParamStr;
77 }
78
79 if (FT->isVariadic()) {
80 if (FD->getNumParams()) Proto += ", ";
81 Proto += "...";
82 }
83 Proto += ")";
84 } else {
85 assert(isa<FunctionTypeNoProto>(AFT));
86 Proto += "()";
87 }
88
89 AFT->getResultType().getAsStringInternal(Proto);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000090 Out << Proto;
Chris Lattner4b009652007-07-25 00:24:17 +000091
Chris Lattner95578782007-08-08 22:51:59 +000092 if (!FD->getBody())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +000093 Out << ";\n";
Chris Lattner95578782007-08-08 22:51:59 +000094 // Doesn't print the body.
Chris Lattner4b009652007-07-25 00:24:17 +000095}
96
Ted Kremeneke09391a2007-11-27 21:46:50 +000097void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
Chris Lattner4b009652007-07-25 00:24:17 +000098 std::string S = TD->getName();
99 TD->getUnderlyingType().getAsStringInternal(S);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000100 Out << "typedef " << S << ";\n";
Chris Lattner4b009652007-07-25 00:24:17 +0000101}
102
Ted Kremeneke09391a2007-11-27 21:46:50 +0000103void DeclPrinter::PrintObjcMethodDecl(ObjcMethodDecl *OMD) {
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000104 if (OMD->isInstance())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000105 Out << "\n- ";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000106 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000107 Out << "\n+ ";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000108 if (!OMD->getResultType().isNull())
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000109 Out << '(' << OMD->getResultType().getAsString() << ") ";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000110 // FIXME: just print original selector name!
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000111 Out << OMD->getSelector().getName();
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000112
113 for (int i = 0; i < OMD->getNumParams(); i++) {
114 ParmVarDecl *PDecl = OMD->getParamDecl(i);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000115 // FIXME: selector is missing here!
116 Out << " :(" << PDecl->getType().getAsString() << ") " << PDecl->getName();
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000117 }
118}
119
Ted Kremeneke09391a2007-11-27 21:46:50 +0000120void DeclPrinter::PrintObjcImplementationDecl(ObjcImplementationDecl *OID) {
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000121 std::string I = OID->getName();
122 ObjcInterfaceDecl *SID = OID->getSuperClass();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000123
124 if (SID)
125 Out << "@implementation " << I << " : " << SID->getName();
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000126 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000127 Out << "@implementation " << I;
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000128
Chris Lattnerdea5bec2007-12-12 07:46:12 +0000129 for (ObjcImplementationDecl::instmeth_iterator I = OID->instmeth_begin(),
130 E = OID->instmeth_end(); I != E; ++I) {
131 ObjcMethodDecl *OMD = *I;
132 PrintObjcMethodDecl(OMD);
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000133 if (OMD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000134 Out << ' ';
135 OMD->getBody()->printPretty(Out);
136 Out << '\n';
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000137 }
138 }
139
Chris Lattnerdea5bec2007-12-12 07:46:12 +0000140 for (ObjcImplementationDecl::classmeth_iterator I = OID->classmeth_begin(),
141 E = OID->classmeth_end(); I != E; ++I) {
142 ObjcMethodDecl *OMD = *I;
143 PrintObjcMethodDecl(OMD);
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000144 if (OMD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000145 Out << ' ';
146 OMD->getBody()->printPretty(Out);
147 Out << '\n';
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000148 }
149 }
150
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000151 Out << "@end\n";
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000152}
153
154
Ted Kremeneke09391a2007-11-27 21:46:50 +0000155void DeclPrinter::PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000156 std::string I = OID->getName();
157 ObjcInterfaceDecl *SID = OID->getSuperClass();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000158
159 if (SID)
160 Out << "@interface " << I << " : " << SID->getName();
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000161 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000162 Out << "@interface " << I;
163
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000164 // Protocols?
165 int count = OID->getNumIntfRefProtocols();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000166
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000167 if (count > 0) {
168 ObjcProtocolDecl **refProtocols = OID->getReferencedProtocols();
169 for (int i = 0; i < count; i++)
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000170 Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName();
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000171 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000172
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000173 if (count > 0)
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000174 Out << ">\n";
Fariborz Jahanianc04aff12007-10-08 23:06:41 +0000175 else
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000176 Out << '\n';
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000177
Chris Lattnerc7b06752007-12-12 07:56:42 +0000178 if (OID->getNumInstanceVariables() > 0) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000179 Out << '{';
Chris Lattnerc7b06752007-12-12 07:56:42 +0000180 for (ObjcInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
181 E = OID->ivar_end(); I != E; ++I) {
182 Out << '\t' << (*I)->getType().getAsString()
183 << ' ' << (*I)->getName() << ";\n";
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000184 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000185 Out << "}\n";
Fariborz Jahanianf468b312007-10-26 16:29:12 +0000186 }
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000187
188 int NumProperties = OID->getNumPropertyDecl();
189 if (NumProperties > 0) {
190 for (int i = 0; i < NumProperties; i++) {
191 ObjcPropertyDecl *PDecl = OID->getPropertyDecl()[i];
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000192 Out << "@property";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000193 if (PDecl->getPropertyAttributes() != ObjcPropertyDecl::OBJC_PR_noattr) {
194 bool first = true;
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000195 Out << " (";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000196 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readonly)
197 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000198 Out << (first ? ' ' : ',') << "readonly";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000199 first = false;
200 }
201
202 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_getter)
203 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000204 Out << (first ? ' ' : ',') << "getter = "
205 << PDecl->getGetterName()->getName();
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000206 first = false;
207 }
208 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_setter)
209 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000210 Out << (first ? ' ' : ',') << "setter = "
211 << PDecl->getSetterName()->getName();
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000212 first = false;
213 }
214
215 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_assign)
216 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000217 Out << (first ? ' ' : ',') << "assign";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000218 first = false;
219 }
220
221 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readwrite)
222 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000223 Out << (first ? ' ' : ',') << "readwrite";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000224 first = false;
225 }
226
227 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_retain)
228 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000229 Out << (first ? ' ' : ',') << "retain";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000230 first = false;
231 }
232
233 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_copy)
234 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000235 Out << (first ? ' ' : ',') << "copy";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000236 first = false;
237 }
238
239 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_nonatomic)
240 {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000241 Out << (first ? ' ' : ',') << "nonatomic";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000242 first = false;
243 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000244 Out << " )";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000245 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000246
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000247 ObjcIvarDecl **IDecl = PDecl->getPropertyDecls();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000248
249 Out << ' ' << IDecl[0]->getType().getAsString()
250 << ' ' << IDecl[0]->getName();
251
252 for (int j = 1; j < PDecl->getNumPropertyDecls(); j++)
253 Out << ", " << IDecl[j]->getName();
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000254
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000255 Out << ";\n";
Fariborz Jahaniand8df6d82007-11-06 22:01:00 +0000256 }
257 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000258
259 Out << "@end\n";
Steve Narofffaed3bf2007-09-10 20:51:04 +0000260 // FIXME: implement the rest...
261}
262
Ted Kremeneke09391a2007-11-27 21:46:50 +0000263void DeclPrinter::PrintObjcProtocolDecl(ObjcProtocolDecl *PID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000264 Out << "@protocol " << PID->getName() << '\n';
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000265 // FIXME: implement the rest...
266}
267
Ted Kremeneke09391a2007-11-27 21:46:50 +0000268void DeclPrinter::PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000269 Out << "@implementation "
270 << PID->getClassInterface()->getName()
271 << '(' << PID->getName() << ");\n";
272
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000273 // FIXME: implement the rest...
274}
275
Ted Kremeneke09391a2007-11-27 21:46:50 +0000276void DeclPrinter::PrintObjcCategoryDecl(ObjcCategoryDecl *PID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000277 Out << "@interface "
278 << PID->getClassInterface()->getName()
279 << '(' << PID->getName() << ");\n";
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000280 // FIXME: implement the rest...
281}
282
Ted Kremeneke09391a2007-11-27 21:46:50 +0000283void DeclPrinter::PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000284 Out << "@compatibility_alias " << AID->getName()
285 << ' ' << AID->getClassInterface()->getName() << ";\n";
Fariborz Jahanian05d212a2007-10-11 23:42:27 +0000286}
287
Ted Kremeneke09391a2007-11-27 21:46:50 +0000288//===----------------------------------------------------------------------===//
289/// ASTPrinter - Pretty-printer of ASTs
290
Chris Lattnerb73abd52007-09-15 23:02:28 +0000291namespace {
Ted Kremeneke09391a2007-11-27 21:46:50 +0000292 class ASTPrinter : public ASTConsumer, public DeclPrinter {
293 public:
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000294 ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}
Ted Kremeneke09391a2007-11-27 21:46:50 +0000295
Chris Lattnerb73abd52007-09-15 23:02:28 +0000296 virtual void HandleTopLevelDecl(Decl *D) {
297 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
298 PrintFunctionDeclStart(FD);
299
300 if (FD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000301 Out << ' ';
302 FD->getBody()->printPretty(Out);
303 Out << '\n';
Chris Lattnerb73abd52007-09-15 23:02:28 +0000304 }
Steve Naroff3a3a0cb2007-11-13 23:48:03 +0000305 } else if (isa<ObjcMethodDecl>(D)) {
306 // Do nothing, methods definitions are printed in
307 // PrintObjcImplementationDecl.
Chris Lattnerb73abd52007-09-15 23:02:28 +0000308 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
309 PrintTypeDefDecl(TD);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000310 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
311 PrintObjcInterfaceDecl(OID);
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000312 } else if (ObjcProtocolDecl *PID = dyn_cast<ObjcProtocolDecl>(D)) {
313 PrintObjcProtocolDecl(PID);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000314 } else if (ObjcForwardProtocolDecl *OFPD =
315 dyn_cast<ObjcForwardProtocolDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000316 Out << "@protocol ";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000317 for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
318 const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000319 if (i) Out << ", ";
320 Out << D->getName();
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000321 }
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000322 Out << ";\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000323 } else if (ObjcImplementationDecl *OID =
324 dyn_cast<ObjcImplementationDecl>(D)) {
Fariborz Jahanian83ddf822007-11-10 20:59:13 +0000325 PrintObjcImplementationDecl(OID);
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000326 } else if (ObjcCategoryImplDecl *OID =
327 dyn_cast<ObjcCategoryImplDecl>(D)) {
328 PrintObjcCategoryImplDecl(OID);
329 } else if (ObjcCategoryDecl *OID =
330 dyn_cast<ObjcCategoryDecl>(D)) {
331 PrintObjcCategoryDecl(OID);
Fariborz Jahanian05d212a2007-10-11 23:42:27 +0000332 } else if (ObjcCompatibleAliasDecl *OID =
333 dyn_cast<ObjcCompatibleAliasDecl>(D)) {
334 PrintObjcCompatibleAliasDecl(OID);
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000335 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000336 Out << "@class [printing todo]\n";
Steve Naroff6fd865b2007-11-28 22:54:11 +0000337 } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
338 Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
Fariborz Jahanianac20be22007-10-08 18:53:38 +0000339 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000340 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000341 } else {
342 assert(0 && "Unknown decl type!");
Chris Lattner95578782007-08-08 22:51:59 +0000343 }
Chris Lattner4b009652007-07-25 00:24:17 +0000344 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000345 };
Chris Lattner4b009652007-07-25 00:24:17 +0000346}
Chris Lattner95578782007-08-08 22:51:59 +0000347
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000348ASTConsumer *clang::CreateASTPrinter(std::ostream* out) {
349 return new ASTPrinter(out);
350}
Ted Kremeneke09391a2007-11-27 21:46:50 +0000351
352//===----------------------------------------------------------------------===//
353/// ASTDumper - Low-level dumper of ASTs
Chris Lattnerb73abd52007-09-15 23:02:28 +0000354
355namespace {
Ted Kremeneke09391a2007-11-27 21:46:50 +0000356 class ASTDumper : public ASTConsumer, public DeclPrinter {
Chris Lattnerb73abd52007-09-15 23:02:28 +0000357 SourceManager *SM;
358 public:
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000359 ASTDumper() : DeclPrinter() {}
Ted Kremeneke09391a2007-11-27 21:46:50 +0000360
Ted Kremenek17861c52007-12-19 22:51:13 +0000361 void Initialize(ASTContext &Context) {
Ted Kremenekb3ee1932007-12-11 21:27:55 +0000362 SM = &Context.getSourceManager();
Chris Lattner95578782007-08-08 22:51:59 +0000363 }
Chris Lattnerb73abd52007-09-15 23:02:28 +0000364
365 virtual void HandleTopLevelDecl(Decl *D) {
366 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
367 PrintFunctionDeclStart(FD);
368
369 if (FD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000370 Out << '\n';
371 // FIXME: convert dumper to use std::ostream?
Chris Lattnerb73abd52007-09-15 23:02:28 +0000372 FD->getBody()->dumpAll(*SM);
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000373 Out << '\n';
Chris Lattnerb73abd52007-09-15 23:02:28 +0000374 }
375 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
376 PrintTypeDefDecl(TD);
377 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000378 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000379 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000380 Out << "Read objc interface '" << OID->getName() << "'\n";
Steve Naroffd5d18732007-10-14 17:03:01 +0000381 } else if (ObjcProtocolDecl *OPD = dyn_cast<ObjcProtocolDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000382 Out << "Read objc protocol '" << OPD->getName() << "'\n";
Steve Naroffd5d18732007-10-14 17:03:01 +0000383 } else if (ObjcCategoryDecl *OCD = dyn_cast<ObjcCategoryDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000384 Out << "Read objc category '" << OCD->getName() << "'\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000385 } else if (isa<ObjcForwardProtocolDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000386 Out << "Read objc fwd protocol decl\n";
Steve Naroffd5d18732007-10-14 17:03:01 +0000387 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000388 Out << "Read objc fwd class decl\n";
Chris Lattnerd5c9d3d2007-10-06 18:52:10 +0000389 } else {
390 assert(0 && "Unknown decl type!");
Chris Lattnerb73abd52007-09-15 23:02:28 +0000391 }
392 }
393 };
Chris Lattner95578782007-08-08 22:51:59 +0000394}
395
Chris Lattnerb73abd52007-09-15 23:02:28 +0000396ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
397
Ted Kremeneke09391a2007-11-27 21:46:50 +0000398//===----------------------------------------------------------------------===//
399/// ASTViewer - AST Visualization
400
Ted Kremenekb6976a22007-09-19 21:29:43 +0000401namespace {
402 class ASTViewer : public ASTConsumer {
403 SourceManager *SM;
404 public:
Ted Kremenek17861c52007-12-19 22:51:13 +0000405 void Initialize(ASTContext &Context) {
Ted Kremenekb3ee1932007-12-11 21:27:55 +0000406 SM = &Context.getSourceManager();
Ted Kremenekb6976a22007-09-19 21:29:43 +0000407 }
408
409 virtual void HandleTopLevelDecl(Decl *D) {
410 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000411 DeclPrinter().PrintFunctionDeclStart(FD);
Ted Kremenekb6976a22007-09-19 21:29:43 +0000412
413 if (FD->getBody()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000414 llvm::cerr << '\n';
Ted Kremenekb6976a22007-09-19 21:29:43 +0000415 FD->getBody()->viewAST();
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000416 llvm::cerr << '\n';
Ted Kremenekb6976a22007-09-19 21:29:43 +0000417 }
418 }
419 }
420 };
421}
422
423ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
424
425
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000426//===----------------------------------------------------------------------===//
427// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
428// the CFGs for all function definitions.
429
430namespace {
431
Chris Lattner52332d02007-09-15 23:21:08 +0000432class CFGVisitor : public ASTConsumer {
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000433public:
Chris Lattner52332d02007-09-15 23:21:08 +0000434 // CFG Visitor interface to be implemented by subclass.
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000435 virtual void VisitCFG(CFG& C) = 0;
436 virtual bool printFuncDeclStart() { return true; }
Chris Lattner52332d02007-09-15 23:21:08 +0000437
438 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000439};
440
441} // end anonymous namespace
442
Chris Lattner52332d02007-09-15 23:21:08 +0000443void CFGVisitor::HandleTopLevelDecl(Decl *D) {
444 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
445 if (!FD || !FD->getBody())
446 return;
447
448 if (printFuncDeclStart()) {
Ted Kremenekbe2ea3b2007-11-28 21:32:21 +0000449 DeclPrinter().PrintFunctionDeclStart(FD);
450 llvm::cerr << '\n';
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000451 }
Chris Lattner52332d02007-09-15 23:21:08 +0000452
Ted Kremenek3e88d752007-09-17 17:10:02 +0000453 CFG *C = CFG::buildCFG(FD->getBody());
454 VisitCFG(*C);
455 delete C;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000456}
457
458//===----------------------------------------------------------------------===//
459// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
460
461namespace {
462 class CFGDumper : public CFGVisitor {
463 const bool UseGraphviz;
464 public:
465 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
466
Chris Lattner52332d02007-09-15 23:21:08 +0000467 virtual void VisitCFG(CFG &C) {
468 if (UseGraphviz)
469 C.viewCFG();
470 else
471 C.dump();
472 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000473 };
474} // end anonymous namespace
475
Chris Lattner52332d02007-09-15 23:21:08 +0000476ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
477 return new CFGDumper(ViewGraphs);
Ted Kremenek97f75312007-08-21 21:42:03 +0000478}
479
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000480//===----------------------------------------------------------------------===//
481// AnalyzeLiveVariables - perform live variable analysis and dump results
482
483namespace {
484 class LivenessVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000485 SourceManager *SM;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000486 public:
Ted Kremenek17861c52007-12-19 22:51:13 +0000487 virtual void Initialize(ASTContext &Context) {
Ted Kremenekb3ee1932007-12-11 21:27:55 +0000488 SM = &Context.getSourceManager();
Chris Lattner52332d02007-09-15 23:21:08 +0000489 }
490
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000491 virtual void VisitCFG(CFG& C) {
Ted Kremenek8ce772b2007-10-01 20:33:52 +0000492 LiveVariables L(C);
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000493 L.runOnCFG(C);
Ted Kremenekd7a2f812007-09-25 04:31:27 +0000494 L.dumpBlockLiveness(*SM);
Ted Kremenekaa04c512007-09-06 00:17:54 +0000495 }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000496 };
497} // end anonymous namespace
498
Chris Lattner52332d02007-09-15 23:21:08 +0000499ASTConsumer *clang::CreateLiveVarAnalyzer() {
500 return new LivenessVisitor();
Ted Kremenekaa04c512007-09-06 00:17:54 +0000501}
502
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000503//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000504// DeadStores - run checker to locate dead stores in a function
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000505
506namespace {
507 class DeadStoreVisitor : public CFGVisitor {
Chris Lattner52332d02007-09-15 23:21:08 +0000508 Diagnostic &Diags;
509 ASTContext *Ctx;
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000510 public:
Chris Lattner52332d02007-09-15 23:21:08 +0000511 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
Ted Kremenek17861c52007-12-19 22:51:13 +0000512 virtual void Initialize(ASTContext &Context) {
Chris Lattner52332d02007-09-15 23:21:08 +0000513 Ctx = &Context;
514 }
515
516 virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
Ted Kremenek39b8c4b2007-09-07 23:54:15 +0000517 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek1e3c2022007-09-07 23:47:56 +0000518 };
519} // end anonymous namespace
520
Chris Lattner52332d02007-09-15 23:21:08 +0000521ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
522 return new DeadStoreVisitor(Diags);
Ted Kremeneke805c4a2007-09-06 23:00:42 +0000523}
Chris Lattner129758d2007-09-16 19:46:59 +0000524
525//===----------------------------------------------------------------------===//
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000526// Unitialized Values - run checker to flag potential uses of uninitalized
527// variables.
528
529namespace {
530 class UninitValsVisitor : public CFGVisitor {
531 Diagnostic &Diags;
532 ASTContext *Ctx;
533 public:
534 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
Ted Kremenek17861c52007-12-19 22:51:13 +0000535 virtual void Initialize(ASTContext &Context) {
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000536 Ctx = &Context;
537 }
538
539 virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
540 virtual bool printFuncDeclStart() { return false; }
541 };
542} // end anonymous namespace
543
544ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
545 return new UninitValsVisitor(Diags);
546}
547
548//===----------------------------------------------------------------------===//
Chris Lattner129758d2007-09-16 19:46:59 +0000549// LLVM Emitter
550
551#include "clang/Basic/Diagnostic.h"
Devang Patela8fccb82007-10-31 20:01:01 +0000552#include "clang/Basic/TargetInfo.h"
Chris Lattner129758d2007-09-16 19:46:59 +0000553#include "clang/CodeGen/ModuleBuilder.h"
554#include "llvm/Module.h"
Devang Patela8fccb82007-10-31 20:01:01 +0000555#include "llvm/Target/TargetData.h"
556#include "llvm/Target/TargetMachine.h"
Chris Lattner129758d2007-09-16 19:46:59 +0000557
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) {}
Ted Kremenek17861c52007-12-19 22:51:13 +0000570 virtual void Initialize(ASTContext &Context) {
Chris Lattner129758d2007-09-16 19:46:59 +0000571 Ctx = &Context;
572 M = new llvm::Module("foo");
Devang Patela8fccb82007-10-31 20:01:01 +0000573 M->setTargetTriple(Ctx->Target.getTargetTriple());
Chris Lattner9efc5012007-12-13 17:34:31 +0000574 M->setDataLayout(Ctx->Target.getTargetDescription());
Devang Patela8fccb82007-10-31 20:01:01 +0000575 TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
Chris Lattner22595b82007-12-02 01:40:18 +0000576 Builder = CodeGen::Init(Context, Features, *M, *TD, Diags);
Chris Lattner129758d2007-09-16 19:46:59 +0000577 }
578
579 virtual void HandleTopLevelDecl(Decl *D) {
580 // If an error occurred, stop code generation, but continue parsing and
581 // semantic analysis (to ensure all warnings and errors are emitted).
582 if (Diags.hasErrorOccurred())
583 return;
584
585 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
586 CodeGen::CodeGenFunction(Builder, FD);
587 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
588 CodeGen::CodeGenGlobalVar(Builder, FVD);
589 } else {
Steve Naroff3340c232007-11-17 21:21:01 +0000590 assert(isa<TypeDecl>(D) && "Only expected type decls here");
Chris Lattner129758d2007-09-16 19:46:59 +0000591 // don't codegen for now, eventually pass down for debug info.
Ted Kremenek21189012007-12-19 23:49:37 +0000592 //std::cerr << "Read top-level typedef decl: '"
593 // << D->getName() << "'\n";
Chris Lattner129758d2007-09-16 19:46:59 +0000594 }
595 }
596
597 ~LLVMEmitter() {
598 CodeGen::Terminate(Builder);
599
600 // Print the generated code.
Ted Kremenek8df2a4d2007-12-13 17:50:11 +0000601 M->print(llvm::cout.stream());
Chris Lattner129758d2007-09-16 19:46:59 +0000602 delete M;
603 }
604 };
605} // end anonymous namespace
606
Ted Kremenek21189012007-12-19 23:49:37 +0000607ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags,
608 const LangOptions &Features) {
Chris Lattnerdb6be562007-11-28 05:34:05 +0000609 return new LLVMEmitter(Diags, Features);
Chris Lattner129758d2007-09-16 19:46:59 +0000610}
611
Ted Kremenek397de012007-12-13 00:37:31 +0000612//===----------------------------------------------------------------------===//
613// AST Serializer
614
615namespace {
Ted Kremenek21189012007-12-19 23:49:37 +0000616
617class ASTSerializer : public ASTConsumer {
618protected:
619 Diagnostic &Diags;
620 TranslationUnit TU;
621public:
622 ASTSerializer(Diagnostic& diags, const LangOptions& LO)
623 : Diags(diags), TU(LO) {}
624
625 virtual void Initialize(ASTContext &Context) {
626 TU.setContext(&Context);
627 }
628
629 virtual void HandleTopLevelDecl(Decl *D) {
630 if (Diags.hasErrorOccurred())
631 return;
632
633 TU.AddTopLevelDecl(D);
634 }
635};
636
637class SingleFileSerializer : public ASTSerializer {
638 const llvm::sys::Path FName;
639public:
640 SingleFileSerializer(const llvm::sys::Path& F, Diagnostic &diags,
641 const LangOptions &LO)
642 : ASTSerializer(diags,LO), FName(F) {}
643
644 ~SingleFileSerializer() {
645 EmitASTBitcodeFile(TU,FName);
646 }
647};
648
649class BuildSerializer : public ASTSerializer {
650 llvm::sys::Path EmitDir;
651public:
652 BuildSerializer(const llvm::sys::Path& dir, Diagnostic &diags,
Ted Kremenek397de012007-12-13 00:37:31 +0000653 const LangOptions &LO)
Ted Kremenek21189012007-12-19 23:49:37 +0000654 : ASTSerializer(diags,LO), EmitDir(dir) {}
655
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000656 ~BuildSerializer() {
657 SourceManager& SourceMgr = TU.getASTContext()->getSourceManager();
658 unsigned ID = SourceMgr.getMainFileID();
659 assert (ID && "MainFileID not set!");
660 const FileEntry* FE = SourceMgr.getFileEntryForID(ID);
661 assert (FE && "No FileEntry for main file.");
662
663 // FIXME: This is not portable to Windows.
664 // FIXME: This logic should probably be moved elsewhere later.
665
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000666 llvm::sys::Path FName(EmitDir);
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000667
668 std::vector<char> buf;
669 buf.reserve(strlen(FE->getName())+100);
670
671 sprintf(&buf[0], "dev_%llx", (uint64_t) FE->getDevice());
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000672 FName.appendComponent(&buf[0]);
673 FName.createDirectoryOnDisk(true);
674 if (!FName.canWrite() || !FName.isDirectory()) {
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000675 assert (false && "Could not create 'device' serialization directory.");
676 return;
677 }
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000678
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000679 sprintf(&buf[0], "%s-%llX.ast", FE->getName(), (uint64_t) FE->getInode());
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000680 FName.appendComponent(&buf[0]);
681 EmitASTBitcodeFile(TU,FName);
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000682
Ted Kremenek0c7cd7a2007-12-20 19:47:16 +0000683 // Now emit the sources.
684
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000685 }
Ted Kremenek21189012007-12-19 23:49:37 +0000686};
687
688
Ted Kremenek397de012007-12-13 00:37:31 +0000689} // end anonymous namespace
690
691
Ted Kremenekd890f6a2007-12-19 22:24:34 +0000692ASTConsumer* clang::CreateASTSerializer(const std::string& InFile,
Ted Kremenek21189012007-12-19 23:49:37 +0000693 const std::string& OutputFile,
Ted Kremenek397de012007-12-13 00:37:31 +0000694 Diagnostic &Diags,
695 const LangOptions &Features) {
Ted Kremenekbde30332007-12-19 17:25:59 +0000696
Ted Kremenek21189012007-12-19 23:49:37 +0000697 if (OutputFile.size()) {
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000698 if (InFile == "-") {
699 llvm::cerr <<
700 "error: Cannot use --serialize with -o for source read from STDIN.\n";
701 return NULL;
702 }
703
Ted Kremenek21189012007-12-19 23:49:37 +0000704 // The user specified an AST-emission directory. Determine if the path
705 // is absolute.
706 llvm::sys::Path EmitDir(OutputFile);
707
708 if (!EmitDir.isAbsolute()) {
709 llvm::cerr <<
710 "error: Output directory for --serialize must be an absolute path.\n";
711
712 return NULL;
713 }
714
715 // Create the directory if it does not exist.
716 EmitDir.createDirectoryOnDisk(true);
717 if (!EmitDir.canWrite() || !EmitDir.isDirectory()) {
718 llvm::cerr <<
719 "error: Could not create output directory for --serialize.\n";
720
721 return NULL;
722 }
723
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000724 // FIXME: We should probably only allow using BuildSerializer when
725 // the ASTs come from parsed source files, and not from .ast files.
Ted Kremenek21189012007-12-19 23:49:37 +0000726 return new BuildSerializer(EmitDir, Diags, Features);
727 }
728
729 // The user did not specify an output directory for serialized ASTs.
730 // Serialize the translation to a single file whose name is the same
731 // as the input file with the ".ast" extension appended.
Ted Kremenekab749372007-12-19 19:27:38 +0000732
Ted Kremenek21189012007-12-19 23:49:37 +0000733 llvm::sys::Path FName(InFile.c_str());
Ted Kremenekfc17b8a2007-12-20 00:34:58 +0000734 FName.appendSuffix("ast");
Ted Kremenek21189012007-12-19 23:49:37 +0000735 return new SingleFileSerializer(FName, Diags, Features);
Ted Kremenek397de012007-12-13 00:37:31 +0000736}