blob: 5d14f0355531411b1db240d7e64bec43e1aab004 [file] [log] [blame]
Chris Lattner77cd2a02007-10-11 00:43:27 +00001//===--- RewriteTest.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Steve Naroffebf2b562007-10-23 23:50:29 +000019#include "clang/Basic/IdentifierTable.h"
Chris Lattner158ecb92007-10-25 17:07:24 +000020#include "llvm/ADT/StringExtras.h"
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000021#include "llvm/ADT/SmallPtrSet.h"
Steve Naroff2feac5e2007-10-30 03:43:13 +000022#include "clang/Lex/Lexer.h"
Steve Naroff874e2322007-11-15 10:28:18 +000023#include <sstream>
Chris Lattner77cd2a02007-10-11 00:43:27 +000024using namespace clang;
Chris Lattner158ecb92007-10-25 17:07:24 +000025using llvm::utostr;
Chris Lattner77cd2a02007-10-11 00:43:27 +000026
Chris Lattner77cd2a02007-10-11 00:43:27 +000027namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000028 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000029 Rewriter Rewrite;
Chris Lattnere365c502007-11-30 22:25:36 +000030 Diagnostic &Diags;
Chris Lattner01c57482007-10-17 22:35:30 +000031 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000032 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000033 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000034 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000035 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
36 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000037 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcSynthesizedStructs;
Steve Naroff8749be52007-10-31 22:11:35 +000038 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcForwardDecls;
Fariborz Jahanianb7908b52007-11-13 21:02:00 +000039 llvm::DenseMap<ObjcMethodDecl*, std::string> MethodInternalNames;
Steve Naroffebf2b562007-10-23 23:50:29 +000040
41 FunctionDecl *MsgSendFunctionDecl;
Steve Naroff874e2322007-11-15 10:28:18 +000042 FunctionDecl *MsgSendSuperFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000043 FunctionDecl *GetClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000044 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroff96984642007-11-08 14:30:50 +000045 FunctionDecl *CFStringFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000046
Steve Naroffbeaf2992007-11-03 11:27:19 +000047 // ObjC string constant support.
48 FileVarDecl *ConstantStringClassReference;
49 RecordDecl *NSStringRecord;
Steve Naroffab972d32007-11-04 22:37:50 +000050
Steve Naroff874e2322007-11-15 10:28:18 +000051 // Needed for super.
52 ObjcMethodDecl *CurMethodDecl;
53 RecordDecl *SuperStructDecl;
54
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000055 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000056 public:
Chris Lattner01c57482007-10-17 22:35:30 +000057 void Initialize(ASTContext &context, unsigned mainFileID) {
58 Context = &context;
59 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000060 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000061 MsgSendFunctionDecl = 0;
Steve Naroff874e2322007-11-15 10:28:18 +000062 MsgSendSuperFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000063 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000064 SelGetUidFunctionDecl = 0;
Steve Naroff96984642007-11-08 14:30:50 +000065 CFStringFunctionDecl = 0;
Steve Naroffbeaf2992007-11-03 11:27:19 +000066 ConstantStringClassReference = 0;
67 NSStringRecord = 0;
Steve Naroff874e2322007-11-15 10:28:18 +000068 CurMethodDecl = 0;
69 SuperStructDecl = 0;
70
Chris Lattner01c57482007-10-17 22:35:30 +000071 Rewrite.setSourceMgr(Context->SourceMgr);
Steve Naroffe3abbf52007-11-05 14:55:35 +000072 // declaring objc_selector outside the parameter list removes a silly
73 // scope related warning...
Steve Narofff6248702007-11-15 17:06:21 +000074 const char *s = "struct objc_selector; struct objc_class; struct objc_super;\n"
Steve Naroffe3abbf52007-11-05 14:55:35 +000075 "extern struct objc_object *objc_msgSend"
Steve Naroffab972d32007-11-04 22:37:50 +000076 "(struct objc_object *, struct objc_selector *, ...);\n"
Steve Naroff874e2322007-11-15 10:28:18 +000077 "extern struct objc_object *objc_msgSendSuper"
78 "(struct objc_super *, struct objc_selector *, ...);\n"
Steve Naroffab972d32007-11-04 22:37:50 +000079 "extern struct objc_object *objc_getClass"
Steve Naroff21867b12007-11-07 18:43:40 +000080 "(const char *);\n"
81 "extern void objc_exception_throw(struct objc_object *);\n"
82 "extern void objc_exception_try_enter(void *);\n"
83 "extern void objc_exception_try_exit(void *);\n"
84 "extern struct objc_object *objc_exception_extract(void *);\n"
85 "extern int objc_exception_match"
Fariborz Jahanian95673922007-11-14 22:26:25 +000086 "(struct objc_class *, struct objc_object *, ...);\n"
87 "#include <Objc/objc.h>\n";
Steve Naroff21867b12007-11-07 18:43:40 +000088
Steve Naroffab972d32007-11-04 22:37:50 +000089 Rewrite.InsertText(SourceLocation::getFileLoc(mainFileID, 0),
90 s, strlen(s));
Chris Lattner77cd2a02007-10-11 00:43:27 +000091 }
Chris Lattner8a12c272007-10-11 18:38:32 +000092
Chris Lattnerf04da132007-10-24 17:06:59 +000093 // Top Level Driver code.
94 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000095 void HandleDeclInMainFile(Decl *D);
Chris Lattnere365c502007-11-30 22:25:36 +000096 RewriteTest(Diagnostic &D) : Diags(D) {}
Chris Lattnerf04da132007-10-24 17:06:59 +000097 ~RewriteTest();
98
99 // Syntactic Rewriting.
Steve Naroffab972d32007-11-04 22:37:50 +0000100 void RewritePrologue(SourceLocation Loc);
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000101 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +0000102 void RewriteTabs();
103 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffbef11852007-10-26 20:53:56 +0000104 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000105 void RewriteImplementationDecl(NamedDecl *Dcl);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000106 void RewriteObjcMethodDecl(ObjcMethodDecl *MDecl, std::string &ResultStr);
Steve Naroff423cb562007-10-30 13:30:57 +0000107 void RewriteCategoryDecl(ObjcCategoryDecl *Dcl);
Steve Naroff752d6ef2007-10-30 16:42:30 +0000108 void RewriteProtocolDecl(ObjcProtocolDecl *Dcl);
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000109 void RewriteForwardProtocolDecl(ObjcForwardProtocolDecl *Dcl);
Steve Naroff71c0a952007-11-13 23:01:27 +0000110 void RewriteMethodDeclarations(int nMethods, ObjcMethodDecl **Methods);
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000111 void RewriteProperties(int nProperties, ObjcPropertyDecl **Properties);
Steve Naroff09b266e2007-10-30 23:14:51 +0000112 void RewriteFunctionDecl(FunctionDecl *FD);
Steve Naroffd5255f52007-11-01 13:24:47 +0000113 void RewriteObjcQualifiedInterfaceTypes(
114 const FunctionTypeProto *proto, FunctionDecl *FD);
115 bool needToScanForQualifiers(QualType T);
Steve Naroff874e2322007-11-15 10:28:18 +0000116 ObjcInterfaceDecl *isSuperReceiver(Expr *recExpr);
117 QualType getSuperStructType();
Chris Lattner311ff022007-10-16 22:36:42 +0000118
Chris Lattnerf04da132007-10-24 17:06:59 +0000119 // Expression Rewriting.
Steve Narofff3473a72007-11-09 15:20:18 +0000120 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
Chris Lattnere64b7772007-10-24 16:57:36 +0000121 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Steve Naroff7e3411b2007-11-15 02:58:25 +0000122 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
Steve Naroffb42f8412007-11-05 14:50:49 +0000123 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Chris Lattnere64b7772007-10-24 16:57:36 +0000124 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000125 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000126 Stmt *RewriteObjcTryStmt(ObjcAtTryStmt *S);
127 Stmt *RewriteObjcCatchStmt(ObjcAtCatchStmt *S);
128 Stmt *RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S);
Steve Naroff2bd03922007-11-07 15:32:26 +0000129 Stmt *RewriteObjcThrowStmt(ObjcAtThrowStmt *S);
Steve Naroff934f2762007-10-24 22:48:43 +0000130 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
131 Expr **args, unsigned nargs);
Steve Naroff09b266e2007-10-30 23:14:51 +0000132 void SynthMsgSendFunctionDecl();
Steve Naroff874e2322007-11-15 10:28:18 +0000133 void SynthMsgSendSuperFunctionDecl();
Steve Naroff09b266e2007-10-30 23:14:51 +0000134 void SynthGetClassFunctionDecl();
Steve Naroff96984642007-11-08 14:30:50 +0000135 void SynthCFStringFunctionDecl();
136
Chris Lattnerf04da132007-10-24 17:06:59 +0000137 // Metadata emission.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000138 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
139 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000140
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000141 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
142 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000143
Steve Naroff0416fb92007-11-11 17:19:15 +0000144 void RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000145 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000146 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000147 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000148 const char *ClassName,
149 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000150
151 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
152 int NumProtocols,
153 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000154 const char *ClassName,
155 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000156 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
157 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000158 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
159 ObjcIvarDecl *ivar,
160 std::string &Result);
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +0000161 void RewriteImplementations(std::string &Result);
Chris Lattner77cd2a02007-10-11 00:43:27 +0000162 };
163}
164
Chris Lattnere365c502007-11-30 22:25:36 +0000165ASTConsumer *clang::CreateCodeRewriterTest(Diagnostic &Diags) {
166 return new RewriteTest(Diags);
167}
Chris Lattner77cd2a02007-10-11 00:43:27 +0000168
Chris Lattnerf04da132007-10-24 17:06:59 +0000169//===----------------------------------------------------------------------===//
170// Top Level Driver Code
171//===----------------------------------------------------------------------===//
172
Chris Lattner8a12c272007-10-11 18:38:32 +0000173void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000174 // Two cases: either the decl could be in the main file, or it could be in a
175 // #included file. If the former, rewrite it now. If the later, check to see
176 // if we rewrote the #include/#import.
177 SourceLocation Loc = D->getLocation();
178 Loc = SM->getLogicalLoc(Loc);
179
180 // If this is for a builtin, ignore it.
181 if (Loc.isInvalid()) return;
182
Steve Naroffebf2b562007-10-23 23:50:29 +0000183 // Look for built-in declarations that we need to refer during the rewrite.
184 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff09b266e2007-10-30 23:14:51 +0000185 RewriteFunctionDecl(FD);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000186 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
187 // declared in <Foundation/NSString.h>
188 if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) {
189 ConstantStringClassReference = FVD;
190 return;
191 }
Steve Naroffbef11852007-10-26 20:53:56 +0000192 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
193 RewriteInterfaceDecl(MD);
Steve Naroff423cb562007-10-30 13:30:57 +0000194 } else if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(D)) {
195 RewriteCategoryDecl(CD);
Steve Naroff752d6ef2007-10-30 16:42:30 +0000196 } else if (ObjcProtocolDecl *PD = dyn_cast<ObjcProtocolDecl>(D)) {
197 RewriteProtocolDecl(PD);
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000198 } else if (ObjcForwardProtocolDecl *FP =
199 dyn_cast<ObjcForwardProtocolDecl>(D)){
200 RewriteForwardProtocolDecl(FP);
Steve Naroffebf2b562007-10-23 23:50:29 +0000201 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000202 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000203 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
204 return HandleDeclInMainFile(D);
205
Chris Lattnerf04da132007-10-24 17:06:59 +0000206 // Otherwise, see if there is a #import in the main file that should be
207 // rewritten.
Steve Naroff32174822007-11-09 12:50:28 +0000208 //RewriteInclude(Loc);
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000209}
210
Chris Lattnerf04da132007-10-24 17:06:59 +0000211/// HandleDeclInMainFile - This is called for each top-level decl defined in the
212/// main file of the input.
213void RewriteTest::HandleDeclInMainFile(Decl *D) {
214 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
215 if (Stmt *Body = FD->getBody())
Steve Narofff3473a72007-11-09 15:20:18 +0000216 FD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
Steve Naroff71c0a952007-11-13 23:01:27 +0000217
218 if (ObjcMethodDecl *MD = dyn_cast<ObjcMethodDecl>(D)) {
Steve Naroff874e2322007-11-15 10:28:18 +0000219 if (Stmt *Body = MD->getBody()) {
220 //Body->dump();
221 CurMethodDecl = MD;
Steve Naroff71c0a952007-11-13 23:01:27 +0000222 MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
Steve Naroff874e2322007-11-15 10:28:18 +0000223 CurMethodDecl = 0;
224 }
Steve Naroff71c0a952007-11-13 23:01:27 +0000225 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000226 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
227 ClassImplementation.push_back(CI);
228 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
229 CategoryImplementation.push_back(CI);
230 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
231 RewriteForwardClassDecl(CD);
Steve Narofff3473a72007-11-09 15:20:18 +0000232 else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
233 if (VD->getInit())
234 RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
235 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000236 // Nothing yet.
237}
238
239RewriteTest::~RewriteTest() {
240 // Get the top-level buffer that this corresponds to.
Chris Lattner74a0c772007-11-08 04:27:23 +0000241
242 // Rewrite tabs if we care.
243 //RewriteTabs();
Chris Lattnerf04da132007-10-24 17:06:59 +0000244
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000245 // Rewrite Objective-c meta data*
246 std::string ResultStr;
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +0000247 RewriteImplementations(ResultStr);
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000248
Chris Lattnerf04da132007-10-24 17:06:59 +0000249 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
250 // we are done.
251 if (const RewriteBuffer *RewriteBuf =
252 Rewrite.getRewriteBufferFor(MainFileID)) {
Steve Naroffbeaf2992007-11-03 11:27:19 +0000253 //printf("Changed:\n");
Chris Lattnerf04da132007-10-24 17:06:59 +0000254 std::string S(RewriteBuf->begin(), RewriteBuf->end());
255 printf("%s\n", S.c_str());
256 } else {
257 printf("No changes\n");
258 }
Fariborz Jahanian4402d812007-11-07 18:40:28 +0000259 // Emit metadata.
260 printf("%s", ResultStr.c_str());
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000261}
262
Chris Lattnerf04da132007-10-24 17:06:59 +0000263//===----------------------------------------------------------------------===//
264// Syntactic (non-AST) Rewriting Code
265//===----------------------------------------------------------------------===//
266
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000267void RewriteTest::RewriteInclude(SourceLocation Loc) {
268 // Rip up the #include stack to the main file.
269 SourceLocation IncLoc = Loc, NextLoc = Loc;
270 do {
271 IncLoc = Loc;
272 Loc = SM->getLogicalLoc(NextLoc);
273 NextLoc = SM->getIncludeLoc(Loc);
274 } while (!NextLoc.isInvalid());
275
276 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
277 // IncLoc indicates the header that was included if it is useful.
278 IncLoc = SM->getLogicalLoc(IncLoc);
279 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
280 Loc == LastIncLoc)
281 return;
282 LastIncLoc = Loc;
283
284 unsigned IncCol = SM->getColumnNumber(Loc);
285 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
286
287 // Replace the #import with #include.
288 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
289}
290
Chris Lattnerf04da132007-10-24 17:06:59 +0000291void RewriteTest::RewriteTabs() {
292 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
293 const char *MainBufStart = MainBuf.first;
294 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000295
Chris Lattnerf04da132007-10-24 17:06:59 +0000296 // Loop over the whole file, looking for tabs.
297 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
298 if (*BufPtr != '\t')
299 continue;
300
301 // Okay, we found a tab. This tab will turn into at least one character,
302 // but it depends on which 'virtual column' it is in. Compute that now.
303 unsigned VCol = 0;
304 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
305 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
306 ++VCol;
307
308 // Okay, now that we know the virtual column, we know how many spaces to
309 // insert. We assume 8-character tab-stops.
310 unsigned Spaces = 8-(VCol & 7);
311
312 // Get the location of the tab.
313 SourceLocation TabLoc =
314 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
315
316 // Rewrite the single tab character into a sequence of spaces.
317 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
318 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000319}
320
321
Chris Lattnerf04da132007-10-24 17:06:59 +0000322void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
323 int numDecls = ClassDecl->getNumForwardDecls();
324 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
325
326 // Get the start location and compute the semi location.
327 SourceLocation startLoc = ClassDecl->getLocation();
328 const char *startBuf = SM->getCharacterData(startLoc);
329 const char *semiPtr = strchr(startBuf, ';');
330
331 // Translate to typedef's that forward reference structs with the same name
332 // as the class. As a convenience, we include the original declaration
333 // as a comment.
334 std::string typedefString;
335 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000336 typedefString.append(startBuf, semiPtr-startBuf+1);
337 typedefString += "\n";
338 for (int i = 0; i < numDecls; i++) {
339 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
Steve Naroff32174822007-11-09 12:50:28 +0000340 typedefString += "#ifndef _REWRITER_typedef_";
341 typedefString += ForwardDecl->getName();
342 typedefString += "\n";
343 typedefString += "#define _REWRITER_typedef_";
344 typedefString += ForwardDecl->getName();
345 typedefString += "\n";
Steve Naroff352336b2007-11-05 14:36:37 +0000346 typedefString += "typedef struct objc_object ";
Steve Naroff934f2762007-10-24 22:48:43 +0000347 typedefString += ForwardDecl->getName();
Steve Naroff32174822007-11-09 12:50:28 +0000348 typedefString += ";\n#endif\n";
Steve Naroff934f2762007-10-24 22:48:43 +0000349 }
350
351 // Replace the @class with typedefs corresponding to the classes.
352 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
353 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000354}
355
Steve Naroff71c0a952007-11-13 23:01:27 +0000356void RewriteTest::RewriteMethodDeclarations(int nMethods, ObjcMethodDecl **Methods) {
Steve Naroff423cb562007-10-30 13:30:57 +0000357 for (int i = 0; i < nMethods; i++) {
358 ObjcMethodDecl *Method = Methods[i];
Steve Naroff1d098f62007-11-14 14:34:23 +0000359 SourceLocation LocStart = Method->getLocStart();
360 SourceLocation LocEnd = Method->getLocEnd();
Steve Naroff423cb562007-10-30 13:30:57 +0000361
Steve Naroff1d098f62007-11-14 14:34:23 +0000362 if (SM->getLineNumber(LocEnd) > SM->getLineNumber(LocStart)) {
363 Rewrite.InsertText(LocStart, "/* ", 3);
364 Rewrite.ReplaceText(LocEnd, 1, ";*/ ", 4);
365 } else {
366 Rewrite.InsertText(LocStart, "// ", 3);
367 }
Steve Naroff423cb562007-10-30 13:30:57 +0000368 }
369}
370
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000371void RewriteTest::RewriteProperties(int nProperties, ObjcPropertyDecl **Properties)
372{
373 for (int i = 0; i < nProperties; i++) {
374 ObjcPropertyDecl *Property = Properties[i];
375 SourceLocation Loc = Property->getLocation();
376
377 Rewrite.ReplaceText(Loc, 0, "// ", 3);
378
379 // FIXME: handle properties that are declared across multiple lines.
380 }
381}
382
Steve Naroff423cb562007-10-30 13:30:57 +0000383void RewriteTest::RewriteCategoryDecl(ObjcCategoryDecl *CatDecl) {
384 SourceLocation LocStart = CatDecl->getLocStart();
385
386 // FIXME: handle category headers that are declared across multiple lines.
387 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
388
Steve Naroff71c0a952007-11-13 23:01:27 +0000389 RewriteMethodDeclarations(CatDecl->getNumInstanceMethods(),
390 CatDecl->getInstanceMethods());
391 RewriteMethodDeclarations(CatDecl->getNumClassMethods(),
392 CatDecl->getClassMethods());
Steve Naroff423cb562007-10-30 13:30:57 +0000393 // Lastly, comment out the @end.
394 Rewrite.ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3);
395}
396
Steve Naroff752d6ef2007-10-30 16:42:30 +0000397void RewriteTest::RewriteProtocolDecl(ObjcProtocolDecl *PDecl) {
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000398 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000399
Steve Naroff752d6ef2007-10-30 16:42:30 +0000400 SourceLocation LocStart = PDecl->getLocStart();
401
402 // FIXME: handle protocol headers that are declared across multiple lines.
403 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
404
Steve Naroff71c0a952007-11-13 23:01:27 +0000405 RewriteMethodDeclarations(PDecl->getNumInstanceMethods(),
406 PDecl->getInstanceMethods());
407 RewriteMethodDeclarations(PDecl->getNumClassMethods(),
408 PDecl->getClassMethods());
Steve Naroff752d6ef2007-10-30 16:42:30 +0000409 // Lastly, comment out the @end.
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000410 SourceLocation LocEnd = PDecl->getAtEndLoc();
411 Rewrite.ReplaceText(LocEnd, 0, "// ", 3);
Steve Naroff8cc764c2007-11-14 15:03:57 +0000412
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000413 // Must comment out @optional/@required
414 const char *startBuf = SM->getCharacterData(LocStart);
415 const char *endBuf = SM->getCharacterData(LocEnd);
416 for (const char *p = startBuf; p < endBuf; p++) {
417 if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
418 std::string CommentedOptional = "/* @optional */";
Steve Naroff8cc764c2007-11-14 15:03:57 +0000419 SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000420 Rewrite.ReplaceText(OptionalLoc, strlen("@optional"),
421 CommentedOptional.c_str(), CommentedOptional.size());
422
423 }
424 else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
425 std::string CommentedRequired = "/* @required */";
Steve Naroff8cc764c2007-11-14 15:03:57 +0000426 SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000427 Rewrite.ReplaceText(OptionalLoc, strlen("@required"),
428 CommentedRequired.c_str(), CommentedRequired.size());
429
430 }
431 }
Steve Naroff752d6ef2007-10-30 16:42:30 +0000432}
433
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000434void RewriteTest::RewriteForwardProtocolDecl(ObjcForwardProtocolDecl *PDecl) {
435 SourceLocation LocStart = PDecl->getLocation();
Steve Naroffb7fa9922007-11-14 03:37:28 +0000436 if (LocStart.isInvalid())
437 assert(false && "Invalid SourceLocation");
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000438 // FIXME: handle forward protocol that are declared across multiple lines.
439 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
440}
441
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000442void RewriteTest::RewriteObjcMethodDecl(ObjcMethodDecl *OMD,
443 std::string &ResultStr) {
444 ResultStr += "\nstatic ";
445 ResultStr += OMD->getResultType().getAsString();
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000446 ResultStr += "\n";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000447
448 // Unique method name
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000449 std::string NameStr;
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000450
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000451 if (OMD->isInstance())
452 NameStr += "_I_";
453 else
454 NameStr += "_C_";
455
456 NameStr += OMD->getClassInterface()->getName();
457 NameStr += "_";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000458
459 NamedDecl *MethodContext = OMD->getMethodContext();
460 if (ObjcCategoryImplDecl *CID =
461 dyn_cast<ObjcCategoryImplDecl>(MethodContext)) {
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000462 NameStr += CID->getName();
463 NameStr += "_";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000464 }
465 // Append selector names, replacing ':' with '_'
466 const char *selName = OMD->getSelector().getName().c_str();
467 if (!strchr(selName, ':'))
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000468 NameStr += OMD->getSelector().getName();
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000469 else {
470 std::string selString = OMD->getSelector().getName();
471 int len = selString.size();
472 for (int i = 0; i < len; i++)
473 if (selString[i] == ':')
474 selString[i] = '_';
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000475 NameStr += selString;
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000476 }
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000477 // Remember this name for metadata emission
478 MethodInternalNames[OMD] = NameStr;
479 ResultStr += NameStr;
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000480
481 // Rewrite arguments
482 ResultStr += "(";
483
484 // invisible arguments
485 if (OMD->isInstance()) {
486 QualType selfTy = Context->getObjcInterfaceType(OMD->getClassInterface());
487 selfTy = Context->getPointerType(selfTy);
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000488 if (ObjcSynthesizedStructs.count(OMD->getClassInterface()))
489 ResultStr += "struct ";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000490 ResultStr += selfTy.getAsString();
491 }
492 else
493 ResultStr += Context->getObjcIdType().getAsString();
494
495 ResultStr += " self, ";
496 ResultStr += Context->getObjcSelType().getAsString();
497 ResultStr += " _cmd";
498
499 // Method arguments.
500 for (int i = 0; i < OMD->getNumParams(); i++) {
501 ParmVarDecl *PDecl = OMD->getParamDecl(i);
502 ResultStr += ", ";
503 ResultStr += PDecl->getType().getAsString();
504 ResultStr += " ";
505 ResultStr += PDecl->getName();
506 }
507 ResultStr += ")";
508
509}
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000510void RewriteTest::RewriteImplementationDecl(NamedDecl *OID) {
511 ObjcImplementationDecl *IMD = dyn_cast<ObjcImplementationDecl>(OID);
512 ObjcCategoryImplDecl *CID = dyn_cast<ObjcCategoryImplDecl>(OID);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000513
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000514 if (IMD)
515 Rewrite.InsertText(IMD->getLocStart(), "// ", 3);
516 else
517 Rewrite.InsertText(CID->getLocStart(), "// ", 3);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000518
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000519 int numMethods = IMD ? IMD->getNumInstanceMethods()
520 : CID->getNumInstanceMethods();
521
522 for (int i = 0; i < numMethods; i++) {
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000523 std::string ResultStr;
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000524 ObjcMethodDecl *OMD;
525 if (IMD)
526 OMD = IMD->getInstanceMethods()[i];
527 else
528 OMD = CID->getInstanceMethods()[i];
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000529 RewriteObjcMethodDecl(OMD, ResultStr);
530 SourceLocation LocStart = OMD->getLocStart();
531 SourceLocation LocEnd = OMD->getBody()->getLocStart();
532
533 const char *startBuf = SM->getCharacterData(LocStart);
534 const char *endBuf = SM->getCharacterData(LocEnd);
535 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
536 ResultStr.c_str(), ResultStr.size());
537 }
538
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000539 numMethods = IMD ? IMD->getNumClassMethods() : CID->getNumClassMethods();
540 for (int i = 0; i < numMethods; i++) {
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000541 std::string ResultStr;
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000542 ObjcMethodDecl *OMD;
543 if (IMD)
544 OMD = IMD->getClassMethods()[i];
545 else
546 OMD = CID->getClassMethods()[i];
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000547 RewriteObjcMethodDecl(OMD, ResultStr);
548 SourceLocation LocStart = OMD->getLocStart();
549 SourceLocation LocEnd = OMD->getBody()->getLocStart();
550
551 const char *startBuf = SM->getCharacterData(LocStart);
552 const char *endBuf = SM->getCharacterData(LocEnd);
553 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
554 ResultStr.c_str(), ResultStr.size());
555 }
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000556 if (IMD)
557 Rewrite.InsertText(IMD->getLocEnd(), "// ", 3);
558 else
559 Rewrite.InsertText(CID->getLocEnd(), "// ", 3);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000560}
561
Steve Naroffbef11852007-10-26 20:53:56 +0000562void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
Steve Narofff908a872007-10-30 02:23:23 +0000563 std::string ResultStr;
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000564 if (!ObjcForwardDecls.count(ClassDecl)) {
565 // we haven't seen a forward decl - generate a typedef.
Steve Naroff5086a8d2007-11-14 23:02:56 +0000566 ResultStr = "#ifndef _REWRITER_typedef_";
Steve Naroff32174822007-11-09 12:50:28 +0000567 ResultStr += ClassDecl->getName();
568 ResultStr += "\n";
569 ResultStr += "#define _REWRITER_typedef_";
570 ResultStr += ClassDecl->getName();
571 ResultStr += "\n";
Steve Naroff352336b2007-11-05 14:36:37 +0000572 ResultStr += "typedef struct objc_object ";
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000573 ResultStr += ClassDecl->getName();
Steve Naroff32174822007-11-09 12:50:28 +0000574 ResultStr += ";\n#endif\n";
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000575
576 // Mark this typedef as having been generated.
577 ObjcForwardDecls.insert(ClassDecl);
578 }
Steve Narofff908a872007-10-30 02:23:23 +0000579 SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
580
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000581 RewriteProperties(ClassDecl->getNumPropertyDecl(),
582 ClassDecl->getPropertyDecl());
Steve Naroff71c0a952007-11-13 23:01:27 +0000583 RewriteMethodDeclarations(ClassDecl->getNumInstanceMethods(),
584 ClassDecl->getInstanceMethods());
585 RewriteMethodDeclarations(ClassDecl->getNumClassMethods(),
586 ClassDecl->getClassMethods());
Steve Naroffbef11852007-10-26 20:53:56 +0000587
Steve Naroff2feac5e2007-10-30 03:43:13 +0000588 // Lastly, comment out the @end.
589 Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
Steve Naroffbef11852007-10-26 20:53:56 +0000590}
591
Steve Naroff7e3411b2007-11-15 02:58:25 +0000592Stmt *RewriteTest::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
593 ObjcIvarDecl *D = IV->getDecl();
594 if (IV->isFreeIvar()) {
595 Expr *Replacement = new MemberExpr(IV->getBase(), true, D,
596 IV->getLocation());
597 Rewrite.ReplaceStmt(IV, Replacement);
598 delete IV;
599 return Replacement;
Steve Naroffc2a689b2007-11-15 11:33:00 +0000600 } else {
601 if (CurMethodDecl) {
602 if (const PointerType *pType = IV->getBase()->getType()->getAsPointerType()) {
603 ObjcInterfaceType *intT = dyn_cast<ObjcInterfaceType>(pType->getPointeeType());
604 if (CurMethodDecl->getClassInterface() == intT->getDecl()) {
605 IdentifierInfo *II = intT->getDecl()->getIdentifier();
606 RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
607 II, 0);
608 QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
609
610 CastExpr *castExpr = new CastExpr(castT, IV->getBase(), SourceLocation());
611 // Don't forget the parens to enforce the proper binding.
612 ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), castExpr);
613 Rewrite.ReplaceStmt(IV->getBase(), PE);
614 delete IV->getBase();
615 return PE;
616 }
617 }
618 }
Steve Naroff7e3411b2007-11-15 02:58:25 +0000619 return IV;
Steve Naroffc2a689b2007-11-15 11:33:00 +0000620 }
Steve Naroff7e3411b2007-11-15 02:58:25 +0000621}
622
Chris Lattnerf04da132007-10-24 17:06:59 +0000623//===----------------------------------------------------------------------===//
624// Function Body / Expression rewriting
625//===----------------------------------------------------------------------===//
626
Steve Narofff3473a72007-11-09 15:20:18 +0000627Stmt *RewriteTest::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000628 // Otherwise, just rewrite all children.
629 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
630 CI != E; ++CI)
Steve Naroff75730982007-11-07 04:08:17 +0000631 if (*CI) {
Steve Narofff3473a72007-11-09 15:20:18 +0000632 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(*CI);
Steve Naroff75730982007-11-07 04:08:17 +0000633 if (newStmt)
634 *CI = newStmt;
635 }
Steve Naroffebf2b562007-10-23 23:50:29 +0000636
637 // Handle specific things.
638 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
639 return RewriteAtEncode(AtEncode);
Steve Naroff7e3411b2007-11-15 02:58:25 +0000640
641 if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S))
642 return RewriteObjCIvarRefExpr(IvarRefExpr);
Steve Naroffb42f8412007-11-05 14:50:49 +0000643
644 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
645 return RewriteAtSelector(AtSelector);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000646
647 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
648 return RewriteObjCStringLiteral(AtString);
Steve Naroffebf2b562007-10-23 23:50:29 +0000649
Steve Naroff934f2762007-10-24 22:48:43 +0000650 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
651 // Before we rewrite it, put the original message expression in a comment.
652 SourceLocation startLoc = MessExpr->getLocStart();
653 SourceLocation endLoc = MessExpr->getLocEnd();
654
655 const char *startBuf = SM->getCharacterData(startLoc);
656 const char *endBuf = SM->getCharacterData(endLoc);
657
658 std::string messString;
659 messString += "// ";
660 messString.append(startBuf, endBuf-startBuf+1);
661 messString += "\n";
Steve Naroffbef11852007-10-26 20:53:56 +0000662
Steve Naroff934f2762007-10-24 22:48:43 +0000663 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
664 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
665 // Tried this, but it didn't work either...
Steve Naroff752d6ef2007-10-30 16:42:30 +0000666 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000667 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000668 }
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000669
670 if (ObjcAtTryStmt *StmtTry = dyn_cast<ObjcAtTryStmt>(S))
671 return RewriteObjcTryStmt(StmtTry);
Steve Naroff2bd03922007-11-07 15:32:26 +0000672
673 if (ObjcAtThrowStmt *StmtThrow = dyn_cast<ObjcAtThrowStmt>(S))
674 return RewriteObjcThrowStmt(StmtThrow);
Steve Naroff874e2322007-11-15 10:28:18 +0000675#if 0
676 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
677 CastExpr *Replacement = new CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
678 // Get the new text.
679 std::ostringstream Buf;
680 Replacement->printPretty(Buf);
681 const std::string &Str = Buf.str();
682
683 printf("CAST = %s\n", &Str[0]);
684 Rewrite.InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
685 delete S;
686 return Replacement;
687 }
688#endif
Chris Lattnere64b7772007-10-24 16:57:36 +0000689 // Return this stmt unmodified.
690 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000691}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000692
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000693Stmt *RewriteTest::RewriteObjcTryStmt(ObjcAtTryStmt *S) {
Steve Naroff75730982007-11-07 04:08:17 +0000694 // Get the start location and compute the semi location.
695 SourceLocation startLoc = S->getLocStart();
696 const char *startBuf = SM->getCharacterData(startLoc);
697
698 assert((*startBuf == '@') && "bogus @try location");
699
700 std::string buf;
701 // declare a new scope with two variables, _stack and _rethrow.
702 buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
703 buf += "int buf[18/*32-bit i386*/];\n";
704 buf += "char *pointers[4];} _stack;\n";
705 buf += "id volatile _rethrow = 0;\n";
706 buf += "objc_exception_try_enter(&_stack);\n";
Steve Naroff21867b12007-11-07 18:43:40 +0000707 buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
Steve Naroff75730982007-11-07 04:08:17 +0000708
709 Rewrite.ReplaceText(startLoc, 4, buf.c_str(), buf.size());
710
711 startLoc = S->getTryBody()->getLocEnd();
712 startBuf = SM->getCharacterData(startLoc);
713
714 assert((*startBuf == '}') && "bogus @try block");
715
716 SourceLocation lastCurlyLoc = startLoc;
717
718 startLoc = startLoc.getFileLocWithOffset(1);
719 buf = " /* @catch begin */ else {\n";
720 buf += " id _caught = objc_exception_extract(&_stack);\n";
721 buf += " objc_exception_try_enter (&_stack);\n";
Steve Naroff21867b12007-11-07 18:43:40 +0000722 buf += " if (_setjmp(_stack.buf))\n";
Steve Naroff75730982007-11-07 04:08:17 +0000723 buf += " _rethrow = objc_exception_extract(&_stack);\n";
724 buf += " else { /* @catch continue */";
725
Chris Lattner28d1fe82007-11-08 04:41:51 +0000726 Rewrite.InsertText(startLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000727
728 bool sawIdTypedCatch = false;
729 Stmt *lastCatchBody = 0;
730 ObjcAtCatchStmt *catchList = S->getCatchStmts();
731 while (catchList) {
732 Stmt *catchStmt = catchList->getCatchParamStmt();
733
734 if (catchList == S->getCatchStmts())
735 buf = "if ("; // we are generating code for the first catch clause
736 else
737 buf = "else if (";
738 startLoc = catchList->getLocStart();
739 startBuf = SM->getCharacterData(startLoc);
740
741 assert((*startBuf == '@') && "bogus @catch location");
742
743 const char *lParenLoc = strchr(startBuf, '(');
744
745 if (DeclStmt *declStmt = dyn_cast<DeclStmt>(catchStmt)) {
746 QualType t = dyn_cast<ValueDecl>(declStmt->getDecl())->getType();
747 if (t == Context->getObjcIdType()) {
748 buf += "1) { ";
749 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
750 buf.c_str(), buf.size());
751 sawIdTypedCatch = true;
752 } else if (const PointerType *pType = t->getAsPointerType()) {
753 ObjcInterfaceType *cls; // Should be a pointer to a class.
754
755 cls = dyn_cast<ObjcInterfaceType>(pType->getPointeeType().getTypePtr());
756 if (cls) {
Steve Naroff21867b12007-11-07 18:43:40 +0000757 buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
Steve Naroff75730982007-11-07 04:08:17 +0000758 buf += cls->getDecl()->getName();
Steve Naroff21867b12007-11-07 18:43:40 +0000759 buf += "\"), (struct objc_object *)_caught)) { ";
Steve Naroff75730982007-11-07 04:08:17 +0000760 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
761 buf.c_str(), buf.size());
762 }
763 }
764 // Now rewrite the body...
765 lastCatchBody = catchList->getCatchBody();
766 SourceLocation rParenLoc = catchList->getRParenLoc();
767 SourceLocation bodyLoc = lastCatchBody->getLocStart();
768 const char *bodyBuf = SM->getCharacterData(bodyLoc);
769 const char *rParenBuf = SM->getCharacterData(rParenLoc);
770 assert((*rParenBuf == ')') && "bogus @catch paren location");
771 assert((*bodyBuf == '{') && "bogus @catch body location");
772
773 buf = " = _caught;";
774 // Here we replace ") {" with "= _caught;" (which initializes and
775 // declares the @catch parameter).
776 Rewrite.ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
777 buf.c_str(), buf.size());
Steve Naroff2bd03922007-11-07 15:32:26 +0000778 } else if (!isa<NullStmt>(catchStmt)) {
Steve Naroff75730982007-11-07 04:08:17 +0000779 assert(false && "@catch rewrite bug");
Steve Naroff2bd03922007-11-07 15:32:26 +0000780 }
Steve Naroff75730982007-11-07 04:08:17 +0000781 catchList = catchList->getNextCatchStmt();
782 }
783 // Complete the catch list...
784 if (lastCatchBody) {
785 SourceLocation bodyLoc = lastCatchBody->getLocEnd();
786 const char *bodyBuf = SM->getCharacterData(bodyLoc);
787 assert((*bodyBuf == '}') && "bogus @catch body location");
788 bodyLoc = bodyLoc.getFileLocWithOffset(1);
789 buf = " } } /* @catch end */\n";
790
Chris Lattner28d1fe82007-11-08 04:41:51 +0000791 Rewrite.InsertText(bodyLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000792
793 // Set lastCurlyLoc
794 lastCurlyLoc = lastCatchBody->getLocEnd();
795 }
796 if (ObjcAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
797 startLoc = finalStmt->getLocStart();
798 startBuf = SM->getCharacterData(startLoc);
799 assert((*startBuf == '@') && "bogus @finally start");
800
801 buf = "/* @finally */";
802 Rewrite.ReplaceText(startLoc, 8, buf.c_str(), buf.size());
803
804 Stmt *body = finalStmt->getFinallyBody();
805 SourceLocation startLoc = body->getLocStart();
806 SourceLocation endLoc = body->getLocEnd();
807 const char *startBuf = SM->getCharacterData(startLoc);
808 const char *endBuf = SM->getCharacterData(endLoc);
809 assert((*startBuf == '{') && "bogus @finally body location");
810 assert((*endBuf == '}') && "bogus @finally body location");
811
812 startLoc = startLoc.getFileLocWithOffset(1);
813 buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
Chris Lattner28d1fe82007-11-08 04:41:51 +0000814 Rewrite.InsertText(startLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000815 endLoc = endLoc.getFileLocWithOffset(-1);
816 buf = " if (_rethrow) objc_exception_throw(_rethrow);\n";
Chris Lattner28d1fe82007-11-08 04:41:51 +0000817 Rewrite.InsertText(endLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000818
819 // Set lastCurlyLoc
820 lastCurlyLoc = body->getLocEnd();
821 }
822 // Now emit the final closing curly brace...
823 lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
824 buf = " } /* @try scope end */\n";
Chris Lattner28d1fe82007-11-08 04:41:51 +0000825 Rewrite.InsertText(lastCurlyLoc, buf.c_str(), buf.size());
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000826 return 0;
827}
828
829Stmt *RewriteTest::RewriteObjcCatchStmt(ObjcAtCatchStmt *S) {
830 return 0;
831}
832
833Stmt *RewriteTest::RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S) {
834 return 0;
835}
836
Steve Naroff2bd03922007-11-07 15:32:26 +0000837// This can't be done with Rewrite.ReplaceStmt(S, ThrowExpr), since
838// the throw expression is typically a message expression that's already
839// been rewritten! (which implies the SourceLocation's are invalid).
840Stmt *RewriteTest::RewriteObjcThrowStmt(ObjcAtThrowStmt *S) {
841 // Get the start location and compute the semi location.
842 SourceLocation startLoc = S->getLocStart();
843 const char *startBuf = SM->getCharacterData(startLoc);
844
845 assert((*startBuf == '@') && "bogus @throw location");
846
847 std::string buf;
848 /* void objc_exception_throw(id) __attribute__((noreturn)); */
849 buf = "objc_exception_throw(";
850 Rewrite.ReplaceText(startLoc, 6, buf.c_str(), buf.size());
851 const char *semiBuf = strchr(startBuf, ';');
852 assert((*semiBuf == ';') && "@throw: can't find ';'");
853 SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
854 buf = ");";
855 Rewrite.ReplaceText(semiLoc, 1, buf.c_str(), buf.size());
856 return 0;
857}
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000858
Chris Lattnere64b7772007-10-24 16:57:36 +0000859Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000860 // Create a new string expression.
861 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson85f9bce2007-10-29 05:01:08 +0000862 std::string StrEncoding;
863 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
864 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
865 StrEncoding.length(), false, StrType,
Chris Lattner01c57482007-10-17 22:35:30 +0000866 SourceLocation(), SourceLocation());
Chris Lattnere365c502007-11-30 22:25:36 +0000867 if (Rewrite.ReplaceStmt(Exp, Replacement)) {
868 // replacement failed.
869 return Exp;
870 }
871
Chris Lattnere64b7772007-10-24 16:57:36 +0000872 delete Exp;
873 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000874}
875
Steve Naroffb42f8412007-11-05 14:50:49 +0000876Stmt *RewriteTest::RewriteAtSelector(ObjCSelectorExpr *Exp) {
877 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
878 // Create a call to sel_registerName("selName").
879 llvm::SmallVector<Expr*, 8> SelExprs;
880 QualType argType = Context->getPointerType(Context->CharTy);
881 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
882 Exp->getSelector().getName().size(),
883 false, argType, SourceLocation(),
884 SourceLocation()));
885 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
886 &SelExprs[0], SelExprs.size());
887 Rewrite.ReplaceStmt(Exp, SelExp);
888 delete Exp;
889 return SelExp;
890}
891
Steve Naroff934f2762007-10-24 22:48:43 +0000892CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
893 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000894 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000895 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000896
897 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000898 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000899
900 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000901 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000902 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
903
904 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000905
Steve Naroff934f2762007-10-24 22:48:43 +0000906 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
907}
908
Steve Naroffd5255f52007-11-01 13:24:47 +0000909static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
910 const char *&startRef, const char *&endRef) {
911 while (startBuf < endBuf) {
912 if (*startBuf == '<')
913 startRef = startBuf; // mark the start.
914 if (*startBuf == '>') {
Steve Naroff32174822007-11-09 12:50:28 +0000915 if (startRef && *startRef == '<') {
916 endRef = startBuf; // mark the end.
917 return true;
918 }
919 return false;
Steve Naroffd5255f52007-11-01 13:24:47 +0000920 }
921 startBuf++;
922 }
923 return false;
924}
925
926bool RewriteTest::needToScanForQualifiers(QualType T) {
927 // FIXME: we don't currently represent "id <Protocol>" in the type system.
928 if (T == Context->getObjcIdType())
929 return true;
930
931 if (const PointerType *pType = T->getAsPointerType()) {
Steve Naroff9165ad32007-10-31 04:38:33 +0000932 Type *pointeeType = pType->getPointeeType().getTypePtr();
933 if (isa<ObjcQualifiedInterfaceType>(pointeeType))
934 return true; // we have "Class <Protocol> *".
935 }
Steve Naroffd5255f52007-11-01 13:24:47 +0000936 return false;
937}
938
939void RewriteTest::RewriteObjcQualifiedInterfaceTypes(
940 const FunctionTypeProto *proto, FunctionDecl *FD) {
941
942 if (needToScanForQualifiers(proto->getResultType())) {
943 // Since types are unique, we need to scan the buffer.
944 SourceLocation Loc = FD->getLocation();
945
946 const char *endBuf = SM->getCharacterData(Loc);
947 const char *startBuf = endBuf;
948 while (*startBuf != ';')
949 startBuf--; // scan backward (from the decl location) for return type.
950 const char *startRef = 0, *endRef = 0;
951 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
952 // Get the locations of the startRef, endRef.
953 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
954 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
955 // Comment out the protocol references.
Chris Lattner28d1fe82007-11-08 04:41:51 +0000956 Rewrite.InsertText(LessLoc, "/*", 2);
957 Rewrite.InsertText(GreaterLoc, "*/", 2);
Steve Naroff9165ad32007-10-31 04:38:33 +0000958 }
959 }
Steve Naroffd5255f52007-11-01 13:24:47 +0000960 // Now check arguments.
961 for (unsigned i = 0; i < proto->getNumArgs(); i++) {
962 if (needToScanForQualifiers(proto->getArgType(i))) {
963 // Since types are unique, we need to scan the buffer.
964 SourceLocation Loc = FD->getLocation();
965
966 const char *startBuf = SM->getCharacterData(Loc);
967 const char *endBuf = startBuf;
968 while (*endBuf != ';')
969 endBuf++; // scan forward (from the decl location) for argument types.
970 const char *startRef = 0, *endRef = 0;
971 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
972 // Get the locations of the startRef, endRef.
973 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
974 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
975 // Comment out the protocol references.
Chris Lattner28d1fe82007-11-08 04:41:51 +0000976 Rewrite.InsertText(LessLoc, "/*", 2);
977 Rewrite.InsertText(GreaterLoc, "*/", 2);
Steve Naroffd5255f52007-11-01 13:24:47 +0000978 }
979 }
980 }
Steve Naroff9165ad32007-10-31 04:38:33 +0000981}
982
Steve Naroff09b266e2007-10-30 23:14:51 +0000983void RewriteTest::RewriteFunctionDecl(FunctionDecl *FD) {
984 // declared in <objc/objc.h>
Steve Naroffbeaf2992007-11-03 11:27:19 +0000985 if (strcmp(FD->getName(), "sel_registerName") == 0) {
Steve Naroff09b266e2007-10-30 23:14:51 +0000986 SelGetUidFunctionDecl = FD;
Steve Naroff9165ad32007-10-31 04:38:33 +0000987 return;
988 }
989 // Check for ObjC 'id' and class types that have been adorned with protocol
990 // information (id<p>, C<p>*). The protocol references need to be rewritten!
991 const FunctionType *funcType = FD->getType()->getAsFunctionType();
992 assert(funcType && "missing function type");
Steve Naroffd5255f52007-11-01 13:24:47 +0000993 if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcType))
994 RewriteObjcQualifiedInterfaceTypes(proto, FD);
Steve Naroff09b266e2007-10-30 23:14:51 +0000995}
996
997// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
998void RewriteTest::SynthMsgSendFunctionDecl() {
999 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
1000 llvm::SmallVector<QualType, 16> ArgTys;
1001 QualType argT = Context->getObjcIdType();
1002 assert(!argT.isNull() && "Can't find 'id' type");
1003 ArgTys.push_back(argT);
1004 argT = Context->getObjcSelType();
1005 assert(!argT.isNull() && "Can't find 'SEL' type");
1006 ArgTys.push_back(argT);
1007 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
1008 &ArgTys[0], ArgTys.size(),
1009 true /*isVariadic*/);
1010 MsgSendFunctionDecl = new FunctionDecl(SourceLocation(),
1011 msgSendIdent, msgSendType,
1012 FunctionDecl::Extern, false, 0);
1013}
1014
Steve Naroff874e2322007-11-15 10:28:18 +00001015// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
1016void RewriteTest::SynthMsgSendSuperFunctionDecl() {
1017 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
1018 llvm::SmallVector<QualType, 16> ArgTys;
1019 RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
1020 &Context->Idents.get("objc_super"), 0);
1021 QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
1022 assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
1023 ArgTys.push_back(argT);
1024 argT = Context->getObjcSelType();
1025 assert(!argT.isNull() && "Can't find 'SEL' type");
1026 ArgTys.push_back(argT);
1027 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
1028 &ArgTys[0], ArgTys.size(),
1029 true /*isVariadic*/);
1030 MsgSendSuperFunctionDecl = new FunctionDecl(SourceLocation(),
1031 msgSendIdent, msgSendType,
1032 FunctionDecl::Extern, false, 0);
1033}
1034
Steve Naroff09b266e2007-10-30 23:14:51 +00001035// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
1036void RewriteTest::SynthGetClassFunctionDecl() {
1037 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
1038 llvm::SmallVector<QualType, 16> ArgTys;
1039 ArgTys.push_back(Context->getPointerType(
1040 Context->CharTy.getQualifiedType(QualType::Const)));
1041 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
1042 &ArgTys[0], ArgTys.size(),
1043 false /*isVariadic*/);
1044 GetClassFunctionDecl = new FunctionDecl(SourceLocation(),
1045 getClassIdent, getClassType,
1046 FunctionDecl::Extern, false, 0);
1047}
1048
Steve Naroff96984642007-11-08 14:30:50 +00001049// SynthCFStringFunctionDecl - id __builtin___CFStringMakeConstantString(const char *name);
1050void RewriteTest::SynthCFStringFunctionDecl() {
1051 IdentifierInfo *getClassIdent = &Context->Idents.get("__builtin___CFStringMakeConstantString");
1052 llvm::SmallVector<QualType, 16> ArgTys;
1053 ArgTys.push_back(Context->getPointerType(
1054 Context->CharTy.getQualifiedType(QualType::Const)));
1055 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
1056 &ArgTys[0], ArgTys.size(),
1057 false /*isVariadic*/);
1058 CFStringFunctionDecl = new FunctionDecl(SourceLocation(),
1059 getClassIdent, getClassType,
1060 FunctionDecl::Extern, false, 0);
1061}
1062
Steve Naroffbeaf2992007-11-03 11:27:19 +00001063Stmt *RewriteTest::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
Steve Naroff96984642007-11-08 14:30:50 +00001064#if 1
1065 // This rewrite is specific to GCC, which has builtin support for CFString.
1066 if (!CFStringFunctionDecl)
1067 SynthCFStringFunctionDecl();
1068 // Create a call to __builtin___CFStringMakeConstantString("cstr").
1069 llvm::SmallVector<Expr*, 8> StrExpr;
1070 StrExpr.push_back(Exp->getString());
1071 CallExpr *call = SynthesizeCallToFunctionDecl(CFStringFunctionDecl,
1072 &StrExpr[0], StrExpr.size());
1073 // cast to NSConstantString *
1074 CastExpr *cast = new CastExpr(Exp->getType(), call, SourceLocation());
1075 Rewrite.ReplaceStmt(Exp, cast);
1076 delete Exp;
1077 return cast;
1078#else
Steve Naroffbeaf2992007-11-03 11:27:19 +00001079 assert(ConstantStringClassReference && "Can't find constant string reference");
1080 llvm::SmallVector<Expr*, 4> InitExprs;
1081
1082 // Synthesize "(Class)&_NSConstantStringClassReference"
1083 DeclRefExpr *ClsRef = new DeclRefExpr(ConstantStringClassReference,
1084 ConstantStringClassReference->getType(),
1085 SourceLocation());
1086 QualType expType = Context->getPointerType(ClsRef->getType());
1087 UnaryOperator *Unop = new UnaryOperator(ClsRef, UnaryOperator::AddrOf,
1088 expType, SourceLocation());
1089 CastExpr *cast = new CastExpr(Context->getObjcClassType(), Unop,
1090 SourceLocation());
1091 InitExprs.push_back(cast); // set the 'isa'.
1092 InitExprs.push_back(Exp->getString()); // set "char *bytes".
1093 unsigned IntSize = static_cast<unsigned>(
1094 Context->getTypeSize(Context->IntTy, Exp->getLocStart()));
1095 llvm::APInt IntVal(IntSize, Exp->getString()->getByteLength());
1096 IntegerLiteral *len = new IntegerLiteral(IntVal, Context->IntTy,
1097 Exp->getLocStart());
1098 InitExprs.push_back(len); // set "int numBytes".
1099
1100 // struct NSConstantString
1101 QualType CFConstantStrType = Context->getCFConstantStringType();
1102 // (struct NSConstantString) { <exprs from above> }
1103 InitListExpr *ILE = new InitListExpr(SourceLocation(),
1104 &InitExprs[0], InitExprs.size(),
1105 SourceLocation());
1106 CompoundLiteralExpr *StrRep = new CompoundLiteralExpr(CFConstantStrType, ILE);
1107 // struct NSConstantString *
1108 expType = Context->getPointerType(StrRep->getType());
1109 Unop = new UnaryOperator(StrRep, UnaryOperator::AddrOf, expType,
1110 SourceLocation());
Steve Naroff352336b2007-11-05 14:36:37 +00001111 // cast to NSConstantString *
1112 cast = new CastExpr(Exp->getType(), Unop, SourceLocation());
Steve Naroffbeaf2992007-11-03 11:27:19 +00001113 Rewrite.ReplaceStmt(Exp, cast);
1114 delete Exp;
Steve Naroff352336b2007-11-05 14:36:37 +00001115 return cast;
Steve Naroff96984642007-11-08 14:30:50 +00001116#endif
Steve Naroffbeaf2992007-11-03 11:27:19 +00001117}
1118
Steve Naroff874e2322007-11-15 10:28:18 +00001119ObjcInterfaceDecl *RewriteTest::isSuperReceiver(Expr *recExpr) {
1120 if (CurMethodDecl) { // check if we are sending a message to 'super'
1121 if (CastExpr *CE = dyn_cast<CastExpr>(recExpr)) {
1122 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
1123 if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
1124 if (!strcmp(PVD->getName(), "self")) {
1125 if (const PointerType *PT = CE->getType()->getAsPointerType()) {
1126 if (ObjcInterfaceType *IT =
1127 dyn_cast<ObjcInterfaceType>(PT->getPointeeType())) {
1128 if (IT->getDecl() ==
1129 CurMethodDecl->getClassInterface()->getSuperClass())
1130 return IT->getDecl();
1131 }
1132 }
1133 }
1134 }
1135 }
1136 }
1137 }
1138 return 0;
1139}
1140
1141// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
1142QualType RewriteTest::getSuperStructType() {
1143 if (!SuperStructDecl) {
1144 SuperStructDecl = new RecordDecl(Decl::Struct, SourceLocation(),
1145 &Context->Idents.get("objc_super"), 0);
1146 QualType FieldTypes[2];
1147
1148 // struct objc_object *receiver;
1149 FieldTypes[0] = Context->getObjcIdType();
1150 // struct objc_class *super;
1151 FieldTypes[1] = Context->getObjcClassType();
1152 // Create fields
1153 FieldDecl *FieldDecls[2];
1154
1155 for (unsigned i = 0; i < 2; ++i)
1156 FieldDecls[i] = new FieldDecl(SourceLocation(), 0, FieldTypes[i]);
1157
1158 SuperStructDecl->defineBody(FieldDecls, 4);
1159 }
1160 return Context->getTagDeclType(SuperStructDecl);
1161}
1162
Steve Naroff934f2762007-10-24 22:48:43 +00001163Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Steve Naroffbeaf2992007-11-03 11:27:19 +00001164 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
Steve Naroff09b266e2007-10-30 23:14:51 +00001165 if (!MsgSendFunctionDecl)
1166 SynthMsgSendFunctionDecl();
Steve Naroff874e2322007-11-15 10:28:18 +00001167 if (!MsgSendSuperFunctionDecl)
1168 SynthMsgSendSuperFunctionDecl();
Steve Naroff09b266e2007-10-30 23:14:51 +00001169 if (!GetClassFunctionDecl)
1170 SynthGetClassFunctionDecl();
Steve Naroff934f2762007-10-24 22:48:43 +00001171
Steve Naroff874e2322007-11-15 10:28:18 +00001172 // default to objc_msgSend().
1173 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
1174
Steve Naroff934f2762007-10-24 22:48:43 +00001175 // Synthesize a call to objc_msgSend().
1176 llvm::SmallVector<Expr*, 8> MsgExprs;
1177 IdentifierInfo *clsName = Exp->getClassName();
1178
1179 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
1180 if (clsName) { // class message.
1181 llvm::SmallVector<Expr*, 8> ClsExprs;
1182 QualType argType = Context->getPointerType(Context->CharTy);
1183 ClsExprs.push_back(new StringLiteral(clsName->getName(),
1184 clsName->getLength(),
1185 false, argType, SourceLocation(),
1186 SourceLocation()));
1187 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
1188 &ClsExprs[0], ClsExprs.size());
1189 MsgExprs.push_back(Cls);
Steve Naroff6568d4d2007-11-14 23:54:14 +00001190 } else { // instance message.
1191 Expr *recExpr = Exp->getReceiver();
Steve Naroff874e2322007-11-15 10:28:18 +00001192
1193 if (ObjcInterfaceDecl *ID = isSuperReceiver(recExpr)) {
1194 MsgSendFlavor = MsgSendSuperFunctionDecl;
1195 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
1196
1197 llvm::SmallVector<Expr*, 4> InitExprs;
1198
1199 InitExprs.push_back(recExpr); // set the 'receiver'.
1200
1201 llvm::SmallVector<Expr*, 8> ClsExprs;
1202 QualType argType = Context->getPointerType(Context->CharTy);
1203 ClsExprs.push_back(new StringLiteral(ID->getIdentifier()->getName(),
1204 ID->getIdentifier()->getLength(),
1205 false, argType, SourceLocation(),
1206 SourceLocation()));
1207 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
1208 &ClsExprs[0], ClsExprs.size());
1209 InitExprs.push_back(Cls); // set 'super class', using objc_getClass().
1210 // struct objc_super
1211 QualType superType = getSuperStructType();
1212 // (struct objc_super) { <exprs from above> }
1213 InitListExpr *ILE = new InitListExpr(SourceLocation(),
1214 &InitExprs[0], InitExprs.size(),
1215 SourceLocation());
1216 CompoundLiteralExpr *SuperRep = new CompoundLiteralExpr(superType, ILE);
1217 // struct objc_super *
1218 Expr *Unop = new UnaryOperator(SuperRep, UnaryOperator::AddrOf,
1219 Context->getPointerType(SuperRep->getType()),
1220 SourceLocation());
1221 MsgExprs.push_back(Unop);
1222 } else {
1223 recExpr = new CastExpr(Context->getObjcIdType(), recExpr, SourceLocation());
1224 MsgExprs.push_back(recExpr);
1225 }
Steve Naroff6568d4d2007-11-14 23:54:14 +00001226 }
Steve Naroffbeaf2992007-11-03 11:27:19 +00001227 // Create a call to sel_registerName("selName"), it will be the 2nd argument.
Steve Naroff934f2762007-10-24 22:48:43 +00001228 llvm::SmallVector<Expr*, 8> SelExprs;
1229 QualType argType = Context->getPointerType(Context->CharTy);
1230 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
1231 Exp->getSelector().getName().size(),
1232 false, argType, SourceLocation(),
1233 SourceLocation()));
1234 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
1235 &SelExprs[0], SelExprs.size());
1236 MsgExprs.push_back(SelExp);
1237
1238 // Now push any user supplied arguments.
1239 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
Steve Naroff6568d4d2007-11-14 23:54:14 +00001240 Expr *userExpr = Exp->getArg(i);
Steve Naroff7e3411b2007-11-15 02:58:25 +00001241 // Make all implicit casts explicit...ICE comes in handy:-)
1242 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
1243 // Reuse the ICE type, it is exactly what the doctor ordered.
1244 userExpr = new CastExpr(ICE->getType(), userExpr, SourceLocation());
1245 }
Steve Naroff6568d4d2007-11-14 23:54:14 +00001246 MsgExprs.push_back(userExpr);
Steve Naroff934f2762007-10-24 22:48:43 +00001247 // We've transferred the ownership to MsgExprs. Null out the argument in
1248 // the original expression, since we will delete it below.
1249 Exp->setArg(i, 0);
1250 }
Steve Naroffab972d32007-11-04 22:37:50 +00001251 // Generate the funky cast.
1252 CastExpr *cast;
1253 llvm::SmallVector<QualType, 8> ArgTypes;
1254 QualType returnType;
1255
1256 // Push 'id' and 'SEL', the 2 implicit arguments.
Steve Naroffc3a438c2007-11-15 10:43:57 +00001257 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
1258 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
1259 else
1260 ArgTypes.push_back(Context->getObjcIdType());
Steve Naroffab972d32007-11-04 22:37:50 +00001261 ArgTypes.push_back(Context->getObjcSelType());
1262 if (ObjcMethodDecl *mDecl = Exp->getMethodDecl()) {
1263 // Push any user argument types.
Steve Naroff352336b2007-11-05 14:36:37 +00001264 for (int i = 0; i < mDecl->getNumParams(); i++) {
1265 QualType t = mDecl->getParamDecl(i)->getType();
Steve Naroff352336b2007-11-05 14:36:37 +00001266 ArgTypes.push_back(t);
1267 }
Steve Naroffab972d32007-11-04 22:37:50 +00001268 returnType = mDecl->getResultType();
1269 } else {
1270 returnType = Context->getObjcIdType();
1271 }
1272 // Get the type, we will need to reference it in a couple spots.
Steve Naroff874e2322007-11-15 10:28:18 +00001273 QualType msgSendType = MsgSendFlavor->getType();
Steve Naroffab972d32007-11-04 22:37:50 +00001274
1275 // Create a reference to the objc_msgSend() declaration.
Steve Naroff874e2322007-11-15 10:28:18 +00001276 DeclRefExpr *DRE = new DeclRefExpr(MsgSendFlavor, msgSendType, SourceLocation());
Steve Naroffab972d32007-11-04 22:37:50 +00001277
1278 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
1279 // If we don't do this cast, we get the following bizarre warning/note:
1280 // xx.m:13: warning: function called through a non-compatible type
1281 // xx.m:13: note: if this code is reached, the program will abort
1282 cast = new CastExpr(Context->getPointerType(Context->VoidTy), DRE,
1283 SourceLocation());
Steve Naroff335eafa2007-11-15 12:35:21 +00001284
Steve Naroffab972d32007-11-04 22:37:50 +00001285 // Now do the "normal" pointer to function cast.
1286 QualType castType = Context->getFunctionType(returnType,
1287 &ArgTypes[0], ArgTypes.size(),
Steve Naroff335eafa2007-11-15 12:35:21 +00001288 Exp->getMethodDecl()->isVariadic());
Steve Naroffab972d32007-11-04 22:37:50 +00001289 castType = Context->getPointerType(castType);
1290 cast = new CastExpr(castType, cast, SourceLocation());
1291
1292 // Don't forget the parens to enforce the proper binding.
1293 ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
1294
1295 const FunctionType *FT = msgSendType->getAsFunctionType();
1296 CallExpr *CE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(),
1297 FT->getResultType(), SourceLocation());
Steve Naroff934f2762007-10-24 22:48:43 +00001298 // Now do the actual rewrite.
Steve Naroffab972d32007-11-04 22:37:50 +00001299 Rewrite.ReplaceStmt(Exp, CE);
Steve Naroff934f2762007-10-24 22:48:43 +00001300
Chris Lattnere64b7772007-10-24 16:57:36 +00001301 delete Exp;
Steve Naroffab972d32007-11-04 22:37:50 +00001302 return CE;
Steve Naroffebf2b562007-10-23 23:50:29 +00001303}
1304
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001305/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
1306/// an objective-c class with ivars.
1307void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
1308 std::string &Result) {
1309 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
1310 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
Fariborz Jahanian212b7682007-10-31 23:08:24 +00001311 // Do not synthesize more than once.
1312 if (ObjcSynthesizedStructs.count(CDecl))
1313 return;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001314 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
1315 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
1316 // Do it for the root
1317 SynthesizeObjcInternalStruct(RCDecl, Result);
1318 }
1319
Steve Naroff03300712007-11-12 13:56:41 +00001320 int NumIvars = CDecl->getNumInstanceVariables();
Steve Narofffea763e82007-11-14 19:25:57 +00001321 SourceLocation LocStart = CDecl->getLocStart();
1322 SourceLocation LocEnd = CDecl->getLocEnd();
1323
1324 const char *startBuf = SM->getCharacterData(LocStart);
1325 const char *endBuf = SM->getCharacterData(LocEnd);
Fariborz Jahanian2c7038b2007-11-26 19:52:57 +00001326 // If no ivars and no root or if its root, directly or indirectly,
1327 // have no ivars (thus not synthesized) then no need to synthesize this class.
1328 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl))) {
Fariborz Jahanian2c7038b2007-11-26 19:52:57 +00001329 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
1330 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
1331 Result.c_str(), Result.size());
1332 return;
1333 }
1334
1335 // FIXME: This has potential of causing problem. If
1336 // SynthesizeObjcInternalStruct is ever called recursively.
1337 Result += "\nstruct ";
1338 Result += CDecl->getName();
Steve Narofffea763e82007-11-14 19:25:57 +00001339
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001340 if (NumIvars > 0) {
Steve Narofffea763e82007-11-14 19:25:57 +00001341 const char *cursor = strchr(startBuf, '{');
1342 assert((cursor && endBuf)
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001343 && "SynthesizeObjcInternalStruct - malformed @interface");
Steve Narofffea763e82007-11-14 19:25:57 +00001344
1345 // rewrite the original header *without* disturbing the '{'
1346 Rewrite.ReplaceText(LocStart, cursor-startBuf-1,
1347 Result.c_str(), Result.size());
1348 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
1349 Result = "\n struct ";
1350 Result += RCDecl->getName();
1351 Result += " _";
1352 Result += RCDecl->getName();
1353 Result += ";\n";
1354
1355 // insert the super class structure definition.
1356 SourceLocation OnePastCurly = LocStart.getFileLocWithOffset(cursor-startBuf+1);
1357 Rewrite.InsertText(OnePastCurly, Result.c_str(), Result.size());
1358 }
1359 cursor++; // past '{'
1360
1361 // Now comment out any visibility specifiers.
1362 while (cursor < endBuf) {
1363 if (*cursor == '@') {
1364 SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
Chris Lattnerdf6a51b2007-11-14 22:57:51 +00001365 // Skip whitespace.
1366 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
1367 /*scan*/;
1368
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001369 // FIXME: presence of @public, etc. inside comment results in
1370 // this transformation as well, which is still correct c-code.
Steve Narofffea763e82007-11-14 19:25:57 +00001371 if (!strncmp(cursor, "public", strlen("public")) ||
1372 !strncmp(cursor, "private", strlen("private")) ||
Fariborz Jahanian95673922007-11-14 22:26:25 +00001373 !strncmp(cursor, "protected", strlen("protected")))
Steve Narofffea763e82007-11-14 19:25:57 +00001374 Rewrite.InsertText(atLoc, "// ", 3);
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001375 }
Fariborz Jahanian95673922007-11-14 22:26:25 +00001376 // FIXME: If there are cases where '<' is used in ivar declaration part
1377 // of user code, then scan the ivar list and use needToScanForQualifiers
1378 // for type checking.
1379 else if (*cursor == '<') {
1380 SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
1381 Rewrite.InsertText(atLoc, "/* ", 3);
1382 cursor = strchr(cursor, '>');
1383 cursor++;
1384 atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
1385 Rewrite.InsertText(atLoc, " */", 3);
1386 }
Steve Narofffea763e82007-11-14 19:25:57 +00001387 cursor++;
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001388 }
Steve Narofffea763e82007-11-14 19:25:57 +00001389 // Don't forget to add a ';'!!
1390 Rewrite.InsertText(LocEnd.getFileLocWithOffset(1), ";", 1);
1391 } else { // we don't have any instance variables - insert super struct.
1392 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
1393 Result += " {\n struct ";
1394 Result += RCDecl->getName();
1395 Result += " _";
1396 Result += RCDecl->getName();
1397 Result += ";\n};\n";
1398 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
1399 Result.c_str(), Result.size());
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001400 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001401 // Mark this struct as having been generated.
1402 if (!ObjcSynthesizedStructs.insert(CDecl))
Fariborz Jahanianaff56d02007-10-31 22:57:04 +00001403 assert(false && "struct already synthesize- SynthesizeObjcInternalStruct");
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001404}
1405
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001406// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
1407/// class methods.
Steve Naroff0416fb92007-11-11 17:19:15 +00001408void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001409 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001410 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001411 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +00001412 const char *ClassName,
1413 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001414 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001415 if (NumMethods > 0 && !objc_impl_method) {
1416 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001417 SEL _cmd;
1418 char *method_types;
1419 void *_imp;
1420 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001421 */
Chris Lattner158ecb92007-10-25 17:07:24 +00001422 Result += "\nstruct _objc_method {\n";
1423 Result += "\tSEL _cmd;\n";
1424 Result += "\tchar *method_types;\n";
1425 Result += "\tvoid *_imp;\n";
1426 Result += "};\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001427
1428 /* struct _objc_method_list {
1429 struct _objc_method_list *next_method;
1430 int method_count;
1431 struct _objc_method method_list[];
1432 }
1433 */
1434 Result += "\nstruct _objc_method_list {\n";
1435 Result += "\tstruct _objc_method_list *next_method;\n";
1436 Result += "\tint method_count;\n";
1437 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001438 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +00001439 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001440 // Build _objc_method_list for class's methods if needed
1441 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001442 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattner158ecb92007-10-25 17:07:24 +00001443 Result += prefix;
1444 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
1445 Result += "_METHODS_";
1446 Result += ClassName;
1447 Result += " __attribute__ ((section (\"__OBJC, __";
1448 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001449 Result += "_meth\")))= ";
1450 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
1451
1452 Result += "\t,{{(SEL)\"";
1453 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001454 std::string MethodTypeString;
1455 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
1456 Result += "\", \"";
1457 Result += MethodTypeString;
Fariborz Jahanianb7908b52007-11-13 21:02:00 +00001458 Result += "\", ";
1459 Result += MethodInternalNames[Methods[0]];
1460 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001461 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001462 Result += "\t ,{(SEL)\"";
1463 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001464 std::string MethodTypeString;
1465 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1466 Result += "\", \"";
1467 Result += MethodTypeString;
Fariborz Jahanianb7908b52007-11-13 21:02:00 +00001468 Result += "\", ";
1469 Result += MethodInternalNames[Methods[i]];
1470 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001471 }
1472 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001473 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001474}
1475
1476/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
1477void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
1478 int NumProtocols,
1479 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001480 const char *ClassName,
1481 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001482 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001483 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001484 for (int i = 0; i < NumProtocols; i++) {
1485 ObjcProtocolDecl *PDecl = Protocols[i];
1486 // Output struct protocol_methods holder of method selector and type.
1487 if (!objc_protocol_methods &&
1488 (PDecl->getNumInstanceMethods() > 0
1489 || PDecl->getNumClassMethods() > 0)) {
1490 /* struct protocol_methods {
1491 SEL _cmd;
1492 char *method_types;
1493 }
1494 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001495 Result += "\nstruct protocol_methods {\n";
1496 Result += "\tSEL _cmd;\n";
1497 Result += "\tchar *method_types;\n";
1498 Result += "};\n";
1499
1500 /* struct _objc_protocol_method_list {
1501 int protocol_method_count;
1502 struct protocol_methods protocols[];
1503 }
1504 */
1505 Result += "\nstruct _objc_protocol_method_list {\n";
1506 Result += "\tint protocol_method_count;\n";
1507 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001508 objc_protocol_methods = true;
1509 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001510
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001511 // Output instance methods declared in this protocol.
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001512 int NumMethods = PDecl->getNumInstanceMethods();
1513 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001514 Result += "\nstatic struct _objc_protocol_method_list "
1515 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
1516 Result += PDecl->getName();
1517 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
1518 "{\n\t" + utostr(NumMethods) + "\n";
1519
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001520 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001521 Result += "\t,{{(SEL)\"";
1522 Result += Methods[0]->getSelector().getName().c_str();
1523 Result += "\", \"\"}\n";
1524
1525 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001526 Result += "\t ,{(SEL)\"";
1527 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001528 std::string MethodTypeString;
1529 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1530 Result += "\", \"";
1531 Result += MethodTypeString;
1532 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001533 }
1534 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001535 }
1536
1537 // Output class methods declared in this protocol.
1538 NumMethods = PDecl->getNumClassMethods();
1539 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001540 Result += "\nstatic struct _objc_protocol_method_list "
1541 "_OBJC_PROTOCOL_CLASS_METHODS_";
1542 Result += PDecl->getName();
1543 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1544 "{\n\t";
1545 Result += utostr(NumMethods);
1546 Result += "\n";
1547
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001548 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001549 Result += "\t,{{(SEL)\"";
1550 Result += Methods[0]->getSelector().getName().c_str();
1551 Result += "\", \"\"}\n";
1552
1553 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001554 Result += "\t ,{(SEL)\"";
1555 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001556 std::string MethodTypeString;
1557 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1558 Result += "\", \"";
1559 Result += MethodTypeString;
1560 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001561 }
1562 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001563 }
1564 // Output:
1565 /* struct _objc_protocol {
1566 // Objective-C 1.0 extensions
1567 struct _objc_protocol_extension *isa;
1568 char *protocol_name;
1569 struct _objc_protocol **protocol_list;
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001570 struct _objc_protocol_method_list *instance_methods;
1571 struct _objc_protocol_method_list *class_methods;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001572 };
1573 */
1574 static bool objc_protocol = false;
1575 if (!objc_protocol) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001576 Result += "\nstruct _objc_protocol {\n";
1577 Result += "\tstruct _objc_protocol_extension *isa;\n";
1578 Result += "\tchar *protocol_name;\n";
1579 Result += "\tstruct _objc_protocol **protocol_list;\n";
1580 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
1581 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
1582 Result += "};\n";
1583
1584 /* struct _objc_protocol_list {
1585 struct _objc_protocol_list *next;
1586 int protocol_count;
1587 struct _objc_protocol *class_protocols[];
1588 }
1589 */
1590 Result += "\nstruct _objc_protocol_list {\n";
1591 Result += "\tstruct _objc_protocol_list *next;\n";
1592 Result += "\tint protocol_count;\n";
1593 Result += "\tstruct _objc_protocol *class_protocols[];\n";
1594 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001595 objc_protocol = true;
1596 }
1597
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001598 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
1599 Result += PDecl->getName();
1600 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
1601 "{\n\t0, \"";
1602 Result += PDecl->getName();
1603 Result += "\", 0, ";
1604 if (PDecl->getInstanceMethods() > 0) {
1605 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
1606 Result += PDecl->getName();
1607 Result += ", ";
1608 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001609 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001610 Result += "0, ";
1611 if (PDecl->getClassMethods() > 0) {
1612 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
1613 Result += PDecl->getName();
1614 Result += "\n";
1615 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001616 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001617 Result += "0\n";
1618 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001619 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001620 // Output the top lovel protocol meta-data for the class.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001621 Result += "\nstatic struct _objc_protocol_list _OBJC_";
1622 Result += prefix;
1623 Result += "_PROTOCOLS_";
1624 Result += ClassName;
1625 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1626 "{\n\t0, ";
1627 Result += utostr(NumProtocols);
1628 Result += "\n";
1629
1630 Result += "\t,{&_OBJC_PROTOCOL_";
1631 Result += Protocols[0]->getName();
1632 Result += " \n";
1633
1634 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001635 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001636 Result += "\t ,&_OBJC_PROTOCOL_";
1637 Result += PDecl->getName();
1638 Result += "\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001639 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001640 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001641 }
1642}
1643
1644/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
1645/// implementation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001646void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
1647 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001648 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
1649 // Find category declaration for this implementation.
1650 ObjcCategoryDecl *CDecl;
1651 for (CDecl = ClassDecl->getCategoryList(); CDecl;
1652 CDecl = CDecl->getNextClassCategory())
1653 if (CDecl->getIdentifier() == IDecl->getIdentifier())
1654 break;
Fariborz Jahanianbac97d42007-11-13 22:09:49 +00001655
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001656 char *FullCategoryName = (char*)alloca(
1657 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
1658 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
1659
1660 // Build _objc_method_list for class's instance methods if needed
1661 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1662 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001663 true,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001664 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001665
1666 // Build _objc_method_list for class's class methods if needed
1667 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
1668 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001669 false,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001670 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001671
1672 // Protocols referenced in class declaration?
Fariborz Jahanianbac97d42007-11-13 22:09:49 +00001673 // Null CDecl is case of a category implementation with no category interface
1674 if (CDecl)
1675 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1676 CDecl->getNumReferencedProtocols(),
1677 "CATEGORY",
1678 FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001679
1680 /* struct _objc_category {
1681 char *category_name;
1682 char *class_name;
1683 struct _objc_method_list *instance_methods;
1684 struct _objc_method_list *class_methods;
1685 struct _objc_protocol_list *protocols;
1686 // Objective-C 1.0 extensions
1687 uint32_t size; // sizeof (struct _objc_category)
1688 struct _objc_property_list *instance_properties; // category's own
1689 // @property decl.
1690 };
1691 */
1692
1693 static bool objc_category = false;
1694 if (!objc_category) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001695 Result += "\nstruct _objc_category {\n";
1696 Result += "\tchar *category_name;\n";
1697 Result += "\tchar *class_name;\n";
1698 Result += "\tstruct _objc_method_list *instance_methods;\n";
1699 Result += "\tstruct _objc_method_list *class_methods;\n";
1700 Result += "\tstruct _objc_protocol_list *protocols;\n";
1701 Result += "\tunsigned int size;\n";
1702 Result += "\tstruct _objc_property_list *instance_properties;\n";
1703 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001704 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001705 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001706 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
1707 Result += FullCategoryName;
1708 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
1709 Result += IDecl->getName();
1710 Result += "\"\n\t, \"";
1711 Result += ClassDecl->getName();
1712 Result += "\"\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001713
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001714 if (IDecl->getNumInstanceMethods() > 0) {
1715 Result += "\t, (struct _objc_method_list *)"
1716 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
1717 Result += FullCategoryName;
1718 Result += "\n";
1719 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001720 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001721 Result += "\t, 0\n";
1722 if (IDecl->getNumClassMethods() > 0) {
1723 Result += "\t, (struct _objc_method_list *)"
1724 "&_OBJC_CATEGORY_CLASS_METHODS_";
1725 Result += FullCategoryName;
1726 Result += "\n";
1727 }
1728 else
1729 Result += "\t, 0\n";
1730
Fariborz Jahanianbac97d42007-11-13 22:09:49 +00001731 if (CDecl && CDecl->getNumReferencedProtocols() > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001732 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
1733 Result += FullCategoryName;
1734 Result += "\n";
1735 }
1736 else
1737 Result += "\t, 0\n";
1738 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001739}
1740
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001741/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
1742/// ivar offset.
1743void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
1744 ObjcIvarDecl *ivar,
1745 std::string &Result) {
Fariborz Jahanian909f02a2007-11-05 17:47:33 +00001746 Result += "offsetof(struct ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001747 Result += IDecl->getName();
1748 Result += ", ";
1749 Result += ivar->getName();
1750 Result += ")";
1751}
1752
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001753//===----------------------------------------------------------------------===//
1754// Meta Data Emission
1755//===----------------------------------------------------------------------===//
1756
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001757void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
1758 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001759 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
1760
1761 // Build _objc_ivar_list metadata for classes ivars if needed
1762 int NumIvars = IDecl->getImplDeclNumIvars() > 0
1763 ? IDecl->getImplDeclNumIvars()
Steve Naroff03300712007-11-12 13:56:41 +00001764 : (CDecl ? CDecl->getNumInstanceVariables() : 0);
Fariborz Jahanianebe668f2007-11-26 20:59:57 +00001765 // Explictly declared @interface's are already synthesized.
1766 if (CDecl->ImplicitInterfaceDecl()) {
1767 // FIXME: Implementation of a class with no @interface (legacy) doese not
1768 // produce correct synthesis as yet.
1769 SynthesizeObjcInternalStruct(CDecl, Result);
1770 }
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001771
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001772 if (NumIvars > 0) {
1773 static bool objc_ivar = false;
1774 if (!objc_ivar) {
1775 /* struct _objc_ivar {
1776 char *ivar_name;
1777 char *ivar_type;
1778 int ivar_offset;
1779 };
1780 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001781 Result += "\nstruct _objc_ivar {\n";
1782 Result += "\tchar *ivar_name;\n";
1783 Result += "\tchar *ivar_type;\n";
1784 Result += "\tint ivar_offset;\n";
1785 Result += "};\n";
1786
1787 /* struct _objc_ivar_list {
1788 int ivar_count;
1789 struct _objc_ivar ivar_list[];
1790 };
1791 */
1792 Result += "\nstruct _objc_ivar_list {\n";
1793 Result += "\tint ivar_count;\n";
1794 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001795 objc_ivar = true;
1796 }
1797
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001798 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
1799 Result += IDecl->getName();
1800 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
1801 "{\n\t";
1802 Result += utostr(NumIvars);
1803 Result += "\n";
1804
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001805 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
1806 ? IDecl->getImplDeclIVars()
Steve Naroff03300712007-11-12 13:56:41 +00001807 : CDecl->getInstanceVariables();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001808 Result += "\t,{{\"";
1809 Result += Ivars[0]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00001810 Result += "\", \"";
1811 std::string StrEncoding;
1812 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
1813 Result += StrEncoding;
1814 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001815 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
1816 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001817 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001818 Result += "\t ,{\"";
1819 Result += Ivars[i]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00001820 Result += "\", \"";
1821 std::string StrEncoding;
1822 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
1823 Result += StrEncoding;
1824 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001825 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
1826 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001827 }
1828
1829 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001830 }
1831
1832 // Build _objc_method_list for class's instance methods if needed
1833 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1834 IDecl->getNumInstanceMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001835 true,
1836 "", IDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001837
1838 // Build _objc_method_list for class's class methods if needed
1839 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001840 IDecl->getNumClassMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001841 false,
1842 "", IDecl->getName(), Result);
1843
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001844 // Protocols referenced in class declaration?
1845 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1846 CDecl->getNumIntfRefProtocols(),
1847 "CLASS",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001848 CDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001849
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001850
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001851 // Declaration of class/meta-class metadata
1852 /* struct _objc_class {
1853 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001854 const char *super_class_name;
1855 char *name;
1856 long version;
1857 long info;
1858 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001859 struct _objc_ivar_list *ivars;
1860 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001861 struct objc_cache *cache;
1862 struct objc_protocol_list *protocols;
1863 const char *ivar_layout;
1864 struct _objc_class_ext *ext;
1865 };
1866 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001867 static bool objc_class = false;
1868 if (!objc_class) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001869 Result += "\nstruct _objc_class {\n";
1870 Result += "\tstruct _objc_class *isa;\n";
1871 Result += "\tconst char *super_class_name;\n";
1872 Result += "\tchar *name;\n";
1873 Result += "\tlong version;\n";
1874 Result += "\tlong info;\n";
1875 Result += "\tlong instance_size;\n";
1876 Result += "\tstruct _objc_ivar_list *ivars;\n";
1877 Result += "\tstruct _objc_method_list *methods;\n";
1878 Result += "\tstruct objc_cache *cache;\n";
1879 Result += "\tstruct _objc_protocol_list *protocols;\n";
1880 Result += "\tconst char *ivar_layout;\n";
1881 Result += "\tstruct _objc_class_ext *ext;\n";
1882 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001883 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001884 }
1885
1886 // Meta-class metadata generation.
1887 ObjcInterfaceDecl *RootClass = 0;
1888 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
1889 while (SuperClass) {
1890 RootClass = SuperClass;
1891 SuperClass = SuperClass->getSuperClass();
1892 }
1893 SuperClass = CDecl->getSuperClass();
1894
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001895 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
1896 Result += CDecl->getName();
1897 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
1898 "{\n\t(struct _objc_class *)\"";
1899 Result += (RootClass ? RootClass->getName() : CDecl->getName());
1900 Result += "\"";
1901
1902 if (SuperClass) {
1903 Result += ", \"";
1904 Result += SuperClass->getName();
1905 Result += "\", \"";
1906 Result += CDecl->getName();
1907 Result += "\"";
1908 }
1909 else {
1910 Result += ", 0, \"";
1911 Result += CDecl->getName();
1912 Result += "\"";
1913 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001914 // TODO: 'ivars' field for root class is currently set to 0.
1915 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001916 Result += ", 0,2, sizeof(struct _objc_class), 0";
1917 if (CDecl->getNumClassMethods() > 0) {
1918 Result += "\n\t, &_OBJC_CLASS_METHODS_";
1919 Result += CDecl->getName();
1920 Result += "\n";
1921 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001922 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001923 Result += ", 0\n";
1924 if (CDecl->getNumIntfRefProtocols() > 0) {
1925 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
1926 Result += CDecl->getName();
1927 Result += ",0,0\n";
1928 }
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001929 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001930 Result += "\t,0,0,0,0\n";
1931 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001932
1933 // class metadata generation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001934 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
1935 Result += CDecl->getName();
1936 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
1937 "{\n\t&_OBJC_METACLASS_";
1938 Result += CDecl->getName();
1939 if (SuperClass) {
1940 Result += ", \"";
1941 Result += SuperClass->getName();
1942 Result += "\", \"";
1943 Result += CDecl->getName();
1944 Result += "\"";
1945 }
1946 else {
1947 Result += ", 0, \"";
1948 Result += CDecl->getName();
1949 Result += "\"";
1950 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001951 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001952 Result += ", 0,1";
1953 if (!ObjcSynthesizedStructs.count(CDecl))
1954 Result += ",0";
1955 else {
1956 // class has size. Must synthesize its size.
Fariborz Jahanian909f02a2007-11-05 17:47:33 +00001957 Result += ",sizeof(struct ";
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001958 Result += CDecl->getName();
1959 Result += ")";
1960 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001961 if (NumIvars > 0) {
1962 Result += ", &_OBJC_INSTANCE_VARIABLES_";
1963 Result += CDecl->getName();
1964 Result += "\n\t";
1965 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001966 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001967 Result += ",0";
1968 if (IDecl->getNumInstanceMethods() > 0) {
1969 Result += ", &_OBJC_INSTANCE_METHODS_";
1970 Result += CDecl->getName();
1971 Result += ", 0\n\t";
1972 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001973 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001974 Result += ",0,0";
1975 if (CDecl->getNumIntfRefProtocols() > 0) {
1976 Result += ", &_OBJC_CLASS_PROTOCOLS_";
1977 Result += CDecl->getName();
1978 Result += ", 0,0\n";
1979 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001980 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001981 Result += ",0,0,0\n";
1982 Result += "};\n";
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001983}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001984
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00001985/// RewriteImplementations - This routine rewrites all method implementations
1986/// and emits meta-data.
1987
1988void RewriteTest::RewriteImplementations(std::string &Result) {
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001989 int ClsDefCount = ClassImplementation.size();
1990 int CatDefCount = CategoryImplementation.size();
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00001991
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001992 if (ClsDefCount == 0 && CatDefCount == 0)
1993 return;
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00001994 // Rewrite implemented methods
1995 for (int i = 0; i < ClsDefCount; i++)
1996 RewriteImplementationDecl(ClassImplementation[i]);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001997
Fariborz Jahanian66d6b292007-11-13 20:04:28 +00001998 for (int i = 0; i < CatDefCount; i++)
1999 RewriteImplementationDecl(CategoryImplementation[i]);
2000
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00002001 // This is needed for use of offsetof
2002 Result += "#include <stddef.h>\n";
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00002003
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002004 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00002005 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002006 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002007
2008 // For each implemented category, write out all its meta data.
2009 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002010 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00002011
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002012 // Write objc_symtab metadata
2013 /*
2014 struct _objc_symtab
2015 {
2016 long sel_ref_cnt;
2017 SEL *refs;
2018 short cls_def_cnt;
2019 short cat_def_cnt;
2020 void *defs[cls_def_cnt + cat_def_cnt];
2021 };
2022 */
2023
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002024 Result += "\nstruct _objc_symtab {\n";
2025 Result += "\tlong sel_ref_cnt;\n";
2026 Result += "\tSEL *refs;\n";
2027 Result += "\tshort cls_def_cnt;\n";
2028 Result += "\tshort cat_def_cnt;\n";
2029 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
2030 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002031
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002032 Result += "static struct _objc_symtab "
2033 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
2034 Result += "\t0, 0, " + utostr(ClsDefCount)
2035 + ", " + utostr(CatDefCount) + "\n";
2036 for (int i = 0; i < ClsDefCount; i++) {
2037 Result += "\t,&_OBJC_CLASS_";
2038 Result += ClassImplementation[i]->getName();
2039 Result += "\n";
2040 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002041
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002042 for (int i = 0; i < CatDefCount; i++) {
2043 Result += "\t,&_OBJC_CATEGORY_";
2044 Result += CategoryImplementation[i]->getClassInterface()->getName();
2045 Result += "_";
2046 Result += CategoryImplementation[i]->getName();
2047 Result += "\n";
2048 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002049
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002050 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002051
2052 // Write objc_module metadata
2053
2054 /*
2055 struct _objc_module {
2056 long version;
2057 long size;
2058 const char *name;
2059 struct _objc_symtab *symtab;
2060 }
2061 */
2062
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002063 Result += "\nstruct _objc_module {\n";
2064 Result += "\tlong version;\n";
2065 Result += "\tlong size;\n";
2066 Result += "\tconst char *name;\n";
2067 Result += "\tstruct _objc_symtab *symtab;\n";
2068 Result += "};\n\n";
2069 Result += "static struct _objc_module "
2070 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00002071 Result += "\t" + utostr(OBJC_ABI_VERSION) +
2072 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002073 Result += "};\n\n";
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00002074
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002075}
Chris Lattner311ff022007-10-16 22:36:42 +00002076