blob: 5cd3f77562b8a541fe7c87584fee28e528c21bba [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 Kremenekea75c552007-11-28 21:32:21 +000020#include "llvm/Support/Streams.h"
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000021
Chris Lattner6000dac2007-08-08 22:51:59 +000022using namespace clang;
Reid Spencer5f016e22007-07-11 17:01:13 +000023
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000024//===----------------------------------------------------------------------===//
25/// DeclPrinter - Utility class for printing top-level decls.
Chris Lattner6000dac2007-08-08 22:51:59 +000026
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000027namespace {
28 class DeclPrinter {
29 public:
Ted Kremenekea75c552007-11-28 21:32:21 +000030 std::ostream& Out;
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000031
Ted Kremenekea75c552007-11-28 21:32:21 +000032 DeclPrinter(std::ostream* out) : Out(out ? *out : *llvm::cerr.stream()) {}
33 DeclPrinter() : Out(*llvm::cerr.stream()) {}
Ted Kremenek1b5a4bd2007-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) {
Reid Spencer5f016e22007-07-11 17:01:13 +000048 bool HasBody = FD->getBody();
49
Ted Kremenekea75c552007-11-28 21:32:21 +000050 Out << '\n';
Chris Lattner70c8b2e2007-08-26 04:02:13 +000051
52 switch (FD->getStorageClass()) {
53 default: assert(0 && "Unknown storage class");
54 case FunctionDecl::None: break;
Ted Kremenekea75c552007-11-28 21:32:21 +000055 case FunctionDecl::Extern: Out << "extern "; break;
56 case FunctionDecl::Static: Out << "static "; break;
Chris Lattner70c8b2e2007-08-26 04:02:13 +000057 }
58
59 if (FD->isInline())
Ted Kremenekea75c552007-11-28 21:32:21 +000060 Out << "inline ";
Chris Lattner70c8b2e2007-08-26 04:02:13 +000061
Reid Spencer5f016e22007-07-11 17:01:13 +000062 std::string Proto = FD->getName();
Chris Lattner0d6ca112007-12-03 21:43:25 +000063 const FunctionType *AFT = FD->getType()->getAsFunctionType();
Reid Spencer5f016e22007-07-11 17:01:13 +000064
Chris Lattner0d6ca112007-12-03 21:43:25 +000065 if (const FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
Reid Spencer5f016e22007-07-11 17:01:13 +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 Kremenekea75c552007-11-28 21:32:21 +000087 Out << Proto;
Reid Spencer5f016e22007-07-11 17:01:13 +000088
Chris Lattner6000dac2007-08-08 22:51:59 +000089 if (!FD->getBody())
Ted Kremenekea75c552007-11-28 21:32:21 +000090 Out << ";\n";
Chris Lattner6000dac2007-08-08 22:51:59 +000091 // Doesn't print the body.
Reid Spencer5f016e22007-07-11 17:01:13 +000092}
93
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +000094void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
Reid Spencer5f016e22007-07-11 17:01:13 +000095 std::string S = TD->getName();
96 TD->getUnderlyingType().getAsStringInternal(S);
Ted Kremenekea75c552007-11-28 21:32:21 +000097 Out << "typedef " << S << ";\n";
Reid Spencer5f016e22007-07-11 17:01:13 +000098}
99
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000100void DeclPrinter::PrintObjcMethodDecl(ObjcMethodDecl *OMD) {
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000101 if (OMD->isInstance())
Ted Kremenekea75c552007-11-28 21:32:21 +0000102 Out << "\n- ";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000103 else
Ted Kremenekea75c552007-11-28 21:32:21 +0000104 Out << "\n+ ";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000105 if (!OMD->getResultType().isNull())
Ted Kremenekea75c552007-11-28 21:32:21 +0000106 Out << '(' << OMD->getResultType().getAsString() << ") ";
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000107 // FIXME: just print original selector name!
Ted Kremenekea75c552007-11-28 21:32:21 +0000108 Out << OMD->getSelector().getName();
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000109
110 for (int i = 0; i < OMD->getNumParams(); i++) {
111 ParmVarDecl *PDecl = OMD->getParamDecl(i);
Ted Kremenekea75c552007-11-28 21:32:21 +0000112 // FIXME: selector is missing here!
113 Out << " :(" << PDecl->getType().getAsString() << ") " << PDecl->getName();
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000114 }
115}
116
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000117void DeclPrinter::PrintObjcImplementationDecl(ObjcImplementationDecl *OID) {
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000118 std::string I = OID->getName();
119 ObjcInterfaceDecl *SID = OID->getSuperClass();
Ted Kremenekea75c552007-11-28 21:32:21 +0000120
121 if (SID)
122 Out << "@implementation " << I << " : " << SID->getName();
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000123 else
Ted Kremenekea75c552007-11-28 21:32:21 +0000124 Out << "@implementation " << I;
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 Kremenekea75c552007-11-28 21:32:21 +0000130 Out << ' ';
131 OMD->getBody()->printPretty(Out);
132 Out << '\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 Kremenekea75c552007-11-28 21:32:21 +0000140 Out << ' ';
141 OMD->getBody()->printPretty(Out);
142 Out << '\n';
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000143 }
144 }
145
Ted Kremenekea75c552007-11-28 21:32:21 +0000146 Out << "@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();
Ted Kremenekea75c552007-11-28 21:32:21 +0000153
154 if (SID)
155 Out << "@interface " << I << " : " << SID->getName();
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000156 else
Ted Kremenekea75c552007-11-28 21:32:21 +0000157 Out << "@interface " << I;
158
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000159 // Protocols?
160 int count = OID->getNumIntfRefProtocols();
Ted Kremenekea75c552007-11-28 21:32:21 +0000161
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000162 if (count > 0) {
163 ObjcProtocolDecl **refProtocols = OID->getReferencedProtocols();
164 for (int i = 0; i < count; i++)
Ted Kremenekea75c552007-11-28 21:32:21 +0000165 Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName();
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000166 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000167
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000168 if (count > 0)
Ted Kremenekea75c552007-11-28 21:32:21 +0000169 Out << ">\n";
Fariborz Jahaniane37882a2007-10-08 23:06:41 +0000170 else
Ted Kremenekea75c552007-11-28 21:32:21 +0000171 Out << '\n';
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000172
Steve Naroff03300712007-11-12 13:56:41 +0000173 int NumIvars = OID->getNumInstanceVariables();
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000174 if (NumIvars > 0) {
Steve Naroff03300712007-11-12 13:56:41 +0000175 ObjcIvarDecl **Ivars = OID->getInstanceVariables();
Ted Kremenekea75c552007-11-28 21:32:21 +0000176 Out << '{';
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000177 for (int i = 0; i < NumIvars; i++) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000178 Out << '\t' << Ivars[i]->getType().getAsString()
179 << ' ' << Ivars[i]->getName()
180 << ";\n";
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000181 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000182 Out << "}\n";
Fariborz Jahanianedcfb422007-10-26 16:29:12 +0000183 }
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000184
185 int NumProperties = OID->getNumPropertyDecl();
186 if (NumProperties > 0) {
187 for (int i = 0; i < NumProperties; i++) {
188 ObjcPropertyDecl *PDecl = OID->getPropertyDecl()[i];
Ted Kremenekea75c552007-11-28 21:32:21 +0000189 Out << "@property";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000190 if (PDecl->getPropertyAttributes() != ObjcPropertyDecl::OBJC_PR_noattr) {
191 bool first = true;
Ted Kremenekea75c552007-11-28 21:32:21 +0000192 Out << " (";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000193 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readonly)
194 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000195 Out << (first ? ' ' : ',') << "readonly";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000196 first = false;
197 }
198
199 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_getter)
200 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000201 Out << (first ? ' ' : ',') << "getter = "
202 << PDecl->getGetterName()->getName();
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000203 first = false;
204 }
205 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_setter)
206 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000207 Out << (first ? ' ' : ',') << "setter = "
208 << PDecl->getSetterName()->getName();
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000209 first = false;
210 }
211
212 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_assign)
213 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000214 Out << (first ? ' ' : ',') << "assign";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000215 first = false;
216 }
217
218 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readwrite)
219 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000220 Out << (first ? ' ' : ',') << "readwrite";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000221 first = false;
222 }
223
224 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_retain)
225 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000226 Out << (first ? ' ' : ',') << "retain";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000227 first = false;
228 }
229
230 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_copy)
231 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000232 Out << (first ? ' ' : ',') << "copy";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000233 first = false;
234 }
235
236 if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_nonatomic)
237 {
Ted Kremenekea75c552007-11-28 21:32:21 +0000238 Out << (first ? ' ' : ',') << "nonatomic";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000239 first = false;
240 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000241 Out << " )";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000242 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000243
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000244 ObjcIvarDecl **IDecl = PDecl->getPropertyDecls();
Ted Kremenekea75c552007-11-28 21:32:21 +0000245
246 Out << ' ' << IDecl[0]->getType().getAsString()
247 << ' ' << IDecl[0]->getName();
248
249 for (int j = 1; j < PDecl->getNumPropertyDecls(); j++)
250 Out << ", " << IDecl[j]->getName();
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000251
Ted Kremenekea75c552007-11-28 21:32:21 +0000252 Out << ";\n";
Fariborz Jahanian82a5fe32007-11-06 22:01:00 +0000253 }
254 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000255
256 Out << "@end\n";
Steve Naroff2bd42fa2007-09-10 20:51:04 +0000257 // FIXME: implement the rest...
258}
259
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000260void DeclPrinter::PrintObjcProtocolDecl(ObjcProtocolDecl *PID) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000261 Out << "@protocol " << PID->getName() << '\n';
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000262 // FIXME: implement the rest...
263}
264
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000265void DeclPrinter::PrintObjcCategoryImplDecl(ObjcCategoryImplDecl *PID) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000266 Out << "@implementation "
267 << PID->getClassInterface()->getName()
268 << '(' << PID->getName() << ");\n";
269
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000270 // FIXME: implement the rest...
271}
272
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000273void DeclPrinter::PrintObjcCategoryDecl(ObjcCategoryDecl *PID) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000274 Out << "@interface "
275 << PID->getClassInterface()->getName()
276 << '(' << PID->getName() << ");\n";
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000277 // FIXME: implement the rest...
278}
279
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000280void DeclPrinter::PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000281 Out << "@compatibility_alias " << AID->getName()
282 << ' ' << AID->getClassInterface()->getName() << ";\n";
Fariborz Jahanian243b64b2007-10-11 23:42:27 +0000283}
284
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000285//===----------------------------------------------------------------------===//
286/// ASTPrinter - Pretty-printer of ASTs
287
Chris Lattner3d4997d2007-09-15 23:02:28 +0000288namespace {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000289 class ASTPrinter : public ASTConsumer, public DeclPrinter {
290 public:
Ted Kremenekea75c552007-11-28 21:32:21 +0000291 ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000292
Chris Lattner3d4997d2007-09-15 23:02:28 +0000293 virtual void HandleTopLevelDecl(Decl *D) {
294 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
295 PrintFunctionDeclStart(FD);
296
297 if (FD->getBody()) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000298 Out << ' ';
299 FD->getBody()->printPretty(Out);
300 Out << '\n';
Chris Lattner3d4997d2007-09-15 23:02:28 +0000301 }
Steve Naroffaaa3cf82007-11-13 23:48:03 +0000302 } else if (isa<ObjcMethodDecl>(D)) {
303 // Do nothing, methods definitions are printed in
304 // PrintObjcImplementationDecl.
Chris Lattner3d4997d2007-09-15 23:02:28 +0000305 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
306 PrintTypeDefDecl(TD);
Chris Lattner9fa5e652007-10-06 18:52:10 +0000307 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
308 PrintObjcInterfaceDecl(OID);
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000309 } else if (ObjcProtocolDecl *PID = dyn_cast<ObjcProtocolDecl>(D)) {
310 PrintObjcProtocolDecl(PID);
Chris Lattner9fa5e652007-10-06 18:52:10 +0000311 } else if (ObjcForwardProtocolDecl *OFPD =
312 dyn_cast<ObjcForwardProtocolDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000313 Out << "@protocol ";
Chris Lattner9fa5e652007-10-06 18:52:10 +0000314 for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
315 const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
Ted Kremenekea75c552007-11-28 21:32:21 +0000316 if (i) Out << ", ";
317 Out << D->getName();
Chris Lattner9fa5e652007-10-06 18:52:10 +0000318 }
Ted Kremenekea75c552007-11-28 21:32:21 +0000319 Out << ";\n";
Chris Lattner9fa5e652007-10-06 18:52:10 +0000320 } else if (ObjcImplementationDecl *OID =
321 dyn_cast<ObjcImplementationDecl>(D)) {
Fariborz Jahaniandb8f3d32007-11-10 20:59:13 +0000322 PrintObjcImplementationDecl(OID);
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000323 } else if (ObjcCategoryImplDecl *OID =
324 dyn_cast<ObjcCategoryImplDecl>(D)) {
325 PrintObjcCategoryImplDecl(OID);
326 } else if (ObjcCategoryDecl *OID =
327 dyn_cast<ObjcCategoryDecl>(D)) {
328 PrintObjcCategoryDecl(OID);
Fariborz Jahanian243b64b2007-10-11 23:42:27 +0000329 } else if (ObjcCompatibleAliasDecl *OID =
330 dyn_cast<ObjcCompatibleAliasDecl>(D)) {
331 PrintObjcCompatibleAliasDecl(OID);
Chris Lattner9fa5e652007-10-06 18:52:10 +0000332 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000333 Out << "@class [printing todo]\n";
Steve Naroff1f644322007-11-28 22:54:11 +0000334 } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
335 Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
Fariborz Jahanianab0aeb02007-10-08 18:53:38 +0000336 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000337 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
Chris Lattner9fa5e652007-10-06 18:52:10 +0000338 } else {
339 assert(0 && "Unknown decl type!");
Chris Lattner6000dac2007-08-08 22:51:59 +0000340 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000341 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000342 };
Reid Spencer5f016e22007-07-11 17:01:13 +0000343}
Chris Lattner6000dac2007-08-08 22:51:59 +0000344
Ted Kremenekea75c552007-11-28 21:32:21 +0000345ASTConsumer *clang::CreateASTPrinter(std::ostream* out) {
346 return new ASTPrinter(out);
347}
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000348
349//===----------------------------------------------------------------------===//
350/// ASTDumper - Low-level dumper of ASTs
Chris Lattner3d4997d2007-09-15 23:02:28 +0000351
352namespace {
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000353 class ASTDumper : public ASTConsumer, public DeclPrinter {
Chris Lattner3d4997d2007-09-15 23:02:28 +0000354 SourceManager *SM;
355 public:
Ted Kremenekea75c552007-11-28 21:32:21 +0000356 ASTDumper() : DeclPrinter() {}
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000357
Chris Lattner3d4997d2007-09-15 23:02:28 +0000358 void Initialize(ASTContext &Context, unsigned MainFileID) {
359 SM = &Context.SourceMgr;
Chris Lattner6000dac2007-08-08 22:51:59 +0000360 }
Chris Lattner3d4997d2007-09-15 23:02:28 +0000361
362 virtual void HandleTopLevelDecl(Decl *D) {
363 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
364 PrintFunctionDeclStart(FD);
365
366 if (FD->getBody()) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000367 Out << '\n';
368 // FIXME: convert dumper to use std::ostream?
Chris Lattner3d4997d2007-09-15 23:02:28 +0000369 FD->getBody()->dumpAll(*SM);
Ted Kremenekea75c552007-11-28 21:32:21 +0000370 Out << '\n';
Chris Lattner3d4997d2007-09-15 23:02:28 +0000371 }
372 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
373 PrintTypeDefDecl(TD);
374 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000375 Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
Chris Lattner9fa5e652007-10-06 18:52:10 +0000376 } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000377 Out << "Read objc interface '" << OID->getName() << "'\n";
Steve Naroff8de28262007-10-14 17:03:01 +0000378 } else if (ObjcProtocolDecl *OPD = dyn_cast<ObjcProtocolDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000379 Out << "Read objc protocol '" << OPD->getName() << "'\n";
Steve Naroff8de28262007-10-14 17:03:01 +0000380 } else if (ObjcCategoryDecl *OCD = dyn_cast<ObjcCategoryDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000381 Out << "Read objc category '" << OCD->getName() << "'\n";
Chris Lattner9fa5e652007-10-06 18:52:10 +0000382 } else if (isa<ObjcForwardProtocolDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000383 Out << "Read objc fwd protocol decl\n";
Steve Naroff8de28262007-10-14 17:03:01 +0000384 } else if (isa<ObjcClassDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000385 Out << "Read objc fwd class decl\n";
Chris Lattner9fa5e652007-10-06 18:52:10 +0000386 } else {
387 assert(0 && "Unknown decl type!");
Chris Lattner3d4997d2007-09-15 23:02:28 +0000388 }
389 }
390 };
Chris Lattner6000dac2007-08-08 22:51:59 +0000391}
392
Chris Lattner3d4997d2007-09-15 23:02:28 +0000393ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
394
Ted Kremenek1b5a4bd2007-11-27 21:46:50 +0000395//===----------------------------------------------------------------------===//
396/// ASTViewer - AST Visualization
397
Ted Kremenek80de08f2007-09-19 21:29:43 +0000398namespace {
399 class ASTViewer : public ASTConsumer {
400 SourceManager *SM;
401 public:
402 void Initialize(ASTContext &Context, unsigned MainFileID) {
403 SM = &Context.SourceMgr;
404 }
405
406 virtual void HandleTopLevelDecl(Decl *D) {
407 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000408 DeclPrinter().PrintFunctionDeclStart(FD);
Ted Kremenek80de08f2007-09-19 21:29:43 +0000409
410 if (FD->getBody()) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000411 llvm::cerr << '\n';
Ted Kremenek80de08f2007-09-19 21:29:43 +0000412 FD->getBody()->viewAST();
Ted Kremenekea75c552007-11-28 21:32:21 +0000413 llvm::cerr << '\n';
Ted Kremenek80de08f2007-09-19 21:29:43 +0000414 }
415 }
416 }
417 };
418}
419
420ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
421
422
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000423//===----------------------------------------------------------------------===//
424// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
425// the CFGs for all function definitions.
426
427namespace {
428
Chris Lattnerc0508f92007-09-15 23:21:08 +0000429class CFGVisitor : public ASTConsumer {
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000430public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000431 // CFG Visitor interface to be implemented by subclass.
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000432 virtual void VisitCFG(CFG& C) = 0;
433 virtual bool printFuncDeclStart() { return true; }
Chris Lattnerc0508f92007-09-15 23:21:08 +0000434
435 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000436};
437
438} // end anonymous namespace
439
Chris Lattnerc0508f92007-09-15 23:21:08 +0000440void CFGVisitor::HandleTopLevelDecl(Decl *D) {
441 FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
442 if (!FD || !FD->getBody())
443 return;
444
445 if (printFuncDeclStart()) {
Ted Kremenekea75c552007-11-28 21:32:21 +0000446 DeclPrinter().PrintFunctionDeclStart(FD);
447 llvm::cerr << '\n';
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000448 }
Chris Lattnerc0508f92007-09-15 23:21:08 +0000449
Ted Kremenek12259662007-09-17 17:10:02 +0000450 CFG *C = CFG::buildCFG(FD->getBody());
451 VisitCFG(*C);
452 delete C;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000453}
454
455//===----------------------------------------------------------------------===//
456// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
457
458namespace {
459 class CFGDumper : public CFGVisitor {
460 const bool UseGraphviz;
461 public:
462 CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
463
Chris Lattnerc0508f92007-09-15 23:21:08 +0000464 virtual void VisitCFG(CFG &C) {
465 if (UseGraphviz)
466 C.viewCFG();
467 else
468 C.dump();
469 }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000470 };
471} // end anonymous namespace
472
Chris Lattnerc0508f92007-09-15 23:21:08 +0000473ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
474 return new CFGDumper(ViewGraphs);
Ted Kremenekfddd5182007-08-21 21:42:03 +0000475}
476
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000477//===----------------------------------------------------------------------===//
478// AnalyzeLiveVariables - perform live variable analysis and dump results
479
480namespace {
481 class LivenessVisitor : public CFGVisitor {
Chris Lattnerc0508f92007-09-15 23:21:08 +0000482 SourceManager *SM;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000483 public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000484 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
485 SM = &Context.SourceMgr;
486 }
487
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000488 virtual void VisitCFG(CFG& C) {
Ted Kremenek11e72182007-10-01 20:33:52 +0000489 LiveVariables L(C);
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000490 L.runOnCFG(C);
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000491 L.dumpBlockLiveness(*SM);
Ted Kremeneke4e63342007-09-06 00:17:54 +0000492 }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000493 };
494} // end anonymous namespace
495
Chris Lattnerc0508f92007-09-15 23:21:08 +0000496ASTConsumer *clang::CreateLiveVarAnalyzer() {
497 return new LivenessVisitor();
Ted Kremeneke4e63342007-09-06 00:17:54 +0000498}
499
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000500//===----------------------------------------------------------------------===//
Ted Kremenek2bf55142007-09-17 20:49:30 +0000501// DeadStores - run checker to locate dead stores in a function
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000502
503namespace {
504 class DeadStoreVisitor : public CFGVisitor {
Chris Lattnerc0508f92007-09-15 23:21:08 +0000505 Diagnostic &Diags;
506 ASTContext *Ctx;
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000507 public:
Chris Lattnerc0508f92007-09-15 23:21:08 +0000508 DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
509 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
510 Ctx = &Context;
511 }
512
513 virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
Ted Kremenek567a7e62007-09-07 23:54:15 +0000514 virtual bool printFuncDeclStart() { return false; }
Ted Kremenek74bf2c92007-09-07 23:47:56 +0000515 };
516} // end anonymous namespace
517
Chris Lattnerc0508f92007-09-15 23:21:08 +0000518ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
519 return new DeadStoreVisitor(Diags);
Ted Kremenek055c2752007-09-06 23:00:42 +0000520}
Chris Lattner580980b2007-09-16 19:46:59 +0000521
522//===----------------------------------------------------------------------===//
Ted Kremenek2bf55142007-09-17 20:49:30 +0000523// Unitialized Values - run checker to flag potential uses of uninitalized
524// variables.
525
526namespace {
527 class UninitValsVisitor : public CFGVisitor {
528 Diagnostic &Diags;
529 ASTContext *Ctx;
530 public:
531 UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
532 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
533 Ctx = &Context;
534 }
535
536 virtual void VisitCFG(CFG& C) { CheckUninitializedValues(C, *Ctx, Diags); }
537 virtual bool printFuncDeclStart() { return false; }
538 };
539} // end anonymous namespace
540
541ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
542 return new UninitValsVisitor(Diags);
543}
544
545//===----------------------------------------------------------------------===//
Chris Lattner580980b2007-09-16 19:46:59 +0000546// LLVM Emitter
547
548#include "clang/Basic/Diagnostic.h"
Devang Patel7a4718e2007-10-31 20:01:01 +0000549#include "clang/Basic/TargetInfo.h"
Chris Lattner580980b2007-09-16 19:46:59 +0000550#include "clang/CodeGen/ModuleBuilder.h"
551#include "llvm/Module.h"
Devang Patel7a4718e2007-10-31 20:01:01 +0000552#include "llvm/Target/TargetData.h"
553#include "llvm/Target/TargetMachine.h"
Chris Lattner580980b2007-09-16 19:46:59 +0000554#include <iostream>
555
556namespace {
557 class LLVMEmitter : public ASTConsumer {
558 Diagnostic &Diags;
559 llvm::Module *M;
Devang Patel7a4718e2007-10-31 20:01:01 +0000560 const llvm::TargetData *TD;
Chris Lattner580980b2007-09-16 19:46:59 +0000561 ASTContext *Ctx;
Chris Lattner45e8cbd2007-11-28 05:34:05 +0000562 const LangOptions &Features;
Chris Lattnera36c4862007-11-13 18:16:41 +0000563 CodeGen::CodeGenModule *Builder;
Chris Lattner580980b2007-09-16 19:46:59 +0000564 public:
Chris Lattner45e8cbd2007-11-28 05:34:05 +0000565 LLVMEmitter(Diagnostic &diags, const LangOptions &LO)
566 : Diags(diags)
567 , Features(LO) {}
Chris Lattner580980b2007-09-16 19:46:59 +0000568 virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
569 Ctx = &Context;
570 M = new llvm::Module("foo");
Devang Patel7a4718e2007-10-31 20:01:01 +0000571 M->setTargetTriple(Ctx->Target.getTargetTriple());
572 TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
Chris Lattnerfb97b032007-12-02 01:40:18 +0000573 Builder = CodeGen::Init(Context, Features, *M, *TD, Diags);
Chris Lattner580980b2007-09-16 19:46:59 +0000574 }
575
576 virtual void HandleTopLevelDecl(Decl *D) {
577 // If an error occurred, stop code generation, but continue parsing and
578 // semantic analysis (to ensure all warnings and errors are emitted).
579 if (Diags.hasErrorOccurred())
580 return;
581
582 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
583 CodeGen::CodeGenFunction(Builder, FD);
584 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
585 CodeGen::CodeGenGlobalVar(Builder, FVD);
586 } else {
Steve Naroff91578f32007-11-17 21:21:01 +0000587 assert(isa<TypeDecl>(D) && "Only expected type decls here");
Chris Lattner580980b2007-09-16 19:46:59 +0000588 // don't codegen for now, eventually pass down for debug info.
589 //std::cerr << "Read top-level typedef decl: '" << D->getName() << "'\n";
590 }
591 }
592
593 ~LLVMEmitter() {
594 CodeGen::Terminate(Builder);
595
596 // Print the generated code.
597 M->print(std::cout);
598 delete M;
599 }
600 };
601} // end anonymous namespace
602
Chris Lattner45e8cbd2007-11-28 05:34:05 +0000603ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features) {
604 return new LLVMEmitter(Diags, Features);
Chris Lattner580980b2007-09-16 19:46:59 +0000605}
606