blob: bcf54f95bf850ff072eb82cab18bd2dd753e4a52 [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 Lattner97e8b6f2007-10-07 06:04:32 +00005// This file was developed by Chris Lattner and is distributed under the
Reid Spencer5f016e22007-07-11 17:01:13 +00006// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner97e8b6f2007-10-07 06:04:32 +000010// AST Consumer Implementations.
Reid Spencer5f016e22007-07-11 17:01:13 +000011//
12//===----------------------------------------------------------------------===//
13
Chris Lattner97e8b6f2007-10-07 06:04:32 +000014#include "ASTConsumers.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000015#include "clang/AST/AST.h"
Chris Lattner3d4997d2007-09-15 23:02:28 +000016#include "clang/AST/ASTConsumer.h"
Ted Kremenekfddd5182007-08-21 21:42:03 +000017#include "clang/AST/CFG.h"
Ted Kremeneke4e63342007-09-06 00:17:54 +000018#include "clang/Analysis/LiveVariables.h"
Ted Kremenek055c2752007-09-06 23:00:42 +000019#include "clang/Analysis/LocalCheckers.h"
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000020
Chris Lattner6000dac2007-08-08 22:51:59 +000021using namespace clang;
Reid Spencer5f016e22007-07-11 17:01:13 +000022
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000023//===----------------------------------------------------------------------===//
24/// DeclPrinter - Utility class for printing top-level decls.
Chris Lattner6000dac2007-08-08 22:51:59 +000025
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000026namespace {
27 class DeclPrinter {
28 public:
29 FILE* FP;
30
31 DeclPrinter(FILE* fp) : FP(fp ? fp : stderr) {}
32
33 void PrintFunctionDeclStart(FunctionDecl *FD);
34 void PrintTypeDefDecl(TypedefDecl *TD);
35 void PrintObjcMethodDecl(ObjcMethodDecl *OMD);
36 void PrintObjcImplementationDecl(ObjcImplementationDecl *OID);
37 void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID);
38 void PrintObjcProtocolDecl(ObjcProtocolDecl *PID);
39 void PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID);
40 void PrintObjcCategoryDecl(ObjcCategoryDecl *PID);
41 void PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID);
42 };
43} // end anonymous namespace
44
45void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
Reid Spencer5f016e22007-07-11 17:01:13 +000046 bool HasBody = FD->getBody();
47
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000048 fprintf(FP, "\n");
Chris Lattner70c8b2e2007-08-26 04:02:13 +000049
50 switch (FD->getStorageClass()) {
51 default: assert(0 && "Unknown storage class");
52 case FunctionDecl::None: break;
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000053 case FunctionDecl::Extern: fprintf(FP, "extern "); break;
54 case FunctionDecl::Static: fprintf(FP, "static "); break;
Chris Lattner70c8b2e2007-08-26 04:02:13 +000055 }
56
57 if (FD->isInline())
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000058 fprintf(FP, "inline ");
Chris Lattner70c8b2e2007-08-26 04:02:13 +000059
Reid Spencer5f016e22007-07-11 17:01:13 +000060 std::string Proto = FD->getName();
61 FunctionType *AFT = cast<FunctionType>(FD->getType());
62
63 if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
64 Proto += "(";
65 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
66 if (i) Proto += ", ";
67 std::string ParamStr;
68 if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
69
70 FT->getArgType(i).getAsStringInternal(ParamStr);
71 Proto += ParamStr;
72 }
73
74 if (FT->isVariadic()) {
75 if (FD->getNumParams()) Proto += ", ";
76 Proto += "...";
77 }
78 Proto += ")";
79 } else {
80 assert(isa<FunctionTypeNoProto>(AFT));
81 Proto += "()";
82 }
83
84 AFT->getResultType().getAsStringInternal(Proto);
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000085 fprintf(FP, "%s", Proto.c_str());
Reid Spencer5f016e22007-07-11 17:01:13 +000086
Chris Lattner6000dac2007-08-08 22:51:59 +000087 if (!FD->getBody())
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000088 fprintf(FP, ";\n");
Chris Lattner6000dac2007-08-08 22:51:59 +000089 // Doesn't print the body.
Reid Spencer5f016e22007-07-11 17:01:13 +000090}
91
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000092void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
Reid Spencer5f016e22007-07-11 17:01:13 +000093 std::string S = TD->getName();
94 TD->getUnderlyingType().getAsStringInternal(S);
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000095 fprintf(FP, "typedef %s;\n", S.c_str());
Reid Spencer5f016e22007-07-11 17:01:13 +000096}
97
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000098void DeclPrinter::PrintObjcMethodDecl(ObjcMethodDecl *OMD) {
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +000099 if (OMD->isInstance())
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000100 fprintf(FP, "\n- ");
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000101 else
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000102 fprintf(FP, "\n+ ");
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000103 if (!OMD->getResultType().isNull())
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000104 fprintf(FP, "(%s) ", OMD->getResultType().getAsString().c_str());
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000105 // FIXME: just print original selector name!
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000106 fprintf(FP, "%s ", OMD->getSelector().getName().c_str());
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000107
108 for (int i = 0; i < OMD->getNumParams(); i++) {
109 ParmVarDecl *PDecl = OMD->getParamDecl(i);
110 // FIXME: selector is missing here!
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000111 fprintf(FP, " :(%s) %s", PDecl->getType().getAsString().c_str(),
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000112 PDecl->getName());
113 }
114}
115
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000116void DeclPrinter::PrintObjcImplementationDecl(ObjcImplementationDecl *OID) {
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000117 std::string I = OID->getName();
118 ObjcInterfaceDecl *SID = OID->getSuperClass();
119 if (SID) {
120 std::string S = SID->getName();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000121 fprintf(FP, "@implementation %s : %s", I.c_str(), S.c_str());
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000122 }
123 else
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000124 fprintf(FP, "@implementation %s", I.c_str());
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000125
126 for (int i = 0; i < OID->getNumInstanceMethods(); i++) {
127 PrintObjcMethodDecl(OID->getInstanceMethods()[i]);
128 ObjcMethodDecl *OMD = OID->getInstanceMethods()[i];
129 if (OMD->getBody()) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000130 fprintf(FP, " ");
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000131 OMD->getBody()->dumpPretty();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000132 fprintf(FP, "\n");
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000133 }
134 }
135
136 for (int i = 0; i < OID->getNumClassMethods(); i++) {
137 PrintObjcMethodDecl(OID->getClassMethods()[i]);
138 ObjcMethodDecl *OMD = OID->getClassMethods()[i];
139 if (OMD->getBody()) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000140 fprintf(FP, " ");
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000141 OMD->getBody()->dumpPretty();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000142 fprintf(FP, "\n");
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000143 }
144 }
145
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000146 fprintf(FP,"@end\n");
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000147}
148
149
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000150void DeclPrinter::PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000151 std::string I = OID->getName();
152 ObjcInterfaceDecl *SID = OID->getSuperClass();
153 if (SID) {
154 std::string S = SID->getName();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000155 fprintf(FP, "@interface %s : %s", I.c_str(), S.c_str());
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000156 }
157 else
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000158 fprintf(FP, "@interface %s", I.c_str());
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000159 // Protocols?
160 int count = OID->getNumIntfRefProtocols();
161 if (count > 0) {
162 ObjcProtocolDecl **refProtocols = OID->getReferencedProtocols();
163 for (int i = 0; i < count; i++)
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000164 fprintf(FP, "%c%s", (i == 0 ? '<' : ','),
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000165 refProtocols[i]->getName());
166 }
167 if (count > 0)
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000168 fprintf(FP, ">\n");
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000169 else
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000170 fprintf(FP, "\n");
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000171
Steve Naroff03300712007-11-12 13:56:41 +0000172 int NumIvars = OID->getNumInstanceVariables();
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000173 if (NumIvars > 0) {
Steve Naroff03300712007-11-12 13:56:41 +0000174 ObjcIvarDecl **Ivars = OID->getInstanceVariables();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000175 fprintf(FP,"{");
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000176 for (int i = 0; i < NumIvars; i++) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000177 fprintf(FP, "\t%s %s;\n", Ivars[i]->getType().getAsString().c_str(),
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000178 Ivars[i]->getName());
179 }
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000180 fprintf(FP, "}\n");
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000181 }
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000182
183 int NumProperties = OID->getNumPropertyDecl();
184 if (NumProperties > 0) {
185 for (int i = 0; i < NumProperties; i++) {
186 ObjcPropertyDecl *PDecl = OID->getPropertyDecl()[i];
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000187 fprintf(FP, "@property");
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000188 if (PDecl->getPropertyAttributes() != ObjcPropertyDecl::OBJC_PR_noattr) {
189 bool first = true;
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000190 fprintf(FP, " (");
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000191 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readonly)
192 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000193 fprintf(FP, "%creadonly", first ? ' ' : ',');
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000194 first = false;
195 }
196
197 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_getter)
198 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000199 fprintf(FP, "%cgetter = %s", first ? ' ' : ','
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000200 , PDecl->getGetterName()->getName());
201 first = false;
202 }
203 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_setter)
204 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000205 fprintf(FP, "%csetter = %s:", first ? ' ' : ','
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000206 , PDecl->getSetterName()->getName());
207 first = false;
208 }
209
210 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_assign)
211 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000212 fprintf(FP, "%cassign", first ? ' ' : ',');
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000213 first = false;
214 }
215
216 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readwrite)
217 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000218 fprintf(FP, "%creadwrite", first ? ' ' : ',');
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000219 first = false;
220 }
221
222 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_retain)
223 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000224 fprintf(FP, "%cretain", first ? ' ' : ',');
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000225 first = false;
226 }
227
228 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_copy)
229 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000230 fprintf(FP, "%ccopy", first ? ' ' : ',');
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000231 first = false;
232 }
233
234 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_nonatomic)
235 {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000236 fprintf(FP, "%cnonatomic", first ? ' ' : ',');
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000237 first = false;
238 }
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000239 fprintf(FP, " )");
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000240 }
241 ObjcIvarDecl **IDecl = PDecl->getPropertyDecls();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000242 fprintf(FP, " %s %s", IDecl[0]->getType().getAsString().c_str(),
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000243 IDecl[0]->getName());
244
245 for (int j = 1; j < PDecl->getNumPropertyDecls(); j++) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000246 fprintf(FP, ", %s", IDecl[j]->getName());
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000247 }
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000248 fprintf(FP, ";\n");
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000249 }
250 }
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000251 fprintf(FP,"@end\n");
Steve Naroff2bd42fa2007-09-10 20:51:04 +0000252 // FIXME: implement the rest...
253}
254
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000255void DeclPrinter::PrintObjcProtocolDecl(ObjcProtocolDecl *PID) {
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000256 std::string S = PID->getName();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000257 fprintf(FP, "@protocol %s;\n", S.c_str());
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000258 // FIXME: implement the rest...
259}
260
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000261void DeclPrinter::PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID) {
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000262 std::string S = PID->getName();
263 std::string I = PID->getClassInterface()->getName();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000264 fprintf(FP, "@implementation %s(%s);\n", I.c_str(), S.c_str());
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000265 // FIXME: implement the rest...
266}
267
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000268void DeclPrinter::PrintObjcCategoryDecl(ObjcCategoryDecl *PID) {
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000269 std::string S = PID->getName();
270 std::string I = PID->getClassInterface()->getName();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000271 fprintf(FP, "@interface %s(%s);\n", I.c_str(), S.c_str());
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000272 // FIXME: implement the rest...
273}
274
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000275void DeclPrinter::PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID) {
Fariborz Jahanian243b64b2007-10-11 23:42:27 +0000276 std::string A = AID->getName();
277 std::string I = AID->getClassInterface()->getName();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000278 fprintf(FP, "@compatibility_alias %s %s;\n", A.c_str(), I.c_str());
Fariborz Jahanian243b64b2007-10-11 23:42:27 +0000279}
280
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000281//===----------------------------------------------------------------------===//
282/// ASTPrinter - Pretty-printer of ASTs
283
Chris Lattner3d4997d2007-09-15 23:02:28 +0000284namespace {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000285 class ASTPrinter : public ASTConsumer, public DeclPrinter {
286 public:
287 ASTPrinter(FILE* F = NULL) : DeclPrinter(F) {}
288
Chris Lattner3d4997d2007-09-15 23:02:28 +0000289 virtual void HandleTopLevelDecl(Decl *D) {
290 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
291 PrintFunctionDeclStart(FD);
292
293 if (FD->getBody()) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000294 fprintf(FP, " ");
Chris Lattner3d4997d2007-09-15 23:02:28 +0000295 FD->getBody()->dumpPretty();
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000296 fprintf(FP, "\n");
Chris Lattner3d4997d2007-09-15 23:02:28 +0000297 }
Steve Naroffaaa3cf82007-11-13 23:48:03 +0000298 } else if (isa<ObjcMethodDecl>(D)) {
299 // Do nothing, methods definitions are printed in
300 // PrintObjcImplementationDecl.
Chris Lattner3d4997d2007-09-15 23:02:28 +0000301 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
302 PrintTypeDefDecl(TD);
Chris Lattner9fa5e652007-10-06 18:52:10 +0000303 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
304 PrintObjcInterfaceDecl(OID);
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000305 } else if (ObjcProtocolDecl *PID = dyn_cast<ObjcProtocolDecl>(D)) {
306 PrintObjcProtocolDecl(PID);
Chris Lattner9fa5e652007-10-06 18:52:10 +0000307 } else if (ObjcForwardProtocolDecl *OFPD =
308 dyn_cast<ObjcForwardProtocolDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000309 fprintf(FP, "@protocol ");
Chris Lattner9fa5e652007-10-06 18:52:10 +0000310 for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
311 const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000312 if (i) fprintf(FP, ", ");
313 fprintf(FP, "%s", D->getName());
Chris Lattner9fa5e652007-10-06 18:52:10 +0000314 }
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000315 fprintf(FP, ";\n");
Chris Lattner9fa5e652007-10-06 18:52:10 +0000316 } else if (ObjcImplementationDecl *OID =
317 dyn_cast<ObjcImplementationDecl>(D)) {
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000318 PrintObjcImplementationDecl(OID);
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000319 } else if (ObjcCategoryImplDecl *OID =
320 dyn_cast<ObjcCategoryImplDecl>(D)) {
321 PrintObjcCategoryImplDecl(OID);
322 } else if (ObjcCategoryDecl *OID =
323 dyn_cast<ObjcCategoryDecl>(D)) {
324 PrintObjcCategoryDecl(OID);
Fariborz Jahanian243b64b2007-10-11 23:42:27 +0000325 } else if (ObjcCompatibleAliasDecl *OID =
326 dyn_cast<ObjcCompatibleAliasDecl>(D)) {
327 PrintObjcCompatibleAliasDecl(OID);
Chris Lattner9fa5e652007-10-06 18:52:10 +0000328 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000329 fprintf(FP, "@class [printing todo]\n");
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000330 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000331 fprintf(FP, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner9fa5e652007-10-06 18:52:10 +0000332 } else {
333 assert(0 && "Unknown decl type!");
Chris Lattner6000dac2007-08-08 22:51:59 +0000334 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000335 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000336 };
Reid Spencer5f016e22007-07-11 17:01:13 +0000337}
Chris Lattner6000dac2007-08-08 22:51:59 +0000338
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000339ASTConsumer *clang::CreateASTPrinter(FILE* fp) { return new ASTPrinter(fp); }
340
341//===----------------------------------------------------------------------===//
342/// ASTDumper - Low-level dumper of ASTs
Chris Lattner3d4997d2007-09-15 23:02:28 +0000343
344namespace {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000345 class ASTDumper : public ASTConsumer, public DeclPrinter {
Chris Lattner3d4997d2007-09-15 23:02:28 +0000346 SourceManager *SM;
347 public:
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000348 ASTDumper(FILE* fp = NULL) : DeclPrinter(fp) {}
349
Chris Lattner3d4997d2007-09-15 23:02:28 +0000350 void Initialize(ASTContext &Context, unsigned MainFileID) {
351 SM = &Context.SourceMgr;
Chris Lattner6000dac2007-08-08 22:51:59 +0000352 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000353
354 virtual void HandleTopLevelDecl(Decl *D) {
355 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
356 PrintFunctionDeclStart(FD);
357
358 if (FD->getBody()) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000359 fprintf(FP, "\n");
Chris Lattner3d4997d2007-09-15 23:02:28 +0000360 FD->getBody()->dumpAll(*SM);
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000361 fprintf(FP, "\n");
Chris Lattner3d4997d2007-09-15 23:02:28 +0000362 }
363 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
364 PrintTypeDefDecl(TD);
365 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000366 fprintf(FP, "Read top-level variable decl: '%s'\n", SD->getName());
Chris Lattner9fa5e652007-10-06 18:52:10 +0000367 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000368 fprintf(FP, "Read objc interface '%s'\n", OID->getName());
Steve Naroff8de28262007-10-14 17:03:01 +0000369 } else if (ObjcProtocolDecl *OPD = dyn_cast<ObjcProtocolDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000370 fprintf(FP, "Read objc protocol '%s'\n", OPD->getName());
Steve Naroff8de28262007-10-14 17:03:01 +0000371 } else if (ObjcCategoryDecl *OCD = dyn_cast<ObjcCategoryDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000372 fprintf(FP, "Read objc category '%s'\n", OCD->getName());
Chris Lattner9fa5e652007-10-06 18:52:10 +0000373 } else if (isa<ObjcForwardProtocolDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000374 fprintf(FP, "Read objc fwd protocol decl\n");
Steve Naroff8de28262007-10-14 17:03:01 +0000375 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000376 fprintf(FP, "Read objc fwd class decl\n");
Chris Lattner9fa5e652007-10-06 18:52:10 +0000377 } else {
378 assert(0 && "Unknown decl type!");
Chris Lattner3d4997d2007-09-15 23:02:28 +0000379 }
380 }
381 };
Chris Lattner6000dac2007-08-08 22:51:59 +0000382}
383
Chris Lattner3d4997d2007-09-15 23:02:28 +0000384ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
385
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000386//===----------------------------------------------------------------------===//
387/// ASTViewer - AST Visualization
388
Ted Kremenek80de08f2007-09-19 21:29:43 +0000389namespace {
390 class ASTViewer : public ASTConsumer {
391 SourceManager *SM;
392 public:
393 void Initialize(ASTContext &Context, unsigned MainFileID) {
394 SM = &Context.SourceMgr;
395 }
396
397 virtual void HandleTopLevelDecl(Decl *D) {
398 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000399 DeclPrinter(stderr).PrintFunctionDeclStart(FD);
Ted Kremenek80de08f2007-09-19 21:29:43 +0000400
401 if (FD->getBody()) {
402 fprintf(stderr, "\n");
403 FD->getBody()->viewAST();
404 fprintf(stderr, "\n");
405 }
406 }
407 }
408 };
409}
410
411ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
412
413
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000414//===----------------------------------------------------------------------===//
415// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
416// the CFGs for all function definitions.
417
418namespace {
419
Chris Lattnerc0508f92007-09-15 23:21:08 +0000420class CFGVisitor : public ASTConsumer {
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000421public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000422 // CFG Visitor interface to be implemented by subclass.
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000423 virtual void VisitCFG(CFG& C) = 0;
424 virtual bool printFuncDeclStart() { return true; }
Chris Lattnerc0508f92007-09-15 23:21:08 +0000425
426 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000427};
428
429} // end anonymous namespace
430
Chris Lattnerc0508f92007-09-15 23:21:08 +0000431void CFGVisitor::HandleTopLevelDecl(Decl *D) {
432 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
433 if (!FD || !FD->getBody())
434 return;
435
436 if (printFuncDeclStart()) {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000437 DeclPrinter(stderr).PrintFunctionDeclStart(FD);
Chris Lattnerc0508f92007-09-15 23:21:08 +0000438 fprintf(stderr,"\n");
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000439 }
Chris Lattnerc0508f92007-09-15 23:21:08 +0000440
Ted Kremenek12259662007-09-17 17:10:02 +0000441 CFG *C = CFG::buildCFG(FD->getBody());
442 VisitCFG(*C);
443 delete C;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000444}
445
446//===----------------------------------------------------------------------===//
447// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
448
449namespace {
450 class CFGDumper : public CFGVisitor {
451 const bool UseGraphviz;
452 public:
453 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
454
Chris Lattnerc0508f92007-09-15 23:21:08 +0000455 virtual void VisitCFG(CFG &C) {
456 if (UseGraphviz)
457 C.viewCFG();
458 else
459 C.dump();
460 }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000461 };
462} // end anonymous namespace
463
Chris Lattnerc0508f92007-09-15 23:21:08 +0000464ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
465 return new CFGDumper(ViewGraphs);
Ted Kremenekfddd5182007-08-21 21:42:03 +0000466}
467
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000468//===----------------------------------------------------------------------===//
469// AnalyzeLiveVariables - perform live variable analysis and dump results
470
471namespace {
472 class LivenessVisitor : public CFGVisitor {
Chris Lattnerc0508f92007-09-15 23:21:08 +0000473 SourceManager *SM;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000474 public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000475 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
476 SM = &Context.SourceMgr;
477 }
478
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000479 virtual void VisitCFG(CFG& C) {
Ted Kremenek11e72182007-10-01 20:33:52 +0000480 LiveVariables L(C);
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000481 L.runOnCFG(C);
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000482 L.dumpBlockLiveness(*SM);
Ted Kremeneke4e63342007-09-06 00:17:54 +0000483 }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000484 };
485} // end anonymous namespace
486
Chris Lattnerc0508f92007-09-15 23:21:08 +0000487ASTConsumer *clang::CreateLiveVarAnalyzer() {
488 return new LivenessVisitor();
Ted Kremeneke4e63342007-09-06 00:17:54 +0000489}
490
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000491//===----------------------------------------------------------------------===//
Ted Kremenek2bf55142007-09-17 20:49:30 +0000492// DeadStores - run checker to locate dead stores in a function
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000493
494namespace {
495 class DeadStoreVisitor : public CFGVisitor {
Chris Lattnerc0508f92007-09-15 23:21:08 +0000496 Diagnostic &Diags;
497 ASTContext *Ctx;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000498 public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000499 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
500 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
501 Ctx = &Context;
502 }
503
504 virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
Ted Kremenek567a7e62007-09-07 23:54:15 +0000505 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000506 };
507} // end anonymous namespace
508
Chris Lattnerc0508f92007-09-15 23:21:08 +0000509ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
510 return new DeadStoreVisitor(Diags);
Ted Kremenek055c2752007-09-06 23:00:42 +0000511}
Chris Lattner580980b2007-09-16 19:46:59 +0000512
513//===----------------------------------------------------------------------===//
Ted Kremenek2bf55142007-09-17 20:49:30 +0000514// Unitialized Values - run checker to flag potential uses of uninitalized
515// variables.
516
517namespace {
518 class UninitValsVisitor : public CFGVisitor {
519 Diagnostic &Diags;
520 ASTContext *Ctx;
521 public:
522 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
523 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
524 Ctx = &Context;
525 }
526
527 virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
528 virtual bool printFuncDeclStart() { return false; }
529 };
530} // end anonymous namespace
531
532ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
533 return new UninitValsVisitor(Diags);
534}
535
536//===----------------------------------------------------------------------===//
Chris Lattner580980b2007-09-16 19:46:59 +0000537// LLVM Emitter
538
539#include "clang/Basic/Diagnostic.h"
Devang Patel7a4718e2007-10-31 20:01:01 +0000540#include "clang/Basic/TargetInfo.h"
Chris Lattner580980b2007-09-16 19:46:59 +0000541#include "clang/CodeGen/ModuleBuilder.h"
542#include "llvm/Module.h"
Devang Patel7a4718e2007-10-31 20:01:01 +0000543#include "llvm/Target/TargetData.h"
544#include "llvm/Target/TargetMachine.h"
Chris Lattner580980b2007-09-16 19:46:59 +0000545#include <iostream>
546
547namespace {
548 class LLVMEmitter : public ASTConsumer {
549 Diagnostic &Diags;
550 llvm::Module *M;
Devang Patel7a4718e2007-10-31 20:01:01 +0000551 const llvm::TargetData *TD;
Chris Lattner580980b2007-09-16 19:46:59 +0000552 ASTContext *Ctx;
Chris Lattner45e8cbd2007-11-28 05:34:05 +0000553 const LangOptions &Features;
Chris Lattnera36c4862007-11-13 18:16:41 +0000554 CodeGen::CodeGenModule *Builder;
Chris Lattner580980b2007-09-16 19:46:59 +0000555 public:
Chris Lattner45e8cbd2007-11-28 05:34:05 +0000556 LLVMEmitter(Diagnostic &diags, const LangOptions &LO)
557 : Diags(diags)
558 , Features(LO) {}
Chris Lattner580980b2007-09-16 19:46:59 +0000559 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
560 Ctx = &Context;
561 M = new llvm::Module("foo");
Devang Patel7a4718e2007-10-31 20:01:01 +0000562 M->setTargetTriple(Ctx->Target.getTargetTriple());
563 TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
Chris Lattner45e8cbd2007-11-28 05:34:05 +0000564 Builder = CodeGen::Init(Context, Features, *M, *TD);
Chris Lattner580980b2007-09-16 19:46:59 +0000565 }
566
567 virtual void HandleTopLevelDecl(Decl *D) {
568 // If an error occurred, stop code generation, but continue parsing and
569 // semantic analysis (to ensure all warnings and errors are emitted).
570 if (Diags.hasErrorOccurred())
571 return;
572
573 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
574 CodeGen::CodeGenFunction(Builder, FD);
575 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
576 CodeGen::CodeGenGlobalVar(Builder, FVD);
577 } else {
Steve Naroff91578f32007-11-17 21:21:01 +0000578 assert(isa<TypeDecl>(D) && "Only expected type decls here");
Chris Lattner580980b2007-09-16 19:46:59 +0000579 // don't codegen for now, eventually pass down for debug info.
580 //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n";
581 }
582 }
583
584 ~LLVMEmitter() {
585 CodeGen::Terminate(Builder);
586
587 // Print the generated code.
588 M->print(std::cout);
589 delete M;
590 }
591 };
592} // end anonymous namespace
593
Chris Lattner45e8cbd2007-11-28 05:34:05 +0000594ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features) {
595 return new LLVMEmitter(Diags, Features);
Chris Lattner580980b2007-09-16 19:46:59 +0000596}
597