blob: 0c3d06b86b1004493297a873b9a242b89dcdb040 [file] [log] [blame]
Chris Lattnerb429ae42007-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 Lattner569faa62007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattnerb429ae42007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner569faa62007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Steve Naroffe9780582007-10-23 23:50:29 +000019#include "clang/Basic/IdentifierTable.h"
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000020#include "llvm/ADT/StringExtras.h"
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000021#include "llvm/ADT/SmallPtrSet.h"
Steve Naroff1ccf4632007-10-30 03:43:13 +000022#include "clang/Lex/Lexer.h"
Chris Lattnerb429ae42007-10-11 00:43:27 +000023using namespace clang;
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000024using llvm::utostr;
Chris Lattnerb429ae42007-10-11 00:43:27 +000025
Chris Lattnerb429ae42007-10-11 00:43:27 +000026namespace {
Chris Lattner569faa62007-10-11 18:38:32 +000027 class RewriteTest : public ASTConsumer {
Chris Lattner74db1682007-10-16 21:07:07 +000028 Rewriter Rewrite;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000029 ASTContext *Context;
Chris Lattnerb429ae42007-10-11 00:43:27 +000030 SourceManager *SM;
Chris Lattner569faa62007-10-11 18:38:32 +000031 unsigned MainFileID;
Chris Lattner74db1682007-10-16 21:07:07 +000032 SourceLocation LastIncLoc;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000033 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
34 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000035 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcSynthesizedStructs;
Steve Naroff809b4f02007-10-31 22:11:35 +000036 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcForwardDecls;
Steve Naroffe9780582007-10-23 23:50:29 +000037
38 FunctionDecl *MsgSendFunctionDecl;
39 FunctionDecl *GetClassFunctionDecl;
Steve Naroff71226032007-10-24 22:48:43 +000040 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffe9780582007-10-23 23:50:29 +000041
Steve Naroff0add5d22007-11-03 11:27:19 +000042 // ObjC string constant support.
43 FileVarDecl *ConstantStringClassReference;
44 RecordDecl *NSStringRecord;
Steve Naroff0744c472007-11-04 22:37:50 +000045
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000046 static const int OBJC_ABI_VERSION =7 ;
Chris Lattnerb429ae42007-10-11 00:43:27 +000047 public:
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000048 void Initialize(ASTContext &context, unsigned mainFileID) {
49 Context = &context;
50 SM = &Context->SourceMgr;
Chris Lattner569faa62007-10-11 18:38:32 +000051 MainFileID = mainFileID;
Steve Naroffe9780582007-10-23 23:50:29 +000052 MsgSendFunctionDecl = 0;
Steve Naroff95b28c12007-10-24 01:09:48 +000053 GetClassFunctionDecl = 0;
Steve Naroff71226032007-10-24 22:48:43 +000054 SelGetUidFunctionDecl = 0;
Steve Naroff0add5d22007-11-03 11:27:19 +000055 ConstantStringClassReference = 0;
56 NSStringRecord = 0;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000057 Rewrite.setSourceMgr(Context->SourceMgr);
Steve Narofffcab7932007-11-05 14:55:35 +000058 // declaring objc_selector outside the parameter list removes a silly
59 // scope related warning...
60 const char *s = "struct objc_selector;\n"
61 "extern struct objc_object *objc_msgSend"
Steve Naroff0744c472007-11-04 22:37:50 +000062 "(struct objc_object *, struct objc_selector *, ...);\n"
63 "extern struct objc_object *objc_getClass"
64 "(const char *);\n";
65 Rewrite.InsertText(SourceLocation::getFileLoc(mainFileID, 0),
66 s, strlen(s));
Chris Lattnerb429ae42007-10-11 00:43:27 +000067 }
Chris Lattner569faa62007-10-11 18:38:32 +000068
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000069 // Top Level Driver code.
70 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner74db1682007-10-16 21:07:07 +000071 void HandleDeclInMainFile(Decl *D);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000072 ~RewriteTest();
73
74 // Syntactic Rewriting.
Steve Naroff0744c472007-11-04 22:37:50 +000075 void RewritePrologue(SourceLocation Loc);
Chris Lattner74db1682007-10-16 21:07:07 +000076 void RewriteInclude(SourceLocation Loc);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000077 void RewriteTabs();
78 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroff3774dd92007-10-26 20:53:56 +000079 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Steve Naroff667f1682007-10-30 13:30:57 +000080 void RewriteCategoryDecl(ObjcCategoryDecl *Dcl);
Steve Narofff4b7d6a2007-10-30 16:42:30 +000081 void RewriteProtocolDecl(ObjcProtocolDecl *Dcl);
Steve Naroff667f1682007-10-30 13:30:57 +000082 void RewriteMethods(int nMethods, ObjcMethodDecl **Methods);
Fariborz Jahanianeca7fad2007-11-07 00:09:37 +000083 void RewriteProperties(int nProperties, ObjcPropertyDecl **Properties);
Steve Naroff02a82aa2007-10-30 23:14:51 +000084 void RewriteFunctionDecl(FunctionDecl *FD);
Steve Naroffc8a92d12007-11-01 13:24:47 +000085 void RewriteObjcQualifiedInterfaceTypes(
86 const FunctionTypeProto *proto, FunctionDecl *FD);
87 bool needToScanForQualifiers(QualType T);
Chris Lattner6fe8b272007-10-16 22:36:42 +000088
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000089 // Expression Rewriting.
Chris Lattner0021f452007-10-24 16:57:36 +000090 Stmt *RewriteFunctionBody(Stmt *S);
91 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Steve Naroff296b74f2007-11-05 14:50:49 +000092 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Chris Lattner0021f452007-10-24 16:57:36 +000093 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff0add5d22007-11-03 11:27:19 +000094 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
Fariborz Jahanian9447e462007-11-05 17:47:33 +000095 Stmt *RewriteObjcTryStmt(ObjcAtTryStmt *S);
96 Stmt *RewriteObjcCatchStmt(ObjcAtCatchStmt *S);
97 Stmt *RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S);
Steve Naroff8b1fb8c2007-11-07 15:32:26 +000098 Stmt *RewriteObjcThrowStmt(ObjcAtThrowStmt *S);
Steve Naroff71226032007-10-24 22:48:43 +000099 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
100 Expr **args, unsigned nargs);
Steve Naroff02a82aa2007-10-30 23:14:51 +0000101 void SynthMsgSendFunctionDecl();
102 void SynthGetClassFunctionDecl();
103
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000104 // Metadata emission.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000105 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
106 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000107
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000108 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
109 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000110
111 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
112 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000113 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000114 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000115 const char *ClassName,
116 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000117
118 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
119 int NumProtocols,
120 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000121 const char *ClassName,
122 std::string &Result);
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000123 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
124 std::string &Result);
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000125 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
126 ObjcIvarDecl *ivar,
127 std::string &Result);
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000128 void WriteObjcMetaData(std::string &Result);
Chris Lattnerb429ae42007-10-11 00:43:27 +0000129 };
130}
131
Chris Lattner569faa62007-10-11 18:38:32 +0000132ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattnerb429ae42007-10-11 00:43:27 +0000133
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000134//===----------------------------------------------------------------------===//
135// Top Level Driver Code
136//===----------------------------------------------------------------------===//
137
Chris Lattner569faa62007-10-11 18:38:32 +0000138void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner74db1682007-10-16 21:07:07 +0000139 // Two cases: either the decl could be in the main file, or it could be in a
140 // #included file. If the former, rewrite it now. If the later, check to see
141 // if we rewrote the #include/#import.
142 SourceLocation Loc = D->getLocation();
143 Loc = SM->getLogicalLoc(Loc);
144
145 // If this is for a builtin, ignore it.
146 if (Loc.isInvalid()) return;
147
Steve Naroffe9780582007-10-23 23:50:29 +0000148 // Look for built-in declarations that we need to refer during the rewrite.
149 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff02a82aa2007-10-30 23:14:51 +0000150 RewriteFunctionDecl(FD);
Steve Naroff0add5d22007-11-03 11:27:19 +0000151 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
152 // declared in <Foundation/NSString.h>
153 if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) {
154 ConstantStringClassReference = FVD;
155 return;
156 }
Steve Naroff3774dd92007-10-26 20:53:56 +0000157 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
158 RewriteInterfaceDecl(MD);
Steve Naroff667f1682007-10-30 13:30:57 +0000159 } else if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(D)) {
160 RewriteCategoryDecl(CD);
Steve Narofff4b7d6a2007-10-30 16:42:30 +0000161 } else if (ObjcProtocolDecl *PD = dyn_cast<ObjcProtocolDecl>(D)) {
162 RewriteProtocolDecl(PD);
Steve Naroffe9780582007-10-23 23:50:29 +0000163 }
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000164 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner74db1682007-10-16 21:07:07 +0000165 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
166 return HandleDeclInMainFile(D);
167
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000168 // Otherwise, see if there is a #import in the main file that should be
169 // rewritten.
Chris Lattner74db1682007-10-16 21:07:07 +0000170 RewriteInclude(Loc);
171}
172
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000173/// HandleDeclInMainFile - This is called for each top-level decl defined in the
174/// main file of the input.
175void RewriteTest::HandleDeclInMainFile(Decl *D) {
176 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
177 if (Stmt *Body = FD->getBody())
178 FD->setBody(RewriteFunctionBody(Body));
179
180 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
181 ClassImplementation.push_back(CI);
182 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
183 CategoryImplementation.push_back(CI);
184 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
185 RewriteForwardClassDecl(CD);
186 // Nothing yet.
187}
188
189RewriteTest::~RewriteTest() {
190 // Get the top-level buffer that this corresponds to.
191 RewriteTabs();
192
Fariborz Jahanian9447e462007-11-05 17:47:33 +0000193 // Rewrite Objective-c meta data*
194 std::string ResultStr;
195 WriteObjcMetaData(ResultStr);
Fariborz Jahanian9447e462007-11-05 17:47:33 +0000196
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000197 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
198 // we are done.
199 if (const RewriteBuffer *RewriteBuf =
200 Rewrite.getRewriteBufferFor(MainFileID)) {
Steve Naroff0add5d22007-11-03 11:27:19 +0000201 //printf("Changed:\n");
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000202 std::string S(RewriteBuf->begin(), RewriteBuf->end());
203 printf("%s\n", S.c_str());
204 } else {
205 printf("No changes\n");
206 }
Fariborz Jahanian70ef5462007-11-07 18:40:28 +0000207 // Emit metadata.
208 printf("%s", ResultStr.c_str());
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000209}
210
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000211//===----------------------------------------------------------------------===//
212// Syntactic (non-AST) Rewriting Code
213//===----------------------------------------------------------------------===//
214
Chris Lattner74db1682007-10-16 21:07:07 +0000215void RewriteTest::RewriteInclude(SourceLocation Loc) {
216 // Rip up the #include stack to the main file.
217 SourceLocation IncLoc = Loc, NextLoc = Loc;
218 do {
219 IncLoc = Loc;
220 Loc = SM->getLogicalLoc(NextLoc);
221 NextLoc = SM->getIncludeLoc(Loc);
222 } while (!NextLoc.isInvalid());
223
224 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
225 // IncLoc indicates the header that was included if it is useful.
226 IncLoc = SM->getLogicalLoc(IncLoc);
227 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
228 Loc == LastIncLoc)
229 return;
230 LastIncLoc = Loc;
231
232 unsigned IncCol = SM->getColumnNumber(Loc);
233 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
234
235 // Replace the #import with #include.
236 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
237}
238
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000239void RewriteTest::RewriteTabs() {
240 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
241 const char *MainBufStart = MainBuf.first;
242 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000243
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000244 // Loop over the whole file, looking for tabs.
245 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
246 if (*BufPtr != '\t')
247 continue;
248
249 // Okay, we found a tab. This tab will turn into at least one character,
250 // but it depends on which 'virtual column' it is in. Compute that now.
251 unsigned VCol = 0;
252 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
253 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
254 ++VCol;
255
256 // Okay, now that we know the virtual column, we know how many spaces to
257 // insert. We assume 8-character tab-stops.
258 unsigned Spaces = 8-(VCol & 7);
259
260 // Get the location of the tab.
261 SourceLocation TabLoc =
262 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
263
264 // Rewrite the single tab character into a sequence of spaces.
265 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
266 }
Chris Lattner569faa62007-10-11 18:38:32 +0000267}
268
269
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000270void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
271 int numDecls = ClassDecl->getNumForwardDecls();
272 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
273
274 // Get the start location and compute the semi location.
275 SourceLocation startLoc = ClassDecl->getLocation();
276 const char *startBuf = SM->getCharacterData(startLoc);
277 const char *semiPtr = strchr(startBuf, ';');
278
279 // Translate to typedef's that forward reference structs with the same name
280 // as the class. As a convenience, we include the original declaration
281 // as a comment.
282 std::string typedefString;
283 typedefString += "// ";
Steve Naroff71226032007-10-24 22:48:43 +0000284 typedefString.append(startBuf, semiPtr-startBuf+1);
285 typedefString += "\n";
286 for (int i = 0; i < numDecls; i++) {
287 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
Steve Naroff809b4f02007-10-31 22:11:35 +0000288 if (ObjcForwardDecls.count(ForwardDecl))
289 continue;
Steve Naroff4242b972007-11-05 14:36:37 +0000290 typedefString += "typedef struct objc_object ";
Steve Naroff71226032007-10-24 22:48:43 +0000291 typedefString += ForwardDecl->getName();
292 typedefString += ";\n";
Steve Naroff809b4f02007-10-31 22:11:35 +0000293
294 // Mark this typedef as having been generated.
295 if (!ObjcForwardDecls.insert(ForwardDecl))
Fariborz Jahanian2a3c7762007-10-31 22:57:04 +0000296 assert(false && "typedef already output");
Steve Naroff71226032007-10-24 22:48:43 +0000297 }
298
299 // Replace the @class with typedefs corresponding to the classes.
300 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
301 typedefString.c_str(), typedefString.size());
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000302}
303
Steve Naroff667f1682007-10-30 13:30:57 +0000304void RewriteTest::RewriteMethods(int nMethods, ObjcMethodDecl **Methods) {
305 for (int i = 0; i < nMethods; i++) {
306 ObjcMethodDecl *Method = Methods[i];
307 SourceLocation Loc = Method->getLocStart();
308
309 Rewrite.ReplaceText(Loc, 0, "// ", 3);
310
311 // FIXME: handle methods that are declared across multiple lines.
312 }
313}
314
Fariborz Jahanianeca7fad2007-11-07 00:09:37 +0000315void RewriteTest::RewriteProperties(int nProperties, ObjcPropertyDecl **Properties)
316{
317 for (int i = 0; i < nProperties; i++) {
318 ObjcPropertyDecl *Property = Properties[i];
319 SourceLocation Loc = Property->getLocation();
320
321 Rewrite.ReplaceText(Loc, 0, "// ", 3);
322
323 // FIXME: handle properties that are declared across multiple lines.
324 }
325}
326
Steve Naroff667f1682007-10-30 13:30:57 +0000327void RewriteTest::RewriteCategoryDecl(ObjcCategoryDecl *CatDecl) {
328 SourceLocation LocStart = CatDecl->getLocStart();
329
330 // FIXME: handle category headers that are declared across multiple lines.
331 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
332
333 RewriteMethods(CatDecl->getNumInstanceMethods(),
334 CatDecl->getInstanceMethods());
335 RewriteMethods(CatDecl->getNumClassMethods(),
336 CatDecl->getClassMethods());
337 // Lastly, comment out the @end.
338 Rewrite.ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3);
339}
340
Steve Narofff4b7d6a2007-10-30 16:42:30 +0000341void RewriteTest::RewriteProtocolDecl(ObjcProtocolDecl *PDecl) {
342 SourceLocation LocStart = PDecl->getLocStart();
343
344 // FIXME: handle protocol headers that are declared across multiple lines.
345 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
346
347 RewriteMethods(PDecl->getNumInstanceMethods(),
348 PDecl->getInstanceMethods());
349 RewriteMethods(PDecl->getNumClassMethods(),
350 PDecl->getClassMethods());
351 // Lastly, comment out the @end.
352 Rewrite.ReplaceText(PDecl->getAtEndLoc(), 0, "// ", 3);
353}
354
Steve Naroff3774dd92007-10-26 20:53:56 +0000355void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
Steve Naroffef20ed32007-10-30 02:23:23 +0000356
357 SourceLocation LocStart = ClassDecl->getLocStart();
358 SourceLocation LocEnd = ClassDecl->getLocEnd();
359
360 const char *startBuf = SM->getCharacterData(LocStart);
361 const char *endBuf = SM->getCharacterData(LocEnd);
362
Steve Naroff1ccf4632007-10-30 03:43:13 +0000363 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
Steve Naroffef20ed32007-10-30 02:23:23 +0000364
365 std::string ResultStr;
Steve Naroff77d081b2007-11-01 03:35:41 +0000366 if (!ObjcForwardDecls.count(ClassDecl)) {
367 // we haven't seen a forward decl - generate a typedef.
Steve Naroff4242b972007-11-05 14:36:37 +0000368 ResultStr += "typedef struct objc_object ";
Steve Naroff77d081b2007-11-01 03:35:41 +0000369 ResultStr += ClassDecl->getName();
370 ResultStr += ";";
371
372 // Mark this typedef as having been generated.
373 ObjcForwardDecls.insert(ClassDecl);
374 }
Steve Naroffef20ed32007-10-30 02:23:23 +0000375 SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
376
Steve Naroff1ccf4632007-10-30 03:43:13 +0000377 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
Steve Naroffef20ed32007-10-30 02:23:23 +0000378 ResultStr.c_str(), ResultStr.size());
Fariborz Jahanianeca7fad2007-11-07 00:09:37 +0000379 RewriteProperties(ClassDecl->getNumPropertyDecl(),
380 ClassDecl->getPropertyDecl());
Steve Naroff667f1682007-10-30 13:30:57 +0000381 RewriteMethods(ClassDecl->getNumInstanceMethods(),
382 ClassDecl->getInstanceMethods());
383 RewriteMethods(ClassDecl->getNumClassMethods(),
384 ClassDecl->getClassMethods());
Steve Naroff3774dd92007-10-26 20:53:56 +0000385
Steve Naroff1ccf4632007-10-30 03:43:13 +0000386 // Lastly, comment out the @end.
387 Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
Steve Naroff3774dd92007-10-26 20:53:56 +0000388}
389
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000390//===----------------------------------------------------------------------===//
391// Function Body / Expression rewriting
392//===----------------------------------------------------------------------===//
393
Chris Lattner0021f452007-10-24 16:57:36 +0000394Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner6fe8b272007-10-16 22:36:42 +0000395 // Otherwise, just rewrite all children.
396 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
397 CI != E; ++CI)
Steve Naroffe9f69842007-11-07 04:08:17 +0000398 if (*CI) {
399 Stmt *newStmt = RewriteFunctionBody(*CI);
400 if (newStmt)
401 *CI = newStmt;
402 }
Steve Naroffe9780582007-10-23 23:50:29 +0000403
404 // Handle specific things.
405 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
406 return RewriteAtEncode(AtEncode);
Steve Naroff296b74f2007-11-05 14:50:49 +0000407
408 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
409 return RewriteAtSelector(AtSelector);
Steve Naroff0add5d22007-11-03 11:27:19 +0000410
411 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
412 return RewriteObjCStringLiteral(AtString);
Steve Naroffe9780582007-10-23 23:50:29 +0000413
Steve Naroff71226032007-10-24 22:48:43 +0000414 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
415 // Before we rewrite it, put the original message expression in a comment.
416 SourceLocation startLoc = MessExpr->getLocStart();
417 SourceLocation endLoc = MessExpr->getLocEnd();
418
419 const char *startBuf = SM->getCharacterData(startLoc);
420 const char *endBuf = SM->getCharacterData(endLoc);
421
422 std::string messString;
423 messString += "// ";
424 messString.append(startBuf, endBuf-startBuf+1);
425 messString += "\n";
Steve Naroff3774dd92007-10-26 20:53:56 +0000426
Steve Naroff71226032007-10-24 22:48:43 +0000427 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
428 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
429 // Tried this, but it didn't work either...
Steve Narofff4b7d6a2007-10-30 16:42:30 +0000430 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffe9780582007-10-23 23:50:29 +0000431 return RewriteMessageExpr(MessExpr);
Steve Naroff71226032007-10-24 22:48:43 +0000432 }
Fariborz Jahanian9447e462007-11-05 17:47:33 +0000433
434 if (ObjcAtTryStmt *StmtTry = dyn_cast<ObjcAtTryStmt>(S))
435 return RewriteObjcTryStmt(StmtTry);
Steve Naroff8b1fb8c2007-11-07 15:32:26 +0000436
437 if (ObjcAtThrowStmt *StmtThrow = dyn_cast<ObjcAtThrowStmt>(S))
438 return RewriteObjcThrowStmt(StmtThrow);
439
Chris Lattner0021f452007-10-24 16:57:36 +0000440 // Return this stmt unmodified.
441 return S;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000442}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000443
Fariborz Jahanian9447e462007-11-05 17:47:33 +0000444Stmt *RewriteTest::RewriteObjcTryStmt(ObjcAtTryStmt *S) {
Steve Naroffe9f69842007-11-07 04:08:17 +0000445 // Get the start location and compute the semi location.
446 SourceLocation startLoc = S->getLocStart();
447 const char *startBuf = SM->getCharacterData(startLoc);
448
449 assert((*startBuf == '@') && "bogus @try location");
450
451 std::string buf;
452 // declare a new scope with two variables, _stack and _rethrow.
453 buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
454 buf += "int buf[18/*32-bit i386*/];\n";
455 buf += "char *pointers[4];} _stack;\n";
456 buf += "id volatile _rethrow = 0;\n";
457 buf += "objc_exception_try_enter(&_stack);\n";
458 buf += "if (!_setjmp(&_stack.buf)) /* @try block continue */\n";
459
460 Rewrite.ReplaceText(startLoc, 4, buf.c_str(), buf.size());
461
462 startLoc = S->getTryBody()->getLocEnd();
463 startBuf = SM->getCharacterData(startLoc);
464
465 assert((*startBuf == '}') && "bogus @try block");
466
467 SourceLocation lastCurlyLoc = startLoc;
468
469 startLoc = startLoc.getFileLocWithOffset(1);
470 buf = " /* @catch begin */ else {\n";
471 buf += " id _caught = objc_exception_extract(&_stack);\n";
472 buf += " objc_exception_try_enter (&_stack);\n";
473 buf += " if (_setjmp(&_stack.buf))\n";
474 buf += " _rethrow = objc_exception_extract(&_stack);\n";
475 buf += " else { /* @catch continue */";
476
477 Rewrite.ReplaceText(startLoc, 0, buf.c_str(), buf.size());
478
479 bool sawIdTypedCatch = false;
480 Stmt *lastCatchBody = 0;
481 ObjcAtCatchStmt *catchList = S->getCatchStmts();
482 while (catchList) {
483 Stmt *catchStmt = catchList->getCatchParamStmt();
484
485 if (catchList == S->getCatchStmts())
486 buf = "if ("; // we are generating code for the first catch clause
487 else
488 buf = "else if (";
489 startLoc = catchList->getLocStart();
490 startBuf = SM->getCharacterData(startLoc);
491
492 assert((*startBuf == '@') && "bogus @catch location");
493
494 const char *lParenLoc = strchr(startBuf, '(');
495
496 if (DeclStmt *declStmt = dyn_cast<DeclStmt>(catchStmt)) {
497 QualType t = dyn_cast<ValueDecl>(declStmt->getDecl())->getType();
498 if (t == Context->getObjcIdType()) {
499 buf += "1) { ";
500 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
501 buf.c_str(), buf.size());
502 sawIdTypedCatch = true;
503 } else if (const PointerType *pType = t->getAsPointerType()) {
504 ObjcInterfaceType *cls; // Should be a pointer to a class.
505
506 cls = dyn_cast<ObjcInterfaceType>(pType->getPointeeType().getTypePtr());
507 if (cls) {
508 buf += "objc_exception_match(objc_getClass(\"";
509 buf += cls->getDecl()->getName();
510 buf += "\"), _caught)) { ";
511 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
512 buf.c_str(), buf.size());
513 }
514 }
515 // Now rewrite the body...
516 lastCatchBody = catchList->getCatchBody();
517 SourceLocation rParenLoc = catchList->getRParenLoc();
518 SourceLocation bodyLoc = lastCatchBody->getLocStart();
519 const char *bodyBuf = SM->getCharacterData(bodyLoc);
520 const char *rParenBuf = SM->getCharacterData(rParenLoc);
521 assert((*rParenBuf == ')') && "bogus @catch paren location");
522 assert((*bodyBuf == '{') && "bogus @catch body location");
523
524 buf = " = _caught;";
525 // Here we replace ") {" with "= _caught;" (which initializes and
526 // declares the @catch parameter).
527 Rewrite.ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
528 buf.c_str(), buf.size());
Steve Naroff8b1fb8c2007-11-07 15:32:26 +0000529 } else if (!isa<NullStmt>(catchStmt)) {
Steve Naroffe9f69842007-11-07 04:08:17 +0000530 assert(false && "@catch rewrite bug");
Steve Naroff8b1fb8c2007-11-07 15:32:26 +0000531 }
Steve Naroffe9f69842007-11-07 04:08:17 +0000532 catchList = catchList->getNextCatchStmt();
533 }
534 // Complete the catch list...
535 if (lastCatchBody) {
536 SourceLocation bodyLoc = lastCatchBody->getLocEnd();
537 const char *bodyBuf = SM->getCharacterData(bodyLoc);
538 assert((*bodyBuf == '}') && "bogus @catch body location");
539 bodyLoc = bodyLoc.getFileLocWithOffset(1);
540 buf = " } } /* @catch end */\n";
541
542 Rewrite.ReplaceText(bodyLoc, 0, buf.c_str(), buf.size());
543
544 // Set lastCurlyLoc
545 lastCurlyLoc = lastCatchBody->getLocEnd();
546 }
547 if (ObjcAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
548 startLoc = finalStmt->getLocStart();
549 startBuf = SM->getCharacterData(startLoc);
550 assert((*startBuf == '@') && "bogus @finally start");
551
552 buf = "/* @finally */";
553 Rewrite.ReplaceText(startLoc, 8, buf.c_str(), buf.size());
554
555 Stmt *body = finalStmt->getFinallyBody();
556 SourceLocation startLoc = body->getLocStart();
557 SourceLocation endLoc = body->getLocEnd();
558 const char *startBuf = SM->getCharacterData(startLoc);
559 const char *endBuf = SM->getCharacterData(endLoc);
560 assert((*startBuf == '{') && "bogus @finally body location");
561 assert((*endBuf == '}') && "bogus @finally body location");
562
563 startLoc = startLoc.getFileLocWithOffset(1);
564 buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
565 Rewrite.ReplaceText(startLoc, 0, buf.c_str(), buf.size());
566 endLoc = endLoc.getFileLocWithOffset(-1);
567 buf = " if (_rethrow) objc_exception_throw(_rethrow);\n";
568 Rewrite.ReplaceText(endLoc, 0, buf.c_str(), buf.size());
569
570 // Set lastCurlyLoc
571 lastCurlyLoc = body->getLocEnd();
572 }
573 // Now emit the final closing curly brace...
574 lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
575 buf = " } /* @try scope end */\n";
576 Rewrite.ReplaceText(lastCurlyLoc, 0, buf.c_str(), buf.size());
Fariborz Jahanian9447e462007-11-05 17:47:33 +0000577 return 0;
578}
579
580Stmt *RewriteTest::RewriteObjcCatchStmt(ObjcAtCatchStmt *S) {
581 return 0;
582}
583
584Stmt *RewriteTest::RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S) {
585 return 0;
586}
587
Steve Naroff8b1fb8c2007-11-07 15:32:26 +0000588// This can't be done with Rewrite.ReplaceStmt(S, ThrowExpr), since
589// the throw expression is typically a message expression that's already
590// been rewritten! (which implies the SourceLocation's are invalid).
591Stmt *RewriteTest::RewriteObjcThrowStmt(ObjcAtThrowStmt *S) {
592 // Get the start location and compute the semi location.
593 SourceLocation startLoc = S->getLocStart();
594 const char *startBuf = SM->getCharacterData(startLoc);
595
596 assert((*startBuf == '@') && "bogus @throw location");
597
598 std::string buf;
599 /* void objc_exception_throw(id) __attribute__((noreturn)); */
600 buf = "objc_exception_throw(";
601 Rewrite.ReplaceText(startLoc, 6, buf.c_str(), buf.size());
602 const char *semiBuf = strchr(startBuf, ';');
603 assert((*semiBuf == ';') && "@throw: can't find ';'");
604 SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
605 buf = ");";
606 Rewrite.ReplaceText(semiLoc, 1, buf.c_str(), buf.size());
607 return 0;
608}
Fariborz Jahanian9447e462007-11-05 17:47:33 +0000609
Chris Lattner0021f452007-10-24 16:57:36 +0000610Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000611 // Create a new string expression.
612 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson36f07d82007-10-29 05:01:08 +0000613 std::string StrEncoding;
614 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
615 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
616 StrEncoding.length(), false, StrType,
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000617 SourceLocation(), SourceLocation());
618 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattner0021f452007-10-24 16:57:36 +0000619 delete Exp;
620 return Replacement;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000621}
622
Steve Naroff296b74f2007-11-05 14:50:49 +0000623Stmt *RewriteTest::RewriteAtSelector(ObjCSelectorExpr *Exp) {
624 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
625 // Create a call to sel_registerName("selName").
626 llvm::SmallVector<Expr*, 8> SelExprs;
627 QualType argType = Context->getPointerType(Context->CharTy);
628 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
629 Exp->getSelector().getName().size(),
630 false, argType, SourceLocation(),
631 SourceLocation()));
632 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
633 &SelExprs[0], SelExprs.size());
634 Rewrite.ReplaceStmt(Exp, SelExp);
635 delete Exp;
636 return SelExp;
637}
638
Steve Naroff71226032007-10-24 22:48:43 +0000639CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
640 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffe9780582007-10-23 23:50:29 +0000641 // Get the type, we will need to reference it in a couple spots.
Steve Naroff71226032007-10-24 22:48:43 +0000642 QualType msgSendType = FD->getType();
Steve Naroffe9780582007-10-23 23:50:29 +0000643
644 // Create a reference to the objc_msgSend() declaration.
Steve Naroff71226032007-10-24 22:48:43 +0000645 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffe9780582007-10-23 23:50:29 +0000646
647 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000648 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffe9780582007-10-23 23:50:29 +0000649 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
650
651 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattner0021f452007-10-24 16:57:36 +0000652
Steve Naroff71226032007-10-24 22:48:43 +0000653 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
654}
655
Steve Naroffc8a92d12007-11-01 13:24:47 +0000656static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
657 const char *&startRef, const char *&endRef) {
658 while (startBuf < endBuf) {
659 if (*startBuf == '<')
660 startRef = startBuf; // mark the start.
661 if (*startBuf == '>') {
662 assert((startRef && *startRef == '<') && "rewrite scanning error");
663 endRef = startBuf; // mark the end.
664 return true;
665 }
666 startBuf++;
667 }
668 return false;
669}
670
671bool RewriteTest::needToScanForQualifiers(QualType T) {
672 // FIXME: we don't currently represent "id <Protocol>" in the type system.
673 if (T == Context->getObjcIdType())
674 return true;
675
676 if (const PointerType *pType = T->getAsPointerType()) {
Steve Naroff05d6ff52007-10-31 04:38:33 +0000677 Type *pointeeType = pType->getPointeeType().getTypePtr();
678 if (isa<ObjcQualifiedInterfaceType>(pointeeType))
679 return true; // we have "Class <Protocol> *".
680 }
Steve Naroffc8a92d12007-11-01 13:24:47 +0000681 return false;
682}
683
684void RewriteTest::RewriteObjcQualifiedInterfaceTypes(
685 const FunctionTypeProto *proto, FunctionDecl *FD) {
686
687 if (needToScanForQualifiers(proto->getResultType())) {
688 // Since types are unique, we need to scan the buffer.
689 SourceLocation Loc = FD->getLocation();
690
691 const char *endBuf = SM->getCharacterData(Loc);
692 const char *startBuf = endBuf;
693 while (*startBuf != ';')
694 startBuf--; // scan backward (from the decl location) for return type.
695 const char *startRef = 0, *endRef = 0;
696 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
697 // Get the locations of the startRef, endRef.
698 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
699 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
700 // Comment out the protocol references.
701 Rewrite.ReplaceText(LessLoc, 0, "/*", 2);
702 Rewrite.ReplaceText(GreaterLoc, 0, "*/", 2);
Steve Naroff05d6ff52007-10-31 04:38:33 +0000703 }
704 }
Steve Naroffc8a92d12007-11-01 13:24:47 +0000705 // Now check arguments.
706 for (unsigned i = 0; i < proto->getNumArgs(); i++) {
707 if (needToScanForQualifiers(proto->getArgType(i))) {
708 // Since types are unique, we need to scan the buffer.
709 SourceLocation Loc = FD->getLocation();
710
711 const char *startBuf = SM->getCharacterData(Loc);
712 const char *endBuf = startBuf;
713 while (*endBuf != ';')
714 endBuf++; // scan forward (from the decl location) for argument types.
715 const char *startRef = 0, *endRef = 0;
716 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
717 // Get the locations of the startRef, endRef.
718 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
719 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
720 // Comment out the protocol references.
721 Rewrite.ReplaceText(LessLoc, 0, "/*", 2);
722 Rewrite.ReplaceText(GreaterLoc, 0, "*/", 2);
723 }
724 }
725 }
Steve Naroff05d6ff52007-10-31 04:38:33 +0000726}
727
Steve Naroff02a82aa2007-10-30 23:14:51 +0000728void RewriteTest::RewriteFunctionDecl(FunctionDecl *FD) {
729 // declared in <objc/objc.h>
Steve Naroff0add5d22007-11-03 11:27:19 +0000730 if (strcmp(FD->getName(), "sel_registerName") == 0) {
Steve Naroff02a82aa2007-10-30 23:14:51 +0000731 SelGetUidFunctionDecl = FD;
Steve Naroff05d6ff52007-10-31 04:38:33 +0000732 return;
733 }
734 // Check for ObjC 'id' and class types that have been adorned with protocol
735 // information (id<p>, C<p>*). The protocol references need to be rewritten!
736 const FunctionType *funcType = FD->getType()->getAsFunctionType();
737 assert(funcType && "missing function type");
Steve Naroffc8a92d12007-11-01 13:24:47 +0000738 if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcType))
739 RewriteObjcQualifiedInterfaceTypes(proto, FD);
Steve Naroff02a82aa2007-10-30 23:14:51 +0000740}
741
742// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
743void RewriteTest::SynthMsgSendFunctionDecl() {
744 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
745 llvm::SmallVector<QualType, 16> ArgTys;
746 QualType argT = Context->getObjcIdType();
747 assert(!argT.isNull() && "Can't find 'id' type");
748 ArgTys.push_back(argT);
749 argT = Context->getObjcSelType();
750 assert(!argT.isNull() && "Can't find 'SEL' type");
751 ArgTys.push_back(argT);
752 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
753 &ArgTys[0], ArgTys.size(),
754 true /*isVariadic*/);
755 MsgSendFunctionDecl = new FunctionDecl(SourceLocation(),
756 msgSendIdent, msgSendType,
757 FunctionDecl::Extern, false, 0);
758}
759
760// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
761void RewriteTest::SynthGetClassFunctionDecl() {
762 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
763 llvm::SmallVector<QualType, 16> ArgTys;
764 ArgTys.push_back(Context->getPointerType(
765 Context->CharTy.getQualifiedType(QualType::Const)));
766 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
767 &ArgTys[0], ArgTys.size(),
768 false /*isVariadic*/);
769 GetClassFunctionDecl = new FunctionDecl(SourceLocation(),
770 getClassIdent, getClassType,
771 FunctionDecl::Extern, false, 0);
772}
773
Steve Naroff0add5d22007-11-03 11:27:19 +0000774Stmt *RewriteTest::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
775 assert(ConstantStringClassReference && "Can't find constant string reference");
776 llvm::SmallVector<Expr*, 4> InitExprs;
777
778 // Synthesize "(Class)&_NSConstantStringClassReference"
779 DeclRefExpr *ClsRef = new DeclRefExpr(ConstantStringClassReference,
780 ConstantStringClassReference->getType(),
781 SourceLocation());
782 QualType expType = Context->getPointerType(ClsRef->getType());
783 UnaryOperator *Unop = new UnaryOperator(ClsRef, UnaryOperator::AddrOf,
784 expType, SourceLocation());
785 CastExpr *cast = new CastExpr(Context->getObjcClassType(), Unop,
786 SourceLocation());
787 InitExprs.push_back(cast); // set the 'isa'.
788 InitExprs.push_back(Exp->getString()); // set "char *bytes".
789 unsigned IntSize = static_cast<unsigned>(
790 Context->getTypeSize(Context->IntTy, Exp->getLocStart()));
791 llvm::APInt IntVal(IntSize, Exp->getString()->getByteLength());
792 IntegerLiteral *len = new IntegerLiteral(IntVal, Context->IntTy,
793 Exp->getLocStart());
794 InitExprs.push_back(len); // set "int numBytes".
795
796 // struct NSConstantString
797 QualType CFConstantStrType = Context->getCFConstantStringType();
798 // (struct NSConstantString) { <exprs from above> }
799 InitListExpr *ILE = new InitListExpr(SourceLocation(),
800 &InitExprs[0], InitExprs.size(),
801 SourceLocation());
802 CompoundLiteralExpr *StrRep = new CompoundLiteralExpr(CFConstantStrType, ILE);
803 // struct NSConstantString *
804 expType = Context->getPointerType(StrRep->getType());
805 Unop = new UnaryOperator(StrRep, UnaryOperator::AddrOf, expType,
806 SourceLocation());
Steve Naroff4242b972007-11-05 14:36:37 +0000807 // cast to NSConstantString *
808 cast = new CastExpr(Exp->getType(), Unop, SourceLocation());
Steve Naroff0add5d22007-11-03 11:27:19 +0000809 Rewrite.ReplaceStmt(Exp, cast);
810 delete Exp;
Steve Naroff4242b972007-11-05 14:36:37 +0000811 return cast;
Steve Naroff0add5d22007-11-03 11:27:19 +0000812}
813
Steve Naroff71226032007-10-24 22:48:43 +0000814Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Steve Naroff0add5d22007-11-03 11:27:19 +0000815 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
Steve Naroff02a82aa2007-10-30 23:14:51 +0000816 if (!MsgSendFunctionDecl)
817 SynthMsgSendFunctionDecl();
818 if (!GetClassFunctionDecl)
819 SynthGetClassFunctionDecl();
Steve Naroff71226032007-10-24 22:48:43 +0000820
821 // Synthesize a call to objc_msgSend().
822 llvm::SmallVector<Expr*, 8> MsgExprs;
823 IdentifierInfo *clsName = Exp->getClassName();
824
825 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
826 if (clsName) { // class message.
827 llvm::SmallVector<Expr*, 8> ClsExprs;
828 QualType argType = Context->getPointerType(Context->CharTy);
829 ClsExprs.push_back(new StringLiteral(clsName->getName(),
830 clsName->getLength(),
831 false, argType, SourceLocation(),
832 SourceLocation()));
833 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
834 &ClsExprs[0], ClsExprs.size());
835 MsgExprs.push_back(Cls);
836 } else // instance message.
837 MsgExprs.push_back(Exp->getReceiver());
838
Steve Naroff0add5d22007-11-03 11:27:19 +0000839 // Create a call to sel_registerName("selName"), it will be the 2nd argument.
Steve Naroff71226032007-10-24 22:48:43 +0000840 llvm::SmallVector<Expr*, 8> SelExprs;
841 QualType argType = Context->getPointerType(Context->CharTy);
842 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
843 Exp->getSelector().getName().size(),
844 false, argType, SourceLocation(),
845 SourceLocation()));
846 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
847 &SelExprs[0], SelExprs.size());
848 MsgExprs.push_back(SelExp);
849
850 // Now push any user supplied arguments.
851 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
852 MsgExprs.push_back(Exp->getArg(i));
853 // We've transferred the ownership to MsgExprs. Null out the argument in
854 // the original expression, since we will delete it below.
855 Exp->setArg(i, 0);
856 }
Steve Naroff0744c472007-11-04 22:37:50 +0000857 // Generate the funky cast.
858 CastExpr *cast;
859 llvm::SmallVector<QualType, 8> ArgTypes;
860 QualType returnType;
861
862 // Push 'id' and 'SEL', the 2 implicit arguments.
863 ArgTypes.push_back(Context->getObjcIdType());
864 ArgTypes.push_back(Context->getObjcSelType());
865 if (ObjcMethodDecl *mDecl = Exp->getMethodDecl()) {
866 // Push any user argument types.
Steve Naroff4242b972007-11-05 14:36:37 +0000867 for (int i = 0; i < mDecl->getNumParams(); i++) {
868 QualType t = mDecl->getParamDecl(i)->getType();
869 if (t == Context->getObjcClassType())
870 t = Context->getObjcIdType(); // Convert "Class"->"id"
871 ArgTypes.push_back(t);
872 }
Steve Naroff0744c472007-11-04 22:37:50 +0000873 returnType = mDecl->getResultType();
874 } else {
875 returnType = Context->getObjcIdType();
876 }
877 // Get the type, we will need to reference it in a couple spots.
878 QualType msgSendType = MsgSendFunctionDecl->getType();
879
880 // Create a reference to the objc_msgSend() declaration.
881 DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType, SourceLocation());
882
883 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
884 // If we don't do this cast, we get the following bizarre warning/note:
885 // xx.m:13: warning: function called through a non-compatible type
886 // xx.m:13: note: if this code is reached, the program will abort
887 cast = new CastExpr(Context->getPointerType(Context->VoidTy), DRE,
888 SourceLocation());
889
890 // Now do the "normal" pointer to function cast.
891 QualType castType = Context->getFunctionType(returnType,
892 &ArgTypes[0], ArgTypes.size(),
893 false/*FIXME:variadic*/);
894 castType = Context->getPointerType(castType);
895 cast = new CastExpr(castType, cast, SourceLocation());
896
897 // Don't forget the parens to enforce the proper binding.
898 ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
899
900 const FunctionType *FT = msgSendType->getAsFunctionType();
901 CallExpr *CE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(),
902 FT->getResultType(), SourceLocation());
Steve Naroff71226032007-10-24 22:48:43 +0000903 // Now do the actual rewrite.
Steve Naroff0744c472007-11-04 22:37:50 +0000904 Rewrite.ReplaceStmt(Exp, CE);
Steve Naroff71226032007-10-24 22:48:43 +0000905
Chris Lattner0021f452007-10-24 16:57:36 +0000906 delete Exp;
Steve Naroff0744c472007-11-04 22:37:50 +0000907 return CE;
Steve Naroffe9780582007-10-23 23:50:29 +0000908}
909
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000910/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
911/// an objective-c class with ivars.
912void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
913 std::string &Result) {
914 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
915 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
Fariborz Jahanianfb4f6a32007-10-31 23:08:24 +0000916 // Do not synthesize more than once.
917 if (ObjcSynthesizedStructs.count(CDecl))
918 return;
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000919 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
920 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
921 // Do it for the root
922 SynthesizeObjcInternalStruct(RCDecl, Result);
923 }
924
925 int NumIvars = CDecl->getIntfDeclNumIvars();
Fariborz Jahanian2a3c7762007-10-31 22:57:04 +0000926 // If no ivars and no root or if its root, directly or indirectly,
Fariborz Jahanian2fd0daa2007-10-31 23:53:01 +0000927 // have no ivars (thus not synthesized) then no need to synthesize this class.
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000928 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
929 return;
930
Steve Naroffb1147382007-11-01 17:12:31 +0000931 Result += "\nstruct ";
932 Result += CDecl->getName();
933 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
934 Result += " {\n struct ";
935 Result += RCDecl->getName();
936 Result += " _";
937 Result += RCDecl->getName();
938 Result += ";\n";
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000939 }
Fariborz Jahanian6acfa2b2007-10-31 17:29:28 +0000940 else
941 Result += " {";
Steve Naroff809b4f02007-10-31 22:11:35 +0000942
Fariborz Jahanian6acfa2b2007-10-31 17:29:28 +0000943 if (NumIvars > 0) {
944 SourceLocation LocStart = CDecl->getLocStart();
945 SourceLocation LocEnd = CDecl->getLocEnd();
946
947 const char *startBuf = SM->getCharacterData(LocStart);
948 const char *endBuf = SM->getCharacterData(LocEnd);
949 startBuf = strchr(startBuf, '{');
950 assert((startBuf && endBuf)
951 && "SynthesizeObjcInternalStruct - malformed @interface");
952 startBuf++; // past '{'
953 while (startBuf < endBuf) {
954 if (*startBuf == '@') {
955 startBuf = strchr(startBuf, 'p');
956 // FIXME: presence of @public, etc. inside comment results in
957 // this transformation as well, which is still correct c-code.
958 if (!strncmp(startBuf, "public", strlen("public"))) {
959 startBuf += strlen("public");
960 Result += "/* @public */";
961 }
962 else if (!strncmp(startBuf, "private", strlen("private"))) {
963 startBuf += strlen("private");
964 Result += "/* @private */";
965 }
966 else if (!strncmp(startBuf, "protected", strlen("protected"))) {
967 startBuf += strlen("protected");
968 Result += "/* @protected */";
969 }
970 }
971 Result += *startBuf++;
972 }
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000973 }
Fariborz Jahanian6acfa2b2007-10-31 17:29:28 +0000974
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000975 Result += "};\n";
976 // Mark this struct as having been generated.
977 if (!ObjcSynthesizedStructs.insert(CDecl))
Fariborz Jahanian2a3c7762007-10-31 22:57:04 +0000978 assert(false && "struct already synthesize- SynthesizeObjcInternalStruct");
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000979}
980
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000981// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
982/// class methods.
983void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
984 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000985 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000986 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000987 const char *ClassName,
988 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000989 static bool objc_impl_method = false;
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000990 if (NumMethods > 0 && !objc_impl_method) {
991 /* struct _objc_method {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000992 SEL _cmd;
993 char *method_types;
994 void *_imp;
995 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000996 */
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000997 Result += "\nstruct _objc_method {\n";
998 Result += "\tSEL _cmd;\n";
999 Result += "\tchar *method_types;\n";
1000 Result += "\tvoid *_imp;\n";
1001 Result += "};\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001002
1003 /* struct _objc_method_list {
1004 struct _objc_method_list *next_method;
1005 int method_count;
1006 struct _objc_method method_list[];
1007 }
1008 */
1009 Result += "\nstruct _objc_method_list {\n";
1010 Result += "\tstruct _objc_method_list *next_method;\n";
1011 Result += "\tint method_count;\n";
1012 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001013 objc_impl_method = true;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +00001014 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001015 // Build _objc_method_list for class's methods if needed
1016 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001017 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattnerc3aa5c42007-10-25 17:07:24 +00001018 Result += prefix;
1019 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
1020 Result += "_METHODS_";
1021 Result += ClassName;
1022 Result += " __attribute__ ((section (\"__OBJC, __";
1023 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001024 Result += "_meth\")))= ";
1025 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
1026
1027 Result += "\t,{{(SEL)\"";
1028 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanianc81f3162007-10-29 22:57:28 +00001029 std::string MethodTypeString;
1030 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
1031 Result += "\", \"";
1032 Result += MethodTypeString;
1033 Result += "\", 0}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001034 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianc81f3162007-10-29 22:57:28 +00001035 // TODO: Need method address as 3rd initializer.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001036 Result += "\t ,{(SEL)\"";
1037 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanianc81f3162007-10-29 22:57:28 +00001038 std::string MethodTypeString;
1039 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1040 Result += "\", \"";
1041 Result += MethodTypeString;
1042 Result += "\", 0}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001043 }
1044 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +00001045 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001046}
1047
1048/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
1049void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
1050 int NumProtocols,
1051 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001052 const char *ClassName,
1053 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +00001054 static bool objc_protocol_methods = false;
Fariborz Jahanian04455192007-10-22 21:41:37 +00001055 if (NumProtocols > 0) {
Fariborz Jahanian04455192007-10-22 21:41:37 +00001056 for (int i = 0; i < NumProtocols; i++) {
1057 ObjcProtocolDecl *PDecl = Protocols[i];
1058 // Output struct protocol_methods holder of method selector and type.
1059 if (!objc_protocol_methods &&
1060 (PDecl->getNumInstanceMethods() > 0
1061 || PDecl->getNumClassMethods() > 0)) {
1062 /* struct protocol_methods {
1063 SEL _cmd;
1064 char *method_types;
1065 }
1066 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001067 Result += "\nstruct protocol_methods {\n";
1068 Result += "\tSEL _cmd;\n";
1069 Result += "\tchar *method_types;\n";
1070 Result += "};\n";
1071
1072 /* struct _objc_protocol_method_list {
1073 int protocol_method_count;
1074 struct protocol_methods protocols[];
1075 }
1076 */
1077 Result += "\nstruct _objc_protocol_method_list {\n";
1078 Result += "\tint protocol_method_count;\n";
1079 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +00001080 objc_protocol_methods = true;
1081 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001082
Fariborz Jahanian04455192007-10-22 21:41:37 +00001083 // Output instance methods declared in this protocol.
Fariborz Jahanian04455192007-10-22 21:41:37 +00001084 int NumMethods = PDecl->getNumInstanceMethods();
1085 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001086 Result += "\nstatic struct _objc_protocol_method_list "
1087 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
1088 Result += PDecl->getName();
1089 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
1090 "{\n\t" + utostr(NumMethods) + "\n";
1091
Fariborz Jahanian04455192007-10-22 21:41:37 +00001092 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001093 Result += "\t,{{(SEL)\"";
1094 Result += Methods[0]->getSelector().getName().c_str();
1095 Result += "\", \"\"}\n";
1096
1097 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001098 Result += "\t ,{(SEL)\"";
1099 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanianc81f3162007-10-29 22:57:28 +00001100 std::string MethodTypeString;
1101 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1102 Result += "\", \"";
1103 Result += MethodTypeString;
1104 Result += "\"}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001105 }
1106 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +00001107 }
1108
1109 // Output class methods declared in this protocol.
1110 NumMethods = PDecl->getNumClassMethods();
1111 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001112 Result += "\nstatic struct _objc_protocol_method_list "
1113 "_OBJC_PROTOCOL_CLASS_METHODS_";
1114 Result += PDecl->getName();
1115 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1116 "{\n\t";
1117 Result += utostr(NumMethods);
1118 Result += "\n";
1119
Fariborz Jahanian04455192007-10-22 21:41:37 +00001120 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001121 Result += "\t,{{(SEL)\"";
1122 Result += Methods[0]->getSelector().getName().c_str();
1123 Result += "\", \"\"}\n";
1124
1125 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001126 Result += "\t ,{(SEL)\"";
1127 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanianc81f3162007-10-29 22:57:28 +00001128 std::string MethodTypeString;
1129 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1130 Result += "\", \"";
1131 Result += MethodTypeString;
1132 Result += "\"}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001133 }
1134 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +00001135 }
1136 // Output:
1137 /* struct _objc_protocol {
1138 // Objective-C 1.0 extensions
1139 struct _objc_protocol_extension *isa;
1140 char *protocol_name;
1141 struct _objc_protocol **protocol_list;
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001142 struct _objc_protocol_method_list *instance_methods;
1143 struct _objc_protocol_method_list *class_methods;
Fariborz Jahanian04455192007-10-22 21:41:37 +00001144 };
1145 */
1146 static bool objc_protocol = false;
1147 if (!objc_protocol) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001148 Result += "\nstruct _objc_protocol {\n";
1149 Result += "\tstruct _objc_protocol_extension *isa;\n";
1150 Result += "\tchar *protocol_name;\n";
1151 Result += "\tstruct _objc_protocol **protocol_list;\n";
1152 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
1153 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
1154 Result += "};\n";
1155
1156 /* struct _objc_protocol_list {
1157 struct _objc_protocol_list *next;
1158 int protocol_count;
1159 struct _objc_protocol *class_protocols[];
1160 }
1161 */
1162 Result += "\nstruct _objc_protocol_list {\n";
1163 Result += "\tstruct _objc_protocol_list *next;\n";
1164 Result += "\tint protocol_count;\n";
1165 Result += "\tstruct _objc_protocol *class_protocols[];\n";
1166 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +00001167 objc_protocol = true;
1168 }
1169
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001170 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
1171 Result += PDecl->getName();
1172 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
1173 "{\n\t0, \"";
1174 Result += PDecl->getName();
1175 Result += "\", 0, ";
1176 if (PDecl->getInstanceMethods() > 0) {
1177 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
1178 Result += PDecl->getName();
1179 Result += ", ";
1180 }
Fariborz Jahanian04455192007-10-22 21:41:37 +00001181 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001182 Result += "0, ";
1183 if (PDecl->getClassMethods() > 0) {
1184 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
1185 Result += PDecl->getName();
1186 Result += "\n";
1187 }
Fariborz Jahanian04455192007-10-22 21:41:37 +00001188 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001189 Result += "0\n";
1190 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +00001191 }
Fariborz Jahanian04455192007-10-22 21:41:37 +00001192 // Output the top lovel protocol meta-data for the class.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001193 Result += "\nstatic struct _objc_protocol_list _OBJC_";
1194 Result += prefix;
1195 Result += "_PROTOCOLS_";
1196 Result += ClassName;
1197 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1198 "{\n\t0, ";
1199 Result += utostr(NumProtocols);
1200 Result += "\n";
1201
1202 Result += "\t,{&_OBJC_PROTOCOL_";
1203 Result += Protocols[0]->getName();
1204 Result += " \n";
1205
1206 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +00001207 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001208 Result += "\t ,&_OBJC_PROTOCOL_";
1209 Result += PDecl->getName();
1210 Result += "\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +00001211 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001212 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001213 }
1214}
1215
1216/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
1217/// implementation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001218void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
1219 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001220 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
1221 // Find category declaration for this implementation.
1222 ObjcCategoryDecl *CDecl;
1223 for (CDecl = ClassDecl->getCategoryList(); CDecl;
1224 CDecl = CDecl->getNextClassCategory())
1225 if (CDecl->getIdentifier() == IDecl->getIdentifier())
1226 break;
1227 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
1228
1229 char *FullCategoryName = (char*)alloca(
1230 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
1231 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
1232
1233 // Build _objc_method_list for class's instance methods if needed
1234 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1235 IDecl->getNumInstanceMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +00001236 true,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001237 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001238
1239 // Build _objc_method_list for class's class methods if needed
1240 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
1241 IDecl->getNumClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +00001242 false,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001243 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001244
1245 // Protocols referenced in class declaration?
1246 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1247 CDecl->getNumReferencedProtocols(),
1248 "CATEGORY",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001249 FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001250
1251 /* struct _objc_category {
1252 char *category_name;
1253 char *class_name;
1254 struct _objc_method_list *instance_methods;
1255 struct _objc_method_list *class_methods;
1256 struct _objc_protocol_list *protocols;
1257 // Objective-C 1.0 extensions
1258 uint32_t size; // sizeof (struct _objc_category)
1259 struct _objc_property_list *instance_properties; // category's own
1260 // @property decl.
1261 };
1262 */
1263
1264 static bool objc_category = false;
1265 if (!objc_category) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001266 Result += "\nstruct _objc_category {\n";
1267 Result += "\tchar *category_name;\n";
1268 Result += "\tchar *class_name;\n";
1269 Result += "\tstruct _objc_method_list *instance_methods;\n";
1270 Result += "\tstruct _objc_method_list *class_methods;\n";
1271 Result += "\tstruct _objc_protocol_list *protocols;\n";
1272 Result += "\tunsigned int size;\n";
1273 Result += "\tstruct _objc_property_list *instance_properties;\n";
1274 Result += "};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001275 objc_category = true;
Fariborz Jahanian04455192007-10-22 21:41:37 +00001276 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001277 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
1278 Result += FullCategoryName;
1279 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
1280 Result += IDecl->getName();
1281 Result += "\"\n\t, \"";
1282 Result += ClassDecl->getName();
1283 Result += "\"\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001284
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001285 if (IDecl->getNumInstanceMethods() > 0) {
1286 Result += "\t, (struct _objc_method_list *)"
1287 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
1288 Result += FullCategoryName;
1289 Result += "\n";
1290 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001291 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001292 Result += "\t, 0\n";
1293 if (IDecl->getNumClassMethods() > 0) {
1294 Result += "\t, (struct _objc_method_list *)"
1295 "&_OBJC_CATEGORY_CLASS_METHODS_";
1296 Result += FullCategoryName;
1297 Result += "\n";
1298 }
1299 else
1300 Result += "\t, 0\n";
1301
1302 if (CDecl->getNumReferencedProtocols() > 0) {
1303 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
1304 Result += FullCategoryName;
1305 Result += "\n";
1306 }
1307 else
1308 Result += "\t, 0\n";
1309 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001310}
1311
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001312/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
1313/// ivar offset.
1314void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
1315 ObjcIvarDecl *ivar,
1316 std::string &Result) {
Fariborz Jahanian9447e462007-11-05 17:47:33 +00001317 Result += "offsetof(struct ";
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001318 Result += IDecl->getName();
1319 Result += ", ";
1320 Result += ivar->getName();
1321 Result += ")";
1322}
1323
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001324//===----------------------------------------------------------------------===//
1325// Meta Data Emission
1326//===----------------------------------------------------------------------===//
1327
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001328void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
1329 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001330 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
1331
1332 // Build _objc_ivar_list metadata for classes ivars if needed
1333 int NumIvars = IDecl->getImplDeclNumIvars() > 0
1334 ? IDecl->getImplDeclNumIvars()
1335 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
1336
Fariborz Jahanianab3ec252007-10-26 23:09:28 +00001337 SynthesizeObjcInternalStruct(CDecl, Result);
1338
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001339 if (NumIvars > 0) {
1340 static bool objc_ivar = false;
1341 if (!objc_ivar) {
1342 /* struct _objc_ivar {
1343 char *ivar_name;
1344 char *ivar_type;
1345 int ivar_offset;
1346 };
1347 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001348 Result += "\nstruct _objc_ivar {\n";
1349 Result += "\tchar *ivar_name;\n";
1350 Result += "\tchar *ivar_type;\n";
1351 Result += "\tint ivar_offset;\n";
1352 Result += "};\n";
1353
1354 /* struct _objc_ivar_list {
1355 int ivar_count;
1356 struct _objc_ivar ivar_list[];
1357 };
1358 */
1359 Result += "\nstruct _objc_ivar_list {\n";
1360 Result += "\tint ivar_count;\n";
1361 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001362 objc_ivar = true;
1363 }
1364
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001365 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
1366 Result += IDecl->getName();
1367 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
1368 "{\n\t";
1369 Result += utostr(NumIvars);
1370 Result += "\n";
1371
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001372 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
1373 ? IDecl->getImplDeclIVars()
1374 : CDecl->getIntfDeclIvars();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001375 Result += "\t,{{\"";
1376 Result += Ivars[0]->getName();
Fariborz Jahaniand5ea4612007-10-29 17:16:25 +00001377 Result += "\", \"";
1378 std::string StrEncoding;
1379 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
1380 Result += StrEncoding;
1381 Result += "\", ";
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001382 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
1383 Result += "}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001384 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001385 Result += "\t ,{\"";
1386 Result += Ivars[i]->getName();
Fariborz Jahaniand5ea4612007-10-29 17:16:25 +00001387 Result += "\", \"";
1388 std::string StrEncoding;
1389 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
1390 Result += StrEncoding;
1391 Result += "\", ";
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001392 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
1393 Result += "}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001394 }
1395
1396 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001397 }
1398
1399 // Build _objc_method_list for class's instance methods if needed
1400 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1401 IDecl->getNumInstanceMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001402 true,
1403 "", IDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001404
1405 // Build _objc_method_list for class's class methods if needed
1406 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +00001407 IDecl->getNumClassMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001408 false,
1409 "", IDecl->getName(), Result);
1410
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001411 // Protocols referenced in class declaration?
1412 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1413 CDecl->getNumIntfRefProtocols(),
1414 "CLASS",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001415 CDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001416
Fariborz Jahanian0f013d12007-10-23 00:02:02 +00001417
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001418 // Declaration of class/meta-class metadata
1419 /* struct _objc_class {
1420 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian0f013d12007-10-23 00:02:02 +00001421 const char *super_class_name;
1422 char *name;
1423 long version;
1424 long info;
1425 long instance_size;
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001426 struct _objc_ivar_list *ivars;
1427 struct _objc_method_list *methods;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +00001428 struct objc_cache *cache;
1429 struct objc_protocol_list *protocols;
1430 const char *ivar_layout;
1431 struct _objc_class_ext *ext;
1432 };
1433 */
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001434 static bool objc_class = false;
1435 if (!objc_class) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001436 Result += "\nstruct _objc_class {\n";
1437 Result += "\tstruct _objc_class *isa;\n";
1438 Result += "\tconst char *super_class_name;\n";
1439 Result += "\tchar *name;\n";
1440 Result += "\tlong version;\n";
1441 Result += "\tlong info;\n";
1442 Result += "\tlong instance_size;\n";
1443 Result += "\tstruct _objc_ivar_list *ivars;\n";
1444 Result += "\tstruct _objc_method_list *methods;\n";
1445 Result += "\tstruct objc_cache *cache;\n";
1446 Result += "\tstruct _objc_protocol_list *protocols;\n";
1447 Result += "\tconst char *ivar_layout;\n";
1448 Result += "\tstruct _objc_class_ext *ext;\n";
1449 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001450 objc_class = true;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +00001451 }
1452
1453 // Meta-class metadata generation.
1454 ObjcInterfaceDecl *RootClass = 0;
1455 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
1456 while (SuperClass) {
1457 RootClass = SuperClass;
1458 SuperClass = SuperClass->getSuperClass();
1459 }
1460 SuperClass = CDecl->getSuperClass();
1461
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001462 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
1463 Result += CDecl->getName();
1464 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
1465 "{\n\t(struct _objc_class *)\"";
1466 Result += (RootClass ? RootClass->getName() : CDecl->getName());
1467 Result += "\"";
1468
1469 if (SuperClass) {
1470 Result += ", \"";
1471 Result += SuperClass->getName();
1472 Result += "\", \"";
1473 Result += CDecl->getName();
1474 Result += "\"";
1475 }
1476 else {
1477 Result += ", 0, \"";
1478 Result += CDecl->getName();
1479 Result += "\"";
1480 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +00001481 // TODO: 'ivars' field for root class is currently set to 0.
1482 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001483 Result += ", 0,2, sizeof(struct _objc_class), 0";
1484 if (CDecl->getNumClassMethods() > 0) {
1485 Result += "\n\t, &_OBJC_CLASS_METHODS_";
1486 Result += CDecl->getName();
1487 Result += "\n";
1488 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +00001489 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001490 Result += ", 0\n";
1491 if (CDecl->getNumIntfRefProtocols() > 0) {
1492 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
1493 Result += CDecl->getName();
1494 Result += ",0,0\n";
1495 }
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +00001496 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001497 Result += "\t,0,0,0,0\n";
1498 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001499
1500 // class metadata generation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001501 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
1502 Result += CDecl->getName();
1503 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
1504 "{\n\t&_OBJC_METACLASS_";
1505 Result += CDecl->getName();
1506 if (SuperClass) {
1507 Result += ", \"";
1508 Result += SuperClass->getName();
1509 Result += "\", \"";
1510 Result += CDecl->getName();
1511 Result += "\"";
1512 }
1513 else {
1514 Result += ", 0, \"";
1515 Result += CDecl->getName();
1516 Result += "\"";
1517 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001518 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanianab3ec252007-10-26 23:09:28 +00001519 Result += ", 0,1";
1520 if (!ObjcSynthesizedStructs.count(CDecl))
1521 Result += ",0";
1522 else {
1523 // class has size. Must synthesize its size.
Fariborz Jahanian9447e462007-11-05 17:47:33 +00001524 Result += ",sizeof(struct ";
Fariborz Jahanianab3ec252007-10-26 23:09:28 +00001525 Result += CDecl->getName();
1526 Result += ")";
1527 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001528 if (NumIvars > 0) {
1529 Result += ", &_OBJC_INSTANCE_VARIABLES_";
1530 Result += CDecl->getName();
1531 Result += "\n\t";
1532 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001533 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001534 Result += ",0";
1535 if (IDecl->getNumInstanceMethods() > 0) {
1536 Result += ", &_OBJC_INSTANCE_METHODS_";
1537 Result += CDecl->getName();
1538 Result += ", 0\n\t";
1539 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001540 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001541 Result += ",0,0";
1542 if (CDecl->getNumIntfRefProtocols() > 0) {
1543 Result += ", &_OBJC_CLASS_PROTOCOLS_";
1544 Result += CDecl->getName();
1545 Result += ", 0,0\n";
1546 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +00001547 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001548 Result += ",0,0,0\n";
1549 Result += "};\n";
Fariborz Jahanian0f013d12007-10-23 00:02:02 +00001550}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +00001551
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001552void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001553 int ClsDefCount = ClassImplementation.size();
1554 int CatDefCount = CategoryImplementation.size();
1555 if (ClsDefCount == 0 && CatDefCount == 0)
1556 return;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +00001557
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +00001558 // TODO: This is temporary until we decide how to access objc types in a
1559 // c program
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001560 Result += "#include <Objc/objc.h>\n";
1561 // This is needed for use of offsetof
1562 Result += "#include <stddef.h>\n";
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +00001563
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001564 // For each implemented class, write out all its meta data.
Fariborz Jahanian45d52f72007-10-18 22:09:03 +00001565 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001566 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001567
1568 // For each implemented category, write out all its meta data.
1569 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001570 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanian45d52f72007-10-18 22:09:03 +00001571
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001572 // Write objc_symtab metadata
1573 /*
1574 struct _objc_symtab
1575 {
1576 long sel_ref_cnt;
1577 SEL *refs;
1578 short cls_def_cnt;
1579 short cat_def_cnt;
1580 void *defs[cls_def_cnt + cat_def_cnt];
1581 };
1582 */
1583
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001584 Result += "\nstruct _objc_symtab {\n";
1585 Result += "\tlong sel_ref_cnt;\n";
1586 Result += "\tSEL *refs;\n";
1587 Result += "\tshort cls_def_cnt;\n";
1588 Result += "\tshort cat_def_cnt;\n";
1589 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1590 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001591
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001592 Result += "static struct _objc_symtab "
1593 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1594 Result += "\t0, 0, " + utostr(ClsDefCount)
1595 + ", " + utostr(CatDefCount) + "\n";
1596 for (int i = 0; i < ClsDefCount; i++) {
1597 Result += "\t,&_OBJC_CLASS_";
1598 Result += ClassImplementation[i]->getName();
1599 Result += "\n";
1600 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001601
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001602 for (int i = 0; i < CatDefCount; i++) {
1603 Result += "\t,&_OBJC_CATEGORY_";
1604 Result += CategoryImplementation[i]->getClassInterface()->getName();
1605 Result += "_";
1606 Result += CategoryImplementation[i]->getName();
1607 Result += "\n";
1608 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001609
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001610 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001611
1612 // Write objc_module metadata
1613
1614 /*
1615 struct _objc_module {
1616 long version;
1617 long size;
1618 const char *name;
1619 struct _objc_symtab *symtab;
1620 }
1621 */
1622
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001623 Result += "\nstruct _objc_module {\n";
1624 Result += "\tlong version;\n";
1625 Result += "\tlong size;\n";
1626 Result += "\tconst char *name;\n";
1627 Result += "\tstruct _objc_symtab *symtab;\n";
1628 Result += "};\n\n";
1629 Result += "static struct _objc_module "
1630 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001631 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1632 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001633 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001634}
Chris Lattner6fe8b272007-10-16 22:36:42 +00001635