blob: 6b9c611c714caabca9925165619f67a262956c49 [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 Lattner07506182007-11-30 22:53:43 +000020#include "clang/Basic/Diagnostic.h"
Chris Lattner26de4652007-12-02 01:13:47 +000021#include "clang/Lex/Lexer.h"
Chris Lattner158ecb92007-10-25 17:07:24 +000022#include "llvm/ADT/StringExtras.h"
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000023#include "llvm/ADT/SmallPtrSet.h"
Chris Lattner26de4652007-12-02 01:13:47 +000024#include "llvm/Support/MemoryBuffer.h"
Steve Naroff874e2322007-11-15 10:28:18 +000025#include <sstream>
Chris Lattner77cd2a02007-10-11 00:43:27 +000026using namespace clang;
Chris Lattner158ecb92007-10-25 17:07:24 +000027using llvm::utostr;
Chris Lattner77cd2a02007-10-11 00:43:27 +000028
Chris Lattner77cd2a02007-10-11 00:43:27 +000029namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000030 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000031 Rewriter Rewrite;
Chris Lattnere365c502007-11-30 22:25:36 +000032 Diagnostic &Diags;
Chris Lattner01c57482007-10-17 22:35:30 +000033 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000034 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000035 unsigned MainFileID;
Chris Lattner26de4652007-12-02 01:13:47 +000036 const char *MainFileStart, *MainFileEnd;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000037 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000038 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
39 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000040 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcSynthesizedStructs;
Steve Naroff8749be52007-10-31 22:11:35 +000041 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcForwardDecls;
Fariborz Jahanianb7908b52007-11-13 21:02:00 +000042 llvm::DenseMap<ObjcMethodDecl*, std::string> MethodInternalNames;
Steve Naroffebf2b562007-10-23 23:50:29 +000043
44 FunctionDecl *MsgSendFunctionDecl;
Steve Naroff874e2322007-11-15 10:28:18 +000045 FunctionDecl *MsgSendSuperFunctionDecl;
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +000046 FunctionDecl *MsgSendStretFunctionDecl;
47 FunctionDecl *MsgSendSuperStretFunctionDecl;
Fariborz Jahanianacb49772007-12-03 21:26:48 +000048 FunctionDecl *MsgSendFpretFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000049 FunctionDecl *GetClassFunctionDecl;
Steve Naroff9bcb5fc2007-12-07 03:50:46 +000050 FunctionDecl *GetMetaClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000051 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroff96984642007-11-08 14:30:50 +000052 FunctionDecl *CFStringFunctionDecl;
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +000053
Steve Naroffbeaf2992007-11-03 11:27:19 +000054 // ObjC string constant support.
55 FileVarDecl *ConstantStringClassReference;
56 RecordDecl *NSStringRecord;
Steve Naroffab972d32007-11-04 22:37:50 +000057
Steve Naroff874e2322007-11-15 10:28:18 +000058 // Needed for super.
59 ObjcMethodDecl *CurMethodDecl;
60 RecordDecl *SuperStructDecl;
61
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000062 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000063 public:
Chris Lattner01c57482007-10-17 22:35:30 +000064 void Initialize(ASTContext &context, unsigned mainFileID) {
65 Context = &context;
66 SM = &Context->SourceMgr;
Steve Naroffebf2b562007-10-23 23:50:29 +000067 MsgSendFunctionDecl = 0;
Steve Naroff874e2322007-11-15 10:28:18 +000068 MsgSendSuperFunctionDecl = 0;
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +000069 MsgSendStretFunctionDecl = 0;
70 MsgSendSuperStretFunctionDecl = 0;
Fariborz Jahanianacb49772007-12-03 21:26:48 +000071 MsgSendFpretFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000072 GetClassFunctionDecl = 0;
Steve Naroff9bcb5fc2007-12-07 03:50:46 +000073 GetMetaClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000074 SelGetUidFunctionDecl = 0;
Steve Naroff96984642007-11-08 14:30:50 +000075 CFStringFunctionDecl = 0;
Steve Naroffbeaf2992007-11-03 11:27:19 +000076 ConstantStringClassReference = 0;
77 NSStringRecord = 0;
Steve Naroff874e2322007-11-15 10:28:18 +000078 CurMethodDecl = 0;
79 SuperStructDecl = 0;
80
Chris Lattner26de4652007-12-02 01:13:47 +000081 // Get the ID and start/end of the main file.
82 MainFileID = mainFileID;
83 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
84 MainFileStart = MainBuf->getBufferStart();
85 MainFileEnd = MainBuf->getBufferEnd();
86
87
Chris Lattner01c57482007-10-17 22:35:30 +000088 Rewrite.setSourceMgr(Context->SourceMgr);
Steve Naroffe3abbf52007-11-05 14:55:35 +000089 // declaring objc_selector outside the parameter list removes a silly
90 // scope related warning...
Steve Naroff3cadd032007-12-04 23:59:30 +000091 const char *s = "struct objc_selector; struct objc_class;\n"
92 "#ifndef OBJC_SUPER\n"
93 "struct objc_super { struct objc_object *o; struct objc_object *superClass; };\n"
94 "#define OBJC_SUPER\n"
95 "#endif\n"
Steve Naroffe3abbf52007-11-05 14:55:35 +000096 "extern struct objc_object *objc_msgSend"
Steve Naroffab972d32007-11-04 22:37:50 +000097 "(struct objc_object *, struct objc_selector *, ...);\n"
Steve Naroff874e2322007-11-15 10:28:18 +000098 "extern struct objc_object *objc_msgSendSuper"
99 "(struct objc_super *, struct objc_selector *, ...);\n"
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +0000100 "extern struct objc_object *objc_msgSend_stret"
101 "(struct objc_object *, struct objc_selector *, ...);\n"
102 "extern struct objc_object *objc_msgSendSuper_stret"
103 "(struct objc_super *, struct objc_selector *, ...);\n"
Fariborz Jahanianacb49772007-12-03 21:26:48 +0000104 "extern struct objc_object *objc_msgSend_fpret"
105 "(struct objc_object *, struct objc_selector *, ...);\n"
Steve Naroffab972d32007-11-04 22:37:50 +0000106 "extern struct objc_object *objc_getClass"
Steve Naroff21867b12007-11-07 18:43:40 +0000107 "(const char *);\n"
Steve Naroff9bcb5fc2007-12-07 03:50:46 +0000108 "extern struct objc_object *objc_getMetaClass"
109 "(const char *);\n"
Steve Naroff21867b12007-11-07 18:43:40 +0000110 "extern void objc_exception_throw(struct objc_object *);\n"
111 "extern void objc_exception_try_enter(void *);\n"
112 "extern void objc_exception_try_exit(void *);\n"
113 "extern struct objc_object *objc_exception_extract(void *);\n"
114 "extern int objc_exception_match"
Fariborz Jahanian95673922007-11-14 22:26:25 +0000115 "(struct objc_class *, struct objc_object *, ...);\n"
Fariborz Jahanian2c1e9c72007-12-03 23:04:29 +0000116 "#include <objc/objc.h>\n";
Steve Naroff21867b12007-11-07 18:43:40 +0000117
Steve Naroffab972d32007-11-04 22:37:50 +0000118 Rewrite.InsertText(SourceLocation::getFileLoc(mainFileID, 0),
119 s, strlen(s));
Chris Lattner77cd2a02007-10-11 00:43:27 +0000120 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000121
Chris Lattnerf04da132007-10-24 17:06:59 +0000122 // Top Level Driver code.
123 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000124 void HandleDeclInMainFile(Decl *D);
Chris Lattnere365c502007-11-30 22:25:36 +0000125 RewriteTest(Diagnostic &D) : Diags(D) {}
Chris Lattnerf04da132007-10-24 17:06:59 +0000126 ~RewriteTest();
127
128 // Syntactic Rewriting.
Steve Naroffab972d32007-11-04 22:37:50 +0000129 void RewritePrologue(SourceLocation Loc);
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000130 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +0000131 void RewriteTabs();
132 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffbef11852007-10-26 20:53:56 +0000133 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000134 void RewriteImplementationDecl(NamedDecl *Dcl);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000135 void RewriteObjcMethodDecl(ObjcMethodDecl *MDecl, std::string &ResultStr);
Steve Naroff423cb562007-10-30 13:30:57 +0000136 void RewriteCategoryDecl(ObjcCategoryDecl *Dcl);
Steve Naroff752d6ef2007-10-30 16:42:30 +0000137 void RewriteProtocolDecl(ObjcProtocolDecl *Dcl);
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000138 void RewriteForwardProtocolDecl(ObjcForwardProtocolDecl *Dcl);
Steve Naroff71c0a952007-11-13 23:01:27 +0000139 void RewriteMethodDeclarations(int nMethods, ObjcMethodDecl **Methods);
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000140 void RewriteProperties(int nProperties, ObjcPropertyDecl **Properties);
Steve Naroff09b266e2007-10-30 23:14:51 +0000141 void RewriteFunctionDecl(FunctionDecl *FD);
Steve Naroffd5255f52007-11-01 13:24:47 +0000142 void RewriteObjcQualifiedInterfaceTypes(
143 const FunctionTypeProto *proto, FunctionDecl *FD);
144 bool needToScanForQualifiers(QualType T);
Steve Naroff874e2322007-11-15 10:28:18 +0000145 ObjcInterfaceDecl *isSuperReceiver(Expr *recExpr);
146 QualType getSuperStructType();
Chris Lattner311ff022007-10-16 22:36:42 +0000147
Chris Lattnerf04da132007-10-24 17:06:59 +0000148 // Expression Rewriting.
Steve Narofff3473a72007-11-09 15:20:18 +0000149 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
Chris Lattnere64b7772007-10-24 16:57:36 +0000150 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Steve Naroff7e3411b2007-11-15 02:58:25 +0000151 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
Steve Naroffb42f8412007-11-05 14:50:49 +0000152 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Chris Lattnere64b7772007-10-24 16:57:36 +0000153 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000154 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000155 Stmt *RewriteObjcTryStmt(ObjcAtTryStmt *S);
156 Stmt *RewriteObjcCatchStmt(ObjcAtCatchStmt *S);
157 Stmt *RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S);
Steve Naroff2bd03922007-11-07 15:32:26 +0000158 Stmt *RewriteObjcThrowStmt(ObjcAtThrowStmt *S);
Steve Naroff934f2762007-10-24 22:48:43 +0000159 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
160 Expr **args, unsigned nargs);
Steve Naroff09b266e2007-10-30 23:14:51 +0000161 void SynthMsgSendFunctionDecl();
Steve Naroff874e2322007-11-15 10:28:18 +0000162 void SynthMsgSendSuperFunctionDecl();
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +0000163 void SynthMsgSendStretFunctionDecl();
Fariborz Jahanianacb49772007-12-03 21:26:48 +0000164 void SynthMsgSendFpretFunctionDecl();
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +0000165 void SynthMsgSendSuperStretFunctionDecl();
Steve Naroff09b266e2007-10-30 23:14:51 +0000166 void SynthGetClassFunctionDecl();
Steve Naroff9bcb5fc2007-12-07 03:50:46 +0000167 void SynthGetMetaClassFunctionDecl();
Steve Naroff96984642007-11-08 14:30:50 +0000168 void SynthCFStringFunctionDecl();
Fariborz Jahaniana70711b2007-12-04 21:47:40 +0000169 void SynthSelGetUidFunctionDecl();
Steve Naroff96984642007-11-08 14:30:50 +0000170
Chris Lattnerf04da132007-10-24 17:06:59 +0000171 // Metadata emission.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000172 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
173 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000174
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000175 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
176 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000177
Steve Naroff0416fb92007-11-11 17:19:15 +0000178 void RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000179 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000180 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000181 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000182 const char *ClassName,
183 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000184
185 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
186 int NumProtocols,
187 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000188 const char *ClassName,
189 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000190 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
191 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000192 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
193 ObjcIvarDecl *ivar,
194 std::string &Result);
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +0000195 void RewriteImplementations(std::string &Result);
Chris Lattner77cd2a02007-10-11 00:43:27 +0000196 };
197}
198
Chris Lattnere365c502007-11-30 22:25:36 +0000199ASTConsumer *clang::CreateCodeRewriterTest(Diagnostic &Diags) {
200 return new RewriteTest(Diags);
201}
Chris Lattner77cd2a02007-10-11 00:43:27 +0000202
Chris Lattnerf04da132007-10-24 17:06:59 +0000203//===----------------------------------------------------------------------===//
204// Top Level Driver Code
205//===----------------------------------------------------------------------===//
206
Chris Lattner8a12c272007-10-11 18:38:32 +0000207void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000208 // Two cases: either the decl could be in the main file, or it could be in a
209 // #included file. If the former, rewrite it now. If the later, check to see
210 // if we rewrote the #include/#import.
211 SourceLocation Loc = D->getLocation();
212 Loc = SM->getLogicalLoc(Loc);
213
214 // If this is for a builtin, ignore it.
215 if (Loc.isInvalid()) return;
216
Steve Naroffebf2b562007-10-23 23:50:29 +0000217 // Look for built-in declarations that we need to refer during the rewrite.
218 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff09b266e2007-10-30 23:14:51 +0000219 RewriteFunctionDecl(FD);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000220 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
221 // declared in <Foundation/NSString.h>
222 if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) {
223 ConstantStringClassReference = FVD;
224 return;
225 }
Steve Naroffbef11852007-10-26 20:53:56 +0000226 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
227 RewriteInterfaceDecl(MD);
Steve Naroff423cb562007-10-30 13:30:57 +0000228 } else if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(D)) {
229 RewriteCategoryDecl(CD);
Steve Naroff752d6ef2007-10-30 16:42:30 +0000230 } else if (ObjcProtocolDecl *PD = dyn_cast<ObjcProtocolDecl>(D)) {
231 RewriteProtocolDecl(PD);
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000232 } else if (ObjcForwardProtocolDecl *FP =
233 dyn_cast<ObjcForwardProtocolDecl>(D)){
234 RewriteForwardProtocolDecl(FP);
Steve Naroffebf2b562007-10-23 23:50:29 +0000235 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000236 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000237 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
238 return HandleDeclInMainFile(D);
239
Chris Lattnerf04da132007-10-24 17:06:59 +0000240 // Otherwise, see if there is a #import in the main file that should be
241 // rewritten.
Steve Naroff32174822007-11-09 12:50:28 +0000242 //RewriteInclude(Loc);
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000243}
244
Chris Lattnerf04da132007-10-24 17:06:59 +0000245/// HandleDeclInMainFile - This is called for each top-level decl defined in the
246/// main file of the input.
247void RewriteTest::HandleDeclInMainFile(Decl *D) {
248 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
249 if (Stmt *Body = FD->getBody())
Steve Narofff3473a72007-11-09 15:20:18 +0000250 FD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
Steve Naroff71c0a952007-11-13 23:01:27 +0000251
252 if (ObjcMethodDecl *MD = dyn_cast<ObjcMethodDecl>(D)) {
Steve Naroff874e2322007-11-15 10:28:18 +0000253 if (Stmt *Body = MD->getBody()) {
254 //Body->dump();
255 CurMethodDecl = MD;
Steve Naroff71c0a952007-11-13 23:01:27 +0000256 MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
Steve Naroff874e2322007-11-15 10:28:18 +0000257 CurMethodDecl = 0;
258 }
Steve Naroff71c0a952007-11-13 23:01:27 +0000259 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000260 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
261 ClassImplementation.push_back(CI);
262 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
263 CategoryImplementation.push_back(CI);
264 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
265 RewriteForwardClassDecl(CD);
Steve Narofff3473a72007-11-09 15:20:18 +0000266 else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
267 if (VD->getInit())
268 RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
269 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000270 // Nothing yet.
271}
272
273RewriteTest::~RewriteTest() {
274 // Get the top-level buffer that this corresponds to.
Chris Lattner74a0c772007-11-08 04:27:23 +0000275
276 // Rewrite tabs if we care.
277 //RewriteTabs();
Chris Lattnerf04da132007-10-24 17:06:59 +0000278
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000279 // Rewrite Objective-c meta data*
280 std::string ResultStr;
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +0000281 RewriteImplementations(ResultStr);
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000282
Chris Lattnerf04da132007-10-24 17:06:59 +0000283 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
284 // we are done.
285 if (const RewriteBuffer *RewriteBuf =
286 Rewrite.getRewriteBufferFor(MainFileID)) {
Steve Naroffbeaf2992007-11-03 11:27:19 +0000287 //printf("Changed:\n");
Chris Lattnerf04da132007-10-24 17:06:59 +0000288 std::string S(RewriteBuf->begin(), RewriteBuf->end());
289 printf("%s\n", S.c_str());
290 } else {
291 printf("No changes\n");
292 }
Fariborz Jahanian4402d812007-11-07 18:40:28 +0000293 // Emit metadata.
294 printf("%s", ResultStr.c_str());
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000295}
296
Chris Lattnerf04da132007-10-24 17:06:59 +0000297//===----------------------------------------------------------------------===//
298// Syntactic (non-AST) Rewriting Code
299//===----------------------------------------------------------------------===//
300
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000301void RewriteTest::RewriteInclude(SourceLocation Loc) {
302 // Rip up the #include stack to the main file.
303 SourceLocation IncLoc = Loc, NextLoc = Loc;
304 do {
305 IncLoc = Loc;
306 Loc = SM->getLogicalLoc(NextLoc);
307 NextLoc = SM->getIncludeLoc(Loc);
308 } while (!NextLoc.isInvalid());
309
310 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
311 // IncLoc indicates the header that was included if it is useful.
312 IncLoc = SM->getLogicalLoc(IncLoc);
313 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
314 Loc == LastIncLoc)
315 return;
316 LastIncLoc = Loc;
317
318 unsigned IncCol = SM->getColumnNumber(Loc);
319 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
320
321 // Replace the #import with #include.
322 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
323}
324
Chris Lattnerf04da132007-10-24 17:06:59 +0000325void RewriteTest::RewriteTabs() {
326 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
327 const char *MainBufStart = MainBuf.first;
328 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000329
Chris Lattnerf04da132007-10-24 17:06:59 +0000330 // Loop over the whole file, looking for tabs.
331 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
332 if (*BufPtr != '\t')
333 continue;
334
335 // Okay, we found a tab. This tab will turn into at least one character,
336 // but it depends on which 'virtual column' it is in. Compute that now.
337 unsigned VCol = 0;
338 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
339 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
340 ++VCol;
341
342 // Okay, now that we know the virtual column, we know how many spaces to
343 // insert. We assume 8-character tab-stops.
344 unsigned Spaces = 8-(VCol & 7);
345
346 // Get the location of the tab.
347 SourceLocation TabLoc =
348 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
349
350 // Rewrite the single tab character into a sequence of spaces.
351 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
352 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000353}
354
355
Chris Lattnerf04da132007-10-24 17:06:59 +0000356void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
357 int numDecls = ClassDecl->getNumForwardDecls();
358 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
359
360 // Get the start location and compute the semi location.
361 SourceLocation startLoc = ClassDecl->getLocation();
362 const char *startBuf = SM->getCharacterData(startLoc);
363 const char *semiPtr = strchr(startBuf, ';');
364
365 // Translate to typedef's that forward reference structs with the same name
366 // as the class. As a convenience, we include the original declaration
367 // as a comment.
368 std::string typedefString;
369 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000370 typedefString.append(startBuf, semiPtr-startBuf+1);
371 typedefString += "\n";
372 for (int i = 0; i < numDecls; i++) {
373 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
Steve Naroff32174822007-11-09 12:50:28 +0000374 typedefString += "#ifndef _REWRITER_typedef_";
375 typedefString += ForwardDecl->getName();
376 typedefString += "\n";
377 typedefString += "#define _REWRITER_typedef_";
378 typedefString += ForwardDecl->getName();
379 typedefString += "\n";
Steve Naroff352336b2007-11-05 14:36:37 +0000380 typedefString += "typedef struct objc_object ";
Steve Naroff934f2762007-10-24 22:48:43 +0000381 typedefString += ForwardDecl->getName();
Steve Naroff32174822007-11-09 12:50:28 +0000382 typedefString += ";\n#endif\n";
Steve Naroff934f2762007-10-24 22:48:43 +0000383 }
384
385 // Replace the @class with typedefs corresponding to the classes.
386 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
387 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000388}
389
Steve Naroff71c0a952007-11-13 23:01:27 +0000390void RewriteTest::RewriteMethodDeclarations(int nMethods, ObjcMethodDecl **Methods) {
Steve Naroff423cb562007-10-30 13:30:57 +0000391 for (int i = 0; i < nMethods; i++) {
392 ObjcMethodDecl *Method = Methods[i];
Steve Naroff1d098f62007-11-14 14:34:23 +0000393 SourceLocation LocStart = Method->getLocStart();
394 SourceLocation LocEnd = Method->getLocEnd();
Steve Naroff423cb562007-10-30 13:30:57 +0000395
Steve Naroff1d098f62007-11-14 14:34:23 +0000396 if (SM->getLineNumber(LocEnd) > SM->getLineNumber(LocStart)) {
397 Rewrite.InsertText(LocStart, "/* ", 3);
398 Rewrite.ReplaceText(LocEnd, 1, ";*/ ", 4);
399 } else {
400 Rewrite.InsertText(LocStart, "// ", 3);
401 }
Steve Naroff423cb562007-10-30 13:30:57 +0000402 }
403}
404
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000405void RewriteTest::RewriteProperties(int nProperties, ObjcPropertyDecl **Properties)
406{
407 for (int i = 0; i < nProperties; i++) {
408 ObjcPropertyDecl *Property = Properties[i];
409 SourceLocation Loc = Property->getLocation();
410
411 Rewrite.ReplaceText(Loc, 0, "// ", 3);
412
413 // FIXME: handle properties that are declared across multiple lines.
414 }
415}
416
Steve Naroff423cb562007-10-30 13:30:57 +0000417void RewriteTest::RewriteCategoryDecl(ObjcCategoryDecl *CatDecl) {
418 SourceLocation LocStart = CatDecl->getLocStart();
419
420 // FIXME: handle category headers that are declared across multiple lines.
421 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
422
Steve Naroff71c0a952007-11-13 23:01:27 +0000423 RewriteMethodDeclarations(CatDecl->getNumInstanceMethods(),
424 CatDecl->getInstanceMethods());
425 RewriteMethodDeclarations(CatDecl->getNumClassMethods(),
426 CatDecl->getClassMethods());
Steve Naroff423cb562007-10-30 13:30:57 +0000427 // Lastly, comment out the @end.
428 Rewrite.ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3);
429}
430
Steve Naroff752d6ef2007-10-30 16:42:30 +0000431void RewriteTest::RewriteProtocolDecl(ObjcProtocolDecl *PDecl) {
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000432 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000433
Steve Naroff752d6ef2007-10-30 16:42:30 +0000434 SourceLocation LocStart = PDecl->getLocStart();
435
436 // FIXME: handle protocol headers that are declared across multiple lines.
437 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
438
Steve Naroff71c0a952007-11-13 23:01:27 +0000439 RewriteMethodDeclarations(PDecl->getNumInstanceMethods(),
440 PDecl->getInstanceMethods());
441 RewriteMethodDeclarations(PDecl->getNumClassMethods(),
442 PDecl->getClassMethods());
Steve Naroff752d6ef2007-10-30 16:42:30 +0000443 // Lastly, comment out the @end.
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000444 SourceLocation LocEnd = PDecl->getAtEndLoc();
445 Rewrite.ReplaceText(LocEnd, 0, "// ", 3);
Steve Naroff8cc764c2007-11-14 15:03:57 +0000446
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000447 // Must comment out @optional/@required
448 const char *startBuf = SM->getCharacterData(LocStart);
449 const char *endBuf = SM->getCharacterData(LocEnd);
450 for (const char *p = startBuf; p < endBuf; p++) {
451 if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
452 std::string CommentedOptional = "/* @optional */";
Steve Naroff8cc764c2007-11-14 15:03:57 +0000453 SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000454 Rewrite.ReplaceText(OptionalLoc, strlen("@optional"),
455 CommentedOptional.c_str(), CommentedOptional.size());
456
457 }
458 else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
459 std::string CommentedRequired = "/* @required */";
Steve Naroff8cc764c2007-11-14 15:03:57 +0000460 SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
Fariborz Jahanianb82b3ea2007-11-14 01:37:46 +0000461 Rewrite.ReplaceText(OptionalLoc, strlen("@required"),
462 CommentedRequired.c_str(), CommentedRequired.size());
463
464 }
465 }
Steve Naroff752d6ef2007-10-30 16:42:30 +0000466}
467
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000468void RewriteTest::RewriteForwardProtocolDecl(ObjcForwardProtocolDecl *PDecl) {
469 SourceLocation LocStart = PDecl->getLocation();
Steve Naroffb7fa9922007-11-14 03:37:28 +0000470 if (LocStart.isInvalid())
471 assert(false && "Invalid SourceLocation");
Fariborz Jahaniand175ddf2007-11-14 00:42:16 +0000472 // FIXME: handle forward protocol that are declared across multiple lines.
473 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
474}
475
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000476void RewriteTest::RewriteObjcMethodDecl(ObjcMethodDecl *OMD,
477 std::string &ResultStr) {
478 ResultStr += "\nstatic ";
479 ResultStr += OMD->getResultType().getAsString();
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000480 ResultStr += "\n";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000481
482 // Unique method name
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000483 std::string NameStr;
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000484
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000485 if (OMD->isInstance())
486 NameStr += "_I_";
487 else
488 NameStr += "_C_";
489
490 NameStr += OMD->getClassInterface()->getName();
491 NameStr += "_";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000492
493 NamedDecl *MethodContext = OMD->getMethodContext();
494 if (ObjcCategoryImplDecl *CID =
495 dyn_cast<ObjcCategoryImplDecl>(MethodContext)) {
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000496 NameStr += CID->getName();
497 NameStr += "_";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000498 }
499 // Append selector names, replacing ':' with '_'
500 const char *selName = OMD->getSelector().getName().c_str();
501 if (!strchr(selName, ':'))
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000502 NameStr += OMD->getSelector().getName();
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000503 else {
504 std::string selString = OMD->getSelector().getName();
505 int len = selString.size();
506 for (int i = 0; i < len; i++)
507 if (selString[i] == ':')
508 selString[i] = '_';
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000509 NameStr += selString;
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000510 }
Fariborz Jahanianb7908b52007-11-13 21:02:00 +0000511 // Remember this name for metadata emission
512 MethodInternalNames[OMD] = NameStr;
513 ResultStr += NameStr;
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000514
515 // Rewrite arguments
516 ResultStr += "(";
517
518 // invisible arguments
519 if (OMD->isInstance()) {
520 QualType selfTy = Context->getObjcInterfaceType(OMD->getClassInterface());
521 selfTy = Context->getPointerType(selfTy);
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000522 if (ObjcSynthesizedStructs.count(OMD->getClassInterface()))
523 ResultStr += "struct ";
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000524 ResultStr += selfTy.getAsString();
525 }
526 else
527 ResultStr += Context->getObjcIdType().getAsString();
528
529 ResultStr += " self, ";
530 ResultStr += Context->getObjcSelType().getAsString();
531 ResultStr += " _cmd";
532
533 // Method arguments.
534 for (int i = 0; i < OMD->getNumParams(); i++) {
535 ParmVarDecl *PDecl = OMD->getParamDecl(i);
536 ResultStr += ", ";
537 ResultStr += PDecl->getType().getAsString();
538 ResultStr += " ";
539 ResultStr += PDecl->getName();
540 }
541 ResultStr += ")";
542
543}
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000544void RewriteTest::RewriteImplementationDecl(NamedDecl *OID) {
545 ObjcImplementationDecl *IMD = dyn_cast<ObjcImplementationDecl>(OID);
546 ObjcCategoryImplDecl *CID = dyn_cast<ObjcCategoryImplDecl>(OID);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000547
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000548 if (IMD)
549 Rewrite.InsertText(IMD->getLocStart(), "// ", 3);
550 else
551 Rewrite.InsertText(CID->getLocStart(), "// ", 3);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000552
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000553 int numMethods = IMD ? IMD->getNumInstanceMethods()
554 : CID->getNumInstanceMethods();
555
556 for (int i = 0; i < numMethods; i++) {
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000557 std::string ResultStr;
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000558 ObjcMethodDecl *OMD;
559 if (IMD)
560 OMD = IMD->getInstanceMethods()[i];
561 else
562 OMD = CID->getInstanceMethods()[i];
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000563 RewriteObjcMethodDecl(OMD, ResultStr);
564 SourceLocation LocStart = OMD->getLocStart();
565 SourceLocation LocEnd = OMD->getBody()->getLocStart();
566
567 const char *startBuf = SM->getCharacterData(LocStart);
568 const char *endBuf = SM->getCharacterData(LocEnd);
569 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
570 ResultStr.c_str(), ResultStr.size());
571 }
572
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000573 numMethods = IMD ? IMD->getNumClassMethods() : CID->getNumClassMethods();
574 for (int i = 0; i < numMethods; i++) {
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000575 std::string ResultStr;
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000576 ObjcMethodDecl *OMD;
577 if (IMD)
578 OMD = IMD->getClassMethods()[i];
579 else
580 OMD = CID->getClassMethods()[i];
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000581 RewriteObjcMethodDecl(OMD, ResultStr);
582 SourceLocation LocStart = OMD->getLocStart();
583 SourceLocation LocEnd = OMD->getBody()->getLocStart();
584
585 const char *startBuf = SM->getCharacterData(LocStart);
586 const char *endBuf = SM->getCharacterData(LocEnd);
587 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
588 ResultStr.c_str(), ResultStr.size());
589 }
Fariborz Jahanian66d6b292007-11-13 20:04:28 +0000590 if (IMD)
591 Rewrite.InsertText(IMD->getLocEnd(), "// ", 3);
592 else
593 Rewrite.InsertText(CID->getLocEnd(), "// ", 3);
Fariborz Jahanian48a0b6a2007-11-13 18:44:14 +0000594}
595
Steve Naroffbef11852007-10-26 20:53:56 +0000596void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
Steve Narofff908a872007-10-30 02:23:23 +0000597 std::string ResultStr;
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000598 if (!ObjcForwardDecls.count(ClassDecl)) {
599 // we haven't seen a forward decl - generate a typedef.
Steve Naroff5086a8d2007-11-14 23:02:56 +0000600 ResultStr = "#ifndef _REWRITER_typedef_";
Steve Naroff32174822007-11-09 12:50:28 +0000601 ResultStr += ClassDecl->getName();
602 ResultStr += "\n";
603 ResultStr += "#define _REWRITER_typedef_";
604 ResultStr += ClassDecl->getName();
605 ResultStr += "\n";
Fariborz Jahanian87ce5d12007-12-03 22:25:42 +0000606 ResultStr += "typedef struct ";
607 ResultStr += ClassDecl->getName();
608 ResultStr += " ";
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000609 ResultStr += ClassDecl->getName();
Steve Naroff32174822007-11-09 12:50:28 +0000610 ResultStr += ";\n#endif\n";
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000611
612 // Mark this typedef as having been generated.
613 ObjcForwardDecls.insert(ClassDecl);
614 }
Steve Narofff908a872007-10-30 02:23:23 +0000615 SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
616
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000617 RewriteProperties(ClassDecl->getNumPropertyDecl(),
618 ClassDecl->getPropertyDecl());
Steve Naroff71c0a952007-11-13 23:01:27 +0000619 RewriteMethodDeclarations(ClassDecl->getNumInstanceMethods(),
620 ClassDecl->getInstanceMethods());
621 RewriteMethodDeclarations(ClassDecl->getNumClassMethods(),
622 ClassDecl->getClassMethods());
Steve Naroffbef11852007-10-26 20:53:56 +0000623
Steve Naroff2feac5e2007-10-30 03:43:13 +0000624 // Lastly, comment out the @end.
625 Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
Steve Naroffbef11852007-10-26 20:53:56 +0000626}
627
Steve Naroff7e3411b2007-11-15 02:58:25 +0000628Stmt *RewriteTest::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
629 ObjcIvarDecl *D = IV->getDecl();
630 if (IV->isFreeIvar()) {
631 Expr *Replacement = new MemberExpr(IV->getBase(), true, D,
632 IV->getLocation());
633 Rewrite.ReplaceStmt(IV, Replacement);
634 delete IV;
635 return Replacement;
Steve Naroffc2a689b2007-11-15 11:33:00 +0000636 } else {
637 if (CurMethodDecl) {
638 if (const PointerType *pType = IV->getBase()->getType()->getAsPointerType()) {
639 ObjcInterfaceType *intT = dyn_cast<ObjcInterfaceType>(pType->getPointeeType());
640 if (CurMethodDecl->getClassInterface() == intT->getDecl()) {
641 IdentifierInfo *II = intT->getDecl()->getIdentifier();
642 RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
643 II, 0);
644 QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
645
646 CastExpr *castExpr = new CastExpr(castT, IV->getBase(), SourceLocation());
647 // Don't forget the parens to enforce the proper binding.
648 ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), castExpr);
649 Rewrite.ReplaceStmt(IV->getBase(), PE);
650 delete IV->getBase();
651 return PE;
652 }
653 }
654 }
Steve Naroff7e3411b2007-11-15 02:58:25 +0000655 return IV;
Steve Naroffc2a689b2007-11-15 11:33:00 +0000656 }
Steve Naroff7e3411b2007-11-15 02:58:25 +0000657}
658
Chris Lattnerf04da132007-10-24 17:06:59 +0000659//===----------------------------------------------------------------------===//
660// Function Body / Expression rewriting
661//===----------------------------------------------------------------------===//
662
Steve Narofff3473a72007-11-09 15:20:18 +0000663Stmt *RewriteTest::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000664 // Otherwise, just rewrite all children.
665 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
666 CI != E; ++CI)
Steve Naroff75730982007-11-07 04:08:17 +0000667 if (*CI) {
Steve Narofff3473a72007-11-09 15:20:18 +0000668 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(*CI);
Steve Naroff75730982007-11-07 04:08:17 +0000669 if (newStmt)
670 *CI = newStmt;
671 }
Steve Naroffebf2b562007-10-23 23:50:29 +0000672
673 // Handle specific things.
674 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
675 return RewriteAtEncode(AtEncode);
Steve Naroff7e3411b2007-11-15 02:58:25 +0000676
677 if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S))
678 return RewriteObjCIvarRefExpr(IvarRefExpr);
Steve Naroffb42f8412007-11-05 14:50:49 +0000679
680 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
681 return RewriteAtSelector(AtSelector);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000682
683 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
684 return RewriteObjCStringLiteral(AtString);
Steve Naroffebf2b562007-10-23 23:50:29 +0000685
Steve Naroff934f2762007-10-24 22:48:43 +0000686 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
687 // Before we rewrite it, put the original message expression in a comment.
688 SourceLocation startLoc = MessExpr->getLocStart();
689 SourceLocation endLoc = MessExpr->getLocEnd();
690
691 const char *startBuf = SM->getCharacterData(startLoc);
692 const char *endBuf = SM->getCharacterData(endLoc);
693
694 std::string messString;
695 messString += "// ";
696 messString.append(startBuf, endBuf-startBuf+1);
697 messString += "\n";
Steve Naroffbef11852007-10-26 20:53:56 +0000698
Steve Naroff934f2762007-10-24 22:48:43 +0000699 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
700 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
701 // Tried this, but it didn't work either...
Steve Naroff752d6ef2007-10-30 16:42:30 +0000702 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000703 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000704 }
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000705
706 if (ObjcAtTryStmt *StmtTry = dyn_cast<ObjcAtTryStmt>(S))
707 return RewriteObjcTryStmt(StmtTry);
Steve Naroff2bd03922007-11-07 15:32:26 +0000708
709 if (ObjcAtThrowStmt *StmtThrow = dyn_cast<ObjcAtThrowStmt>(S))
710 return RewriteObjcThrowStmt(StmtThrow);
Steve Naroff874e2322007-11-15 10:28:18 +0000711#if 0
712 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
713 CastExpr *Replacement = new CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
714 // Get the new text.
715 std::ostringstream Buf;
716 Replacement->printPretty(Buf);
717 const std::string &Str = Buf.str();
718
719 printf("CAST = %s\n", &Str[0]);
720 Rewrite.InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
721 delete S;
722 return Replacement;
723 }
724#endif
Chris Lattnere64b7772007-10-24 16:57:36 +0000725 // Return this stmt unmodified.
726 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000727}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000728
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000729Stmt *RewriteTest::RewriteObjcTryStmt(ObjcAtTryStmt *S) {
Steve Naroff75730982007-11-07 04:08:17 +0000730 // Get the start location and compute the semi location.
731 SourceLocation startLoc = S->getLocStart();
732 const char *startBuf = SM->getCharacterData(startLoc);
733
734 assert((*startBuf == '@') && "bogus @try location");
735
736 std::string buf;
737 // declare a new scope with two variables, _stack and _rethrow.
738 buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
739 buf += "int buf[18/*32-bit i386*/];\n";
740 buf += "char *pointers[4];} _stack;\n";
741 buf += "id volatile _rethrow = 0;\n";
742 buf += "objc_exception_try_enter(&_stack);\n";
Steve Naroff21867b12007-11-07 18:43:40 +0000743 buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
Steve Naroff75730982007-11-07 04:08:17 +0000744
745 Rewrite.ReplaceText(startLoc, 4, buf.c_str(), buf.size());
746
747 startLoc = S->getTryBody()->getLocEnd();
748 startBuf = SM->getCharacterData(startLoc);
749
750 assert((*startBuf == '}') && "bogus @try block");
751
752 SourceLocation lastCurlyLoc = startLoc;
753
754 startLoc = startLoc.getFileLocWithOffset(1);
755 buf = " /* @catch begin */ else {\n";
756 buf += " id _caught = objc_exception_extract(&_stack);\n";
757 buf += " objc_exception_try_enter (&_stack);\n";
Steve Naroff21867b12007-11-07 18:43:40 +0000758 buf += " if (_setjmp(_stack.buf))\n";
Steve Naroff75730982007-11-07 04:08:17 +0000759 buf += " _rethrow = objc_exception_extract(&_stack);\n";
760 buf += " else { /* @catch continue */";
761
Chris Lattner28d1fe82007-11-08 04:41:51 +0000762 Rewrite.InsertText(startLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000763
764 bool sawIdTypedCatch = false;
765 Stmt *lastCatchBody = 0;
766 ObjcAtCatchStmt *catchList = S->getCatchStmts();
767 while (catchList) {
768 Stmt *catchStmt = catchList->getCatchParamStmt();
769
770 if (catchList == S->getCatchStmts())
771 buf = "if ("; // we are generating code for the first catch clause
772 else
773 buf = "else if (";
774 startLoc = catchList->getLocStart();
775 startBuf = SM->getCharacterData(startLoc);
776
777 assert((*startBuf == '@') && "bogus @catch location");
778
779 const char *lParenLoc = strchr(startBuf, '(');
780
781 if (DeclStmt *declStmt = dyn_cast<DeclStmt>(catchStmt)) {
782 QualType t = dyn_cast<ValueDecl>(declStmt->getDecl())->getType();
783 if (t == Context->getObjcIdType()) {
784 buf += "1) { ";
785 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
786 buf.c_str(), buf.size());
787 sawIdTypedCatch = true;
788 } else if (const PointerType *pType = t->getAsPointerType()) {
789 ObjcInterfaceType *cls; // Should be a pointer to a class.
790
791 cls = dyn_cast<ObjcInterfaceType>(pType->getPointeeType().getTypePtr());
792 if (cls) {
Steve Naroff21867b12007-11-07 18:43:40 +0000793 buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
Steve Naroff75730982007-11-07 04:08:17 +0000794 buf += cls->getDecl()->getName();
Steve Naroff21867b12007-11-07 18:43:40 +0000795 buf += "\"), (struct objc_object *)_caught)) { ";
Steve Naroff75730982007-11-07 04:08:17 +0000796 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
797 buf.c_str(), buf.size());
798 }
799 }
800 // Now rewrite the body...
801 lastCatchBody = catchList->getCatchBody();
802 SourceLocation rParenLoc = catchList->getRParenLoc();
803 SourceLocation bodyLoc = lastCatchBody->getLocStart();
804 const char *bodyBuf = SM->getCharacterData(bodyLoc);
805 const char *rParenBuf = SM->getCharacterData(rParenLoc);
806 assert((*rParenBuf == ')') && "bogus @catch paren location");
807 assert((*bodyBuf == '{') && "bogus @catch body location");
808
809 buf = " = _caught;";
810 // Here we replace ") {" with "= _caught;" (which initializes and
811 // declares the @catch parameter).
812 Rewrite.ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
813 buf.c_str(), buf.size());
Steve Naroff2bd03922007-11-07 15:32:26 +0000814 } else if (!isa<NullStmt>(catchStmt)) {
Steve Naroff75730982007-11-07 04:08:17 +0000815 assert(false && "@catch rewrite bug");
Steve Naroff2bd03922007-11-07 15:32:26 +0000816 }
Steve Naroff75730982007-11-07 04:08:17 +0000817 catchList = catchList->getNextCatchStmt();
818 }
819 // Complete the catch list...
820 if (lastCatchBody) {
821 SourceLocation bodyLoc = lastCatchBody->getLocEnd();
822 const char *bodyBuf = SM->getCharacterData(bodyLoc);
823 assert((*bodyBuf == '}') && "bogus @catch body location");
824 bodyLoc = bodyLoc.getFileLocWithOffset(1);
825 buf = " } } /* @catch end */\n";
826
Chris Lattner28d1fe82007-11-08 04:41:51 +0000827 Rewrite.InsertText(bodyLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000828
829 // Set lastCurlyLoc
830 lastCurlyLoc = lastCatchBody->getLocEnd();
831 }
832 if (ObjcAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
833 startLoc = finalStmt->getLocStart();
834 startBuf = SM->getCharacterData(startLoc);
835 assert((*startBuf == '@') && "bogus @finally start");
836
837 buf = "/* @finally */";
838 Rewrite.ReplaceText(startLoc, 8, buf.c_str(), buf.size());
839
840 Stmt *body = finalStmt->getFinallyBody();
841 SourceLocation startLoc = body->getLocStart();
842 SourceLocation endLoc = body->getLocEnd();
843 const char *startBuf = SM->getCharacterData(startLoc);
844 const char *endBuf = SM->getCharacterData(endLoc);
845 assert((*startBuf == '{') && "bogus @finally body location");
846 assert((*endBuf == '}') && "bogus @finally body location");
847
848 startLoc = startLoc.getFileLocWithOffset(1);
849 buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
Chris Lattner28d1fe82007-11-08 04:41:51 +0000850 Rewrite.InsertText(startLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000851 endLoc = endLoc.getFileLocWithOffset(-1);
852 buf = " if (_rethrow) objc_exception_throw(_rethrow);\n";
Chris Lattner28d1fe82007-11-08 04:41:51 +0000853 Rewrite.InsertText(endLoc, buf.c_str(), buf.size());
Steve Naroff75730982007-11-07 04:08:17 +0000854
855 // Set lastCurlyLoc
856 lastCurlyLoc = body->getLocEnd();
857 }
858 // Now emit the final closing curly brace...
859 lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
860 buf = " } /* @try scope end */\n";
Chris Lattner28d1fe82007-11-08 04:41:51 +0000861 Rewrite.InsertText(lastCurlyLoc, buf.c_str(), buf.size());
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000862 return 0;
863}
864
865Stmt *RewriteTest::RewriteObjcCatchStmt(ObjcAtCatchStmt *S) {
866 return 0;
867}
868
869Stmt *RewriteTest::RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S) {
870 return 0;
871}
872
Steve Naroff2bd03922007-11-07 15:32:26 +0000873// This can't be done with Rewrite.ReplaceStmt(S, ThrowExpr), since
874// the throw expression is typically a message expression that's already
875// been rewritten! (which implies the SourceLocation's are invalid).
876Stmt *RewriteTest::RewriteObjcThrowStmt(ObjcAtThrowStmt *S) {
877 // Get the start location and compute the semi location.
878 SourceLocation startLoc = S->getLocStart();
879 const char *startBuf = SM->getCharacterData(startLoc);
880
881 assert((*startBuf == '@') && "bogus @throw location");
882
883 std::string buf;
884 /* void objc_exception_throw(id) __attribute__((noreturn)); */
885 buf = "objc_exception_throw(";
886 Rewrite.ReplaceText(startLoc, 6, buf.c_str(), buf.size());
887 const char *semiBuf = strchr(startBuf, ';');
888 assert((*semiBuf == ';') && "@throw: can't find ';'");
889 SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
890 buf = ");";
891 Rewrite.ReplaceText(semiLoc, 1, buf.c_str(), buf.size());
892 return 0;
893}
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000894
Chris Lattnere64b7772007-10-24 16:57:36 +0000895Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000896 // Create a new string expression.
897 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson85f9bce2007-10-29 05:01:08 +0000898 std::string StrEncoding;
899 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
900 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
901 StrEncoding.length(), false, StrType,
Chris Lattner01c57482007-10-17 22:35:30 +0000902 SourceLocation(), SourceLocation());
Chris Lattnere365c502007-11-30 22:25:36 +0000903 if (Rewrite.ReplaceStmt(Exp, Replacement)) {
904 // replacement failed.
Chris Lattner182745a2007-12-02 01:09:57 +0000905 unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
906 "rewriter could not replace sub-expression due to macros");
907 SourceRange Range = Exp->getSourceRange();
908 Diags.Report(Exp->getAtLoc(), DiagID, 0, 0, &Range, 1);
909 delete Replacement;
Chris Lattnere365c502007-11-30 22:25:36 +0000910 return Exp;
911 }
912
Chris Lattner07506182007-11-30 22:53:43 +0000913 // Replace this subexpr in the parent.
Chris Lattnere64b7772007-10-24 16:57:36 +0000914 delete Exp;
915 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000916}
917
Steve Naroffb42f8412007-11-05 14:50:49 +0000918Stmt *RewriteTest::RewriteAtSelector(ObjCSelectorExpr *Exp) {
919 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
920 // Create a call to sel_registerName("selName").
921 llvm::SmallVector<Expr*, 8> SelExprs;
922 QualType argType = Context->getPointerType(Context->CharTy);
923 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
924 Exp->getSelector().getName().size(),
925 false, argType, SourceLocation(),
926 SourceLocation()));
927 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
928 &SelExprs[0], SelExprs.size());
929 Rewrite.ReplaceStmt(Exp, SelExp);
930 delete Exp;
931 return SelExp;
932}
933
Steve Naroff934f2762007-10-24 22:48:43 +0000934CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
935 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000936 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000937 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000938
939 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000940 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000941
942 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000943 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000944 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
945
946 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000947
Steve Naroff934f2762007-10-24 22:48:43 +0000948 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
949}
950
Steve Naroffd5255f52007-11-01 13:24:47 +0000951static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
952 const char *&startRef, const char *&endRef) {
953 while (startBuf < endBuf) {
954 if (*startBuf == '<')
955 startRef = startBuf; // mark the start.
956 if (*startBuf == '>') {
Steve Naroff32174822007-11-09 12:50:28 +0000957 if (startRef && *startRef == '<') {
958 endRef = startBuf; // mark the end.
959 return true;
960 }
961 return false;
Steve Naroffd5255f52007-11-01 13:24:47 +0000962 }
963 startBuf++;
964 }
965 return false;
966}
967
968bool RewriteTest::needToScanForQualifiers(QualType T) {
969 // FIXME: we don't currently represent "id <Protocol>" in the type system.
970 if (T == Context->getObjcIdType())
971 return true;
972
973 if (const PointerType *pType = T->getAsPointerType()) {
Steve Naroff9165ad32007-10-31 04:38:33 +0000974 Type *pointeeType = pType->getPointeeType().getTypePtr();
975 if (isa<ObjcQualifiedInterfaceType>(pointeeType))
976 return true; // we have "Class <Protocol> *".
977 }
Steve Naroffd5255f52007-11-01 13:24:47 +0000978 return false;
979}
980
981void RewriteTest::RewriteObjcQualifiedInterfaceTypes(
982 const FunctionTypeProto *proto, FunctionDecl *FD) {
983
984 if (needToScanForQualifiers(proto->getResultType())) {
985 // Since types are unique, we need to scan the buffer.
986 SourceLocation Loc = FD->getLocation();
987
988 const char *endBuf = SM->getCharacterData(Loc);
989 const char *startBuf = endBuf;
Chris Lattner26de4652007-12-02 01:13:47 +0000990 while (*startBuf != ';' && startBuf != MainFileStart)
Steve Naroffd5255f52007-11-01 13:24:47 +0000991 startBuf--; // scan backward (from the decl location) for return type.
992 const char *startRef = 0, *endRef = 0;
993 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
994 // Get the locations of the startRef, endRef.
995 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
996 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
997 // Comment out the protocol references.
Chris Lattner28d1fe82007-11-08 04:41:51 +0000998 Rewrite.InsertText(LessLoc, "/*", 2);
999 Rewrite.InsertText(GreaterLoc, "*/", 2);
Steve Naroff9165ad32007-10-31 04:38:33 +00001000 }
1001 }
Steve Naroffd5255f52007-11-01 13:24:47 +00001002 // Now check arguments.
1003 for (unsigned i = 0; i < proto->getNumArgs(); i++) {
1004 if (needToScanForQualifiers(proto->getArgType(i))) {
1005 // Since types are unique, we need to scan the buffer.
1006 SourceLocation Loc = FD->getLocation();
1007
1008 const char *startBuf = SM->getCharacterData(Loc);
1009 const char *endBuf = startBuf;
1010 while (*endBuf != ';')
1011 endBuf++; // scan forward (from the decl location) for argument types.
1012 const char *startRef = 0, *endRef = 0;
1013 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
1014 // Get the locations of the startRef, endRef.
1015 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
1016 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
1017 // Comment out the protocol references.
Chris Lattner28d1fe82007-11-08 04:41:51 +00001018 Rewrite.InsertText(LessLoc, "/*", 2);
1019 Rewrite.InsertText(GreaterLoc, "*/", 2);
Steve Naroffd5255f52007-11-01 13:24:47 +00001020 }
1021 }
1022 }
Steve Naroff9165ad32007-10-31 04:38:33 +00001023}
1024
Fariborz Jahaniana70711b2007-12-04 21:47:40 +00001025// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
1026void RewriteTest::SynthSelGetUidFunctionDecl() {
1027 IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
1028 llvm::SmallVector<QualType, 16> ArgTys;
1029 ArgTys.push_back(Context->getPointerType(
1030 Context->CharTy.getQualifiedType(QualType::Const)));
1031 QualType getFuncType = Context->getFunctionType(Context->getObjcSelType(),
1032 &ArgTys[0], ArgTys.size(),
1033 false /*isVariadic*/);
1034 SelGetUidFunctionDecl = new FunctionDecl(SourceLocation(),
1035 SelGetUidIdent, getFuncType,
1036 FunctionDecl::Extern, false, 0);
1037}
1038
Steve Naroff09b266e2007-10-30 23:14:51 +00001039void RewriteTest::RewriteFunctionDecl(FunctionDecl *FD) {
1040 // declared in <objc/objc.h>
Steve Naroffbeaf2992007-11-03 11:27:19 +00001041 if (strcmp(FD->getName(), "sel_registerName") == 0) {
Steve Naroff09b266e2007-10-30 23:14:51 +00001042 SelGetUidFunctionDecl = FD;
Steve Naroff9165ad32007-10-31 04:38:33 +00001043 return;
1044 }
1045 // Check for ObjC 'id' and class types that have been adorned with protocol
1046 // information (id<p>, C<p>*). The protocol references need to be rewritten!
1047 const FunctionType *funcType = FD->getType()->getAsFunctionType();
1048 assert(funcType && "missing function type");
Steve Naroffd5255f52007-11-01 13:24:47 +00001049 if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcType))
1050 RewriteObjcQualifiedInterfaceTypes(proto, FD);
Steve Naroff09b266e2007-10-30 23:14:51 +00001051}
1052
1053// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
1054void RewriteTest::SynthMsgSendFunctionDecl() {
1055 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
1056 llvm::SmallVector<QualType, 16> ArgTys;
1057 QualType argT = Context->getObjcIdType();
1058 assert(!argT.isNull() && "Can't find 'id' type");
1059 ArgTys.push_back(argT);
1060 argT = Context->getObjcSelType();
1061 assert(!argT.isNull() && "Can't find 'SEL' type");
1062 ArgTys.push_back(argT);
1063 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
1064 &ArgTys[0], ArgTys.size(),
1065 true /*isVariadic*/);
1066 MsgSendFunctionDecl = new FunctionDecl(SourceLocation(),
1067 msgSendIdent, msgSendType,
1068 FunctionDecl::Extern, false, 0);
1069}
1070
Steve Naroff874e2322007-11-15 10:28:18 +00001071// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
1072void RewriteTest::SynthMsgSendSuperFunctionDecl() {
1073 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
1074 llvm::SmallVector<QualType, 16> ArgTys;
1075 RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
1076 &Context->Idents.get("objc_super"), 0);
1077 QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
1078 assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
1079 ArgTys.push_back(argT);
1080 argT = Context->getObjcSelType();
1081 assert(!argT.isNull() && "Can't find 'SEL' type");
1082 ArgTys.push_back(argT);
1083 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
1084 &ArgTys[0], ArgTys.size(),
1085 true /*isVariadic*/);
1086 MsgSendSuperFunctionDecl = new FunctionDecl(SourceLocation(),
1087 msgSendIdent, msgSendType,
1088 FunctionDecl::Extern, false, 0);
1089}
1090
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001091// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
1092void RewriteTest::SynthMsgSendStretFunctionDecl() {
1093 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
1094 llvm::SmallVector<QualType, 16> ArgTys;
1095 QualType argT = Context->getObjcIdType();
1096 assert(!argT.isNull() && "Can't find 'id' type");
1097 ArgTys.push_back(argT);
1098 argT = Context->getObjcSelType();
1099 assert(!argT.isNull() && "Can't find 'SEL' type");
1100 ArgTys.push_back(argT);
1101 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
1102 &ArgTys[0], ArgTys.size(),
1103 true /*isVariadic*/);
1104 MsgSendStretFunctionDecl = new FunctionDecl(SourceLocation(),
1105 msgSendIdent, msgSendType,
1106 FunctionDecl::Extern, false, 0);
1107}
1108
1109// SynthMsgSendSuperStretFunctionDecl -
1110// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
1111void RewriteTest::SynthMsgSendSuperStretFunctionDecl() {
1112 IdentifierInfo *msgSendIdent =
1113 &Context->Idents.get("objc_msgSendSuper_stret");
1114 llvm::SmallVector<QualType, 16> ArgTys;
1115 RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
1116 &Context->Idents.get("objc_super"), 0);
1117 QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
1118 assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
1119 ArgTys.push_back(argT);
1120 argT = Context->getObjcSelType();
1121 assert(!argT.isNull() && "Can't find 'SEL' type");
1122 ArgTys.push_back(argT);
1123 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
1124 &ArgTys[0], ArgTys.size(),
1125 true /*isVariadic*/);
1126 MsgSendSuperStretFunctionDecl = new FunctionDecl(SourceLocation(),
1127 msgSendIdent, msgSendType,
1128 FunctionDecl::Extern, false, 0);
1129}
1130
Fariborz Jahanianacb49772007-12-03 21:26:48 +00001131// SynthMsgSendFpretFunctionDecl - id objc_msgSend_fpret(id self, SEL op, ...);
1132void RewriteTest::SynthMsgSendFpretFunctionDecl() {
1133 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
1134 llvm::SmallVector<QualType, 16> ArgTys;
1135 QualType argT = Context->getObjcIdType();
1136 assert(!argT.isNull() && "Can't find 'id' type");
1137 ArgTys.push_back(argT);
1138 argT = Context->getObjcSelType();
1139 assert(!argT.isNull() && "Can't find 'SEL' type");
1140 ArgTys.push_back(argT);
1141 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
1142 &ArgTys[0], ArgTys.size(),
1143 true /*isVariadic*/);
1144 MsgSendFpretFunctionDecl = new FunctionDecl(SourceLocation(),
1145 msgSendIdent, msgSendType,
1146 FunctionDecl::Extern, false, 0);
1147}
1148
Steve Naroff09b266e2007-10-30 23:14:51 +00001149// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
1150void RewriteTest::SynthGetClassFunctionDecl() {
1151 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
1152 llvm::SmallVector<QualType, 16> ArgTys;
1153 ArgTys.push_back(Context->getPointerType(
1154 Context->CharTy.getQualifiedType(QualType::Const)));
1155 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
1156 &ArgTys[0], ArgTys.size(),
1157 false /*isVariadic*/);
1158 GetClassFunctionDecl = new FunctionDecl(SourceLocation(),
1159 getClassIdent, getClassType,
1160 FunctionDecl::Extern, false, 0);
1161}
1162
Steve Naroff9bcb5fc2007-12-07 03:50:46 +00001163// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
1164void RewriteTest::SynthGetMetaClassFunctionDecl() {
1165 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
1166 llvm::SmallVector<QualType, 16> ArgTys;
1167 ArgTys.push_back(Context->getPointerType(
1168 Context->CharTy.getQualifiedType(QualType::Const)));
1169 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
1170 &ArgTys[0], ArgTys.size(),
1171 false /*isVariadic*/);
1172 GetMetaClassFunctionDecl = new FunctionDecl(SourceLocation(),
1173 getClassIdent, getClassType,
1174 FunctionDecl::Extern, false, 0);
1175}
1176
Steve Naroff96984642007-11-08 14:30:50 +00001177// SynthCFStringFunctionDecl - id __builtin___CFStringMakeConstantString(const char *name);
1178void RewriteTest::SynthCFStringFunctionDecl() {
1179 IdentifierInfo *getClassIdent = &Context->Idents.get("__builtin___CFStringMakeConstantString");
1180 llvm::SmallVector<QualType, 16> ArgTys;
1181 ArgTys.push_back(Context->getPointerType(
1182 Context->CharTy.getQualifiedType(QualType::Const)));
1183 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
1184 &ArgTys[0], ArgTys.size(),
1185 false /*isVariadic*/);
1186 CFStringFunctionDecl = new FunctionDecl(SourceLocation(),
1187 getClassIdent, getClassType,
1188 FunctionDecl::Extern, false, 0);
1189}
1190
Steve Naroffbeaf2992007-11-03 11:27:19 +00001191Stmt *RewriteTest::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
Steve Naroff96984642007-11-08 14:30:50 +00001192#if 1
1193 // This rewrite is specific to GCC, which has builtin support for CFString.
1194 if (!CFStringFunctionDecl)
1195 SynthCFStringFunctionDecl();
1196 // Create a call to __builtin___CFStringMakeConstantString("cstr").
1197 llvm::SmallVector<Expr*, 8> StrExpr;
1198 StrExpr.push_back(Exp->getString());
1199 CallExpr *call = SynthesizeCallToFunctionDecl(CFStringFunctionDecl,
1200 &StrExpr[0], StrExpr.size());
1201 // cast to NSConstantString *
1202 CastExpr *cast = new CastExpr(Exp->getType(), call, SourceLocation());
1203 Rewrite.ReplaceStmt(Exp, cast);
1204 delete Exp;
1205 return cast;
1206#else
Steve Naroffbeaf2992007-11-03 11:27:19 +00001207 assert(ConstantStringClassReference && "Can't find constant string reference");
1208 llvm::SmallVector<Expr*, 4> InitExprs;
1209
1210 // Synthesize "(Class)&_NSConstantStringClassReference"
1211 DeclRefExpr *ClsRef = new DeclRefExpr(ConstantStringClassReference,
1212 ConstantStringClassReference->getType(),
1213 SourceLocation());
1214 QualType expType = Context->getPointerType(ClsRef->getType());
1215 UnaryOperator *Unop = new UnaryOperator(ClsRef, UnaryOperator::AddrOf,
1216 expType, SourceLocation());
1217 CastExpr *cast = new CastExpr(Context->getObjcClassType(), Unop,
1218 SourceLocation());
1219 InitExprs.push_back(cast); // set the 'isa'.
1220 InitExprs.push_back(Exp->getString()); // set "char *bytes".
1221 unsigned IntSize = static_cast<unsigned>(
1222 Context->getTypeSize(Context->IntTy, Exp->getLocStart()));
1223 llvm::APInt IntVal(IntSize, Exp->getString()->getByteLength());
1224 IntegerLiteral *len = new IntegerLiteral(IntVal, Context->IntTy,
1225 Exp->getLocStart());
1226 InitExprs.push_back(len); // set "int numBytes".
1227
1228 // struct NSConstantString
1229 QualType CFConstantStrType = Context->getCFConstantStringType();
1230 // (struct NSConstantString) { <exprs from above> }
1231 InitListExpr *ILE = new InitListExpr(SourceLocation(),
1232 &InitExprs[0], InitExprs.size(),
1233 SourceLocation());
1234 CompoundLiteralExpr *StrRep = new CompoundLiteralExpr(CFConstantStrType, ILE);
1235 // struct NSConstantString *
1236 expType = Context->getPointerType(StrRep->getType());
1237 Unop = new UnaryOperator(StrRep, UnaryOperator::AddrOf, expType,
1238 SourceLocation());
Steve Naroff352336b2007-11-05 14:36:37 +00001239 // cast to NSConstantString *
1240 cast = new CastExpr(Exp->getType(), Unop, SourceLocation());
Steve Naroffbeaf2992007-11-03 11:27:19 +00001241 Rewrite.ReplaceStmt(Exp, cast);
1242 delete Exp;
Steve Naroff352336b2007-11-05 14:36:37 +00001243 return cast;
Steve Naroff96984642007-11-08 14:30:50 +00001244#endif
Steve Naroffbeaf2992007-11-03 11:27:19 +00001245}
1246
Steve Naroff874e2322007-11-15 10:28:18 +00001247ObjcInterfaceDecl *RewriteTest::isSuperReceiver(Expr *recExpr) {
Steve Naroff9bcb5fc2007-12-07 03:50:46 +00001248 // check if we are sending a message to 'super'
1249 if (CurMethodDecl && CurMethodDecl->isInstance()) {
Steve Naroff874e2322007-11-15 10:28:18 +00001250 if (CastExpr *CE = dyn_cast<CastExpr>(recExpr)) {
1251 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
1252 if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
1253 if (!strcmp(PVD->getName(), "self")) {
1254 if (const PointerType *PT = CE->getType()->getAsPointerType()) {
1255 if (ObjcInterfaceType *IT =
1256 dyn_cast<ObjcInterfaceType>(PT->getPointeeType())) {
1257 if (IT->getDecl() ==
1258 CurMethodDecl->getClassInterface()->getSuperClass())
1259 return IT->getDecl();
1260 }
1261 }
1262 }
1263 }
1264 }
Steve Naroff9bcb5fc2007-12-07 03:50:46 +00001265 }
Steve Naroff874e2322007-11-15 10:28:18 +00001266 }
1267 return 0;
1268}
1269
1270// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
1271QualType RewriteTest::getSuperStructType() {
1272 if (!SuperStructDecl) {
1273 SuperStructDecl = new RecordDecl(Decl::Struct, SourceLocation(),
1274 &Context->Idents.get("objc_super"), 0);
1275 QualType FieldTypes[2];
1276
1277 // struct objc_object *receiver;
1278 FieldTypes[0] = Context->getObjcIdType();
1279 // struct objc_class *super;
1280 FieldTypes[1] = Context->getObjcClassType();
1281 // Create fields
1282 FieldDecl *FieldDecls[2];
1283
1284 for (unsigned i = 0; i < 2; ++i)
1285 FieldDecls[i] = new FieldDecl(SourceLocation(), 0, FieldTypes[i]);
1286
1287 SuperStructDecl->defineBody(FieldDecls, 4);
1288 }
1289 return Context->getTagDeclType(SuperStructDecl);
1290}
1291
Steve Naroff934f2762007-10-24 22:48:43 +00001292Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Fariborz Jahaniana70711b2007-12-04 21:47:40 +00001293 if (!SelGetUidFunctionDecl)
1294 SynthSelGetUidFunctionDecl();
Steve Naroff09b266e2007-10-30 23:14:51 +00001295 if (!MsgSendFunctionDecl)
1296 SynthMsgSendFunctionDecl();
Steve Naroff874e2322007-11-15 10:28:18 +00001297 if (!MsgSendSuperFunctionDecl)
1298 SynthMsgSendSuperFunctionDecl();
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001299 if (!MsgSendStretFunctionDecl)
1300 SynthMsgSendStretFunctionDecl();
1301 if (!MsgSendSuperStretFunctionDecl)
1302 SynthMsgSendSuperStretFunctionDecl();
Fariborz Jahanianacb49772007-12-03 21:26:48 +00001303 if (!MsgSendFpretFunctionDecl)
1304 SynthMsgSendFpretFunctionDecl();
Steve Naroff09b266e2007-10-30 23:14:51 +00001305 if (!GetClassFunctionDecl)
1306 SynthGetClassFunctionDecl();
Steve Naroff9bcb5fc2007-12-07 03:50:46 +00001307 if (!GetMetaClassFunctionDecl)
1308 SynthGetMetaClassFunctionDecl();
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001309
Steve Naroff874e2322007-11-15 10:28:18 +00001310 // default to objc_msgSend().
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001311 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
1312 // May need to use objc_msgSend_stret() as well.
1313 FunctionDecl *MsgSendStretFlavor = 0;
1314 if (ObjcMethodDecl *mDecl = Exp->getMethodDecl()) {
1315 QualType resultType = mDecl->getResultType();
1316 if (resultType.getCanonicalType()->isStructureType()
1317 || resultType.getCanonicalType()->isUnionType())
1318 MsgSendStretFlavor = MsgSendStretFunctionDecl;
Fariborz Jahanianacb49772007-12-03 21:26:48 +00001319 else if (resultType.getCanonicalType()->isRealFloatingType())
1320 MsgSendFlavor = MsgSendFpretFunctionDecl;
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001321 }
Steve Naroff874e2322007-11-15 10:28:18 +00001322
Steve Naroff934f2762007-10-24 22:48:43 +00001323 // Synthesize a call to objc_msgSend().
1324 llvm::SmallVector<Expr*, 8> MsgExprs;
1325 IdentifierInfo *clsName = Exp->getClassName();
1326
1327 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
1328 if (clsName) { // class message.
Steve Naroff9bcb5fc2007-12-07 03:50:46 +00001329 if (!strcmp(clsName->getName(), "super")) {
1330 MsgSendFlavor = MsgSendSuperFunctionDecl;
1331 if (MsgSendStretFlavor)
1332 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
1333 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
1334
1335 ObjcInterfaceDecl *SuperDecl =
1336 CurMethodDecl->getClassInterface()->getSuperClass();
1337
1338 llvm::SmallVector<Expr*, 4> InitExprs;
1339
1340 // set the receiver to self, the first argument to all methods.
1341 InitExprs.push_back(new DeclRefExpr(CurMethodDecl->getSelfDecl(),
1342 Context->getObjcIdType(),
1343 SourceLocation()));
1344 llvm::SmallVector<Expr*, 8> ClsExprs;
1345 QualType argType = Context->getPointerType(Context->CharTy);
1346 ClsExprs.push_back(new StringLiteral(SuperDecl->getIdentifier()->getName(),
1347 SuperDecl->getIdentifier()->getLength(),
1348 false, argType, SourceLocation(),
1349 SourceLocation()));
1350 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
1351 &ClsExprs[0],
1352 ClsExprs.size());
1353 // To turn off a warning, type-cast to 'id'
1354 InitExprs.push_back(
1355 new CastExpr(Context->getObjcIdType(),
1356 Cls, SourceLocation())); // set 'super class', using objc_getClass().
1357 // struct objc_super
1358 QualType superType = getSuperStructType();
1359 // (struct objc_super) { <exprs from above> }
1360 InitListExpr *ILE = new InitListExpr(SourceLocation(),
1361 &InitExprs[0], InitExprs.size(),
1362 SourceLocation());
1363 CompoundLiteralExpr *SuperRep = new CompoundLiteralExpr(superType, ILE);
1364 // struct objc_super *
1365 Expr *Unop = new UnaryOperator(SuperRep, UnaryOperator::AddrOf,
1366 Context->getPointerType(SuperRep->getType()),
1367 SourceLocation());
1368 MsgExprs.push_back(Unop);
1369 } else {
1370 llvm::SmallVector<Expr*, 8> ClsExprs;
1371 QualType argType = Context->getPointerType(Context->CharTy);
1372 ClsExprs.push_back(new StringLiteral(clsName->getName(),
1373 clsName->getLength(),
1374 false, argType, SourceLocation(),
1375 SourceLocation()));
1376 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
1377 &ClsExprs[0],
1378 ClsExprs.size());
1379 MsgExprs.push_back(Cls);
1380 }
Steve Naroff6568d4d2007-11-14 23:54:14 +00001381 } else { // instance message.
1382 Expr *recExpr = Exp->getReceiver();
Steve Naroff874e2322007-11-15 10:28:18 +00001383
Steve Naroff9bcb5fc2007-12-07 03:50:46 +00001384 if (ObjcInterfaceDecl *SuperDecl = isSuperReceiver(recExpr)) {
Steve Naroff874e2322007-11-15 10:28:18 +00001385 MsgSendFlavor = MsgSendSuperFunctionDecl;
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001386 if (MsgSendStretFlavor)
1387 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
Steve Naroff874e2322007-11-15 10:28:18 +00001388 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
1389
1390 llvm::SmallVector<Expr*, 4> InitExprs;
1391
Fariborz Jahanianceee3e82007-12-04 22:32:58 +00001392 InitExprs.push_back(
1393 new CastExpr(Context->getObjcIdType(),
1394 recExpr, SourceLocation())); // set the 'receiver'.
Steve Naroff874e2322007-11-15 10:28:18 +00001395
1396 llvm::SmallVector<Expr*, 8> ClsExprs;
1397 QualType argType = Context->getPointerType(Context->CharTy);
Steve Naroff9bcb5fc2007-12-07 03:50:46 +00001398 ClsExprs.push_back(new StringLiteral(SuperDecl->getIdentifier()->getName(),
1399 SuperDecl->getIdentifier()->getLength(),
Steve Naroff874e2322007-11-15 10:28:18 +00001400 false, argType, SourceLocation(),
1401 SourceLocation()));
1402 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
Fariborz Jahanianceee3e82007-12-04 22:32:58 +00001403 &ClsExprs[0],
1404 ClsExprs.size());
Fariborz Jahanian71274312007-12-05 17:29:46 +00001405 // To turn off a warning, type-cast to 'id'
Fariborz Jahanianceee3e82007-12-04 22:32:58 +00001406 InitExprs.push_back(
Fariborz Jahanian71274312007-12-05 17:29:46 +00001407 new CastExpr(Context->getObjcIdType(),
Fariborz Jahanianceee3e82007-12-04 22:32:58 +00001408 Cls, SourceLocation())); // set 'super class', using objc_getClass().
Steve Naroff874e2322007-11-15 10:28:18 +00001409 // struct objc_super
1410 QualType superType = getSuperStructType();
1411 // (struct objc_super) { <exprs from above> }
1412 InitListExpr *ILE = new InitListExpr(SourceLocation(),
1413 &InitExprs[0], InitExprs.size(),
1414 SourceLocation());
1415 CompoundLiteralExpr *SuperRep = new CompoundLiteralExpr(superType, ILE);
1416 // struct objc_super *
1417 Expr *Unop = new UnaryOperator(SuperRep, UnaryOperator::AddrOf,
1418 Context->getPointerType(SuperRep->getType()),
1419 SourceLocation());
1420 MsgExprs.push_back(Unop);
1421 } else {
1422 recExpr = new CastExpr(Context->getObjcIdType(), recExpr, SourceLocation());
1423 MsgExprs.push_back(recExpr);
1424 }
Steve Naroff6568d4d2007-11-14 23:54:14 +00001425 }
Steve Naroffbeaf2992007-11-03 11:27:19 +00001426 // Create a call to sel_registerName("selName"), it will be the 2nd argument.
Steve Naroff934f2762007-10-24 22:48:43 +00001427 llvm::SmallVector<Expr*, 8> SelExprs;
1428 QualType argType = Context->getPointerType(Context->CharTy);
1429 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
1430 Exp->getSelector().getName().size(),
1431 false, argType, SourceLocation(),
1432 SourceLocation()));
1433 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
1434 &SelExprs[0], SelExprs.size());
1435 MsgExprs.push_back(SelExp);
1436
1437 // Now push any user supplied arguments.
1438 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
Steve Naroff6568d4d2007-11-14 23:54:14 +00001439 Expr *userExpr = Exp->getArg(i);
Steve Naroff7e3411b2007-11-15 02:58:25 +00001440 // Make all implicit casts explicit...ICE comes in handy:-)
1441 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
1442 // Reuse the ICE type, it is exactly what the doctor ordered.
1443 userExpr = new CastExpr(ICE->getType(), userExpr, SourceLocation());
1444 }
Steve Naroff6568d4d2007-11-14 23:54:14 +00001445 MsgExprs.push_back(userExpr);
Steve Naroff934f2762007-10-24 22:48:43 +00001446 // We've transferred the ownership to MsgExprs. Null out the argument in
1447 // the original expression, since we will delete it below.
1448 Exp->setArg(i, 0);
1449 }
Steve Naroffab972d32007-11-04 22:37:50 +00001450 // Generate the funky cast.
1451 CastExpr *cast;
1452 llvm::SmallVector<QualType, 8> ArgTypes;
1453 QualType returnType;
1454
1455 // Push 'id' and 'SEL', the 2 implicit arguments.
Steve Naroffc3a438c2007-11-15 10:43:57 +00001456 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
1457 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
1458 else
1459 ArgTypes.push_back(Context->getObjcIdType());
Steve Naroffab972d32007-11-04 22:37:50 +00001460 ArgTypes.push_back(Context->getObjcSelType());
1461 if (ObjcMethodDecl *mDecl = Exp->getMethodDecl()) {
1462 // Push any user argument types.
Steve Naroff352336b2007-11-05 14:36:37 +00001463 for (int i = 0; i < mDecl->getNumParams(); i++) {
1464 QualType t = mDecl->getParamDecl(i)->getType();
Steve Naroff352336b2007-11-05 14:36:37 +00001465 ArgTypes.push_back(t);
1466 }
Steve Naroffab972d32007-11-04 22:37:50 +00001467 returnType = mDecl->getResultType();
1468 } else {
1469 returnType = Context->getObjcIdType();
1470 }
1471 // Get the type, we will need to reference it in a couple spots.
Steve Naroff874e2322007-11-15 10:28:18 +00001472 QualType msgSendType = MsgSendFlavor->getType();
Steve Naroffab972d32007-11-04 22:37:50 +00001473
1474 // Create a reference to the objc_msgSend() declaration.
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001475 DeclRefExpr *DRE = new DeclRefExpr(MsgSendFlavor, msgSendType,
1476 SourceLocation());
Steve Naroffab972d32007-11-04 22:37:50 +00001477
1478 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
1479 // If we don't do this cast, we get the following bizarre warning/note:
1480 // xx.m:13: warning: function called through a non-compatible type
1481 // xx.m:13: note: if this code is reached, the program will abort
1482 cast = new CastExpr(Context->getPointerType(Context->VoidTy), DRE,
1483 SourceLocation());
Steve Naroff335eafa2007-11-15 12:35:21 +00001484
Steve Naroffab972d32007-11-04 22:37:50 +00001485 // Now do the "normal" pointer to function cast.
1486 QualType castType = Context->getFunctionType(returnType,
Fariborz Jahaniand0ee6f92007-12-06 19:49:56 +00001487 &ArgTypes[0], ArgTypes.size(),
1488 Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
Steve Naroffab972d32007-11-04 22:37:50 +00001489 castType = Context->getPointerType(castType);
1490 cast = new CastExpr(castType, cast, SourceLocation());
1491
1492 // Don't forget the parens to enforce the proper binding.
1493 ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
1494
1495 const FunctionType *FT = msgSendType->getAsFunctionType();
1496 CallExpr *CE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(),
1497 FT->getResultType(), SourceLocation());
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001498 if (MsgSendStretFlavor) {
1499 // We have the method which returns a struct/union. Must also generate
1500 // call to objc_msgSend_stret and hang both varieties on a conditional
1501 // expression which dictate which one to envoke depending on size of
1502 // method's return type.
1503
1504 // Create a reference to the objc_msgSend_stret() declaration.
1505 DeclRefExpr *STDRE = new DeclRefExpr(MsgSendStretFlavor, msgSendType,
1506 SourceLocation());
1507 // Need to cast objc_msgSend_stret to "void *" (see above comment).
1508 cast = new CastExpr(Context->getPointerType(Context->VoidTy), STDRE,
1509 SourceLocation());
1510 // Now do the "normal" pointer to function cast.
1511 castType = Context->getFunctionType(returnType,
Fariborz Jahaniand0ee6f92007-12-06 19:49:56 +00001512 &ArgTypes[0], ArgTypes.size(),
1513 Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
Fariborz Jahanian80a6a5a2007-12-03 19:17:29 +00001514 castType = Context->getPointerType(castType);
1515 cast = new CastExpr(castType, cast, SourceLocation());
1516
1517 // Don't forget the parens to enforce the proper binding.
1518 PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
1519
1520 FT = msgSendType->getAsFunctionType();
1521 CallExpr *STCE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(),
1522 FT->getResultType(), SourceLocation());
1523
1524 // Build sizeof(returnType)
1525 SizeOfAlignOfTypeExpr *sizeofExpr = new SizeOfAlignOfTypeExpr(true,
1526 returnType, Context->getSizeType(),
1527 SourceLocation(), SourceLocation());
1528 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
1529 // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
1530 // For X86 it is more complicated and some kind of target specific routine
1531 // is needed to decide what to do.
1532 unsigned IntSize = static_cast<unsigned>(
1533 Context->getTypeSize(Context->IntTy, SourceLocation()));
1534
1535 IntegerLiteral *limit = new IntegerLiteral(llvm::APInt(IntSize, 8),
1536 Context->IntTy,
1537 SourceLocation());
1538 BinaryOperator *lessThanExpr = new BinaryOperator(sizeofExpr, limit,
1539 BinaryOperator::LE,
1540 Context->IntTy,
1541 SourceLocation());
1542 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
1543 ConditionalOperator *CondExpr =
1544 new ConditionalOperator(lessThanExpr, CE, STCE, returnType);
1545 ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
1546 // Now do the actual rewrite.
1547 Rewrite.ReplaceStmt(Exp, PE);
1548 delete Exp;
1549 return PE;
1550 }
Steve Naroff934f2762007-10-24 22:48:43 +00001551 // Now do the actual rewrite.
Steve Naroffab972d32007-11-04 22:37:50 +00001552 Rewrite.ReplaceStmt(Exp, CE);
Steve Naroff934f2762007-10-24 22:48:43 +00001553
Chris Lattnere64b7772007-10-24 16:57:36 +00001554 delete Exp;
Steve Naroffab972d32007-11-04 22:37:50 +00001555 return CE;
Steve Naroffebf2b562007-10-23 23:50:29 +00001556}
1557
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001558/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
1559/// an objective-c class with ivars.
1560void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
1561 std::string &Result) {
1562 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
1563 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
Fariborz Jahanian212b7682007-10-31 23:08:24 +00001564 // Do not synthesize more than once.
1565 if (ObjcSynthesizedStructs.count(CDecl))
1566 return;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001567 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
Steve Naroff03300712007-11-12 13:56:41 +00001568 int NumIvars = CDecl->getNumInstanceVariables();
Steve Narofffea763e82007-11-14 19:25:57 +00001569 SourceLocation LocStart = CDecl->getLocStart();
1570 SourceLocation LocEnd = CDecl->getLocEnd();
1571
1572 const char *startBuf = SM->getCharacterData(LocStart);
1573 const char *endBuf = SM->getCharacterData(LocEnd);
Fariborz Jahanian2c7038b2007-11-26 19:52:57 +00001574 // If no ivars and no root or if its root, directly or indirectly,
1575 // have no ivars (thus not synthesized) then no need to synthesize this class.
1576 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl))) {
Fariborz Jahanian2c7038b2007-11-26 19:52:57 +00001577 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
1578 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
1579 Result.c_str(), Result.size());
1580 return;
1581 }
1582
1583 // FIXME: This has potential of causing problem. If
1584 // SynthesizeObjcInternalStruct is ever called recursively.
1585 Result += "\nstruct ";
1586 Result += CDecl->getName();
Steve Narofffea763e82007-11-14 19:25:57 +00001587
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001588 if (NumIvars > 0) {
Steve Narofffea763e82007-11-14 19:25:57 +00001589 const char *cursor = strchr(startBuf, '{');
1590 assert((cursor && endBuf)
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001591 && "SynthesizeObjcInternalStruct - malformed @interface");
Steve Narofffea763e82007-11-14 19:25:57 +00001592
1593 // rewrite the original header *without* disturbing the '{'
1594 Rewrite.ReplaceText(LocStart, cursor-startBuf-1,
1595 Result.c_str(), Result.size());
1596 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
1597 Result = "\n struct ";
1598 Result += RCDecl->getName();
1599 Result += " _";
1600 Result += RCDecl->getName();
1601 Result += ";\n";
1602
1603 // insert the super class structure definition.
1604 SourceLocation OnePastCurly = LocStart.getFileLocWithOffset(cursor-startBuf+1);
1605 Rewrite.InsertText(OnePastCurly, Result.c_str(), Result.size());
1606 }
1607 cursor++; // past '{'
1608
1609 // Now comment out any visibility specifiers.
1610 while (cursor < endBuf) {
1611 if (*cursor == '@') {
1612 SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
Chris Lattnerdf6a51b2007-11-14 22:57:51 +00001613 // Skip whitespace.
1614 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
1615 /*scan*/;
1616
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001617 // FIXME: presence of @public, etc. inside comment results in
1618 // this transformation as well, which is still correct c-code.
Steve Narofffea763e82007-11-14 19:25:57 +00001619 if (!strncmp(cursor, "public", strlen("public")) ||
1620 !strncmp(cursor, "private", strlen("private")) ||
Fariborz Jahanian95673922007-11-14 22:26:25 +00001621 !strncmp(cursor, "protected", strlen("protected")))
Steve Narofffea763e82007-11-14 19:25:57 +00001622 Rewrite.InsertText(atLoc, "// ", 3);
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001623 }
Fariborz Jahanian95673922007-11-14 22:26:25 +00001624 // FIXME: If there are cases where '<' is used in ivar declaration part
1625 // of user code, then scan the ivar list and use needToScanForQualifiers
1626 // for type checking.
1627 else if (*cursor == '<') {
1628 SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
1629 Rewrite.InsertText(atLoc, "/* ", 3);
1630 cursor = strchr(cursor, '>');
1631 cursor++;
1632 atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
1633 Rewrite.InsertText(atLoc, " */", 3);
1634 }
Steve Narofffea763e82007-11-14 19:25:57 +00001635 cursor++;
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +00001636 }
Steve Narofffea763e82007-11-14 19:25:57 +00001637 // Don't forget to add a ';'!!
1638 Rewrite.InsertText(LocEnd.getFileLocWithOffset(1), ";", 1);
1639 } else { // we don't have any instance variables - insert super struct.
1640 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
1641 Result += " {\n struct ";
1642 Result += RCDecl->getName();
1643 Result += " _";
1644 Result += RCDecl->getName();
1645 Result += ";\n};\n";
1646 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
1647 Result.c_str(), Result.size());
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001648 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001649 // Mark this struct as having been generated.
1650 if (!ObjcSynthesizedStructs.insert(CDecl))
Fariborz Jahanianaff56d02007-10-31 22:57:04 +00001651 assert(false && "struct already synthesize- SynthesizeObjcInternalStruct");
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001652}
1653
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001654// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
1655/// class methods.
Steve Naroff0416fb92007-11-11 17:19:15 +00001656void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001657 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001658 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001659 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +00001660 const char *ClassName,
1661 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001662 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001663 if (NumMethods > 0 && !objc_impl_method) {
1664 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001665 SEL _cmd;
1666 char *method_types;
1667 void *_imp;
1668 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001669 */
Chris Lattner158ecb92007-10-25 17:07:24 +00001670 Result += "\nstruct _objc_method {\n";
1671 Result += "\tSEL _cmd;\n";
1672 Result += "\tchar *method_types;\n";
1673 Result += "\tvoid *_imp;\n";
1674 Result += "};\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001675
1676 /* struct _objc_method_list {
1677 struct _objc_method_list *next_method;
1678 int method_count;
1679 struct _objc_method method_list[];
1680 }
1681 */
1682 Result += "\nstruct _objc_method_list {\n";
1683 Result += "\tstruct _objc_method_list *next_method;\n";
1684 Result += "\tint method_count;\n";
1685 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001686 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +00001687 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001688 // Build _objc_method_list for class's methods if needed
1689 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001690 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattner158ecb92007-10-25 17:07:24 +00001691 Result += prefix;
1692 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
1693 Result += "_METHODS_";
1694 Result += ClassName;
1695 Result += " __attribute__ ((section (\"__OBJC, __";
1696 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001697 Result += "_meth\")))= ";
1698 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
1699
1700 Result += "\t,{{(SEL)\"";
1701 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001702 std::string MethodTypeString;
1703 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
1704 Result += "\", \"";
1705 Result += MethodTypeString;
Fariborz Jahanianb7908b52007-11-13 21:02:00 +00001706 Result += "\", ";
1707 Result += MethodInternalNames[Methods[0]];
1708 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001709 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001710 Result += "\t ,{(SEL)\"";
1711 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001712 std::string MethodTypeString;
1713 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1714 Result += "\", \"";
1715 Result += MethodTypeString;
Fariborz Jahanianb7908b52007-11-13 21:02:00 +00001716 Result += "\", ";
1717 Result += MethodInternalNames[Methods[i]];
1718 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001719 }
1720 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001721 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001722}
1723
1724/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
1725void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
1726 int NumProtocols,
1727 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001728 const char *ClassName,
1729 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001730 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001731 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001732 for (int i = 0; i < NumProtocols; i++) {
1733 ObjcProtocolDecl *PDecl = Protocols[i];
1734 // Output struct protocol_methods holder of method selector and type.
1735 if (!objc_protocol_methods &&
1736 (PDecl->getNumInstanceMethods() > 0
1737 || PDecl->getNumClassMethods() > 0)) {
1738 /* struct protocol_methods {
1739 SEL _cmd;
1740 char *method_types;
1741 }
1742 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001743 Result += "\nstruct protocol_methods {\n";
1744 Result += "\tSEL _cmd;\n";
1745 Result += "\tchar *method_types;\n";
1746 Result += "};\n";
1747
1748 /* struct _objc_protocol_method_list {
1749 int protocol_method_count;
1750 struct protocol_methods protocols[];
1751 }
1752 */
1753 Result += "\nstruct _objc_protocol_method_list {\n";
1754 Result += "\tint protocol_method_count;\n";
1755 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001756 objc_protocol_methods = true;
1757 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001758
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001759 // Output instance methods declared in this protocol.
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001760 int NumMethods = PDecl->getNumInstanceMethods();
1761 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001762 Result += "\nstatic struct _objc_protocol_method_list "
1763 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
1764 Result += PDecl->getName();
1765 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
1766 "{\n\t" + utostr(NumMethods) + "\n";
1767
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001768 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001769 Result += "\t,{{(SEL)\"";
1770 Result += Methods[0]->getSelector().getName().c_str();
1771 Result += "\", \"\"}\n";
1772
1773 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001774 Result += "\t ,{(SEL)\"";
1775 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001776 std::string MethodTypeString;
1777 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1778 Result += "\", \"";
1779 Result += MethodTypeString;
1780 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001781 }
1782 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001783 }
1784
1785 // Output class methods declared in this protocol.
1786 NumMethods = PDecl->getNumClassMethods();
1787 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001788 Result += "\nstatic struct _objc_protocol_method_list "
1789 "_OBJC_PROTOCOL_CLASS_METHODS_";
1790 Result += PDecl->getName();
1791 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1792 "{\n\t";
1793 Result += utostr(NumMethods);
1794 Result += "\n";
1795
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001796 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001797 Result += "\t,{{(SEL)\"";
1798 Result += Methods[0]->getSelector().getName().c_str();
1799 Result += "\", \"\"}\n";
1800
1801 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001802 Result += "\t ,{(SEL)\"";
1803 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001804 std::string MethodTypeString;
1805 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1806 Result += "\", \"";
1807 Result += MethodTypeString;
1808 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001809 }
1810 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001811 }
1812 // Output:
1813 /* struct _objc_protocol {
1814 // Objective-C 1.0 extensions
1815 struct _objc_protocol_extension *isa;
1816 char *protocol_name;
1817 struct _objc_protocol **protocol_list;
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001818 struct _objc_protocol_method_list *instance_methods;
1819 struct _objc_protocol_method_list *class_methods;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001820 };
1821 */
1822 static bool objc_protocol = false;
1823 if (!objc_protocol) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001824 Result += "\nstruct _objc_protocol {\n";
1825 Result += "\tstruct _objc_protocol_extension *isa;\n";
1826 Result += "\tchar *protocol_name;\n";
1827 Result += "\tstruct _objc_protocol **protocol_list;\n";
1828 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
1829 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
1830 Result += "};\n";
1831
1832 /* struct _objc_protocol_list {
1833 struct _objc_protocol_list *next;
1834 int protocol_count;
1835 struct _objc_protocol *class_protocols[];
1836 }
1837 */
1838 Result += "\nstruct _objc_protocol_list {\n";
1839 Result += "\tstruct _objc_protocol_list *next;\n";
1840 Result += "\tint protocol_count;\n";
1841 Result += "\tstruct _objc_protocol *class_protocols[];\n";
1842 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001843 objc_protocol = true;
1844 }
1845
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001846 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
1847 Result += PDecl->getName();
1848 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
1849 "{\n\t0, \"";
1850 Result += PDecl->getName();
1851 Result += "\", 0, ";
1852 if (PDecl->getInstanceMethods() > 0) {
1853 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
1854 Result += PDecl->getName();
1855 Result += ", ";
1856 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001857 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001858 Result += "0, ";
1859 if (PDecl->getClassMethods() > 0) {
1860 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
1861 Result += PDecl->getName();
1862 Result += "\n";
1863 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001864 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001865 Result += "0\n";
1866 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001867 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001868 // Output the top lovel protocol meta-data for the class.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001869 Result += "\nstatic struct _objc_protocol_list _OBJC_";
1870 Result += prefix;
1871 Result += "_PROTOCOLS_";
1872 Result += ClassName;
1873 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1874 "{\n\t0, ";
1875 Result += utostr(NumProtocols);
1876 Result += "\n";
1877
1878 Result += "\t,{&_OBJC_PROTOCOL_";
1879 Result += Protocols[0]->getName();
1880 Result += " \n";
1881
1882 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001883 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001884 Result += "\t ,&_OBJC_PROTOCOL_";
1885 Result += PDecl->getName();
1886 Result += "\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001887 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001888 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001889 }
1890}
1891
1892/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
1893/// implementation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001894void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
1895 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001896 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
1897 // Find category declaration for this implementation.
1898 ObjcCategoryDecl *CDecl;
1899 for (CDecl = ClassDecl->getCategoryList(); CDecl;
1900 CDecl = CDecl->getNextClassCategory())
1901 if (CDecl->getIdentifier() == IDecl->getIdentifier())
1902 break;
Fariborz Jahanianbac97d42007-11-13 22:09:49 +00001903
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001904 char *FullCategoryName = (char*)alloca(
1905 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
1906 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
1907
1908 // Build _objc_method_list for class's instance methods if needed
1909 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1910 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001911 true,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001912 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001913
1914 // Build _objc_method_list for class's class methods if needed
1915 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
1916 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001917 false,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001918 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001919
1920 // Protocols referenced in class declaration?
Fariborz Jahanianbac97d42007-11-13 22:09:49 +00001921 // Null CDecl is case of a category implementation with no category interface
1922 if (CDecl)
1923 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1924 CDecl->getNumReferencedProtocols(),
1925 "CATEGORY",
1926 FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001927
1928 /* struct _objc_category {
1929 char *category_name;
1930 char *class_name;
1931 struct _objc_method_list *instance_methods;
1932 struct _objc_method_list *class_methods;
1933 struct _objc_protocol_list *protocols;
1934 // Objective-C 1.0 extensions
1935 uint32_t size; // sizeof (struct _objc_category)
1936 struct _objc_property_list *instance_properties; // category's own
1937 // @property decl.
1938 };
1939 */
1940
1941 static bool objc_category = false;
1942 if (!objc_category) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001943 Result += "\nstruct _objc_category {\n";
1944 Result += "\tchar *category_name;\n";
1945 Result += "\tchar *class_name;\n";
1946 Result += "\tstruct _objc_method_list *instance_methods;\n";
1947 Result += "\tstruct _objc_method_list *class_methods;\n";
1948 Result += "\tstruct _objc_protocol_list *protocols;\n";
1949 Result += "\tunsigned int size;\n";
1950 Result += "\tstruct _objc_property_list *instance_properties;\n";
1951 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001952 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001953 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001954 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
1955 Result += FullCategoryName;
1956 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
1957 Result += IDecl->getName();
1958 Result += "\"\n\t, \"";
1959 Result += ClassDecl->getName();
1960 Result += "\"\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001961
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001962 if (IDecl->getNumInstanceMethods() > 0) {
1963 Result += "\t, (struct _objc_method_list *)"
1964 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
1965 Result += FullCategoryName;
1966 Result += "\n";
1967 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001968 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001969 Result += "\t, 0\n";
1970 if (IDecl->getNumClassMethods() > 0) {
1971 Result += "\t, (struct _objc_method_list *)"
1972 "&_OBJC_CATEGORY_CLASS_METHODS_";
1973 Result += FullCategoryName;
1974 Result += "\n";
1975 }
1976 else
1977 Result += "\t, 0\n";
1978
Fariborz Jahanianbac97d42007-11-13 22:09:49 +00001979 if (CDecl && CDecl->getNumReferencedProtocols() > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001980 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
1981 Result += FullCategoryName;
1982 Result += "\n";
1983 }
1984 else
1985 Result += "\t, 0\n";
1986 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001987}
1988
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001989/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
1990/// ivar offset.
1991void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
1992 ObjcIvarDecl *ivar,
1993 std::string &Result) {
Fariborz Jahanian909f02a2007-11-05 17:47:33 +00001994 Result += "offsetof(struct ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001995 Result += IDecl->getName();
1996 Result += ", ";
1997 Result += ivar->getName();
1998 Result += ")";
1999}
2000
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002001//===----------------------------------------------------------------------===//
2002// Meta Data Emission
2003//===----------------------------------------------------------------------===//
2004
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002005void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
2006 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002007 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
2008
2009 // Build _objc_ivar_list metadata for classes ivars if needed
2010 int NumIvars = IDecl->getImplDeclNumIvars() > 0
2011 ? IDecl->getImplDeclNumIvars()
Steve Naroff03300712007-11-12 13:56:41 +00002012 : (CDecl ? CDecl->getNumInstanceVariables() : 0);
Fariborz Jahanianebe668f2007-11-26 20:59:57 +00002013 // Explictly declared @interface's are already synthesized.
2014 if (CDecl->ImplicitInterfaceDecl()) {
2015 // FIXME: Implementation of a class with no @interface (legacy) doese not
2016 // produce correct synthesis as yet.
2017 SynthesizeObjcInternalStruct(CDecl, Result);
2018 }
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00002019
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002020 if (NumIvars > 0) {
2021 static bool objc_ivar = false;
2022 if (!objc_ivar) {
2023 /* struct _objc_ivar {
2024 char *ivar_name;
2025 char *ivar_type;
2026 int ivar_offset;
2027 };
2028 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002029 Result += "\nstruct _objc_ivar {\n";
2030 Result += "\tchar *ivar_name;\n";
2031 Result += "\tchar *ivar_type;\n";
2032 Result += "\tint ivar_offset;\n";
2033 Result += "};\n";
2034
2035 /* struct _objc_ivar_list {
2036 int ivar_count;
2037 struct _objc_ivar ivar_list[];
2038 };
2039 */
2040 Result += "\nstruct _objc_ivar_list {\n";
2041 Result += "\tint ivar_count;\n";
2042 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002043 objc_ivar = true;
2044 }
2045
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002046 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
2047 Result += IDecl->getName();
2048 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
2049 "{\n\t";
2050 Result += utostr(NumIvars);
2051 Result += "\n";
2052
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002053 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
2054 ? IDecl->getImplDeclIVars()
Steve Naroff03300712007-11-12 13:56:41 +00002055 : CDecl->getInstanceVariables();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002056 Result += "\t,{{\"";
2057 Result += Ivars[0]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00002058 Result += "\", \"";
2059 std::string StrEncoding;
2060 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
2061 Result += StrEncoding;
2062 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00002063 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
2064 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002065 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002066 Result += "\t ,{\"";
2067 Result += Ivars[i]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00002068 Result += "\", \"";
2069 std::string StrEncoding;
2070 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
2071 Result += StrEncoding;
2072 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00002073 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
2074 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002075 }
2076
2077 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002078 }
2079
2080 // Build _objc_method_list for class's instance methods if needed
2081 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
2082 IDecl->getNumInstanceMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002083 true,
2084 "", IDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002085
2086 // Build _objc_method_list for class's class methods if needed
2087 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00002088 IDecl->getNumClassMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002089 false,
2090 "", IDecl->getName(), Result);
2091
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002092 // Protocols referenced in class declaration?
2093 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
2094 CDecl->getNumIntfRefProtocols(),
2095 "CLASS",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002096 CDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002097
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00002098
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002099 // Declaration of class/meta-class metadata
2100 /* struct _objc_class {
2101 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00002102 const char *super_class_name;
2103 char *name;
2104 long version;
2105 long info;
2106 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002107 struct _objc_ivar_list *ivars;
2108 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00002109 struct objc_cache *cache;
2110 struct objc_protocol_list *protocols;
2111 const char *ivar_layout;
2112 struct _objc_class_ext *ext;
2113 };
2114 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002115 static bool objc_class = false;
2116 if (!objc_class) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002117 Result += "\nstruct _objc_class {\n";
2118 Result += "\tstruct _objc_class *isa;\n";
2119 Result += "\tconst char *super_class_name;\n";
2120 Result += "\tchar *name;\n";
2121 Result += "\tlong version;\n";
2122 Result += "\tlong info;\n";
2123 Result += "\tlong instance_size;\n";
2124 Result += "\tstruct _objc_ivar_list *ivars;\n";
2125 Result += "\tstruct _objc_method_list *methods;\n";
2126 Result += "\tstruct objc_cache *cache;\n";
2127 Result += "\tstruct _objc_protocol_list *protocols;\n";
2128 Result += "\tconst char *ivar_layout;\n";
2129 Result += "\tstruct _objc_class_ext *ext;\n";
2130 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002131 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00002132 }
2133
2134 // Meta-class metadata generation.
2135 ObjcInterfaceDecl *RootClass = 0;
2136 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
2137 while (SuperClass) {
2138 RootClass = SuperClass;
2139 SuperClass = SuperClass->getSuperClass();
2140 }
2141 SuperClass = CDecl->getSuperClass();
2142
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002143 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
2144 Result += CDecl->getName();
2145 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
2146 "{\n\t(struct _objc_class *)\"";
2147 Result += (RootClass ? RootClass->getName() : CDecl->getName());
2148 Result += "\"";
2149
2150 if (SuperClass) {
2151 Result += ", \"";
2152 Result += SuperClass->getName();
2153 Result += "\", \"";
2154 Result += CDecl->getName();
2155 Result += "\"";
2156 }
2157 else {
2158 Result += ", 0, \"";
2159 Result += CDecl->getName();
2160 Result += "\"";
2161 }
Fariborz Jahanian04b38242007-12-04 19:31:56 +00002162 // Set 'ivars' field for root class to 0. Objc1 runtime does not use it.
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00002163 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002164 Result += ", 0,2, sizeof(struct _objc_class), 0";
Steve Naroffb26d7132007-12-05 21:49:40 +00002165 if (IDecl->getNumClassMethods() > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002166 Result += "\n\t, &_OBJC_CLASS_METHODS_";
Steve Naroffb26d7132007-12-05 21:49:40 +00002167 Result += IDecl->getName();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002168 Result += "\n";
2169 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00002170 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002171 Result += ", 0\n";
2172 if (CDecl->getNumIntfRefProtocols() > 0) {
2173 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
2174 Result += CDecl->getName();
2175 Result += ",0,0\n";
2176 }
Fariborz Jahanian454cb012007-10-24 20:54:23 +00002177 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002178 Result += "\t,0,0,0,0\n";
2179 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002180
2181 // class metadata generation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002182 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
2183 Result += CDecl->getName();
2184 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
2185 "{\n\t&_OBJC_METACLASS_";
2186 Result += CDecl->getName();
2187 if (SuperClass) {
2188 Result += ", \"";
2189 Result += SuperClass->getName();
2190 Result += "\", \"";
2191 Result += CDecl->getName();
2192 Result += "\"";
2193 }
2194 else {
2195 Result += ", 0, \"";
2196 Result += CDecl->getName();
2197 Result += "\"";
2198 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002199 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00002200 Result += ", 0,1";
2201 if (!ObjcSynthesizedStructs.count(CDecl))
2202 Result += ",0";
2203 else {
2204 // class has size. Must synthesize its size.
Fariborz Jahanian909f02a2007-11-05 17:47:33 +00002205 Result += ",sizeof(struct ";
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00002206 Result += CDecl->getName();
2207 Result += ")";
2208 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002209 if (NumIvars > 0) {
2210 Result += ", &_OBJC_INSTANCE_VARIABLES_";
2211 Result += CDecl->getName();
2212 Result += "\n\t";
2213 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002214 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002215 Result += ",0";
2216 if (IDecl->getNumInstanceMethods() > 0) {
2217 Result += ", &_OBJC_INSTANCE_METHODS_";
2218 Result += CDecl->getName();
2219 Result += ", 0\n\t";
2220 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002221 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002222 Result += ",0,0";
2223 if (CDecl->getNumIntfRefProtocols() > 0) {
2224 Result += ", &_OBJC_CLASS_PROTOCOLS_";
2225 Result += CDecl->getName();
2226 Result += ", 0,0\n";
2227 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00002228 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002229 Result += ",0,0,0\n";
2230 Result += "};\n";
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00002231}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00002232
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00002233/// RewriteImplementations - This routine rewrites all method implementations
2234/// and emits meta-data.
2235
2236void RewriteTest::RewriteImplementations(std::string &Result) {
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002237 int ClsDefCount = ClassImplementation.size();
2238 int CatDefCount = CategoryImplementation.size();
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00002239
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002240 if (ClsDefCount == 0 && CatDefCount == 0)
2241 return;
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00002242 // Rewrite implemented methods
2243 for (int i = 0; i < ClsDefCount; i++)
2244 RewriteImplementationDecl(ClassImplementation[i]);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00002245
Fariborz Jahanian66d6b292007-11-13 20:04:28 +00002246 for (int i = 0; i < CatDefCount; i++)
2247 RewriteImplementationDecl(CategoryImplementation[i]);
2248
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00002249 // This is needed for use of offsetof
2250 Result += "#include <stddef.h>\n";
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00002251
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002252 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00002253 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002254 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00002255
2256 // For each implemented category, write out all its meta data.
2257 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002258 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00002259
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002260 // Write objc_symtab metadata
2261 /*
2262 struct _objc_symtab
2263 {
2264 long sel_ref_cnt;
2265 SEL *refs;
2266 short cls_def_cnt;
2267 short cat_def_cnt;
2268 void *defs[cls_def_cnt + cat_def_cnt];
2269 };
2270 */
2271
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002272 Result += "\nstruct _objc_symtab {\n";
2273 Result += "\tlong sel_ref_cnt;\n";
2274 Result += "\tSEL *refs;\n";
2275 Result += "\tshort cls_def_cnt;\n";
2276 Result += "\tshort cat_def_cnt;\n";
2277 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
2278 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002279
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002280 Result += "static struct _objc_symtab "
2281 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
2282 Result += "\t0, 0, " + utostr(ClsDefCount)
2283 + ", " + utostr(CatDefCount) + "\n";
2284 for (int i = 0; i < ClsDefCount; i++) {
2285 Result += "\t,&_OBJC_CLASS_";
2286 Result += ClassImplementation[i]->getName();
2287 Result += "\n";
2288 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002289
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002290 for (int i = 0; i < CatDefCount; i++) {
2291 Result += "\t,&_OBJC_CATEGORY_";
2292 Result += CategoryImplementation[i]->getClassInterface()->getName();
2293 Result += "_";
2294 Result += CategoryImplementation[i]->getName();
2295 Result += "\n";
2296 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002297
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002298 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002299
2300 // Write objc_module metadata
2301
2302 /*
2303 struct _objc_module {
2304 long version;
2305 long size;
2306 const char *name;
2307 struct _objc_symtab *symtab;
2308 }
2309 */
2310
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002311 Result += "\nstruct _objc_module {\n";
2312 Result += "\tlong version;\n";
2313 Result += "\tlong size;\n";
2314 Result += "\tconst char *name;\n";
2315 Result += "\tstruct _objc_symtab *symtab;\n";
2316 Result += "};\n\n";
2317 Result += "static struct _objc_module "
2318 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00002319 Result += "\t" + utostr(OBJC_ABI_VERSION) +
2320 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00002321 Result += "};\n\n";
Fariborz Jahanian7a3279d2007-11-13 19:21:13 +00002322
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00002323}
Chris Lattner311ff022007-10-16 22:36:42 +00002324