blob: bfd14bb55b2bec0407abe033a266a19355d49623 [file] [log] [blame]
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Rewrite/ASTConsumers.h"
15#include "clang/Rewrite/Rewriter.h"
16#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
18#include "clang/AST/ParentMap.h"
19#include "clang/Basic/SourceManager.h"
20#include "clang/Basic/IdentifierTable.h"
21#include "clang/Basic/Diagnostic.h"
22#include "clang/Lex/Lexer.h"
23#include "llvm/Support/MemoryBuffer.h"
24#include "llvm/Support/raw_ostream.h"
25#include "llvm/ADT/StringExtras.h"
26#include "llvm/ADT/SmallPtrSet.h"
27#include "llvm/ADT/OwningPtr.h"
28#include "llvm/ADT/DenseSet.h"
29
30using namespace clang;
31using llvm::utostr;
32
33namespace {
34 class RewriteModernObjC : public ASTConsumer {
35 protected:
36
37 enum {
38 BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
39 block, ... */
40 BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
41 BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
42 __block variable */
43 BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
44 helpers */
45 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
46 support routines */
47 BLOCK_BYREF_CURRENT_MAX = 256
48 };
49
50 enum {
51 BLOCK_NEEDS_FREE = (1 << 24),
52 BLOCK_HAS_COPY_DISPOSE = (1 << 25),
53 BLOCK_HAS_CXX_OBJ = (1 << 26),
54 BLOCK_IS_GC = (1 << 27),
55 BLOCK_IS_GLOBAL = (1 << 28),
56 BLOCK_HAS_DESCRIPTOR = (1 << 29)
57 };
58 static const int OBJC_ABI_VERSION = 7;
59
60 Rewriter Rewrite;
61 DiagnosticsEngine &Diags;
62 const LangOptions &LangOpts;
63 ASTContext *Context;
64 SourceManager *SM;
65 TranslationUnitDecl *TUDecl;
66 FileID MainFileID;
67 const char *MainFileStart, *MainFileEnd;
68 Stmt *CurrentBody;
69 ParentMap *PropParentMap; // created lazily.
70 std::string InFileName;
71 raw_ostream* OutFile;
72 std::string Preamble;
73
74 TypeDecl *ProtocolTypeDecl;
75 VarDecl *GlobalVarDecl;
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +000076 Expr *GlobalConstructionExp;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +000077 unsigned RewriteFailedDiag;
Fariborz Jahaniand13c2c22012-03-22 19:54:39 +000078 unsigned GlobalBlockRewriteFailedDiag;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +000079 // ObjC string constant support.
80 unsigned NumObjCStringLiterals;
81 VarDecl *ConstantStringClassReference;
82 RecordDecl *NSStringRecord;
83
84 // ObjC foreach break/continue generation support.
85 int BcLabelCount;
86
87 unsigned TryFinallyContainsReturnDiag;
88 // Needed for super.
89 ObjCMethodDecl *CurMethodDef;
90 RecordDecl *SuperStructDecl;
91 RecordDecl *ConstantStringDecl;
92
93 FunctionDecl *MsgSendFunctionDecl;
94 FunctionDecl *MsgSendSuperFunctionDecl;
95 FunctionDecl *MsgSendStretFunctionDecl;
96 FunctionDecl *MsgSendSuperStretFunctionDecl;
97 FunctionDecl *MsgSendFpretFunctionDecl;
98 FunctionDecl *GetClassFunctionDecl;
99 FunctionDecl *GetMetaClassFunctionDecl;
100 FunctionDecl *GetSuperClassFunctionDecl;
101 FunctionDecl *SelGetUidFunctionDecl;
102 FunctionDecl *CFStringFunctionDecl;
103 FunctionDecl *SuperContructorFunctionDecl;
104 FunctionDecl *CurFunctionDef;
105 FunctionDecl *CurFunctionDeclToDeclareForBlock;
106
107 /* Misc. containers needed for meta-data rewrite. */
108 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
109 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
110 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
111 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
Fariborz Jahaniancf4c60f2012-02-17 22:20:12 +0000112 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;
Fariborz Jahanian15f87772012-02-28 22:45:07 +0000113 llvm::SmallPtrSet<TagDecl*, 8> TagsDefinedInIvarDecls;
Fariborz Jahaniancf4c60f2012-02-17 22:20:12 +0000114 SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
Fariborz Jahanian88f7f752012-03-14 23:18:19 +0000115 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
116 SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
117
118 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
119 llvm::SmallVector<ObjCCategoryDecl*, 8> DefinedNonLazyCategories;
120
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000121 SmallVector<Stmt *, 32> Stmts;
122 SmallVector<int, 8> ObjCBcLabelNo;
123 // Remember all the @protocol(<expr>) expressions.
124 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
125
126 llvm::DenseSet<uint64_t> CopyDestroyCache;
127
128 // Block expressions.
129 SmallVector<BlockExpr *, 32> Blocks;
130 SmallVector<int, 32> InnerDeclRefsCount;
John McCallf4b88a42012-03-10 09:33:50 +0000131 SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000132
John McCallf4b88a42012-03-10 09:33:50 +0000133 SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000134
135 // Block related declarations.
136 SmallVector<ValueDecl *, 8> BlockByCopyDecls;
137 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
138 SmallVector<ValueDecl *, 8> BlockByRefDecls;
139 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
140 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
141 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
142 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
143
144 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
Fariborz Jahanian72c88f12012-02-22 18:13:25 +0000145 llvm::DenseMap<ObjCInterfaceDecl *,
146 llvm::SmallPtrSet<ObjCIvarDecl *, 8> > ReferencedIvars;
147
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000148 // This maps an original source AST to it's rewritten form. This allows
149 // us to avoid rewriting the same node twice (which is very uncommon).
150 // This is needed to support some of the exotic property rewriting.
151 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
152
153 // Needed for header files being rewritten
154 bool IsHeader;
155 bool SilenceRewriteMacroWarning;
156 bool objc_impl_method;
157
158 bool DisableReplaceStmt;
159 class DisableReplaceStmtScope {
160 RewriteModernObjC &R;
161 bool SavedValue;
162
163 public:
164 DisableReplaceStmtScope(RewriteModernObjC &R)
165 : R(R), SavedValue(R.DisableReplaceStmt) {
166 R.DisableReplaceStmt = true;
167 }
168 ~DisableReplaceStmtScope() {
169 R.DisableReplaceStmt = SavedValue;
170 }
171 };
172 void InitializeCommon(ASTContext &context);
173
174 public:
Fariborz Jahanian90af4e22012-02-14 17:19:02 +0000175 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000176 // Top Level Driver code.
177 virtual bool HandleTopLevelDecl(DeclGroupRef D) {
178 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
179 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
180 if (!Class->isThisDeclarationADefinition()) {
181 RewriteForwardClassDecl(D);
182 break;
Fariborz Jahaniancf4c60f2012-02-17 22:20:12 +0000183 } else {
184 // Keep track of all interface declarations seen.
Fariborz Jahanianf3295272012-02-24 21:42:38 +0000185 ObjCInterfacesSeen.push_back(Class);
Fariborz Jahaniancf4c60f2012-02-17 22:20:12 +0000186 break;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000187 }
188 }
189
190 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
191 if (!Proto->isThisDeclarationADefinition()) {
192 RewriteForwardProtocolDecl(D);
193 break;
194 }
195 }
196
197 HandleTopLevelSingleDecl(*I);
198 }
199 return true;
200 }
201 void HandleTopLevelSingleDecl(Decl *D);
202 void HandleDeclInMainFile(Decl *D);
203 RewriteModernObjC(std::string inFile, raw_ostream *OS,
204 DiagnosticsEngine &D, const LangOptions &LOpts,
205 bool silenceMacroWarn);
206
207 ~RewriteModernObjC() {}
208
209 virtual void HandleTranslationUnit(ASTContext &C);
210
211 void ReplaceStmt(Stmt *Old, Stmt *New) {
212 Stmt *ReplacingStmt = ReplacedNodes[Old];
213
214 if (ReplacingStmt)
215 return; // We can't rewrite the same node twice.
216
217 if (DisableReplaceStmt)
218 return;
219
220 // If replacement succeeded or warning disabled return with no warning.
221 if (!Rewrite.ReplaceStmt(Old, New)) {
222 ReplacedNodes[Old] = New;
223 return;
224 }
225 if (SilenceRewriteMacroWarning)
226 return;
227 Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
228 << Old->getSourceRange();
229 }
230
231 void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
232 if (DisableReplaceStmt)
233 return;
234
235 // Measure the old text.
236 int Size = Rewrite.getRangeSize(SrcRange);
237 if (Size == -1) {
238 Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
239 << Old->getSourceRange();
240 return;
241 }
242 // Get the new text.
243 std::string SStr;
244 llvm::raw_string_ostream S(SStr);
245 New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts));
246 const std::string &Str = S.str();
247
248 // If replacement succeeded or warning disabled return with no warning.
249 if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
250 ReplacedNodes[Old] = New;
251 return;
252 }
253 if (SilenceRewriteMacroWarning)
254 return;
255 Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
256 << Old->getSourceRange();
257 }
258
259 void InsertText(SourceLocation Loc, StringRef Str,
260 bool InsertAfter = true) {
261 // If insertion succeeded or warning disabled return with no warning.
262 if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
263 SilenceRewriteMacroWarning)
264 return;
265
266 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
267 }
268
269 void ReplaceText(SourceLocation Start, unsigned OrigLength,
270 StringRef Str) {
271 // If removal succeeded or warning disabled return with no warning.
272 if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
273 SilenceRewriteMacroWarning)
274 return;
275
276 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
277 }
278
279 // Syntactic Rewriting.
280 void RewriteRecordBody(RecordDecl *RD);
281 void RewriteInclude();
282 void RewriteForwardClassDecl(DeclGroupRef D);
283 void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG);
284 void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
285 const std::string &typedefString);
286 void RewriteImplementations();
287 void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
288 ObjCImplementationDecl *IMD,
289 ObjCCategoryImplDecl *CID);
290 void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
291 void RewriteImplementationDecl(Decl *Dcl);
292 void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
293 ObjCMethodDecl *MDecl, std::string &ResultStr);
294 void RewriteTypeIntoString(QualType T, std::string &ResultStr,
295 const FunctionType *&FPRetType);
296 void RewriteByRefString(std::string &ResultStr, const std::string &Name,
297 ValueDecl *VD, bool def=false);
298 void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
299 void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
300 void RewriteForwardProtocolDecl(DeclGroupRef D);
301 void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG);
302 void RewriteMethodDeclaration(ObjCMethodDecl *Method);
303 void RewriteProperty(ObjCPropertyDecl *prop);
304 void RewriteFunctionDecl(FunctionDecl *FD);
305 void RewriteBlockPointerType(std::string& Str, QualType Type);
306 void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
307 void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
308 void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
309 void RewriteTypeOfDecl(VarDecl *VD);
310 void RewriteObjCQualifiedInterfaceTypes(Expr *E);
311
312 // Expression Rewriting.
313 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
314 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
315 Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
316 Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
317 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
318 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
319 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
Fariborz Jahanian55947042012-03-27 20:17:30 +0000320 Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);
Fariborz Jahanian0f9b18e2012-03-30 16:49:36 +0000321 Stmt *RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000322 Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000323 Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
324 Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
325 Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
326 Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
327 SourceLocation OrigEnd);
328 Stmt *RewriteBreakStmt(BreakStmt *S);
329 Stmt *RewriteContinueStmt(ContinueStmt *S);
330 void RewriteCastExpr(CStyleCastExpr *CE);
331
332 // Block rewriting.
333 void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
334
335 // Block specific rewrite rules.
336 void RewriteBlockPointerDecl(NamedDecl *VD);
337 void RewriteByRefVar(VarDecl *VD);
John McCallf4b88a42012-03-10 09:33:50 +0000338 Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000339 Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
340 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
341
342 void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
343 std::string &Result);
344
Fariborz Jahanian15f87772012-02-28 22:45:07 +0000345 void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
346
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +0000347 bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
348
Fariborz Jahanian72c88f12012-02-22 18:13:25 +0000349 void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
350 std::string &Result);
351
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000352 virtual void Initialize(ASTContext &context);
353
354 // Misc. AST transformation routines. Somtimes they end up calling
355 // rewriting routines on the new ASTs.
356 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
357 Expr **args, unsigned nargs,
358 SourceLocation StartLoc=SourceLocation(),
359 SourceLocation EndLoc=SourceLocation());
360
361 Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
362 SourceLocation StartLoc=SourceLocation(),
363 SourceLocation EndLoc=SourceLocation());
364
365 void SynthCountByEnumWithState(std::string &buf);
366 void SynthMsgSendFunctionDecl();
367 void SynthMsgSendSuperFunctionDecl();
368 void SynthMsgSendStretFunctionDecl();
369 void SynthMsgSendFpretFunctionDecl();
370 void SynthMsgSendSuperStretFunctionDecl();
371 void SynthGetClassFunctionDecl();
372 void SynthGetMetaClassFunctionDecl();
373 void SynthGetSuperClassFunctionDecl();
374 void SynthSelGetUidFunctionDecl();
375 void SynthSuperContructorFunctionDecl();
376
377 // Rewriting metadata
378 template<typename MethodIterator>
379 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
380 MethodIterator MethodEnd,
381 bool IsInstanceMethod,
382 StringRef prefix,
383 StringRef ClassName,
384 std::string &Result);
Fariborz Jahanianda9624a2012-02-08 19:53:58 +0000385 void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
386 std::string &Result);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000387 virtual void RewriteObjCProtocolListMetaData(
388 const ObjCList<ObjCProtocolDecl> &Prots,
389 StringRef prefix, StringRef ClassName, std::string &Result);
390 virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
391 std::string &Result);
Fariborz Jahaniane0335782012-03-27 18:41:05 +0000392 virtual void RewriteClassSetupInitHook(std::string &Result);
393
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000394 virtual void RewriteMetaDataIntoBuffer(std::string &Result);
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +0000395 virtual void WriteImageInfo(std::string &Result);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000396 virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
397 std::string &Result);
Fariborz Jahaniane0335782012-03-27 18:41:05 +0000398 virtual void RewriteCategorySetupInitHook(std::string &Result);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000399
400 // Rewriting ivar
401 virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
402 std::string &Result);
403 virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
404
405
406 std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
407 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
408 StringRef funcName, std::string Tag);
409 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
410 StringRef funcName, std::string Tag);
411 std::string SynthesizeBlockImpl(BlockExpr *CE,
412 std::string Tag, std::string Desc);
413 std::string SynthesizeBlockDescriptor(std::string DescTag,
414 std::string ImplTag,
415 int i, StringRef funcName,
416 unsigned hasCopy);
417 Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
418 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
419 StringRef FunName);
420 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
421 Stmt *SynthBlockInitExpr(BlockExpr *Exp,
John McCallf4b88a42012-03-10 09:33:50 +0000422 const SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000423
424 // Misc. helper routines.
425 QualType getProtocolType();
426 void WarnAboutReturnGotoStmts(Stmt *S);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000427 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
428 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
429 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
430
431 bool IsDeclStmtInForeachHeader(DeclStmt *DS);
432 void CollectBlockDeclRefInfo(BlockExpr *Exp);
433 void GetBlockDeclRefExprs(Stmt *S);
434 void GetInnerBlockDeclRefExprs(Stmt *S,
John McCallf4b88a42012-03-10 09:33:50 +0000435 SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000436 llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts);
437
438 // We avoid calling Type::isBlockPointerType(), since it operates on the
439 // canonical type. We only care if the top-level type is a closure pointer.
440 bool isTopLevelBlockPointerType(QualType T) {
441 return isa<BlockPointerType>(T);
442 }
443
444 /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
445 /// to a function pointer type and upon success, returns true; false
446 /// otherwise.
447 bool convertBlockPointerToFunctionPointer(QualType &T) {
448 if (isTopLevelBlockPointerType(T)) {
449 const BlockPointerType *BPT = T->getAs<BlockPointerType>();
450 T = Context->getPointerType(BPT->getPointeeType());
451 return true;
452 }
453 return false;
454 }
455
Fariborz Jahanian164d6f82012-02-13 18:57:49 +0000456 bool convertObjCTypeToCStyleType(QualType &T);
457
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000458 bool needToScanForQualifiers(QualType T);
459 QualType getSuperStructType();
460 QualType getConstantStringStructType();
461 QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
462 bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
463
464 void convertToUnqualifiedObjCType(QualType &T) {
465 if (T->isObjCQualifiedIdType())
466 T = Context->getObjCIdType();
467 else if (T->isObjCQualifiedClassType())
468 T = Context->getObjCClassType();
469 else if (T->isObjCObjectPointerType() &&
470 T->getPointeeType()->isObjCQualifiedInterfaceType()) {
471 if (const ObjCObjectPointerType * OBJPT =
472 T->getAsObjCInterfacePointerType()) {
473 const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
474 T = QualType(IFaceT, 0);
475 T = Context->getPointerType(T);
476 }
477 }
478 }
479
480 // FIXME: This predicate seems like it would be useful to add to ASTContext.
481 bool isObjCType(QualType T) {
482 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
483 return false;
484
485 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
486
487 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
488 OCT == Context->getCanonicalType(Context->getObjCClassType()))
489 return true;
490
491 if (const PointerType *PT = OCT->getAs<PointerType>()) {
492 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
493 PT->getPointeeType()->isObjCQualifiedIdType())
494 return true;
495 }
496 return false;
497 }
498 bool PointerTypeTakesAnyBlockArguments(QualType QT);
499 bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
500 void GetExtentOfArgList(const char *Name, const char *&LParen,
501 const char *&RParen);
502
503 void QuoteDoublequotes(std::string &From, std::string &To) {
504 for (unsigned i = 0; i < From.length(); i++) {
505 if (From[i] == '"')
506 To += "\\\"";
507 else
508 To += From[i];
509 }
510 }
511
512 QualType getSimpleFunctionType(QualType result,
513 const QualType *args,
514 unsigned numArgs,
515 bool variadic = false) {
516 if (result == Context->getObjCInstanceType())
517 result = Context->getObjCIdType();
518 FunctionProtoType::ExtProtoInfo fpi;
519 fpi.Variadic = variadic;
520 return Context->getFunctionType(result, args, numArgs, fpi);
521 }
522
523 // Helper function: create a CStyleCastExpr with trivial type source info.
524 CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
525 CastKind Kind, Expr *E) {
526 TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
527 return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo,
528 SourceLocation(), SourceLocation());
529 }
Fariborz Jahanian88f7f752012-03-14 23:18:19 +0000530
531 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
532 IdentifierInfo* II = &Context->Idents.get("load");
533 Selector LoadSel = Context->Selectors.getSelector(0, &II);
534 return OD->getClassMethod(LoadSel) != 0;
535 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000536 };
537
538}
539
540void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
541 NamedDecl *D) {
542 if (const FunctionProtoType *fproto
543 = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
544 for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
545 E = fproto->arg_type_end(); I && (I != E); ++I)
546 if (isTopLevelBlockPointerType(*I)) {
547 // All the args are checked/rewritten. Don't call twice!
548 RewriteBlockPointerDecl(D);
549 break;
550 }
551 }
552}
553
554void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
555 const PointerType *PT = funcType->getAs<PointerType>();
556 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
557 RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
558}
559
560static bool IsHeaderFile(const std::string &Filename) {
561 std::string::size_type DotPos = Filename.rfind('.');
562
563 if (DotPos == std::string::npos) {
564 // no file extension
565 return false;
566 }
567
568 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
569 // C header: .h
570 // C++ header: .hh or .H;
571 return Ext == "h" || Ext == "hh" || Ext == "H";
572}
573
574RewriteModernObjC::RewriteModernObjC(std::string inFile, raw_ostream* OS,
575 DiagnosticsEngine &D, const LangOptions &LOpts,
576 bool silenceMacroWarn)
577 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
578 SilenceRewriteMacroWarning(silenceMacroWarn) {
579 IsHeader = IsHeaderFile(inFile);
580 RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
581 "rewriting sub-expression within a macro (may not be correct)");
Fariborz Jahaniand13c2c22012-03-22 19:54:39 +0000582 // FIXME. This should be an error. But if block is not called, it is OK. And it
583 // may break including some headers.
584 GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
585 "rewriting block literal declared in global scope is not implemented");
586
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000587 TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
588 DiagnosticsEngine::Warning,
589 "rewriter doesn't support user-specified control flow semantics "
590 "for @try/@finally (code may not execute properly)");
591}
592
593ASTConsumer *clang::CreateModernObjCRewriter(const std::string& InFile,
594 raw_ostream* OS,
595 DiagnosticsEngine &Diags,
596 const LangOptions &LOpts,
597 bool SilenceRewriteMacroWarning) {
598 return new RewriteModernObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
599}
600
601void RewriteModernObjC::InitializeCommon(ASTContext &context) {
602 Context = &context;
603 SM = &Context->getSourceManager();
604 TUDecl = Context->getTranslationUnitDecl();
605 MsgSendFunctionDecl = 0;
606 MsgSendSuperFunctionDecl = 0;
607 MsgSendStretFunctionDecl = 0;
608 MsgSendSuperStretFunctionDecl = 0;
609 MsgSendFpretFunctionDecl = 0;
610 GetClassFunctionDecl = 0;
611 GetMetaClassFunctionDecl = 0;
612 GetSuperClassFunctionDecl = 0;
613 SelGetUidFunctionDecl = 0;
614 CFStringFunctionDecl = 0;
615 ConstantStringClassReference = 0;
616 NSStringRecord = 0;
617 CurMethodDef = 0;
618 CurFunctionDef = 0;
619 CurFunctionDeclToDeclareForBlock = 0;
620 GlobalVarDecl = 0;
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +0000621 GlobalConstructionExp = 0;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000622 SuperStructDecl = 0;
623 ProtocolTypeDecl = 0;
624 ConstantStringDecl = 0;
625 BcLabelCount = 0;
626 SuperContructorFunctionDecl = 0;
627 NumObjCStringLiterals = 0;
628 PropParentMap = 0;
629 CurrentBody = 0;
630 DisableReplaceStmt = false;
631 objc_impl_method = false;
632
633 // Get the ID and start/end of the main file.
634 MainFileID = SM->getMainFileID();
635 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
636 MainFileStart = MainBuf->getBufferStart();
637 MainFileEnd = MainBuf->getBufferEnd();
638
David Blaikie4e4d0842012-03-11 07:00:24 +0000639 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000640}
641
642//===----------------------------------------------------------------------===//
643// Top Level Driver Code
644//===----------------------------------------------------------------------===//
645
646void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
647 if (Diags.hasErrorOccurred())
648 return;
649
650 // Two cases: either the decl could be in the main file, or it could be in a
651 // #included file. If the former, rewrite it now. If the later, check to see
652 // if we rewrote the #include/#import.
653 SourceLocation Loc = D->getLocation();
654 Loc = SM->getExpansionLoc(Loc);
655
656 // If this is for a builtin, ignore it.
657 if (Loc.isInvalid()) return;
658
659 // Look for built-in declarations that we need to refer during the rewrite.
660 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
661 RewriteFunctionDecl(FD);
662 } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
663 // declared in <Foundation/NSString.h>
664 if (FVD->getName() == "_NSConstantStringClassReference") {
665 ConstantStringClassReference = FVD;
666 return;
667 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000668 } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
669 RewriteCategoryDecl(CD);
670 } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
671 if (PD->isThisDeclarationADefinition())
672 RewriteProtocolDecl(PD);
673 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
674 // Recurse into linkage specifications
675 for (DeclContext::decl_iterator DI = LSD->decls_begin(),
676 DIEnd = LSD->decls_end();
677 DI != DIEnd; ) {
678 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
679 if (!IFace->isThisDeclarationADefinition()) {
680 SmallVector<Decl *, 8> DG;
681 SourceLocation StartLoc = IFace->getLocStart();
682 do {
683 if (isa<ObjCInterfaceDecl>(*DI) &&
684 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
685 StartLoc == (*DI)->getLocStart())
686 DG.push_back(*DI);
687 else
688 break;
689
690 ++DI;
691 } while (DI != DIEnd);
692 RewriteForwardClassDecl(DG);
693 continue;
694 }
695 }
696
697 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
698 if (!Proto->isThisDeclarationADefinition()) {
699 SmallVector<Decl *, 8> DG;
700 SourceLocation StartLoc = Proto->getLocStart();
701 do {
702 if (isa<ObjCProtocolDecl>(*DI) &&
703 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
704 StartLoc == (*DI)->getLocStart())
705 DG.push_back(*DI);
706 else
707 break;
708
709 ++DI;
710 } while (DI != DIEnd);
711 RewriteForwardProtocolDecl(DG);
712 continue;
713 }
714 }
715
716 HandleTopLevelSingleDecl(*DI);
717 ++DI;
718 }
719 }
720 // If we have a decl in the main file, see if we should rewrite it.
721 if (SM->isFromMainFile(Loc))
722 return HandleDeclInMainFile(D);
723}
724
725//===----------------------------------------------------------------------===//
726// Syntactic (non-AST) Rewriting Code
727//===----------------------------------------------------------------------===//
728
729void RewriteModernObjC::RewriteInclude() {
730 SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
731 StringRef MainBuf = SM->getBufferData(MainFileID);
732 const char *MainBufStart = MainBuf.begin();
733 const char *MainBufEnd = MainBuf.end();
734 size_t ImportLen = strlen("import");
735
736 // Loop over the whole file, looking for includes.
737 for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
738 if (*BufPtr == '#') {
739 if (++BufPtr == MainBufEnd)
740 return;
741 while (*BufPtr == ' ' || *BufPtr == '\t')
742 if (++BufPtr == MainBufEnd)
743 return;
744 if (!strncmp(BufPtr, "import", ImportLen)) {
745 // replace import with include
746 SourceLocation ImportLoc =
747 LocStart.getLocWithOffset(BufPtr-MainBufStart);
748 ReplaceText(ImportLoc, ImportLen, "include");
749 BufPtr += ImportLen;
750 }
751 }
752 }
753}
754
755static std::string getIvarAccessString(ObjCIvarDecl *OID) {
756 const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();
757 std::string S;
758 S = "((struct ";
759 S += ClassDecl->getIdentifier()->getName();
760 S += "_IMPL *)self)->";
761 S += OID->getName();
762 return S;
763}
764
765void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
766 ObjCImplementationDecl *IMD,
767 ObjCCategoryImplDecl *CID) {
768 static bool objcGetPropertyDefined = false;
769 static bool objcSetPropertyDefined = false;
770 SourceLocation startLoc = PID->getLocStart();
771 InsertText(startLoc, "// ");
772 const char *startBuf = SM->getCharacterData(startLoc);
773 assert((*startBuf == '@') && "bogus @synthesize location");
774 const char *semiBuf = strchr(startBuf, ';');
775 assert((*semiBuf == ';') && "@synthesize: can't find ';'");
776 SourceLocation onePastSemiLoc =
777 startLoc.getLocWithOffset(semiBuf-startBuf+1);
778
779 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
780 return; // FIXME: is this correct?
781
782 // Generate the 'getter' function.
783 ObjCPropertyDecl *PD = PID->getPropertyDecl();
784 ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
785
786 if (!OID)
787 return;
788 unsigned Attributes = PD->getPropertyAttributes();
789 if (!PD->getGetterMethodDecl()->isDefined()) {
790 bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
791 (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
792 ObjCPropertyDecl::OBJC_PR_copy));
793 std::string Getr;
794 if (GenGetProperty && !objcGetPropertyDefined) {
795 objcGetPropertyDefined = true;
796 // FIXME. Is this attribute correct in all cases?
797 Getr = "\nextern \"C\" __declspec(dllimport) "
798 "id objc_getProperty(id, SEL, long, bool);\n";
799 }
800 RewriteObjCMethodDecl(OID->getContainingInterface(),
801 PD->getGetterMethodDecl(), Getr);
802 Getr += "{ ";
803 // Synthesize an explicit cast to gain access to the ivar.
804 // See objc-act.c:objc_synthesize_new_getter() for details.
805 if (GenGetProperty) {
806 // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
807 Getr += "typedef ";
808 const FunctionType *FPRetType = 0;
809 RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr,
810 FPRetType);
811 Getr += " _TYPE";
812 if (FPRetType) {
813 Getr += ")"; // close the precedence "scope" for "*".
814
815 // Now, emit the argument types (if any).
816 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
817 Getr += "(";
818 for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
819 if (i) Getr += ", ";
820 std::string ParamStr = FT->getArgType(i).getAsString(
821 Context->getPrintingPolicy());
822 Getr += ParamStr;
823 }
824 if (FT->isVariadic()) {
825 if (FT->getNumArgs()) Getr += ", ";
826 Getr += "...";
827 }
828 Getr += ")";
829 } else
830 Getr += "()";
831 }
832 Getr += ";\n";
833 Getr += "return (_TYPE)";
834 Getr += "objc_getProperty(self, _cmd, ";
835 RewriteIvarOffsetComputation(OID, Getr);
836 Getr += ", 1)";
837 }
838 else
839 Getr += "return " + getIvarAccessString(OID);
840 Getr += "; }";
841 InsertText(onePastSemiLoc, Getr);
842 }
843
844 if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined())
845 return;
846
847 // Generate the 'setter' function.
848 std::string Setr;
849 bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
850 ObjCPropertyDecl::OBJC_PR_copy);
851 if (GenSetProperty && !objcSetPropertyDefined) {
852 objcSetPropertyDefined = true;
853 // FIXME. Is this attribute correct in all cases?
854 Setr = "\nextern \"C\" __declspec(dllimport) "
855 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
856 }
857
858 RewriteObjCMethodDecl(OID->getContainingInterface(),
859 PD->getSetterMethodDecl(), Setr);
860 Setr += "{ ";
861 // Synthesize an explicit cast to initialize the ivar.
862 // See objc-act.c:objc_synthesize_new_setter() for details.
863 if (GenSetProperty) {
864 Setr += "objc_setProperty (self, _cmd, ";
865 RewriteIvarOffsetComputation(OID, Setr);
866 Setr += ", (id)";
867 Setr += PD->getName();
868 Setr += ", ";
869 if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
870 Setr += "0, ";
871 else
872 Setr += "1, ";
873 if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
874 Setr += "1)";
875 else
876 Setr += "0)";
877 }
878 else {
879 Setr += getIvarAccessString(OID) + " = ";
880 Setr += PD->getName();
881 }
882 Setr += "; }";
883 InsertText(onePastSemiLoc, Setr);
884}
885
886static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
887 std::string &typedefString) {
888 typedefString += "#ifndef _REWRITER_typedef_";
889 typedefString += ForwardDecl->getNameAsString();
890 typedefString += "\n";
891 typedefString += "#define _REWRITER_typedef_";
892 typedefString += ForwardDecl->getNameAsString();
893 typedefString += "\n";
894 typedefString += "typedef struct objc_object ";
895 typedefString += ForwardDecl->getNameAsString();
Fariborz Jahanianc38503b2012-03-12 23:58:28 +0000896 // typedef struct { } _objc_exc_Classname;
897 typedefString += ";\ntypedef struct {} _objc_exc_";
898 typedefString += ForwardDecl->getNameAsString();
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000899 typedefString += ";\n#endif\n";
900}
901
902void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
903 const std::string &typedefString) {
904 SourceLocation startLoc = ClassDecl->getLocStart();
905 const char *startBuf = SM->getCharacterData(startLoc);
906 const char *semiPtr = strchr(startBuf, ';');
907 // Replace the @class with typedefs corresponding to the classes.
908 ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
909}
910
911void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {
912 std::string typedefString;
913 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
914 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);
915 if (I == D.begin()) {
916 // Translate to typedef's that forward reference structs with the same name
917 // as the class. As a convenience, we include the original declaration
918 // as a comment.
919 typedefString += "// @class ";
920 typedefString += ForwardDecl->getNameAsString();
921 typedefString += ";\n";
922 }
923 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
924 }
925 DeclGroupRef::iterator I = D.begin();
926 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
927}
928
929void RewriteModernObjC::RewriteForwardClassDecl(
930 const llvm::SmallVector<Decl*, 8> &D) {
931 std::string typedefString;
932 for (unsigned i = 0; i < D.size(); i++) {
933 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
934 if (i == 0) {
935 typedefString += "// @class ";
936 typedefString += ForwardDecl->getNameAsString();
937 typedefString += ";\n";
938 }
939 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
940 }
941 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
942}
943
944void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
945 // When method is a synthesized one, such as a getter/setter there is
946 // nothing to rewrite.
947 if (Method->isImplicit())
948 return;
949 SourceLocation LocStart = Method->getLocStart();
950 SourceLocation LocEnd = Method->getLocEnd();
951
952 if (SM->getExpansionLineNumber(LocEnd) >
953 SM->getExpansionLineNumber(LocStart)) {
954 InsertText(LocStart, "#if 0\n");
955 ReplaceText(LocEnd, 1, ";\n#endif\n");
956 } else {
957 InsertText(LocStart, "// ");
958 }
959}
960
961void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {
962 SourceLocation Loc = prop->getAtLoc();
963
964 ReplaceText(Loc, 0, "// ");
965 // FIXME: handle properties that are declared across multiple lines.
966}
967
968void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
969 SourceLocation LocStart = CatDecl->getLocStart();
970
971 // FIXME: handle category headers that are declared across multiple lines.
972 ReplaceText(LocStart, 0, "// ");
Fariborz Jahanianaf300292012-02-20 20:09:20 +0000973 if (CatDecl->getIvarLBraceLoc().isValid())
974 InsertText(CatDecl->getIvarLBraceLoc(), "// ");
Fariborz Jahaniand2aea122012-02-19 19:00:05 +0000975 for (ObjCCategoryDecl::ivar_iterator
976 I = CatDecl->ivar_begin(), E = CatDecl->ivar_end(); I != E; ++I) {
977 ObjCIvarDecl *Ivar = (*I);
978 SourceLocation LocStart = Ivar->getLocStart();
979 ReplaceText(LocStart, 0, "// ");
980 }
Fariborz Jahanianaf300292012-02-20 20:09:20 +0000981 if (CatDecl->getIvarRBraceLoc().isValid())
982 InsertText(CatDecl->getIvarRBraceLoc(), "// ");
983
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +0000984 for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(),
985 E = CatDecl->prop_end(); I != E; ++I)
986 RewriteProperty(*I);
987
988 for (ObjCCategoryDecl::instmeth_iterator
989 I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end();
990 I != E; ++I)
991 RewriteMethodDeclaration(*I);
992 for (ObjCCategoryDecl::classmeth_iterator
993 I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end();
994 I != E; ++I)
995 RewriteMethodDeclaration(*I);
996
997 // Lastly, comment out the @end.
998 ReplaceText(CatDecl->getAtEndRange().getBegin(),
999 strlen("@end"), "/* @end */");
1000}
1001
1002void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
1003 SourceLocation LocStart = PDecl->getLocStart();
1004 assert(PDecl->isThisDeclarationADefinition());
1005
1006 // FIXME: handle protocol headers that are declared across multiple lines.
1007 ReplaceText(LocStart, 0, "// ");
1008
1009 for (ObjCProtocolDecl::instmeth_iterator
1010 I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
1011 I != E; ++I)
1012 RewriteMethodDeclaration(*I);
1013 for (ObjCProtocolDecl::classmeth_iterator
1014 I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
1015 I != E; ++I)
1016 RewriteMethodDeclaration(*I);
1017
1018 for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(),
1019 E = PDecl->prop_end(); I != E; ++I)
1020 RewriteProperty(*I);
1021
1022 // Lastly, comment out the @end.
1023 SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
1024 ReplaceText(LocEnd, strlen("@end"), "/* @end */");
1025
1026 // Must comment out @optional/@required
1027 const char *startBuf = SM->getCharacterData(LocStart);
1028 const char *endBuf = SM->getCharacterData(LocEnd);
1029 for (const char *p = startBuf; p < endBuf; p++) {
1030 if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
1031 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1032 ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
1033
1034 }
1035 else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
1036 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1037 ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
1038
1039 }
1040 }
1041}
1042
1043void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
1044 SourceLocation LocStart = (*D.begin())->getLocStart();
1045 if (LocStart.isInvalid())
1046 llvm_unreachable("Invalid SourceLocation");
1047 // FIXME: handle forward protocol that are declared across multiple lines.
1048 ReplaceText(LocStart, 0, "// ");
1049}
1050
1051void
1052RewriteModernObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) {
1053 SourceLocation LocStart = DG[0]->getLocStart();
1054 if (LocStart.isInvalid())
1055 llvm_unreachable("Invalid SourceLocation");
1056 // FIXME: handle forward protocol that are declared across multiple lines.
1057 ReplaceText(LocStart, 0, "// ");
1058}
1059
1060void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
1061 const FunctionType *&FPRetType) {
1062 if (T->isObjCQualifiedIdType())
1063 ResultStr += "id";
1064 else if (T->isFunctionPointerType() ||
1065 T->isBlockPointerType()) {
1066 // needs special handling, since pointer-to-functions have special
1067 // syntax (where a decaration models use).
1068 QualType retType = T;
1069 QualType PointeeTy;
1070 if (const PointerType* PT = retType->getAs<PointerType>())
1071 PointeeTy = PT->getPointeeType();
1072 else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
1073 PointeeTy = BPT->getPointeeType();
1074 if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
1075 ResultStr += FPRetType->getResultType().getAsString(
1076 Context->getPrintingPolicy());
1077 ResultStr += "(*";
1078 }
1079 } else
1080 ResultStr += T.getAsString(Context->getPrintingPolicy());
1081}
1082
1083void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
1084 ObjCMethodDecl *OMD,
1085 std::string &ResultStr) {
1086 //fprintf(stderr,"In RewriteObjCMethodDecl\n");
1087 const FunctionType *FPRetType = 0;
1088 ResultStr += "\nstatic ";
1089 RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType);
1090 ResultStr += " ";
1091
1092 // Unique method name
1093 std::string NameStr;
1094
1095 if (OMD->isInstanceMethod())
1096 NameStr += "_I_";
1097 else
1098 NameStr += "_C_";
1099
1100 NameStr += IDecl->getNameAsString();
1101 NameStr += "_";
1102
1103 if (ObjCCategoryImplDecl *CID =
1104 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
1105 NameStr += CID->getNameAsString();
1106 NameStr += "_";
1107 }
1108 // Append selector names, replacing ':' with '_'
1109 {
1110 std::string selString = OMD->getSelector().getAsString();
1111 int len = selString.size();
1112 for (int i = 0; i < len; i++)
1113 if (selString[i] == ':')
1114 selString[i] = '_';
1115 NameStr += selString;
1116 }
1117 // Remember this name for metadata emission
1118 MethodInternalNames[OMD] = NameStr;
1119 ResultStr += NameStr;
1120
1121 // Rewrite arguments
1122 ResultStr += "(";
1123
1124 // invisible arguments
1125 if (OMD->isInstanceMethod()) {
1126 QualType selfTy = Context->getObjCInterfaceType(IDecl);
1127 selfTy = Context->getPointerType(selfTy);
1128 if (!LangOpts.MicrosoftExt) {
1129 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
1130 ResultStr += "struct ";
1131 }
1132 // When rewriting for Microsoft, explicitly omit the structure name.
1133 ResultStr += IDecl->getNameAsString();
1134 ResultStr += " *";
1135 }
1136 else
1137 ResultStr += Context->getObjCClassType().getAsString(
1138 Context->getPrintingPolicy());
1139
1140 ResultStr += " self, ";
1141 ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
1142 ResultStr += " _cmd";
1143
1144 // Method arguments.
1145 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
1146 E = OMD->param_end(); PI != E; ++PI) {
1147 ParmVarDecl *PDecl = *PI;
1148 ResultStr += ", ";
1149 if (PDecl->getType()->isObjCQualifiedIdType()) {
1150 ResultStr += "id ";
1151 ResultStr += PDecl->getNameAsString();
1152 } else {
1153 std::string Name = PDecl->getNameAsString();
1154 QualType QT = PDecl->getType();
1155 // Make sure we convert "t (^)(...)" to "t (*)(...)".
Fariborz Jahanian2610f902012-03-27 16:42:20 +00001156 (void)convertBlockPointerToFunctionPointer(QT);
1157 QT.getAsStringInternal(Name, Context->getPrintingPolicy());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001158 ResultStr += Name;
1159 }
1160 }
1161 if (OMD->isVariadic())
1162 ResultStr += ", ...";
1163 ResultStr += ") ";
1164
1165 if (FPRetType) {
1166 ResultStr += ")"; // close the precedence "scope" for "*".
1167
1168 // Now, emit the argument types (if any).
1169 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
1170 ResultStr += "(";
1171 for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
1172 if (i) ResultStr += ", ";
1173 std::string ParamStr = FT->getArgType(i).getAsString(
1174 Context->getPrintingPolicy());
1175 ResultStr += ParamStr;
1176 }
1177 if (FT->isVariadic()) {
1178 if (FT->getNumArgs()) ResultStr += ", ";
1179 ResultStr += "...";
1180 }
1181 ResultStr += ")";
1182 } else {
1183 ResultStr += "()";
1184 }
1185 }
1186}
1187void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
1188 ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
1189 ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
1190
Fariborz Jahaniand2aea122012-02-19 19:00:05 +00001191 if (IMD) {
1192 InsertText(IMD->getLocStart(), "// ");
Fariborz Jahanianaf300292012-02-20 20:09:20 +00001193 if (IMD->getIvarLBraceLoc().isValid())
1194 InsertText(IMD->getIvarLBraceLoc(), "// ");
1195 for (ObjCImplementationDecl::ivar_iterator
1196 I = IMD->ivar_begin(), E = IMD->ivar_end(); I != E; ++I) {
1197 ObjCIvarDecl *Ivar = (*I);
1198 SourceLocation LocStart = Ivar->getLocStart();
1199 ReplaceText(LocStart, 0, "// ");
Fariborz Jahaniand2aea122012-02-19 19:00:05 +00001200 }
Fariborz Jahanianaf300292012-02-20 20:09:20 +00001201 if (IMD->getIvarRBraceLoc().isValid())
1202 InsertText(IMD->getIvarRBraceLoc(), "// ");
Fariborz Jahaniand2aea122012-02-19 19:00:05 +00001203 }
1204 else
1205 InsertText(CID->getLocStart(), "// ");
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001206
1207 for (ObjCCategoryImplDecl::instmeth_iterator
1208 I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(),
1209 E = IMD ? IMD->instmeth_end() : CID->instmeth_end();
1210 I != E; ++I) {
1211 std::string ResultStr;
1212 ObjCMethodDecl *OMD = *I;
1213 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
1214 SourceLocation LocStart = OMD->getLocStart();
1215 SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
1216
1217 const char *startBuf = SM->getCharacterData(LocStart);
1218 const char *endBuf = SM->getCharacterData(LocEnd);
1219 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1220 }
1221
1222 for (ObjCCategoryImplDecl::classmeth_iterator
1223 I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(),
1224 E = IMD ? IMD->classmeth_end() : CID->classmeth_end();
1225 I != E; ++I) {
1226 std::string ResultStr;
1227 ObjCMethodDecl *OMD = *I;
1228 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
1229 SourceLocation LocStart = OMD->getLocStart();
1230 SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
1231
1232 const char *startBuf = SM->getCharacterData(LocStart);
1233 const char *endBuf = SM->getCharacterData(LocEnd);
1234 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1235 }
1236 for (ObjCCategoryImplDecl::propimpl_iterator
1237 I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(),
1238 E = IMD ? IMD->propimpl_end() : CID->propimpl_end();
1239 I != E; ++I) {
1240 RewritePropertyImplDecl(*I, IMD, CID);
1241 }
1242
1243 InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// ");
1244}
1245
1246void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
Fariborz Jahanian8f1fed02012-02-11 20:10:52 +00001247 // Do not synthesize more than once.
1248 if (ObjCSynthesizedStructs.count(ClassDecl))
1249 return;
1250 // Make sure super class's are written before current class is written.
1251 ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass();
1252 while (SuperClass) {
1253 RewriteInterfaceDecl(SuperClass);
1254 SuperClass = SuperClass->getSuperClass();
1255 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001256 std::string ResultStr;
Fariborz Jahaniancf4c60f2012-02-17 22:20:12 +00001257 if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001258 // we haven't seen a forward decl - generate a typedef.
Fariborz Jahanianc38503b2012-03-12 23:58:28 +00001259 RewriteOneForwardClassDecl(ClassDecl, ResultStr);
Fariborz Jahanian72c88f12012-02-22 18:13:25 +00001260 RewriteIvarOffsetSymbols(ClassDecl, ResultStr);
1261
Fariborz Jahanian4339bb32012-02-15 22:01:47 +00001262 RewriteObjCInternalStruct(ClassDecl, ResultStr);
Fariborz Jahaniancf4c60f2012-02-17 22:20:12 +00001263 // Mark this typedef as having been written into its c++ equivalent.
1264 ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());
Fariborz Jahanian4339bb32012-02-15 22:01:47 +00001265
1266 for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(),
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001267 E = ClassDecl->prop_end(); I != E; ++I)
Fariborz Jahanian4339bb32012-02-15 22:01:47 +00001268 RewriteProperty(*I);
1269 for (ObjCInterfaceDecl::instmeth_iterator
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001270 I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end();
Fariborz Jahanian4339bb32012-02-15 22:01:47 +00001271 I != E; ++I)
1272 RewriteMethodDeclaration(*I);
1273 for (ObjCInterfaceDecl::classmeth_iterator
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001274 I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end();
Fariborz Jahanian4339bb32012-02-15 22:01:47 +00001275 I != E; ++I)
1276 RewriteMethodDeclaration(*I);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001277
Fariborz Jahanian4339bb32012-02-15 22:01:47 +00001278 // Lastly, comment out the @end.
1279 ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
1280 "/* @end */");
1281 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001282}
1283
1284Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {
1285 SourceRange OldRange = PseudoOp->getSourceRange();
1286
1287 // We just magically know some things about the structure of this
1288 // expression.
1289 ObjCMessageExpr *OldMsg =
1290 cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
1291 PseudoOp->getNumSemanticExprs() - 1));
1292
1293 // Because the rewriter doesn't allow us to rewrite rewritten code,
1294 // we need to suppress rewriting the sub-statements.
1295 Expr *Base, *RHS;
1296 {
1297 DisableReplaceStmtScope S(*this);
1298
1299 // Rebuild the base expression if we have one.
1300 Base = 0;
1301 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
1302 Base = OldMsg->getInstanceReceiver();
1303 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1304 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1305 }
1306
1307 // Rebuild the RHS.
1308 RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();
1309 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1310 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1311 }
1312
1313 // TODO: avoid this copy.
1314 SmallVector<SourceLocation, 1> SelLocs;
1315 OldMsg->getSelectorLocs(SelLocs);
1316
1317 ObjCMessageExpr *NewMsg = 0;
1318 switch (OldMsg->getReceiverKind()) {
1319 case ObjCMessageExpr::Class:
1320 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1321 OldMsg->getValueKind(),
1322 OldMsg->getLeftLoc(),
1323 OldMsg->getClassReceiverTypeInfo(),
1324 OldMsg->getSelector(),
1325 SelLocs,
1326 OldMsg->getMethodDecl(),
1327 RHS,
1328 OldMsg->getRightLoc(),
1329 OldMsg->isImplicit());
1330 break;
1331
1332 case ObjCMessageExpr::Instance:
1333 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1334 OldMsg->getValueKind(),
1335 OldMsg->getLeftLoc(),
1336 Base,
1337 OldMsg->getSelector(),
1338 SelLocs,
1339 OldMsg->getMethodDecl(),
1340 RHS,
1341 OldMsg->getRightLoc(),
1342 OldMsg->isImplicit());
1343 break;
1344
1345 case ObjCMessageExpr::SuperClass:
1346 case ObjCMessageExpr::SuperInstance:
1347 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1348 OldMsg->getValueKind(),
1349 OldMsg->getLeftLoc(),
1350 OldMsg->getSuperLoc(),
1351 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
1352 OldMsg->getSuperType(),
1353 OldMsg->getSelector(),
1354 SelLocs,
1355 OldMsg->getMethodDecl(),
1356 RHS,
1357 OldMsg->getRightLoc(),
1358 OldMsg->isImplicit());
1359 break;
1360 }
1361
1362 Stmt *Replacement = SynthMessageExpr(NewMsg);
1363 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1364 return Replacement;
1365}
1366
1367Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
1368 SourceRange OldRange = PseudoOp->getSourceRange();
1369
1370 // We just magically know some things about the structure of this
1371 // expression.
1372 ObjCMessageExpr *OldMsg =
1373 cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
1374
1375 // Because the rewriter doesn't allow us to rewrite rewritten code,
1376 // we need to suppress rewriting the sub-statements.
1377 Expr *Base = 0;
1378 {
1379 DisableReplaceStmtScope S(*this);
1380
1381 // Rebuild the base expression if we have one.
1382 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
1383 Base = OldMsg->getInstanceReceiver();
1384 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1385 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1386 }
1387 }
1388
1389 // Intentionally empty.
1390 SmallVector<SourceLocation, 1> SelLocs;
1391 SmallVector<Expr*, 1> Args;
1392
1393 ObjCMessageExpr *NewMsg = 0;
1394 switch (OldMsg->getReceiverKind()) {
1395 case ObjCMessageExpr::Class:
1396 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1397 OldMsg->getValueKind(),
1398 OldMsg->getLeftLoc(),
1399 OldMsg->getClassReceiverTypeInfo(),
1400 OldMsg->getSelector(),
1401 SelLocs,
1402 OldMsg->getMethodDecl(),
1403 Args,
1404 OldMsg->getRightLoc(),
1405 OldMsg->isImplicit());
1406 break;
1407
1408 case ObjCMessageExpr::Instance:
1409 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1410 OldMsg->getValueKind(),
1411 OldMsg->getLeftLoc(),
1412 Base,
1413 OldMsg->getSelector(),
1414 SelLocs,
1415 OldMsg->getMethodDecl(),
1416 Args,
1417 OldMsg->getRightLoc(),
1418 OldMsg->isImplicit());
1419 break;
1420
1421 case ObjCMessageExpr::SuperClass:
1422 case ObjCMessageExpr::SuperInstance:
1423 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1424 OldMsg->getValueKind(),
1425 OldMsg->getLeftLoc(),
1426 OldMsg->getSuperLoc(),
1427 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
1428 OldMsg->getSuperType(),
1429 OldMsg->getSelector(),
1430 SelLocs,
1431 OldMsg->getMethodDecl(),
1432 Args,
1433 OldMsg->getRightLoc(),
1434 OldMsg->isImplicit());
1435 break;
1436 }
1437
1438 Stmt *Replacement = SynthMessageExpr(NewMsg);
1439 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1440 return Replacement;
1441}
1442
1443/// SynthCountByEnumWithState - To print:
1444/// ((unsigned int (*)
1445/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1446/// (void *)objc_msgSend)((id)l_collection,
1447/// sel_registerName(
1448/// "countByEnumeratingWithState:objects:count:"),
1449/// &enumState,
1450/// (id *)__rw_items, (unsigned int)16)
1451///
1452void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) {
1453 buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
1454 "id *, unsigned int))(void *)objc_msgSend)";
1455 buf += "\n\t\t";
1456 buf += "((id)l_collection,\n\t\t";
1457 buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1458 buf += "\n\t\t";
1459 buf += "&enumState, "
1460 "(id *)__rw_items, (unsigned int)16)";
1461}
1462
1463/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
1464/// statement to exit to its outer synthesized loop.
1465///
1466Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {
1467 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1468 return S;
1469 // replace break with goto __break_label
1470 std::string buf;
1471
1472 SourceLocation startLoc = S->getLocStart();
1473 buf = "goto __break_label_";
1474 buf += utostr(ObjCBcLabelNo.back());
1475 ReplaceText(startLoc, strlen("break"), buf);
1476
1477 return 0;
1478}
1479
1480/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
1481/// statement to continue with its inner synthesized loop.
1482///
1483Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {
1484 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1485 return S;
1486 // replace continue with goto __continue_label
1487 std::string buf;
1488
1489 SourceLocation startLoc = S->getLocStart();
1490 buf = "goto __continue_label_";
1491 buf += utostr(ObjCBcLabelNo.back());
1492 ReplaceText(startLoc, strlen("continue"), buf);
1493
1494 return 0;
1495}
1496
1497/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
1498/// It rewrites:
1499/// for ( type elem in collection) { stmts; }
1500
1501/// Into:
1502/// {
1503/// type elem;
1504/// struct __objcFastEnumerationState enumState = { 0 };
1505/// id __rw_items[16];
1506/// id l_collection = (id)collection;
1507/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1508/// objects:__rw_items count:16];
1509/// if (limit) {
1510/// unsigned long startMutations = *enumState.mutationsPtr;
1511/// do {
1512/// unsigned long counter = 0;
1513/// do {
1514/// if (startMutations != *enumState.mutationsPtr)
1515/// objc_enumerationMutation(l_collection);
1516/// elem = (type)enumState.itemsPtr[counter++];
1517/// stmts;
1518/// __continue_label: ;
1519/// } while (counter < limit);
1520/// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1521/// objects:__rw_items count:16]);
1522/// elem = nil;
1523/// __break_label: ;
1524/// }
1525/// else
1526/// elem = nil;
1527/// }
1528///
1529Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
1530 SourceLocation OrigEnd) {
1531 assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
1532 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1533 "ObjCForCollectionStmt Statement stack mismatch");
1534 assert(!ObjCBcLabelNo.empty() &&
1535 "ObjCForCollectionStmt - Label No stack empty");
1536
1537 SourceLocation startLoc = S->getLocStart();
1538 const char *startBuf = SM->getCharacterData(startLoc);
1539 StringRef elementName;
1540 std::string elementTypeAsString;
1541 std::string buf;
1542 buf = "\n{\n\t";
1543 if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
1544 // type elem;
1545 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1546 QualType ElementType = cast<ValueDecl>(D)->getType();
1547 if (ElementType->isObjCQualifiedIdType() ||
1548 ElementType->isObjCQualifiedInterfaceType())
1549 // Simply use 'id' for all qualified types.
1550 elementTypeAsString = "id";
1551 else
1552 elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());
1553 buf += elementTypeAsString;
1554 buf += " ";
1555 elementName = D->getName();
1556 buf += elementName;
1557 buf += ";\n\t";
1558 }
1559 else {
1560 DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
1561 elementName = DR->getDecl()->getName();
1562 ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
1563 if (VD->getType()->isObjCQualifiedIdType() ||
1564 VD->getType()->isObjCQualifiedInterfaceType())
1565 // Simply use 'id' for all qualified types.
1566 elementTypeAsString = "id";
1567 else
1568 elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());
1569 }
1570
1571 // struct __objcFastEnumerationState enumState = { 0 };
1572 buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
1573 // id __rw_items[16];
1574 buf += "id __rw_items[16];\n\t";
1575 // id l_collection = (id)
1576 buf += "id l_collection = (id)";
1577 // Find start location of 'collection' the hard way!
1578 const char *startCollectionBuf = startBuf;
1579 startCollectionBuf += 3; // skip 'for'
1580 startCollectionBuf = strchr(startCollectionBuf, '(');
1581 startCollectionBuf++; // skip '('
1582 // find 'in' and skip it.
1583 while (*startCollectionBuf != ' ' ||
1584 *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
1585 (*(startCollectionBuf+3) != ' ' &&
1586 *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
1587 startCollectionBuf++;
1588 startCollectionBuf += 3;
1589
1590 // Replace: "for (type element in" with string constructed thus far.
1591 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1592 // Replace ')' in for '(' type elem in collection ')' with ';'
1593 SourceLocation rightParenLoc = S->getRParenLoc();
1594 const char *rparenBuf = SM->getCharacterData(rightParenLoc);
1595 SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
1596 buf = ";\n\t";
1597
1598 // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1599 // objects:__rw_items count:16];
1600 // which is synthesized into:
1601 // unsigned int limit =
1602 // ((unsigned int (*)
1603 // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1604 // (void *)objc_msgSend)((id)l_collection,
1605 // sel_registerName(
1606 // "countByEnumeratingWithState:objects:count:"),
1607 // (struct __objcFastEnumerationState *)&state,
1608 // (id *)__rw_items, (unsigned int)16);
1609 buf += "unsigned long limit =\n\t\t";
1610 SynthCountByEnumWithState(buf);
1611 buf += ";\n\t";
1612 /// if (limit) {
1613 /// unsigned long startMutations = *enumState.mutationsPtr;
1614 /// do {
1615 /// unsigned long counter = 0;
1616 /// do {
1617 /// if (startMutations != *enumState.mutationsPtr)
1618 /// objc_enumerationMutation(l_collection);
1619 /// elem = (type)enumState.itemsPtr[counter++];
1620 buf += "if (limit) {\n\t";
1621 buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1622 buf += "do {\n\t\t";
1623 buf += "unsigned long counter = 0;\n\t\t";
1624 buf += "do {\n\t\t\t";
1625 buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1626 buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
1627 buf += elementName;
1628 buf += " = (";
1629 buf += elementTypeAsString;
1630 buf += ")enumState.itemsPtr[counter++];";
1631 // Replace ')' in for '(' type elem in collection ')' with all of these.
1632 ReplaceText(lparenLoc, 1, buf);
1633
1634 /// __continue_label: ;
1635 /// } while (counter < limit);
1636 /// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1637 /// objects:__rw_items count:16]);
1638 /// elem = nil;
1639 /// __break_label: ;
1640 /// }
1641 /// else
1642 /// elem = nil;
1643 /// }
1644 ///
1645 buf = ";\n\t";
1646 buf += "__continue_label_";
1647 buf += utostr(ObjCBcLabelNo.back());
1648 buf += ": ;";
1649 buf += "\n\t\t";
1650 buf += "} while (counter < limit);\n\t";
1651 buf += "} while (limit = ";
1652 SynthCountByEnumWithState(buf);
1653 buf += ");\n\t";
1654 buf += elementName;
1655 buf += " = ((";
1656 buf += elementTypeAsString;
1657 buf += ")0);\n\t";
1658 buf += "__break_label_";
1659 buf += utostr(ObjCBcLabelNo.back());
1660 buf += ": ;\n\t";
1661 buf += "}\n\t";
1662 buf += "else\n\t\t";
1663 buf += elementName;
1664 buf += " = ((";
1665 buf += elementTypeAsString;
1666 buf += ")0);\n\t";
1667 buf += "}\n";
1668
1669 // Insert all these *after* the statement body.
1670 // FIXME: If this should support Obj-C++, support CXXTryStmt
1671 if (isa<CompoundStmt>(S->getBody())) {
1672 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
1673 InsertText(endBodyLoc, buf);
1674 } else {
1675 /* Need to treat single statements specially. For example:
1676 *
1677 * for (A *a in b) if (stuff()) break;
1678 * for (A *a in b) xxxyy;
1679 *
1680 * The following code simply scans ahead to the semi to find the actual end.
1681 */
1682 const char *stmtBuf = SM->getCharacterData(OrigEnd);
1683 const char *semiBuf = strchr(stmtBuf, ';');
1684 assert(semiBuf && "Can't find ';'");
1685 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
1686 InsertText(endBodyLoc, buf);
1687 }
1688 Stmts.pop_back();
1689 ObjCBcLabelNo.pop_back();
1690 return 0;
1691}
1692
Fariborz Jahanian542125f2012-03-16 21:33:16 +00001693static void Write_RethrowObject(std::string &buf) {
1694 buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";
1695 buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";
1696 buf += "\tid rethrow;\n";
1697 buf += "\t} _fin_force_rethow(_rethrow);";
1698}
1699
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001700/// RewriteObjCSynchronizedStmt -
1701/// This routine rewrites @synchronized(expr) stmt;
1702/// into:
1703/// objc_sync_enter(expr);
1704/// @try stmt @finally { objc_sync_exit(expr); }
1705///
1706Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
1707 // Get the start location and compute the semi location.
1708 SourceLocation startLoc = S->getLocStart();
1709 const char *startBuf = SM->getCharacterData(startLoc);
1710
1711 assert((*startBuf == '@') && "bogus @synchronized location");
1712
1713 std::string buf;
Fariborz Jahanian22e2f852012-03-17 17:46:02 +00001714 buf = "{ id _rethrow = 0; id _sync_obj = ";
Fariborz Jahanian542125f2012-03-16 21:33:16 +00001715
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001716 const char *lparenBuf = startBuf;
1717 while (*lparenBuf != '(') lparenBuf++;
1718 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
Fariborz Jahanian22e2f852012-03-17 17:46:02 +00001719
1720 buf = "; objc_sync_enter(_sync_obj);\n";
1721 buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";
1722 buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";
1723 buf += "\n\tid sync_exit;";
1724 buf += "\n\t} _sync_exit(_sync_obj);\n";
1725
1726 // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
1727 // the sync expression is typically a message expression that's already
1728 // been rewritten! (which implies the SourceLocation's are invalid).
1729 SourceLocation RParenExprLoc = S->getSynchBody()->getLocStart();
1730 const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);
1731 while (*RParenExprLocBuf != ')') RParenExprLocBuf--;
1732 RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);
1733
1734 SourceLocation LBranceLoc = S->getSynchBody()->getLocStart();
1735 const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);
1736 assert (*LBraceLocBuf == '{');
1737 ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);
Fariborz Jahanian542125f2012-03-16 21:33:16 +00001738
Fariborz Jahanianb655bf02012-03-16 21:43:45 +00001739 SourceLocation startRBraceLoc = S->getSynchBody()->getLocEnd();
Matt Beaumont-Gay9ab511c2012-03-16 22:20:39 +00001740 assert((*SM->getCharacterData(startRBraceLoc) == '}') &&
1741 "bogus @synchronized block");
Fariborz Jahanian542125f2012-03-16 21:33:16 +00001742
1743 buf = "} catch (id e) {_rethrow = e;}\n";
1744 Write_RethrowObject(buf);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001745 buf += "}\n";
Fariborz Jahanian542125f2012-03-16 21:33:16 +00001746 buf += "}\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001747
Fariborz Jahanianb655bf02012-03-16 21:43:45 +00001748 ReplaceText(startRBraceLoc, 1, buf);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001749
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001750 return 0;
1751}
1752
1753void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
1754{
1755 // Perform a bottom up traversal of all children.
1756 for (Stmt::child_range CI = S->children(); CI; ++CI)
1757 if (*CI)
1758 WarnAboutReturnGotoStmts(*CI);
1759
1760 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1761 Diags.Report(Context->getFullLoc(S->getLocStart()),
1762 TryFinallyContainsReturnDiag);
1763 }
1764 return;
1765}
1766
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001767Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
Fariborz Jahanianb1228182012-03-15 22:42:15 +00001768 ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();
Fariborz Jahanian220419a2012-03-15 23:50:33 +00001769 bool noCatch = S->getNumCatchStmts() == 0;
Fariborz Jahanianb1228182012-03-15 22:42:15 +00001770 std::string buf;
1771
1772 if (finalStmt) {
Fariborz Jahanian220419a2012-03-15 23:50:33 +00001773 if (noCatch)
1774 buf = "{ id volatile _rethrow = 0;\n";
1775 else {
1776 buf = "{ id volatile _rethrow = 0;\ntry {\n";
1777 }
Fariborz Jahanianb1228182012-03-15 22:42:15 +00001778 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001779 // Get the start location and compute the semi location.
1780 SourceLocation startLoc = S->getLocStart();
1781 const char *startBuf = SM->getCharacterData(startLoc);
1782
1783 assert((*startBuf == '@') && "bogus @try location");
Fariborz Jahanianb1228182012-03-15 22:42:15 +00001784 if (finalStmt)
1785 ReplaceText(startLoc, 1, buf);
1786 else
1787 // @try -> try
1788 ReplaceText(startLoc, 1, "");
1789
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001790 for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
1791 ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
Fariborz Jahanian4c148812012-03-15 20:11:10 +00001792 VarDecl *catchDecl = Catch->getCatchParamDecl();
Fariborz Jahanianc38503b2012-03-12 23:58:28 +00001793
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001794 startLoc = Catch->getLocStart();
Fariborz Jahanian4c148812012-03-15 20:11:10 +00001795 bool AtRemoved = false;
1796 if (catchDecl) {
1797 QualType t = catchDecl->getType();
1798 if (const ObjCObjectPointerType *Ptr = t->getAs<ObjCObjectPointerType>()) {
1799 // Should be a pointer to a class.
1800 ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
1801 if (IDecl) {
1802 std::string Result;
1803 startBuf = SM->getCharacterData(startLoc);
1804 assert((*startBuf == '@') && "bogus @catch location");
1805 SourceLocation rParenLoc = Catch->getRParenLoc();
1806 const char *rParenBuf = SM->getCharacterData(rParenLoc);
1807
1808 // _objc_exc_Foo *_e as argument to catch.
1809 Result = "catch (_objc_exc_"; Result += IDecl->getNameAsString();
1810 Result += " *_"; Result += catchDecl->getNameAsString();
1811 Result += ")";
1812 ReplaceText(startLoc, rParenBuf-startBuf+1, Result);
1813 // Foo *e = (Foo *)_e;
1814 Result.clear();
1815 Result = "{ ";
1816 Result += IDecl->getNameAsString();
1817 Result += " *"; Result += catchDecl->getNameAsString();
1818 Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";
1819 Result += "_"; Result += catchDecl->getNameAsString();
1820
1821 Result += "; ";
1822 SourceLocation lBraceLoc = Catch->getCatchBody()->getLocStart();
1823 ReplaceText(lBraceLoc, 1, Result);
1824 AtRemoved = true;
1825 }
1826 }
1827 }
1828 if (!AtRemoved)
1829 // @catch -> catch
1830 ReplaceText(startLoc, 1, "");
Fariborz Jahanianc38503b2012-03-12 23:58:28 +00001831
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001832 }
Fariborz Jahanian220419a2012-03-15 23:50:33 +00001833 if (finalStmt) {
1834 buf.clear();
1835 if (noCatch)
1836 buf = "catch (id e) {_rethrow = e;}\n";
1837 else
1838 buf = "}\ncatch (id e) {_rethrow = e;}\n";
1839
1840 SourceLocation startFinalLoc = finalStmt->getLocStart();
1841 ReplaceText(startFinalLoc, 8, buf);
1842 Stmt *body = finalStmt->getFinallyBody();
1843 SourceLocation startFinalBodyLoc = body->getLocStart();
1844 buf.clear();
Fariborz Jahanian542125f2012-03-16 21:33:16 +00001845 Write_RethrowObject(buf);
Fariborz Jahanian220419a2012-03-15 23:50:33 +00001846 ReplaceText(startFinalBodyLoc, 1, buf);
1847
1848 SourceLocation endFinalBodyLoc = body->getLocEnd();
1849 ReplaceText(endFinalBodyLoc, 1, "}\n}");
Fariborz Jahanian22e2f852012-03-17 17:46:02 +00001850 // Now check for any return/continue/go statements within the @try.
1851 WarnAboutReturnGotoStmts(S->getTryBody());
Fariborz Jahanian220419a2012-03-15 23:50:33 +00001852 }
1853
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001854 return 0;
1855}
1856
1857// This can't be done with ReplaceStmt(S, ThrowExpr), since
1858// the throw expression is typically a message expression that's already
1859// been rewritten! (which implies the SourceLocation's are invalid).
1860Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
1861 // Get the start location and compute the semi location.
1862 SourceLocation startLoc = S->getLocStart();
1863 const char *startBuf = SM->getCharacterData(startLoc);
1864
1865 assert((*startBuf == '@') && "bogus @throw location");
1866
1867 std::string buf;
1868 /* void objc_exception_throw(id) __attribute__((noreturn)); */
1869 if (S->getThrowExpr())
1870 buf = "objc_exception_throw(";
Fariborz Jahanian40539462012-03-16 16:52:06 +00001871 else
1872 buf = "throw";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001873
1874 // handle "@ throw" correctly.
1875 const char *wBuf = strchr(startBuf, 'w');
1876 assert((*wBuf == 'w') && "@throw: can't find 'w'");
1877 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1878
1879 const char *semiBuf = strchr(startBuf, ';');
1880 assert((*semiBuf == ';') && "@throw: can't find ';'");
1881 SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
Fariborz Jahanian40539462012-03-16 16:52:06 +00001882 if (S->getThrowExpr())
1883 ReplaceText(semiLoc, 1, ");");
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001884 return 0;
1885}
1886
1887Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
1888 // Create a new string expression.
1889 QualType StrType = Context->getPointerType(Context->CharTy);
1890 std::string StrEncoding;
1891 Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
1892 Expr *Replacement = StringLiteral::Create(*Context, StrEncoding,
1893 StringLiteral::Ascii, false,
1894 StrType, SourceLocation());
1895 ReplaceStmt(Exp, Replacement);
1896
1897 // Replace this subexpr in the parent.
1898 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
1899 return Replacement;
1900}
1901
1902Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
1903 if (!SelGetUidFunctionDecl)
1904 SynthSelGetUidFunctionDecl();
1905 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
1906 // Create a call to sel_registerName("selName").
1907 SmallVector<Expr*, 8> SelExprs;
1908 QualType argType = Context->getPointerType(Context->CharTy);
1909 SelExprs.push_back(StringLiteral::Create(*Context,
1910 Exp->getSelector().getAsString(),
1911 StringLiteral::Ascii, false,
1912 argType, SourceLocation()));
1913 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
1914 &SelExprs[0], SelExprs.size());
1915 ReplaceStmt(Exp, SelExp);
1916 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
1917 return SelExp;
1918}
1919
1920CallExpr *RewriteModernObjC::SynthesizeCallToFunctionDecl(
1921 FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc,
1922 SourceLocation EndLoc) {
1923 // Get the type, we will need to reference it in a couple spots.
1924 QualType msgSendType = FD->getType();
1925
1926 // Create a reference to the objc_msgSend() declaration.
1927 DeclRefExpr *DRE =
John McCallf4b88a42012-03-10 09:33:50 +00001928 new (Context) DeclRefExpr(FD, false, msgSendType, VK_LValue, SourceLocation());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00001929
1930 // Now, we cast the reference to a pointer to the objc_msgSend type.
1931 QualType pToFunc = Context->getPointerType(msgSendType);
1932 ImplicitCastExpr *ICE =
1933 ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
1934 DRE, 0, VK_RValue);
1935
1936 const FunctionType *FT = msgSendType->getAs<FunctionType>();
1937
1938 CallExpr *Exp =
1939 new (Context) CallExpr(*Context, ICE, args, nargs,
1940 FT->getCallResultType(*Context),
1941 VK_RValue, EndLoc);
1942 return Exp;
1943}
1944
1945static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
1946 const char *&startRef, const char *&endRef) {
1947 while (startBuf < endBuf) {
1948 if (*startBuf == '<')
1949 startRef = startBuf; // mark the start.
1950 if (*startBuf == '>') {
1951 if (startRef && *startRef == '<') {
1952 endRef = startBuf; // mark the end.
1953 return true;
1954 }
1955 return false;
1956 }
1957 startBuf++;
1958 }
1959 return false;
1960}
1961
1962static void scanToNextArgument(const char *&argRef) {
1963 int angle = 0;
1964 while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
1965 if (*argRef == '<')
1966 angle++;
1967 else if (*argRef == '>')
1968 angle--;
1969 argRef++;
1970 }
1971 assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
1972}
1973
1974bool RewriteModernObjC::needToScanForQualifiers(QualType T) {
1975 if (T->isObjCQualifiedIdType())
1976 return true;
1977 if (const PointerType *PT = T->getAs<PointerType>()) {
1978 if (PT->getPointeeType()->isObjCQualifiedIdType())
1979 return true;
1980 }
1981 if (T->isObjCObjectPointerType()) {
1982 T = T->getPointeeType();
1983 return T->isObjCQualifiedInterfaceType();
1984 }
1985 if (T->isArrayType()) {
1986 QualType ElemTy = Context->getBaseElementType(T);
1987 return needToScanForQualifiers(ElemTy);
1988 }
1989 return false;
1990}
1991
1992void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
1993 QualType Type = E->getType();
1994 if (needToScanForQualifiers(Type)) {
1995 SourceLocation Loc, EndLoc;
1996
1997 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
1998 Loc = ECE->getLParenLoc();
1999 EndLoc = ECE->getRParenLoc();
2000 } else {
2001 Loc = E->getLocStart();
2002 EndLoc = E->getLocEnd();
2003 }
2004 // This will defend against trying to rewrite synthesized expressions.
2005 if (Loc.isInvalid() || EndLoc.isInvalid())
2006 return;
2007
2008 const char *startBuf = SM->getCharacterData(Loc);
2009 const char *endBuf = SM->getCharacterData(EndLoc);
2010 const char *startRef = 0, *endRef = 0;
2011 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2012 // Get the locations of the startRef, endRef.
2013 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
2014 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
2015 // Comment out the protocol references.
2016 InsertText(LessLoc, "/*");
2017 InsertText(GreaterLoc, "*/");
2018 }
2019 }
2020}
2021
2022void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
2023 SourceLocation Loc;
2024 QualType Type;
2025 const FunctionProtoType *proto = 0;
2026 if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2027 Loc = VD->getLocation();
2028 Type = VD->getType();
2029 }
2030 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2031 Loc = FD->getLocation();
2032 // Check for ObjC 'id' and class types that have been adorned with protocol
2033 // information (id<p>, C<p>*). The protocol references need to be rewritten!
2034 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2035 assert(funcType && "missing function type");
2036 proto = dyn_cast<FunctionProtoType>(funcType);
2037 if (!proto)
2038 return;
2039 Type = proto->getResultType();
2040 }
2041 else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2042 Loc = FD->getLocation();
2043 Type = FD->getType();
2044 }
2045 else
2046 return;
2047
2048 if (needToScanForQualifiers(Type)) {
2049 // Since types are unique, we need to scan the buffer.
2050
2051 const char *endBuf = SM->getCharacterData(Loc);
2052 const char *startBuf = endBuf;
2053 while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
2054 startBuf--; // scan backward (from the decl location) for return type.
2055 const char *startRef = 0, *endRef = 0;
2056 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2057 // Get the locations of the startRef, endRef.
2058 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
2059 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
2060 // Comment out the protocol references.
2061 InsertText(LessLoc, "/*");
2062 InsertText(GreaterLoc, "*/");
2063 }
2064 }
2065 if (!proto)
2066 return; // most likely, was a variable
2067 // Now check arguments.
2068 const char *startBuf = SM->getCharacterData(Loc);
2069 const char *startFuncBuf = startBuf;
2070 for (unsigned i = 0; i < proto->getNumArgs(); i++) {
2071 if (needToScanForQualifiers(proto->getArgType(i))) {
2072 // Since types are unique, we need to scan the buffer.
2073
2074 const char *endBuf = startBuf;
2075 // scan forward (from the decl location) for argument types.
2076 scanToNextArgument(endBuf);
2077 const char *startRef = 0, *endRef = 0;
2078 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2079 // Get the locations of the startRef, endRef.
2080 SourceLocation LessLoc =
2081 Loc.getLocWithOffset(startRef-startFuncBuf);
2082 SourceLocation GreaterLoc =
2083 Loc.getLocWithOffset(endRef-startFuncBuf+1);
2084 // Comment out the protocol references.
2085 InsertText(LessLoc, "/*");
2086 InsertText(GreaterLoc, "*/");
2087 }
2088 startBuf = ++endBuf;
2089 }
2090 else {
2091 // If the function name is derived from a macro expansion, then the
2092 // argument buffer will not follow the name. Need to speak with Chris.
2093 while (*startBuf && *startBuf != ')' && *startBuf != ',')
2094 startBuf++; // scan forward (from the decl location) for argument types.
2095 startBuf++;
2096 }
2097 }
2098}
2099
2100void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {
2101 QualType QT = ND->getType();
2102 const Type* TypePtr = QT->getAs<Type>();
2103 if (!isa<TypeOfExprType>(TypePtr))
2104 return;
2105 while (isa<TypeOfExprType>(TypePtr)) {
2106 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2107 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
2108 TypePtr = QT->getAs<Type>();
2109 }
2110 // FIXME. This will not work for multiple declarators; as in:
2111 // __typeof__(a) b,c,d;
2112 std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));
2113 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
2114 const char *startBuf = SM->getCharacterData(DeclLoc);
2115 if (ND->getInit()) {
2116 std::string Name(ND->getNameAsString());
2117 TypeAsString += " " + Name + " = ";
2118 Expr *E = ND->getInit();
2119 SourceLocation startLoc;
2120 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
2121 startLoc = ECE->getLParenLoc();
2122 else
2123 startLoc = E->getLocStart();
2124 startLoc = SM->getExpansionLoc(startLoc);
2125 const char *endBuf = SM->getCharacterData(startLoc);
2126 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2127 }
2128 else {
2129 SourceLocation X = ND->getLocEnd();
2130 X = SM->getExpansionLoc(X);
2131 const char *endBuf = SM->getCharacterData(X);
2132 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2133 }
2134}
2135
2136// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
2137void RewriteModernObjC::SynthSelGetUidFunctionDecl() {
2138 IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
2139 SmallVector<QualType, 16> ArgTys;
2140 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2141 QualType getFuncType =
2142 getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size());
2143 SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2144 SourceLocation(),
2145 SourceLocation(),
2146 SelGetUidIdent, getFuncType, 0,
2147 SC_Extern,
2148 SC_None, false);
2149}
2150
2151void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {
2152 // declared in <objc/objc.h>
2153 if (FD->getIdentifier() &&
2154 FD->getName() == "sel_registerName") {
2155 SelGetUidFunctionDecl = FD;
2156 return;
2157 }
2158 RewriteObjCQualifiedInterfaceTypes(FD);
2159}
2160
2161void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
2162 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2163 const char *argPtr = TypeString.c_str();
2164 if (!strchr(argPtr, '^')) {
2165 Str += TypeString;
2166 return;
2167 }
2168 while (*argPtr) {
2169 Str += (*argPtr == '^' ? '*' : *argPtr);
2170 argPtr++;
2171 }
2172}
2173
2174// FIXME. Consolidate this routine with RewriteBlockPointerType.
2175void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2176 ValueDecl *VD) {
2177 QualType Type = VD->getType();
2178 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2179 const char *argPtr = TypeString.c_str();
2180 int paren = 0;
2181 while (*argPtr) {
2182 switch (*argPtr) {
2183 case '(':
2184 Str += *argPtr;
2185 paren++;
2186 break;
2187 case ')':
2188 Str += *argPtr;
2189 paren--;
2190 break;
2191 case '^':
2192 Str += '*';
2193 if (paren == 1)
2194 Str += VD->getNameAsString();
2195 break;
2196 default:
2197 Str += *argPtr;
2198 break;
2199 }
2200 argPtr++;
2201 }
2202}
2203
2204
2205void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
2206 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
2207 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2208 const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
2209 if (!proto)
2210 return;
2211 QualType Type = proto->getResultType();
2212 std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
2213 FdStr += " ";
2214 FdStr += FD->getName();
2215 FdStr += "(";
2216 unsigned numArgs = proto->getNumArgs();
2217 for (unsigned i = 0; i < numArgs; i++) {
2218 QualType ArgType = proto->getArgType(i);
2219 RewriteBlockPointerType(FdStr, ArgType);
2220 if (i+1 < numArgs)
2221 FdStr += ", ";
2222 }
2223 FdStr += ");\n";
2224 InsertText(FunLocStart, FdStr);
2225 CurFunctionDeclToDeclareForBlock = 0;
2226}
2227
2228// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
2229void RewriteModernObjC::SynthSuperContructorFunctionDecl() {
2230 if (SuperContructorFunctionDecl)
2231 return;
2232 IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
2233 SmallVector<QualType, 16> ArgTys;
2234 QualType argT = Context->getObjCIdType();
2235 assert(!argT.isNull() && "Can't find 'id' type");
2236 ArgTys.push_back(argT);
2237 ArgTys.push_back(argT);
2238 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2239 &ArgTys[0], ArgTys.size());
2240 SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2241 SourceLocation(),
2242 SourceLocation(),
2243 msgSendIdent, msgSendType, 0,
2244 SC_Extern,
2245 SC_None, false);
2246}
2247
2248// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
2249void RewriteModernObjC::SynthMsgSendFunctionDecl() {
2250 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
2251 SmallVector<QualType, 16> ArgTys;
2252 QualType argT = Context->getObjCIdType();
2253 assert(!argT.isNull() && "Can't find 'id' type");
2254 ArgTys.push_back(argT);
2255 argT = Context->getObjCSelType();
2256 assert(!argT.isNull() && "Can't find 'SEL' type");
2257 ArgTys.push_back(argT);
2258 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2259 &ArgTys[0], ArgTys.size(),
2260 true /*isVariadic*/);
2261 MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2262 SourceLocation(),
2263 SourceLocation(),
2264 msgSendIdent, msgSendType, 0,
2265 SC_Extern,
2266 SC_None, false);
2267}
2268
2269// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
2270void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {
2271 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
2272 SmallVector<QualType, 16> ArgTys;
2273 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
2274 SourceLocation(), SourceLocation(),
2275 &Context->Idents.get("objc_super"));
2276 QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
2277 assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
2278 ArgTys.push_back(argT);
2279 argT = Context->getObjCSelType();
2280 assert(!argT.isNull() && "Can't find 'SEL' type");
2281 ArgTys.push_back(argT);
2282 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2283 &ArgTys[0], ArgTys.size(),
2284 true /*isVariadic*/);
2285 MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2286 SourceLocation(),
2287 SourceLocation(),
2288 msgSendIdent, msgSendType, 0,
2289 SC_Extern,
2290 SC_None, false);
2291}
2292
2293// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
2294void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {
2295 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
2296 SmallVector<QualType, 16> ArgTys;
2297 QualType argT = Context->getObjCIdType();
2298 assert(!argT.isNull() && "Can't find 'id' type");
2299 ArgTys.push_back(argT);
2300 argT = Context->getObjCSelType();
2301 assert(!argT.isNull() && "Can't find 'SEL' type");
2302 ArgTys.push_back(argT);
2303 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2304 &ArgTys[0], ArgTys.size(),
2305 true /*isVariadic*/);
2306 MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2307 SourceLocation(),
2308 SourceLocation(),
2309 msgSendIdent, msgSendType, 0,
2310 SC_Extern,
2311 SC_None, false);
2312}
2313
2314// SynthMsgSendSuperStretFunctionDecl -
2315// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
2316void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {
2317 IdentifierInfo *msgSendIdent =
2318 &Context->Idents.get("objc_msgSendSuper_stret");
2319 SmallVector<QualType, 16> ArgTys;
2320 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
2321 SourceLocation(), SourceLocation(),
2322 &Context->Idents.get("objc_super"));
2323 QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
2324 assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
2325 ArgTys.push_back(argT);
2326 argT = Context->getObjCSelType();
2327 assert(!argT.isNull() && "Can't find 'SEL' type");
2328 ArgTys.push_back(argT);
2329 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2330 &ArgTys[0], ArgTys.size(),
2331 true /*isVariadic*/);
2332 MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2333 SourceLocation(),
2334 SourceLocation(),
2335 msgSendIdent, msgSendType, 0,
2336 SC_Extern,
2337 SC_None, false);
2338}
2339
2340// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
2341void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {
2342 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
2343 SmallVector<QualType, 16> ArgTys;
2344 QualType argT = Context->getObjCIdType();
2345 assert(!argT.isNull() && "Can't find 'id' type");
2346 ArgTys.push_back(argT);
2347 argT = Context->getObjCSelType();
2348 assert(!argT.isNull() && "Can't find 'SEL' type");
2349 ArgTys.push_back(argT);
2350 QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
2351 &ArgTys[0], ArgTys.size(),
2352 true /*isVariadic*/);
2353 MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2354 SourceLocation(),
2355 SourceLocation(),
2356 msgSendIdent, msgSendType, 0,
2357 SC_Extern,
2358 SC_None, false);
2359}
2360
2361// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
2362void RewriteModernObjC::SynthGetClassFunctionDecl() {
2363 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
2364 SmallVector<QualType, 16> ArgTys;
2365 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2366 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2367 &ArgTys[0], ArgTys.size());
2368 GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2369 SourceLocation(),
2370 SourceLocation(),
2371 getClassIdent, getClassType, 0,
2372 SC_Extern,
2373 SC_None, false);
2374}
2375
2376// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
2377void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {
2378 IdentifierInfo *getSuperClassIdent =
2379 &Context->Idents.get("class_getSuperclass");
2380 SmallVector<QualType, 16> ArgTys;
2381 ArgTys.push_back(Context->getObjCClassType());
2382 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2383 &ArgTys[0], ArgTys.size());
2384 GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2385 SourceLocation(),
2386 SourceLocation(),
2387 getSuperClassIdent,
2388 getClassType, 0,
2389 SC_Extern,
2390 SC_None,
2391 false);
2392}
2393
2394// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);
2395void RewriteModernObjC::SynthGetMetaClassFunctionDecl() {
2396 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
2397 SmallVector<QualType, 16> ArgTys;
2398 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2399 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2400 &ArgTys[0], ArgTys.size());
2401 GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2402 SourceLocation(),
2403 SourceLocation(),
2404 getClassIdent, getClassType, 0,
2405 SC_Extern,
2406 SC_None, false);
2407}
2408
2409Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
2410 QualType strType = getConstantStringStructType();
2411
2412 std::string S = "__NSConstantStringImpl_";
2413
2414 std::string tmpName = InFileName;
2415 unsigned i;
2416 for (i=0; i < tmpName.length(); i++) {
2417 char c = tmpName.at(i);
2418 // replace any non alphanumeric characters with '_'.
2419 if (!isalpha(c) && (c < '0' || c > '9'))
2420 tmpName[i] = '_';
2421 }
2422 S += tmpName;
2423 S += "_";
2424 S += utostr(NumObjCStringLiterals++);
2425
2426 Preamble += "static __NSConstantStringImpl " + S;
2427 Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2428 Preamble += "0x000007c8,"; // utf8_str
2429 // The pretty printer for StringLiteral handles escape characters properly.
2430 std::string prettyBufS;
2431 llvm::raw_string_ostream prettyBuf(prettyBufS);
2432 Exp->getString()->printPretty(prettyBuf, *Context, 0,
2433 PrintingPolicy(LangOpts));
2434 Preamble += prettyBuf.str();
2435 Preamble += ",";
2436 Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
2437
2438 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
2439 SourceLocation(), &Context->Idents.get(S),
2440 strType, 0, SC_Static, SC_None);
John McCallf4b88a42012-03-10 09:33:50 +00002441 DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00002442 SourceLocation());
2443 Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
2444 Context->getPointerType(DRE->getType()),
2445 VK_RValue, OK_Ordinary,
2446 SourceLocation());
2447 // cast to NSConstantString *
2448 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
2449 CK_CPointerToObjCPointerCast, Unop);
2450 ReplaceStmt(Exp, cast);
2451 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
2452 return cast;
2453}
2454
Fariborz Jahanian55947042012-03-27 20:17:30 +00002455Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {
2456 unsigned IntSize =
2457 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
2458
2459 Expr *FlagExp = IntegerLiteral::Create(*Context,
2460 llvm::APInt(IntSize, Exp->getValue()),
2461 Context->IntTy, Exp->getLocation());
2462 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,
2463 CK_BitCast, FlagExp);
2464 ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),
2465 cast);
2466 ReplaceStmt(Exp, PE);
2467 return PE;
2468}
2469
Fariborz Jahanian0f9b18e2012-03-30 16:49:36 +00002470Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp) {
2471 // synthesize declaration of helper functions needed in this routine.
2472 if (!SelGetUidFunctionDecl)
2473 SynthSelGetUidFunctionDecl();
2474 // use objc_msgSend() for all.
2475 if (!MsgSendFunctionDecl)
2476 SynthMsgSendFunctionDecl();
2477 if (!GetClassFunctionDecl)
2478 SynthGetClassFunctionDecl();
2479
2480 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2481 SourceLocation StartLoc = Exp->getLocStart();
2482 SourceLocation EndLoc = Exp->getLocEnd();
2483
2484 // Synthesize a call to objc_msgSend().
2485 SmallVector<Expr*, 4> MsgExprs;
2486 SmallVector<Expr*, 4> ClsExprs;
2487 QualType argType = Context->getPointerType(Context->CharTy);
2488 QualType expType = Exp->getType();
2489
2490 // Create a call to objc_getClass("NSNumber"). It will be th 1st argument.
2491 ObjCInterfaceDecl *Class =
2492 expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface();
2493
2494 IdentifierInfo *clsName = Class->getIdentifier();
2495 ClsExprs.push_back(StringLiteral::Create(*Context,
2496 clsName->getName(),
2497 StringLiteral::Ascii, false,
2498 argType, SourceLocation()));
2499 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2500 &ClsExprs[0],
2501 ClsExprs.size(),
2502 StartLoc, EndLoc);
2503 MsgExprs.push_back(Cls);
2504
2505 // Create a call to sel_registerName("numberWithBool:"), etc.
2506 // it will be the 2nd argument.
2507 SmallVector<Expr*, 4> SelExprs;
2508 ObjCMethodDecl *NumericMethod = Exp->getObjCNumericLiteralMethod();
2509 SelExprs.push_back(StringLiteral::Create(*Context,
2510 NumericMethod->getSelector().getAsString(),
2511 StringLiteral::Ascii, false,
2512 argType, SourceLocation()));
2513 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2514 &SelExprs[0], SelExprs.size(),
2515 StartLoc, EndLoc);
2516 MsgExprs.push_back(SelExp);
2517
2518 // User provided numeric literal is the 3rd, and last, argument.
2519 Expr *userExpr = Exp->getNumber();
2520 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
2521 QualType type = ICE->getType();
2522 const Expr *SubExpr = ICE->IgnoreParenImpCasts();
2523 CastKind CK = CK_BitCast;
2524 if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())
2525 CK = CK_IntegralToBoolean;
2526 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2527 }
2528 MsgExprs.push_back(userExpr);
2529
2530 SmallVector<QualType, 4> ArgTypes;
2531 ArgTypes.push_back(Context->getObjCIdType());
2532 ArgTypes.push_back(Context->getObjCSelType());
2533 for (ObjCMethodDecl::param_iterator PI = NumericMethod->param_begin(),
2534 E = NumericMethod->param_end(); PI != E; ++PI)
2535 ArgTypes.push_back((*PI)->getType());
2536
2537 QualType returnType = Exp->getType();
2538 // Get the type, we will need to reference it in a couple spots.
2539 QualType msgSendType = MsgSendFlavor->getType();
2540
2541 // Create a reference to the objc_msgSend() declaration.
2542 DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
2543 VK_LValue, SourceLocation());
2544
2545 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
2546 Context->getPointerType(Context->VoidTy),
2547 CK_BitCast, DRE);
2548
2549 // Now do the "normal" pointer to function cast.
2550 QualType castType =
2551 getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
2552 NumericMethod->isVariadic());
2553 castType = Context->getPointerType(castType);
2554 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2555 cast);
2556
2557 // Don't forget the parens to enforce the proper binding.
2558 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
2559
2560 const FunctionType *FT = msgSendType->getAs<FunctionType>();
2561 CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
2562 MsgExprs.size(),
2563 FT->getResultType(), VK_RValue,
2564 EndLoc);
2565 ReplaceStmt(Exp, CE);
2566 return CE;
2567}
2568
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00002569// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
2570QualType RewriteModernObjC::getSuperStructType() {
2571 if (!SuperStructDecl) {
2572 SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
2573 SourceLocation(), SourceLocation(),
2574 &Context->Idents.get("objc_super"));
2575 QualType FieldTypes[2];
2576
2577 // struct objc_object *receiver;
2578 FieldTypes[0] = Context->getObjCIdType();
2579 // struct objc_class *super;
2580 FieldTypes[1] = Context->getObjCClassType();
2581
2582 // Create fields
2583 for (unsigned i = 0; i < 2; ++i) {
2584 SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
2585 SourceLocation(),
2586 SourceLocation(), 0,
2587 FieldTypes[i], 0,
2588 /*BitWidth=*/0,
2589 /*Mutable=*/false,
2590 /*HasInit=*/false));
2591 }
2592
2593 SuperStructDecl->completeDefinition();
2594 }
2595 return Context->getTagDeclType(SuperStructDecl);
2596}
2597
2598QualType RewriteModernObjC::getConstantStringStructType() {
2599 if (!ConstantStringDecl) {
2600 ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
2601 SourceLocation(), SourceLocation(),
2602 &Context->Idents.get("__NSConstantStringImpl"));
2603 QualType FieldTypes[4];
2604
2605 // struct objc_object *receiver;
2606 FieldTypes[0] = Context->getObjCIdType();
2607 // int flags;
2608 FieldTypes[1] = Context->IntTy;
2609 // char *str;
2610 FieldTypes[2] = Context->getPointerType(Context->CharTy);
2611 // long length;
2612 FieldTypes[3] = Context->LongTy;
2613
2614 // Create fields
2615 for (unsigned i = 0; i < 4; ++i) {
2616 ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
2617 ConstantStringDecl,
2618 SourceLocation(),
2619 SourceLocation(), 0,
2620 FieldTypes[i], 0,
2621 /*BitWidth=*/0,
2622 /*Mutable=*/true,
2623 /*HasInit=*/false));
2624 }
2625
2626 ConstantStringDecl->completeDefinition();
2627 }
2628 return Context->getTagDeclType(ConstantStringDecl);
2629}
2630
2631Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
2632 SourceLocation StartLoc,
2633 SourceLocation EndLoc) {
2634 if (!SelGetUidFunctionDecl)
2635 SynthSelGetUidFunctionDecl();
2636 if (!MsgSendFunctionDecl)
2637 SynthMsgSendFunctionDecl();
2638 if (!MsgSendSuperFunctionDecl)
2639 SynthMsgSendSuperFunctionDecl();
2640 if (!MsgSendStretFunctionDecl)
2641 SynthMsgSendStretFunctionDecl();
2642 if (!MsgSendSuperStretFunctionDecl)
2643 SynthMsgSendSuperStretFunctionDecl();
2644 if (!MsgSendFpretFunctionDecl)
2645 SynthMsgSendFpretFunctionDecl();
2646 if (!GetClassFunctionDecl)
2647 SynthGetClassFunctionDecl();
2648 if (!GetSuperClassFunctionDecl)
2649 SynthGetSuperClassFunctionDecl();
2650 if (!GetMetaClassFunctionDecl)
2651 SynthGetMetaClassFunctionDecl();
2652
2653 // default to objc_msgSend().
2654 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2655 // May need to use objc_msgSend_stret() as well.
2656 FunctionDecl *MsgSendStretFlavor = 0;
2657 if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
2658 QualType resultType = mDecl->getResultType();
2659 if (resultType->isRecordType())
2660 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2661 else if (resultType->isRealFloatingType())
2662 MsgSendFlavor = MsgSendFpretFunctionDecl;
2663 }
2664
2665 // Synthesize a call to objc_msgSend().
2666 SmallVector<Expr*, 8> MsgExprs;
2667 switch (Exp->getReceiverKind()) {
2668 case ObjCMessageExpr::SuperClass: {
2669 MsgSendFlavor = MsgSendSuperFunctionDecl;
2670 if (MsgSendStretFlavor)
2671 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2672 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
2673
2674 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
2675
2676 SmallVector<Expr*, 4> InitExprs;
2677
2678 // set the receiver to self, the first argument to all methods.
2679 InitExprs.push_back(
2680 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2681 CK_BitCast,
2682 new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
John McCallf4b88a42012-03-10 09:33:50 +00002683 false,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00002684 Context->getObjCIdType(),
2685 VK_RValue,
2686 SourceLocation()))
2687 ); // set the 'receiver'.
2688
2689 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2690 SmallVector<Expr*, 8> ClsExprs;
2691 QualType argType = Context->getPointerType(Context->CharTy);
2692 ClsExprs.push_back(StringLiteral::Create(*Context,
2693 ClassDecl->getIdentifier()->getName(),
2694 StringLiteral::Ascii, false,
2695 argType, SourceLocation()));
2696 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2697 &ClsExprs[0],
2698 ClsExprs.size(),
2699 StartLoc,
2700 EndLoc);
2701 // (Class)objc_getClass("CurrentClass")
2702 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2703 Context->getObjCClassType(),
2704 CK_BitCast, Cls);
2705 ClsExprs.clear();
2706 ClsExprs.push_back(ArgExpr);
2707 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
2708 &ClsExprs[0], ClsExprs.size(),
2709 StartLoc, EndLoc);
2710
2711 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2712 // To turn off a warning, type-cast to 'id'
2713 InitExprs.push_back( // set 'super class', using class_getSuperclass().
2714 NoTypeInfoCStyleCastExpr(Context,
2715 Context->getObjCIdType(),
2716 CK_BitCast, Cls));
2717 // struct objc_super
2718 QualType superType = getSuperStructType();
2719 Expr *SuperRep;
2720
2721 if (LangOpts.MicrosoftExt) {
2722 SynthSuperContructorFunctionDecl();
2723 // Simulate a contructor call...
2724 DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
John McCallf4b88a42012-03-10 09:33:50 +00002725 false, superType, VK_LValue,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00002726 SourceLocation());
2727 SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
2728 InitExprs.size(),
2729 superType, VK_LValue,
2730 SourceLocation());
2731 // The code for super is a little tricky to prevent collision with
2732 // the structure definition in the header. The rewriter has it's own
2733 // internal definition (__rw_objc_super) that is uses. This is why
2734 // we need the cast below. For example:
2735 // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2736 //
2737 SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
2738 Context->getPointerType(SuperRep->getType()),
2739 VK_RValue, OK_Ordinary,
2740 SourceLocation());
2741 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2742 Context->getPointerType(superType),
2743 CK_BitCast, SuperRep);
2744 } else {
2745 // (struct objc_super) { <exprs from above> }
2746 InitListExpr *ILE =
2747 new (Context) InitListExpr(*Context, SourceLocation(),
2748 &InitExprs[0], InitExprs.size(),
2749 SourceLocation());
2750 TypeSourceInfo *superTInfo
2751 = Context->getTrivialTypeSourceInfo(superType);
2752 SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
2753 superType, VK_LValue,
2754 ILE, false);
2755 // struct objc_super *
2756 SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
2757 Context->getPointerType(SuperRep->getType()),
2758 VK_RValue, OK_Ordinary,
2759 SourceLocation());
2760 }
2761 MsgExprs.push_back(SuperRep);
2762 break;
2763 }
2764
2765 case ObjCMessageExpr::Class: {
2766 SmallVector<Expr*, 8> ClsExprs;
2767 QualType argType = Context->getPointerType(Context->CharTy);
2768 ObjCInterfaceDecl *Class
2769 = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
2770 IdentifierInfo *clsName = Class->getIdentifier();
2771 ClsExprs.push_back(StringLiteral::Create(*Context,
2772 clsName->getName(),
2773 StringLiteral::Ascii, false,
2774 argType, SourceLocation()));
2775 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2776 &ClsExprs[0],
2777 ClsExprs.size(),
2778 StartLoc, EndLoc);
2779 MsgExprs.push_back(Cls);
2780 break;
2781 }
2782
2783 case ObjCMessageExpr::SuperInstance:{
2784 MsgSendFlavor = MsgSendSuperFunctionDecl;
2785 if (MsgSendStretFlavor)
2786 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2787 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
2788 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
2789 SmallVector<Expr*, 4> InitExprs;
2790
2791 InitExprs.push_back(
2792 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2793 CK_BitCast,
2794 new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
John McCallf4b88a42012-03-10 09:33:50 +00002795 false,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00002796 Context->getObjCIdType(),
2797 VK_RValue, SourceLocation()))
2798 ); // set the 'receiver'.
2799
2800 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2801 SmallVector<Expr*, 8> ClsExprs;
2802 QualType argType = Context->getPointerType(Context->CharTy);
2803 ClsExprs.push_back(StringLiteral::Create(*Context,
2804 ClassDecl->getIdentifier()->getName(),
2805 StringLiteral::Ascii, false, argType,
2806 SourceLocation()));
2807 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2808 &ClsExprs[0],
2809 ClsExprs.size(),
2810 StartLoc, EndLoc);
2811 // (Class)objc_getClass("CurrentClass")
2812 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2813 Context->getObjCClassType(),
2814 CK_BitCast, Cls);
2815 ClsExprs.clear();
2816 ClsExprs.push_back(ArgExpr);
2817 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
2818 &ClsExprs[0], ClsExprs.size(),
2819 StartLoc, EndLoc);
2820
2821 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2822 // To turn off a warning, type-cast to 'id'
2823 InitExprs.push_back(
2824 // set 'super class', using class_getSuperclass().
2825 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2826 CK_BitCast, Cls));
2827 // struct objc_super
2828 QualType superType = getSuperStructType();
2829 Expr *SuperRep;
2830
2831 if (LangOpts.MicrosoftExt) {
2832 SynthSuperContructorFunctionDecl();
2833 // Simulate a contructor call...
2834 DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
John McCallf4b88a42012-03-10 09:33:50 +00002835 false, superType, VK_LValue,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00002836 SourceLocation());
2837 SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
2838 InitExprs.size(),
2839 superType, VK_LValue, SourceLocation());
2840 // The code for super is a little tricky to prevent collision with
2841 // the structure definition in the header. The rewriter has it's own
2842 // internal definition (__rw_objc_super) that is uses. This is why
2843 // we need the cast below. For example:
2844 // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2845 //
2846 SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
2847 Context->getPointerType(SuperRep->getType()),
2848 VK_RValue, OK_Ordinary,
2849 SourceLocation());
2850 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2851 Context->getPointerType(superType),
2852 CK_BitCast, SuperRep);
2853 } else {
2854 // (struct objc_super) { <exprs from above> }
2855 InitListExpr *ILE =
2856 new (Context) InitListExpr(*Context, SourceLocation(),
2857 &InitExprs[0], InitExprs.size(),
2858 SourceLocation());
2859 TypeSourceInfo *superTInfo
2860 = Context->getTrivialTypeSourceInfo(superType);
2861 SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
2862 superType, VK_RValue, ILE,
2863 false);
2864 }
2865 MsgExprs.push_back(SuperRep);
2866 break;
2867 }
2868
2869 case ObjCMessageExpr::Instance: {
2870 // Remove all type-casts because it may contain objc-style types; e.g.
2871 // Foo<Proto> *.
2872 Expr *recExpr = Exp->getInstanceReceiver();
2873 while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
2874 recExpr = CE->getSubExpr();
2875 CastKind CK = recExpr->getType()->isObjCObjectPointerType()
2876 ? CK_BitCast : recExpr->getType()->isBlockPointerType()
2877 ? CK_BlockPointerToObjCPointerCast
2878 : CK_CPointerToObjCPointerCast;
2879
2880 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2881 CK, recExpr);
2882 MsgExprs.push_back(recExpr);
2883 break;
2884 }
2885 }
2886
2887 // Create a call to sel_registerName("selName"), it will be the 2nd argument.
2888 SmallVector<Expr*, 8> SelExprs;
2889 QualType argType = Context->getPointerType(Context->CharTy);
2890 SelExprs.push_back(StringLiteral::Create(*Context,
2891 Exp->getSelector().getAsString(),
2892 StringLiteral::Ascii, false,
2893 argType, SourceLocation()));
2894 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2895 &SelExprs[0], SelExprs.size(),
2896 StartLoc,
2897 EndLoc);
2898 MsgExprs.push_back(SelExp);
2899
2900 // Now push any user supplied arguments.
2901 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
2902 Expr *userExpr = Exp->getArg(i);
2903 // Make all implicit casts explicit...ICE comes in handy:-)
2904 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
2905 // Reuse the ICE type, it is exactly what the doctor ordered.
2906 QualType type = ICE->getType();
2907 if (needToScanForQualifiers(type))
2908 type = Context->getObjCIdType();
2909 // Make sure we convert "type (^)(...)" to "type (*)(...)".
2910 (void)convertBlockPointerToFunctionPointer(type);
2911 const Expr *SubExpr = ICE->IgnoreParenImpCasts();
2912 CastKind CK;
2913 if (SubExpr->getType()->isIntegralType(*Context) &&
2914 type->isBooleanType()) {
2915 CK = CK_IntegralToBoolean;
2916 } else if (type->isObjCObjectPointerType()) {
2917 if (SubExpr->getType()->isBlockPointerType()) {
2918 CK = CK_BlockPointerToObjCPointerCast;
2919 } else if (SubExpr->getType()->isPointerType()) {
2920 CK = CK_CPointerToObjCPointerCast;
2921 } else {
2922 CK = CK_BitCast;
2923 }
2924 } else {
2925 CK = CK_BitCast;
2926 }
2927
2928 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2929 }
2930 // Make id<P...> cast into an 'id' cast.
2931 else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2932 if (CE->getType()->isObjCQualifiedIdType()) {
2933 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2934 userExpr = CE->getSubExpr();
2935 CastKind CK;
2936 if (userExpr->getType()->isIntegralType(*Context)) {
2937 CK = CK_IntegralToPointer;
2938 } else if (userExpr->getType()->isBlockPointerType()) {
2939 CK = CK_BlockPointerToObjCPointerCast;
2940 } else if (userExpr->getType()->isPointerType()) {
2941 CK = CK_CPointerToObjCPointerCast;
2942 } else {
2943 CK = CK_BitCast;
2944 }
2945 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2946 CK, userExpr);
2947 }
2948 }
2949 MsgExprs.push_back(userExpr);
2950 // We've transferred the ownership to MsgExprs. For now, we *don't* null
2951 // out the argument in the original expression (since we aren't deleting
2952 // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
2953 //Exp->setArg(i, 0);
2954 }
2955 // Generate the funky cast.
2956 CastExpr *cast;
2957 SmallVector<QualType, 8> ArgTypes;
2958 QualType returnType;
2959
2960 // Push 'id' and 'SEL', the 2 implicit arguments.
2961 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2962 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
2963 else
2964 ArgTypes.push_back(Context->getObjCIdType());
2965 ArgTypes.push_back(Context->getObjCSelType());
2966 if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
2967 // Push any user argument types.
2968 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
2969 E = OMD->param_end(); PI != E; ++PI) {
2970 QualType t = (*PI)->getType()->isObjCQualifiedIdType()
2971 ? Context->getObjCIdType()
2972 : (*PI)->getType();
2973 // Make sure we convert "t (^)(...)" to "t (*)(...)".
2974 (void)convertBlockPointerToFunctionPointer(t);
2975 ArgTypes.push_back(t);
2976 }
2977 returnType = Exp->getType();
2978 convertToUnqualifiedObjCType(returnType);
2979 (void)convertBlockPointerToFunctionPointer(returnType);
2980 } else {
2981 returnType = Context->getObjCIdType();
2982 }
2983 // Get the type, we will need to reference it in a couple spots.
2984 QualType msgSendType = MsgSendFlavor->getType();
2985
2986 // Create a reference to the objc_msgSend() declaration.
John McCallf4b88a42012-03-10 09:33:50 +00002987 DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00002988 VK_LValue, SourceLocation());
2989
2990 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
2991 // If we don't do this cast, we get the following bizarre warning/note:
2992 // xx.m:13: warning: function called through a non-compatible type
2993 // xx.m:13: note: if this code is reached, the program will abort
2994 cast = NoTypeInfoCStyleCastExpr(Context,
2995 Context->getPointerType(Context->VoidTy),
2996 CK_BitCast, DRE);
2997
2998 // Now do the "normal" pointer to function cast.
2999 QualType castType =
3000 getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
3001 // If we don't have a method decl, force a variadic cast.
3002 Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true);
3003 castType = Context->getPointerType(castType);
3004 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
3005 cast);
3006
3007 // Don't forget the parens to enforce the proper binding.
3008 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
3009
3010 const FunctionType *FT = msgSendType->getAs<FunctionType>();
3011 CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
3012 MsgExprs.size(),
3013 FT->getResultType(), VK_RValue,
3014 EndLoc);
3015 Stmt *ReplacingStmt = CE;
3016 if (MsgSendStretFlavor) {
3017 // We have the method which returns a struct/union. Must also generate
3018 // call to objc_msgSend_stret and hang both varieties on a conditional
3019 // expression which dictate which one to envoke depending on size of
3020 // method's return type.
3021
3022 // Create a reference to the objc_msgSend_stret() declaration.
John McCallf4b88a42012-03-10 09:33:50 +00003023 DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor,
3024 false, msgSendType,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003025 VK_LValue, SourceLocation());
3026 // Need to cast objc_msgSend_stret to "void *" (see above comment).
3027 cast = NoTypeInfoCStyleCastExpr(Context,
3028 Context->getPointerType(Context->VoidTy),
3029 CK_BitCast, STDRE);
3030 // Now do the "normal" pointer to function cast.
3031 castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
3032 Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
3033 castType = Context->getPointerType(castType);
3034 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
3035 cast);
3036
3037 // Don't forget the parens to enforce the proper binding.
3038 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
3039
3040 FT = msgSendType->getAs<FunctionType>();
3041 CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
3042 MsgExprs.size(),
3043 FT->getResultType(), VK_RValue,
3044 SourceLocation());
3045
3046 // Build sizeof(returnType)
3047 UnaryExprOrTypeTraitExpr *sizeofExpr =
3048 new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf,
3049 Context->getTrivialTypeSourceInfo(returnType),
3050 Context->getSizeType(), SourceLocation(),
3051 SourceLocation());
3052 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
3053 // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
3054 // For X86 it is more complicated and some kind of target specific routine
3055 // is needed to decide what to do.
3056 unsigned IntSize =
3057 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
3058 IntegerLiteral *limit = IntegerLiteral::Create(*Context,
3059 llvm::APInt(IntSize, 8),
3060 Context->IntTy,
3061 SourceLocation());
3062 BinaryOperator *lessThanExpr =
3063 new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,
3064 VK_RValue, OK_Ordinary, SourceLocation());
3065 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
3066 ConditionalOperator *CondExpr =
3067 new (Context) ConditionalOperator(lessThanExpr,
3068 SourceLocation(), CE,
3069 SourceLocation(), STCE,
3070 returnType, VK_RValue, OK_Ordinary);
3071 ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
3072 CondExpr);
3073 }
3074 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3075 return ReplacingStmt;
3076}
3077
3078Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
3079 Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(),
3080 Exp->getLocEnd());
3081
3082 // Now do the actual rewrite.
3083 ReplaceStmt(Exp, ReplacingStmt);
3084
3085 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3086 return ReplacingStmt;
3087}
3088
3089// typedef struct objc_object Protocol;
3090QualType RewriteModernObjC::getProtocolType() {
3091 if (!ProtocolTypeDecl) {
3092 TypeSourceInfo *TInfo
3093 = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
3094 ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
3095 SourceLocation(), SourceLocation(),
3096 &Context->Idents.get("Protocol"),
3097 TInfo);
3098 }
3099 return Context->getTypeDeclType(ProtocolTypeDecl);
3100}
3101
3102/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
3103/// a synthesized/forward data reference (to the protocol's metadata).
3104/// The forward references (and metadata) are generated in
3105/// RewriteModernObjC::HandleTranslationUnit().
3106Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
Fariborz Jahanian30650eb2012-03-15 17:05:33 +00003107 std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +
3108 Exp->getProtocol()->getNameAsString();
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003109 IdentifierInfo *ID = &Context->Idents.get(Name);
3110 VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
3111 SourceLocation(), ID, getProtocolType(), 0,
3112 SC_Extern, SC_None);
John McCallf4b88a42012-03-10 09:33:50 +00003113 DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
3114 VK_LValue, SourceLocation());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003115 Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
3116 Context->getPointerType(DRE->getType()),
3117 VK_RValue, OK_Ordinary, SourceLocation());
3118 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
3119 CK_BitCast,
3120 DerefExpr);
3121 ReplaceStmt(Exp, castExpr);
3122 ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
3123 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3124 return castExpr;
3125
3126}
3127
3128bool RewriteModernObjC::BufferContainsPPDirectives(const char *startBuf,
3129 const char *endBuf) {
3130 while (startBuf < endBuf) {
3131 if (*startBuf == '#') {
3132 // Skip whitespace.
3133 for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
3134 ;
3135 if (!strncmp(startBuf, "if", strlen("if")) ||
3136 !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
3137 !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
3138 !strncmp(startBuf, "define", strlen("define")) ||
3139 !strncmp(startBuf, "undef", strlen("undef")) ||
3140 !strncmp(startBuf, "else", strlen("else")) ||
3141 !strncmp(startBuf, "elif", strlen("elif")) ||
3142 !strncmp(startBuf, "endif", strlen("endif")) ||
3143 !strncmp(startBuf, "pragma", strlen("pragma")) ||
3144 !strncmp(startBuf, "include", strlen("include")) ||
3145 !strncmp(startBuf, "import", strlen("import")) ||
3146 !strncmp(startBuf, "include_next", strlen("include_next")))
3147 return true;
3148 }
3149 startBuf++;
3150 }
3151 return false;
3152}
3153
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003154/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003155/// It handles elaborated types, as well as enum types in the process.
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003156bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
3157 std::string &Result) {
3158 if (Type->isArrayType()) {
3159 QualType ElemTy = Context->getBaseElementType(Type);
3160 return RewriteObjCFieldDeclType(ElemTy, Result);
3161 }
3162 else if (Type->isRecordType()) {
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003163 RecordDecl *RD = Type->getAs<RecordType>()->getDecl();
3164 if (RD->isCompleteDefinition()) {
3165 if (RD->isStruct())
3166 Result += "\n\tstruct ";
3167 else if (RD->isUnion())
3168 Result += "\n\tunion ";
3169 else
3170 assert(false && "class not allowed as an ivar type");
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003171
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003172 Result += RD->getName();
3173 if (TagsDefinedInIvarDecls.count(RD)) {
3174 // This struct is already defined. Do not write its definition again.
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003175 Result += " ";
3176 return true;
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003177 }
3178 TagsDefinedInIvarDecls.insert(RD);
3179 Result += " {\n";
3180 for (RecordDecl::field_iterator i = RD->field_begin(),
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003181 e = RD->field_end(); i != e; ++i) {
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003182 FieldDecl *FD = *i;
3183 RewriteObjCFieldDecl(FD, Result);
3184 }
3185 Result += "\t} ";
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003186 return true;
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003187 }
3188 }
3189 else if (Type->isEnumeralType()) {
3190 EnumDecl *ED = Type->getAs<EnumType>()->getDecl();
3191 if (ED->isCompleteDefinition()) {
3192 Result += "\n\tenum ";
3193 Result += ED->getName();
3194 if (TagsDefinedInIvarDecls.count(ED)) {
3195 // This enum is already defined. Do not write its definition again.
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003196 Result += " ";
3197 return true;
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003198 }
3199 TagsDefinedInIvarDecls.insert(ED);
3200
3201 Result += " {\n";
3202 for (EnumDecl::enumerator_iterator EC = ED->enumerator_begin(),
3203 ECEnd = ED->enumerator_end(); EC != ECEnd; ++EC) {
3204 Result += "\t"; Result += EC->getName(); Result += " = ";
3205 llvm::APSInt Val = EC->getInitVal();
3206 Result += Val.toString(10);
3207 Result += ",\n";
3208 }
3209 Result += "\t} ";
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003210 return true;
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003211 }
3212 }
3213
3214 Result += "\t";
3215 convertObjCTypeToCStyleType(Type);
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003216 return false;
3217}
3218
3219
3220/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.
3221/// It handles elaborated types, as well as enum types in the process.
3222void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
3223 std::string &Result) {
3224 QualType Type = fieldDecl->getType();
3225 std::string Name = fieldDecl->getNameAsString();
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003226
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003227 bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);
3228 if (!EleboratedType)
3229 Type.getAsStringInternal(Name, Context->getPrintingPolicy());
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003230 Result += Name;
3231 if (fieldDecl->isBitField()) {
3232 Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context));
3233 }
Fariborz Jahanian97c1fd62012-03-09 23:46:23 +00003234 else if (EleboratedType && Type->isArrayType()) {
3235 CanQualType CType = Context->getCanonicalType(Type);
3236 while (isa<ArrayType>(CType)) {
3237 if (const ConstantArrayType *CAT = Context->getAsConstantArrayType(CType)) {
3238 Result += "[";
3239 llvm::APInt Dim = CAT->getSize();
3240 Result += utostr(Dim.getZExtValue());
3241 Result += "]";
3242 }
3243 CType = CType->getAs<ArrayType>()->getElementType();
3244 }
3245 }
3246
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003247 Result += ";\n";
3248}
3249
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003250/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
3251/// an objective-c class with ivars.
3252void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
3253 std::string &Result) {
3254 assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
3255 assert(CDecl->getName() != "" &&
3256 "Name missing in SynthesizeObjCInternalStruct");
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003257 ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003258 SmallVector<ObjCIvarDecl *, 8> IVars;
3259 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
Fariborz Jahanian9a2105b2012-03-06 17:16:27 +00003260 IVD; IVD = IVD->getNextIvar())
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003261 IVars.push_back(IVD);
Fariborz Jahanian9a2105b2012-03-06 17:16:27 +00003262
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003263 SourceLocation LocStart = CDecl->getLocStart();
3264 SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003265
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003266 const char *startBuf = SM->getCharacterData(LocStart);
3267 const char *endBuf = SM->getCharacterData(LocEnd);
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003268
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003269 // If no ivars and no root or if its root, directly or indirectly,
3270 // have no ivars (thus not synthesized) then no need to synthesize this class.
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003271 if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003272 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3273 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3274 ReplaceText(LocStart, endBuf-startBuf, Result);
3275 return;
3276 }
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003277
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003278 Result += "\nstruct ";
3279 Result += CDecl->getNameAsString();
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003280 Result += "_IMPL {\n";
3281
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00003282 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003283 Result += "\tstruct "; Result += RCDecl->getNameAsString();
3284 Result += "_IMPL "; Result += RCDecl->getNameAsString();
3285 Result += "_IVARS;\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003286 }
Fariborz Jahanian15f87772012-02-28 22:45:07 +00003287 TagsDefinedInIvarDecls.clear();
3288 for (unsigned i = 0, e = IVars.size(); i < e; i++)
3289 RewriteObjCFieldDecl(IVars[i], Result);
Fariborz Jahanian0b17b9a2012-02-12 21:36:23 +00003290
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00003291 Result += "};\n";
3292 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3293 ReplaceText(LocStart, endBuf-startBuf, Result);
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00003294 // Mark this struct as having been generated.
3295 if (!ObjCSynthesizedStructs.insert(CDecl))
3296 llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003297}
3298
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00003299static void WriteInternalIvarName(ObjCInterfaceDecl *IDecl,
3300 ObjCIvarDecl *IvarDecl, std::string &Result) {
3301 Result += "OBJC_IVAR_$_";
3302 Result += IDecl->getName();
3303 Result += "$";
3304 Result += IvarDecl->getName();
3305}
3306
Fariborz Jahanian72c88f12012-02-22 18:13:25 +00003307/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which
3308/// have been referenced in an ivar access expression.
3309void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
3310 std::string &Result) {
3311 // write out ivar offset symbols which have been referenced in an ivar
3312 // access expression.
3313 llvm::SmallPtrSet<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];
3314 if (Ivars.empty())
3315 return;
3316 for (llvm::SmallPtrSet<ObjCIvarDecl *, 8>::iterator i = Ivars.begin(),
3317 e = Ivars.end(); i != e; i++) {
3318 ObjCIvarDecl *IvarDecl = (*i);
Fariborz Jahanian40a777a2012-03-12 16:46:58 +00003319 Result += "\n";
3320 if (LangOpts.MicrosoftExt)
3321 Result += "__declspec(allocate(\".objc_ivar$B\")) ";
Fariborz Jahanian297976d2012-03-29 17:51:09 +00003322 Result += "extern \"C\" ";
Fariborz Jahanian40a777a2012-03-12 16:46:58 +00003323 if (LangOpts.MicrosoftExt &&
3324 IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&
Fariborz Jahanian297976d2012-03-29 17:51:09 +00003325 IvarDecl->getAccessControl() != ObjCIvarDecl::Package)
3326 Result += "__declspec(dllimport) ";
3327
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00003328 Result += "unsigned long ";
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00003329 WriteInternalIvarName(CDecl, IvarDecl, Result);
3330 Result += ";";
Fariborz Jahanian72c88f12012-02-22 18:13:25 +00003331 }
3332}
3333
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003334//===----------------------------------------------------------------------===//
3335// Meta Data Emission
3336//===----------------------------------------------------------------------===//
3337
3338
3339/// RewriteImplementations - This routine rewrites all method implementations
3340/// and emits meta-data.
3341
3342void RewriteModernObjC::RewriteImplementations() {
3343 int ClsDefCount = ClassImplementation.size();
3344 int CatDefCount = CategoryImplementation.size();
3345
3346 // Rewrite implemented methods
Fariborz Jahanian8f1fed02012-02-11 20:10:52 +00003347 for (int i = 0; i < ClsDefCount; i++) {
3348 ObjCImplementationDecl *OIMP = ClassImplementation[i];
3349 ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();
3350 if (CDecl->isImplicitInterfaceDecl())
Fariborz Jahaniancf4c60f2012-02-17 22:20:12 +00003351 assert(false &&
3352 "Legacy implicit interface rewriting not supported in moder abi");
Fariborz Jahanian8f1fed02012-02-11 20:10:52 +00003353 RewriteImplementationDecl(OIMP);
3354 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003355
Fariborz Jahanian8c00a1b2012-02-17 20:33:00 +00003356 for (int i = 0; i < CatDefCount; i++) {
3357 ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];
3358 ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();
3359 if (CDecl->isImplicitInterfaceDecl())
3360 assert(false &&
3361 "Legacy implicit interface rewriting not supported in moder abi");
Fariborz Jahanian8c00a1b2012-02-17 20:33:00 +00003362 RewriteImplementationDecl(CIMP);
3363 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003364}
3365
3366void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,
3367 const std::string &Name,
3368 ValueDecl *VD, bool def) {
3369 assert(BlockByRefDeclNo.count(VD) &&
3370 "RewriteByRefString: ByRef decl missing");
3371 if (def)
3372 ResultStr += "struct ";
3373 ResultStr += "__Block_byref_" + Name +
3374 "_" + utostr(BlockByRefDeclNo[VD]) ;
3375}
3376
3377static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
3378 if (VarDecl *Var = dyn_cast<VarDecl>(VD))
3379 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3380 return false;
3381}
3382
3383std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
3384 StringRef funcName,
3385 std::string Tag) {
3386 const FunctionType *AFT = CE->getFunctionType();
3387 QualType RT = AFT->getResultType();
3388 std::string StructRef = "struct " + Tag;
3389 std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +00003390 funcName.str() + "_block_func_" + utostr(i);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003391
3392 BlockDecl *BD = CE->getBlockDecl();
3393
3394 if (isa<FunctionNoProtoType>(AFT)) {
3395 // No user-supplied arguments. Still need to pass in a pointer to the
3396 // block (to reference imported block decl refs).
3397 S += "(" + StructRef + " *__cself)";
3398 } else if (BD->param_empty()) {
3399 S += "(" + StructRef + " *__cself)";
3400 } else {
3401 const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
3402 assert(FT && "SynthesizeBlockFunc: No function proto");
3403 S += '(';
3404 // first add the implicit argument.
3405 S += StructRef + " *__cself, ";
3406 std::string ParamStr;
3407 for (BlockDecl::param_iterator AI = BD->param_begin(),
3408 E = BD->param_end(); AI != E; ++AI) {
3409 if (AI != BD->param_begin()) S += ", ";
3410 ParamStr = (*AI)->getNameAsString();
3411 QualType QT = (*AI)->getType();
Fariborz Jahanian2610f902012-03-27 16:42:20 +00003412 (void)convertBlockPointerToFunctionPointer(QT);
3413 QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003414 S += ParamStr;
3415 }
3416 if (FT->isVariadic()) {
3417 if (!BD->param_empty()) S += ", ";
3418 S += "...";
3419 }
3420 S += ')';
3421 }
3422 S += " {\n";
3423
3424 // Create local declarations to avoid rewriting all closure decl ref exprs.
3425 // First, emit a declaration for all "by ref" decls.
3426 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
3427 E = BlockByRefDecls.end(); I != E; ++I) {
3428 S += " ";
3429 std::string Name = (*I)->getNameAsString();
3430 std::string TypeString;
3431 RewriteByRefString(TypeString, Name, (*I));
3432 TypeString += " *";
3433 Name = TypeString + Name;
3434 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
3435 }
3436 // Next, emit a declaration for all "by copy" declarations.
3437 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
3438 E = BlockByCopyDecls.end(); I != E; ++I) {
3439 S += " ";
3440 // Handle nested closure invocation. For example:
3441 //
3442 // void (^myImportedClosure)(void);
3443 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
3444 //
3445 // void (^anotherClosure)(void);
3446 // anotherClosure = ^(void) {
3447 // myImportedClosure(); // import and invoke the closure
3448 // };
3449 //
3450 if (isTopLevelBlockPointerType((*I)->getType())) {
3451 RewriteBlockPointerTypeVariable(S, (*I));
3452 S += " = (";
3453 RewriteBlockPointerType(S, (*I)->getType());
3454 S += ")";
3455 S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
3456 }
3457 else {
3458 std::string Name = (*I)->getNameAsString();
3459 QualType QT = (*I)->getType();
3460 if (HasLocalVariableExternalStorage(*I))
3461 QT = Context->getPointerType(QT);
3462 QT.getAsStringInternal(Name, Context->getPrintingPolicy());
3463 S += Name + " = __cself->" +
3464 (*I)->getNameAsString() + "; // bound by copy\n";
3465 }
3466 }
3467 std::string RewrittenStr = RewrittenBlockExprs[CE];
3468 const char *cstr = RewrittenStr.c_str();
3469 while (*cstr++ != '{') ;
3470 S += cstr;
3471 S += "\n";
3472 return S;
3473}
3474
3475std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
3476 StringRef funcName,
3477 std::string Tag) {
3478 std::string StructRef = "struct " + Tag;
3479 std::string S = "static void __";
3480
3481 S += funcName;
3482 S += "_block_copy_" + utostr(i);
3483 S += "(" + StructRef;
3484 S += "*dst, " + StructRef;
3485 S += "*src) {";
3486 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
3487 E = ImportedBlockDecls.end(); I != E; ++I) {
3488 ValueDecl *VD = (*I);
3489 S += "_Block_object_assign((void*)&dst->";
3490 S += (*I)->getNameAsString();
3491 S += ", (void*)src->";
3492 S += (*I)->getNameAsString();
3493 if (BlockByRefDeclsPtrSet.count((*I)))
3494 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
3495 else if (VD->getType()->isBlockPointerType())
3496 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
3497 else
3498 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
3499 }
3500 S += "}\n";
3501
3502 S += "\nstatic void __";
3503 S += funcName;
3504 S += "_block_dispose_" + utostr(i);
3505 S += "(" + StructRef;
3506 S += "*src) {";
3507 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
3508 E = ImportedBlockDecls.end(); I != E; ++I) {
3509 ValueDecl *VD = (*I);
3510 S += "_Block_object_dispose((void*)src->";
3511 S += (*I)->getNameAsString();
3512 if (BlockByRefDeclsPtrSet.count((*I)))
3513 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
3514 else if (VD->getType()->isBlockPointerType())
3515 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
3516 else
3517 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
3518 }
3519 S += "}\n";
3520 return S;
3521}
3522
3523std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
3524 std::string Desc) {
3525 std::string S = "\nstruct " + Tag;
3526 std::string Constructor = " " + Tag;
3527
3528 S += " {\n struct __block_impl impl;\n";
3529 S += " struct " + Desc;
3530 S += "* Desc;\n";
3531
3532 Constructor += "(void *fp, "; // Invoke function pointer.
3533 Constructor += "struct " + Desc; // Descriptor pointer.
3534 Constructor += " *desc";
3535
3536 if (BlockDeclRefs.size()) {
3537 // Output all "by copy" declarations.
3538 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
3539 E = BlockByCopyDecls.end(); I != E; ++I) {
3540 S += " ";
3541 std::string FieldName = (*I)->getNameAsString();
3542 std::string ArgName = "_" + FieldName;
3543 // Handle nested closure invocation. For example:
3544 //
3545 // void (^myImportedBlock)(void);
3546 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
3547 //
3548 // void (^anotherBlock)(void);
3549 // anotherBlock = ^(void) {
3550 // myImportedBlock(); // import and invoke the closure
3551 // };
3552 //
3553 if (isTopLevelBlockPointerType((*I)->getType())) {
3554 S += "struct __block_impl *";
3555 Constructor += ", void *" + ArgName;
3556 } else {
3557 QualType QT = (*I)->getType();
3558 if (HasLocalVariableExternalStorage(*I))
3559 QT = Context->getPointerType(QT);
3560 QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
3561 QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
3562 Constructor += ", " + ArgName;
3563 }
3564 S += FieldName + ";\n";
3565 }
3566 // Output all "by ref" declarations.
3567 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
3568 E = BlockByRefDecls.end(); I != E; ++I) {
3569 S += " ";
3570 std::string FieldName = (*I)->getNameAsString();
3571 std::string ArgName = "_" + FieldName;
3572 {
3573 std::string TypeString;
3574 RewriteByRefString(TypeString, FieldName, (*I));
3575 TypeString += " *";
3576 FieldName = TypeString + FieldName;
3577 ArgName = TypeString + ArgName;
3578 Constructor += ", " + ArgName;
3579 }
3580 S += FieldName + "; // by ref\n";
3581 }
3582 // Finish writing the constructor.
3583 Constructor += ", int flags=0)";
3584 // Initialize all "by copy" arguments.
3585 bool firsTime = true;
3586 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
3587 E = BlockByCopyDecls.end(); I != E; ++I) {
3588 std::string Name = (*I)->getNameAsString();
3589 if (firsTime) {
3590 Constructor += " : ";
3591 firsTime = false;
3592 }
3593 else
3594 Constructor += ", ";
3595 if (isTopLevelBlockPointerType((*I)->getType()))
3596 Constructor += Name + "((struct __block_impl *)_" + Name + ")";
3597 else
3598 Constructor += Name + "(_" + Name + ")";
3599 }
3600 // Initialize all "by ref" arguments.
3601 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
3602 E = BlockByRefDecls.end(); I != E; ++I) {
3603 std::string Name = (*I)->getNameAsString();
3604 if (firsTime) {
3605 Constructor += " : ";
3606 firsTime = false;
3607 }
3608 else
3609 Constructor += ", ";
3610 Constructor += Name + "(_" + Name + "->__forwarding)";
3611 }
3612
3613 Constructor += " {\n";
3614 if (GlobalVarDecl)
3615 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
3616 else
3617 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
3618 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3619
3620 Constructor += " Desc = desc;\n";
3621 } else {
3622 // Finish writing the constructor.
3623 Constructor += ", int flags=0) {\n";
3624 if (GlobalVarDecl)
3625 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
3626 else
3627 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
3628 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3629 Constructor += " Desc = desc;\n";
3630 }
3631 Constructor += " ";
3632 Constructor += "}\n";
3633 S += Constructor;
3634 S += "};\n";
3635 return S;
3636}
3637
3638std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
3639 std::string ImplTag, int i,
3640 StringRef FunName,
3641 unsigned hasCopy) {
3642 std::string S = "\nstatic struct " + DescTag;
3643
3644 S += " {\n unsigned long reserved;\n";
3645 S += " unsigned long Block_size;\n";
3646 if (hasCopy) {
3647 S += " void (*copy)(struct ";
3648 S += ImplTag; S += "*, struct ";
3649 S += ImplTag; S += "*);\n";
3650
3651 S += " void (*dispose)(struct ";
3652 S += ImplTag; S += "*);\n";
3653 }
3654 S += "} ";
3655
3656 S += DescTag + "_DATA = { 0, sizeof(struct ";
3657 S += ImplTag + ")";
3658 if (hasCopy) {
3659 S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
3660 S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
3661 }
3662 S += "};\n";
3663 return S;
3664}
3665
3666void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
3667 StringRef FunName) {
3668 // Insert declaration for the function in which block literal is used.
3669 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3670 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3671 bool RewriteSC = (GlobalVarDecl &&
3672 !Blocks.empty() &&
3673 GlobalVarDecl->getStorageClass() == SC_Static &&
3674 GlobalVarDecl->getType().getCVRQualifiers());
3675 if (RewriteSC) {
3676 std::string SC(" void __");
3677 SC += GlobalVarDecl->getNameAsString();
3678 SC += "() {}";
3679 InsertText(FunLocStart, SC);
3680 }
3681
3682 // Insert closures that were part of the function.
3683 for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
3684 CollectBlockDeclRefInfo(Blocks[i]);
3685 // Need to copy-in the inner copied-in variables not actually used in this
3686 // block.
3687 for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
John McCallf4b88a42012-03-10 09:33:50 +00003688 DeclRefExpr *Exp = InnerDeclRefs[count++];
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003689 ValueDecl *VD = Exp->getDecl();
3690 BlockDeclRefs.push_back(Exp);
John McCallf4b88a42012-03-10 09:33:50 +00003691 if (!VD->hasAttr<BlocksAttr>()) {
3692 if (!BlockByCopyDeclsPtrSet.count(VD)) {
3693 BlockByCopyDeclsPtrSet.insert(VD);
3694 BlockByCopyDecls.push_back(VD);
3695 }
3696 continue;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003697 }
John McCallf4b88a42012-03-10 09:33:50 +00003698
3699 if (!BlockByRefDeclsPtrSet.count(VD)) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003700 BlockByRefDeclsPtrSet.insert(VD);
3701 BlockByRefDecls.push_back(VD);
3702 }
John McCallf4b88a42012-03-10 09:33:50 +00003703
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003704 // imported objects in the inner blocks not used in the outer
3705 // blocks must be copied/disposed in the outer block as well.
John McCallf4b88a42012-03-10 09:33:50 +00003706 if (VD->getType()->isObjCObjectPointerType() ||
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003707 VD->getType()->isBlockPointerType())
3708 ImportedBlockDecls.insert(VD);
3709 }
3710
3711 std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
3712 std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
3713
3714 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3715
3716 InsertText(FunLocStart, CI);
3717
3718 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3719
3720 InsertText(FunLocStart, CF);
3721
3722 if (ImportedBlockDecls.size()) {
3723 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3724 InsertText(FunLocStart, HF);
3725 }
3726 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3727 ImportedBlockDecls.size() > 0);
3728 InsertText(FunLocStart, BD);
3729
3730 BlockDeclRefs.clear();
3731 BlockByRefDecls.clear();
3732 BlockByRefDeclsPtrSet.clear();
3733 BlockByCopyDecls.clear();
3734 BlockByCopyDeclsPtrSet.clear();
3735 ImportedBlockDecls.clear();
3736 }
3737 if (RewriteSC) {
3738 // Must insert any 'const/volatile/static here. Since it has been
3739 // removed as result of rewriting of block literals.
3740 std::string SC;
3741 if (GlobalVarDecl->getStorageClass() == SC_Static)
3742 SC = "static ";
3743 if (GlobalVarDecl->getType().isConstQualified())
3744 SC += "const ";
3745 if (GlobalVarDecl->getType().isVolatileQualified())
3746 SC += "volatile ";
3747 if (GlobalVarDecl->getType().isRestrictQualified())
3748 SC += "restrict ";
3749 InsertText(FunLocStart, SC);
3750 }
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +00003751 if (GlobalConstructionExp) {
3752 // extra fancy dance for global literal expression.
3753
3754 // Always the latest block expression on the block stack.
3755 std::string Tag = "__";
3756 Tag += FunName;
3757 Tag += "_block_impl_";
3758 Tag += utostr(Blocks.size()-1);
3759 std::string globalBuf = "static ";
3760 globalBuf += Tag; globalBuf += " ";
3761 std::string SStr;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003762
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +00003763 llvm::raw_string_ostream constructorExprBuf(SStr);
3764 GlobalConstructionExp->printPretty(constructorExprBuf, *Context, 0,
3765 PrintingPolicy(LangOpts));
3766 globalBuf += constructorExprBuf.str();
3767 globalBuf += ";\n";
3768 InsertText(FunLocStart, globalBuf);
3769 GlobalConstructionExp = 0;
3770 }
3771
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003772 Blocks.clear();
3773 InnerDeclRefsCount.clear();
3774 InnerDeclRefs.clear();
3775 RewrittenBlockExprs.clear();
3776}
3777
3778void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
3779 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
3780 StringRef FuncName = FD->getName();
3781
3782 SynthesizeBlockLiterals(FunLocStart, FuncName);
3783}
3784
3785static void BuildUniqueMethodName(std::string &Name,
3786 ObjCMethodDecl *MD) {
3787 ObjCInterfaceDecl *IFace = MD->getClassInterface();
3788 Name = IFace->getName();
3789 Name += "__" + MD->getSelector().getAsString();
3790 // Convert colons to underscores.
3791 std::string::size_type loc = 0;
3792 while ((loc = Name.find(":", loc)) != std::string::npos)
3793 Name.replace(loc, 1, "_");
3794}
3795
3796void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
3797 //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
3798 //SourceLocation FunLocStart = MD->getLocStart();
3799 SourceLocation FunLocStart = MD->getLocStart();
3800 std::string FuncName;
3801 BuildUniqueMethodName(FuncName, MD);
3802 SynthesizeBlockLiterals(FunLocStart, FuncName);
3803}
3804
3805void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
3806 for (Stmt::child_range CI = S->children(); CI; ++CI)
3807 if (*CI) {
3808 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
3809 GetBlockDeclRefExprs(CBE->getBody());
3810 else
3811 GetBlockDeclRefExprs(*CI);
3812 }
3813 // Handle specific things.
John McCallf4b88a42012-03-10 09:33:50 +00003814 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
3815 if (DRE->refersToEnclosingLocal() &&
3816 HasLocalVariableExternalStorage(DRE->getDecl())) {
3817 BlockDeclRefs.push_back(DRE);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003818 }
3819
3820 return;
3821}
3822
3823void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
John McCallf4b88a42012-03-10 09:33:50 +00003824 SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003825 llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
3826 for (Stmt::child_range CI = S->children(); CI; ++CI)
3827 if (*CI) {
3828 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
3829 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3830 GetInnerBlockDeclRefExprs(CBE->getBody(),
3831 InnerBlockDeclRefs,
3832 InnerContexts);
3833 }
3834 else
3835 GetInnerBlockDeclRefExprs(*CI,
3836 InnerBlockDeclRefs,
3837 InnerContexts);
3838
3839 }
3840 // Handle specific things.
John McCallf4b88a42012-03-10 09:33:50 +00003841 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3842 if (DRE->refersToEnclosingLocal()) {
3843 if (!isa<FunctionDecl>(DRE->getDecl()) &&
3844 !InnerContexts.count(DRE->getDecl()->getDeclContext()))
3845 InnerBlockDeclRefs.push_back(DRE);
3846 if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
3847 if (Var->isFunctionOrMethodVarDecl())
3848 ImportedLocalExternalDecls.insert(Var);
3849 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003850 }
3851
3852 return;
3853}
3854
Fariborz Jahanian164d6f82012-02-13 18:57:49 +00003855/// convertObjCTypeToCStyleType - This routine converts such objc types
3856/// as qualified objects, and blocks to their closest c/c++ types that
3857/// it can. It returns true if input type was modified.
3858bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {
3859 QualType oldT = T;
3860 convertBlockPointerToFunctionPointer(T);
3861 if (T->isFunctionPointerType()) {
3862 QualType PointeeTy;
3863 if (const PointerType* PT = T->getAs<PointerType>()) {
3864 PointeeTy = PT->getPointeeType();
3865 if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
3866 T = convertFunctionTypeOfBlocks(FT);
3867 T = Context->getPointerType(T);
3868 }
3869 }
3870 }
3871
3872 convertToUnqualifiedObjCType(T);
3873 return T != oldT;
3874}
3875
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003876/// convertFunctionTypeOfBlocks - This routine converts a function type
3877/// whose result type may be a block pointer or whose argument type(s)
3878/// might be block pointers to an equivalent function type replacing
3879/// all block pointers to function pointers.
3880QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
3881 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
3882 // FTP will be null for closures that don't take arguments.
3883 // Generate a funky cast.
3884 SmallVector<QualType, 8> ArgTypes;
3885 QualType Res = FT->getResultType();
Fariborz Jahanian164d6f82012-02-13 18:57:49 +00003886 bool modified = convertObjCTypeToCStyleType(Res);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003887
3888 if (FTP) {
3889 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
3890 E = FTP->arg_type_end(); I && (I != E); ++I) {
3891 QualType t = *I;
3892 // Make sure we convert "t (^)(...)" to "t (*)(...)".
Fariborz Jahanian164d6f82012-02-13 18:57:49 +00003893 if (convertObjCTypeToCStyleType(t))
3894 modified = true;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003895 ArgTypes.push_back(t);
3896 }
3897 }
3898 QualType FuncType;
Fariborz Jahanian164d6f82012-02-13 18:57:49 +00003899 if (modified)
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003900 FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size());
3901 else FuncType = QualType(FT, 0);
3902 return FuncType;
3903}
3904
3905Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
3906 // Navigate to relevant type information.
3907 const BlockPointerType *CPT = 0;
3908
3909 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3910 CPT = DRE->getType()->getAs<BlockPointerType>();
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00003911 } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3912 CPT = MExpr->getType()->getAs<BlockPointerType>();
3913 }
3914 else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3915 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3916 }
3917 else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3918 CPT = IEXPR->getType()->getAs<BlockPointerType>();
3919 else if (const ConditionalOperator *CEXPR =
3920 dyn_cast<ConditionalOperator>(BlockExp)) {
3921 Expr *LHSExp = CEXPR->getLHS();
3922 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3923 Expr *RHSExp = CEXPR->getRHS();
3924 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3925 Expr *CONDExp = CEXPR->getCond();
3926 ConditionalOperator *CondExpr =
3927 new (Context) ConditionalOperator(CONDExp,
3928 SourceLocation(), cast<Expr>(LHSStmt),
3929 SourceLocation(), cast<Expr>(RHSStmt),
3930 Exp->getType(), VK_RValue, OK_Ordinary);
3931 return CondExpr;
3932 } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3933 CPT = IRE->getType()->getAs<BlockPointerType>();
3934 } else if (const PseudoObjectExpr *POE
3935 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3936 CPT = POE->getType()->castAs<BlockPointerType>();
3937 } else {
3938 assert(1 && "RewriteBlockClass: Bad type");
3939 }
3940 assert(CPT && "RewriteBlockClass: Bad type");
3941 const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
3942 assert(FT && "RewriteBlockClass: Bad type");
3943 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
3944 // FTP will be null for closures that don't take arguments.
3945
3946 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
3947 SourceLocation(), SourceLocation(),
3948 &Context->Idents.get("__block_impl"));
3949 QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
3950
3951 // Generate a funky cast.
3952 SmallVector<QualType, 8> ArgTypes;
3953
3954 // Push the block argument type.
3955 ArgTypes.push_back(PtrBlock);
3956 if (FTP) {
3957 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
3958 E = FTP->arg_type_end(); I && (I != E); ++I) {
3959 QualType t = *I;
3960 // Make sure we convert "t (^)(...)" to "t (*)(...)".
3961 if (!convertBlockPointerToFunctionPointer(t))
3962 convertToUnqualifiedObjCType(t);
3963 ArgTypes.push_back(t);
3964 }
3965 }
3966 // Now do the pointer to function cast.
3967 QualType PtrToFuncCastType
3968 = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size());
3969
3970 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
3971
3972 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3973 CK_BitCast,
3974 const_cast<Expr*>(BlockExp));
3975 // Don't forget the parens to enforce the proper binding.
3976 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
3977 BlkCast);
3978 //PE->dump();
3979
3980 FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
3981 SourceLocation(),
3982 &Context->Idents.get("FuncPtr"),
3983 Context->VoidPtrTy, 0,
3984 /*BitWidth=*/0, /*Mutable=*/true,
3985 /*HasInit=*/false);
3986 MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
3987 FD->getType(), VK_LValue,
3988 OK_Ordinary);
3989
3990
3991 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3992 CK_BitCast, ME);
3993 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
3994
3995 SmallVector<Expr*, 8> BlkExprs;
3996 // Add the implicit argument.
3997 BlkExprs.push_back(BlkCast);
3998 // Add the user arguments.
3999 for (CallExpr::arg_iterator I = Exp->arg_begin(),
4000 E = Exp->arg_end(); I != E; ++I) {
4001 BlkExprs.push_back(*I);
4002 }
4003 CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0],
4004 BlkExprs.size(),
4005 Exp->getType(), VK_RValue,
4006 SourceLocation());
4007 return CE;
4008}
4009
4010// We need to return the rewritten expression to handle cases where the
John McCallf4b88a42012-03-10 09:33:50 +00004011// DeclRefExpr is embedded in another expression being rewritten.
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004012// For example:
4013//
4014// int main() {
4015// __block Foo *f;
4016// __block int i;
4017//
4018// void (^myblock)() = ^() {
John McCallf4b88a42012-03-10 09:33:50 +00004019// [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004020// i = 77;
4021// };
4022//}
John McCallf4b88a42012-03-10 09:33:50 +00004023Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004024 // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
4025 // for each DeclRefExp where BYREFVAR is name of the variable.
John McCallf4b88a42012-03-10 09:33:50 +00004026 ValueDecl *VD = DeclRefExp->getDecl();
4027 bool isArrow = DeclRefExp->refersToEnclosingLocal();
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004028
4029 FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
4030 SourceLocation(),
4031 &Context->Idents.get("__forwarding"),
4032 Context->VoidPtrTy, 0,
4033 /*BitWidth=*/0, /*Mutable=*/true,
4034 /*HasInit=*/false);
4035 MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
4036 FD, SourceLocation(),
4037 FD->getType(), VK_LValue,
4038 OK_Ordinary);
4039
4040 StringRef Name = VD->getName();
4041 FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
4042 &Context->Idents.get(Name),
4043 Context->VoidPtrTy, 0,
4044 /*BitWidth=*/0, /*Mutable=*/true,
4045 /*HasInit=*/false);
4046 ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
4047 DeclRefExp->getType(), VK_LValue, OK_Ordinary);
4048
4049
4050
4051 // Need parens to enforce precedence.
4052 ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
4053 DeclRefExp->getExprLoc(),
4054 ME);
4055 ReplaceStmt(DeclRefExp, PE);
4056 return PE;
4057}
4058
4059// Rewrites the imported local variable V with external storage
4060// (static, extern, etc.) as *V
4061//
4062Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
4063 ValueDecl *VD = DRE->getDecl();
4064 if (VarDecl *Var = dyn_cast<VarDecl>(VD))
4065 if (!ImportedLocalExternalDecls.count(Var))
4066 return DRE;
4067 Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
4068 VK_LValue, OK_Ordinary,
4069 DRE->getLocation());
4070 // Need parens to enforce precedence.
4071 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
4072 Exp);
4073 ReplaceStmt(DRE, PE);
4074 return PE;
4075}
4076
4077void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {
4078 SourceLocation LocStart = CE->getLParenLoc();
4079 SourceLocation LocEnd = CE->getRParenLoc();
4080
4081 // Need to avoid trying to rewrite synthesized casts.
4082 if (LocStart.isInvalid())
4083 return;
4084 // Need to avoid trying to rewrite casts contained in macros.
4085 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
4086 return;
4087
4088 const char *startBuf = SM->getCharacterData(LocStart);
4089 const char *endBuf = SM->getCharacterData(LocEnd);
4090 QualType QT = CE->getType();
4091 const Type* TypePtr = QT->getAs<Type>();
4092 if (isa<TypeOfExprType>(TypePtr)) {
4093 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
4094 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
4095 std::string TypeAsString = "(";
4096 RewriteBlockPointerType(TypeAsString, QT);
4097 TypeAsString += ")";
4098 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
4099 return;
4100 }
4101 // advance the location to startArgList.
4102 const char *argPtr = startBuf;
4103
4104 while (*argPtr++ && (argPtr < endBuf)) {
4105 switch (*argPtr) {
4106 case '^':
4107 // Replace the '^' with '*'.
4108 LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
4109 ReplaceText(LocStart, 1, "*");
4110 break;
4111 }
4112 }
4113 return;
4114}
4115
4116void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
4117 SourceLocation DeclLoc = FD->getLocation();
4118 unsigned parenCount = 0;
4119
4120 // We have 1 or more arguments that have closure pointers.
4121 const char *startBuf = SM->getCharacterData(DeclLoc);
4122 const char *startArgList = strchr(startBuf, '(');
4123
4124 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
4125
4126 parenCount++;
4127 // advance the location to startArgList.
4128 DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
4129 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
4130
4131 const char *argPtr = startArgList;
4132
4133 while (*argPtr++ && parenCount) {
4134 switch (*argPtr) {
4135 case '^':
4136 // Replace the '^' with '*'.
4137 DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
4138 ReplaceText(DeclLoc, 1, "*");
4139 break;
4140 case '(':
4141 parenCount++;
4142 break;
4143 case ')':
4144 parenCount--;
4145 break;
4146 }
4147 }
4148 return;
4149}
4150
4151bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
4152 const FunctionProtoType *FTP;
4153 const PointerType *PT = QT->getAs<PointerType>();
4154 if (PT) {
4155 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
4156 } else {
4157 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
4158 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
4159 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
4160 }
4161 if (FTP) {
4162 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
4163 E = FTP->arg_type_end(); I != E; ++I)
4164 if (isTopLevelBlockPointerType(*I))
4165 return true;
4166 }
4167 return false;
4168}
4169
4170bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
4171 const FunctionProtoType *FTP;
4172 const PointerType *PT = QT->getAs<PointerType>();
4173 if (PT) {
4174 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
4175 } else {
4176 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
4177 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
4178 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
4179 }
4180 if (FTP) {
4181 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
4182 E = FTP->arg_type_end(); I != E; ++I) {
4183 if ((*I)->isObjCQualifiedIdType())
4184 return true;
4185 if ((*I)->isObjCObjectPointerType() &&
4186 (*I)->getPointeeType()->isObjCQualifiedInterfaceType())
4187 return true;
4188 }
4189
4190 }
4191 return false;
4192}
4193
4194void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
4195 const char *&RParen) {
4196 const char *argPtr = strchr(Name, '(');
4197 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
4198
4199 LParen = argPtr; // output the start.
4200 argPtr++; // skip past the left paren.
4201 unsigned parenCount = 1;
4202
4203 while (*argPtr && parenCount) {
4204 switch (*argPtr) {
4205 case '(': parenCount++; break;
4206 case ')': parenCount--; break;
4207 default: break;
4208 }
4209 if (parenCount) argPtr++;
4210 }
4211 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
4212 RParen = argPtr; // output the end
4213}
4214
4215void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
4216 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
4217 RewriteBlockPointerFunctionArgs(FD);
4218 return;
4219 }
4220 // Handle Variables and Typedefs.
4221 SourceLocation DeclLoc = ND->getLocation();
4222 QualType DeclT;
4223 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
4224 DeclT = VD->getType();
4225 else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
4226 DeclT = TDD->getUnderlyingType();
4227 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4228 DeclT = FD->getType();
4229 else
4230 llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
4231
4232 const char *startBuf = SM->getCharacterData(DeclLoc);
4233 const char *endBuf = startBuf;
4234 // scan backward (from the decl location) for the end of the previous decl.
4235 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
4236 startBuf--;
4237 SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
4238 std::string buf;
4239 unsigned OrigLength=0;
4240 // *startBuf != '^' if we are dealing with a pointer to function that
4241 // may take block argument types (which will be handled below).
4242 if (*startBuf == '^') {
4243 // Replace the '^' with '*', computing a negative offset.
4244 buf = '*';
4245 startBuf++;
4246 OrigLength++;
4247 }
4248 while (*startBuf != ')') {
4249 buf += *startBuf;
4250 startBuf++;
4251 OrigLength++;
4252 }
4253 buf += ')';
4254 OrigLength++;
4255
4256 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4257 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4258 // Replace the '^' with '*' for arguments.
4259 // Replace id<P> with id/*<>*/
4260 DeclLoc = ND->getLocation();
4261 startBuf = SM->getCharacterData(DeclLoc);
4262 const char *argListBegin, *argListEnd;
4263 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4264 while (argListBegin < argListEnd) {
4265 if (*argListBegin == '^')
4266 buf += '*';
4267 else if (*argListBegin == '<') {
4268 buf += "/*";
4269 buf += *argListBegin++;
4270 OrigLength++;;
4271 while (*argListBegin != '>') {
4272 buf += *argListBegin++;
4273 OrigLength++;
4274 }
4275 buf += *argListBegin;
4276 buf += "*/";
4277 }
4278 else
4279 buf += *argListBegin;
4280 argListBegin++;
4281 OrigLength++;
4282 }
4283 buf += ')';
4284 OrigLength++;
4285 }
4286 ReplaceText(Start, OrigLength, buf);
4287
4288 return;
4289}
4290
4291
4292/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
4293/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
4294/// struct Block_byref_id_object *src) {
4295/// _Block_object_assign (&_dest->object, _src->object,
4296/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4297/// [|BLOCK_FIELD_IS_WEAK]) // object
4298/// _Block_object_assign(&_dest->object, _src->object,
4299/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4300/// [|BLOCK_FIELD_IS_WEAK]) // block
4301/// }
4302/// And:
4303/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
4304/// _Block_object_dispose(_src->object,
4305/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4306/// [|BLOCK_FIELD_IS_WEAK]) // object
4307/// _Block_object_dispose(_src->object,
4308/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4309/// [|BLOCK_FIELD_IS_WEAK]) // block
4310/// }
4311
4312std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
4313 int flag) {
4314 std::string S;
4315 if (CopyDestroyCache.count(flag))
4316 return S;
4317 CopyDestroyCache.insert(flag);
4318 S = "static void __Block_byref_id_object_copy_";
4319 S += utostr(flag);
4320 S += "(void *dst, void *src) {\n";
4321
4322 // offset into the object pointer is computed as:
4323 // void * + void* + int + int + void* + void *
4324 unsigned IntSize =
4325 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4326 unsigned VoidPtrSize =
4327 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
4328
4329 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
4330 S += " _Block_object_assign((char*)dst + ";
4331 S += utostr(offset);
4332 S += ", *(void * *) ((char*)src + ";
4333 S += utostr(offset);
4334 S += "), ";
4335 S += utostr(flag);
4336 S += ");\n}\n";
4337
4338 S += "static void __Block_byref_id_object_dispose_";
4339 S += utostr(flag);
4340 S += "(void *src) {\n";
4341 S += " _Block_object_dispose(*(void * *) ((char*)src + ";
4342 S += utostr(offset);
4343 S += "), ";
4344 S += utostr(flag);
4345 S += ");\n}\n";
4346 return S;
4347}
4348
4349/// RewriteByRefVar - For each __block typex ND variable this routine transforms
4350/// the declaration into:
4351/// struct __Block_byref_ND {
4352/// void *__isa; // NULL for everything except __weak pointers
4353/// struct __Block_byref_ND *__forwarding;
4354/// int32_t __flags;
4355/// int32_t __size;
4356/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
4357/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
4358/// typex ND;
4359/// };
4360///
4361/// It then replaces declaration of ND variable with:
4362/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
4363/// __size=sizeof(struct __Block_byref_ND),
4364/// ND=initializer-if-any};
4365///
4366///
4367void RewriteModernObjC::RewriteByRefVar(VarDecl *ND) {
4368 // Insert declaration for the function in which block literal is
4369 // used.
4370 if (CurFunctionDeclToDeclareForBlock)
4371 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4372 int flag = 0;
4373 int isa = 0;
4374 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
4375 if (DeclLoc.isInvalid())
4376 // If type location is missing, it is because of missing type (a warning).
4377 // Use variable's location which is good for this case.
4378 DeclLoc = ND->getLocation();
4379 const char *startBuf = SM->getCharacterData(DeclLoc);
4380 SourceLocation X = ND->getLocEnd();
4381 X = SM->getExpansionLoc(X);
4382 const char *endBuf = SM->getCharacterData(X);
4383 std::string Name(ND->getNameAsString());
4384 std::string ByrefType;
4385 RewriteByRefString(ByrefType, Name, ND, true);
4386 ByrefType += " {\n";
4387 ByrefType += " void *__isa;\n";
4388 RewriteByRefString(ByrefType, Name, ND);
4389 ByrefType += " *__forwarding;\n";
4390 ByrefType += " int __flags;\n";
4391 ByrefType += " int __size;\n";
4392 // Add void *__Block_byref_id_object_copy;
4393 // void *__Block_byref_id_object_dispose; if needed.
4394 QualType Ty = ND->getType();
4395 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
4396 if (HasCopyAndDispose) {
4397 ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
4398 ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
4399 }
4400
4401 QualType T = Ty;
4402 (void)convertBlockPointerToFunctionPointer(T);
4403 T.getAsStringInternal(Name, Context->getPrintingPolicy());
4404
4405 ByrefType += " " + Name + ";\n";
4406 ByrefType += "};\n";
4407 // Insert this type in global scope. It is needed by helper function.
4408 SourceLocation FunLocStart;
4409 if (CurFunctionDef)
4410 FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
4411 else {
4412 assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
4413 FunLocStart = CurMethodDef->getLocStart();
4414 }
4415 InsertText(FunLocStart, ByrefType);
4416 if (Ty.isObjCGCWeak()) {
4417 flag |= BLOCK_FIELD_IS_WEAK;
4418 isa = 1;
4419 }
4420
4421 if (HasCopyAndDispose) {
4422 flag = BLOCK_BYREF_CALLER;
4423 QualType Ty = ND->getType();
4424 // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
4425 if (Ty->isBlockPointerType())
4426 flag |= BLOCK_FIELD_IS_BLOCK;
4427 else
4428 flag |= BLOCK_FIELD_IS_OBJECT;
4429 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4430 if (!HF.empty())
4431 InsertText(FunLocStart, HF);
4432 }
4433
4434 // struct __Block_byref_ND ND =
4435 // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
4436 // initializer-if-any};
4437 bool hasInit = (ND->getInit() != 0);
4438 unsigned flags = 0;
4439 if (HasCopyAndDispose)
4440 flags |= BLOCK_HAS_COPY_DISPOSE;
4441 Name = ND->getNameAsString();
4442 ByrefType.clear();
4443 RewriteByRefString(ByrefType, Name, ND);
4444 std::string ForwardingCastType("(");
4445 ForwardingCastType += ByrefType + " *)";
4446 if (!hasInit) {
4447 ByrefType += " " + Name + " = {(void*)";
4448 ByrefType += utostr(isa);
4449 ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
4450 ByrefType += utostr(flags);
4451 ByrefType += ", ";
4452 ByrefType += "sizeof(";
4453 RewriteByRefString(ByrefType, Name, ND);
4454 ByrefType += ")";
4455 if (HasCopyAndDispose) {
4456 ByrefType += ", __Block_byref_id_object_copy_";
4457 ByrefType += utostr(flag);
4458 ByrefType += ", __Block_byref_id_object_dispose_";
4459 ByrefType += utostr(flag);
4460 }
4461 ByrefType += "};\n";
4462 unsigned nameSize = Name.size();
4463 // for block or function pointer declaration. Name is aleady
4464 // part of the declaration.
4465 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
4466 nameSize = 1;
4467 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4468 }
4469 else {
4470 SourceLocation startLoc;
4471 Expr *E = ND->getInit();
4472 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
4473 startLoc = ECE->getLParenLoc();
4474 else
4475 startLoc = E->getLocStart();
4476 startLoc = SM->getExpansionLoc(startLoc);
4477 endBuf = SM->getCharacterData(startLoc);
4478 ByrefType += " " + Name;
4479 ByrefType += " = {(void*)";
4480 ByrefType += utostr(isa);
4481 ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
4482 ByrefType += utostr(flags);
4483 ByrefType += ", ";
4484 ByrefType += "sizeof(";
4485 RewriteByRefString(ByrefType, Name, ND);
4486 ByrefType += "), ";
4487 if (HasCopyAndDispose) {
4488 ByrefType += "__Block_byref_id_object_copy_";
4489 ByrefType += utostr(flag);
4490 ByrefType += ", __Block_byref_id_object_dispose_";
4491 ByrefType += utostr(flag);
4492 ByrefType += ", ";
4493 }
4494 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4495
4496 // Complete the newly synthesized compound expression by inserting a right
4497 // curly brace before the end of the declaration.
4498 // FIXME: This approach avoids rewriting the initializer expression. It
4499 // also assumes there is only one declarator. For example, the following
4500 // isn't currently supported by this routine (in general):
4501 //
4502 // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
4503 //
4504 const char *startInitializerBuf = SM->getCharacterData(startLoc);
4505 const char *semiBuf = strchr(startInitializerBuf, ';');
4506 assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
4507 SourceLocation semiLoc =
4508 startLoc.getLocWithOffset(semiBuf-startInitializerBuf);
4509
4510 InsertText(semiLoc, "}");
4511 }
4512 return;
4513}
4514
4515void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
4516 // Add initializers for any closure decl refs.
4517 GetBlockDeclRefExprs(Exp->getBody());
4518 if (BlockDeclRefs.size()) {
4519 // Unique all "by copy" declarations.
4520 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
John McCallf4b88a42012-03-10 09:33:50 +00004521 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004522 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4523 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4524 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4525 }
4526 }
4527 // Unique all "by ref" declarations.
4528 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
John McCallf4b88a42012-03-10 09:33:50 +00004529 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004530 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4531 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4532 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4533 }
4534 }
4535 // Find any imported blocks...they will need special attention.
4536 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
John McCallf4b88a42012-03-10 09:33:50 +00004537 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004538 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4539 BlockDeclRefs[i]->getType()->isBlockPointerType())
4540 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4541 }
4542}
4543
4544FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {
4545 IdentifierInfo *ID = &Context->Idents.get(name);
4546 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
4547 return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
4548 SourceLocation(), ID, FType, 0, SC_Extern,
4549 SC_None, false, false);
4550}
4551
4552Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
John McCallf4b88a42012-03-10 09:33:50 +00004553 const SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs) {
Fariborz Jahaniand13c2c22012-03-22 19:54:39 +00004554
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004555 const BlockDecl *block = Exp->getBlockDecl();
Fariborz Jahaniand13c2c22012-03-22 19:54:39 +00004556
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004557 Blocks.push_back(Exp);
4558
4559 CollectBlockDeclRefInfo(Exp);
4560
4561 // Add inner imported variables now used in current block.
4562 int countOfInnerDecls = 0;
4563 if (!InnerBlockDeclRefs.empty()) {
4564 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
John McCallf4b88a42012-03-10 09:33:50 +00004565 DeclRefExpr *Exp = InnerBlockDeclRefs[i];
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004566 ValueDecl *VD = Exp->getDecl();
John McCallf4b88a42012-03-10 09:33:50 +00004567 if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004568 // We need to save the copied-in variables in nested
4569 // blocks because it is needed at the end for some of the API generations.
4570 // See SynthesizeBlockLiterals routine.
4571 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4572 BlockDeclRefs.push_back(Exp);
4573 BlockByCopyDeclsPtrSet.insert(VD);
4574 BlockByCopyDecls.push_back(VD);
4575 }
John McCallf4b88a42012-03-10 09:33:50 +00004576 if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004577 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4578 BlockDeclRefs.push_back(Exp);
4579 BlockByRefDeclsPtrSet.insert(VD);
4580 BlockByRefDecls.push_back(VD);
4581 }
4582 }
4583 // Find any imported blocks...they will need special attention.
4584 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
John McCallf4b88a42012-03-10 09:33:50 +00004585 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004586 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4587 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
4588 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4589 }
4590 InnerDeclRefsCount.push_back(countOfInnerDecls);
4591
4592 std::string FuncName;
4593
4594 if (CurFunctionDef)
4595 FuncName = CurFunctionDef->getNameAsString();
4596 else if (CurMethodDef)
4597 BuildUniqueMethodName(FuncName, CurMethodDef);
4598 else if (GlobalVarDecl)
4599 FuncName = std::string(GlobalVarDecl->getNameAsString());
4600
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +00004601 bool GlobalBlockExpr =
4602 block->getDeclContext()->getRedeclContext()->isFileContext();
4603
4604 if (GlobalBlockExpr && !GlobalVarDecl) {
4605 Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
4606 GlobalBlockExpr = false;
4607 }
4608
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004609 std::string BlockNumber = utostr(Blocks.size()-1);
4610
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004611 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
4612
4613 // Get a pointer to the function type so we can cast appropriately.
4614 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
4615 QualType FType = Context->getPointerType(BFT);
4616
4617 FunctionDecl *FD;
4618 Expr *NewRep;
4619
4620 // Simulate a contructor call...
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +00004621 std::string Tag;
4622
4623 if (GlobalBlockExpr)
4624 Tag = "__global_";
4625 else
4626 Tag = "__";
4627 Tag += FuncName + "_block_impl_" + BlockNumber;
4628
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004629 FD = SynthBlockInitFunctionDecl(Tag);
John McCallf4b88a42012-03-10 09:33:50 +00004630 DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004631 SourceLocation());
4632
4633 SmallVector<Expr*, 4> InitExprs;
4634
4635 // Initialize the block function.
4636 FD = SynthBlockInitFunctionDecl(Func);
John McCallf4b88a42012-03-10 09:33:50 +00004637 DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(),
4638 VK_LValue, SourceLocation());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004639 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
4640 CK_BitCast, Arg);
4641 InitExprs.push_back(castExpr);
4642
4643 // Initialize the block descriptor.
4644 std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
4645
4646 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
4647 SourceLocation(), SourceLocation(),
4648 &Context->Idents.get(DescData.c_str()),
4649 Context->VoidPtrTy, 0,
4650 SC_Static, SC_None);
4651 UnaryOperator *DescRefExpr =
John McCallf4b88a42012-03-10 09:33:50 +00004652 new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004653 Context->VoidPtrTy,
4654 VK_LValue,
4655 SourceLocation()),
4656 UO_AddrOf,
4657 Context->getPointerType(Context->VoidPtrTy),
4658 VK_RValue, OK_Ordinary,
4659 SourceLocation());
4660 InitExprs.push_back(DescRefExpr);
4661
4662 // Add initializers for any closure decl refs.
4663 if (BlockDeclRefs.size()) {
4664 Expr *Exp;
4665 // Output all "by copy" declarations.
4666 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
4667 E = BlockByCopyDecls.end(); I != E; ++I) {
4668 if (isObjCType((*I)->getType())) {
4669 // FIXME: Conform to ABI ([[obj retain] autorelease]).
4670 FD = SynthBlockInitFunctionDecl((*I)->getName());
John McCallf4b88a42012-03-10 09:33:50 +00004671 Exp = new (Context) DeclRefExpr(FD, false, FD->getType(),
4672 VK_LValue, SourceLocation());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004673 if (HasLocalVariableExternalStorage(*I)) {
4674 QualType QT = (*I)->getType();
4675 QT = Context->getPointerType(QT);
4676 Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
4677 OK_Ordinary, SourceLocation());
4678 }
4679 } else if (isTopLevelBlockPointerType((*I)->getType())) {
4680 FD = SynthBlockInitFunctionDecl((*I)->getName());
John McCallf4b88a42012-03-10 09:33:50 +00004681 Arg = new (Context) DeclRefExpr(FD, false, FD->getType(),
4682 VK_LValue, SourceLocation());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004683 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
4684 CK_BitCast, Arg);
4685 } else {
4686 FD = SynthBlockInitFunctionDecl((*I)->getName());
John McCallf4b88a42012-03-10 09:33:50 +00004687 Exp = new (Context) DeclRefExpr(FD, false, FD->getType(),
4688 VK_LValue, SourceLocation());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004689 if (HasLocalVariableExternalStorage(*I)) {
4690 QualType QT = (*I)->getType();
4691 QT = Context->getPointerType(QT);
4692 Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
4693 OK_Ordinary, SourceLocation());
4694 }
4695
4696 }
4697 InitExprs.push_back(Exp);
4698 }
4699 // Output all "by ref" declarations.
4700 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
4701 E = BlockByRefDecls.end(); I != E; ++I) {
4702 ValueDecl *ND = (*I);
4703 std::string Name(ND->getNameAsString());
4704 std::string RecName;
4705 RewriteByRefString(RecName, Name, ND, true);
4706 IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
4707 + sizeof("struct"));
4708 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
4709 SourceLocation(), SourceLocation(),
4710 II);
4711 assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
4712 QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
4713
4714 FD = SynthBlockInitFunctionDecl((*I)->getName());
John McCallf4b88a42012-03-10 09:33:50 +00004715 Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004716 SourceLocation());
4717 bool isNestedCapturedVar = false;
4718 if (block)
4719 for (BlockDecl::capture_const_iterator ci = block->capture_begin(),
4720 ce = block->capture_end(); ci != ce; ++ci) {
4721 const VarDecl *variable = ci->getVariable();
4722 if (variable == ND && ci->isNested()) {
4723 assert (ci->isByRef() &&
4724 "SynthBlockInitExpr - captured block variable is not byref");
4725 isNestedCapturedVar = true;
4726 break;
4727 }
4728 }
4729 // captured nested byref variable has its address passed. Do not take
4730 // its address again.
4731 if (!isNestedCapturedVar)
4732 Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
4733 Context->getPointerType(Exp->getType()),
4734 VK_RValue, OK_Ordinary, SourceLocation());
4735 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4736 InitExprs.push_back(Exp);
4737 }
4738 }
4739 if (ImportedBlockDecls.size()) {
4740 // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
4741 int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
4742 unsigned IntSize =
4743 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4744 Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
4745 Context->IntTy, SourceLocation());
4746 InitExprs.push_back(FlagExp);
4747 }
4748 NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
4749 FType, VK_LValue, SourceLocation());
Fariborz Jahaniandf474ec2012-03-23 00:00:49 +00004750
4751 if (GlobalBlockExpr) {
4752 assert (GlobalConstructionExp == 0 &&
4753 "SynthBlockInitExpr - GlobalConstructionExp must be null");
4754 GlobalConstructionExp = NewRep;
4755 NewRep = DRE;
4756 }
4757
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004758 NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
4759 Context->getPointerType(NewRep->getType()),
4760 VK_RValue, OK_Ordinary, SourceLocation());
4761 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4762 NewRep);
4763 BlockDeclRefs.clear();
4764 BlockByRefDecls.clear();
4765 BlockByRefDeclsPtrSet.clear();
4766 BlockByCopyDecls.clear();
4767 BlockByCopyDeclsPtrSet.clear();
4768 ImportedBlockDecls.clear();
4769 return NewRep;
4770}
4771
4772bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
4773 if (const ObjCForCollectionStmt * CS =
4774 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4775 return CS->getElement() == DS;
4776 return false;
4777}
4778
4779//===----------------------------------------------------------------------===//
4780// Function Body / Expression rewriting
4781//===----------------------------------------------------------------------===//
4782
4783Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
4784 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4785 isa<DoStmt>(S) || isa<ForStmt>(S))
4786 Stmts.push_back(S);
4787 else if (isa<ObjCForCollectionStmt>(S)) {
4788 Stmts.push_back(S);
4789 ObjCBcLabelNo.push_back(++BcLabelCount);
4790 }
4791
4792 // Pseudo-object operations and ivar references need special
4793 // treatment because we're going to recursively rewrite them.
4794 if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
4795 if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
4796 return RewritePropertyOrImplicitSetter(PseudoOp);
4797 } else {
4798 return RewritePropertyOrImplicitGetter(PseudoOp);
4799 }
4800 } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4801 return RewriteObjCIvarRefExpr(IvarRefExpr);
4802 }
4803
4804 SourceRange OrigStmtRange = S->getSourceRange();
4805
4806 // Perform a bottom up rewrite of all children.
4807 for (Stmt::child_range CI = S->children(); CI; ++CI)
4808 if (*CI) {
4809 Stmt *childStmt = (*CI);
4810 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4811 if (newStmt) {
4812 *CI = newStmt;
4813 }
4814 }
4815
4816 if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
John McCallf4b88a42012-03-10 09:33:50 +00004817 SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004818 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
4819 InnerContexts.insert(BE->getBlockDecl());
4820 ImportedLocalExternalDecls.clear();
4821 GetInnerBlockDeclRefExprs(BE->getBody(),
4822 InnerBlockDeclRefs, InnerContexts);
4823 // Rewrite the block body in place.
4824 Stmt *SaveCurrentBody = CurrentBody;
4825 CurrentBody = BE->getBody();
4826 PropParentMap = 0;
4827 // block literal on rhs of a property-dot-sytax assignment
4828 // must be replaced by its synthesize ast so getRewrittenText
4829 // works as expected. In this case, what actually ends up on RHS
4830 // is the blockTranscribed which is the helper function for the
4831 // block literal; as in: self.c = ^() {[ace ARR];};
4832 bool saveDisableReplaceStmt = DisableReplaceStmt;
4833 DisableReplaceStmt = false;
4834 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4835 DisableReplaceStmt = saveDisableReplaceStmt;
4836 CurrentBody = SaveCurrentBody;
4837 PropParentMap = 0;
4838 ImportedLocalExternalDecls.clear();
4839 // Now we snarf the rewritten text and stash it away for later use.
4840 std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
4841 RewrittenBlockExprs[BE] = Str;
4842
4843 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4844
4845 //blockTranscribed->dump();
4846 ReplaceStmt(S, blockTranscribed);
4847 return blockTranscribed;
4848 }
4849 // Handle specific things.
4850 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
4851 return RewriteAtEncode(AtEncode);
4852
4853 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
4854 return RewriteAtSelector(AtSelector);
4855
4856 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
4857 return RewriteObjCStringLiteral(AtString);
Fariborz Jahanian55947042012-03-27 20:17:30 +00004858
4859 if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
4860 return RewriteObjCBoolLiteralExpr(BoolLitExpr);
Fariborz Jahanian0f9b18e2012-03-30 16:49:36 +00004861
4862 if (ObjCNumericLiteral *NumericLitExpr = dyn_cast<ObjCNumericLiteral>(S))
4863 return RewriteObjCNumericLiteralExpr(NumericLitExpr);
4864
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004865
4866 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
4867#if 0
4868 // Before we rewrite it, put the original message expression in a comment.
4869 SourceLocation startLoc = MessExpr->getLocStart();
4870 SourceLocation endLoc = MessExpr->getLocEnd();
4871
4872 const char *startBuf = SM->getCharacterData(startLoc);
4873 const char *endBuf = SM->getCharacterData(endLoc);
4874
4875 std::string messString;
4876 messString += "// ";
4877 messString.append(startBuf, endBuf-startBuf+1);
4878 messString += "\n";
4879
4880 // FIXME: Missing definition of
4881 // InsertText(clang::SourceLocation, char const*, unsigned int).
4882 // InsertText(startLoc, messString.c_str(), messString.size());
4883 // Tried this, but it didn't work either...
4884 // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
4885#endif
4886 return RewriteMessageExpr(MessExpr);
4887 }
4888
4889 if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
4890 return RewriteObjCTryStmt(StmtTry);
4891
4892 if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
4893 return RewriteObjCSynchronizedStmt(StmtTry);
4894
4895 if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
4896 return RewriteObjCThrowStmt(StmtThrow);
4897
4898 if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
4899 return RewriteObjCProtocolExpr(ProtocolExp);
4900
4901 if (ObjCForCollectionStmt *StmtForCollection =
4902 dyn_cast<ObjCForCollectionStmt>(S))
4903 return RewriteObjCForCollectionStmt(StmtForCollection,
4904 OrigStmtRange.getEnd());
4905 if (BreakStmt *StmtBreakStmt =
4906 dyn_cast<BreakStmt>(S))
4907 return RewriteBreakStmt(StmtBreakStmt);
4908 if (ContinueStmt *StmtContinueStmt =
4909 dyn_cast<ContinueStmt>(S))
4910 return RewriteContinueStmt(StmtContinueStmt);
4911
4912 // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
4913 // and cast exprs.
4914 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4915 // FIXME: What we're doing here is modifying the type-specifier that
4916 // precedes the first Decl. In the future the DeclGroup should have
4917 // a separate type-specifier that we can rewrite.
4918 // NOTE: We need to avoid rewriting the DeclStmt if it is within
4919 // the context of an ObjCForCollectionStmt. For example:
4920 // NSArray *someArray;
4921 // for (id <FooProtocol> index in someArray) ;
4922 // This is because RewriteObjCForCollectionStmt() does textual rewriting
4923 // and it depends on the original text locations/positions.
4924 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4925 RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
4926
4927 // Blocks rewrite rules.
4928 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
4929 DI != DE; ++DI) {
4930 Decl *SD = *DI;
4931 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4932 if (isTopLevelBlockPointerType(ND->getType()))
4933 RewriteBlockPointerDecl(ND);
4934 else if (ND->getType()->isFunctionPointerType())
4935 CheckFunctionPointerDecl(ND->getType(), ND);
4936 if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4937 if (VD->hasAttr<BlocksAttr>()) {
4938 static unsigned uniqueByrefDeclCount = 0;
4939 assert(!BlockByRefDeclNo.count(ND) &&
4940 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4941 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4942 RewriteByRefVar(VD);
4943 }
4944 else
4945 RewriteTypeOfDecl(VD);
4946 }
4947 }
4948 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
4949 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4950 RewriteBlockPointerDecl(TD);
4951 else if (TD->getUnderlyingType()->isFunctionPointerType())
4952 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4953 }
4954 }
4955 }
4956
4957 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
4958 RewriteObjCQualifiedInterfaceTypes(CE);
4959
4960 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4961 isa<DoStmt>(S) || isa<ForStmt>(S)) {
4962 assert(!Stmts.empty() && "Statement stack is empty");
4963 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4964 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4965 && "Statement stack mismatch");
4966 Stmts.pop_back();
4967 }
4968 // Handle blocks rewriting.
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00004969 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4970 ValueDecl *VD = DRE->getDecl();
4971 if (VD->hasAttr<BlocksAttr>())
4972 return RewriteBlockDeclRefExpr(DRE);
4973 if (HasLocalVariableExternalStorage(VD))
4974 return RewriteLocalVariableExternalStorage(DRE);
4975 }
4976
4977 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
4978 if (CE->getCallee()->getType()->isBlockPointerType()) {
4979 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
4980 ReplaceStmt(S, BlockCall);
4981 return BlockCall;
4982 }
4983 }
4984 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
4985 RewriteCastExpr(CE);
4986 }
4987#if 0
4988 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
4989 CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
4990 ICE->getSubExpr(),
4991 SourceLocation());
4992 // Get the new text.
4993 std::string SStr;
4994 llvm::raw_string_ostream Buf(SStr);
4995 Replacement->printPretty(Buf, *Context);
4996 const std::string &Str = Buf.str();
4997
4998 printf("CAST = %s\n", &Str[0]);
4999 InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
5000 delete S;
5001 return Replacement;
5002 }
5003#endif
5004 // Return this stmt unmodified.
5005 return S;
5006}
5007
5008void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {
5009 for (RecordDecl::field_iterator i = RD->field_begin(),
5010 e = RD->field_end(); i != e; ++i) {
5011 FieldDecl *FD = *i;
5012 if (isTopLevelBlockPointerType(FD->getType()))
5013 RewriteBlockPointerDecl(FD);
5014 if (FD->getType()->isObjCQualifiedIdType() ||
5015 FD->getType()->isObjCQualifiedInterfaceType())
5016 RewriteObjCQualifiedInterfaceTypes(FD);
5017 }
5018}
5019
5020/// HandleDeclInMainFile - This is called for each top-level decl defined in the
5021/// main file of the input.
5022void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
5023 switch (D->getKind()) {
5024 case Decl::Function: {
5025 FunctionDecl *FD = cast<FunctionDecl>(D);
5026 if (FD->isOverloadedOperator())
5027 return;
5028
5029 // Since function prototypes don't have ParmDecl's, we check the function
5030 // prototype. This enables us to rewrite function declarations and
5031 // definitions using the same code.
5032 RewriteBlocksInFunctionProtoType(FD->getType(), FD);
5033
Argyrios Kyrtzidis9335df32012-02-12 04:48:45 +00005034 if (!FD->isThisDeclarationADefinition())
5035 break;
5036
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005037 // FIXME: If this should support Obj-C++, support CXXTryStmt
5038 if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
5039 CurFunctionDef = FD;
5040 CurFunctionDeclToDeclareForBlock = FD;
5041 CurrentBody = Body;
5042 Body =
5043 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
5044 FD->setBody(Body);
5045 CurrentBody = 0;
5046 if (PropParentMap) {
5047 delete PropParentMap;
5048 PropParentMap = 0;
5049 }
5050 // This synthesizes and inserts the block "impl" struct, invoke function,
5051 // and any copy/dispose helper functions.
5052 InsertBlockLiteralsWithinFunction(FD);
5053 CurFunctionDef = 0;
5054 CurFunctionDeclToDeclareForBlock = 0;
5055 }
5056 break;
5057 }
5058 case Decl::ObjCMethod: {
5059 ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
5060 if (CompoundStmt *Body = MD->getCompoundBody()) {
5061 CurMethodDef = MD;
5062 CurrentBody = Body;
5063 Body =
5064 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
5065 MD->setBody(Body);
5066 CurrentBody = 0;
5067 if (PropParentMap) {
5068 delete PropParentMap;
5069 PropParentMap = 0;
5070 }
5071 InsertBlockLiteralsWithinMethod(MD);
5072 CurMethodDef = 0;
5073 }
5074 break;
5075 }
5076 case Decl::ObjCImplementation: {
5077 ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
5078 ClassImplementation.push_back(CI);
5079 break;
5080 }
5081 case Decl::ObjCCategoryImpl: {
5082 ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
5083 CategoryImplementation.push_back(CI);
5084 break;
5085 }
5086 case Decl::Var: {
5087 VarDecl *VD = cast<VarDecl>(D);
5088 RewriteObjCQualifiedInterfaceTypes(VD);
5089 if (isTopLevelBlockPointerType(VD->getType()))
5090 RewriteBlockPointerDecl(VD);
5091 else if (VD->getType()->isFunctionPointerType()) {
5092 CheckFunctionPointerDecl(VD->getType(), VD);
5093 if (VD->getInit()) {
5094 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
5095 RewriteCastExpr(CE);
5096 }
5097 }
5098 } else if (VD->getType()->isRecordType()) {
5099 RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
5100 if (RD->isCompleteDefinition())
5101 RewriteRecordBody(RD);
5102 }
5103 if (VD->getInit()) {
5104 GlobalVarDecl = VD;
5105 CurrentBody = VD->getInit();
5106 RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
5107 CurrentBody = 0;
5108 if (PropParentMap) {
5109 delete PropParentMap;
5110 PropParentMap = 0;
5111 }
5112 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
5113 GlobalVarDecl = 0;
5114
5115 // This is needed for blocks.
5116 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
5117 RewriteCastExpr(CE);
5118 }
5119 }
5120 break;
5121 }
5122 case Decl::TypeAlias:
5123 case Decl::Typedef: {
5124 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
5125 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
5126 RewriteBlockPointerDecl(TD);
5127 else if (TD->getUnderlyingType()->isFunctionPointerType())
5128 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
5129 }
5130 break;
5131 }
5132 case Decl::CXXRecord:
5133 case Decl::Record: {
5134 RecordDecl *RD = cast<RecordDecl>(D);
5135 if (RD->isCompleteDefinition())
5136 RewriteRecordBody(RD);
5137 break;
5138 }
5139 default:
5140 break;
5141 }
5142 // Nothing yet.
5143}
5144
Fariborz Jahanian30650eb2012-03-15 17:05:33 +00005145/// Write_ProtocolExprReferencedMetadata - This routine writer out the
5146/// protocol reference symbols in the for of:
5147/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.
5148static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,
5149 ObjCProtocolDecl *PDecl,
5150 std::string &Result) {
5151 // Also output .objc_protorefs$B section and its meta-data.
5152 if (Context->getLangOpts().MicrosoftExt)
5153 Result += "__declspec(allocate(\".objc_protorefs$B\")) ";
5154 Result += "struct _protocol_t *";
5155 Result += "_OBJC_PROTOCOL_REFERENCE_$_";
5156 Result += PDecl->getNameAsString();
5157 Result += " = &";
5158 Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
5159 Result += ";\n";
5160}
5161
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005162void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
5163 if (Diags.hasErrorOccurred())
5164 return;
5165
5166 RewriteInclude();
5167
5168 // Here's a great place to add any extra declarations that may be needed.
5169 // Write out meta data for each @protocol(<expr>).
5170 for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
Fariborz Jahanian30650eb2012-03-15 17:05:33 +00005171 E = ProtocolExprDecls.end(); I != E; ++I) {
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00005172 RewriteObjCProtocolMetaData(*I, Preamble);
Fariborz Jahanian30650eb2012-03-15 17:05:33 +00005173 Write_ProtocolExprReferencedMetadata(Context, (*I), Preamble);
5174 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005175
5176 InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
Fariborz Jahanian57317782012-02-21 23:58:41 +00005177 for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {
5178 ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];
5179 // Write struct declaration for the class matching its ivar declarations.
5180 // Note that for modern abi, this is postponed until the end of TU
5181 // because class extensions and the implementation might declare their own
5182 // private ivars.
5183 RewriteInterfaceDecl(CDecl);
5184 }
Fariborz Jahanian72c88f12012-02-22 18:13:25 +00005185
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005186 if (ClassImplementation.size() || CategoryImplementation.size())
5187 RewriteImplementations();
5188
5189 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
5190 // we are done.
5191 if (const RewriteBuffer *RewriteBuf =
5192 Rewrite.getRewriteBufferFor(MainFileID)) {
5193 //printf("Changed:\n");
5194 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
5195 } else {
5196 llvm::errs() << "No changes\n";
5197 }
5198
5199 if (ClassImplementation.size() || CategoryImplementation.size() ||
5200 ProtocolExprDecls.size()) {
5201 // Rewrite Objective-c meta data*
5202 std::string ResultStr;
5203 RewriteMetaDataIntoBuffer(ResultStr);
5204 // Emit metadata.
5205 *OutFile << ResultStr;
5206 }
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00005207 // Emit ImageInfo;
5208 {
5209 std::string ResultStr;
5210 WriteImageInfo(ResultStr);
5211 *OutFile << ResultStr;
5212 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005213 OutFile->flush();
5214}
5215
5216void RewriteModernObjC::Initialize(ASTContext &context) {
5217 InitializeCommon(context);
5218
Fariborz Jahanian6991bc52012-03-10 17:45:38 +00005219 Preamble += "#ifndef __OBJC2__\n";
5220 Preamble += "#define __OBJC2__\n";
5221 Preamble += "#endif\n";
5222
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005223 // declaring objc_selector outside the parameter list removes a silly
5224 // scope related warning...
5225 if (IsHeader)
5226 Preamble = "#pragma once\n";
5227 Preamble += "struct objc_selector; struct objc_class;\n";
5228 Preamble += "struct __rw_objc_super { struct objc_object *object; ";
5229 Preamble += "struct objc_object *superClass; ";
5230 if (LangOpts.MicrosoftExt) {
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00005231 // Define all sections using syntax that makes sense.
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00005232 // These are currently generated.
5233 Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00005234 Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00005235 Preamble += "#pragma section(\".objc_protolist$B\", long, read, write)\n";
5236 Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00005237 Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";
5238 Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00005239 Preamble += "#pragma section(\".objc_protorefs$B\", long, read, write)\n";
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00005240 // These are generated but not necessary for functionality.
5241 Preamble += "#pragma section(\".datacoal_nt$B\", long, read, write)\n";
5242 Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00005243 Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";
5244 Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";
Fariborz Jahanian40a777a2012-03-12 16:46:58 +00005245 Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";
Fariborz Jahaniande5d9462012-03-14 18:09:23 +00005246
Fariborz Jahanian30650eb2012-03-15 17:05:33 +00005247 // These need be generated for performance. Currently they are not,
5248 // using API calls instead.
5249 Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";
5250 Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";
5251 Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";
5252
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005253 // Add a constructor for creating temporary objects.
5254 Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
5255 ": ";
5256 Preamble += "object(o), superClass(s) {} ";
5257 }
5258 Preamble += "};\n";
5259 Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
5260 Preamble += "typedef struct objc_object Protocol;\n";
5261 Preamble += "#define _REWRITER_typedef_Protocol\n";
5262 Preamble += "#endif\n";
5263 if (LangOpts.MicrosoftExt) {
5264 Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
5265 Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
Fariborz Jahanian5cf6b6c2012-03-21 23:41:04 +00005266 }
5267 else
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005268 Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
Fariborz Jahanian5cf6b6c2012-03-21 23:41:04 +00005269
5270 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";
5271 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";
5272 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";
5273 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";
5274 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";
5275
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005276 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
5277 Preamble += "(const char *);\n";
5278 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
5279 Preamble += "(struct objc_class *);\n";
5280 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
5281 Preamble += "(const char *);\n";
Fariborz Jahanian55261af2012-03-19 18:11:32 +00005282 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005283 // @synchronized hooks.
Fariborz Jahanian55261af2012-03-19 18:11:32 +00005284 Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter( struct objc_object *);\n";
5285 Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit( struct objc_object *);\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005286 Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
5287 Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
5288 Preamble += "struct __objcFastEnumerationState {\n\t";
5289 Preamble += "unsigned long state;\n\t";
5290 Preamble += "void **itemsPtr;\n\t";
5291 Preamble += "unsigned long *mutationsPtr;\n\t";
5292 Preamble += "unsigned long extra[5];\n};\n";
5293 Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
5294 Preamble += "#define __FASTENUMERATIONSTATE\n";
5295 Preamble += "#endif\n";
5296 Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
5297 Preamble += "struct __NSConstantStringImpl {\n";
5298 Preamble += " int *isa;\n";
5299 Preamble += " int flags;\n";
5300 Preamble += " char *str;\n";
5301 Preamble += " long length;\n";
5302 Preamble += "};\n";
5303 Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
5304 Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5305 Preamble += "#else\n";
5306 Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5307 Preamble += "#endif\n";
5308 Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
5309 Preamble += "#endif\n";
5310 // Blocks preamble.
5311 Preamble += "#ifndef BLOCK_IMPL\n";
5312 Preamble += "#define BLOCK_IMPL\n";
5313 Preamble += "struct __block_impl {\n";
5314 Preamble += " void *isa;\n";
5315 Preamble += " int Flags;\n";
5316 Preamble += " int Reserved;\n";
5317 Preamble += " void *FuncPtr;\n";
5318 Preamble += "};\n";
5319 Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
5320 Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
5321 Preamble += "extern \"C\" __declspec(dllexport) "
5322 "void _Block_object_assign(void *, const void *, const int);\n";
5323 Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5324 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5325 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5326 Preamble += "#else\n";
5327 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5328 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5329 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5330 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5331 Preamble += "#endif\n";
5332 Preamble += "#endif\n";
5333 if (LangOpts.MicrosoftExt) {
5334 Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
5335 Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
5336 Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
5337 Preamble += "#define __attribute__(X)\n";
5338 Preamble += "#endif\n";
5339 Preamble += "#define __weak\n";
5340 }
5341 else {
5342 Preamble += "#define __block\n";
5343 Preamble += "#define __weak\n";
5344 }
5345 // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
5346 // as this avoids warning in any 64bit/32bit compilation model.
5347 Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5348}
5349
5350/// RewriteIvarOffsetComputation - This rutine synthesizes computation of
5351/// ivar offset.
5352void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
5353 std::string &Result) {
5354 if (ivar->isBitField()) {
5355 // FIXME: The hack below doesn't work for bitfields. For now, we simply
5356 // place all bitfields at offset 0.
5357 Result += "0";
5358 } else {
5359 Result += "__OFFSETOFIVAR__(struct ";
5360 Result += ivar->getContainingInterface()->getNameAsString();
5361 if (LangOpts.MicrosoftExt)
5362 Result += "_IMPL";
5363 Result += ", ";
5364 Result += ivar->getNameAsString();
5365 Result += ")";
5366 }
5367}
5368
5369/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.
5370/// struct _prop_t {
Fariborz Jahanianda35eac2012-02-07 23:31:52 +00005371/// const char *name;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005372/// char *attributes;
5373/// }
5374
5375/// struct _prop_list_t {
5376/// uint32_t entsize; // sizeof(struct _prop_t)
5377/// uint32_t count_of_properties;
5378/// struct _prop_t prop_list[count_of_properties];
5379/// }
5380
5381/// struct _protocol_t;
5382
5383/// struct _protocol_list_t {
5384/// long protocol_count; // Note, this is 32/64 bit
5385/// struct _protocol_t * protocol_list[protocol_count];
5386/// }
5387
5388/// struct _objc_method {
5389/// SEL _cmd;
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005390/// const char *method_type;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005391/// char *_imp;
5392/// }
5393
5394/// struct _method_list_t {
5395/// uint32_t entsize; // sizeof(struct _objc_method)
5396/// uint32_t method_count;
5397/// struct _objc_method method_list[method_count];
5398/// }
5399
5400/// struct _protocol_t {
5401/// id isa; // NULL
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005402/// const char *protocol_name;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005403/// const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005404/// const struct method_list_t *instance_methods;
5405/// const struct method_list_t *class_methods;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005406/// const struct method_list_t *optionalInstanceMethods;
5407/// const struct method_list_t *optionalClassMethods;
5408/// const struct _prop_list_t * properties;
5409/// const uint32_t size; // sizeof(struct _protocol_t)
5410/// const uint32_t flags; // = 0
5411/// const char ** extendedMethodTypes;
5412/// }
5413
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005414/// struct _ivar_t {
5415/// unsigned long int *offset; // pointer to ivar offset location
Fariborz Jahanianae932952012-02-10 20:47:10 +00005416/// const char *name;
5417/// const char *type;
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005418/// uint32_t alignment;
5419/// uint32_t size;
5420/// }
5421
5422/// struct _ivar_list_t {
5423/// uint32 entsize; // sizeof(struct _ivar_t)
5424/// uint32 count;
Fariborz Jahanianae932952012-02-10 20:47:10 +00005425/// struct _ivar_t list[count];
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005426/// }
5427
5428/// struct _class_ro_t {
Fariborz Jahanian249cd102012-03-24 16:53:16 +00005429/// uint32_t flags;
5430/// uint32_t instanceStart;
5431/// uint32_t instanceSize;
5432/// uint32_t reserved; // only when building for 64bit targets
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005433/// const uint8_t *ivarLayout;
5434/// const char *name;
5435/// const struct _method_list_t *baseMethods;
5436/// const struct _protocol_list_t *baseProtocols;
5437/// const struct _ivar_list_t *ivars;
5438/// const uint8_t *weakIvarLayout;
5439/// const struct _prop_list_t *properties;
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005440/// }
5441
5442/// struct _class_t {
5443/// struct _class_t *isa;
Fariborz Jahanianfd4ce2c2012-03-20 17:34:50 +00005444/// struct _class_t *superclass;
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005445/// void *cache;
5446/// IMP *vtable;
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005447/// struct _class_ro_t *ro;
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005448/// }
5449
5450/// struct _category_t {
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005451/// const char *name;
Fariborz Jahanian4b2fe6e2012-03-20 21:41:28 +00005452/// struct _class_t *cls;
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005453/// const struct _method_list_t *instance_methods;
5454/// const struct _method_list_t *class_methods;
5455/// const struct _protocol_list_t *protocols;
5456/// const struct _prop_list_t *properties;
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005457/// }
5458
5459/// MessageRefTy - LLVM for:
5460/// struct _message_ref_t {
5461/// IMP messenger;
5462/// SEL name;
5463/// };
5464
5465/// SuperMessageRefTy - LLVM for:
5466/// struct _super_message_ref_t {
5467/// SUPER_IMP messenger;
5468/// SEL name;
5469/// };
5470
Fariborz Jahaniande5d9462012-03-14 18:09:23 +00005471static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005472 static bool meta_data_declared = false;
5473 if (meta_data_declared)
5474 return;
5475
5476 Result += "\nstruct _prop_t {\n";
Fariborz Jahanianda35eac2012-02-07 23:31:52 +00005477 Result += "\tconst char *name;\n";
5478 Result += "\tconst char *attributes;\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005479 Result += "};\n";
5480
5481 Result += "\nstruct _protocol_t;\n";
5482
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005483 Result += "\nstruct _objc_method {\n";
5484 Result += "\tstruct objc_selector * _cmd;\n";
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005485 Result += "\tconst char *method_type;\n";
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00005486 Result += "\tvoid *_imp;\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005487 Result += "};\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005488
5489 Result += "\nstruct _protocol_t {\n";
5490 Result += "\tvoid * isa; // NULL\n";
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005491 Result += "\tconst char *protocol_name;\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005492 Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005493 Result += "\tconst struct method_list_t *instance_methods;\n";
5494 Result += "\tconst struct method_list_t *class_methods;\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005495 Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";
5496 Result += "\tconst struct method_list_t *optionalClassMethods;\n";
5497 Result += "\tconst struct _prop_list_t * properties;\n";
5498 Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n";
5499 Result += "\tconst unsigned int flags; // = 0\n";
5500 Result += "\tconst char ** extendedMethodTypes;\n";
5501 Result += "};\n";
5502
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005503 Result += "\nstruct _ivar_t {\n";
5504 Result += "\tunsigned long int *offset; // pointer to ivar offset location\n";
Fariborz Jahanianae932952012-02-10 20:47:10 +00005505 Result += "\tconst char *name;\n";
5506 Result += "\tconst char *type;\n";
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005507 Result += "\tunsigned int alignment;\n";
5508 Result += "\tunsigned int size;\n";
5509 Result += "};\n";
5510
5511 Result += "\nstruct _class_ro_t {\n";
Fariborz Jahanian249cd102012-03-24 16:53:16 +00005512 Result += "\tunsigned int flags;\n";
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005513 Result += "\tunsigned int instanceStart;\n";
Fariborz Jahanian249cd102012-03-24 16:53:16 +00005514 Result += "\tunsigned int instanceSize;\n";
Fariborz Jahaniande5d9462012-03-14 18:09:23 +00005515 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
5516 if (Triple.getArch() == llvm::Triple::x86_64)
Fariborz Jahanian249cd102012-03-24 16:53:16 +00005517 Result += "\tunsigned int reserved;\n";
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005518 Result += "\tconst unsigned char *ivarLayout;\n";
5519 Result += "\tconst char *name;\n";
5520 Result += "\tconst struct _method_list_t *baseMethods;\n";
5521 Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";
5522 Result += "\tconst struct _ivar_list_t *ivars;\n";
5523 Result += "\tconst unsigned char *weakIvarLayout;\n";
5524 Result += "\tconst struct _prop_list_t *properties;\n";
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005525 Result += "};\n";
5526
5527 Result += "\nstruct _class_t {\n";
5528 Result += "\tstruct _class_t *isa;\n";
Fariborz Jahanianfd4ce2c2012-03-20 17:34:50 +00005529 Result += "\tstruct _class_t *superclass;\n";
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005530 Result += "\tvoid *cache;\n";
5531 Result += "\tvoid *vtable;\n";
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005532 Result += "\tstruct _class_ro_t *ro;\n";
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005533 Result += "};\n";
5534
5535 Result += "\nstruct _category_t {\n";
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005536 Result += "\tconst char *name;\n";
Fariborz Jahanian4b2fe6e2012-03-20 21:41:28 +00005537 Result += "\tstruct _class_t *cls;\n";
Fariborz Jahanian4e825df2012-03-21 16:23:16 +00005538 Result += "\tconst struct _method_list_t *instance_methods;\n";
5539 Result += "\tconst struct _method_list_t *class_methods;\n";
5540 Result += "\tconst struct _protocol_list_t *protocols;\n";
5541 Result += "\tconst struct _prop_list_t *properties;\n";
Fariborz Jahanian42e9a352012-02-10 00:04:22 +00005542 Result += "};\n";
5543
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005544 Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";
Fariborz Jahanian297976d2012-03-29 17:51:09 +00005545 Result += "#pragma warning(disable:4273)\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00005546 meta_data_declared = true;
5547}
5548
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00005549static void Write_protocol_list_t_TypeDecl(std::string &Result,
5550 long super_protocol_count) {
5551 Result += "struct /*_protocol_list_t*/"; Result += " {\n";
5552 Result += "\tlong protocol_count; // Note, this is 32/64 bit\n";
5553 Result += "\tstruct _protocol_t *super_protocols[";
5554 Result += utostr(super_protocol_count); Result += "];\n";
5555 Result += "}";
5556}
5557
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005558static void Write_method_list_t_TypeDecl(std::string &Result,
5559 unsigned int method_count) {
5560 Result += "struct /*_method_list_t*/"; Result += " {\n";
5561 Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n";
5562 Result += "\tunsigned int method_count;\n";
5563 Result += "\tstruct _objc_method method_list[";
5564 Result += utostr(method_count); Result += "];\n";
5565 Result += "}";
5566}
5567
Fariborz Jahanianda35eac2012-02-07 23:31:52 +00005568static void Write__prop_list_t_TypeDecl(std::string &Result,
5569 unsigned int property_count) {
5570 Result += "struct /*_prop_list_t*/"; Result += " {\n";
5571 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";
5572 Result += "\tunsigned int count_of_properties;\n";
5573 Result += "\tstruct _prop_t prop_list[";
5574 Result += utostr(property_count); Result += "];\n";
5575 Result += "}";
5576}
5577
Fariborz Jahanianae932952012-02-10 20:47:10 +00005578static void Write__ivar_list_t_TypeDecl(std::string &Result,
5579 unsigned int ivar_count) {
5580 Result += "struct /*_ivar_list_t*/"; Result += " {\n";
5581 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";
5582 Result += "\tunsigned int count;\n";
5583 Result += "\tstruct _ivar_t ivar_list[";
5584 Result += utostr(ivar_count); Result += "];\n";
5585 Result += "}";
5586}
5587
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00005588static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,
5589 ArrayRef<ObjCProtocolDecl *> SuperProtocols,
5590 StringRef VarName,
5591 StringRef ProtocolName) {
5592 if (SuperProtocols.size() > 0) {
5593 Result += "\nstatic ";
5594 Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());
5595 Result += " "; Result += VarName;
5596 Result += ProtocolName;
5597 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
5598 Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";
5599 for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {
5600 ObjCProtocolDecl *SuperPD = SuperProtocols[i];
5601 Result += "\t&"; Result += "_OBJC_PROTOCOL_";
5602 Result += SuperPD->getNameAsString();
5603 if (i == e-1)
5604 Result += "\n};\n";
5605 else
5606 Result += ",\n";
5607 }
5608 }
5609}
5610
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00005611static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,
5612 ASTContext *Context, std::string &Result,
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005613 ArrayRef<ObjCMethodDecl *> Methods,
5614 StringRef VarName,
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00005615 StringRef TopLevelDeclName,
5616 bool MethodImpl) {
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005617 if (Methods.size() > 0) {
5618 Result += "\nstatic ";
5619 Write_method_list_t_TypeDecl(Result, Methods.size());
5620 Result += " "; Result += VarName;
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00005621 Result += TopLevelDeclName;
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005622 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
5623 Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";
5624 Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";
5625 for (unsigned i = 0, e = Methods.size(); i < e; i++) {
5626 ObjCMethodDecl *MD = Methods[i];
5627 if (i == 0)
5628 Result += "\t{{(struct objc_selector *)\"";
5629 else
5630 Result += "\t{(struct objc_selector *)\"";
5631 Result += (MD)->getSelector().getAsString(); Result += "\"";
5632 Result += ", ";
5633 std::string MethodTypeString;
5634 Context->getObjCEncodingForMethodDecl(MD, MethodTypeString);
5635 Result += "\""; Result += MethodTypeString; Result += "\"";
5636 Result += ", ";
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00005637 if (!MethodImpl)
5638 Result += "0";
5639 else {
5640 Result += "(void *)";
5641 Result += RewriteObj.MethodInternalNames[MD];
5642 }
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005643 if (i == e-1)
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00005644 Result += "}}\n";
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005645 else
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00005646 Result += "},\n";
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00005647 }
5648 Result += "};\n";
5649 }
5650}
5651
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005652static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,
Fariborz Jahanianda35eac2012-02-07 23:31:52 +00005653 ASTContext *Context, std::string &Result,
5654 ArrayRef<ObjCPropertyDecl *> Properties,
5655 const Decl *Container,
5656 StringRef VarName,
5657 StringRef ProtocolName) {
5658 if (Properties.size() > 0) {
5659 Result += "\nstatic ";
5660 Write__prop_list_t_TypeDecl(Result, Properties.size());
5661 Result += " "; Result += VarName;
5662 Result += ProtocolName;
5663 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
5664 Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";
5665 Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";
5666 for (unsigned i = 0, e = Properties.size(); i < e; i++) {
5667 ObjCPropertyDecl *PropDecl = Properties[i];
5668 if (i == 0)
5669 Result += "\t{{\"";
5670 else
5671 Result += "\t{\"";
5672 Result += PropDecl->getName(); Result += "\",";
5673 std::string PropertyTypeString, QuotePropertyTypeString;
5674 Context->getObjCEncodingForPropertyDecl(PropDecl, Container, PropertyTypeString);
5675 RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);
5676 Result += "\""; Result += QuotePropertyTypeString; Result += "\"";
5677 if (i == e-1)
5678 Result += "}}\n";
5679 else
5680 Result += "},\n";
5681 }
5682 Result += "};\n";
5683 }
5684}
5685
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00005686// Metadata flags
5687enum MetaDataDlags {
5688 CLS = 0x0,
5689 CLS_META = 0x1,
5690 CLS_ROOT = 0x2,
5691 OBJC2_CLS_HIDDEN = 0x10,
5692 CLS_EXCEPTION = 0x20,
5693
5694 /// (Obsolete) ARC-specific: this class has a .release_ivars method
5695 CLS_HAS_IVAR_RELEASER = 0x40,
5696 /// class was compiled with -fobjc-arr
5697 CLS_COMPILED_BY_ARC = 0x80 // (1<<7)
5698};
5699
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005700static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,
5701 unsigned int flags,
5702 const std::string &InstanceStart,
5703 const std::string &InstanceSize,
5704 ArrayRef<ObjCMethodDecl *>baseMethods,
5705 ArrayRef<ObjCProtocolDecl *>baseProtocols,
5706 ArrayRef<ObjCIvarDecl *>ivars,
5707 ArrayRef<ObjCPropertyDecl *>Properties,
5708 StringRef VarName,
5709 StringRef ClassName) {
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005710 Result += "\nstatic struct _class_ro_t ";
5711 Result += VarName; Result += ClassName;
5712 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
5713 Result += "\t";
5714 Result += llvm::utostr(flags); Result += ", ";
5715 Result += InstanceStart; Result += ", ";
5716 Result += InstanceSize; Result += ", \n";
5717 Result += "\t";
Fariborz Jahaniande5d9462012-03-14 18:09:23 +00005718 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
5719 if (Triple.getArch() == llvm::Triple::x86_64)
5720 // uint32_t const reserved; // only when building for 64bit targets
5721 Result += "(unsigned int)0, \n\t";
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005722 // const uint8_t * const ivarLayout;
5723 Result += "0, \n\t";
5724 Result += "\""; Result += ClassName; Result += "\",\n\t";
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00005725 bool metaclass = ((flags & CLS_META) != 0);
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005726 if (baseMethods.size() > 0) {
5727 Result += "(const struct _method_list_t *)&";
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00005728 if (metaclass)
5729 Result += "_OBJC_$_CLASS_METHODS_";
5730 else
5731 Result += "_OBJC_$_INSTANCE_METHODS_";
5732 Result += ClassName;
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005733 Result += ",\n\t";
5734 }
5735 else
5736 Result += "0, \n\t";
5737
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00005738 if (!metaclass && baseProtocols.size() > 0) {
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005739 Result += "(const struct _objc_protocol_list *)&";
5740 Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;
5741 Result += ",\n\t";
5742 }
5743 else
5744 Result += "0, \n\t";
5745
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00005746 if (!metaclass && ivars.size() > 0) {
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005747 Result += "(const struct _ivar_list_t *)&";
5748 Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;
5749 Result += ",\n\t";
5750 }
5751 else
5752 Result += "0, \n\t";
5753
5754 // weakIvarLayout
5755 Result += "0, \n\t";
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00005756 if (!metaclass && Properties.size() > 0) {
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005757 Result += "(const struct _prop_list_t *)&";
Fariborz Jahanianeeabf382012-02-16 21:57:59 +00005758 Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00005759 Result += ",\n";
5760 }
5761 else
5762 Result += "0, \n";
5763
5764 Result += "};\n";
5765}
5766
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005767static void Write_class_t(ASTContext *Context, std::string &Result,
5768 StringRef VarName,
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005769 const ObjCInterfaceDecl *CDecl, bool metaclass) {
5770 bool rootClass = (!CDecl->getSuperClass());
5771 const ObjCInterfaceDecl *RootClass = CDecl;
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005772
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005773 if (!rootClass) {
5774 // Find the Root class
5775 RootClass = CDecl->getSuperClass();
5776 while (RootClass->getSuperClass()) {
5777 RootClass = RootClass->getSuperClass();
5778 }
5779 }
5780
5781 if (metaclass && rootClass) {
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005782 // Need to handle a case of use of forward declaration.
Fariborz Jahaniance0d8972012-03-10 18:25:06 +00005783 Result += "\n";
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005784 Result += "extern \"C\" ";
Fariborz Jahaniance0d8972012-03-10 18:25:06 +00005785 if (CDecl->getImplementation())
5786 Result += "__declspec(dllexport) ";
Fariborz Jahanian297976d2012-03-29 17:51:09 +00005787 else
5788 Result += "__declspec(dllimport) ";
5789
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005790 Result += "struct _class_t OBJC_CLASS_$_";
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005791 Result += CDecl->getNameAsString();
5792 Result += ";\n";
5793 }
5794 // Also, for possibility of 'super' metadata class not having been defined yet.
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005795 if (!rootClass) {
Fariborz Jahanian868e9852012-03-29 19:04:10 +00005796 ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
Fariborz Jahaniance0d8972012-03-10 18:25:06 +00005797 Result += "\n";
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005798 Result += "extern \"C\" ";
Fariborz Jahanian868e9852012-03-29 19:04:10 +00005799 if (SuperClass->getImplementation())
Fariborz Jahaniance0d8972012-03-10 18:25:06 +00005800 Result += "__declspec(dllexport) ";
Fariborz Jahanian297976d2012-03-29 17:51:09 +00005801 else
5802 Result += "__declspec(dllimport) ";
5803
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005804 Result += "struct _class_t ";
Fariborz Jahaniance0d8972012-03-10 18:25:06 +00005805 Result += VarName;
Fariborz Jahanian868e9852012-03-29 19:04:10 +00005806 Result += SuperClass->getNameAsString();
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005807 Result += ";\n";
Fariborz Jahanian452eac12012-03-20 21:09:58 +00005808
Fariborz Jahanian868e9852012-03-29 19:04:10 +00005809 if (metaclass && RootClass != SuperClass) {
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005810 Result += "extern \"C\" ";
Fariborz Jahanian452eac12012-03-20 21:09:58 +00005811 if (RootClass->getImplementation())
5812 Result += "__declspec(dllexport) ";
Fariborz Jahanian297976d2012-03-29 17:51:09 +00005813 else
5814 Result += "__declspec(dllimport) ";
5815
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005816 Result += "struct _class_t ";
Fariborz Jahanian452eac12012-03-20 21:09:58 +00005817 Result += VarName;
5818 Result += RootClass->getNameAsString();
5819 Result += ";\n";
5820 }
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005821 }
5822
Fariborz Jahanian297976d2012-03-29 17:51:09 +00005823 Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";
5824 Result += VarName; Result += CDecl->getNameAsString();
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005825 Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";
5826 Result += "\t";
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005827 if (metaclass) {
5828 if (!rootClass) {
5829 Result += "0, // &"; Result += VarName;
5830 Result += RootClass->getNameAsString();
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005831 Result += ",\n\t";
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005832 Result += "0, // &"; Result += VarName;
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005833 Result += CDecl->getSuperClass()->getNameAsString();
5834 Result += ",\n\t";
5835 }
5836 else {
Fariborz Jahanian452eac12012-03-20 21:09:58 +00005837 Result += "0, // &"; Result += VarName;
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005838 Result += CDecl->getNameAsString();
5839 Result += ",\n\t";
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005840 Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005841 Result += ",\n\t";
5842 }
5843 }
5844 else {
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005845 Result += "0, // &OBJC_METACLASS_$_";
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005846 Result += CDecl->getNameAsString();
5847 Result += ",\n\t";
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005848 if (!rootClass) {
5849 Result += "0, // &"; Result += VarName;
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005850 Result += CDecl->getSuperClass()->getNameAsString();
5851 Result += ",\n\t";
5852 }
5853 else
5854 Result += "0,\n\t";
5855 }
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005856 Result += "0, // (void *)&_objc_empty_cache,\n\t";
5857 Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";
5858 if (metaclass)
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005859 Result += "&_OBJC_METACLASS_RO_$_";
5860 else
5861 Result += "&_OBJC_CLASS_RO_$_";
5862 Result += CDecl->getNameAsString();
5863 Result += ",\n};\n";
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005864
5865 // Add static function to initialize some of the meta-data fields.
5866 // avoid doing it twice.
5867 if (metaclass)
5868 return;
5869
5870 const ObjCInterfaceDecl *SuperClass =
5871 rootClass ? CDecl : CDecl->getSuperClass();
5872
5873 Result += "static void OBJC_CLASS_SETUP_$_";
5874 Result += CDecl->getNameAsString();
5875 Result += "(void ) {\n";
5876 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
5877 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
Fariborz Jahanian452eac12012-03-20 21:09:58 +00005878 Result += RootClass->getNameAsString(); Result += ";\n";
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005879
5880 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
Fariborz Jahanian452eac12012-03-20 21:09:58 +00005881 Result += ".superclass = ";
5882 if (rootClass)
5883 Result += "&OBJC_CLASS_$_";
5884 else
5885 Result += "&OBJC_METACLASS_$_";
5886
Fariborz Jahaniana03e40c2012-03-20 19:54:33 +00005887 Result += SuperClass->getNameAsString(); Result += ";\n";
5888
5889 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
5890 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
5891
5892 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
5893 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
5894 Result += CDecl->getNameAsString(); Result += ";\n";
5895
5896 if (!rootClass) {
5897 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
5898 Result += ".superclass = "; Result += "&OBJC_CLASS_$_";
5899 Result += SuperClass->getNameAsString(); Result += ";\n";
5900 }
5901
5902 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
5903 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
5904 Result += "}\n";
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00005905}
5906
Fariborz Jahanian61186122012-02-17 18:40:41 +00005907static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
5908 std::string &Result,
Fariborz Jahaniane0335782012-03-27 18:41:05 +00005909 ObjCCategoryDecl *CatDecl,
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00005910 ObjCInterfaceDecl *ClassDecl,
Fariborz Jahanian61186122012-02-17 18:40:41 +00005911 ArrayRef<ObjCMethodDecl *> InstanceMethods,
5912 ArrayRef<ObjCMethodDecl *> ClassMethods,
5913 ArrayRef<ObjCProtocolDecl *> RefedProtocols,
5914 ArrayRef<ObjCPropertyDecl *> ClassProperties) {
Fariborz Jahaniane0335782012-03-27 18:41:05 +00005915 StringRef CatName = CatDecl->getName();
NAKAMURA Takumi20f89392012-03-21 03:21:46 +00005916 StringRef ClassName = ClassDecl->getName();
Fariborz Jahanian8c00a1b2012-02-17 20:33:00 +00005917 // must declare an extern class object in case this class is not implemented
5918 // in this TU.
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00005919 Result += "\n";
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005920 Result += "extern \"C\" ";
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00005921 if (ClassDecl->getImplementation())
5922 Result += "__declspec(dllexport) ";
Fariborz Jahanian297976d2012-03-29 17:51:09 +00005923 else
5924 Result += "__declspec(dllimport) ";
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00005925
Fariborz Jahanian3f162c32012-03-27 16:21:30 +00005926 Result += "struct _class_t ";
Fariborz Jahanian8c00a1b2012-02-17 20:33:00 +00005927 Result += "OBJC_CLASS_$_"; Result += ClassName;
5928 Result += ";\n";
5929
Fariborz Jahanian61186122012-02-17 18:40:41 +00005930 Result += "\nstatic struct _category_t ";
5931 Result += "_OBJC_$_CATEGORY_";
5932 Result += ClassName; Result += "_$_"; Result += CatName;
5933 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
5934 Result += "{\n";
5935 Result += "\t\""; Result += ClassName; Result += "\",\n";
Fariborz Jahanian4b2fe6e2012-03-20 21:41:28 +00005936 Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;
Fariborz Jahanian61186122012-02-17 18:40:41 +00005937 Result += ",\n";
5938 if (InstanceMethods.size() > 0) {
5939 Result += "\t(const struct _method_list_t *)&";
5940 Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
5941 Result += ClassName; Result += "_$_"; Result += CatName;
5942 Result += ",\n";
5943 }
5944 else
5945 Result += "\t0,\n";
5946
5947 if (ClassMethods.size() > 0) {
5948 Result += "\t(const struct _method_list_t *)&";
5949 Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";
5950 Result += ClassName; Result += "_$_"; Result += CatName;
5951 Result += ",\n";
5952 }
5953 else
5954 Result += "\t0,\n";
5955
5956 if (RefedProtocols.size() > 0) {
5957 Result += "\t(const struct _protocol_list_t *)&";
5958 Result += "_OBJC_CATEGORY_PROTOCOLS_$_";
5959 Result += ClassName; Result += "_$_"; Result += CatName;
5960 Result += ",\n";
5961 }
5962 else
5963 Result += "\t0,\n";
5964
5965 if (ClassProperties.size() > 0) {
5966 Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_";
5967 Result += ClassName; Result += "_$_"; Result += CatName;
5968 Result += ",\n";
5969 }
5970 else
5971 Result += "\t0,\n";
5972
5973 Result += "};\n";
Fariborz Jahanian4b2fe6e2012-03-20 21:41:28 +00005974
5975 // Add static function to initialize the class pointer in the category structure.
5976 Result += "static void OBJC_CATEGORY_SETUP_$_";
5977 Result += ClassDecl->getNameAsString();
5978 Result += "_$_";
5979 Result += CatName;
5980 Result += "(void ) {\n";
5981 Result += "\t_OBJC_$_CATEGORY_";
5982 Result += ClassDecl->getNameAsString();
5983 Result += "_$_";
5984 Result += CatName;
5985 Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;
5986 Result += ";\n}\n";
Fariborz Jahanian61186122012-02-17 18:40:41 +00005987}
5988
Fariborz Jahaniane0adbd82012-02-08 22:23:26 +00005989static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,
5990 ASTContext *Context, std::string &Result,
5991 ArrayRef<ObjCMethodDecl *> Methods,
5992 StringRef VarName,
5993 StringRef ProtocolName) {
5994 if (Methods.size() == 0)
5995 return;
5996
5997 Result += "\nstatic const char *";
5998 Result += VarName; Result += ProtocolName;
5999 Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
6000 Result += "{\n";
6001 for (unsigned i = 0, e = Methods.size(); i < e; i++) {
6002 ObjCMethodDecl *MD = Methods[i];
6003 std::string MethodTypeString, QuoteMethodTypeString;
6004 Context->getObjCEncodingForMethodDecl(MD, MethodTypeString, true);
6005 RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);
6006 Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";
6007 if (i == e-1)
6008 Result += "\n};\n";
6009 else {
6010 Result += ",\n";
6011 }
6012 }
6013}
6014
Fariborz Jahanian40a777a2012-03-12 16:46:58 +00006015static void Write_IvarOffsetVar(ASTContext *Context,
6016 std::string &Result,
Fariborz Jahaniandb649232012-02-13 20:59:02 +00006017 ArrayRef<ObjCIvarDecl *> Ivars,
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006018 ObjCInterfaceDecl *CDecl) {
Fariborz Jahaniandb649232012-02-13 20:59:02 +00006019 // FIXME. visibilty of offset symbols may have to be set; for Darwin
6020 // this is what happens:
6021 /**
6022 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6023 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6024 Class->getVisibility() == HiddenVisibility)
6025 Visibility shoud be: HiddenVisibility;
6026 else
6027 Visibility shoud be: DefaultVisibility;
6028 */
6029
Fariborz Jahanian07e52882012-02-13 21:34:45 +00006030 Result += "\n";
6031 for (unsigned i =0, e = Ivars.size(); i < e; i++) {
6032 ObjCIvarDecl *IvarDecl = Ivars[i];
Fariborz Jahanian40a777a2012-03-12 16:46:58 +00006033 if (Context->getLangOpts().MicrosoftExt)
6034 Result += "__declspec(allocate(\".objc_ivar$B\")) ";
6035
6036 if (!Context->getLangOpts().MicrosoftExt ||
6037 IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||
Fariborz Jahanian117591f2012-03-10 01:34:42 +00006038 IvarDecl->getAccessControl() == ObjCIvarDecl::Package)
Fariborz Jahanian297976d2012-03-29 17:51:09 +00006039 Result += "extern \"C\" unsigned long int ";
Fariborz Jahaniand1c84d32012-03-10 00:53:02 +00006040 else
Fariborz Jahanian297976d2012-03-29 17:51:09 +00006041 Result += "extern \"C\" __declspec(dllexport) unsigned long int ";
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006042 WriteInternalIvarName(CDecl, IvarDecl, Result);
Fariborz Jahanian07e52882012-02-13 21:34:45 +00006043 Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";
6044 Result += " = ";
6045 if (IvarDecl->isBitField()) {
6046 // FIXME: The hack below doesn't work for bitfields. For now, we simply
6047 // place all bitfields at offset 0.
6048 Result += "0;\n";
6049 }
6050 else {
Fariborz Jahaniandb649232012-02-13 20:59:02 +00006051 Result += "__OFFSETOFIVAR__(struct ";
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006052 Result += CDecl->getNameAsString();
Fariborz Jahaniandb649232012-02-13 20:59:02 +00006053 Result += "_IMPL, ";
6054 Result += IvarDecl->getName(); Result += ");\n";
6055 }
6056 }
6057}
6058
Fariborz Jahanianae932952012-02-10 20:47:10 +00006059static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
6060 ASTContext *Context, std::string &Result,
6061 ArrayRef<ObjCIvarDecl *> Ivars,
6062 StringRef VarName,
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006063 ObjCInterfaceDecl *CDecl) {
Fariborz Jahanianae932952012-02-10 20:47:10 +00006064 if (Ivars.size() > 0) {
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006065 Write_IvarOffsetVar(Context, Result, Ivars, CDecl);
Fariborz Jahanian07e52882012-02-13 21:34:45 +00006066
Fariborz Jahanianae932952012-02-10 20:47:10 +00006067 Result += "\nstatic ";
6068 Write__ivar_list_t_TypeDecl(Result, Ivars.size());
6069 Result += " "; Result += VarName;
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006070 Result += CDecl->getNameAsString();
Fariborz Jahanianae932952012-02-10 20:47:10 +00006071 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6072 Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";
6073 Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";
6074 for (unsigned i =0, e = Ivars.size(); i < e; i++) {
6075 ObjCIvarDecl *IvarDecl = Ivars[i];
6076 if (i == 0)
6077 Result += "\t{{";
6078 else
6079 Result += "\t {";
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006080 Result += "(unsigned long int *)&";
6081 WriteInternalIvarName(CDecl, IvarDecl, Result);
Fariborz Jahaniandb649232012-02-13 20:59:02 +00006082 Result += ", ";
Fariborz Jahanianae932952012-02-10 20:47:10 +00006083
6084 Result += "\""; Result += IvarDecl->getName(); Result += "\", ";
6085 std::string IvarTypeString, QuoteIvarTypeString;
6086 Context->getObjCEncodingForType(IvarDecl->getType(), IvarTypeString,
6087 IvarDecl);
6088 RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);
6089 Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";
6090
Fariborz Jahanian8f1fed02012-02-11 20:10:52 +00006091 // FIXME. this alignment represents the host alignment and need be changed to
6092 // represent the target alignment.
6093 unsigned Align = Context->getTypeAlign(IvarDecl->getType())/8;
6094 Align = llvm::Log2_32(Align);
Fariborz Jahanianae932952012-02-10 20:47:10 +00006095 Result += llvm::utostr(Align); Result += ", ";
Fariborz Jahaniana63b4222012-02-10 23:18:24 +00006096 CharUnits Size = Context->getTypeSizeInChars(IvarDecl->getType());
6097 Result += llvm::utostr(Size.getQuantity());
Fariborz Jahanianae932952012-02-10 20:47:10 +00006098 if (i == e-1)
6099 Result += "}}\n";
6100 else
6101 Result += "},\n";
6102 }
6103 Result += "};\n";
6104 }
6105}
6106
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006107/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00006108void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
6109 std::string &Result) {
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006110
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006111 // Do not synthesize the protocol more than once.
6112 if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
6113 return;
Fariborz Jahaniande5d9462012-03-14 18:09:23 +00006114 WriteModernMetadataDeclarations(Context, Result);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006115
6116 if (ObjCProtocolDecl *Def = PDecl->getDefinition())
6117 PDecl = Def;
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00006118 // Must write out all protocol definitions in current qualifier list,
6119 // and in their nested qualifiers before writing out current definition.
6120 for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
6121 E = PDecl->protocol_end(); I != E; ++I)
6122 RewriteObjCProtocolMetaData(*I, Result);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006123
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006124 // Construct method lists.
6125 std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;
6126 std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;
6127 for (ObjCProtocolDecl::instmeth_iterator
6128 I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
6129 I != E; ++I) {
6130 ObjCMethodDecl *MD = *I;
6131 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6132 OptInstanceMethods.push_back(MD);
6133 } else {
6134 InstanceMethods.push_back(MD);
6135 }
6136 }
6137
6138 for (ObjCProtocolDecl::classmeth_iterator
6139 I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
6140 I != E; ++I) {
6141 ObjCMethodDecl *MD = *I;
6142 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6143 OptClassMethods.push_back(MD);
6144 } else {
6145 ClassMethods.push_back(MD);
6146 }
6147 }
Fariborz Jahaniane0adbd82012-02-08 22:23:26 +00006148 std::vector<ObjCMethodDecl *> AllMethods;
6149 for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)
6150 AllMethods.push_back(InstanceMethods[i]);
6151 for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)
6152 AllMethods.push_back(ClassMethods[i]);
6153 for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)
6154 AllMethods.push_back(OptInstanceMethods[i]);
6155 for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)
6156 AllMethods.push_back(OptClassMethods[i]);
6157
6158 Write__extendedMethodTypes_initializer(*this, Context, Result,
6159 AllMethods,
6160 "_OBJC_PROTOCOL_METHOD_TYPES_",
6161 PDecl->getNameAsString());
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00006162 // Protocol's super protocol list
6163 std::vector<ObjCProtocolDecl *> SuperProtocols;
6164 for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
6165 E = PDecl->protocol_end(); I != E; ++I)
6166 SuperProtocols.push_back(*I);
6167
6168 Write_protocol_list_initializer(Context, Result, SuperProtocols,
6169 "_OBJC_PROTOCOL_REFS_",
6170 PDecl->getNameAsString());
6171
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006172 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006173 "_OBJC_PROTOCOL_INSTANCE_METHODS_",
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006174 PDecl->getNameAsString(), false);
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006175
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006176 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006177 "_OBJC_PROTOCOL_CLASS_METHODS_",
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006178 PDecl->getNameAsString(), false);
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006179
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006180 Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006181 "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006182 PDecl->getNameAsString(), false);
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006183
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006184 Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006185 "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006186 PDecl->getNameAsString(), false);
Fariborz Jahanian77e4bca2012-02-07 20:15:08 +00006187
Fariborz Jahanianda35eac2012-02-07 23:31:52 +00006188 // Protocol's property metadata.
6189 std::vector<ObjCPropertyDecl *> ProtocolProperties;
6190 for (ObjCContainerDecl::prop_iterator I = PDecl->prop_begin(),
6191 E = PDecl->prop_end(); I != E; ++I)
6192 ProtocolProperties.push_back(*I);
6193
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006194 Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,
Fariborz Jahanianda35eac2012-02-07 23:31:52 +00006195 /* Container */0,
6196 "_OBJC_PROTOCOL_PROPERTIES_",
6197 PDecl->getNameAsString());
Fariborz Jahanianda35eac2012-02-07 23:31:52 +00006198
Fariborz Jahanian82848c22012-02-08 00:50:52 +00006199 // Writer out root metadata for current protocol: struct _protocol_t
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00006200 Result += "\n";
6201 if (LangOpts.MicrosoftExt)
6202 Result += "__declspec(allocate(\".datacoal_nt$B\")) ";
Fariborz Jahanian30650eb2012-03-15 17:05:33 +00006203 Result += "struct _protocol_t _OBJC_PROTOCOL_";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006204 Result += PDecl->getNameAsString();
Fariborz Jahanian82848c22012-02-08 00:50:52 +00006205 Result += " __attribute__ ((used, section (\"__DATA,__datacoal_nt,coalesced\"))) = {\n";
6206 Result += "\t0,\n"; // id is; is null
6207 Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00006208 if (SuperProtocols.size() > 0) {
6209 Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";
6210 Result += PDecl->getNameAsString(); Result += ",\n";
6211 }
6212 else
6213 Result += "\t0,\n";
Fariborz Jahanian82848c22012-02-08 00:50:52 +00006214 if (InstanceMethods.size() > 0) {
6215 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
6216 Result += PDecl->getNameAsString(); Result += ",\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006217 }
6218 else
Fariborz Jahanian82848c22012-02-08 00:50:52 +00006219 Result += "\t0,\n";
6220
6221 if (ClassMethods.size() > 0) {
6222 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";
6223 Result += PDecl->getNameAsString(); Result += ",\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006224 }
6225 else
Fariborz Jahanian82848c22012-02-08 00:50:52 +00006226 Result += "\t0,\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006227
Fariborz Jahanian82848c22012-02-08 00:50:52 +00006228 if (OptInstanceMethods.size() > 0) {
6229 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";
6230 Result += PDecl->getNameAsString(); Result += ",\n";
6231 }
6232 else
6233 Result += "\t0,\n";
6234
6235 if (OptClassMethods.size() > 0) {
6236 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";
6237 Result += PDecl->getNameAsString(); Result += ",\n";
6238 }
6239 else
6240 Result += "\t0,\n";
6241
6242 if (ProtocolProperties.size() > 0) {
6243 Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";
6244 Result += PDecl->getNameAsString(); Result += ",\n";
6245 }
6246 else
6247 Result += "\t0,\n";
6248
6249 Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";
6250 Result += "\t0,\n";
6251
Fariborz Jahaniane0adbd82012-02-08 22:23:26 +00006252 if (AllMethods.size() > 0) {
6253 Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";
6254 Result += PDecl->getNameAsString();
6255 Result += "\n};\n";
6256 }
6257 else
6258 Result += "\t0\n};\n";
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00006259
6260 // Use this protocol meta-data to build protocol list table in section
6261 // .objc_protolist$B
6262 // Unspecified visibility means 'private extern'.
6263 if (LangOpts.MicrosoftExt)
6264 Result += "__declspec(allocate(\".objc_protolist$B\")) ";
6265 Result += "struct _protocol_t *";
6266 Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();
6267 Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
6268 Result += ";\n";
Fariborz Jahanian82848c22012-02-08 00:50:52 +00006269
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006270 // Mark this protocol as having been generated.
6271 if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()))
6272 llvm_unreachable("protocol already synthesized");
6273
6274}
6275
6276void RewriteModernObjC::RewriteObjCProtocolListMetaData(
6277 const ObjCList<ObjCProtocolDecl> &Protocols,
6278 StringRef prefix, StringRef ClassName,
6279 std::string &Result) {
6280 if (Protocols.empty()) return;
6281
6282 for (unsigned i = 0; i != Protocols.size(); i++)
Fariborz Jahanianda9624a2012-02-08 19:53:58 +00006283 RewriteObjCProtocolMetaData(Protocols[i], Result);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006284
6285 // Output the top lovel protocol meta-data for the class.
6286 /* struct _objc_protocol_list {
6287 struct _objc_protocol_list *next;
6288 int protocol_count;
6289 struct _objc_protocol *class_protocols[];
6290 }
6291 */
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00006292 Result += "\n";
6293 if (LangOpts.MicrosoftExt)
6294 Result += "__declspec(allocate(\".cat_cls_meth$B\")) ";
6295 Result += "static struct {\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006296 Result += "\tstruct _objc_protocol_list *next;\n";
6297 Result += "\tint protocol_count;\n";
6298 Result += "\tstruct _objc_protocol *class_protocols[";
6299 Result += utostr(Protocols.size());
6300 Result += "];\n} _OBJC_";
6301 Result += prefix;
6302 Result += "_PROTOCOLS_";
6303 Result += ClassName;
6304 Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
6305 "{\n\t0, ";
6306 Result += utostr(Protocols.size());
6307 Result += "\n";
6308
6309 Result += "\t,{&_OBJC_PROTOCOL_";
6310 Result += Protocols[0]->getNameAsString();
6311 Result += " \n";
6312
6313 for (unsigned i = 1; i != Protocols.size(); i++) {
6314 Result += "\t ,&_OBJC_PROTOCOL_";
6315 Result += Protocols[i]->getNameAsString();
6316 Result += "\n";
6317 }
6318 Result += "\t }\n};\n";
6319}
6320
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00006321/// hasObjCExceptionAttribute - Return true if this class or any super
6322/// class has the __objc_exception__ attribute.
6323/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.
6324static bool hasObjCExceptionAttribute(ASTContext &Context,
6325 const ObjCInterfaceDecl *OID) {
6326 if (OID->hasAttr<ObjCExceptionAttr>())
6327 return true;
6328 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
6329 return hasObjCExceptionAttribute(Context, Super);
6330 return false;
6331}
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006332
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006333void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
6334 std::string &Result) {
6335 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
6336
6337 // Explicitly declared @interface's are already synthesized.
Fariborz Jahanianae932952012-02-10 20:47:10 +00006338 if (CDecl->isImplicitInterfaceDecl())
6339 assert(false &&
6340 "Legacy implicit interface rewriting not supported in moder abi");
Fariborz Jahanian8f1fed02012-02-11 20:10:52 +00006341
Fariborz Jahaniande5d9462012-03-14 18:09:23 +00006342 WriteModernMetadataDeclarations(Context, Result);
Fariborz Jahanianae932952012-02-10 20:47:10 +00006343 SmallVector<ObjCIvarDecl *, 8> IVars;
6344
6345 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
6346 IVD; IVD = IVD->getNextIvar()) {
6347 // Ignore unnamed bit-fields.
6348 if (!IVD->getDeclName())
6349 continue;
6350 IVars.push_back(IVD);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006351 }
6352
Fariborz Jahanianae932952012-02-10 20:47:10 +00006353 Write__ivar_list_t_initializer(*this, Context, Result, IVars,
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006354 "_OBJC_$_INSTANCE_VARIABLES_",
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006355 CDecl);
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006356
6357 // Build _objc_method_list for class's instance methods if needed
6358 SmallVector<ObjCMethodDecl *, 32>
6359 InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
6360
6361 // If any of our property implementations have associated getters or
6362 // setters, produce metadata for them as well.
6363 for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
6364 PropEnd = IDecl->propimpl_end();
6365 Prop != PropEnd; ++Prop) {
6366 if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
6367 continue;
6368 if (!(*Prop)->getPropertyIvarDecl())
6369 continue;
6370 ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
6371 if (!PD)
6372 continue;
6373 if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
6374 if (!Getter->isDefined())
6375 InstanceMethods.push_back(Getter);
6376 if (PD->isReadOnly())
6377 continue;
6378 if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
6379 if (!Setter->isDefined())
6380 InstanceMethods.push_back(Setter);
6381 }
6382
6383 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
6384 "_OBJC_$_INSTANCE_METHODS_",
6385 IDecl->getNameAsString(), true);
6386
6387 SmallVector<ObjCMethodDecl *, 32>
6388 ClassMethods(IDecl->classmeth_begin(), IDecl->classmeth_end());
6389
6390 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
6391 "_OBJC_$_CLASS_METHODS_",
6392 IDecl->getNameAsString(), true);
Fariborz Jahanian0a525342012-02-14 19:31:35 +00006393
6394 // Protocols referenced in class declaration?
6395 // Protocol's super protocol list
6396 std::vector<ObjCProtocolDecl *> RefedProtocols;
6397 const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();
6398 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6399 E = Protocols.end();
6400 I != E; ++I) {
6401 RefedProtocols.push_back(*I);
6402 // Must write out all protocol definitions in current qualifier list,
6403 // and in their nested qualifiers before writing out current definition.
6404 RewriteObjCProtocolMetaData(*I, Result);
6405 }
6406
6407 Write_protocol_list_initializer(Context, Result,
6408 RefedProtocols,
6409 "_OBJC_CLASS_PROTOCOLS_$_",
6410 IDecl->getNameAsString());
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006411
6412 // Protocol's property metadata.
6413 std::vector<ObjCPropertyDecl *> ClassProperties;
6414 for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
6415 E = CDecl->prop_end(); I != E; ++I)
6416 ClassProperties.push_back(*I);
6417
6418 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
Fariborz Jahanian2df089d2012-03-22 17:39:35 +00006419 /* Container */IDecl,
Fariborz Jahanianeeabf382012-02-16 21:57:59 +00006420 "_OBJC_$_PROP_LIST_",
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006421 CDecl->getNameAsString());
Fariborz Jahanian90af4e22012-02-14 17:19:02 +00006422
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006423
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00006424 // Data for initializing _class_ro_t metaclass meta-data
6425 uint32_t flags = CLS_META;
6426 std::string InstanceSize;
6427 std::string InstanceStart;
6428
6429
6430 bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;
6431 if (classIsHidden)
6432 flags |= OBJC2_CLS_HIDDEN;
6433
6434 if (!CDecl->getSuperClass())
6435 // class is root
6436 flags |= CLS_ROOT;
6437 InstanceSize = "sizeof(struct _class_t)";
6438 InstanceStart = InstanceSize;
6439 Write__class_ro_t_initializer(Context, Result, flags,
6440 InstanceStart, InstanceSize,
6441 ClassMethods,
6442 0,
6443 0,
6444 0,
6445 "_OBJC_METACLASS_RO_$_",
6446 CDecl->getNameAsString());
6447
6448
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006449 // Data for initializing _class_ro_t meta-data
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00006450 flags = CLS;
6451 if (classIsHidden)
6452 flags |= OBJC2_CLS_HIDDEN;
6453
6454 if (hasObjCExceptionAttribute(*Context, CDecl))
6455 flags |= CLS_EXCEPTION;
6456
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006457 if (!CDecl->getSuperClass())
6458 // class is root
6459 flags |= CLS_ROOT;
6460
Fariborz Jahanian6ade3432012-02-16 18:54:09 +00006461 InstanceSize.clear();
6462 InstanceStart.clear();
Fariborz Jahanianf1c1d9a2012-02-15 00:50:11 +00006463 if (!ObjCSynthesizedStructs.count(CDecl)) {
6464 InstanceSize = "0";
6465 InstanceStart = "0";
6466 }
6467 else {
6468 InstanceSize = "sizeof(struct ";
6469 InstanceSize += CDecl->getNameAsString();
6470 InstanceSize += "_IMPL)";
6471
6472 ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
6473 if (IVD) {
6474 InstanceStart += "__OFFSETOFIVAR__(struct ";
6475 InstanceStart += CDecl->getNameAsString();
6476 InstanceStart += "_IMPL, ";
6477 InstanceStart += IVD->getNameAsString();
6478 InstanceStart += ")";
6479 }
6480 else
6481 InstanceStart = InstanceSize;
6482 }
6483 Write__class_ro_t_initializer(Context, Result, flags,
6484 InstanceStart, InstanceSize,
6485 InstanceMethods,
6486 RefedProtocols,
6487 IVars,
6488 ClassProperties,
6489 "_OBJC_CLASS_RO_$_",
6490 CDecl->getNameAsString());
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00006491
6492 Write_class_t(Context, Result,
6493 "OBJC_METACLASS_$_",
6494 CDecl, /*metaclass*/true);
6495
6496 Write_class_t(Context, Result,
6497 "OBJC_CLASS_$_",
6498 CDecl, /*metaclass*/false);
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00006499
6500 if (ImplementationIsNonLazy(IDecl))
6501 DefinedNonLazyClasses.push_back(CDecl);
Fariborz Jahanian3f77c7b2012-02-16 21:37:05 +00006502
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006503}
6504
Fariborz Jahaniane0335782012-03-27 18:41:05 +00006505void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {
6506 int ClsDefCount = ClassImplementation.size();
6507 if (!ClsDefCount)
6508 return;
6509 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
6510 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
6511 Result += "static void *OBJC_CLASS_SETUP[] = {\n";
6512 for (int i = 0; i < ClsDefCount; i++) {
6513 ObjCImplementationDecl *IDecl = ClassImplementation[i];
6514 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
6515 Result += "\t(void *)&OBJC_CLASS_SETUP_$_";
6516 Result += CDecl->getName(); Result += ",\n";
6517 }
6518 Result += "};\n";
6519}
6520
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006521void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
6522 int ClsDefCount = ClassImplementation.size();
6523 int CatDefCount = CategoryImplementation.size();
6524
6525 // For each implemented class, write out all its meta data.
6526 for (int i = 0; i < ClsDefCount; i++)
6527 RewriteObjCClassMetaData(ClassImplementation[i], Result);
6528
Fariborz Jahaniane0335782012-03-27 18:41:05 +00006529 RewriteClassSetupInitHook(Result);
6530
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006531 // For each implemented category, write out all its meta data.
6532 for (int i = 0; i < CatDefCount; i++)
6533 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
6534
Fariborz Jahaniane0335782012-03-27 18:41:05 +00006535 RewriteCategorySetupInitHook(Result);
6536
Fariborz Jahaniandf795672012-02-17 00:06:14 +00006537 if (ClsDefCount > 0) {
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00006538 if (LangOpts.MicrosoftExt)
6539 Result += "__declspec(allocate(\".objc_classlist$B\")) ";
Fariborz Jahaniandf795672012-02-17 00:06:14 +00006540 Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";
6541 Result += llvm::utostr(ClsDefCount); Result += "]";
6542 Result +=
6543 " __attribute__((used, section (\"__DATA, __objc_classlist,"
6544 "regular,no_dead_strip\")))= {\n";
6545 for (int i = 0; i < ClsDefCount; i++) {
6546 Result += "\t&OBJC_CLASS_$_";
6547 Result += ClassImplementation[i]->getNameAsString();
6548 Result += ",\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006549 }
Fariborz Jahaniandf795672012-02-17 00:06:14 +00006550 Result += "};\n";
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00006551
6552 if (!DefinedNonLazyClasses.empty()) {
6553 if (LangOpts.MicrosoftExt)
6554 Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";
6555 Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";
6556 for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {
6557 Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();
6558 Result += ",\n";
6559 }
6560 Result += "};\n";
6561 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006562 }
Fariborz Jahanian61186122012-02-17 18:40:41 +00006563
6564 if (CatDefCount > 0) {
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00006565 if (LangOpts.MicrosoftExt)
6566 Result += "__declspec(allocate(\".objc_catlist$B\")) ";
Fariborz Jahanian61186122012-02-17 18:40:41 +00006567 Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";
6568 Result += llvm::utostr(CatDefCount); Result += "]";
6569 Result +=
6570 " __attribute__((used, section (\"__DATA, __objc_catlist,"
6571 "regular,no_dead_strip\")))= {\n";
6572 for (int i = 0; i < CatDefCount; i++) {
6573 Result += "\t&_OBJC_$_CATEGORY_";
6574 Result +=
6575 CategoryImplementation[i]->getClassInterface()->getNameAsString();
6576 Result += "_$_";
6577 Result += CategoryImplementation[i]->getNameAsString();
6578 Result += ",\n";
6579 }
6580 Result += "};\n";
6581 }
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00006582
6583 if (!DefinedNonLazyCategories.empty()) {
6584 if (LangOpts.MicrosoftExt)
6585 Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";
6586 Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";
6587 for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {
6588 Result += "\t&_OBJC_$_CATEGORY_";
6589 Result +=
6590 DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();
6591 Result += "_$_";
6592 Result += DefinedNonLazyCategories[i]->getNameAsString();
6593 Result += ",\n";
6594 }
6595 Result += "};\n";
6596 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006597}
6598
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00006599void RewriteModernObjC::WriteImageInfo(std::string &Result) {
6600 if (LangOpts.MicrosoftExt)
6601 Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";
6602
6603 Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";
6604 // version 0, ObjCABI is 2
Fariborz Jahanian30650eb2012-03-15 17:05:33 +00006605 Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";
Fariborz Jahanian10cde2f2012-03-14 21:44:09 +00006606}
6607
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006608/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
6609/// implementation.
6610void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
6611 std::string &Result) {
Fariborz Jahaniande5d9462012-03-14 18:09:23 +00006612 WriteModernMetadataDeclarations(Context, Result);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006613 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
6614 // Find category declaration for this implementation.
Fariborz Jahanian61186122012-02-17 18:40:41 +00006615 ObjCCategoryDecl *CDecl=0;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006616 for (CDecl = ClassDecl->getCategoryList(); CDecl;
6617 CDecl = CDecl->getNextClassCategory())
6618 if (CDecl->getIdentifier() == IDecl->getIdentifier())
6619 break;
6620
6621 std::string FullCategoryName = ClassDecl->getNameAsString();
Fariborz Jahanian61186122012-02-17 18:40:41 +00006622 FullCategoryName += "_$_";
6623 FullCategoryName += CDecl->getNameAsString();
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006624
6625 // Build _objc_method_list for class's instance methods if needed
6626 SmallVector<ObjCMethodDecl *, 32>
6627 InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
6628
6629 // If any of our property implementations have associated getters or
6630 // setters, produce metadata for them as well.
6631 for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
6632 PropEnd = IDecl->propimpl_end();
6633 Prop != PropEnd; ++Prop) {
6634 if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
6635 continue;
6636 if (!(*Prop)->getPropertyIvarDecl())
6637 continue;
6638 ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
6639 if (!PD)
6640 continue;
6641 if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
6642 InstanceMethods.push_back(Getter);
6643 if (PD->isReadOnly())
6644 continue;
6645 if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
6646 InstanceMethods.push_back(Setter);
6647 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006648
Fariborz Jahanian61186122012-02-17 18:40:41 +00006649 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
6650 "_OBJC_$_CATEGORY_INSTANCE_METHODS_",
6651 FullCategoryName, true);
6652
6653 SmallVector<ObjCMethodDecl *, 32>
6654 ClassMethods(IDecl->classmeth_begin(), IDecl->classmeth_end());
6655
6656 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
6657 "_OBJC_$_CATEGORY_CLASS_METHODS_",
6658 FullCategoryName, true);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006659
6660 // Protocols referenced in class declaration?
Fariborz Jahanian61186122012-02-17 18:40:41 +00006661 // Protocol's super protocol list
6662 std::vector<ObjCProtocolDecl *> RefedProtocols;
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00006663 for (ObjCInterfaceDecl::protocol_iterator I = CDecl->protocol_begin(),
6664 E = CDecl->protocol_end();
6665
6666 I != E; ++I) {
Fariborz Jahanian61186122012-02-17 18:40:41 +00006667 RefedProtocols.push_back(*I);
6668 // Must write out all protocol definitions in current qualifier list,
6669 // and in their nested qualifiers before writing out current definition.
6670 RewriteObjCProtocolMetaData(*I, Result);
6671 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006672
Fariborz Jahanian61186122012-02-17 18:40:41 +00006673 Write_protocol_list_initializer(Context, Result,
6674 RefedProtocols,
6675 "_OBJC_CATEGORY_PROTOCOLS_$_",
6676 FullCategoryName);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006677
Fariborz Jahanian61186122012-02-17 18:40:41 +00006678 // Protocol's property metadata.
6679 std::vector<ObjCPropertyDecl *> ClassProperties;
6680 for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
6681 E = CDecl->prop_end(); I != E; ++I)
6682 ClassProperties.push_back(*I);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006683
Fariborz Jahanian61186122012-02-17 18:40:41 +00006684 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
6685 /* Container */0,
6686 "_OBJC_$_PROP_LIST_",
6687 FullCategoryName);
6688
6689 Write_category_t(*this, Context, Result,
Fariborz Jahaniane0335782012-03-27 18:41:05 +00006690 CDecl,
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00006691 ClassDecl,
Fariborz Jahanian61186122012-02-17 18:40:41 +00006692 InstanceMethods,
6693 ClassMethods,
6694 RefedProtocols,
6695 ClassProperties);
6696
Fariborz Jahanian88f7f752012-03-14 23:18:19 +00006697 // Determine if this category is also "non-lazy".
6698 if (ImplementationIsNonLazy(IDecl))
6699 DefinedNonLazyCategories.push_back(CDecl);
Fariborz Jahaniane0335782012-03-27 18:41:05 +00006700
6701}
6702
6703void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {
6704 int CatDefCount = CategoryImplementation.size();
6705 if (!CatDefCount)
6706 return;
6707 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
6708 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
6709 Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";
6710 for (int i = 0; i < CatDefCount; i++) {
6711 ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];
6712 ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();
6713 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
6714 Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";
6715 Result += ClassDecl->getName();
6716 Result += "_$_";
6717 Result += CatDecl->getName();
6718 Result += ",\n";
6719 }
6720 Result += "};\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006721}
6722
6723// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
6724/// class methods.
6725template<typename MethodIterator>
6726void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
6727 MethodIterator MethodEnd,
6728 bool IsInstanceMethod,
6729 StringRef prefix,
6730 StringRef ClassName,
6731 std::string &Result) {
6732 if (MethodBegin == MethodEnd) return;
6733
6734 if (!objc_impl_method) {
6735 /* struct _objc_method {
6736 SEL _cmd;
6737 char *method_types;
6738 void *_imp;
6739 }
6740 */
6741 Result += "\nstruct _objc_method {\n";
6742 Result += "\tSEL _cmd;\n";
6743 Result += "\tchar *method_types;\n";
6744 Result += "\tvoid *_imp;\n";
6745 Result += "};\n";
6746
6747 objc_impl_method = true;
6748 }
6749
6750 // Build _objc_method_list for class's methods if needed
6751
6752 /* struct {
6753 struct _objc_method_list *next_method;
6754 int method_count;
6755 struct _objc_method method_list[];
6756 }
6757 */
6758 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
Fariborz Jahanian1ca052c2012-03-11 19:41:56 +00006759 Result += "\n";
6760 if (LangOpts.MicrosoftExt) {
6761 if (IsInstanceMethod)
6762 Result += "__declspec(allocate(\".inst_meth$B\")) ";
6763 else
6764 Result += "__declspec(allocate(\".cls_meth$B\")) ";
6765 }
6766 Result += "static struct {\n";
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006767 Result += "\tstruct _objc_method_list *next_method;\n";
6768 Result += "\tint method_count;\n";
6769 Result += "\tstruct _objc_method method_list[";
6770 Result += utostr(NumMethods);
6771 Result += "];\n} _OBJC_";
6772 Result += prefix;
6773 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
6774 Result += "_METHODS_";
6775 Result += ClassName;
6776 Result += " __attribute__ ((used, section (\"__OBJC, __";
6777 Result += IsInstanceMethod ? "inst" : "cls";
6778 Result += "_meth\")))= ";
6779 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
6780
6781 Result += "\t,{{(SEL)\"";
6782 Result += (*MethodBegin)->getSelector().getAsString().c_str();
6783 std::string MethodTypeString;
6784 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
6785 Result += "\", \"";
6786 Result += MethodTypeString;
6787 Result += "\", (void *)";
6788 Result += MethodInternalNames[*MethodBegin];
6789 Result += "}\n";
6790 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
6791 Result += "\t ,{(SEL)\"";
6792 Result += (*MethodBegin)->getSelector().getAsString().c_str();
6793 std::string MethodTypeString;
6794 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
6795 Result += "\", \"";
6796 Result += MethodTypeString;
6797 Result += "\", (void *)";
6798 Result += MethodInternalNames[*MethodBegin];
6799 Result += "}\n";
6800 }
6801 Result += "\t }\n};\n";
6802}
6803
6804Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
6805 SourceRange OldRange = IV->getSourceRange();
6806 Expr *BaseExpr = IV->getBase();
6807
6808 // Rewrite the base, but without actually doing replaces.
6809 {
6810 DisableReplaceStmtScope S(*this);
6811 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
6812 IV->setBase(BaseExpr);
6813 }
6814
6815 ObjCIvarDecl *D = IV->getDecl();
6816
6817 Expr *Replacement = IV;
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006818
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006819 if (BaseExpr->getType()->isObjCObjectPointerType()) {
6820 const ObjCInterfaceType *iFaceDecl =
6821 dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
6822 assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
6823 // lookup which class implements the instance variable.
6824 ObjCInterfaceDecl *clsDeclared = 0;
6825 iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
6826 clsDeclared);
6827 assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
6828
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006829 // Build name of symbol holding ivar offset.
Fariborz Jahanian7cb2a1b2012-03-20 17:13:39 +00006830 std::string IvarOffsetName;
6831 WriteInternalIvarName(clsDeclared, D, IvarOffsetName);
6832
Fariborz Jahanian72c88f12012-02-22 18:13:25 +00006833 ReferencedIvars[clsDeclared].insert(D);
6834
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006835 // cast offset to "char *".
6836 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,
6837 Context->getPointerType(Context->CharTy),
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006838 CK_BitCast,
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006839 BaseExpr);
6840 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
6841 SourceLocation(), &Context->Idents.get(IvarOffsetName),
6842 Context->UnsignedLongTy, 0, SC_Extern, SC_None);
John McCallf4b88a42012-03-10 09:33:50 +00006843 DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false,
6844 Context->UnsignedLongTy, VK_LValue,
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006845 SourceLocation());
6846 BinaryOperator *addExpr =
6847 new (Context) BinaryOperator(castExpr, DRE, BO_Add,
6848 Context->getPointerType(Context->CharTy),
6849 VK_RValue, OK_Ordinary, SourceLocation());
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006850 // Don't forget the parens to enforce the proper binding.
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006851 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
6852 SourceLocation(),
6853 addExpr);
Fariborz Jahanian0d6e22a2012-02-24 17:35:35 +00006854 QualType IvarT = D->getType();
Fariborz Jahanian8e0913d2012-02-29 00:26:20 +00006855 convertObjCTypeToCStyleType(IvarT);
Fariborz Jahanian0d6e22a2012-02-24 17:35:35 +00006856 QualType castT = Context->getPointerType(IvarT);
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006857
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006858 castExpr = NoTypeInfoCStyleCastExpr(Context,
6859 castT,
6860 CK_BitCast,
6861 PE);
Fariborz Jahanian8e0913d2012-02-29 00:26:20 +00006862 Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT,
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006863 VK_LValue, OK_Ordinary,
6864 SourceLocation());
6865 PE = new (Context) ParenExpr(OldRange.getBegin(),
6866 OldRange.getEnd(),
6867 Exp);
6868
6869 Replacement = PE;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006870 }
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006871
Fariborz Jahaniane7b3fa72012-02-21 23:46:48 +00006872 ReplaceStmtWithRange(IV, Replacement, OldRange);
6873 return Replacement;
Fariborz Jahanian64cb63a2012-02-07 17:11:38 +00006874}