1 //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Hacks and fun related to the code rewriter.
12 //===----------------------------------------------------------------------===//
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"
30 using namespace clang
;
34 class RewriteObjC
: public ASTConsumer
{
36 BLOCK_FIELD_IS_OBJECT
= 3, /* id, NSObject, __attribute__((NSObject)),
38 BLOCK_FIELD_IS_BLOCK
= 7, /* a block variable */
39 BLOCK_FIELD_IS_BYREF
= 8, /* the on stack structure holding the
41 BLOCK_FIELD_IS_WEAK
= 16, /* declared __weak, only used in byref copy
43 BLOCK_BYREF_CALLER
= 128, /* called from __block (byref) copy/dispose
45 BLOCK_BYREF_CURRENT_MAX
= 256
49 BLOCK_NEEDS_FREE
= (1 << 24),
50 BLOCK_HAS_COPY_DISPOSE
= (1 << 25),
51 BLOCK_HAS_CXX_OBJ
= (1 << 26),
52 BLOCK_IS_GC
= (1 << 27),
53 BLOCK_IS_GLOBAL
= (1 << 28),
54 BLOCK_HAS_DESCRIPTOR
= (1 << 29)
59 const LangOptions
&LangOpts
;
60 unsigned RewriteFailedDiag
;
61 unsigned TryFinallyContainsReturnDiag
;
65 TranslationUnitDecl
*TUDecl
;
67 const char *MainFileStart
, *MainFileEnd
;
68 SourceLocation LastIncLoc
;
70 llvm::SmallVector
<ObjCImplementationDecl
*, 8> ClassImplementation
;
71 llvm::SmallVector
<ObjCCategoryImplDecl
*, 8> CategoryImplementation
;
72 llvm::SmallPtrSet
<ObjCInterfaceDecl
*, 8> ObjCSynthesizedStructs
;
73 llvm::SmallPtrSet
<ObjCProtocolDecl
*, 8> ObjCSynthesizedProtocols
;
74 llvm::SmallPtrSet
<ObjCInterfaceDecl
*, 8> ObjCForwardDecls
;
75 llvm::DenseMap
<ObjCMethodDecl
*, std::string
> MethodInternalNames
;
76 llvm::SmallVector
<Stmt
*, 32> Stmts
;
77 llvm::SmallVector
<int, 8> ObjCBcLabelNo
;
78 // Remember all the @protocol(<expr>) expressions.
79 llvm::SmallPtrSet
<ObjCProtocolDecl
*, 32> ProtocolExprDecls
;
81 llvm::DenseSet
<uint64_t> CopyDestroyCache
;
83 unsigned NumObjCStringLiterals
;
85 FunctionDecl
*MsgSendFunctionDecl
;
86 FunctionDecl
*MsgSendSuperFunctionDecl
;
87 FunctionDecl
*MsgSendStretFunctionDecl
;
88 FunctionDecl
*MsgSendSuperStretFunctionDecl
;
89 FunctionDecl
*MsgSendFpretFunctionDecl
;
90 FunctionDecl
*GetClassFunctionDecl
;
91 FunctionDecl
*GetMetaClassFunctionDecl
;
92 FunctionDecl
*GetSuperClassFunctionDecl
;
93 FunctionDecl
*SelGetUidFunctionDecl
;
94 FunctionDecl
*CFStringFunctionDecl
;
95 FunctionDecl
*SuperContructorFunctionDecl
;
97 // ObjC string constant support.
98 VarDecl
*ConstantStringClassReference
;
99 RecordDecl
*NSStringRecord
;
101 // ObjC foreach break/continue generation support.
105 ObjCMethodDecl
*CurMethodDef
;
106 RecordDecl
*SuperStructDecl
;
107 RecordDecl
*ConstantStringDecl
;
109 TypeDecl
*ProtocolTypeDecl
;
110 QualType
getProtocolType();
112 // Needed for header files being rewritten
115 std::string InFileName
;
116 llvm::raw_ostream
* OutFile
;
118 bool SilenceRewriteMacroWarning
;
119 bool objc_impl_method
;
121 std::string Preamble
;
123 // Block expressions.
124 llvm::SmallVector
<BlockExpr
*, 32> Blocks
;
125 llvm::SmallVector
<int, 32> InnerDeclRefsCount
;
126 llvm::SmallVector
<BlockDeclRefExpr
*, 32> InnerDeclRefs
;
128 llvm::SmallVector
<BlockDeclRefExpr
*, 32> BlockDeclRefs
;
130 // Block related declarations.
131 llvm::SmallVector
<ValueDecl
*, 8> BlockByCopyDecls
;
132 llvm::SmallPtrSet
<ValueDecl
*, 8> BlockByCopyDeclsPtrSet
;
133 llvm::SmallVector
<ValueDecl
*, 8> BlockByRefDecls
;
134 llvm::SmallPtrSet
<ValueDecl
*, 8> BlockByRefDeclsPtrSet
;
135 llvm::DenseMap
<ValueDecl
*, unsigned> BlockByRefDeclNo
;
136 llvm::SmallPtrSet
<ValueDecl
*, 8> ImportedBlockDecls
;
137 llvm::SmallPtrSet
<VarDecl
*, 8> ImportedLocalExternalDecls
;
139 llvm::DenseMap
<BlockExpr
*, std::string
> RewrittenBlockExprs
;
141 // This maps a property to it's assignment statement.
142 llvm::DenseMap
<ObjCPropertyRefExpr
*, BinaryOperator
*> PropSetters
;
143 // This maps a property to it's synthesied message expression.
144 // This allows us to rewrite chained getters (e.g. o.a.b.c).
145 llvm::DenseMap
<ObjCPropertyRefExpr
*, Stmt
*> PropGetters
;
147 // This maps an original source AST to it's rewritten form. This allows
148 // us to avoid rewriting the same node twice (which is very uncommon).
149 // This is needed to support some of the exotic property rewriting.
150 llvm::DenseMap
<Stmt
*, Stmt
*> ReplacedNodes
;
152 FunctionDecl
*CurFunctionDef
;
153 FunctionDecl
*CurFunctionDeclToDeclareForBlock
;
154 VarDecl
*GlobalVarDecl
;
156 bool DisableReplaceStmt
;
158 static const int OBJC_ABI_VERSION
=7 ;
160 virtual void Initialize(ASTContext
&context
);
162 // Top Level Driver code.
163 virtual void HandleTopLevelDecl(DeclGroupRef D
) {
164 for (DeclGroupRef::iterator I
= D
.begin(), E
= D
.end(); I
!= E
; ++I
)
165 HandleTopLevelSingleDecl(*I
);
167 void HandleTopLevelSingleDecl(Decl
*D
);
168 void HandleDeclInMainFile(Decl
*D
);
169 RewriteObjC(std::string inFile
, llvm::raw_ostream
*OS
,
170 Diagnostic
&D
, const LangOptions
&LOpts
,
171 bool silenceMacroWarn
);
175 virtual void HandleTranslationUnit(ASTContext
&C
);
177 void ReplaceStmt(Stmt
*Old
, Stmt
*New
) {
178 Stmt
*ReplacingStmt
= ReplacedNodes
[Old
];
181 return; // We can't rewrite the same node twice.
183 if (DisableReplaceStmt
)
184 return; // Used when rewriting the assignment of a property setter.
186 // If replacement succeeded or warning disabled return with no warning.
187 if (!Rewrite
.ReplaceStmt(Old
, New
)) {
188 ReplacedNodes
[Old
] = New
;
191 if (SilenceRewriteMacroWarning
)
193 Diags
.Report(Context
->getFullLoc(Old
->getLocStart()), RewriteFailedDiag
)
194 << Old
->getSourceRange();
197 void ReplaceStmtWithRange(Stmt
*Old
, Stmt
*New
, SourceRange SrcRange
) {
198 // Measaure the old text.
199 int Size
= Rewrite
.getRangeSize(SrcRange
);
201 Diags
.Report(Context
->getFullLoc(Old
->getLocStart()), RewriteFailedDiag
)
202 << Old
->getSourceRange();
207 llvm::raw_string_ostream
S(SStr
);
208 New
->printPretty(S
, *Context
, 0, PrintingPolicy(LangOpts
));
209 const std::string
&Str
= S
.str();
211 // If replacement succeeded or warning disabled return with no warning.
212 if (!Rewrite
.ReplaceText(SrcRange
.getBegin(), Size
, Str
)) {
213 ReplacedNodes
[Old
] = New
;
216 if (SilenceRewriteMacroWarning
)
218 Diags
.Report(Context
->getFullLoc(Old
->getLocStart()), RewriteFailedDiag
)
219 << Old
->getSourceRange();
222 void InsertText(SourceLocation Loc
, llvm::StringRef Str
,
223 bool InsertAfter
= true) {
224 // If insertion succeeded or warning disabled return with no warning.
225 if (!Rewrite
.InsertText(Loc
, Str
, InsertAfter
) ||
226 SilenceRewriteMacroWarning
)
229 Diags
.Report(Context
->getFullLoc(Loc
), RewriteFailedDiag
);
232 void ReplaceText(SourceLocation Start
, unsigned OrigLength
,
233 llvm::StringRef Str
) {
234 // If removal succeeded or warning disabled return with no warning.
235 if (!Rewrite
.ReplaceText(Start
, OrigLength
, Str
) ||
236 SilenceRewriteMacroWarning
)
239 Diags
.Report(Context
->getFullLoc(Start
), RewriteFailedDiag
);
242 // Syntactic Rewriting.
243 void RewriteInclude();
244 void RewriteForwardClassDecl(ObjCClassDecl
*Dcl
);
245 void RewritePropertyImplDecl(ObjCPropertyImplDecl
*PID
,
246 ObjCImplementationDecl
*IMD
,
247 ObjCCategoryImplDecl
*CID
);
248 void RewriteInterfaceDecl(ObjCInterfaceDecl
*Dcl
);
249 void RewriteImplementationDecl(Decl
*Dcl
);
250 void RewriteObjCMethodDecl(ObjCMethodDecl
*MDecl
, std::string
&ResultStr
);
251 void RewriteTypeIntoString(QualType T
, std::string
&ResultStr
,
252 const FunctionType
*&FPRetType
);
253 void RewriteByRefString(std::string
&ResultStr
, const std::string
&Name
,
255 void RewriteCategoryDecl(ObjCCategoryDecl
*Dcl
);
256 void RewriteProtocolDecl(ObjCProtocolDecl
*Dcl
);
257 void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl
*Dcl
);
258 void RewriteMethodDeclaration(ObjCMethodDecl
*Method
);
259 void RewriteProperty(ObjCPropertyDecl
*prop
);
260 void RewriteFunctionDecl(FunctionDecl
*FD
);
261 void RewriteBlockPointerType(std::string
& Str
, QualType Type
);
262 void RewriteBlockPointerTypeVariable(std::string
& Str
, ValueDecl
*VD
);
263 void RewriteBlockLiteralFunctionDecl(FunctionDecl
*FD
);
264 void RewriteObjCQualifiedInterfaceTypes(Decl
*Dcl
);
265 void RewriteTypeOfDecl(VarDecl
*VD
);
266 void RewriteObjCQualifiedInterfaceTypes(Expr
*E
);
267 bool needToScanForQualifiers(QualType T
);
268 QualType
getSuperStructType();
269 QualType
getConstantStringStructType();
270 QualType
convertFunctionTypeOfBlocks(const FunctionType
*FT
);
271 bool BufferContainsPPDirectives(const char *startBuf
, const char *endBuf
);
273 // Expression Rewriting.
274 Stmt
*RewriteFunctionBodyOrGlobalInitializer(Stmt
*S
);
275 void CollectPropertySetters(Stmt
*S
);
278 ParentMap
*PropParentMap
; // created lazily.
280 Stmt
*RewriteAtEncode(ObjCEncodeExpr
*Exp
);
281 Stmt
*RewriteObjCIvarRefExpr(ObjCIvarRefExpr
*IV
, SourceLocation OrigStart
,
283 Stmt
*RewriteObjCNestedIvarRefExpr(Stmt
*S
, bool &replaced
);
284 Stmt
*RewritePropertyGetter(ObjCPropertyRefExpr
*PropRefExpr
);
285 Stmt
*RewritePropertySetter(BinaryOperator
*BinOp
, Expr
*newStmt
,
286 SourceRange SrcRange
);
287 Stmt
*RewriteAtSelector(ObjCSelectorExpr
*Exp
);
288 Stmt
*RewriteMessageExpr(ObjCMessageExpr
*Exp
);
289 Stmt
*RewriteObjCStringLiteral(ObjCStringLiteral
*Exp
);
290 Stmt
*RewriteObjCProtocolExpr(ObjCProtocolExpr
*Exp
);
291 void WarnAboutReturnGotoStmts(Stmt
*S
);
292 void HasReturnStmts(Stmt
*S
, bool &hasReturns
);
293 void RewriteTryReturnStmts(Stmt
*S
);
294 void RewriteSyncReturnStmts(Stmt
*S
, std::string buf
);
295 Stmt
*RewriteObjCTryStmt(ObjCAtTryStmt
*S
);
296 Stmt
*RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt
*S
);
297 Stmt
*RewriteObjCThrowStmt(ObjCAtThrowStmt
*S
);
298 Stmt
*RewriteObjCForCollectionStmt(ObjCForCollectionStmt
*S
,
299 SourceLocation OrigEnd
);
300 CallExpr
*SynthesizeCallToFunctionDecl(FunctionDecl
*FD
,
301 Expr
**args
, unsigned nargs
,
302 SourceLocation StartLoc
=SourceLocation(),
303 SourceLocation EndLoc
=SourceLocation());
304 Stmt
*SynthMessageExpr(ObjCMessageExpr
*Exp
,
305 SourceLocation StartLoc
=SourceLocation(),
306 SourceLocation EndLoc
=SourceLocation());
307 Stmt
*RewriteBreakStmt(BreakStmt
*S
);
308 Stmt
*RewriteContinueStmt(ContinueStmt
*S
);
309 void SynthCountByEnumWithState(std::string
&buf
);
311 void SynthMsgSendFunctionDecl();
312 void SynthMsgSendSuperFunctionDecl();
313 void SynthMsgSendStretFunctionDecl();
314 void SynthMsgSendFpretFunctionDecl();
315 void SynthMsgSendSuperStretFunctionDecl();
316 void SynthGetClassFunctionDecl();
317 void SynthGetMetaClassFunctionDecl();
318 void SynthGetSuperClassFunctionDecl();
319 void SynthSelGetUidFunctionDecl();
320 void SynthSuperContructorFunctionDecl();
322 // Metadata emission.
323 void RewriteObjCClassMetaData(ObjCImplementationDecl
*IDecl
,
324 std::string
&Result
);
326 void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl
*CDecl
,
327 std::string
&Result
);
329 template<typename MethodIterator
>
330 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin
,
331 MethodIterator MethodEnd
,
332 bool IsInstanceMethod
,
334 const char *ClassName
,
335 std::string
&Result
);
337 void RewriteObjCProtocolMetaData(ObjCProtocolDecl
*Protocol
,
339 const char *ClassName
,
340 std::string
&Result
);
341 void RewriteObjCProtocolListMetaData(const ObjCList
<ObjCProtocolDecl
> &Prots
,
343 const char *ClassName
,
344 std::string
&Result
);
345 void SynthesizeObjCInternalStruct(ObjCInterfaceDecl
*CDecl
,
346 std::string
&Result
);
347 void SynthesizeIvarOffsetComputation(ObjCContainerDecl
*IDecl
,
349 std::string
&Result
);
350 void RewriteImplementations();
351 void SynthesizeMetaDataIntoBuffer(std::string
&Result
);
354 void RewriteBlocksInFunctionProtoType(QualType funcType
, NamedDecl
*D
);
355 void CheckFunctionPointerDecl(QualType dType
, NamedDecl
*ND
);
357 void InsertBlockLiteralsWithinFunction(FunctionDecl
*FD
);
358 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl
*MD
);
360 // Block specific rewrite rules.
361 void RewriteBlockPointerDecl(NamedDecl
*VD
);
362 void RewriteByRefVar(VarDecl
*VD
);
363 std::string
SynthesizeByrefCopyDestroyHelper(VarDecl
*VD
, int flag
);
364 Stmt
*RewriteBlockDeclRefExpr(Expr
*VD
);
365 Stmt
*RewriteLocalVariableExternalStorage(DeclRefExpr
*DRE
);
366 void RewriteBlockPointerFunctionArgs(FunctionDecl
*FD
);
368 std::string
SynthesizeBlockHelperFuncs(BlockExpr
*CE
, int i
,
369 const char *funcName
, std::string Tag
);
370 std::string
SynthesizeBlockFunc(BlockExpr
*CE
, int i
,
371 const char *funcName
, std::string Tag
);
372 std::string
SynthesizeBlockImpl(BlockExpr
*CE
,
373 std::string Tag
, std::string Desc
);
374 std::string
SynthesizeBlockDescriptor(std::string DescTag
,
376 int i
, const char *funcName
,
378 Stmt
*SynthesizeBlockCall(CallExpr
*Exp
, const Expr
* BlockExp
);
379 void SynthesizeBlockLiterals(SourceLocation FunLocStart
,
380 const char *FunName
);
381 void RewriteRecordBody(RecordDecl
*RD
);
383 void CollectBlockDeclRefInfo(BlockExpr
*Exp
);
384 void GetBlockDeclRefExprs(Stmt
*S
);
385 void GetInnerBlockDeclRefExprs(Stmt
*S
,
386 llvm::SmallVector
<BlockDeclRefExpr
*, 8> &InnerBlockDeclRefs
,
387 llvm::SmallPtrSet
<const DeclContext
*, 8> &InnerContexts
);
389 // We avoid calling Type::isBlockPointerType(), since it operates on the
390 // canonical type. We only care if the top-level type is a closure pointer.
391 bool isTopLevelBlockPointerType(QualType T
) {
392 return isa
<BlockPointerType
>(T
);
395 /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
396 /// to a function pointer type and upon success, returns true; false
398 bool convertBlockPointerToFunctionPointer(QualType
&T
) {
399 if (isTopLevelBlockPointerType(T
)) {
400 const BlockPointerType
*BPT
= T
->getAs
<BlockPointerType
>();
401 T
= Context
->getPointerType(BPT
->getPointeeType());
407 // FIXME: This predicate seems like it would be useful to add to ASTContext.
408 bool isObjCType(QualType T
) {
409 if (!LangOpts
.ObjC1
&& !LangOpts
.ObjC2
)
412 QualType OCT
= Context
->getCanonicalType(T
).getUnqualifiedType();
414 if (OCT
== Context
->getCanonicalType(Context
->getObjCIdType()) ||
415 OCT
== Context
->getCanonicalType(Context
->getObjCClassType()))
418 if (const PointerType
*PT
= OCT
->getAs
<PointerType
>()) {
419 if (isa
<ObjCInterfaceType
>(PT
->getPointeeType()) ||
420 PT
->getPointeeType()->isObjCQualifiedIdType())
425 bool PointerTypeTakesAnyBlockArguments(QualType QT
);
426 void GetExtentOfArgList(const char *Name
, const char *&LParen
,
427 const char *&RParen
);
428 void RewriteCastExpr(CStyleCastExpr
*CE
);
430 FunctionDecl
*SynthBlockInitFunctionDecl(const char *name
);
431 Stmt
*SynthBlockInitExpr(BlockExpr
*Exp
,
432 const llvm::SmallVector
<BlockDeclRefExpr
*, 8> &InnerBlockDeclRefs
);
434 void QuoteDoublequotes(std::string
&From
, std::string
&To
) {
435 for (unsigned i
= 0; i
< From
.length(); i
++) {
444 // Helper function: create a CStyleCastExpr with trivial type source info.
445 CStyleCastExpr
* NoTypeInfoCStyleCastExpr(ASTContext
*Ctx
, QualType Ty
,
446 CastExpr::CastKind Kind
, Expr
*E
) {
447 TypeSourceInfo
*TInfo
= Ctx
->getTrivialTypeSourceInfo(Ty
, SourceLocation());
448 return CStyleCastExpr::Create(*Ctx
, Ty
, Kind
, E
, 0, TInfo
,
449 SourceLocation(), SourceLocation());
453 void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType
,
455 if (FunctionProtoType
*fproto
= dyn_cast
<FunctionProtoType
>(funcType
)) {
456 for (FunctionProtoType::arg_type_iterator I
= fproto
->arg_type_begin(),
457 E
= fproto
->arg_type_end(); I
&& (I
!= E
); ++I
)
458 if (isTopLevelBlockPointerType(*I
)) {
459 // All the args are checked/rewritten. Don't call twice!
460 RewriteBlockPointerDecl(D
);
466 void RewriteObjC::CheckFunctionPointerDecl(QualType funcType
, NamedDecl
*ND
) {
467 const PointerType
*PT
= funcType
->getAs
<PointerType
>();
468 if (PT
&& PointerTypeTakesAnyBlockArguments(funcType
))
469 RewriteBlocksInFunctionProtoType(PT
->getPointeeType(), ND
);
472 static bool IsHeaderFile(const std::string
&Filename
) {
473 std::string::size_type DotPos
= Filename
.rfind('.');
475 if (DotPos
== std::string::npos
) {
480 std::string Ext
= std::string(Filename
.begin()+DotPos
+1, Filename
.end());
482 // C++ header: .hh or .H;
483 return Ext
== "h" || Ext
== "hh" || Ext
== "H";
486 RewriteObjC::RewriteObjC(std::string inFile
, llvm::raw_ostream
* OS
,
487 Diagnostic
&D
, const LangOptions
&LOpts
,
488 bool silenceMacroWarn
)
489 : Diags(D
), LangOpts(LOpts
), InFileName(inFile
), OutFile(OS
),
490 SilenceRewriteMacroWarning(silenceMacroWarn
) {
491 IsHeader
= IsHeaderFile(inFile
);
492 RewriteFailedDiag
= Diags
.getCustomDiagID(Diagnostic::Warning
,
493 "rewriting sub-expression within a macro (may not be correct)");
494 TryFinallyContainsReturnDiag
= Diags
.getCustomDiagID(Diagnostic::Warning
,
495 "rewriter doesn't support user-specified control flow semantics "
496 "for @try/@finally (code may not execute properly)");
499 ASTConsumer
*clang::CreateObjCRewriter(const std::string
& InFile
,
500 llvm::raw_ostream
* OS
,
502 const LangOptions
&LOpts
,
503 bool SilenceRewriteMacroWarning
) {
504 return new RewriteObjC(InFile
, OS
, Diags
, LOpts
, SilenceRewriteMacroWarning
);
507 void RewriteObjC::Initialize(ASTContext
&context
) {
509 SM
= &Context
->getSourceManager();
510 TUDecl
= Context
->getTranslationUnitDecl();
511 MsgSendFunctionDecl
= 0;
512 MsgSendSuperFunctionDecl
= 0;
513 MsgSendStretFunctionDecl
= 0;
514 MsgSendSuperStretFunctionDecl
= 0;
515 MsgSendFpretFunctionDecl
= 0;
516 GetClassFunctionDecl
= 0;
517 GetMetaClassFunctionDecl
= 0;
518 GetSuperClassFunctionDecl
= 0;
519 SelGetUidFunctionDecl
= 0;
520 CFStringFunctionDecl
= 0;
521 ConstantStringClassReference
= 0;
525 CurFunctionDeclToDeclareForBlock
= 0;
528 ProtocolTypeDecl
= 0;
529 ConstantStringDecl
= 0;
531 SuperContructorFunctionDecl
= 0;
532 NumObjCStringLiterals
= 0;
535 DisableReplaceStmt
= false;
536 objc_impl_method
= false;
538 // Get the ID and start/end of the main file.
539 MainFileID
= SM
->getMainFileID();
540 const llvm::MemoryBuffer
*MainBuf
= SM
->getBuffer(MainFileID
);
541 MainFileStart
= MainBuf
->getBufferStart();
542 MainFileEnd
= MainBuf
->getBufferEnd();
544 Rewrite
.setSourceMgr(Context
->getSourceManager(), Context
->getLangOptions());
546 // declaring objc_selector outside the parameter list removes a silly
547 // scope related warning...
549 Preamble
= "#pragma once\n";
550 Preamble
+= "struct objc_selector; struct objc_class;\n";
551 Preamble
+= "struct __rw_objc_super { struct objc_object *object; ";
552 Preamble
+= "struct objc_object *superClass; ";
553 if (LangOpts
.Microsoft
) {
554 // Add a constructor for creating temporary objects.
555 Preamble
+= "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
557 Preamble
+= "object(o), superClass(s) {} ";
560 Preamble
+= "#ifndef _REWRITER_typedef_Protocol\n";
561 Preamble
+= "typedef struct objc_object Protocol;\n";
562 Preamble
+= "#define _REWRITER_typedef_Protocol\n";
563 Preamble
+= "#endif\n";
564 if (LangOpts
.Microsoft
) {
565 Preamble
+= "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
566 Preamble
+= "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
568 Preamble
+= "#define __OBJC_RW_DLLIMPORT extern\n";
569 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
570 Preamble
+= "(struct objc_object *, struct objc_selector *, ...);\n";
571 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
572 Preamble
+= "(struct objc_super *, struct objc_selector *, ...);\n";
573 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend_stret";
574 Preamble
+= "(struct objc_object *, struct objc_selector *, ...);\n";
575 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper_stret";
576 Preamble
+= "(struct objc_super *, struct objc_selector *, ...);\n";
577 Preamble
+= "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
578 Preamble
+= "(struct objc_object *, struct objc_selector *, ...);\n";
579 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
580 Preamble
+= "(const char *);\n";
581 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
582 Preamble
+= "(struct objc_class *);\n";
583 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
584 Preamble
+= "(const char *);\n";
585 Preamble
+= "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
586 Preamble
+= "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
587 Preamble
+= "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
588 Preamble
+= "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
589 Preamble
+= "__OBJC_RW_DLLIMPORT int objc_exception_match";
590 Preamble
+= "(struct objc_class *, struct objc_object *);\n";
591 // @synchronized hooks.
592 Preamble
+= "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
593 Preamble
+= "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
594 Preamble
+= "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
595 Preamble
+= "#ifndef __FASTENUMERATIONSTATE\n";
596 Preamble
+= "struct __objcFastEnumerationState {\n\t";
597 Preamble
+= "unsigned long state;\n\t";
598 Preamble
+= "void **itemsPtr;\n\t";
599 Preamble
+= "unsigned long *mutationsPtr;\n\t";
600 Preamble
+= "unsigned long extra[5];\n};\n";
601 Preamble
+= "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
602 Preamble
+= "#define __FASTENUMERATIONSTATE\n";
603 Preamble
+= "#endif\n";
604 Preamble
+= "#ifndef __NSCONSTANTSTRINGIMPL\n";
605 Preamble
+= "struct __NSConstantStringImpl {\n";
606 Preamble
+= " int *isa;\n";
607 Preamble
+= " int flags;\n";
608 Preamble
+= " char *str;\n";
609 Preamble
+= " long length;\n";
611 Preamble
+= "#ifdef CF_EXPORT_CONSTANT_STRING\n";
612 Preamble
+= "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
613 Preamble
+= "#else\n";
614 Preamble
+= "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
615 Preamble
+= "#endif\n";
616 Preamble
+= "#define __NSCONSTANTSTRINGIMPL\n";
617 Preamble
+= "#endif\n";
619 Preamble
+= "#ifndef BLOCK_IMPL\n";
620 Preamble
+= "#define BLOCK_IMPL\n";
621 Preamble
+= "struct __block_impl {\n";
622 Preamble
+= " void *isa;\n";
623 Preamble
+= " int Flags;\n";
624 Preamble
+= " int Reserved;\n";
625 Preamble
+= " void *FuncPtr;\n";
627 Preamble
+= "// Runtime copy/destroy helper functions (from Block_private.h)\n";
628 Preamble
+= "#ifdef __OBJC_EXPORT_BLOCKS\n";
629 Preamble
+= "extern \"C\" __declspec(dllexport) "
630 "void _Block_object_assign(void *, const void *, const int);\n";
631 Preamble
+= "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
632 Preamble
+= "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
633 Preamble
+= "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
634 Preamble
+= "#else\n";
635 Preamble
+= "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
636 Preamble
+= "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
637 Preamble
+= "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
638 Preamble
+= "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
639 Preamble
+= "#endif\n";
640 Preamble
+= "#endif\n";
641 if (LangOpts
.Microsoft
) {
642 Preamble
+= "#undef __OBJC_RW_DLLIMPORT\n";
643 Preamble
+= "#undef __OBJC_RW_STATICIMPORT\n";
644 Preamble
+= "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
645 Preamble
+= "#define __attribute__(X)\n";
646 Preamble
+= "#endif\n";
647 Preamble
+= "#define __weak\n";
650 Preamble
+= "#define __block\n";
651 Preamble
+= "#define __weak\n";
653 // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
654 // as this avoids warning in any 64bit/32bit compilation model.
655 Preamble
+= "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
659 //===----------------------------------------------------------------------===//
660 // Top Level Driver Code
661 //===----------------------------------------------------------------------===//
663 void RewriteObjC::HandleTopLevelSingleDecl(Decl
*D
) {
664 if (Diags
.hasErrorOccurred())
667 // Two cases: either the decl could be in the main file, or it could be in a
668 // #included file. If the former, rewrite it now. If the later, check to see
669 // if we rewrote the #include/#import.
670 SourceLocation Loc
= D
->getLocation();
671 Loc
= SM
->getInstantiationLoc(Loc
);
673 // If this is for a builtin, ignore it.
674 if (Loc
.isInvalid()) return;
676 // Look for built-in declarations that we need to refer during the rewrite.
677 if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(D
)) {
678 RewriteFunctionDecl(FD
);
679 } else if (VarDecl
*FVD
= dyn_cast
<VarDecl
>(D
)) {
680 // declared in <Foundation/NSString.h>
681 if (strcmp(FVD
->getNameAsCString(), "_NSConstantStringClassReference") == 0) {
682 ConstantStringClassReference
= FVD
;
685 } else if (ObjCInterfaceDecl
*MD
= dyn_cast
<ObjCInterfaceDecl
>(D
)) {
686 RewriteInterfaceDecl(MD
);
687 } else if (ObjCCategoryDecl
*CD
= dyn_cast
<ObjCCategoryDecl
>(D
)) {
688 RewriteCategoryDecl(CD
);
689 } else if (ObjCProtocolDecl
*PD
= dyn_cast
<ObjCProtocolDecl
>(D
)) {
690 RewriteProtocolDecl(PD
);
691 } else if (ObjCForwardProtocolDecl
*FP
=
692 dyn_cast
<ObjCForwardProtocolDecl
>(D
)){
693 RewriteForwardProtocolDecl(FP
);
694 } else if (LinkageSpecDecl
*LSD
= dyn_cast
<LinkageSpecDecl
>(D
)) {
695 // Recurse into linkage specifications
696 for (DeclContext::decl_iterator DI
= LSD
->decls_begin(),
697 DIEnd
= LSD
->decls_end();
699 HandleTopLevelSingleDecl(*DI
);
701 // If we have a decl in the main file, see if we should rewrite it.
702 if (SM
->isFromMainFile(Loc
))
703 return HandleDeclInMainFile(D
);
706 //===----------------------------------------------------------------------===//
707 // Syntactic (non-AST) Rewriting Code
708 //===----------------------------------------------------------------------===//
710 void RewriteObjC::RewriteInclude() {
711 SourceLocation LocStart
= SM
->getLocForStartOfFile(MainFileID
);
712 llvm::StringRef MainBuf
= SM
->getBufferData(MainFileID
);
713 const char *MainBufStart
= MainBuf
.begin();
714 const char *MainBufEnd
= MainBuf
.end();
715 size_t ImportLen
= strlen("import");
717 // Loop over the whole file, looking for includes.
718 for (const char *BufPtr
= MainBufStart
; BufPtr
< MainBufEnd
; ++BufPtr
) {
719 if (*BufPtr
== '#') {
720 if (++BufPtr
== MainBufEnd
)
722 while (*BufPtr
== ' ' || *BufPtr
== '\t')
723 if (++BufPtr
== MainBufEnd
)
725 if (!strncmp(BufPtr
, "import", ImportLen
)) {
726 // replace import with include
727 SourceLocation ImportLoc
=
728 LocStart
.getFileLocWithOffset(BufPtr
-MainBufStart
);
729 ReplaceText(ImportLoc
, ImportLen
, "include");
736 static std::string
getIvarAccessString(ObjCInterfaceDecl
*ClassDecl
,
740 S
+= ClassDecl
->getIdentifier()->getName();
741 S
+= "_IMPL *)self)->";
746 void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl
*PID
,
747 ObjCImplementationDecl
*IMD
,
748 ObjCCategoryImplDecl
*CID
) {
749 static bool objcGetPropertyDefined
= false;
750 static bool objcSetPropertyDefined
= false;
751 SourceLocation startLoc
= PID
->getLocStart();
752 InsertText(startLoc
, "// ");
753 const char *startBuf
= SM
->getCharacterData(startLoc
);
754 assert((*startBuf
== '@') && "bogus @synthesize location");
755 const char *semiBuf
= strchr(startBuf
, ';');
756 assert((*semiBuf
== ';') && "@synthesize: can't find ';'");
757 SourceLocation onePastSemiLoc
=
758 startLoc
.getFileLocWithOffset(semiBuf
-startBuf
+1);
760 if (PID
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
761 return; // FIXME: is this correct?
763 // Generate the 'getter' function.
764 ObjCPropertyDecl
*PD
= PID
->getPropertyDecl();
765 ObjCInterfaceDecl
*ClassDecl
= PD
->getGetterMethodDecl()->getClassInterface();
766 ObjCIvarDecl
*OID
= PID
->getPropertyIvarDecl();
770 unsigned Attributes
= PD
->getPropertyAttributes();
771 bool GenGetProperty
= !(Attributes
& ObjCPropertyDecl::OBJC_PR_nonatomic
) &&
772 (Attributes
& (ObjCPropertyDecl::OBJC_PR_retain
|
773 ObjCPropertyDecl::OBJC_PR_copy
));
775 if (GenGetProperty
&& !objcGetPropertyDefined
) {
776 objcGetPropertyDefined
= true;
777 // FIXME. Is this attribute correct in all cases?
778 Getr
= "\nextern \"C\" __declspec(dllimport) "
779 "id objc_getProperty(id, SEL, long, bool);\n";
781 RewriteObjCMethodDecl(PD
->getGetterMethodDecl(), Getr
);
783 // Synthesize an explicit cast to gain access to the ivar.
784 // See objc-act.c:objc_synthesize_new_getter() for details.
785 if (GenGetProperty
) {
786 // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
788 const FunctionType
*FPRetType
= 0;
789 RewriteTypeIntoString(PD
->getGetterMethodDecl()->getResultType(), Getr
,
793 Getr
+= ")"; // close the precedence "scope" for "*".
795 // Now, emit the argument types (if any).
796 if (const FunctionProtoType
*FT
= dyn_cast
<FunctionProtoType
>(FPRetType
)){
798 for (unsigned i
= 0, e
= FT
->getNumArgs(); i
!= e
; ++i
) {
800 std::string ParamStr
= FT
->getArgType(i
).getAsString(
801 Context
->PrintingPolicy
);
804 if (FT
->isVariadic()) {
805 if (FT
->getNumArgs()) Getr
+= ", ";
813 Getr
+= "return (_TYPE)";
814 Getr
+= "objc_getProperty(self, _cmd, ";
815 SynthesizeIvarOffsetComputation(ClassDecl
, OID
, Getr
);
819 Getr
+= "return " + getIvarAccessString(ClassDecl
, OID
);
821 InsertText(onePastSemiLoc
, Getr
);
822 if (PD
->isReadOnly())
825 // Generate the 'setter' function.
827 bool GenSetProperty
= Attributes
& (ObjCPropertyDecl::OBJC_PR_retain
|
828 ObjCPropertyDecl::OBJC_PR_copy
);
829 if (GenSetProperty
&& !objcSetPropertyDefined
) {
830 objcSetPropertyDefined
= true;
831 // FIXME. Is this attribute correct in all cases?
832 Setr
= "\nextern \"C\" __declspec(dllimport) "
833 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
836 RewriteObjCMethodDecl(PD
->getSetterMethodDecl(), Setr
);
838 // Synthesize an explicit cast to initialize the ivar.
839 // See objc-act.c:objc_synthesize_new_setter() for details.
840 if (GenSetProperty
) {
841 Setr
+= "objc_setProperty (self, _cmd, ";
842 SynthesizeIvarOffsetComputation(ClassDecl
, OID
, Setr
);
844 Setr
+= PD
->getNameAsCString();
846 if (Attributes
& ObjCPropertyDecl::OBJC_PR_nonatomic
)
850 if (Attributes
& ObjCPropertyDecl::OBJC_PR_copy
)
856 Setr
+= getIvarAccessString(ClassDecl
, OID
) + " = ";
857 Setr
+= PD
->getNameAsCString();
860 InsertText(onePastSemiLoc
, Setr
);
863 void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl
*ClassDecl
) {
864 // Get the start location and compute the semi location.
865 SourceLocation startLoc
= ClassDecl
->getLocation();
866 const char *startBuf
= SM
->getCharacterData(startLoc
);
867 const char *semiPtr
= strchr(startBuf
, ';');
869 // Translate to typedef's that forward reference structs with the same name
870 // as the class. As a convenience, we include the original declaration
872 std::string typedefString
;
873 typedefString
+= "// @class ";
874 for (ObjCClassDecl::iterator I
= ClassDecl
->begin(), E
= ClassDecl
->end();
876 ObjCInterfaceDecl
*ForwardDecl
= I
->getInterface();
877 typedefString
+= ForwardDecl
->getNameAsString();
879 typedefString
+= ", ";
881 typedefString
+= ";\n";
884 for (ObjCClassDecl::iterator I
= ClassDecl
->begin(), E
= ClassDecl
->end();
886 ObjCInterfaceDecl
*ForwardDecl
= I
->getInterface();
887 typedefString
+= "#ifndef _REWRITER_typedef_";
888 typedefString
+= ForwardDecl
->getNameAsString();
889 typedefString
+= "\n";
890 typedefString
+= "#define _REWRITER_typedef_";
891 typedefString
+= ForwardDecl
->getNameAsString();
892 typedefString
+= "\n";
893 typedefString
+= "typedef struct objc_object ";
894 typedefString
+= ForwardDecl
->getNameAsString();
895 typedefString
+= ";\n#endif\n";
898 // Replace the @class with typedefs corresponding to the classes.
899 ReplaceText(startLoc
, semiPtr
-startBuf
+1, typedefString
);
902 void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl
*Method
) {
903 // When method is a synthesized one, such as a getter/setter there is
904 // nothing to rewrite.
905 if (Method
->isSynthesized())
907 SourceLocation LocStart
= Method
->getLocStart();
908 SourceLocation LocEnd
= Method
->getLocEnd();
910 if (SM
->getInstantiationLineNumber(LocEnd
) >
911 SM
->getInstantiationLineNumber(LocStart
)) {
912 InsertText(LocStart
, "#if 0\n");
913 ReplaceText(LocEnd
, 1, ";\n#endif\n");
915 InsertText(LocStart
, "// ");
919 void RewriteObjC::RewriteProperty(ObjCPropertyDecl
*prop
) {
920 SourceLocation Loc
= prop
->getAtLoc();
922 ReplaceText(Loc
, 0, "// ");
923 // FIXME: handle properties that are declared across multiple lines.
926 void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl
*CatDecl
) {
927 SourceLocation LocStart
= CatDecl
->getLocStart();
929 // FIXME: handle category headers that are declared across multiple lines.
930 ReplaceText(LocStart
, 0, "// ");
932 for (ObjCCategoryDecl::prop_iterator I
= CatDecl
->prop_begin(),
933 E
= CatDecl
->prop_end(); I
!= E
; ++I
)
936 for (ObjCCategoryDecl::instmeth_iterator
937 I
= CatDecl
->instmeth_begin(), E
= CatDecl
->instmeth_end();
939 RewriteMethodDeclaration(*I
);
940 for (ObjCCategoryDecl::classmeth_iterator
941 I
= CatDecl
->classmeth_begin(), E
= CatDecl
->classmeth_end();
943 RewriteMethodDeclaration(*I
);
945 // Lastly, comment out the @end.
946 ReplaceText(CatDecl
->getAtEndRange().getBegin(),
947 strlen("@end"), "/* @end */");
950 void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl
*PDecl
) {
951 SourceLocation LocStart
= PDecl
->getLocStart();
953 // FIXME: handle protocol headers that are declared across multiple lines.
954 ReplaceText(LocStart
, 0, "// ");
956 for (ObjCProtocolDecl::instmeth_iterator
957 I
= PDecl
->instmeth_begin(), E
= PDecl
->instmeth_end();
959 RewriteMethodDeclaration(*I
);
960 for (ObjCProtocolDecl::classmeth_iterator
961 I
= PDecl
->classmeth_begin(), E
= PDecl
->classmeth_end();
963 RewriteMethodDeclaration(*I
);
965 // Lastly, comment out the @end.
966 SourceLocation LocEnd
= PDecl
->getAtEndRange().getBegin();
967 ReplaceText(LocEnd
, strlen("@end"), "/* @end */");
969 // Must comment out @optional/@required
970 const char *startBuf
= SM
->getCharacterData(LocStart
);
971 const char *endBuf
= SM
->getCharacterData(LocEnd
);
972 for (const char *p
= startBuf
; p
< endBuf
; p
++) {
973 if (*p
== '@' && !strncmp(p
+1, "optional", strlen("optional"))) {
974 SourceLocation OptionalLoc
= LocStart
.getFileLocWithOffset(p
-startBuf
);
975 ReplaceText(OptionalLoc
, strlen("@optional"), "/* @optional */");
978 else if (*p
== '@' && !strncmp(p
+1, "required", strlen("required"))) {
979 SourceLocation OptionalLoc
= LocStart
.getFileLocWithOffset(p
-startBuf
);
980 ReplaceText(OptionalLoc
, strlen("@required"), "/* @required */");
986 void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl
*PDecl
) {
987 SourceLocation LocStart
= PDecl
->getLocation();
988 if (LocStart
.isInvalid())
989 assert(false && "Invalid SourceLocation");
990 // FIXME: handle forward protocol that are declared across multiple lines.
991 ReplaceText(LocStart
, 0, "// ");
994 void RewriteObjC::RewriteTypeIntoString(QualType T
, std::string
&ResultStr
,
995 const FunctionType
*&FPRetType
) {
996 if (T
->isObjCQualifiedIdType())
998 else if (T
->isFunctionPointerType() ||
999 T
->isBlockPointerType()) {
1000 // needs special handling, since pointer-to-functions have special
1001 // syntax (where a decaration models use).
1002 QualType retType
= T
;
1004 if (const PointerType
* PT
= retType
->getAs
<PointerType
>())
1005 PointeeTy
= PT
->getPointeeType();
1006 else if (const BlockPointerType
*BPT
= retType
->getAs
<BlockPointerType
>())
1007 PointeeTy
= BPT
->getPointeeType();
1008 if ((FPRetType
= PointeeTy
->getAs
<FunctionType
>())) {
1009 ResultStr
+= FPRetType
->getResultType().getAsString(
1010 Context
->PrintingPolicy
);
1014 ResultStr
+= T
.getAsString(Context
->PrintingPolicy
);
1017 void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl
*OMD
,
1018 std::string
&ResultStr
) {
1019 //fprintf(stderr,"In RewriteObjCMethodDecl\n");
1020 const FunctionType
*FPRetType
= 0;
1021 ResultStr
+= "\nstatic ";
1022 RewriteTypeIntoString(OMD
->getResultType(), ResultStr
, FPRetType
);
1025 // Unique method name
1026 std::string NameStr
;
1028 if (OMD
->isInstanceMethod())
1033 NameStr
+= OMD
->getClassInterface()->getNameAsString();
1036 if (ObjCCategoryImplDecl
*CID
=
1037 dyn_cast
<ObjCCategoryImplDecl
>(OMD
->getDeclContext())) {
1038 NameStr
+= CID
->getNameAsString();
1041 // Append selector names, replacing ':' with '_'
1043 std::string selString
= OMD
->getSelector().getAsString();
1044 int len
= selString
.size();
1045 for (int i
= 0; i
< len
; i
++)
1046 if (selString
[i
] == ':')
1048 NameStr
+= selString
;
1050 // Remember this name for metadata emission
1051 MethodInternalNames
[OMD
] = NameStr
;
1052 ResultStr
+= NameStr
;
1054 // Rewrite arguments
1057 // invisible arguments
1058 if (OMD
->isInstanceMethod()) {
1059 QualType selfTy
= Context
->getObjCInterfaceType(OMD
->getClassInterface());
1060 selfTy
= Context
->getPointerType(selfTy
);
1061 if (!LangOpts
.Microsoft
) {
1062 if (ObjCSynthesizedStructs
.count(OMD
->getClassInterface()))
1063 ResultStr
+= "struct ";
1065 // When rewriting for Microsoft, explicitly omit the structure name.
1066 ResultStr
+= OMD
->getClassInterface()->getNameAsString();
1070 ResultStr
+= Context
->getObjCClassType().getAsString(
1071 Context
->PrintingPolicy
);
1073 ResultStr
+= " self, ";
1074 ResultStr
+= Context
->getObjCSelType().getAsString(Context
->PrintingPolicy
);
1075 ResultStr
+= " _cmd";
1077 // Method arguments.
1078 for (ObjCMethodDecl::param_iterator PI
= OMD
->param_begin(),
1079 E
= OMD
->param_end(); PI
!= E
; ++PI
) {
1080 ParmVarDecl
*PDecl
= *PI
;
1082 if (PDecl
->getType()->isObjCQualifiedIdType()) {
1084 ResultStr
+= PDecl
->getNameAsString();
1086 std::string Name
= PDecl
->getNameAsString();
1087 QualType QT
= PDecl
->getType();
1088 // Make sure we convert "t (^)(...)" to "t (*)(...)".
1089 if (convertBlockPointerToFunctionPointer(QT
))
1090 QT
.getAsStringInternal(Name
, Context
->PrintingPolicy
);
1092 PDecl
->getType().getAsStringInternal(Name
, Context
->PrintingPolicy
);
1096 if (OMD
->isVariadic())
1097 ResultStr
+= ", ...";
1101 ResultStr
+= ")"; // close the precedence "scope" for "*".
1103 // Now, emit the argument types (if any).
1104 if (const FunctionProtoType
*FT
= dyn_cast
<FunctionProtoType
>(FPRetType
)) {
1106 for (unsigned i
= 0, e
= FT
->getNumArgs(); i
!= e
; ++i
) {
1107 if (i
) ResultStr
+= ", ";
1108 std::string ParamStr
= FT
->getArgType(i
).getAsString(
1109 Context
->PrintingPolicy
);
1110 ResultStr
+= ParamStr
;
1112 if (FT
->isVariadic()) {
1113 if (FT
->getNumArgs()) ResultStr
+= ", ";
1122 void RewriteObjC::RewriteImplementationDecl(Decl
*OID
) {
1123 ObjCImplementationDecl
*IMD
= dyn_cast
<ObjCImplementationDecl
>(OID
);
1124 ObjCCategoryImplDecl
*CID
= dyn_cast
<ObjCCategoryImplDecl
>(OID
);
1126 InsertText(IMD
? IMD
->getLocStart() : CID
->getLocStart(), "// ");
1128 for (ObjCCategoryImplDecl::instmeth_iterator
1129 I
= IMD
? IMD
->instmeth_begin() : CID
->instmeth_begin(),
1130 E
= IMD
? IMD
->instmeth_end() : CID
->instmeth_end();
1132 std::string ResultStr
;
1133 ObjCMethodDecl
*OMD
= *I
;
1134 RewriteObjCMethodDecl(OMD
, ResultStr
);
1135 SourceLocation LocStart
= OMD
->getLocStart();
1136 SourceLocation LocEnd
= OMD
->getCompoundBody()->getLocStart();
1138 const char *startBuf
= SM
->getCharacterData(LocStart
);
1139 const char *endBuf
= SM
->getCharacterData(LocEnd
);
1140 ReplaceText(LocStart
, endBuf
-startBuf
, ResultStr
);
1143 for (ObjCCategoryImplDecl::classmeth_iterator
1144 I
= IMD
? IMD
->classmeth_begin() : CID
->classmeth_begin(),
1145 E
= IMD
? IMD
->classmeth_end() : CID
->classmeth_end();
1147 std::string ResultStr
;
1148 ObjCMethodDecl
*OMD
= *I
;
1149 RewriteObjCMethodDecl(OMD
, ResultStr
);
1150 SourceLocation LocStart
= OMD
->getLocStart();
1151 SourceLocation LocEnd
= OMD
->getCompoundBody()->getLocStart();
1153 const char *startBuf
= SM
->getCharacterData(LocStart
);
1154 const char *endBuf
= SM
->getCharacterData(LocEnd
);
1155 ReplaceText(LocStart
, endBuf
-startBuf
, ResultStr
);
1157 for (ObjCCategoryImplDecl::propimpl_iterator
1158 I
= IMD
? IMD
->propimpl_begin() : CID
->propimpl_begin(),
1159 E
= IMD
? IMD
->propimpl_end() : CID
->propimpl_end();
1161 RewritePropertyImplDecl(*I
, IMD
, CID
);
1164 InsertText(IMD
? IMD
->getLocEnd() : CID
->getLocEnd(), "// ");
1167 void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl
*ClassDecl
) {
1168 std::string ResultStr
;
1169 if (!ObjCForwardDecls
.count(ClassDecl
)) {
1170 // we haven't seen a forward decl - generate a typedef.
1171 ResultStr
= "#ifndef _REWRITER_typedef_";
1172 ResultStr
+= ClassDecl
->getNameAsString();
1174 ResultStr
+= "#define _REWRITER_typedef_";
1175 ResultStr
+= ClassDecl
->getNameAsString();
1177 ResultStr
+= "typedef struct objc_object ";
1178 ResultStr
+= ClassDecl
->getNameAsString();
1179 ResultStr
+= ";\n#endif\n";
1180 // Mark this typedef as having been generated.
1181 ObjCForwardDecls
.insert(ClassDecl
);
1183 SynthesizeObjCInternalStruct(ClassDecl
, ResultStr
);
1185 for (ObjCInterfaceDecl::prop_iterator I
= ClassDecl
->prop_begin(),
1186 E
= ClassDecl
->prop_end(); I
!= E
; ++I
)
1187 RewriteProperty(*I
);
1188 for (ObjCInterfaceDecl::instmeth_iterator
1189 I
= ClassDecl
->instmeth_begin(), E
= ClassDecl
->instmeth_end();
1191 RewriteMethodDeclaration(*I
);
1192 for (ObjCInterfaceDecl::classmeth_iterator
1193 I
= ClassDecl
->classmeth_begin(), E
= ClassDecl
->classmeth_end();
1195 RewriteMethodDeclaration(*I
);
1197 // Lastly, comment out the @end.
1198 ReplaceText(ClassDecl
->getAtEndRange().getBegin(), strlen("@end"),
1202 Stmt
*RewriteObjC::RewritePropertySetter(BinaryOperator
*BinOp
, Expr
*newStmt
,
1203 SourceRange SrcRange
) {
1204 // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
1205 // This allows us to reuse all the fun and games in SynthMessageExpr().
1206 ObjCPropertyRefExpr
*PropRefExpr
= dyn_cast
<ObjCPropertyRefExpr
>(BinOp
->getLHS());
1207 ObjCMessageExpr
*MsgExpr
;
1208 ObjCPropertyDecl
*PDecl
= PropRefExpr
->getProperty();
1209 llvm::SmallVector
<Expr
*, 1> ExprVec
;
1210 ExprVec
.push_back(newStmt
);
1212 Stmt
*Receiver
= PropRefExpr
->getBase();
1213 ObjCPropertyRefExpr
*PRE
= dyn_cast
<ObjCPropertyRefExpr
>(Receiver
);
1214 if (PRE
&& PropGetters
[PRE
]) {
1215 // This allows us to handle chain/nested property getters.
1216 Receiver
= PropGetters
[PRE
];
1218 if (isa
<ObjCSuperExpr
>(Receiver
))
1219 MsgExpr
= ObjCMessageExpr::Create(*Context
,
1220 PDecl
->getType().getNonReferenceType(),
1221 /*FIXME?*/SourceLocation(),
1222 Receiver
->getLocStart(),
1223 /*IsInstanceSuper=*/true,
1224 cast
<Expr
>(Receiver
)->getType(),
1225 PDecl
->getSetterName(),
1226 PDecl
->getSetterMethodDecl(),
1228 /*FIXME:*/SourceLocation());
1230 MsgExpr
= ObjCMessageExpr::Create(*Context
,
1231 PDecl
->getType().getNonReferenceType(),
1232 /*FIXME: */SourceLocation(),
1233 cast
<Expr
>(Receiver
),
1234 PDecl
->getSetterName(),
1235 PDecl
->getSetterMethodDecl(),
1237 /*FIXME:*/SourceLocation());
1238 Stmt
*ReplacingStmt
= SynthMessageExpr(MsgExpr
);
1240 // Now do the actual rewrite.
1241 ReplaceStmtWithRange(BinOp
, ReplacingStmt
, SrcRange
);
1243 // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
1244 // to things that stay around.
1245 Context
->Deallocate(MsgExpr
);
1246 return ReplacingStmt
;
1249 Stmt
*RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr
*PropRefExpr
) {
1250 // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
1251 // This allows us to reuse all the fun and games in SynthMessageExpr().
1252 ObjCMessageExpr
*MsgExpr
;
1253 ObjCPropertyDecl
*PDecl
= PropRefExpr
->getProperty();
1255 Stmt
*Receiver
= PropRefExpr
->getBase();
1257 ObjCPropertyRefExpr
*PRE
= dyn_cast
<ObjCPropertyRefExpr
>(Receiver
);
1258 if (PRE
&& PropGetters
[PRE
]) {
1259 // This allows us to handle chain/nested property getters.
1260 Receiver
= PropGetters
[PRE
];
1263 if (isa
<ObjCSuperExpr
>(Receiver
))
1264 MsgExpr
= ObjCMessageExpr::Create(*Context
,
1265 PDecl
->getType().getNonReferenceType(),
1266 /*FIXME:*/SourceLocation(),
1267 Receiver
->getLocStart(),
1268 /*IsInstanceSuper=*/true,
1269 cast
<Expr
>(Receiver
)->getType(),
1270 PDecl
->getGetterName(),
1271 PDecl
->getGetterMethodDecl(),
1273 /*FIXME:*/SourceLocation());
1275 MsgExpr
= ObjCMessageExpr::Create(*Context
,
1276 PDecl
->getType().getNonReferenceType(),
1277 /*FIXME:*/SourceLocation(),
1278 cast
<Expr
>(Receiver
),
1279 PDecl
->getGetterName(),
1280 PDecl
->getGetterMethodDecl(),
1282 /*FIXME:*/SourceLocation());
1284 Stmt
*ReplacingStmt
= SynthMessageExpr(MsgExpr
);
1287 PropParentMap
= new ParentMap(CurrentBody
);
1289 Stmt
*Parent
= PropParentMap
->getParent(PropRefExpr
);
1290 if (Parent
&& isa
<ObjCPropertyRefExpr
>(Parent
)) {
1291 // We stash away the ReplacingStmt since actually doing the
1292 // replacement/rewrite won't work for nested getters (e.g. obj.p.i)
1293 PropGetters
[PropRefExpr
] = ReplacingStmt
;
1294 // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
1295 // to things that stay around.
1296 Context
->Deallocate(MsgExpr
);
1297 return PropRefExpr
; // return the original...
1299 ReplaceStmt(PropRefExpr
, ReplacingStmt
);
1300 // delete PropRefExpr; elsewhere...
1301 // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
1302 // to things that stay around.
1303 Context
->Deallocate(MsgExpr
);
1304 return ReplacingStmt
;
1308 Stmt
*RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr
*IV
,
1309 SourceLocation OrigStart
,
1311 ObjCIvarDecl
*D
= IV
->getDecl();
1312 const Expr
*BaseExpr
= IV
->getBase();
1314 if (BaseExpr
->getType()->isObjCObjectPointerType()) {
1315 ObjCInterfaceType
*iFaceDecl
=
1316 dyn_cast
<ObjCInterfaceType
>(BaseExpr
->getType()->getPointeeType());
1317 assert(iFaceDecl
&& "RewriteObjCIvarRefExpr - iFaceDecl is null");
1318 // lookup which class implements the instance variable.
1319 ObjCInterfaceDecl
*clsDeclared
= 0;
1320 iFaceDecl
->getDecl()->lookupInstanceVariable(D
->getIdentifier(),
1322 assert(clsDeclared
&& "RewriteObjCIvarRefExpr(): Can't find class");
1324 // Synthesize an explicit cast to gain access to the ivar.
1325 std::string RecName
= clsDeclared
->getIdentifier()->getName();
1327 IdentifierInfo
*II
= &Context
->Idents
.get(RecName
);
1328 RecordDecl
*RD
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
1329 SourceLocation(), II
);
1330 assert(RD
&& "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
1331 QualType castT
= Context
->getPointerType(Context
->getTagDeclType(RD
));
1332 CastExpr
*castExpr
= NoTypeInfoCStyleCastExpr(Context
, castT
,
1333 CastExpr::CK_Unknown
,
1335 // Don't forget the parens to enforce the proper binding.
1336 ParenExpr
*PE
= new (Context
) ParenExpr(IV
->getBase()->getLocStart(),
1337 IV
->getBase()->getLocEnd(),
1340 if (IV
->isFreeIvar() &&
1341 CurMethodDef
->getClassInterface() == iFaceDecl
->getDecl()) {
1342 MemberExpr
*ME
= new (Context
) MemberExpr(PE
, true, D
,
1345 // delete IV; leak for now, see RewritePropertySetter() usage for more info.
1349 // Cannot delete IV->getBase(), since PE points to it.
1350 // Replace the old base with the cast. This is important when doing
1351 // embedded rewrites. For example, [newInv->_container addObject:0].
1355 } else { // we are outside a method.
1356 assert(!IV
->isFreeIvar() && "Cannot have a free standing ivar outside a method");
1358 // Explicit ivar refs need to have a cast inserted.
1359 // FIXME: consider sharing some of this code with the code above.
1360 if (BaseExpr
->getType()->isObjCObjectPointerType()) {
1361 ObjCInterfaceType
*iFaceDecl
=
1362 dyn_cast
<ObjCInterfaceType
>(BaseExpr
->getType()->getPointeeType());
1363 // lookup which class implements the instance variable.
1364 ObjCInterfaceDecl
*clsDeclared
= 0;
1365 iFaceDecl
->getDecl()->lookupInstanceVariable(D
->getIdentifier(),
1367 assert(clsDeclared
&& "RewriteObjCIvarRefExpr(): Can't find class");
1369 // Synthesize an explicit cast to gain access to the ivar.
1370 std::string RecName
= clsDeclared
->getIdentifier()->getName();
1372 IdentifierInfo
*II
= &Context
->Idents
.get(RecName
);
1373 RecordDecl
*RD
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
1374 SourceLocation(), II
);
1375 assert(RD
&& "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
1376 QualType castT
= Context
->getPointerType(Context
->getTagDeclType(RD
));
1377 CastExpr
*castExpr
= NoTypeInfoCStyleCastExpr(Context
, castT
,
1378 CastExpr::CK_Unknown
,
1380 // Don't forget the parens to enforce the proper binding.
1381 ParenExpr
*PE
= new (Context
) ParenExpr(IV
->getBase()->getLocStart(),
1382 IV
->getBase()->getLocEnd(), castExpr
);
1384 // Cannot delete IV->getBase(), since PE points to it.
1385 // Replace the old base with the cast. This is important when doing
1386 // embedded rewrites. For example, [newInv->_container addObject:0].
1394 Stmt
*RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt
*S
, bool &replaced
) {
1395 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
1398 Stmt
*newStmt
= RewriteObjCNestedIvarRefExpr(*CI
, replaced
);
1403 if (ObjCIvarRefExpr
*IvarRefExpr
= dyn_cast
<ObjCIvarRefExpr
>(S
)) {
1404 SourceRange OrigStmtRange
= S
->getSourceRange();
1405 Stmt
*newStmt
= RewriteObjCIvarRefExpr(IvarRefExpr
, OrigStmtRange
.getBegin(),
1409 if (ObjCMessageExpr
*MsgRefExpr
= dyn_cast
<ObjCMessageExpr
>(S
)) {
1410 Stmt
*newStmt
= SynthMessageExpr(MsgRefExpr
);
1416 /// SynthCountByEnumWithState - To print:
1417 /// ((unsigned int (*)
1418 /// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1419 /// (void *)objc_msgSend)((id)l_collection,
1420 /// sel_registerName(
1421 /// "countByEnumeratingWithState:objects:count:"),
1423 /// (id *)items, (unsigned int)16)
1425 void RewriteObjC::SynthCountByEnumWithState(std::string
&buf
) {
1426 buf
+= "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
1427 "id *, unsigned int))(void *)objc_msgSend)";
1429 buf
+= "((id)l_collection,\n\t\t";
1430 buf
+= "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1432 buf
+= "&enumState, "
1433 "(id *)items, (unsigned int)16)";
1436 /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
1437 /// statement to exit to its outer synthesized loop.
1439 Stmt
*RewriteObjC::RewriteBreakStmt(BreakStmt
*S
) {
1440 if (Stmts
.empty() || !isa
<ObjCForCollectionStmt
>(Stmts
.back()))
1442 // replace break with goto __break_label
1445 SourceLocation startLoc
= S
->getLocStart();
1446 buf
= "goto __break_label_";
1447 buf
+= utostr(ObjCBcLabelNo
.back());
1448 ReplaceText(startLoc
, strlen("break"), buf
);
1453 /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
1454 /// statement to continue with its inner synthesized loop.
1456 Stmt
*RewriteObjC::RewriteContinueStmt(ContinueStmt
*S
) {
1457 if (Stmts
.empty() || !isa
<ObjCForCollectionStmt
>(Stmts
.back()))
1459 // replace continue with goto __continue_label
1462 SourceLocation startLoc
= S
->getLocStart();
1463 buf
= "goto __continue_label_";
1464 buf
+= utostr(ObjCBcLabelNo
.back());
1465 ReplaceText(startLoc
, strlen("continue"), buf
);
1470 /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
1472 /// for ( type elem in collection) { stmts; }
1477 /// struct __objcFastEnumerationState enumState = { 0 };
1479 /// id l_collection = (id)collection;
1480 /// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1481 /// objects:items count:16];
1483 /// unsigned long startMutations = *enumState.mutationsPtr;
1485 /// unsigned long counter = 0;
1487 /// if (startMutations != *enumState.mutationsPtr)
1488 /// objc_enumerationMutation(l_collection);
1489 /// elem = (type)enumState.itemsPtr[counter++];
1491 /// __continue_label: ;
1492 /// } while (counter < limit);
1493 /// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1494 /// objects:items count:16]);
1496 /// __break_label: ;
1502 Stmt
*RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt
*S
,
1503 SourceLocation OrigEnd
) {
1504 assert(!Stmts
.empty() && "ObjCForCollectionStmt - Statement stack empty");
1505 assert(isa
<ObjCForCollectionStmt
>(Stmts
.back()) &&
1506 "ObjCForCollectionStmt Statement stack mismatch");
1507 assert(!ObjCBcLabelNo
.empty() &&
1508 "ObjCForCollectionStmt - Label No stack empty");
1510 SourceLocation startLoc
= S
->getLocStart();
1511 const char *startBuf
= SM
->getCharacterData(startLoc
);
1512 const char *elementName
;
1513 std::string elementTypeAsString
;
1516 if (DeclStmt
*DS
= dyn_cast
<DeclStmt
>(S
->getElement())) {
1518 NamedDecl
* D
= cast
<NamedDecl
>(DS
->getSingleDecl());
1519 QualType ElementType
= cast
<ValueDecl
>(D
)->getType();
1520 if (ElementType
->isObjCQualifiedIdType() ||
1521 ElementType
->isObjCQualifiedInterfaceType())
1522 // Simply use 'id' for all qualified types.
1523 elementTypeAsString
= "id";
1525 elementTypeAsString
= ElementType
.getAsString(Context
->PrintingPolicy
);
1526 buf
+= elementTypeAsString
;
1528 elementName
= D
->getNameAsCString();
1533 DeclRefExpr
*DR
= cast
<DeclRefExpr
>(S
->getElement());
1534 elementName
= DR
->getDecl()->getNameAsCString();
1535 ValueDecl
*VD
= cast
<ValueDecl
>(DR
->getDecl());
1536 if (VD
->getType()->isObjCQualifiedIdType() ||
1537 VD
->getType()->isObjCQualifiedInterfaceType())
1538 // Simply use 'id' for all qualified types.
1539 elementTypeAsString
= "id";
1541 elementTypeAsString
= VD
->getType().getAsString(Context
->PrintingPolicy
);
1544 // struct __objcFastEnumerationState enumState = { 0 };
1545 buf
+= "struct __objcFastEnumerationState enumState = { 0 };\n\t";
1547 buf
+= "id items[16];\n\t";
1548 // id l_collection = (id)
1549 buf
+= "id l_collection = (id)";
1550 // Find start location of 'collection' the hard way!
1551 const char *startCollectionBuf
= startBuf
;
1552 startCollectionBuf
+= 3; // skip 'for'
1553 startCollectionBuf
= strchr(startCollectionBuf
, '(');
1554 startCollectionBuf
++; // skip '('
1555 // find 'in' and skip it.
1556 while (*startCollectionBuf
!= ' ' ||
1557 *(startCollectionBuf
+1) != 'i' || *(startCollectionBuf
+2) != 'n' ||
1558 (*(startCollectionBuf
+3) != ' ' &&
1559 *(startCollectionBuf
+3) != '[' && *(startCollectionBuf
+3) != '('))
1560 startCollectionBuf
++;
1561 startCollectionBuf
+= 3;
1563 // Replace: "for (type element in" with string constructed thus far.
1564 ReplaceText(startLoc
, startCollectionBuf
- startBuf
, buf
);
1565 // Replace ')' in for '(' type elem in collection ')' with ';'
1566 SourceLocation rightParenLoc
= S
->getRParenLoc();
1567 const char *rparenBuf
= SM
->getCharacterData(rightParenLoc
);
1568 SourceLocation lparenLoc
= startLoc
.getFileLocWithOffset(rparenBuf
-startBuf
);
1571 // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1572 // objects:items count:16];
1573 // which is synthesized into:
1574 // unsigned int limit =
1575 // ((unsigned int (*)
1576 // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1577 // (void *)objc_msgSend)((id)l_collection,
1578 // sel_registerName(
1579 // "countByEnumeratingWithState:objects:count:"),
1580 // (struct __objcFastEnumerationState *)&state,
1581 // (id *)items, (unsigned int)16);
1582 buf
+= "unsigned long limit =\n\t\t";
1583 SynthCountByEnumWithState(buf
);
1586 /// unsigned long startMutations = *enumState.mutationsPtr;
1588 /// unsigned long counter = 0;
1590 /// if (startMutations != *enumState.mutationsPtr)
1591 /// objc_enumerationMutation(l_collection);
1592 /// elem = (type)enumState.itemsPtr[counter++];
1593 buf
+= "if (limit) {\n\t";
1594 buf
+= "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1595 buf
+= "do {\n\t\t";
1596 buf
+= "unsigned long counter = 0;\n\t\t";
1597 buf
+= "do {\n\t\t\t";
1598 buf
+= "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1599 buf
+= "objc_enumerationMutation(l_collection);\n\t\t\t";
1602 buf
+= elementTypeAsString
;
1603 buf
+= ")enumState.itemsPtr[counter++];";
1604 // Replace ')' in for '(' type elem in collection ')' with all of these.
1605 ReplaceText(lparenLoc
, 1, buf
);
1607 /// __continue_label: ;
1608 /// } while (counter < limit);
1609 /// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1610 /// objects:items count:16]);
1612 /// __break_label: ;
1619 buf
+= "__continue_label_";
1620 buf
+= utostr(ObjCBcLabelNo
.back());
1623 buf
+= "} while (counter < limit);\n\t";
1624 buf
+= "} while (limit = ";
1625 SynthCountByEnumWithState(buf
);
1629 buf
+= elementTypeAsString
;
1631 buf
+= "__break_label_";
1632 buf
+= utostr(ObjCBcLabelNo
.back());
1635 buf
+= "else\n\t\t";
1638 buf
+= elementTypeAsString
;
1642 // Insert all these *after* the statement body.
1643 // FIXME: If this should support Obj-C++, support CXXTryStmt
1644 if (isa
<CompoundStmt
>(S
->getBody())) {
1645 SourceLocation endBodyLoc
= OrigEnd
.getFileLocWithOffset(1);
1646 InsertText(endBodyLoc
, buf
);
1648 /* Need to treat single statements specially. For example:
1650 * for (A *a in b) if (stuff()) break;
1651 * for (A *a in b) xxxyy;
1653 * The following code simply scans ahead to the semi to find the actual end.
1655 const char *stmtBuf
= SM
->getCharacterData(OrigEnd
);
1656 const char *semiBuf
= strchr(stmtBuf
, ';');
1657 assert(semiBuf
&& "Can't find ';'");
1658 SourceLocation endBodyLoc
= OrigEnd
.getFileLocWithOffset(semiBuf
-stmtBuf
+1);
1659 InsertText(endBodyLoc
, buf
);
1662 ObjCBcLabelNo
.pop_back();
1666 /// RewriteObjCSynchronizedStmt -
1667 /// This routine rewrites @synchronized(expr) stmt;
1669 /// objc_sync_enter(expr);
1670 /// @try stmt @finally { objc_sync_exit(expr); }
1672 Stmt
*RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt
*S
) {
1673 // Get the start location and compute the semi location.
1674 SourceLocation startLoc
= S
->getLocStart();
1675 const char *startBuf
= SM
->getCharacterData(startLoc
);
1677 assert((*startBuf
== '@') && "bogus @synchronized location");
1680 buf
= "objc_sync_enter((id)";
1681 const char *lparenBuf
= startBuf
;
1682 while (*lparenBuf
!= '(') lparenBuf
++;
1683 ReplaceText(startLoc
, lparenBuf
-startBuf
+1, buf
);
1684 // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
1685 // the sync expression is typically a message expression that's already
1686 // been rewritten! (which implies the SourceLocation's are invalid).
1687 SourceLocation endLoc
= S
->getSynchBody()->getLocStart();
1688 const char *endBuf
= SM
->getCharacterData(endLoc
);
1689 while (*endBuf
!= ')') endBuf
--;
1690 SourceLocation rparenLoc
= startLoc
.getFileLocWithOffset(endBuf
-startBuf
);
1692 // declare a new scope with two variables, _stack and _rethrow.
1693 buf
+= "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1694 buf
+= "int buf[18/*32-bit i386*/];\n";
1695 buf
+= "char *pointers[4];} _stack;\n";
1696 buf
+= "id volatile _rethrow = 0;\n";
1697 buf
+= "objc_exception_try_enter(&_stack);\n";
1698 buf
+= "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1699 ReplaceText(rparenLoc
, 1, buf
);
1700 startLoc
= S
->getSynchBody()->getLocEnd();
1701 startBuf
= SM
->getCharacterData(startLoc
);
1703 assert((*startBuf
== '}') && "bogus @synchronized block");
1704 SourceLocation lastCurlyLoc
= startLoc
;
1705 buf
= "}\nelse {\n";
1706 buf
+= " _rethrow = objc_exception_extract(&_stack);\n";
1708 buf
+= "{ /* implicit finally clause */\n";
1709 buf
+= " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1711 std::string syncBuf
;
1712 syncBuf
+= " objc_sync_exit(";
1713 Expr
*syncExpr
= NoTypeInfoCStyleCastExpr(Context
, Context
->getObjCIdType(),
1714 CastExpr::CK_Unknown
,
1716 std::string syncExprBufS
;
1717 llvm::raw_string_ostream
syncExprBuf(syncExprBufS
);
1718 syncExpr
->printPretty(syncExprBuf
, *Context
, 0,
1719 PrintingPolicy(LangOpts
));
1720 syncBuf
+= syncExprBuf
.str();
1724 buf
+= "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1728 ReplaceText(lastCurlyLoc
, 1, buf
);
1730 bool hasReturns
= false;
1731 HasReturnStmts(S
->getSynchBody(), hasReturns
);
1733 RewriteSyncReturnStmts(S
->getSynchBody(), syncBuf
);
1738 void RewriteObjC::WarnAboutReturnGotoStmts(Stmt
*S
)
1740 // Perform a bottom up traversal of all children.
1741 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
1744 WarnAboutReturnGotoStmts(*CI
);
1746 if (isa
<ReturnStmt
>(S
) || isa
<GotoStmt
>(S
)) {
1747 Diags
.Report(Context
->getFullLoc(S
->getLocStart()),
1748 TryFinallyContainsReturnDiag
);
1753 void RewriteObjC::HasReturnStmts(Stmt
*S
, bool &hasReturns
)
1755 // Perform a bottom up traversal of all children.
1756 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
1759 HasReturnStmts(*CI
, hasReturns
);
1761 if (isa
<ReturnStmt
>(S
))
1766 void RewriteObjC::RewriteTryReturnStmts(Stmt
*S
) {
1767 // Perform a bottom up traversal of all children.
1768 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
1771 RewriteTryReturnStmts(*CI
);
1773 if (isa
<ReturnStmt
>(S
)) {
1774 SourceLocation startLoc
= S
->getLocStart();
1775 const char *startBuf
= SM
->getCharacterData(startLoc
);
1777 const char *semiBuf
= strchr(startBuf
, ';');
1778 assert((*semiBuf
== ';') && "RewriteTryReturnStmts: can't find ';'");
1779 SourceLocation onePastSemiLoc
= startLoc
.getFileLocWithOffset(semiBuf
-startBuf
+1);
1782 buf
= "{ objc_exception_try_exit(&_stack); return";
1784 ReplaceText(startLoc
, 6, buf
);
1785 InsertText(onePastSemiLoc
, "}");
1790 void RewriteObjC::RewriteSyncReturnStmts(Stmt
*S
, std::string syncExitBuf
) {
1791 // Perform a bottom up traversal of all children.
1792 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
1795 RewriteSyncReturnStmts(*CI
, syncExitBuf
);
1797 if (isa
<ReturnStmt
>(S
)) {
1798 SourceLocation startLoc
= S
->getLocStart();
1799 const char *startBuf
= SM
->getCharacterData(startLoc
);
1801 const char *semiBuf
= strchr(startBuf
, ';');
1802 assert((*semiBuf
== ';') && "RewriteSyncReturnStmts: can't find ';'");
1803 SourceLocation onePastSemiLoc
= startLoc
.getFileLocWithOffset(semiBuf
-startBuf
+1);
1806 buf
= "{ objc_exception_try_exit(&_stack);";
1810 ReplaceText(startLoc
, 6, buf
);
1811 InsertText(onePastSemiLoc
, "}");
1816 Stmt
*RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt
*S
) {
1817 // Get the start location and compute the semi location.
1818 SourceLocation startLoc
= S
->getLocStart();
1819 const char *startBuf
= SM
->getCharacterData(startLoc
);
1821 assert((*startBuf
== '@') && "bogus @try location");
1824 // declare a new scope with two variables, _stack and _rethrow.
1825 buf
= "/* @try scope begin */ { struct _objc_exception_data {\n";
1826 buf
+= "int buf[18/*32-bit i386*/];\n";
1827 buf
+= "char *pointers[4];} _stack;\n";
1828 buf
+= "id volatile _rethrow = 0;\n";
1829 buf
+= "objc_exception_try_enter(&_stack);\n";
1830 buf
+= "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1832 ReplaceText(startLoc
, 4, buf
);
1834 startLoc
= S
->getTryBody()->getLocEnd();
1835 startBuf
= SM
->getCharacterData(startLoc
);
1837 assert((*startBuf
== '}') && "bogus @try block");
1839 SourceLocation lastCurlyLoc
= startLoc
;
1840 if (S
->getNumCatchStmts()) {
1841 startLoc
= startLoc
.getFileLocWithOffset(1);
1842 buf
= " /* @catch begin */ else {\n";
1843 buf
+= " id _caught = objc_exception_extract(&_stack);\n";
1844 buf
+= " objc_exception_try_enter (&_stack);\n";
1845 buf
+= " if (_setjmp(_stack.buf))\n";
1846 buf
+= " _rethrow = objc_exception_extract(&_stack);\n";
1847 buf
+= " else { /* @catch continue */";
1849 InsertText(startLoc
, buf
);
1850 } else { /* no catch list */
1851 buf
= "}\nelse {\n";
1852 buf
+= " _rethrow = objc_exception_extract(&_stack);\n";
1854 ReplaceText(lastCurlyLoc
, 1, buf
);
1856 bool sawIdTypedCatch
= false;
1857 Stmt
*lastCatchBody
= 0;
1858 for (unsigned I
= 0, N
= S
->getNumCatchStmts(); I
!= N
; ++I
) {
1859 ObjCAtCatchStmt
*Catch
= S
->getCatchStmt(I
);
1860 VarDecl
*catchDecl
= Catch
->getCatchParamDecl();
1863 buf
= "if ("; // we are generating code for the first catch clause
1866 startLoc
= Catch
->getLocStart();
1867 startBuf
= SM
->getCharacterData(startLoc
);
1869 assert((*startBuf
== '@') && "bogus @catch location");
1871 const char *lParenLoc
= strchr(startBuf
, '(');
1873 if (Catch
->hasEllipsis()) {
1874 // Now rewrite the body...
1875 lastCatchBody
= Catch
->getCatchBody();
1876 SourceLocation bodyLoc
= lastCatchBody
->getLocStart();
1877 const char *bodyBuf
= SM
->getCharacterData(bodyLoc
);
1878 assert(*SM
->getCharacterData(Catch
->getRParenLoc()) == ')' &&
1879 "bogus @catch paren location");
1880 assert((*bodyBuf
== '{') && "bogus @catch body location");
1882 buf
+= "1) { id _tmp = _caught;";
1883 Rewrite
.ReplaceText(startLoc
, bodyBuf
-startBuf
+1, buf
);
1884 } else if (catchDecl
) {
1885 QualType t
= catchDecl
->getType();
1886 if (t
== Context
->getObjCIdType()) {
1888 ReplaceText(startLoc
, lParenLoc
-startBuf
+1, buf
);
1889 sawIdTypedCatch
= true;
1890 } else if (const ObjCObjectPointerType
*Ptr
=
1891 t
->getAs
<ObjCObjectPointerType
>()) {
1892 // Should be a pointer to a class.
1893 ObjCInterfaceDecl
*IDecl
= Ptr
->getObjectType()->getInterface();
1895 buf
+= "objc_exception_match((struct objc_class *)objc_getClass(\"";
1896 buf
+= IDecl
->getNameAsString();
1897 buf
+= "\"), (struct objc_object *)_caught)) { ";
1898 ReplaceText(startLoc
, lParenLoc
-startBuf
+1, buf
);
1901 // Now rewrite the body...
1902 lastCatchBody
= Catch
->getCatchBody();
1903 SourceLocation rParenLoc
= Catch
->getRParenLoc();
1904 SourceLocation bodyLoc
= lastCatchBody
->getLocStart();
1905 const char *bodyBuf
= SM
->getCharacterData(bodyLoc
);
1906 const char *rParenBuf
= SM
->getCharacterData(rParenLoc
);
1907 assert((*rParenBuf
== ')') && "bogus @catch paren location");
1908 assert((*bodyBuf
== '{') && "bogus @catch body location");
1910 // Here we replace ") {" with "= _caught;" (which initializes and
1911 // declares the @catch parameter).
1912 ReplaceText(rParenLoc
, bodyBuf
-rParenBuf
+1, " = _caught;");
1914 assert(false && "@catch rewrite bug");
1917 // Complete the catch list...
1918 if (lastCatchBody
) {
1919 SourceLocation bodyLoc
= lastCatchBody
->getLocEnd();
1920 assert(*SM
->getCharacterData(bodyLoc
) == '}' &&
1921 "bogus @catch body location");
1923 // Insert the last (implicit) else clause *before* the right curly brace.
1924 bodyLoc
= bodyLoc
.getFileLocWithOffset(-1);
1925 buf
= "} /* last catch end */\n";
1927 buf
+= " _rethrow = _caught;\n";
1928 buf
+= " objc_exception_try_exit(&_stack);\n";
1929 buf
+= "} } /* @catch end */\n";
1930 if (!S
->getFinallyStmt())
1932 InsertText(bodyLoc
, buf
);
1935 lastCurlyLoc
= lastCatchBody
->getLocEnd();
1937 if (ObjCAtFinallyStmt
*finalStmt
= S
->getFinallyStmt()) {
1938 startLoc
= finalStmt
->getLocStart();
1939 startBuf
= SM
->getCharacterData(startLoc
);
1940 assert((*startBuf
== '@') && "bogus @finally start");
1942 ReplaceText(startLoc
, 8, "/* @finally */");
1944 Stmt
*body
= finalStmt
->getFinallyBody();
1945 SourceLocation startLoc
= body
->getLocStart();
1946 SourceLocation endLoc
= body
->getLocEnd();
1947 assert(*SM
->getCharacterData(startLoc
) == '{' &&
1948 "bogus @finally body location");
1949 assert(*SM
->getCharacterData(endLoc
) == '}' &&
1950 "bogus @finally body location");
1952 startLoc
= startLoc
.getFileLocWithOffset(1);
1953 InsertText(startLoc
, " if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1954 endLoc
= endLoc
.getFileLocWithOffset(-1);
1955 InsertText(endLoc
, " if (_rethrow) objc_exception_throw(_rethrow);\n");
1958 lastCurlyLoc
= body
->getLocEnd();
1960 // Now check for any return/continue/go statements within the @try.
1961 WarnAboutReturnGotoStmts(S
->getTryBody());
1962 } else { /* no finally clause - make sure we synthesize an implicit one */
1963 buf
= "{ /* implicit finally clause */\n";
1964 buf
+= " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1965 buf
+= " if (_rethrow) objc_exception_throw(_rethrow);\n";
1967 ReplaceText(lastCurlyLoc
, 1, buf
);
1969 // Now check for any return/continue/go statements within the @try.
1970 // The implicit finally clause won't called if the @try contains any
1972 bool hasReturns
= false;
1973 HasReturnStmts(S
->getTryBody(), hasReturns
);
1975 RewriteTryReturnStmts(S
->getTryBody());
1977 // Now emit the final closing curly brace...
1978 lastCurlyLoc
= lastCurlyLoc
.getFileLocWithOffset(1);
1979 InsertText(lastCurlyLoc
, " } /* @try scope end */\n");
1983 // This can't be done with ReplaceStmt(S, ThrowExpr), since
1984 // the throw expression is typically a message expression that's already
1985 // been rewritten! (which implies the SourceLocation's are invalid).
1986 Stmt
*RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt
*S
) {
1987 // Get the start location and compute the semi location.
1988 SourceLocation startLoc
= S
->getLocStart();
1989 const char *startBuf
= SM
->getCharacterData(startLoc
);
1991 assert((*startBuf
== '@') && "bogus @throw location");
1994 /* void objc_exception_throw(id) __attribute__((noreturn)); */
1995 if (S
->getThrowExpr())
1996 buf
= "objc_exception_throw(";
1997 else // add an implicit argument
1998 buf
= "objc_exception_throw(_caught";
2000 // handle "@ throw" correctly.
2001 const char *wBuf
= strchr(startBuf
, 'w');
2002 assert((*wBuf
== 'w') && "@throw: can't find 'w'");
2003 ReplaceText(startLoc
, wBuf
-startBuf
+1, buf
);
2005 const char *semiBuf
= strchr(startBuf
, ';');
2006 assert((*semiBuf
== ';') && "@throw: can't find ';'");
2007 SourceLocation semiLoc
= startLoc
.getFileLocWithOffset(semiBuf
-startBuf
);
2008 ReplaceText(semiLoc
, 1, ");");
2012 Stmt
*RewriteObjC::RewriteAtEncode(ObjCEncodeExpr
*Exp
) {
2013 // Create a new string expression.
2014 QualType StrType
= Context
->getPointerType(Context
->CharTy
);
2015 std::string StrEncoding
;
2016 Context
->getObjCEncodingForType(Exp
->getEncodedType(), StrEncoding
);
2017 Expr
*Replacement
= StringLiteral::Create(*Context
,StrEncoding
.c_str(),
2018 StrEncoding
.length(), false,StrType
,
2020 ReplaceStmt(Exp
, Replacement
);
2022 // Replace this subexpr in the parent.
2023 // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
2027 Stmt
*RewriteObjC::RewriteAtSelector(ObjCSelectorExpr
*Exp
) {
2028 if (!SelGetUidFunctionDecl
)
2029 SynthSelGetUidFunctionDecl();
2030 assert(SelGetUidFunctionDecl
&& "Can't find sel_registerName() decl");
2031 // Create a call to sel_registerName("selName").
2032 llvm::SmallVector
<Expr
*, 8> SelExprs
;
2033 QualType argType
= Context
->getPointerType(Context
->CharTy
);
2034 SelExprs
.push_back(StringLiteral::Create(*Context
,
2035 Exp
->getSelector().getAsString().c_str(),
2036 Exp
->getSelector().getAsString().size(),
2037 false, argType
, SourceLocation()));
2038 CallExpr
*SelExp
= SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl
,
2039 &SelExprs
[0], SelExprs
.size());
2040 ReplaceStmt(Exp
, SelExp
);
2041 // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
2045 CallExpr
*RewriteObjC::SynthesizeCallToFunctionDecl(
2046 FunctionDecl
*FD
, Expr
**args
, unsigned nargs
, SourceLocation StartLoc
,
2047 SourceLocation EndLoc
) {
2048 // Get the type, we will need to reference it in a couple spots.
2049 QualType msgSendType
= FD
->getType();
2051 // Create a reference to the objc_msgSend() declaration.
2052 DeclRefExpr
*DRE
= new (Context
) DeclRefExpr(FD
, msgSendType
, SourceLocation());
2054 // Now, we cast the reference to a pointer to the objc_msgSend type.
2055 QualType pToFunc
= Context
->getPointerType(msgSendType
);
2056 ImplicitCastExpr
*ICE
=
2057 ImplicitCastExpr::Create(*Context
, pToFunc
, CastExpr::CK_Unknown
,
2058 DRE
, 0, ImplicitCastExpr::RValue
);
2060 const FunctionType
*FT
= msgSendType
->getAs
<FunctionType
>();
2063 new (Context
) CallExpr(*Context
, ICE
, args
, nargs
,
2064 FT
->getCallResultType(*Context
), EndLoc
);
2068 static bool scanForProtocolRefs(const char *startBuf
, const char *endBuf
,
2069 const char *&startRef
, const char *&endRef
) {
2070 while (startBuf
< endBuf
) {
2071 if (*startBuf
== '<')
2072 startRef
= startBuf
; // mark the start.
2073 if (*startBuf
== '>') {
2074 if (startRef
&& *startRef
== '<') {
2075 endRef
= startBuf
; // mark the end.
2085 static void scanToNextArgument(const char *&argRef
) {
2087 while (*argRef
!= ')' && (*argRef
!= ',' || angle
> 0)) {
2090 else if (*argRef
== '>')
2094 assert(angle
== 0 && "scanToNextArgument - bad protocol type syntax");
2097 bool RewriteObjC::needToScanForQualifiers(QualType T
) {
2098 if (T
->isObjCQualifiedIdType())
2100 if (const PointerType
*PT
= T
->getAs
<PointerType
>()) {
2101 if (PT
->getPointeeType()->isObjCQualifiedIdType())
2104 if (T
->isObjCObjectPointerType()) {
2105 T
= T
->getPointeeType();
2106 return T
->isObjCQualifiedInterfaceType();
2111 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr
*E
) {
2112 QualType Type
= E
->getType();
2113 if (needToScanForQualifiers(Type
)) {
2114 SourceLocation Loc
, EndLoc
;
2116 if (const CStyleCastExpr
*ECE
= dyn_cast
<CStyleCastExpr
>(E
)) {
2117 Loc
= ECE
->getLParenLoc();
2118 EndLoc
= ECE
->getRParenLoc();
2120 Loc
= E
->getLocStart();
2121 EndLoc
= E
->getLocEnd();
2123 // This will defend against trying to rewrite synthesized expressions.
2124 if (Loc
.isInvalid() || EndLoc
.isInvalid())
2127 const char *startBuf
= SM
->getCharacterData(Loc
);
2128 const char *endBuf
= SM
->getCharacterData(EndLoc
);
2129 const char *startRef
= 0, *endRef
= 0;
2130 if (scanForProtocolRefs(startBuf
, endBuf
, startRef
, endRef
)) {
2131 // Get the locations of the startRef, endRef.
2132 SourceLocation LessLoc
= Loc
.getFileLocWithOffset(startRef
-startBuf
);
2133 SourceLocation GreaterLoc
= Loc
.getFileLocWithOffset(endRef
-startBuf
+1);
2134 // Comment out the protocol references.
2135 InsertText(LessLoc
, "/*");
2136 InsertText(GreaterLoc
, "*/");
2141 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl
*Dcl
) {
2144 const FunctionProtoType
*proto
= 0;
2145 if (VarDecl
*VD
= dyn_cast
<VarDecl
>(Dcl
)) {
2146 Loc
= VD
->getLocation();
2147 Type
= VD
->getType();
2149 else if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(Dcl
)) {
2150 Loc
= FD
->getLocation();
2151 // Check for ObjC 'id' and class types that have been adorned with protocol
2152 // information (id<p>, C<p>*). The protocol references need to be rewritten!
2153 const FunctionType
*funcType
= FD
->getType()->getAs
<FunctionType
>();
2154 assert(funcType
&& "missing function type");
2155 proto
= dyn_cast
<FunctionProtoType
>(funcType
);
2158 Type
= proto
->getResultType();
2160 else if (FieldDecl
*FD
= dyn_cast
<FieldDecl
>(Dcl
)) {
2161 Loc
= FD
->getLocation();
2162 Type
= FD
->getType();
2167 if (needToScanForQualifiers(Type
)) {
2168 // Since types are unique, we need to scan the buffer.
2170 const char *endBuf
= SM
->getCharacterData(Loc
);
2171 const char *startBuf
= endBuf
;
2172 while (*startBuf
!= ';' && *startBuf
!= '<' && startBuf
!= MainFileStart
)
2173 startBuf
--; // scan backward (from the decl location) for return type.
2174 const char *startRef
= 0, *endRef
= 0;
2175 if (scanForProtocolRefs(startBuf
, endBuf
, startRef
, endRef
)) {
2176 // Get the locations of the startRef, endRef.
2177 SourceLocation LessLoc
= Loc
.getFileLocWithOffset(startRef
-endBuf
);
2178 SourceLocation GreaterLoc
= Loc
.getFileLocWithOffset(endRef
-endBuf
+1);
2179 // Comment out the protocol references.
2180 InsertText(LessLoc
, "/*");
2181 InsertText(GreaterLoc
, "*/");
2185 return; // most likely, was a variable
2186 // Now check arguments.
2187 const char *startBuf
= SM
->getCharacterData(Loc
);
2188 const char *startFuncBuf
= startBuf
;
2189 for (unsigned i
= 0; i
< proto
->getNumArgs(); i
++) {
2190 if (needToScanForQualifiers(proto
->getArgType(i
))) {
2191 // Since types are unique, we need to scan the buffer.
2193 const char *endBuf
= startBuf
;
2194 // scan forward (from the decl location) for argument types.
2195 scanToNextArgument(endBuf
);
2196 const char *startRef
= 0, *endRef
= 0;
2197 if (scanForProtocolRefs(startBuf
, endBuf
, startRef
, endRef
)) {
2198 // Get the locations of the startRef, endRef.
2199 SourceLocation LessLoc
=
2200 Loc
.getFileLocWithOffset(startRef
-startFuncBuf
);
2201 SourceLocation GreaterLoc
=
2202 Loc
.getFileLocWithOffset(endRef
-startFuncBuf
+1);
2203 // Comment out the protocol references.
2204 InsertText(LessLoc
, "/*");
2205 InsertText(GreaterLoc
, "*/");
2207 startBuf
= ++endBuf
;
2210 // If the function name is derived from a macro expansion, then the
2211 // argument buffer will not follow the name. Need to speak with Chris.
2212 while (*startBuf
&& *startBuf
!= ')' && *startBuf
!= ',')
2213 startBuf
++; // scan forward (from the decl location) for argument types.
2219 void RewriteObjC::RewriteTypeOfDecl(VarDecl
*ND
) {
2220 QualType QT
= ND
->getType();
2221 const Type
* TypePtr
= QT
->getAs
<Type
>();
2222 if (!isa
<TypeOfExprType
>(TypePtr
))
2224 while (isa
<TypeOfExprType
>(TypePtr
)) {
2225 const TypeOfExprType
*TypeOfExprTypePtr
= cast
<TypeOfExprType
>(TypePtr
);
2226 QT
= TypeOfExprTypePtr
->getUnderlyingExpr()->getType();
2227 TypePtr
= QT
->getAs
<Type
>();
2229 // FIXME. This will not work for multiple declarators; as in:
2230 // __typeof__(a) b,c,d;
2231 std::string
TypeAsString(QT
.getAsString(Context
->PrintingPolicy
));
2232 SourceLocation DeclLoc
= ND
->getTypeSpecStartLoc();
2233 const char *startBuf
= SM
->getCharacterData(DeclLoc
);
2234 if (ND
->getInit()) {
2235 std::string
Name(ND
->getNameAsString());
2236 TypeAsString
+= " " + Name
+ " = ";
2237 Expr
*E
= ND
->getInit();
2238 SourceLocation startLoc
;
2239 if (const CStyleCastExpr
*ECE
= dyn_cast
<CStyleCastExpr
>(E
))
2240 startLoc
= ECE
->getLParenLoc();
2242 startLoc
= E
->getLocStart();
2243 startLoc
= SM
->getInstantiationLoc(startLoc
);
2244 const char *endBuf
= SM
->getCharacterData(startLoc
);
2245 ReplaceText(DeclLoc
, endBuf
-startBuf
-1, TypeAsString
);
2248 SourceLocation X
= ND
->getLocEnd();
2249 X
= SM
->getInstantiationLoc(X
);
2250 const char *endBuf
= SM
->getCharacterData(X
);
2251 ReplaceText(DeclLoc
, endBuf
-startBuf
-1, TypeAsString
);
2255 // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
2256 void RewriteObjC::SynthSelGetUidFunctionDecl() {
2257 IdentifierInfo
*SelGetUidIdent
= &Context
->Idents
.get("sel_registerName");
2258 llvm::SmallVector
<QualType
, 16> ArgTys
;
2259 ArgTys
.push_back(Context
->getPointerType(Context
->CharTy
.withConst()));
2260 QualType getFuncType
= Context
->getFunctionType(Context
->getObjCSelType(),
2261 &ArgTys
[0], ArgTys
.size(),
2262 false /*isVariadic*/, 0,
2264 FunctionType::ExtInfo());
2265 SelGetUidFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2267 SelGetUidIdent
, getFuncType
, 0,
2268 FunctionDecl::Extern
,
2269 FunctionDecl::None
, false);
2272 void RewriteObjC::RewriteFunctionDecl(FunctionDecl
*FD
) {
2273 // declared in <objc/objc.h>
2274 if (FD
->getIdentifier() &&
2275 strcmp(FD
->getNameAsCString(), "sel_registerName") == 0) {
2276 SelGetUidFunctionDecl
= FD
;
2279 RewriteObjCQualifiedInterfaceTypes(FD
);
2282 void RewriteObjC::RewriteBlockPointerType(std::string
& Str
, QualType Type
) {
2283 std::string
TypeString(Type
.getAsString(Context
->PrintingPolicy
));
2284 const char *argPtr
= TypeString
.c_str();
2285 if (!strchr(argPtr
, '^')) {
2290 Str
+= (*argPtr
== '^' ? '*' : *argPtr
);
2295 // FIXME. Consolidate this routine with RewriteBlockPointerType.
2296 void RewriteObjC::RewriteBlockPointerTypeVariable(std::string
& Str
,
2298 QualType Type
= VD
->getType();
2299 std::string
TypeString(Type
.getAsString(Context
->PrintingPolicy
));
2300 const char *argPtr
= TypeString
.c_str();
2315 Str
+= VD
->getNameAsString();
2326 void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl
*FD
) {
2327 SourceLocation FunLocStart
= FD
->getTypeSpecStartLoc();
2328 const FunctionType
*funcType
= FD
->getType()->getAs
<FunctionType
>();
2329 const FunctionProtoType
*proto
= dyn_cast
<FunctionProtoType
>(funcType
);
2332 QualType Type
= proto
->getResultType();
2333 std::string FdStr
= Type
.getAsString(Context
->PrintingPolicy
);
2335 FdStr
+= FD
->getNameAsCString();
2337 unsigned numArgs
= proto
->getNumArgs();
2338 for (unsigned i
= 0; i
< numArgs
; i
++) {
2339 QualType ArgType
= proto
->getArgType(i
);
2340 RewriteBlockPointerType(FdStr
, ArgType
);
2345 InsertText(FunLocStart
, FdStr
);
2346 CurFunctionDeclToDeclareForBlock
= 0;
2349 // SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
2350 void RewriteObjC::SynthSuperContructorFunctionDecl() {
2351 if (SuperContructorFunctionDecl
)
2353 IdentifierInfo
*msgSendIdent
= &Context
->Idents
.get("__rw_objc_super");
2354 llvm::SmallVector
<QualType
, 16> ArgTys
;
2355 QualType argT
= Context
->getObjCIdType();
2356 assert(!argT
.isNull() && "Can't find 'id' type");
2357 ArgTys
.push_back(argT
);
2358 ArgTys
.push_back(argT
);
2359 QualType msgSendType
= Context
->getFunctionType(Context
->getObjCIdType(),
2360 &ArgTys
[0], ArgTys
.size(),
2363 FunctionType::ExtInfo());
2364 SuperContructorFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2366 msgSendIdent
, msgSendType
, 0,
2367 FunctionDecl::Extern
,
2368 FunctionDecl::None
, false);
2371 // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
2372 void RewriteObjC::SynthMsgSendFunctionDecl() {
2373 IdentifierInfo
*msgSendIdent
= &Context
->Idents
.get("objc_msgSend");
2374 llvm::SmallVector
<QualType
, 16> ArgTys
;
2375 QualType argT
= Context
->getObjCIdType();
2376 assert(!argT
.isNull() && "Can't find 'id' type");
2377 ArgTys
.push_back(argT
);
2378 argT
= Context
->getObjCSelType();
2379 assert(!argT
.isNull() && "Can't find 'SEL' type");
2380 ArgTys
.push_back(argT
);
2381 QualType msgSendType
= Context
->getFunctionType(Context
->getObjCIdType(),
2382 &ArgTys
[0], ArgTys
.size(),
2383 true /*isVariadic*/, 0,
2385 FunctionType::ExtInfo());
2386 MsgSendFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2388 msgSendIdent
, msgSendType
, 0,
2389 FunctionDecl::Extern
,
2390 FunctionDecl::None
, false);
2393 // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
2394 void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2395 IdentifierInfo
*msgSendIdent
= &Context
->Idents
.get("objc_msgSendSuper");
2396 llvm::SmallVector
<QualType
, 16> ArgTys
;
2397 RecordDecl
*RD
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
2399 &Context
->Idents
.get("objc_super"));
2400 QualType argT
= Context
->getPointerType(Context
->getTagDeclType(RD
));
2401 assert(!argT
.isNull() && "Can't build 'struct objc_super *' type");
2402 ArgTys
.push_back(argT
);
2403 argT
= Context
->getObjCSelType();
2404 assert(!argT
.isNull() && "Can't find 'SEL' type");
2405 ArgTys
.push_back(argT
);
2406 QualType msgSendType
= Context
->getFunctionType(Context
->getObjCIdType(),
2407 &ArgTys
[0], ArgTys
.size(),
2408 true /*isVariadic*/, 0,
2410 FunctionType::ExtInfo());
2411 MsgSendSuperFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2413 msgSendIdent
, msgSendType
, 0,
2414 FunctionDecl::Extern
,
2415 FunctionDecl::None
, false);
2418 // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
2419 void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2420 IdentifierInfo
*msgSendIdent
= &Context
->Idents
.get("objc_msgSend_stret");
2421 llvm::SmallVector
<QualType
, 16> ArgTys
;
2422 QualType argT
= Context
->getObjCIdType();
2423 assert(!argT
.isNull() && "Can't find 'id' type");
2424 ArgTys
.push_back(argT
);
2425 argT
= Context
->getObjCSelType();
2426 assert(!argT
.isNull() && "Can't find 'SEL' type");
2427 ArgTys
.push_back(argT
);
2428 QualType msgSendType
= Context
->getFunctionType(Context
->getObjCIdType(),
2429 &ArgTys
[0], ArgTys
.size(),
2430 true /*isVariadic*/, 0,
2432 FunctionType::ExtInfo());
2433 MsgSendStretFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2435 msgSendIdent
, msgSendType
, 0,
2436 FunctionDecl::Extern
,
2437 FunctionDecl::None
, false);
2440 // SynthMsgSendSuperStretFunctionDecl -
2441 // id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
2442 void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2443 IdentifierInfo
*msgSendIdent
=
2444 &Context
->Idents
.get("objc_msgSendSuper_stret");
2445 llvm::SmallVector
<QualType
, 16> ArgTys
;
2446 RecordDecl
*RD
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
2448 &Context
->Idents
.get("objc_super"));
2449 QualType argT
= Context
->getPointerType(Context
->getTagDeclType(RD
));
2450 assert(!argT
.isNull() && "Can't build 'struct objc_super *' type");
2451 ArgTys
.push_back(argT
);
2452 argT
= Context
->getObjCSelType();
2453 assert(!argT
.isNull() && "Can't find 'SEL' type");
2454 ArgTys
.push_back(argT
);
2455 QualType msgSendType
= Context
->getFunctionType(Context
->getObjCIdType(),
2456 &ArgTys
[0], ArgTys
.size(),
2457 true /*isVariadic*/, 0,
2459 FunctionType::ExtInfo());
2460 MsgSendSuperStretFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2462 msgSendIdent
, msgSendType
, 0,
2463 FunctionDecl::Extern
,
2464 FunctionDecl::None
, false);
2467 // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
2468 void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2469 IdentifierInfo
*msgSendIdent
= &Context
->Idents
.get("objc_msgSend_fpret");
2470 llvm::SmallVector
<QualType
, 16> ArgTys
;
2471 QualType argT
= Context
->getObjCIdType();
2472 assert(!argT
.isNull() && "Can't find 'id' type");
2473 ArgTys
.push_back(argT
);
2474 argT
= Context
->getObjCSelType();
2475 assert(!argT
.isNull() && "Can't find 'SEL' type");
2476 ArgTys
.push_back(argT
);
2477 QualType msgSendType
= Context
->getFunctionType(Context
->DoubleTy
,
2478 &ArgTys
[0], ArgTys
.size(),
2479 true /*isVariadic*/, 0,
2481 FunctionType::ExtInfo());
2482 MsgSendFpretFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2484 msgSendIdent
, msgSendType
, 0,
2485 FunctionDecl::Extern
,
2486 FunctionDecl::None
, false);
2489 // SynthGetClassFunctionDecl - id objc_getClass(const char *name);
2490 void RewriteObjC::SynthGetClassFunctionDecl() {
2491 IdentifierInfo
*getClassIdent
= &Context
->Idents
.get("objc_getClass");
2492 llvm::SmallVector
<QualType
, 16> ArgTys
;
2493 ArgTys
.push_back(Context
->getPointerType(Context
->CharTy
.withConst()));
2494 QualType getClassType
= Context
->getFunctionType(Context
->getObjCIdType(),
2495 &ArgTys
[0], ArgTys
.size(),
2496 false /*isVariadic*/, 0,
2498 FunctionType::ExtInfo());
2499 GetClassFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2501 getClassIdent
, getClassType
, 0,
2502 FunctionDecl::Extern
,
2503 FunctionDecl::None
, false);
2506 // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
2507 void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2508 IdentifierInfo
*getSuperClassIdent
=
2509 &Context
->Idents
.get("class_getSuperclass");
2510 llvm::SmallVector
<QualType
, 16> ArgTys
;
2511 ArgTys
.push_back(Context
->getObjCClassType());
2512 QualType getClassType
= Context
->getFunctionType(Context
->getObjCClassType(),
2513 &ArgTys
[0], ArgTys
.size(),
2514 false /*isVariadic*/, 0,
2516 FunctionType::ExtInfo());
2517 GetSuperClassFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2521 FunctionDecl::Extern
,
2526 // SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
2527 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2528 IdentifierInfo
*getClassIdent
= &Context
->Idents
.get("objc_getMetaClass");
2529 llvm::SmallVector
<QualType
, 16> ArgTys
;
2530 ArgTys
.push_back(Context
->getPointerType(Context
->CharTy
.withConst()));
2531 QualType getClassType
= Context
->getFunctionType(Context
->getObjCIdType(),
2532 &ArgTys
[0], ArgTys
.size(),
2533 false /*isVariadic*/, 0,
2535 FunctionType::ExtInfo());
2536 GetMetaClassFunctionDecl
= FunctionDecl::Create(*Context
, TUDecl
,
2538 getClassIdent
, getClassType
, 0,
2539 FunctionDecl::Extern
,
2540 FunctionDecl::None
, false);
2543 Stmt
*RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral
*Exp
) {
2544 QualType strType
= getConstantStringStructType();
2546 std::string S
= "__NSConstantStringImpl_";
2548 std::string tmpName
= InFileName
;
2550 for (i
=0; i
< tmpName
.length(); i
++) {
2551 char c
= tmpName
.at(i
);
2552 // replace any non alphanumeric characters with '_'.
2553 if (!isalpha(c
) && (c
< '0' || c
> '9'))
2558 S
+= utostr(NumObjCStringLiterals
++);
2560 Preamble
+= "static __NSConstantStringImpl " + S
;
2561 Preamble
+= " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2562 Preamble
+= "0x000007c8,"; // utf8_str
2563 // The pretty printer for StringLiteral handles escape characters properly.
2564 std::string prettyBufS
;
2565 llvm::raw_string_ostream
prettyBuf(prettyBufS
);
2566 Exp
->getString()->printPretty(prettyBuf
, *Context
, 0,
2567 PrintingPolicy(LangOpts
));
2568 Preamble
+= prettyBuf
.str();
2570 Preamble
+= utostr(Exp
->getString()->getByteLength()) + "};\n";
2572 VarDecl
*NewVD
= VarDecl::Create(*Context
, TUDecl
, SourceLocation(),
2573 &Context
->Idents
.get(S
), strType
, 0,
2574 VarDecl::Static
, VarDecl::None
);
2575 DeclRefExpr
*DRE
= new (Context
) DeclRefExpr(NewVD
, strType
, SourceLocation());
2576 Expr
*Unop
= new (Context
) UnaryOperator(DRE
, UnaryOperator::AddrOf
,
2577 Context
->getPointerType(DRE
->getType()),
2579 // cast to NSConstantString *
2580 CastExpr
*cast
= NoTypeInfoCStyleCastExpr(Context
, Exp
->getType(),
2581 CastExpr::CK_Unknown
, Unop
);
2582 ReplaceStmt(Exp
, cast
);
2583 // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
2587 // struct objc_super { struct objc_object *receiver; struct objc_class *super; };
2588 QualType
RewriteObjC::getSuperStructType() {
2589 if (!SuperStructDecl
) {
2590 SuperStructDecl
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
2592 &Context
->Idents
.get("objc_super"));
2593 QualType FieldTypes
[2];
2595 // struct objc_object *receiver;
2596 FieldTypes
[0] = Context
->getObjCIdType();
2597 // struct objc_class *super;
2598 FieldTypes
[1] = Context
->getObjCClassType();
2601 for (unsigned i
= 0; i
< 2; ++i
) {
2602 SuperStructDecl
->addDecl(FieldDecl::Create(*Context
, SuperStructDecl
,
2603 SourceLocation(), 0,
2606 /*Mutable=*/false));
2609 SuperStructDecl
->completeDefinition();
2611 return Context
->getTagDeclType(SuperStructDecl
);
2614 QualType
RewriteObjC::getConstantStringStructType() {
2615 if (!ConstantStringDecl
) {
2616 ConstantStringDecl
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
2618 &Context
->Idents
.get("__NSConstantStringImpl"));
2619 QualType FieldTypes
[4];
2621 // struct objc_object *receiver;
2622 FieldTypes
[0] = Context
->getObjCIdType();
2624 FieldTypes
[1] = Context
->IntTy
;
2626 FieldTypes
[2] = Context
->getPointerType(Context
->CharTy
);
2628 FieldTypes
[3] = Context
->LongTy
;
2631 for (unsigned i
= 0; i
< 4; ++i
) {
2632 ConstantStringDecl
->addDecl(FieldDecl::Create(*Context
,
2634 SourceLocation(), 0,
2640 ConstantStringDecl
->completeDefinition();
2642 return Context
->getTagDeclType(ConstantStringDecl
);
2645 Stmt
*RewriteObjC::SynthMessageExpr(ObjCMessageExpr
*Exp
,
2646 SourceLocation StartLoc
,
2647 SourceLocation EndLoc
) {
2648 if (!SelGetUidFunctionDecl
)
2649 SynthSelGetUidFunctionDecl();
2650 if (!MsgSendFunctionDecl
)
2651 SynthMsgSendFunctionDecl();
2652 if (!MsgSendSuperFunctionDecl
)
2653 SynthMsgSendSuperFunctionDecl();
2654 if (!MsgSendStretFunctionDecl
)
2655 SynthMsgSendStretFunctionDecl();
2656 if (!MsgSendSuperStretFunctionDecl
)
2657 SynthMsgSendSuperStretFunctionDecl();
2658 if (!MsgSendFpretFunctionDecl
)
2659 SynthMsgSendFpretFunctionDecl();
2660 if (!GetClassFunctionDecl
)
2661 SynthGetClassFunctionDecl();
2662 if (!GetSuperClassFunctionDecl
)
2663 SynthGetSuperClassFunctionDecl();
2664 if (!GetMetaClassFunctionDecl
)
2665 SynthGetMetaClassFunctionDecl();
2667 // default to objc_msgSend().
2668 FunctionDecl
*MsgSendFlavor
= MsgSendFunctionDecl
;
2669 // May need to use objc_msgSend_stret() as well.
2670 FunctionDecl
*MsgSendStretFlavor
= 0;
2671 if (ObjCMethodDecl
*mDecl
= Exp
->getMethodDecl()) {
2672 QualType resultType
= mDecl
->getResultType();
2673 if (resultType
->isRecordType())
2674 MsgSendStretFlavor
= MsgSendStretFunctionDecl
;
2675 else if (resultType
->isRealFloatingType())
2676 MsgSendFlavor
= MsgSendFpretFunctionDecl
;
2679 // Synthesize a call to objc_msgSend().
2680 llvm::SmallVector
<Expr
*, 8> MsgExprs
;
2681 switch (Exp
->getReceiverKind()) {
2682 case ObjCMessageExpr::SuperClass
: {
2683 MsgSendFlavor
= MsgSendSuperFunctionDecl
;
2684 if (MsgSendStretFlavor
)
2685 MsgSendStretFlavor
= MsgSendSuperStretFunctionDecl
;
2686 assert(MsgSendFlavor
&& "MsgSendFlavor is NULL!");
2688 ObjCInterfaceDecl
*ClassDecl
= CurMethodDef
->getClassInterface();
2690 llvm::SmallVector
<Expr
*, 4> InitExprs
;
2692 // set the receiver to self, the first argument to all methods.
2693 InitExprs
.push_back(
2694 NoTypeInfoCStyleCastExpr(Context
, Context
->getObjCIdType(),
2695 CastExpr::CK_Unknown
,
2696 new (Context
) DeclRefExpr(CurMethodDef
->getSelfDecl(),
2697 Context
->getObjCIdType(),
2699 ); // set the 'receiver'.
2701 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2702 llvm::SmallVector
<Expr
*, 8> ClsExprs
;
2703 QualType argType
= Context
->getPointerType(Context
->CharTy
);
2704 ClsExprs
.push_back(StringLiteral::Create(*Context
,
2705 ClassDecl
->getIdentifier()->getNameStart(),
2706 ClassDecl
->getIdentifier()->getLength(),
2707 false, argType
, SourceLocation()));
2708 CallExpr
*Cls
= SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl
,
2713 // (Class)objc_getClass("CurrentClass")
2714 CastExpr
*ArgExpr
= NoTypeInfoCStyleCastExpr(Context
,
2715 Context
->getObjCClassType(),
2716 CastExpr::CK_Unknown
, Cls
);
2718 ClsExprs
.push_back(ArgExpr
);
2719 Cls
= SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl
,
2720 &ClsExprs
[0], ClsExprs
.size(),
2723 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2724 // To turn off a warning, type-cast to 'id'
2725 InitExprs
.push_back( // set 'super class', using class_getSuperclass().
2726 NoTypeInfoCStyleCastExpr(Context
,
2727 Context
->getObjCIdType(),
2728 CastExpr::CK_Unknown
, Cls
));
2729 // struct objc_super
2730 QualType superType
= getSuperStructType();
2733 if (LangOpts
.Microsoft
) {
2734 SynthSuperContructorFunctionDecl();
2735 // Simulate a contructor call...
2736 DeclRefExpr
*DRE
= new (Context
) DeclRefExpr(SuperContructorFunctionDecl
,
2737 superType
, SourceLocation());
2738 SuperRep
= new (Context
) CallExpr(*Context
, DRE
, &InitExprs
[0],
2740 superType
, SourceLocation());
2741 // The code for super is a little tricky to prevent collision with
2742 // the structure definition in the header. The rewriter has it's own
2743 // internal definition (__rw_objc_super) that is uses. This is why
2744 // we need the cast below. For example:
2745 // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2747 SuperRep
= new (Context
) UnaryOperator(SuperRep
, UnaryOperator::AddrOf
,
2748 Context
->getPointerType(SuperRep
->getType()),
2750 SuperRep
= NoTypeInfoCStyleCastExpr(Context
,
2751 Context
->getPointerType(superType
),
2752 CastExpr::CK_Unknown
, SuperRep
);
2754 // (struct objc_super) { <exprs from above> }
2756 new (Context
) InitListExpr(*Context
, SourceLocation(),
2757 &InitExprs
[0], InitExprs
.size(),
2759 TypeSourceInfo
*superTInfo
2760 = Context
->getTrivialTypeSourceInfo(superType
);
2761 SuperRep
= new (Context
) CompoundLiteralExpr(SourceLocation(), superTInfo
,
2762 superType
, ILE
, false);
2763 // struct objc_super *
2764 SuperRep
= new (Context
) UnaryOperator(SuperRep
, UnaryOperator::AddrOf
,
2765 Context
->getPointerType(SuperRep
->getType()),
2768 MsgExprs
.push_back(SuperRep
);
2772 case ObjCMessageExpr::Class
: {
2773 llvm::SmallVector
<Expr
*, 8> ClsExprs
;
2774 QualType argType
= Context
->getPointerType(Context
->CharTy
);
2775 ObjCInterfaceDecl
*Class
2776 = Exp
->getClassReceiver()->getAs
<ObjCObjectType
>()->getInterface();
2777 IdentifierInfo
*clsName
= Class
->getIdentifier();
2778 ClsExprs
.push_back(StringLiteral::Create(*Context
,
2779 clsName
->getNameStart(),
2780 clsName
->getLength(),
2783 CallExpr
*Cls
= SynthesizeCallToFunctionDecl(GetClassFunctionDecl
,
2787 MsgExprs
.push_back(Cls
);
2791 case ObjCMessageExpr::SuperInstance
:{
2792 MsgSendFlavor
= MsgSendSuperFunctionDecl
;
2793 if (MsgSendStretFlavor
)
2794 MsgSendStretFlavor
= MsgSendSuperStretFunctionDecl
;
2795 assert(MsgSendFlavor
&& "MsgSendFlavor is NULL!");
2796 ObjCInterfaceDecl
*ClassDecl
= CurMethodDef
->getClassInterface();
2797 llvm::SmallVector
<Expr
*, 4> InitExprs
;
2799 InitExprs
.push_back(
2800 NoTypeInfoCStyleCastExpr(Context
, Context
->getObjCIdType(),
2801 CastExpr::CK_Unknown
,
2802 new (Context
) DeclRefExpr(CurMethodDef
->getSelfDecl(),
2803 Context
->getObjCIdType(),
2805 ); // set the 'receiver'.
2807 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2808 llvm::SmallVector
<Expr
*, 8> ClsExprs
;
2809 QualType argType
= Context
->getPointerType(Context
->CharTy
);
2810 ClsExprs
.push_back(StringLiteral::Create(*Context
,
2811 ClassDecl
->getIdentifier()->getNameStart(),
2812 ClassDecl
->getIdentifier()->getLength(),
2813 false, argType
, SourceLocation()));
2814 CallExpr
*Cls
= SynthesizeCallToFunctionDecl(GetClassFunctionDecl
,
2818 // (Class)objc_getClass("CurrentClass")
2819 CastExpr
*ArgExpr
= NoTypeInfoCStyleCastExpr(Context
,
2820 Context
->getObjCClassType(),
2821 CastExpr::CK_Unknown
, Cls
);
2823 ClsExprs
.push_back(ArgExpr
);
2824 Cls
= SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl
,
2825 &ClsExprs
[0], ClsExprs
.size(),
2828 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2829 // To turn off a warning, type-cast to 'id'
2830 InitExprs
.push_back(
2831 // set 'super class', using class_getSuperclass().
2832 NoTypeInfoCStyleCastExpr(Context
, Context
->getObjCIdType(),
2833 CastExpr::CK_Unknown
, Cls
));
2834 // struct objc_super
2835 QualType superType
= getSuperStructType();
2838 if (LangOpts
.Microsoft
) {
2839 SynthSuperContructorFunctionDecl();
2840 // Simulate a contructor call...
2841 DeclRefExpr
*DRE
= new (Context
) DeclRefExpr(SuperContructorFunctionDecl
,
2842 superType
, SourceLocation());
2843 SuperRep
= new (Context
) CallExpr(*Context
, DRE
, &InitExprs
[0],
2845 superType
, SourceLocation());
2846 // The code for super is a little tricky to prevent collision with
2847 // the structure definition in the header. The rewriter has it's own
2848 // internal definition (__rw_objc_super) that is uses. This is why
2849 // we need the cast below. For example:
2850 // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2852 SuperRep
= new (Context
) UnaryOperator(SuperRep
, UnaryOperator::AddrOf
,
2853 Context
->getPointerType(SuperRep
->getType()),
2855 SuperRep
= NoTypeInfoCStyleCastExpr(Context
,
2856 Context
->getPointerType(superType
),
2857 CastExpr::CK_Unknown
, SuperRep
);
2859 // (struct objc_super) { <exprs from above> }
2861 new (Context
) InitListExpr(*Context
, SourceLocation(),
2862 &InitExprs
[0], InitExprs
.size(),
2864 TypeSourceInfo
*superTInfo
2865 = Context
->getTrivialTypeSourceInfo(superType
);
2866 SuperRep
= new (Context
) CompoundLiteralExpr(SourceLocation(), superTInfo
,
2867 superType
, ILE
, false);
2869 MsgExprs
.push_back(SuperRep
);
2873 case ObjCMessageExpr::Instance
: {
2874 // Remove all type-casts because it may contain objc-style types; e.g.
2876 Expr
*recExpr
= Exp
->getInstanceReceiver();
2877 while (CStyleCastExpr
*CE
= dyn_cast
<CStyleCastExpr
>(recExpr
))
2878 recExpr
= CE
->getSubExpr();
2879 recExpr
= NoTypeInfoCStyleCastExpr(Context
, Context
->getObjCIdType(),
2880 CastExpr::CK_Unknown
, recExpr
);
2881 MsgExprs
.push_back(recExpr
);
2886 // Create a call to sel_registerName("selName"), it will be the 2nd argument.
2887 llvm::SmallVector
<Expr
*, 8> SelExprs
;
2888 QualType argType
= Context
->getPointerType(Context
->CharTy
);
2889 SelExprs
.push_back(StringLiteral::Create(*Context
,
2890 Exp
->getSelector().getAsString().c_str(),
2891 Exp
->getSelector().getAsString().size(),
2892 false, argType
, SourceLocation()));
2893 CallExpr
*SelExp
= SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl
,
2894 &SelExprs
[0], SelExprs
.size(),
2897 MsgExprs
.push_back(SelExp
);
2899 // Now push any user supplied arguments.
2900 for (unsigned i
= 0; i
< Exp
->getNumArgs(); i
++) {
2901 Expr
*userExpr
= Exp
->getArg(i
);
2902 // Make all implicit casts explicit...ICE comes in handy:-)
2903 if (ImplicitCastExpr
*ICE
= dyn_cast
<ImplicitCastExpr
>(userExpr
)) {
2904 // Reuse the ICE type, it is exactly what the doctor ordered.
2905 QualType type
= ICE
->getType()->isObjCQualifiedIdType()
2906 ? Context
->getObjCIdType()
2908 // Make sure we convert "type (^)(...)" to "type (*)(...)".
2909 (void)convertBlockPointerToFunctionPointer(type
);
2910 userExpr
= NoTypeInfoCStyleCastExpr(Context
, type
, CastExpr::CK_Unknown
,
2913 // Make id<P...> cast into an 'id' cast.
2914 else if (CStyleCastExpr
*CE
= dyn_cast
<CStyleCastExpr
>(userExpr
)) {
2915 if (CE
->getType()->isObjCQualifiedIdType()) {
2916 while ((CE
= dyn_cast
<CStyleCastExpr
>(userExpr
)))
2917 userExpr
= CE
->getSubExpr();
2918 userExpr
= NoTypeInfoCStyleCastExpr(Context
, Context
->getObjCIdType(),
2919 CastExpr::CK_Unknown
, userExpr
);
2922 MsgExprs
.push_back(userExpr
);
2923 // We've transferred the ownership to MsgExprs. For now, we *don't* null
2924 // out the argument in the original expression (since we aren't deleting
2925 // the ObjCMessageExpr). See RewritePropertySetter() usage for more info.
2926 //Exp->setArg(i, 0);
2928 // Generate the funky cast.
2930 llvm::SmallVector
<QualType
, 8> ArgTypes
;
2931 QualType returnType
;
2933 // Push 'id' and 'SEL', the 2 implicit arguments.
2934 if (MsgSendFlavor
== MsgSendSuperFunctionDecl
)
2935 ArgTypes
.push_back(Context
->getPointerType(getSuperStructType()));
2937 ArgTypes
.push_back(Context
->getObjCIdType());
2938 ArgTypes
.push_back(Context
->getObjCSelType());
2939 if (ObjCMethodDecl
*OMD
= Exp
->getMethodDecl()) {
2940 // Push any user argument types.
2941 for (ObjCMethodDecl::param_iterator PI
= OMD
->param_begin(),
2942 E
= OMD
->param_end(); PI
!= E
; ++PI
) {
2943 QualType t
= (*PI
)->getType()->isObjCQualifiedIdType()
2944 ? Context
->getObjCIdType()
2946 // Make sure we convert "t (^)(...)" to "t (*)(...)".
2947 (void)convertBlockPointerToFunctionPointer(t
);
2948 ArgTypes
.push_back(t
);
2950 returnType
= OMD
->getResultType()->isObjCQualifiedIdType()
2951 ? Context
->getObjCIdType() : OMD
->getResultType();
2952 (void)convertBlockPointerToFunctionPointer(returnType
);
2954 returnType
= Context
->getObjCIdType();
2956 // Get the type, we will need to reference it in a couple spots.
2957 QualType msgSendType
= MsgSendFlavor
->getType();
2959 // Create a reference to the objc_msgSend() declaration.
2960 DeclRefExpr
*DRE
= new (Context
) DeclRefExpr(MsgSendFlavor
, msgSendType
,
2963 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
2964 // If we don't do this cast, we get the following bizarre warning/note:
2965 // xx.m:13: warning: function called through a non-compatible type
2966 // xx.m:13: note: if this code is reached, the program will abort
2967 cast
= NoTypeInfoCStyleCastExpr(Context
,
2968 Context
->getPointerType(Context
->VoidTy
),
2969 CastExpr::CK_Unknown
, DRE
);
2971 // Now do the "normal" pointer to function cast.
2972 QualType castType
= Context
->getFunctionType(returnType
,
2973 &ArgTypes
[0], ArgTypes
.size(),
2974 // If we don't have a method decl, force a variadic cast.
2975 Exp
->getMethodDecl() ? Exp
->getMethodDecl()->isVariadic() : true, 0,
2977 FunctionType::ExtInfo());
2978 castType
= Context
->getPointerType(castType
);
2979 cast
= NoTypeInfoCStyleCastExpr(Context
, castType
, CastExpr::CK_Unknown
,
2982 // Don't forget the parens to enforce the proper binding.
2983 ParenExpr
*PE
= new (Context
) ParenExpr(StartLoc
, EndLoc
, cast
);
2985 const FunctionType
*FT
= msgSendType
->getAs
<FunctionType
>();
2986 CallExpr
*CE
= new (Context
) CallExpr(*Context
, PE
, &MsgExprs
[0],
2988 FT
->getResultType(), EndLoc
);
2989 Stmt
*ReplacingStmt
= CE
;
2990 if (MsgSendStretFlavor
) {
2991 // We have the method which returns a struct/union. Must also generate
2992 // call to objc_msgSend_stret and hang both varieties on a conditional
2993 // expression which dictate which one to envoke depending on size of
2994 // method's return type.
2996 // Create a reference to the objc_msgSend_stret() declaration.
2997 DeclRefExpr
*STDRE
= new (Context
) DeclRefExpr(MsgSendStretFlavor
, msgSendType
,
2999 // Need to cast objc_msgSend_stret to "void *" (see above comment).
3000 cast
= NoTypeInfoCStyleCastExpr(Context
,
3001 Context
->getPointerType(Context
->VoidTy
),
3002 CastExpr::CK_Unknown
, STDRE
);
3003 // Now do the "normal" pointer to function cast.
3004 castType
= Context
->getFunctionType(returnType
,
3005 &ArgTypes
[0], ArgTypes
.size(),
3006 Exp
->getMethodDecl() ? Exp
->getMethodDecl()->isVariadic() : false, 0,
3008 FunctionType::ExtInfo());
3009 castType
= Context
->getPointerType(castType
);
3010 cast
= NoTypeInfoCStyleCastExpr(Context
, castType
, CastExpr::CK_Unknown
,
3013 // Don't forget the parens to enforce the proper binding.
3014 PE
= new (Context
) ParenExpr(SourceLocation(), SourceLocation(), cast
);
3016 FT
= msgSendType
->getAs
<FunctionType
>();
3017 CallExpr
*STCE
= new (Context
) CallExpr(*Context
, PE
, &MsgExprs
[0],
3019 FT
->getResultType(), SourceLocation());
3021 // Build sizeof(returnType)
3022 SizeOfAlignOfExpr
*sizeofExpr
= new (Context
) SizeOfAlignOfExpr(true,
3023 Context
->getTrivialTypeSourceInfo(returnType
),
3024 Context
->getSizeType(),
3025 SourceLocation(), SourceLocation());
3026 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
3027 // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
3028 // For X86 it is more complicated and some kind of target specific routine
3029 // is needed to decide what to do.
3031 static_cast<unsigned>(Context
->getTypeSize(Context
->IntTy
));
3032 IntegerLiteral
*limit
= new (Context
) IntegerLiteral(llvm::APInt(IntSize
, 8),
3035 BinaryOperator
*lessThanExpr
= new (Context
) BinaryOperator(sizeofExpr
, limit
,
3039 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
3040 ConditionalOperator
*CondExpr
=
3041 new (Context
) ConditionalOperator(lessThanExpr
,
3042 SourceLocation(), CE
,
3043 SourceLocation(), STCE
, returnType
);
3044 ReplacingStmt
= new (Context
) ParenExpr(SourceLocation(), SourceLocation(), CondExpr
);
3046 // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
3047 return ReplacingStmt
;
3050 Stmt
*RewriteObjC::RewriteMessageExpr(ObjCMessageExpr
*Exp
) {
3051 Stmt
*ReplacingStmt
= SynthMessageExpr(Exp
, Exp
->getLocStart(),
3054 // Now do the actual rewrite.
3055 ReplaceStmt(Exp
, ReplacingStmt
);
3057 // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
3058 return ReplacingStmt
;
3061 // typedef struct objc_object Protocol;
3062 QualType
RewriteObjC::getProtocolType() {
3063 if (!ProtocolTypeDecl
) {
3064 TypeSourceInfo
*TInfo
3065 = Context
->getTrivialTypeSourceInfo(Context
->getObjCIdType());
3066 ProtocolTypeDecl
= TypedefDecl::Create(*Context
, TUDecl
,
3068 &Context
->Idents
.get("Protocol"),
3071 return Context
->getTypeDeclType(ProtocolTypeDecl
);
3074 /// RewriteObjCProtocolExpr - Rewrite a protocol expression into
3075 /// a synthesized/forward data reference (to the protocol's metadata).
3076 /// The forward references (and metadata) are generated in
3077 /// RewriteObjC::HandleTranslationUnit().
3078 Stmt
*RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr
*Exp
) {
3079 std::string Name
= "_OBJC_PROTOCOL_" + Exp
->getProtocol()->getNameAsString();
3080 IdentifierInfo
*ID
= &Context
->Idents
.get(Name
);
3081 VarDecl
*VD
= VarDecl::Create(*Context
, TUDecl
, SourceLocation(),
3082 ID
, getProtocolType(), 0,
3083 VarDecl::Extern
, VarDecl::None
);
3084 DeclRefExpr
*DRE
= new (Context
) DeclRefExpr(VD
, getProtocolType(), SourceLocation());
3085 Expr
*DerefExpr
= new (Context
) UnaryOperator(DRE
, UnaryOperator::AddrOf
,
3086 Context
->getPointerType(DRE
->getType()),
3088 CastExpr
*castExpr
= NoTypeInfoCStyleCastExpr(Context
, DerefExpr
->getType(),
3089 CastExpr::CK_Unknown
,
3091 ReplaceStmt(Exp
, castExpr
);
3092 ProtocolExprDecls
.insert(Exp
->getProtocol());
3093 // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
3098 bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf
,
3099 const char *endBuf
) {
3100 while (startBuf
< endBuf
) {
3101 if (*startBuf
== '#') {
3103 for (++startBuf
; startBuf
[0] == ' ' || startBuf
[0] == '\t'; ++startBuf
)
3105 if (!strncmp(startBuf
, "if", strlen("if")) ||
3106 !strncmp(startBuf
, "ifdef", strlen("ifdef")) ||
3107 !strncmp(startBuf
, "ifndef", strlen("ifndef")) ||
3108 !strncmp(startBuf
, "define", strlen("define")) ||
3109 !strncmp(startBuf
, "undef", strlen("undef")) ||
3110 !strncmp(startBuf
, "else", strlen("else")) ||
3111 !strncmp(startBuf
, "elif", strlen("elif")) ||
3112 !strncmp(startBuf
, "endif", strlen("endif")) ||
3113 !strncmp(startBuf
, "pragma", strlen("pragma")) ||
3114 !strncmp(startBuf
, "include", strlen("include")) ||
3115 !strncmp(startBuf
, "import", strlen("import")) ||
3116 !strncmp(startBuf
, "include_next", strlen("include_next")))
3124 /// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to
3125 /// an objective-c class with ivars.
3126 void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl
*CDecl
,
3127 std::string
&Result
) {
3128 assert(CDecl
&& "Class missing in SynthesizeObjCInternalStruct");
3129 assert(CDecl
->getNameAsCString() &&
3130 "Name missing in SynthesizeObjCInternalStruct");
3131 // Do not synthesize more than once.
3132 if (ObjCSynthesizedStructs
.count(CDecl
))
3134 ObjCInterfaceDecl
*RCDecl
= CDecl
->getSuperClass();
3135 int NumIvars
= CDecl
->ivar_size();
3136 SourceLocation LocStart
= CDecl
->getLocStart();
3137 SourceLocation LocEnd
= CDecl
->getLocEnd();
3139 const char *startBuf
= SM
->getCharacterData(LocStart
);
3140 const char *endBuf
= SM
->getCharacterData(LocEnd
);
3142 // If no ivars and no root or if its root, directly or indirectly,
3143 // have no ivars (thus not synthesized) then no need to synthesize this class.
3144 if ((CDecl
->isForwardDecl() || NumIvars
== 0) &&
3145 (!RCDecl
|| !ObjCSynthesizedStructs
.count(RCDecl
))) {
3146 endBuf
+= Lexer::MeasureTokenLength(LocEnd
, *SM
, LangOpts
);
3147 ReplaceText(LocStart
, endBuf
-startBuf
, Result
);
3151 // FIXME: This has potential of causing problem. If
3152 // SynthesizeObjCInternalStruct is ever called recursively.
3153 Result
+= "\nstruct ";
3154 Result
+= CDecl
->getNameAsString();
3155 if (LangOpts
.Microsoft
)
3159 const char *cursor
= strchr(startBuf
, '{');
3160 assert((cursor
&& endBuf
)
3161 && "SynthesizeObjCInternalStruct - malformed @interface");
3162 // If the buffer contains preprocessor directives, we do more fine-grained
3163 // rewrites. This is intended to fix code that looks like (which occurs in
3164 // NSURL.h, for example):
3167 // @interface Foo : NSObject
3169 // @interface FooBar : NSObject
3176 // This clause is segregated to avoid breaking the common case.
3177 if (BufferContainsPPDirectives(startBuf
, cursor
)) {
3178 SourceLocation L
= RCDecl
? CDecl
->getSuperClassLoc() :
3179 CDecl
->getClassLoc();
3180 const char *endHeader
= SM
->getCharacterData(L
);
3181 endHeader
+= Lexer::MeasureTokenLength(L
, *SM
, LangOpts
);
3183 if (CDecl
->protocol_begin() != CDecl
->protocol_end()) {
3184 // advance to the end of the referenced protocols.
3185 while (endHeader
< cursor
&& *endHeader
!= '>') endHeader
++;
3188 // rewrite the original header
3189 ReplaceText(LocStart
, endHeader
-startBuf
, Result
);
3191 // rewrite the original header *without* disturbing the '{'
3192 ReplaceText(LocStart
, cursor
-startBuf
, Result
);
3194 if (RCDecl
&& ObjCSynthesizedStructs
.count(RCDecl
)) {
3195 Result
= "\n struct ";
3196 Result
+= RCDecl
->getNameAsString();
3198 Result
+= RCDecl
->getNameAsString();
3199 Result
+= "_IVARS;\n";
3201 // insert the super class structure definition.
3202 SourceLocation OnePastCurly
=
3203 LocStart
.getFileLocWithOffset(cursor
-startBuf
+1);
3204 InsertText(OnePastCurly
, Result
);
3206 cursor
++; // past '{'
3208 // Now comment out any visibility specifiers.
3209 while (cursor
< endBuf
) {
3210 if (*cursor
== '@') {
3211 SourceLocation atLoc
= LocStart
.getFileLocWithOffset(cursor
-startBuf
);
3213 for (++cursor
; cursor
[0] == ' ' || cursor
[0] == '\t'; ++cursor
)
3216 // FIXME: presence of @public, etc. inside comment results in
3217 // this transformation as well, which is still correct c-code.
3218 if (!strncmp(cursor
, "public", strlen("public")) ||
3219 !strncmp(cursor
, "private", strlen("private")) ||
3220 !strncmp(cursor
, "package", strlen("package")) ||
3221 !strncmp(cursor
, "protected", strlen("protected")))
3222 InsertText(atLoc
, "// ");
3224 // FIXME: If there are cases where '<' is used in ivar declaration part
3225 // of user code, then scan the ivar list and use needToScanForQualifiers
3226 // for type checking.
3227 else if (*cursor
== '<') {
3228 SourceLocation atLoc
= LocStart
.getFileLocWithOffset(cursor
-startBuf
);
3229 InsertText(atLoc
, "/* ");
3230 cursor
= strchr(cursor
, '>');
3232 atLoc
= LocStart
.getFileLocWithOffset(cursor
-startBuf
);
3233 InsertText(atLoc
, " */");
3234 } else if (*cursor
== '^') { // rewrite block specifier.
3235 SourceLocation caretLoc
= LocStart
.getFileLocWithOffset(cursor
-startBuf
);
3236 ReplaceText(caretLoc
, 1, "*");
3240 // Don't forget to add a ';'!!
3241 InsertText(LocEnd
.getFileLocWithOffset(1), ";");
3242 } else { // we don't have any instance variables - insert super struct.
3243 endBuf
+= Lexer::MeasureTokenLength(LocEnd
, *SM
, LangOpts
);
3244 Result
+= " {\n struct ";
3245 Result
+= RCDecl
->getNameAsString();
3247 Result
+= RCDecl
->getNameAsString();
3248 Result
+= "_IVARS;\n};\n";
3249 ReplaceText(LocStart
, endBuf
-startBuf
, Result
);
3251 // Mark this struct as having been generated.
3252 if (!ObjCSynthesizedStructs
.insert(CDecl
))
3253 assert(false && "struct already synthesize- SynthesizeObjCInternalStruct");
3256 // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
3258 template<typename MethodIterator
>
3259 void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin
,
3260 MethodIterator MethodEnd
,
3261 bool IsInstanceMethod
,
3263 const char *ClassName
,
3264 std::string
&Result
) {
3265 if (MethodBegin
== MethodEnd
) return;
3267 if (!objc_impl_method
) {
3268 /* struct _objc_method {
3274 Result
+= "\nstruct _objc_method {\n";
3275 Result
+= "\tSEL _cmd;\n";
3276 Result
+= "\tchar *method_types;\n";
3277 Result
+= "\tvoid *_imp;\n";
3280 objc_impl_method
= true;
3283 // Build _objc_method_list for class's methods if needed
3286 struct _objc_method_list *next_method;
3288 struct _objc_method method_list[];
3291 unsigned NumMethods
= std::distance(MethodBegin
, MethodEnd
);
3292 Result
+= "\nstatic struct {\n";
3293 Result
+= "\tstruct _objc_method_list *next_method;\n";
3294 Result
+= "\tint method_count;\n";
3295 Result
+= "\tstruct _objc_method method_list[";
3296 Result
+= utostr(NumMethods
);
3297 Result
+= "];\n} _OBJC_";
3299 Result
+= IsInstanceMethod
? "INSTANCE" : "CLASS";
3300 Result
+= "_METHODS_";
3301 Result
+= ClassName
;
3302 Result
+= " __attribute__ ((used, section (\"__OBJC, __";
3303 Result
+= IsInstanceMethod
? "inst" : "cls";
3304 Result
+= "_meth\")))= ";
3305 Result
+= "{\n\t0, " + utostr(NumMethods
) + "\n";
3307 Result
+= "\t,{{(SEL)\"";
3308 Result
+= (*MethodBegin
)->getSelector().getAsString().c_str();
3309 std::string MethodTypeString
;
3310 Context
->getObjCEncodingForMethodDecl(*MethodBegin
, MethodTypeString
);
3312 Result
+= MethodTypeString
;
3313 Result
+= "\", (void *)";
3314 Result
+= MethodInternalNames
[*MethodBegin
];
3316 for (++MethodBegin
; MethodBegin
!= MethodEnd
; ++MethodBegin
) {
3317 Result
+= "\t ,{(SEL)\"";
3318 Result
+= (*MethodBegin
)->getSelector().getAsString().c_str();
3319 std::string MethodTypeString
;
3320 Context
->getObjCEncodingForMethodDecl(*MethodBegin
, MethodTypeString
);
3322 Result
+= MethodTypeString
;
3323 Result
+= "\", (void *)";
3324 Result
+= MethodInternalNames
[*MethodBegin
];
3327 Result
+= "\t }\n};\n";
3330 /// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
3332 RewriteObjCProtocolMetaData(ObjCProtocolDecl
*PDecl
, const char *prefix
,
3333 const char *ClassName
, std::string
&Result
) {
3334 static bool objc_protocol_methods
= false;
3336 // Output struct protocol_methods holder of method selector and type.
3337 if (!objc_protocol_methods
&& !PDecl
->isForwardDecl()) {
3338 /* struct protocol_methods {
3343 Result
+= "\nstruct _protocol_methods {\n";
3344 Result
+= "\tstruct objc_selector *_cmd;\n";
3345 Result
+= "\tchar *method_types;\n";
3348 objc_protocol_methods
= true;
3350 // Do not synthesize the protocol more than once.
3351 if (ObjCSynthesizedProtocols
.count(PDecl
))
3354 if (PDecl
->instmeth_begin() != PDecl
->instmeth_end()) {
3355 unsigned NumMethods
= std::distance(PDecl
->instmeth_begin(),
3356 PDecl
->instmeth_end());
3357 /* struct _objc_protocol_method_list {
3358 int protocol_method_count;
3359 struct protocol_methods protocols[];
3362 Result
+= "\nstatic struct {\n";
3363 Result
+= "\tint protocol_method_count;\n";
3364 Result
+= "\tstruct _protocol_methods protocol_methods[";
3365 Result
+= utostr(NumMethods
);
3366 Result
+= "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
3367 Result
+= PDecl
->getNameAsString();
3368 Result
+= " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
3369 "{\n\t" + utostr(NumMethods
) + "\n";
3371 // Output instance methods declared in this protocol.
3372 for (ObjCProtocolDecl::instmeth_iterator
3373 I
= PDecl
->instmeth_begin(), E
= PDecl
->instmeth_end();
3375 if (I
== PDecl
->instmeth_begin())
3376 Result
+= "\t ,{{(struct objc_selector *)\"";
3378 Result
+= "\t ,{(struct objc_selector *)\"";
3379 Result
+= (*I
)->getSelector().getAsString().c_str();
3380 std::string MethodTypeString
;
3381 Context
->getObjCEncodingForMethodDecl((*I
), MethodTypeString
);
3383 Result
+= MethodTypeString
;
3386 Result
+= "\t }\n};\n";
3389 // Output class methods declared in this protocol.
3390 unsigned NumMethods
= std::distance(PDecl
->classmeth_begin(),
3391 PDecl
->classmeth_end());
3392 if (NumMethods
> 0) {
3393 /* struct _objc_protocol_method_list {
3394 int protocol_method_count;
3395 struct protocol_methods protocols[];
3398 Result
+= "\nstatic struct {\n";
3399 Result
+= "\tint protocol_method_count;\n";
3400 Result
+= "\tstruct _protocol_methods protocol_methods[";
3401 Result
+= utostr(NumMethods
);
3402 Result
+= "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
3403 Result
+= PDecl
->getNameAsString();
3404 Result
+= " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
3406 Result
+= utostr(NumMethods
);
3409 // Output instance methods declared in this protocol.
3410 for (ObjCProtocolDecl::classmeth_iterator
3411 I
= PDecl
->classmeth_begin(), E
= PDecl
->classmeth_end();
3413 if (I
== PDecl
->classmeth_begin())
3414 Result
+= "\t ,{{(struct objc_selector *)\"";
3416 Result
+= "\t ,{(struct objc_selector *)\"";
3417 Result
+= (*I
)->getSelector().getAsString().c_str();
3418 std::string MethodTypeString
;
3419 Context
->getObjCEncodingForMethodDecl((*I
), MethodTypeString
);
3421 Result
+= MethodTypeString
;
3424 Result
+= "\t }\n};\n";
3428 /* struct _objc_protocol {
3429 // Objective-C 1.0 extensions
3430 struct _objc_protocol_extension *isa;
3431 char *protocol_name;
3432 struct _objc_protocol **protocol_list;
3433 struct _objc_protocol_method_list *instance_methods;
3434 struct _objc_protocol_method_list *class_methods;
3437 static bool objc_protocol
= false;
3438 if (!objc_protocol
) {
3439 Result
+= "\nstruct _objc_protocol {\n";
3440 Result
+= "\tstruct _objc_protocol_extension *isa;\n";
3441 Result
+= "\tchar *protocol_name;\n";
3442 Result
+= "\tstruct _objc_protocol **protocol_list;\n";
3443 Result
+= "\tstruct _objc_protocol_method_list *instance_methods;\n";
3444 Result
+= "\tstruct _objc_protocol_method_list *class_methods;\n";
3447 objc_protocol
= true;
3450 Result
+= "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
3451 Result
+= PDecl
->getNameAsString();
3452 Result
+= " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
3454 Result
+= PDecl
->getNameAsString();
3455 Result
+= "\", 0, ";
3456 if (PDecl
->instmeth_begin() != PDecl
->instmeth_end()) {
3457 Result
+= "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
3458 Result
+= PDecl
->getNameAsString();
3463 if (PDecl
->classmeth_begin() != PDecl
->classmeth_end()) {
3464 Result
+= "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
3465 Result
+= PDecl
->getNameAsString();
3472 // Mark this protocol as having been generated.
3473 if (!ObjCSynthesizedProtocols
.insert(PDecl
))
3474 assert(false && "protocol already synthesized");
3479 RewriteObjCProtocolListMetaData(const ObjCList
<ObjCProtocolDecl
> &Protocols
,
3480 const char *prefix
, const char *ClassName
,
3481 std::string
&Result
) {
3482 if (Protocols
.empty()) return;
3484 for (unsigned i
= 0; i
!= Protocols
.size(); i
++)
3485 RewriteObjCProtocolMetaData(Protocols
[i
], prefix
, ClassName
, Result
);
3487 // Output the top lovel protocol meta-data for the class.
3488 /* struct _objc_protocol_list {
3489 struct _objc_protocol_list *next;
3491 struct _objc_protocol *class_protocols[];
3494 Result
+= "\nstatic struct {\n";
3495 Result
+= "\tstruct _objc_protocol_list *next;\n";
3496 Result
+= "\tint protocol_count;\n";
3497 Result
+= "\tstruct _objc_protocol *class_protocols[";
3498 Result
+= utostr(Protocols
.size());
3499 Result
+= "];\n} _OBJC_";
3501 Result
+= "_PROTOCOLS_";
3502 Result
+= ClassName
;
3503 Result
+= " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
3505 Result
+= utostr(Protocols
.size());
3508 Result
+= "\t,{&_OBJC_PROTOCOL_";
3509 Result
+= Protocols
[0]->getNameAsString();
3512 for (unsigned i
= 1; i
!= Protocols
.size(); i
++) {
3513 Result
+= "\t ,&_OBJC_PROTOCOL_";
3514 Result
+= Protocols
[i
]->getNameAsString();
3517 Result
+= "\t }\n};\n";
3521 /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
3523 void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl
*IDecl
,
3524 std::string
&Result
) {
3525 ObjCInterfaceDecl
*ClassDecl
= IDecl
->getClassInterface();
3526 // Find category declaration for this implementation.
3527 ObjCCategoryDecl
*CDecl
;
3528 for (CDecl
= ClassDecl
->getCategoryList(); CDecl
;
3529 CDecl
= CDecl
->getNextClassCategory())
3530 if (CDecl
->getIdentifier() == IDecl
->getIdentifier())
3533 std::string FullCategoryName
= ClassDecl
->getNameAsString();
3534 FullCategoryName
+= '_';
3535 FullCategoryName
+= IDecl
->getNameAsString();
3537 // Build _objc_method_list for class's instance methods if needed
3538 llvm::SmallVector
<ObjCMethodDecl
*, 32>
3539 InstanceMethods(IDecl
->instmeth_begin(), IDecl
->instmeth_end());
3541 // If any of our property implementations have associated getters or
3542 // setters, produce metadata for them as well.
3543 for (ObjCImplDecl::propimpl_iterator Prop
= IDecl
->propimpl_begin(),
3544 PropEnd
= IDecl
->propimpl_end();
3545 Prop
!= PropEnd
; ++Prop
) {
3546 if ((*Prop
)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
3548 if (!(*Prop
)->getPropertyIvarDecl())
3550 ObjCPropertyDecl
*PD
= (*Prop
)->getPropertyDecl();
3553 if (ObjCMethodDecl
*Getter
= PD
->getGetterMethodDecl())
3554 InstanceMethods
.push_back(Getter
);
3555 if (PD
->isReadOnly())
3557 if (ObjCMethodDecl
*Setter
= PD
->getSetterMethodDecl())
3558 InstanceMethods
.push_back(Setter
);
3560 RewriteObjCMethodsMetaData(InstanceMethods
.begin(), InstanceMethods
.end(),
3561 true, "CATEGORY_", FullCategoryName
.c_str(),
3564 // Build _objc_method_list for class's class methods if needed
3565 RewriteObjCMethodsMetaData(IDecl
->classmeth_begin(), IDecl
->classmeth_end(),
3566 false, "CATEGORY_", FullCategoryName
.c_str(),
3569 // Protocols referenced in class declaration?
3570 // Null CDecl is case of a category implementation with no category interface
3572 RewriteObjCProtocolListMetaData(CDecl
->getReferencedProtocols(), "CATEGORY",
3573 FullCategoryName
.c_str(), Result
);
3574 /* struct _objc_category {
3575 char *category_name;
3577 struct _objc_method_list *instance_methods;
3578 struct _objc_method_list *class_methods;
3579 struct _objc_protocol_list *protocols;
3580 // Objective-C 1.0 extensions
3581 uint32_t size; // sizeof (struct _objc_category)
3582 struct _objc_property_list *instance_properties; // category's own
3587 static bool objc_category
= false;
3588 if (!objc_category
) {
3589 Result
+= "\nstruct _objc_category {\n";
3590 Result
+= "\tchar *category_name;\n";
3591 Result
+= "\tchar *class_name;\n";
3592 Result
+= "\tstruct _objc_method_list *instance_methods;\n";
3593 Result
+= "\tstruct _objc_method_list *class_methods;\n";
3594 Result
+= "\tstruct _objc_protocol_list *protocols;\n";
3595 Result
+= "\tunsigned int size;\n";
3596 Result
+= "\tstruct _objc_property_list *instance_properties;\n";
3598 objc_category
= true;
3600 Result
+= "\nstatic struct _objc_category _OBJC_CATEGORY_";
3601 Result
+= FullCategoryName
;
3602 Result
+= " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
3603 Result
+= IDecl
->getNameAsString();
3604 Result
+= "\"\n\t, \"";
3605 Result
+= ClassDecl
->getNameAsString();
3608 if (IDecl
->instmeth_begin() != IDecl
->instmeth_end()) {
3609 Result
+= "\t, (struct _objc_method_list *)"
3610 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
3611 Result
+= FullCategoryName
;
3615 Result
+= "\t, 0\n";
3616 if (IDecl
->classmeth_begin() != IDecl
->classmeth_end()) {
3617 Result
+= "\t, (struct _objc_method_list *)"
3618 "&_OBJC_CATEGORY_CLASS_METHODS_";
3619 Result
+= FullCategoryName
;
3623 Result
+= "\t, 0\n";
3625 if (CDecl
&& CDecl
->protocol_begin() != CDecl
->protocol_end()) {
3626 Result
+= "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
3627 Result
+= FullCategoryName
;
3631 Result
+= "\t, 0\n";
3632 Result
+= "\t, sizeof(struct _objc_category), 0\n};\n";
3635 /// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
3637 void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCContainerDecl
*IDecl
,
3639 std::string
&Result
) {
3640 if (ivar
->isBitField()) {
3641 // FIXME: The hack below doesn't work for bitfields. For now, we simply
3642 // place all bitfields at offset 0.
3645 Result
+= "__OFFSETOFIVAR__(struct ";
3646 Result
+= IDecl
->getNameAsString();
3647 if (LangOpts
.Microsoft
)
3650 Result
+= ivar
->getNameAsString();
3655 //===----------------------------------------------------------------------===//
3656 // Meta Data Emission
3657 //===----------------------------------------------------------------------===//
3659 void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl
*IDecl
,
3660 std::string
&Result
) {
3661 ObjCInterfaceDecl
*CDecl
= IDecl
->getClassInterface();
3663 // Explictly declared @interface's are already synthesized.
3664 if (CDecl
->isImplicitInterfaceDecl()) {
3665 // FIXME: Implementation of a class with no @interface (legacy) doese not
3666 // produce correct synthesis as yet.
3667 SynthesizeObjCInternalStruct(CDecl
, Result
);
3670 // Build _objc_ivar_list metadata for classes ivars if needed
3671 unsigned NumIvars
= !IDecl
->ivar_empty()
3672 ? IDecl
->ivar_size()
3673 : (CDecl
? CDecl
->ivar_size() : 0);
3675 static bool objc_ivar
= false;
3677 /* struct _objc_ivar {
3683 Result
+= "\nstruct _objc_ivar {\n";
3684 Result
+= "\tchar *ivar_name;\n";
3685 Result
+= "\tchar *ivar_type;\n";
3686 Result
+= "\tint ivar_offset;\n";
3694 struct _objc_ivar ivar_list[nIvars];
3697 Result
+= "\nstatic struct {\n";
3698 Result
+= "\tint ivar_count;\n";
3699 Result
+= "\tstruct _objc_ivar ivar_list[";
3700 Result
+= utostr(NumIvars
);
3701 Result
+= "];\n} _OBJC_INSTANCE_VARIABLES_";
3702 Result
+= IDecl
->getNameAsString();
3703 Result
+= " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
3705 Result
+= utostr(NumIvars
);
3708 ObjCInterfaceDecl::ivar_iterator IVI
, IVE
;
3709 llvm::SmallVector
<ObjCIvarDecl
*, 8> IVars
;
3710 if (!IDecl
->ivar_empty()) {
3711 for (ObjCInterfaceDecl::ivar_iterator
3712 IV
= IDecl
->ivar_begin(), IVEnd
= IDecl
->ivar_end();
3714 IVars
.push_back(*IV
);
3715 IVI
= IDecl
->ivar_begin();
3716 IVE
= IDecl
->ivar_end();
3718 IVI
= CDecl
->ivar_begin();
3719 IVE
= CDecl
->ivar_end();
3721 Result
+= "\t,{{\"";
3722 Result
+= (*IVI
)->getNameAsString();
3724 std::string TmpString
, StrEncoding
;
3725 Context
->getObjCEncodingForType((*IVI
)->getType(), TmpString
, *IVI
);
3726 QuoteDoublequotes(TmpString
, StrEncoding
);
3727 Result
+= StrEncoding
;
3729 SynthesizeIvarOffsetComputation(IDecl
, *IVI
, Result
);
3731 for (++IVI
; IVI
!= IVE
; ++IVI
) {
3732 Result
+= "\t ,{\"";
3733 Result
+= (*IVI
)->getNameAsString();
3735 std::string TmpString
, StrEncoding
;
3736 Context
->getObjCEncodingForType((*IVI
)->getType(), TmpString
, *IVI
);
3737 QuoteDoublequotes(TmpString
, StrEncoding
);
3738 Result
+= StrEncoding
;
3740 SynthesizeIvarOffsetComputation(IDecl
, (*IVI
), Result
);
3744 Result
+= "\t }\n};\n";
3747 // Build _objc_method_list for class's instance methods if needed
3748 llvm::SmallVector
<ObjCMethodDecl
*, 32>
3749 InstanceMethods(IDecl
->instmeth_begin(), IDecl
->instmeth_end());
3751 // If any of our property implementations have associated getters or
3752 // setters, produce metadata for them as well.
3753 for (ObjCImplDecl::propimpl_iterator Prop
= IDecl
->propimpl_begin(),
3754 PropEnd
= IDecl
->propimpl_end();
3755 Prop
!= PropEnd
; ++Prop
) {
3756 if ((*Prop
)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
3758 if (!(*Prop
)->getPropertyIvarDecl())
3760 ObjCPropertyDecl
*PD
= (*Prop
)->getPropertyDecl();
3763 if (ObjCMethodDecl
*Getter
= PD
->getGetterMethodDecl())
3764 InstanceMethods
.push_back(Getter
);
3765 if (PD
->isReadOnly())
3767 if (ObjCMethodDecl
*Setter
= PD
->getSetterMethodDecl())
3768 InstanceMethods
.push_back(Setter
);
3770 RewriteObjCMethodsMetaData(InstanceMethods
.begin(), InstanceMethods
.end(),
3771 true, "", IDecl
->getNameAsCString(), Result
);
3773 // Build _objc_method_list for class's class methods if needed
3774 RewriteObjCMethodsMetaData(IDecl
->classmeth_begin(), IDecl
->classmeth_end(),
3775 false, "", IDecl
->getNameAsCString(), Result
);
3777 // Protocols referenced in class declaration?
3778 RewriteObjCProtocolListMetaData(CDecl
->getReferencedProtocols(),
3779 "CLASS", CDecl
->getNameAsCString(), Result
);
3781 // Declaration of class/meta-class metadata
3782 /* struct _objc_class {
3783 struct _objc_class *isa; // or const char *root_class_name when metadata
3784 const char *super_class_name;
3789 struct _objc_ivar_list *ivars;
3790 struct _objc_method_list *methods;
3791 struct objc_cache *cache;
3792 struct objc_protocol_list *protocols;
3793 const char *ivar_layout;
3794 struct _objc_class_ext *ext;
3797 static bool objc_class
= false;
3799 Result
+= "\nstruct _objc_class {\n";
3800 Result
+= "\tstruct _objc_class *isa;\n";
3801 Result
+= "\tconst char *super_class_name;\n";
3802 Result
+= "\tchar *name;\n";
3803 Result
+= "\tlong version;\n";
3804 Result
+= "\tlong info;\n";
3805 Result
+= "\tlong instance_size;\n";
3806 Result
+= "\tstruct _objc_ivar_list *ivars;\n";
3807 Result
+= "\tstruct _objc_method_list *methods;\n";
3808 Result
+= "\tstruct objc_cache *cache;\n";
3809 Result
+= "\tstruct _objc_protocol_list *protocols;\n";
3810 Result
+= "\tconst char *ivar_layout;\n";
3811 Result
+= "\tstruct _objc_class_ext *ext;\n";
3816 // Meta-class metadata generation.
3817 ObjCInterfaceDecl
*RootClass
= 0;
3818 ObjCInterfaceDecl
*SuperClass
= CDecl
->getSuperClass();
3819 while (SuperClass
) {
3820 RootClass
= SuperClass
;
3821 SuperClass
= SuperClass
->getSuperClass();
3823 SuperClass
= CDecl
->getSuperClass();
3825 Result
+= "\nstatic struct _objc_class _OBJC_METACLASS_";
3826 Result
+= CDecl
->getNameAsString();
3827 Result
+= " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
3828 "{\n\t(struct _objc_class *)\"";
3829 Result
+= (RootClass
? RootClass
->getNameAsString() : CDecl
->getNameAsString());
3834 Result
+= SuperClass
->getNameAsString();
3836 Result
+= CDecl
->getNameAsString();
3840 Result
+= ", 0, \"";
3841 Result
+= CDecl
->getNameAsString();
3844 // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
3845 // 'info' field is initialized to CLS_META(2) for metaclass
3846 Result
+= ", 0,2, sizeof(struct _objc_class), 0";
3847 if (IDecl
->classmeth_begin() != IDecl
->classmeth_end()) {
3848 Result
+= "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
3849 Result
+= IDecl
->getNameAsString();
3854 if (CDecl
->protocol_begin() != CDecl
->protocol_end()) {
3855 Result
+= "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
3856 Result
+= CDecl
->getNameAsString();
3860 Result
+= "\t,0,0,0,0\n";
3863 // class metadata generation.
3864 Result
+= "\nstatic struct _objc_class _OBJC_CLASS_";
3865 Result
+= CDecl
->getNameAsString();
3866 Result
+= " __attribute__ ((used, section (\"__OBJC, __class\")))= "
3867 "{\n\t&_OBJC_METACLASS_";
3868 Result
+= CDecl
->getNameAsString();
3871 Result
+= SuperClass
->getNameAsString();
3873 Result
+= CDecl
->getNameAsString();
3877 Result
+= ", 0, \"";
3878 Result
+= CDecl
->getNameAsString();
3881 // 'info' field is initialized to CLS_CLASS(1) for class
3883 if (!ObjCSynthesizedStructs
.count(CDecl
))
3886 // class has size. Must synthesize its size.
3887 Result
+= ",sizeof(struct ";
3888 Result
+= CDecl
->getNameAsString();
3889 if (LangOpts
.Microsoft
)
3894 Result
+= ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
3895 Result
+= CDecl
->getNameAsString();
3900 if (IDecl
->instmeth_begin() != IDecl
->instmeth_end()) {
3901 Result
+= ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
3902 Result
+= CDecl
->getNameAsString();
3903 Result
+= ", 0\n\t";
3907 if (CDecl
->protocol_begin() != CDecl
->protocol_end()) {
3908 Result
+= ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
3909 Result
+= CDecl
->getNameAsString();
3910 Result
+= ", 0,0\n";
3913 Result
+= ",0,0,0\n";
3917 /// RewriteImplementations - This routine rewrites all method implementations
3918 /// and emits meta-data.
3920 void RewriteObjC::RewriteImplementations() {
3921 int ClsDefCount
= ClassImplementation
.size();
3922 int CatDefCount
= CategoryImplementation
.size();
3924 // Rewrite implemented methods
3925 for (int i
= 0; i
< ClsDefCount
; i
++)
3926 RewriteImplementationDecl(ClassImplementation
[i
]);
3928 for (int i
= 0; i
< CatDefCount
; i
++)
3929 RewriteImplementationDecl(CategoryImplementation
[i
]);
3932 void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string
&Result
) {
3933 int ClsDefCount
= ClassImplementation
.size();
3934 int CatDefCount
= CategoryImplementation
.size();
3936 // For each implemented class, write out all its meta data.
3937 for (int i
= 0; i
< ClsDefCount
; i
++)
3938 RewriteObjCClassMetaData(ClassImplementation
[i
], Result
);
3940 // For each implemented category, write out all its meta data.
3941 for (int i
= 0; i
< CatDefCount
; i
++)
3942 RewriteObjCCategoryImplDecl(CategoryImplementation
[i
], Result
);
3944 // Write objc_symtab metadata
3952 void *defs[cls_def_cnt + cat_def_cnt];
3956 Result
+= "\nstruct _objc_symtab {\n";
3957 Result
+= "\tlong sel_ref_cnt;\n";
3958 Result
+= "\tSEL *refs;\n";
3959 Result
+= "\tshort cls_def_cnt;\n";
3960 Result
+= "\tshort cat_def_cnt;\n";
3961 Result
+= "\tvoid *defs[" + utostr(ClsDefCount
+ CatDefCount
)+ "];\n";
3964 Result
+= "static struct _objc_symtab "
3965 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
3966 Result
+= "\t0, 0, " + utostr(ClsDefCount
)
3967 + ", " + utostr(CatDefCount
) + "\n";
3968 for (int i
= 0; i
< ClsDefCount
; i
++) {
3969 Result
+= "\t,&_OBJC_CLASS_";
3970 Result
+= ClassImplementation
[i
]->getNameAsString();
3974 for (int i
= 0; i
< CatDefCount
; i
++) {
3975 Result
+= "\t,&_OBJC_CATEGORY_";
3976 Result
+= CategoryImplementation
[i
]->getClassInterface()->getNameAsString();
3978 Result
+= CategoryImplementation
[i
]->getNameAsString();
3984 // Write objc_module metadata
3987 struct _objc_module {
3991 struct _objc_symtab *symtab;
3995 Result
+= "\nstruct _objc_module {\n";
3996 Result
+= "\tlong version;\n";
3997 Result
+= "\tlong size;\n";
3998 Result
+= "\tconst char *name;\n";
3999 Result
+= "\tstruct _objc_symtab *symtab;\n";
4001 Result
+= "static struct _objc_module "
4002 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
4003 Result
+= "\t" + utostr(OBJC_ABI_VERSION
) +
4004 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
4007 if (LangOpts
.Microsoft
) {
4008 if (ProtocolExprDecls
.size()) {
4009 Result
+= "#pragma section(\".objc_protocol$B\",long,read,write)\n";
4010 Result
+= "#pragma data_seg(push, \".objc_protocol$B\")\n";
4011 for (llvm::SmallPtrSet
<ObjCProtocolDecl
*,8>::iterator I
= ProtocolExprDecls
.begin(),
4012 E
= ProtocolExprDecls
.end(); I
!= E
; ++I
) {
4013 Result
+= "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
4014 Result
+= (*I
)->getNameAsString();
4015 Result
+= " = &_OBJC_PROTOCOL_";
4016 Result
+= (*I
)->getNameAsString();
4019 Result
+= "#pragma data_seg(pop)\n\n";
4021 Result
+= "#pragma section(\".objc_module_info$B\",long,read,write)\n";
4022 Result
+= "#pragma data_seg(push, \".objc_module_info$B\")\n";
4023 Result
+= "static struct _objc_module *_POINTER_OBJC_MODULES = ";
4024 Result
+= "&_OBJC_MODULES;\n";
4025 Result
+= "#pragma data_seg(pop)\n\n";
4029 void RewriteObjC::RewriteByRefString(std::string
&ResultStr
,
4030 const std::string
&Name
,
4032 assert(BlockByRefDeclNo
.count(VD
) &&
4033 "RewriteByRefString: ByRef decl missing");
4034 ResultStr
+= "struct __Block_byref_" + Name
+
4035 "_" + utostr(BlockByRefDeclNo
[VD
]) ;
4038 static bool HasLocalVariableExternalStorage(ValueDecl
*VD
) {
4039 if (VarDecl
*Var
= dyn_cast
<VarDecl
>(VD
))
4040 return (Var
->isFunctionOrMethodVarDecl() && !Var
->hasLocalStorage());
4044 std::string
RewriteObjC::SynthesizeBlockFunc(BlockExpr
*CE
, int i
,
4045 const char *funcName
,
4047 const FunctionType
*AFT
= CE
->getFunctionType();
4048 QualType RT
= AFT
->getResultType();
4049 std::string StructRef
= "struct " + Tag
;
4050 std::string S
= "static " + RT
.getAsString(Context
->PrintingPolicy
) + " __" +
4051 funcName
+ "_" + "block_func_" + utostr(i
);
4053 BlockDecl
*BD
= CE
->getBlockDecl();
4055 if (isa
<FunctionNoProtoType
>(AFT
)) {
4056 // No user-supplied arguments. Still need to pass in a pointer to the
4057 // block (to reference imported block decl refs).
4058 S
+= "(" + StructRef
+ " *__cself)";
4059 } else if (BD
->param_empty()) {
4060 S
+= "(" + StructRef
+ " *__cself)";
4062 const FunctionProtoType
*FT
= cast
<FunctionProtoType
>(AFT
);
4063 assert(FT
&& "SynthesizeBlockFunc: No function proto");
4065 // first add the implicit argument.
4066 S
+= StructRef
+ " *__cself, ";
4067 std::string ParamStr
;
4068 for (BlockDecl::param_iterator AI
= BD
->param_begin(),
4069 E
= BD
->param_end(); AI
!= E
; ++AI
) {
4070 if (AI
!= BD
->param_begin()) S
+= ", ";
4071 ParamStr
= (*AI
)->getNameAsString();
4072 QualType QT
= (*AI
)->getType();
4073 if (convertBlockPointerToFunctionPointer(QT
))
4074 QT
.getAsStringInternal(ParamStr
, Context
->PrintingPolicy
);
4076 QT
.getAsStringInternal(ParamStr
, Context
->PrintingPolicy
);
4079 if (FT
->isVariadic()) {
4080 if (!BD
->param_empty()) S
+= ", ";
4087 // Create local declarations to avoid rewriting all closure decl ref exprs.
4088 // First, emit a declaration for all "by ref" decls.
4089 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByRefDecls
.begin(),
4090 E
= BlockByRefDecls
.end(); I
!= E
; ++I
) {
4092 std::string Name
= (*I
)->getNameAsString();
4093 std::string TypeString
;
4094 RewriteByRefString(TypeString
, Name
, (*I
));
4096 Name
= TypeString
+ Name
;
4097 S
+= Name
+ " = __cself->" + (*I
)->getNameAsString() + "; // bound by ref\n";
4099 // Next, emit a declaration for all "by copy" declarations.
4100 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByCopyDecls
.begin(),
4101 E
= BlockByCopyDecls
.end(); I
!= E
; ++I
) {
4103 // Handle nested closure invocation. For example:
4105 // void (^myImportedClosure)(void);
4106 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
4108 // void (^anotherClosure)(void);
4109 // anotherClosure = ^(void) {
4110 // myImportedClosure(); // import and invoke the closure
4113 if (isTopLevelBlockPointerType((*I
)->getType())) {
4114 RewriteBlockPointerTypeVariable(S
, (*I
));
4116 RewriteBlockPointerType(S
, (*I
)->getType());
4118 S
+= "__cself->" + (*I
)->getNameAsString() + "; // bound by copy\n";
4121 std::string Name
= (*I
)->getNameAsString();
4122 QualType QT
= (*I
)->getType();
4123 if (HasLocalVariableExternalStorage(*I
))
4124 QT
= Context
->getPointerType(QT
);
4125 QT
.getAsStringInternal(Name
, Context
->PrintingPolicy
);
4126 S
+= Name
+ " = __cself->" +
4127 (*I
)->getNameAsString() + "; // bound by copy\n";
4130 std::string RewrittenStr
= RewrittenBlockExprs
[CE
];
4131 const char *cstr
= RewrittenStr
.c_str();
4132 while (*cstr
++ != '{') ;
4138 std::string
RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr
*CE
, int i
,
4139 const char *funcName
,
4141 std::string StructRef
= "struct " + Tag
;
4142 std::string S
= "static void __";
4145 S
+= "_block_copy_" + utostr(i
);
4146 S
+= "(" + StructRef
;
4147 S
+= "*dst, " + StructRef
;
4149 for (llvm::SmallPtrSet
<ValueDecl
*,8>::iterator I
= ImportedBlockDecls
.begin(),
4150 E
= ImportedBlockDecls
.end(); I
!= E
; ++I
) {
4151 S
+= "_Block_object_assign((void*)&dst->";
4152 S
+= (*I
)->getNameAsString();
4153 S
+= ", (void*)src->";
4154 S
+= (*I
)->getNameAsString();
4155 if (BlockByRefDeclsPtrSet
.count((*I
)))
4156 S
+= ", " + utostr(BLOCK_FIELD_IS_BYREF
) + "/*BLOCK_FIELD_IS_BYREF*/);";
4158 S
+= ", " + utostr(BLOCK_FIELD_IS_OBJECT
) + "/*BLOCK_FIELD_IS_OBJECT*/);";
4162 S
+= "\nstatic void __";
4164 S
+= "_block_dispose_" + utostr(i
);
4165 S
+= "(" + StructRef
;
4167 for (llvm::SmallPtrSet
<ValueDecl
*,8>::iterator I
= ImportedBlockDecls
.begin(),
4168 E
= ImportedBlockDecls
.end(); I
!= E
; ++I
) {
4169 S
+= "_Block_object_dispose((void*)src->";
4170 S
+= (*I
)->getNameAsString();
4171 if (BlockByRefDeclsPtrSet
.count((*I
)))
4172 S
+= ", " + utostr(BLOCK_FIELD_IS_BYREF
) + "/*BLOCK_FIELD_IS_BYREF*/);";
4174 S
+= ", " + utostr(BLOCK_FIELD_IS_OBJECT
) + "/*BLOCK_FIELD_IS_OBJECT*/);";
4180 std::string
RewriteObjC::SynthesizeBlockImpl(BlockExpr
*CE
, std::string Tag
,
4182 std::string S
= "\nstruct " + Tag
;
4183 std::string Constructor
= " " + Tag
;
4185 S
+= " {\n struct __block_impl impl;\n";
4186 S
+= " struct " + Desc
;
4189 Constructor
+= "(void *fp, "; // Invoke function pointer.
4190 Constructor
+= "struct " + Desc
; // Descriptor pointer.
4191 Constructor
+= " *desc";
4193 if (BlockDeclRefs
.size()) {
4194 // Output all "by copy" declarations.
4195 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByCopyDecls
.begin(),
4196 E
= BlockByCopyDecls
.end(); I
!= E
; ++I
) {
4198 std::string FieldName
= (*I
)->getNameAsString();
4199 std::string ArgName
= "_" + FieldName
;
4200 // Handle nested closure invocation. For example:
4202 // void (^myImportedBlock)(void);
4203 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
4205 // void (^anotherBlock)(void);
4206 // anotherBlock = ^(void) {
4207 // myImportedBlock(); // import and invoke the closure
4210 if (isTopLevelBlockPointerType((*I
)->getType())) {
4211 S
+= "struct __block_impl *";
4212 Constructor
+= ", void *" + ArgName
;
4214 QualType QT
= (*I
)->getType();
4215 if (HasLocalVariableExternalStorage(*I
))
4216 QT
= Context
->getPointerType(QT
);
4217 QT
.getAsStringInternal(FieldName
, Context
->PrintingPolicy
);
4218 QT
.getAsStringInternal(ArgName
, Context
->PrintingPolicy
);
4219 Constructor
+= ", " + ArgName
;
4221 S
+= FieldName
+ ";\n";
4223 // Output all "by ref" declarations.
4224 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByRefDecls
.begin(),
4225 E
= BlockByRefDecls
.end(); I
!= E
; ++I
) {
4227 std::string FieldName
= (*I
)->getNameAsString();
4228 std::string ArgName
= "_" + FieldName
;
4229 // Handle nested closure invocation. For example:
4231 // void (^myImportedBlock)(void);
4232 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
4234 // void (^anotherBlock)(void);
4235 // anotherBlock = ^(void) {
4236 // myImportedBlock(); // import and invoke the closure
4239 if (isTopLevelBlockPointerType((*I
)->getType())) {
4240 S
+= "struct __block_impl *";
4241 Constructor
+= ", void *" + ArgName
;
4243 std::string TypeString
;
4244 RewriteByRefString(TypeString
, FieldName
, (*I
));
4246 FieldName
= TypeString
+ FieldName
;
4247 ArgName
= TypeString
+ ArgName
;
4248 Constructor
+= ", " + ArgName
;
4250 S
+= FieldName
+ "; // by ref\n";
4252 // Finish writing the constructor.
4253 Constructor
+= ", int flags=0)";
4254 // Initialize all "by copy" arguments.
4255 bool firsTime
= true;
4256 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByCopyDecls
.begin(),
4257 E
= BlockByCopyDecls
.end(); I
!= E
; ++I
) {
4258 std::string Name
= (*I
)->getNameAsString();
4260 Constructor
+= " : ";
4264 Constructor
+= ", ";
4265 if (isTopLevelBlockPointerType((*I
)->getType()))
4266 Constructor
+= Name
+ "((struct __block_impl *)_" + Name
+ ")";
4268 Constructor
+= Name
+ "(_" + Name
+ ")";
4270 // Initialize all "by ref" arguments.
4271 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByRefDecls
.begin(),
4272 E
= BlockByRefDecls
.end(); I
!= E
; ++I
) {
4273 std::string Name
= (*I
)->getNameAsString();
4275 Constructor
+= " : ";
4279 Constructor
+= ", ";
4280 if (isTopLevelBlockPointerType((*I
)->getType()))
4281 Constructor
+= Name
+ "((struct __block_impl *)_"
4282 + Name
+ "->__forwarding)";
4284 Constructor
+= Name
+ "(_" + Name
+ "->__forwarding)";
4287 Constructor
+= " {\n";
4289 Constructor
+= " impl.isa = &_NSConcreteGlobalBlock;\n";
4291 Constructor
+= " impl.isa = &_NSConcreteStackBlock;\n";
4292 Constructor
+= " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
4294 Constructor
+= " Desc = desc;\n";
4296 // Finish writing the constructor.
4297 Constructor
+= ", int flags=0) {\n";
4299 Constructor
+= " impl.isa = &_NSConcreteGlobalBlock;\n";
4301 Constructor
+= " impl.isa = &_NSConcreteStackBlock;\n";
4302 Constructor
+= " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
4303 Constructor
+= " Desc = desc;\n";
4306 Constructor
+= "}\n";
4312 std::string
RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag
,
4313 std::string ImplTag
, int i
,
4314 const char *FunName
,
4316 std::string S
= "\nstatic struct " + DescTag
;
4318 S
+= " {\n unsigned long reserved;\n";
4319 S
+= " unsigned long Block_size;\n";
4321 S
+= " void (*copy)(struct ";
4322 S
+= ImplTag
; S
+= "*, struct ";
4323 S
+= ImplTag
; S
+= "*);\n";
4325 S
+= " void (*dispose)(struct ";
4326 S
+= ImplTag
; S
+= "*);\n";
4330 S
+= DescTag
+ "_DATA = { 0, sizeof(struct ";
4333 S
+= ", __" + std::string(FunName
) + "_block_copy_" + utostr(i
);
4334 S
+= ", __" + std::string(FunName
) + "_block_dispose_" + utostr(i
);
4340 void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart
,
4341 const char *FunName
) {
4342 // Insert declaration for the function in which block literal is used.
4343 if (CurFunctionDeclToDeclareForBlock
&& !Blocks
.empty())
4344 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock
);
4345 bool RewriteSC
= (GlobalVarDecl
&&
4347 GlobalVarDecl
->getStorageClass() == VarDecl::Static
&&
4348 GlobalVarDecl
->getType().getCVRQualifiers());
4350 std::string
SC(" void __");
4351 SC
+= GlobalVarDecl
->getNameAsString();
4353 InsertText(FunLocStart
, SC
);
4356 // Insert closures that were part of the function.
4357 for (unsigned i
= 0, count
=0; i
< Blocks
.size(); i
++) {
4358 CollectBlockDeclRefInfo(Blocks
[i
]);
4359 // Need to copy-in the inner copied-in variables not actually used in this
4361 for (int j
= 0; j
< InnerDeclRefsCount
[i
]; j
++) {
4362 BlockDeclRefExpr
*Exp
= InnerDeclRefs
[count
++];
4363 ValueDecl
*VD
= Exp
->getDecl();
4364 BlockDeclRefs
.push_back(Exp
);
4365 if (!Exp
->isByRef() && !BlockByCopyDeclsPtrSet
.count(VD
)) {
4366 BlockByCopyDeclsPtrSet
.insert(VD
);
4367 BlockByCopyDecls
.push_back(VD
);
4369 if (Exp
->isByRef() && !BlockByRefDeclsPtrSet
.count(VD
)) {
4370 BlockByRefDeclsPtrSet
.insert(VD
);
4371 BlockByRefDecls
.push_back(VD
);
4375 std::string ImplTag
= "__" + std::string(FunName
) + "_block_impl_" + utostr(i
);
4376 std::string DescTag
= "__" + std::string(FunName
) + "_block_desc_" + utostr(i
);
4378 std::string CI
= SynthesizeBlockImpl(Blocks
[i
], ImplTag
, DescTag
);
4380 InsertText(FunLocStart
, CI
);
4382 std::string CF
= SynthesizeBlockFunc(Blocks
[i
], i
, FunName
, ImplTag
);
4384 InsertText(FunLocStart
, CF
);
4386 if (ImportedBlockDecls
.size()) {
4387 std::string HF
= SynthesizeBlockHelperFuncs(Blocks
[i
], i
, FunName
, ImplTag
);
4388 InsertText(FunLocStart
, HF
);
4390 std::string BD
= SynthesizeBlockDescriptor(DescTag
, ImplTag
, i
, FunName
,
4391 ImportedBlockDecls
.size() > 0);
4392 InsertText(FunLocStart
, BD
);
4394 BlockDeclRefs
.clear();
4395 BlockByRefDecls
.clear();
4396 BlockByRefDeclsPtrSet
.clear();
4397 BlockByCopyDecls
.clear();
4398 BlockByCopyDeclsPtrSet
.clear();
4399 ImportedBlockDecls
.clear();
4402 // Must insert any 'const/volatile/static here. Since it has been
4403 // removed as result of rewriting of block literals.
4405 if (GlobalVarDecl
->getStorageClass() == VarDecl::Static
)
4407 if (GlobalVarDecl
->getType().isConstQualified())
4409 if (GlobalVarDecl
->getType().isVolatileQualified())
4411 if (GlobalVarDecl
->getType().isRestrictQualified())
4413 InsertText(FunLocStart
, SC
);
4417 InnerDeclRefsCount
.clear();
4418 InnerDeclRefs
.clear();
4419 RewrittenBlockExprs
.clear();
4422 void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl
*FD
) {
4423 SourceLocation FunLocStart
= FD
->getTypeSpecStartLoc();
4424 const char *FuncName
= FD
->getNameAsCString();
4426 SynthesizeBlockLiterals(FunLocStart
, FuncName
);
4429 static void BuildUniqueMethodName(std::string
&Name
,
4430 ObjCMethodDecl
*MD
) {
4431 ObjCInterfaceDecl
*IFace
= MD
->getClassInterface();
4432 Name
= IFace
->getNameAsCString();
4433 Name
+= "__" + MD
->getSelector().getAsString();
4434 // Convert colons to underscores.
4435 std::string::size_type loc
= 0;
4436 while ((loc
= Name
.find(":", loc
)) != std::string::npos
)
4437 Name
.replace(loc
, 1, "_");
4440 void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl
*MD
) {
4441 //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
4442 //SourceLocation FunLocStart = MD->getLocStart();
4443 SourceLocation FunLocStart
= MD
->getLocStart();
4444 std::string FuncName
;
4445 BuildUniqueMethodName(FuncName
, MD
);
4446 SynthesizeBlockLiterals(FunLocStart
, FuncName
.c_str());
4449 void RewriteObjC::GetBlockDeclRefExprs(Stmt
*S
) {
4450 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
4453 if (BlockExpr
*CBE
= dyn_cast
<BlockExpr
>(*CI
))
4454 GetBlockDeclRefExprs(CBE
->getBody());
4456 GetBlockDeclRefExprs(*CI
);
4458 // Handle specific things.
4459 if (BlockDeclRefExpr
*CDRE
= dyn_cast
<BlockDeclRefExpr
>(S
)) {
4460 // FIXME: Handle enums.
4461 if (!isa
<FunctionDecl
>(CDRE
->getDecl()))
4462 BlockDeclRefs
.push_back(CDRE
);
4464 else if (DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(S
))
4465 if (HasLocalVariableExternalStorage(DRE
->getDecl())) {
4466 BlockDeclRefExpr
*BDRE
=
4467 new (Context
)BlockDeclRefExpr(DRE
->getDecl(), DRE
->getType(),
4468 DRE
->getLocation(), false);
4469 BlockDeclRefs
.push_back(BDRE
);
4475 void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt
*S
,
4476 llvm::SmallVector
<BlockDeclRefExpr
*, 8> &InnerBlockDeclRefs
,
4477 llvm::SmallPtrSet
<const DeclContext
*, 8> &InnerContexts
) {
4478 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
4481 if (BlockExpr
*CBE
= dyn_cast
<BlockExpr
>(*CI
)) {
4482 InnerContexts
.insert(cast
<DeclContext
>(CBE
->getBlockDecl()));
4483 GetInnerBlockDeclRefExprs(CBE
->getBody(),
4488 GetInnerBlockDeclRefExprs(*CI
,
4493 // Handle specific things.
4494 if (BlockDeclRefExpr
*CDRE
= dyn_cast
<BlockDeclRefExpr
>(S
)) {
4495 if (!isa
<FunctionDecl
>(CDRE
->getDecl()) &&
4496 !InnerContexts
.count(CDRE
->getDecl()->getDeclContext()))
4497 InnerBlockDeclRefs
.push_back(CDRE
);
4499 else if (DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(S
)) {
4500 if (VarDecl
*Var
= dyn_cast
<VarDecl
>(DRE
->getDecl()))
4501 if (Var
->isFunctionOrMethodVarDecl())
4502 ImportedLocalExternalDecls
.insert(Var
);
4508 /// convertFunctionTypeOfBlocks - This routine converts a function type
4509 /// whose result type may be a block pointer or whose argument type(s)
4510 /// might be block pointers to an equivalent funtion type replacing
4511 /// all block pointers to function pointers.
4512 QualType
RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType
*FT
) {
4513 const FunctionProtoType
*FTP
= dyn_cast
<FunctionProtoType
>(FT
);
4514 // FTP will be null for closures that don't take arguments.
4515 // Generate a funky cast.
4516 llvm::SmallVector
<QualType
, 8> ArgTypes
;
4517 QualType Res
= FT
->getResultType();
4518 bool HasBlockType
= convertBlockPointerToFunctionPointer(Res
);
4521 for (FunctionProtoType::arg_type_iterator I
= FTP
->arg_type_begin(),
4522 E
= FTP
->arg_type_end(); I
&& (I
!= E
); ++I
) {
4524 // Make sure we convert "t (^)(...)" to "t (*)(...)".
4525 if (convertBlockPointerToFunctionPointer(t
))
4526 HasBlockType
= true;
4527 ArgTypes
.push_back(t
);
4531 // FIXME. Does this work if block takes no argument but has a return type
4532 // which is of block type?
4534 FuncType
= Context
->getFunctionType(Res
,
4535 &ArgTypes
[0], ArgTypes
.size(), false/*no variadic*/, 0,
4536 false, false, 0, 0, FunctionType::ExtInfo());
4537 else FuncType
= QualType(FT
, 0);
4541 Stmt
*RewriteObjC::SynthesizeBlockCall(CallExpr
*Exp
, const Expr
*BlockExp
) {
4542 // Navigate to relevant type information.
4543 const BlockPointerType
*CPT
= 0;
4545 if (const DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(BlockExp
)) {
4546 CPT
= DRE
->getType()->getAs
<BlockPointerType
>();
4547 } else if (const BlockDeclRefExpr
*CDRE
=
4548 dyn_cast
<BlockDeclRefExpr
>(BlockExp
)) {
4549 CPT
= CDRE
->getType()->getAs
<BlockPointerType
>();
4550 } else if (const MemberExpr
*MExpr
= dyn_cast
<MemberExpr
>(BlockExp
)) {
4551 CPT
= MExpr
->getType()->getAs
<BlockPointerType
>();
4553 else if (const ParenExpr
*PRE
= dyn_cast
<ParenExpr
>(BlockExp
)) {
4554 return SynthesizeBlockCall(Exp
, PRE
->getSubExpr());
4556 else if (const ImplicitCastExpr
*IEXPR
= dyn_cast
<ImplicitCastExpr
>(BlockExp
))
4557 CPT
= IEXPR
->getType()->getAs
<BlockPointerType
>();
4558 else if (const ConditionalOperator
*CEXPR
=
4559 dyn_cast
<ConditionalOperator
>(BlockExp
)) {
4560 Expr
*LHSExp
= CEXPR
->getLHS();
4561 Stmt
*LHSStmt
= SynthesizeBlockCall(Exp
, LHSExp
);
4562 Expr
*RHSExp
= CEXPR
->getRHS();
4563 Stmt
*RHSStmt
= SynthesizeBlockCall(Exp
, RHSExp
);
4564 Expr
*CONDExp
= CEXPR
->getCond();
4565 ConditionalOperator
*CondExpr
=
4566 new (Context
) ConditionalOperator(CONDExp
,
4567 SourceLocation(), cast
<Expr
>(LHSStmt
),
4568 SourceLocation(), cast
<Expr
>(RHSStmt
),
4571 } else if (const ObjCIvarRefExpr
*IRE
= dyn_cast
<ObjCIvarRefExpr
>(BlockExp
)) {
4572 CPT
= IRE
->getType()->getAs
<BlockPointerType
>();
4574 assert(1 && "RewriteBlockClass: Bad type");
4576 assert(CPT
&& "RewriteBlockClass: Bad type");
4577 const FunctionType
*FT
= CPT
->getPointeeType()->getAs
<FunctionType
>();
4578 assert(FT
&& "RewriteBlockClass: Bad type");
4579 const FunctionProtoType
*FTP
= dyn_cast
<FunctionProtoType
>(FT
);
4580 // FTP will be null for closures that don't take arguments.
4582 RecordDecl
*RD
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
4584 &Context
->Idents
.get("__block_impl"));
4585 QualType PtrBlock
= Context
->getPointerType(Context
->getTagDeclType(RD
));
4587 // Generate a funky cast.
4588 llvm::SmallVector
<QualType
, 8> ArgTypes
;
4590 // Push the block argument type.
4591 ArgTypes
.push_back(PtrBlock
);
4593 for (FunctionProtoType::arg_type_iterator I
= FTP
->arg_type_begin(),
4594 E
= FTP
->arg_type_end(); I
&& (I
!= E
); ++I
) {
4596 // Make sure we convert "t (^)(...)" to "t (*)(...)".
4597 (void)convertBlockPointerToFunctionPointer(t
);
4598 ArgTypes
.push_back(t
);
4601 // Now do the pointer to function cast.
4602 QualType PtrToFuncCastType
= Context
->getFunctionType(Exp
->getType(),
4603 &ArgTypes
[0], ArgTypes
.size(), false/*no variadic*/, 0,
4605 FunctionType::ExtInfo());
4607 PtrToFuncCastType
= Context
->getPointerType(PtrToFuncCastType
);
4609 CastExpr
*BlkCast
= NoTypeInfoCStyleCastExpr(Context
, PtrBlock
,
4610 CastExpr::CK_Unknown
,
4611 const_cast<Expr
*>(BlockExp
));
4612 // Don't forget the parens to enforce the proper binding.
4613 ParenExpr
*PE
= new (Context
) ParenExpr(SourceLocation(), SourceLocation(),
4617 FieldDecl
*FD
= FieldDecl::Create(*Context
, 0, SourceLocation(),
4618 &Context
->Idents
.get("FuncPtr"), Context
->VoidPtrTy
, 0,
4619 /*BitWidth=*/0, /*Mutable=*/true);
4620 MemberExpr
*ME
= new (Context
) MemberExpr(PE
, true, FD
, SourceLocation(),
4623 CastExpr
*FunkCast
= NoTypeInfoCStyleCastExpr(Context
, PtrToFuncCastType
,
4624 CastExpr::CK_Unknown
, ME
);
4625 PE
= new (Context
) ParenExpr(SourceLocation(), SourceLocation(), FunkCast
);
4627 llvm::SmallVector
<Expr
*, 8> BlkExprs
;
4628 // Add the implicit argument.
4629 BlkExprs
.push_back(BlkCast
);
4630 // Add the user arguments.
4631 for (CallExpr::arg_iterator I
= Exp
->arg_begin(),
4632 E
= Exp
->arg_end(); I
!= E
; ++I
) {
4633 BlkExprs
.push_back(*I
);
4635 CallExpr
*CE
= new (Context
) CallExpr(*Context
, PE
, &BlkExprs
[0],
4637 Exp
->getType(), SourceLocation());
4641 // We need to return the rewritten expression to handle cases where the
4642 // BlockDeclRefExpr is embedded in another expression being rewritten.
4649 // void (^myblock)() = ^() {
4650 // [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
4654 Stmt
*RewriteObjC::RewriteBlockDeclRefExpr(Expr
*DeclRefExp
) {
4655 // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
4656 // for each DeclRefExp where BYREFVAR is name of the variable.
4658 bool isArrow
= true;
4659 if (BlockDeclRefExpr
*BDRE
= dyn_cast
<BlockDeclRefExpr
>(DeclRefExp
))
4660 VD
= BDRE
->getDecl();
4662 VD
= cast
<DeclRefExpr
>(DeclRefExp
)->getDecl();
4666 FieldDecl
*FD
= FieldDecl::Create(*Context
, 0, SourceLocation(),
4667 &Context
->Idents
.get("__forwarding"),
4668 Context
->VoidPtrTy
, 0,
4669 /*BitWidth=*/0, /*Mutable=*/true);
4670 MemberExpr
*ME
= new (Context
) MemberExpr(DeclRefExp
, isArrow
,
4671 FD
, SourceLocation(),
4674 const char *Name
= VD
->getNameAsCString();
4675 FD
= FieldDecl::Create(*Context
, 0, SourceLocation(),
4676 &Context
->Idents
.get(Name
),
4677 Context
->VoidPtrTy
, 0,
4678 /*BitWidth=*/0, /*Mutable=*/true);
4679 ME
= new (Context
) MemberExpr(ME
, true, FD
, SourceLocation(),
4680 DeclRefExp
->getType());
4684 // Need parens to enforce precedence.
4685 ParenExpr
*PE
= new (Context
) ParenExpr(SourceLocation(), SourceLocation(),
4687 ReplaceStmt(DeclRefExp
, PE
);
4691 // Rewrites the imported local variable V with external storage
4692 // (static, extern, etc.) as *V
4694 Stmt
*RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr
*DRE
) {
4695 ValueDecl
*VD
= DRE
->getDecl();
4696 if (VarDecl
*Var
= dyn_cast
<VarDecl
>(VD
))
4697 if (!ImportedLocalExternalDecls
.count(Var
))
4699 Expr
*Exp
= new (Context
) UnaryOperator(DRE
, UnaryOperator::Deref
,
4700 DRE
->getType(), DRE
->getLocation());
4701 // Need parens to enforce precedence.
4702 ParenExpr
*PE
= new (Context
) ParenExpr(SourceLocation(), SourceLocation(),
4704 ReplaceStmt(DRE
, PE
);
4708 void RewriteObjC::RewriteCastExpr(CStyleCastExpr
*CE
) {
4709 SourceLocation LocStart
= CE
->getLParenLoc();
4710 SourceLocation LocEnd
= CE
->getRParenLoc();
4712 // Need to avoid trying to rewrite synthesized casts.
4713 if (LocStart
.isInvalid())
4715 // Need to avoid trying to rewrite casts contained in macros.
4716 if (!Rewriter::isRewritable(LocStart
) || !Rewriter::isRewritable(LocEnd
))
4719 const char *startBuf
= SM
->getCharacterData(LocStart
);
4720 const char *endBuf
= SM
->getCharacterData(LocEnd
);
4721 QualType QT
= CE
->getType();
4722 const Type
* TypePtr
= QT
->getAs
<Type
>();
4723 if (isa
<TypeOfExprType
>(TypePtr
)) {
4724 const TypeOfExprType
*TypeOfExprTypePtr
= cast
<TypeOfExprType
>(TypePtr
);
4725 QT
= TypeOfExprTypePtr
->getUnderlyingExpr()->getType();
4726 std::string TypeAsString
= "(";
4727 RewriteBlockPointerType(TypeAsString
, QT
);
4728 TypeAsString
+= ")";
4729 ReplaceText(LocStart
, endBuf
-startBuf
+1, TypeAsString
);
4732 // advance the location to startArgList.
4733 const char *argPtr
= startBuf
;
4735 while (*argPtr
++ && (argPtr
< endBuf
)) {
4738 // Replace the '^' with '*'.
4739 LocStart
= LocStart
.getFileLocWithOffset(argPtr
-startBuf
);
4740 ReplaceText(LocStart
, 1, "*");
4747 void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl
*FD
) {
4748 SourceLocation DeclLoc
= FD
->getLocation();
4749 unsigned parenCount
= 0;
4751 // We have 1 or more arguments that have closure pointers.
4752 const char *startBuf
= SM
->getCharacterData(DeclLoc
);
4753 const char *startArgList
= strchr(startBuf
, '(');
4755 assert((*startArgList
== '(') && "Rewriter fuzzy parser confused");
4758 // advance the location to startArgList.
4759 DeclLoc
= DeclLoc
.getFileLocWithOffset(startArgList
-startBuf
);
4760 assert((DeclLoc
.isValid()) && "Invalid DeclLoc");
4762 const char *argPtr
= startArgList
;
4764 while (*argPtr
++ && parenCount
) {
4767 // Replace the '^' with '*'.
4768 DeclLoc
= DeclLoc
.getFileLocWithOffset(argPtr
-startArgList
);
4769 ReplaceText(DeclLoc
, 1, "*");
4782 bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT
) {
4783 const FunctionProtoType
*FTP
;
4784 const PointerType
*PT
= QT
->getAs
<PointerType
>();
4786 FTP
= PT
->getPointeeType()->getAs
<FunctionProtoType
>();
4788 const BlockPointerType
*BPT
= QT
->getAs
<BlockPointerType
>();
4789 assert(BPT
&& "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
4790 FTP
= BPT
->getPointeeType()->getAs
<FunctionProtoType
>();
4793 for (FunctionProtoType::arg_type_iterator I
= FTP
->arg_type_begin(),
4794 E
= FTP
->arg_type_end(); I
!= E
; ++I
)
4795 if (isTopLevelBlockPointerType(*I
))
4801 void RewriteObjC::GetExtentOfArgList(const char *Name
, const char *&LParen
,
4802 const char *&RParen
) {
4803 const char *argPtr
= strchr(Name
, '(');
4804 assert((*argPtr
== '(') && "Rewriter fuzzy parser confused");
4806 LParen
= argPtr
; // output the start.
4807 argPtr
++; // skip past the left paren.
4808 unsigned parenCount
= 1;
4810 while (*argPtr
&& parenCount
) {
4812 case '(': parenCount
++; break;
4813 case ')': parenCount
--; break;
4816 if (parenCount
) argPtr
++;
4818 assert((*argPtr
== ')') && "Rewriter fuzzy parser confused");
4819 RParen
= argPtr
; // output the end
4822 void RewriteObjC::RewriteBlockPointerDecl(NamedDecl
*ND
) {
4823 if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(ND
)) {
4824 RewriteBlockPointerFunctionArgs(FD
);
4827 // Handle Variables and Typedefs.
4828 SourceLocation DeclLoc
= ND
->getLocation();
4830 if (VarDecl
*VD
= dyn_cast
<VarDecl
>(ND
))
4831 DeclT
= VD
->getType();
4832 else if (TypedefDecl
*TDD
= dyn_cast
<TypedefDecl
>(ND
))
4833 DeclT
= TDD
->getUnderlyingType();
4834 else if (FieldDecl
*FD
= dyn_cast
<FieldDecl
>(ND
))
4835 DeclT
= FD
->getType();
4837 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
4839 const char *startBuf
= SM
->getCharacterData(DeclLoc
);
4840 const char *endBuf
= startBuf
;
4841 // scan backward (from the decl location) for the end of the previous decl.
4842 while (*startBuf
!= '^' && *startBuf
!= ';' && startBuf
!= MainFileStart
)
4845 // *startBuf != '^' if we are dealing with a pointer to function that
4846 // may take block argument types (which will be handled below).
4847 if (*startBuf
== '^') {
4848 // Replace the '^' with '*', computing a negative offset.
4849 DeclLoc
= DeclLoc
.getFileLocWithOffset(startBuf
-endBuf
);
4850 ReplaceText(DeclLoc
, 1, "*");
4852 if (PointerTypeTakesAnyBlockArguments(DeclT
)) {
4853 // Replace the '^' with '*' for arguments.
4854 DeclLoc
= ND
->getLocation();
4855 startBuf
= SM
->getCharacterData(DeclLoc
);
4856 const char *argListBegin
, *argListEnd
;
4857 GetExtentOfArgList(startBuf
, argListBegin
, argListEnd
);
4858 while (argListBegin
< argListEnd
) {
4859 if (*argListBegin
== '^') {
4860 SourceLocation CaretLoc
= DeclLoc
.getFileLocWithOffset(argListBegin
-startBuf
);
4861 ReplaceText(CaretLoc
, 1, "*");
4870 /// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
4871 /// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
4872 /// struct Block_byref_id_object *src) {
4873 /// _Block_object_assign (&_dest->object, _src->object,
4874 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4875 /// [|BLOCK_FIELD_IS_WEAK]) // object
4876 /// _Block_object_assign(&_dest->object, _src->object,
4877 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4878 /// [|BLOCK_FIELD_IS_WEAK]) // block
4881 /// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
4882 /// _Block_object_dispose(_src->object,
4883 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4884 /// [|BLOCK_FIELD_IS_WEAK]) // object
4885 /// _Block_object_dispose(_src->object,
4886 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4887 /// [|BLOCK_FIELD_IS_WEAK]) // block
4890 std::string
RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl
*VD
,
4893 if (CopyDestroyCache
.count(flag
))
4895 CopyDestroyCache
.insert(flag
);
4896 S
= "static void __Block_byref_id_object_copy_";
4898 S
+= "(void *dst, void *src) {\n";
4900 // offset into the object pointer is computed as:
4901 // void * + void* + int + int + void* + void *
4903 static_cast<unsigned>(Context
->getTypeSize(Context
->IntTy
));
4904 unsigned VoidPtrSize
=
4905 static_cast<unsigned>(Context
->getTypeSize(Context
->VoidPtrTy
));
4907 unsigned offset
= (VoidPtrSize
*4 + IntSize
+ IntSize
)/8;
4908 S
+= " _Block_object_assign((char*)dst + ";
4909 S
+= utostr(offset
);
4910 S
+= ", *(void * *) ((char*)src + ";
4911 S
+= utostr(offset
);
4916 S
+= "static void __Block_byref_id_object_dispose_";
4918 S
+= "(void *src) {\n";
4919 S
+= " _Block_object_dispose(*(void * *) ((char*)src + ";
4920 S
+= utostr(offset
);
4927 /// RewriteByRefVar - For each __block typex ND variable this routine transforms
4928 /// the declaration into:
4929 /// struct __Block_byref_ND {
4930 /// void *__isa; // NULL for everything except __weak pointers
4931 /// struct __Block_byref_ND *__forwarding;
4932 /// int32_t __flags;
4934 /// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
4935 /// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
4939 /// It then replaces declaration of ND variable with:
4940 /// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
4941 /// __size=sizeof(struct __Block_byref_ND),
4942 /// ND=initializer-if-any};
4945 void RewriteObjC::RewriteByRefVar(VarDecl
*ND
) {
4946 // Insert declaration for the function in which block literal is
4948 if (CurFunctionDeclToDeclareForBlock
)
4949 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock
);
4952 SourceLocation DeclLoc
= ND
->getTypeSpecStartLoc();
4953 if (DeclLoc
.isInvalid())
4954 // If type location is missing, it is because of missing type (a warning).
4955 // Use variable's location which is good for this case.
4956 DeclLoc
= ND
->getLocation();
4957 const char *startBuf
= SM
->getCharacterData(DeclLoc
);
4958 SourceLocation X
= ND
->getLocEnd();
4959 X
= SM
->getInstantiationLoc(X
);
4960 const char *endBuf
= SM
->getCharacterData(X
);
4961 std::string
Name(ND
->getNameAsString());
4962 std::string ByrefType
;
4963 RewriteByRefString(ByrefType
, Name
, ND
);
4964 ByrefType
+= " {\n";
4965 ByrefType
+= " void *__isa;\n";
4966 RewriteByRefString(ByrefType
, Name
, ND
);
4967 ByrefType
+= " *__forwarding;\n";
4968 ByrefType
+= " int __flags;\n";
4969 ByrefType
+= " int __size;\n";
4970 // Add void *__Block_byref_id_object_copy;
4971 // void *__Block_byref_id_object_dispose; if needed.
4972 QualType Ty
= ND
->getType();
4973 bool HasCopyAndDispose
= Context
->BlockRequiresCopying(Ty
);
4974 if (HasCopyAndDispose
) {
4975 ByrefType
+= " void (*__Block_byref_id_object_copy)(void*, void*);\n";
4976 ByrefType
+= " void (*__Block_byref_id_object_dispose)(void*);\n";
4979 Ty
.getAsStringInternal(Name
, Context
->PrintingPolicy
);
4980 ByrefType
+= " " + Name
+ ";\n";
4981 ByrefType
+= "};\n";
4982 // Insert this type in global scope. It is needed by helper function.
4983 SourceLocation FunLocStart
;
4985 FunLocStart
= CurFunctionDef
->getTypeSpecStartLoc();
4987 assert(CurMethodDef
&& "RewriteByRefVar - CurMethodDef is null");
4988 FunLocStart
= CurMethodDef
->getLocStart();
4990 InsertText(FunLocStart
, ByrefType
);
4991 if (Ty
.isObjCGCWeak()) {
4992 flag
|= BLOCK_FIELD_IS_WEAK
;
4996 if (HasCopyAndDispose
) {
4997 flag
= BLOCK_BYREF_CALLER
;
4998 QualType Ty
= ND
->getType();
4999 // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
5000 if (Ty
->isBlockPointerType())
5001 flag
|= BLOCK_FIELD_IS_BLOCK
;
5003 flag
|= BLOCK_FIELD_IS_OBJECT
;
5004 std::string HF
= SynthesizeByrefCopyDestroyHelper(ND
, flag
);
5006 InsertText(FunLocStart
, HF
);
5009 // struct __Block_byref_ND ND =
5010 // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
5011 // initializer-if-any};
5012 bool hasInit
= (ND
->getInit() != 0);
5014 if (HasCopyAndDispose
)
5015 flags
|= BLOCK_HAS_COPY_DISPOSE
;
5016 Name
= ND
->getNameAsString();
5018 RewriteByRefString(ByrefType
, Name
, ND
);
5019 std::string
ForwardingCastType("(");
5020 ForwardingCastType
+= ByrefType
+ " *)";
5022 ByrefType
+= " " + Name
+ " = {(void*)";
5023 ByrefType
+= utostr(isa
);
5024 ByrefType
+= "," + ForwardingCastType
+ "&" + Name
+ ", ";
5025 ByrefType
+= utostr(flags
);
5027 ByrefType
+= "sizeof(";
5028 RewriteByRefString(ByrefType
, Name
, ND
);
5030 if (HasCopyAndDispose
) {
5031 ByrefType
+= ", __Block_byref_id_object_copy_";
5032 ByrefType
+= utostr(flag
);
5033 ByrefType
+= ", __Block_byref_id_object_dispose_";
5034 ByrefType
+= utostr(flag
);
5036 ByrefType
+= "};\n";
5037 ReplaceText(DeclLoc
, endBuf
-startBuf
+Name
.size(), ByrefType
);
5040 SourceLocation startLoc
;
5041 Expr
*E
= ND
->getInit();
5042 if (const CStyleCastExpr
*ECE
= dyn_cast
<CStyleCastExpr
>(E
))
5043 startLoc
= ECE
->getLParenLoc();
5045 startLoc
= E
->getLocStart();
5046 startLoc
= SM
->getInstantiationLoc(startLoc
);
5047 endBuf
= SM
->getCharacterData(startLoc
);
5048 ByrefType
+= " " + Name
;
5049 ByrefType
+= " = {(void*)";
5050 ByrefType
+= utostr(isa
);
5051 ByrefType
+= "," + ForwardingCastType
+ "&" + Name
+ ", ";
5052 ByrefType
+= utostr(flags
);
5054 ByrefType
+= "sizeof(";
5055 RewriteByRefString(ByrefType
, Name
, ND
);
5057 if (HasCopyAndDispose
) {
5058 ByrefType
+= "__Block_byref_id_object_copy_";
5059 ByrefType
+= utostr(flag
);
5060 ByrefType
+= ", __Block_byref_id_object_dispose_";
5061 ByrefType
+= utostr(flag
);
5064 ReplaceText(DeclLoc
, endBuf
-startBuf
, ByrefType
);
5066 // Complete the newly synthesized compound expression by inserting a right
5067 // curly brace before the end of the declaration.
5068 // FIXME: This approach avoids rewriting the initializer expression. It
5069 // also assumes there is only one declarator. For example, the following
5070 // isn't currently supported by this routine (in general):
5072 // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
5074 const char *startInitializerBuf
= SM
->getCharacterData(startLoc
);
5075 const char *semiBuf
= strchr(startInitializerBuf
, ';');
5076 assert((*semiBuf
== ';') && "RewriteByRefVar: can't find ';'");
5077 SourceLocation semiLoc
=
5078 startLoc
.getFileLocWithOffset(semiBuf
-startInitializerBuf
);
5080 InsertText(semiLoc
, "}");
5085 void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr
*Exp
) {
5086 // Add initializers for any closure decl refs.
5087 GetBlockDeclRefExprs(Exp
->getBody());
5088 if (BlockDeclRefs
.size()) {
5089 // Unique all "by copy" declarations.
5090 for (unsigned i
= 0; i
< BlockDeclRefs
.size(); i
++)
5091 if (!BlockDeclRefs
[i
]->isByRef()) {
5092 if (!BlockByCopyDeclsPtrSet
.count(BlockDeclRefs
[i
]->getDecl())) {
5093 BlockByCopyDeclsPtrSet
.insert(BlockDeclRefs
[i
]->getDecl());
5094 BlockByCopyDecls
.push_back(BlockDeclRefs
[i
]->getDecl());
5097 // Unique all "by ref" declarations.
5098 for (unsigned i
= 0; i
< BlockDeclRefs
.size(); i
++)
5099 if (BlockDeclRefs
[i
]->isByRef()) {
5100 if (!BlockByRefDeclsPtrSet
.count(BlockDeclRefs
[i
]->getDecl())) {
5101 BlockByRefDeclsPtrSet
.insert(BlockDeclRefs
[i
]->getDecl());
5102 BlockByRefDecls
.push_back(BlockDeclRefs
[i
]->getDecl());
5105 // Find any imported blocks...they will need special attention.
5106 for (unsigned i
= 0; i
< BlockDeclRefs
.size(); i
++)
5107 if (BlockDeclRefs
[i
]->isByRef() ||
5108 BlockDeclRefs
[i
]->getType()->isObjCObjectPointerType() ||
5109 BlockDeclRefs
[i
]->getType()->isBlockPointerType())
5110 ImportedBlockDecls
.insert(BlockDeclRefs
[i
]->getDecl());
5114 FunctionDecl
*RewriteObjC::SynthBlockInitFunctionDecl(const char *name
) {
5115 IdentifierInfo
*ID
= &Context
->Idents
.get(name
);
5116 QualType FType
= Context
->getFunctionNoProtoType(Context
->VoidPtrTy
);
5117 return FunctionDecl::Create(*Context
, TUDecl
,SourceLocation(),
5118 ID
, FType
, 0, FunctionDecl::Extern
,
5119 FunctionDecl::None
, false, false);
5122 Stmt
*RewriteObjC::SynthBlockInitExpr(BlockExpr
*Exp
,
5123 const llvm::SmallVector
<BlockDeclRefExpr
*, 8> &InnerBlockDeclRefs
) {
5124 Blocks
.push_back(Exp
);
5126 CollectBlockDeclRefInfo(Exp
);
5128 // Add inner imported variables now used in current block.
5129 int countOfInnerDecls
= 0;
5130 if (!InnerBlockDeclRefs
.empty()) {
5131 for (unsigned i
= 0; i
< InnerBlockDeclRefs
.size(); i
++) {
5132 BlockDeclRefExpr
*Exp
= InnerBlockDeclRefs
[i
];
5133 ValueDecl
*VD
= Exp
->getDecl();
5134 if (!Exp
->isByRef() && !BlockByCopyDeclsPtrSet
.count(VD
)) {
5135 // We need to save the copied-in variables in nested
5136 // blocks because it is needed at the end for some of the API generations.
5137 // See SynthesizeBlockLiterals routine.
5138 InnerDeclRefs
.push_back(Exp
); countOfInnerDecls
++;
5139 BlockDeclRefs
.push_back(Exp
);
5140 BlockByCopyDeclsPtrSet
.insert(VD
);
5141 BlockByCopyDecls
.push_back(VD
);
5143 if (Exp
->isByRef() && !BlockByRefDeclsPtrSet
.count(VD
)) {
5144 InnerDeclRefs
.push_back(Exp
); countOfInnerDecls
++;
5145 BlockDeclRefs
.push_back(Exp
);
5146 BlockByRefDeclsPtrSet
.insert(VD
);
5147 BlockByRefDecls
.push_back(VD
);
5150 // Find any imported blocks...they will need special attention.
5151 for (unsigned i
= 0; i
< InnerBlockDeclRefs
.size(); i
++)
5152 if (InnerBlockDeclRefs
[i
]->isByRef() ||
5153 InnerBlockDeclRefs
[i
]->getType()->isObjCObjectPointerType() ||
5154 InnerBlockDeclRefs
[i
]->getType()->isBlockPointerType())
5155 ImportedBlockDecls
.insert(InnerBlockDeclRefs
[i
]->getDecl());
5157 InnerDeclRefsCount
.push_back(countOfInnerDecls
);
5159 std::string FuncName
;
5162 FuncName
= CurFunctionDef
->getNameAsString();
5163 else if (CurMethodDef
)
5164 BuildUniqueMethodName(FuncName
, CurMethodDef
);
5165 else if (GlobalVarDecl
)
5166 FuncName
= std::string(GlobalVarDecl
->getNameAsString());
5168 std::string BlockNumber
= utostr(Blocks
.size()-1);
5170 std::string Tag
= "__" + FuncName
+ "_block_impl_" + BlockNumber
;
5171 std::string Func
= "__" + FuncName
+ "_block_func_" + BlockNumber
;
5173 // Get a pointer to the function type so we can cast appropriately.
5174 QualType BFT
= convertFunctionTypeOfBlocks(Exp
->getFunctionType());
5175 QualType FType
= Context
->getPointerType(BFT
);
5180 // Simulate a contructor call...
5181 FD
= SynthBlockInitFunctionDecl(Tag
.c_str());
5182 DeclRefExpr
*DRE
= new (Context
) DeclRefExpr(FD
, FType
, SourceLocation());
5184 llvm::SmallVector
<Expr
*, 4> InitExprs
;
5186 // Initialize the block function.
5187 FD
= SynthBlockInitFunctionDecl(Func
.c_str());
5188 DeclRefExpr
*Arg
= new (Context
) DeclRefExpr(FD
, FD
->getType(),
5190 CastExpr
*castExpr
= NoTypeInfoCStyleCastExpr(Context
, Context
->VoidPtrTy
,
5191 CastExpr::CK_Unknown
, Arg
);
5192 InitExprs
.push_back(castExpr
);
5194 // Initialize the block descriptor.
5195 std::string DescData
= "__" + FuncName
+ "_block_desc_" + BlockNumber
+ "_DATA";
5197 VarDecl
*NewVD
= VarDecl::Create(*Context
, TUDecl
, SourceLocation(),
5198 &Context
->Idents
.get(DescData
.c_str()),
5199 Context
->VoidPtrTy
, 0,
5200 VarDecl::Static
, VarDecl::None
);
5201 UnaryOperator
*DescRefExpr
= new (Context
) UnaryOperator(
5202 new (Context
) DeclRefExpr(NewVD
,
5203 Context
->VoidPtrTy
, SourceLocation()),
5204 UnaryOperator::AddrOf
,
5205 Context
->getPointerType(Context
->VoidPtrTy
),
5207 InitExprs
.push_back(DescRefExpr
);
5209 // Add initializers for any closure decl refs.
5210 if (BlockDeclRefs
.size()) {
5212 // Output all "by copy" declarations.
5213 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByCopyDecls
.begin(),
5214 E
= BlockByCopyDecls
.end(); I
!= E
; ++I
) {
5215 if (isObjCType((*I
)->getType())) {
5216 // FIXME: Conform to ABI ([[obj retain] autorelease]).
5217 FD
= SynthBlockInitFunctionDecl((*I
)->getNameAsCString());
5218 Exp
= new (Context
) DeclRefExpr(FD
, FD
->getType(), SourceLocation());
5219 if (HasLocalVariableExternalStorage(*I
)) {
5220 QualType QT
= (*I
)->getType();
5221 QT
= Context
->getPointerType(QT
);
5222 Exp
= new (Context
) UnaryOperator(Exp
, UnaryOperator::AddrOf
, QT
,
5225 } else if (isTopLevelBlockPointerType((*I
)->getType())) {
5226 FD
= SynthBlockInitFunctionDecl((*I
)->getNameAsCString());
5227 Arg
= new (Context
) DeclRefExpr(FD
, FD
->getType(), SourceLocation());
5228 Exp
= NoTypeInfoCStyleCastExpr(Context
, Context
->VoidPtrTy
,
5229 CastExpr::CK_Unknown
, Arg
);
5231 FD
= SynthBlockInitFunctionDecl((*I
)->getNameAsCString());
5232 Exp
= new (Context
) DeclRefExpr(FD
, FD
->getType(), SourceLocation());
5233 if (HasLocalVariableExternalStorage(*I
)) {
5234 QualType QT
= (*I
)->getType();
5235 QT
= Context
->getPointerType(QT
);
5236 Exp
= new (Context
) UnaryOperator(Exp
, UnaryOperator::AddrOf
, QT
,
5241 InitExprs
.push_back(Exp
);
5243 // Output all "by ref" declarations.
5244 for (llvm::SmallVector
<ValueDecl
*,8>::iterator I
= BlockByRefDecls
.begin(),
5245 E
= BlockByRefDecls
.end(); I
!= E
; ++I
) {
5246 ValueDecl
*ND
= (*I
);
5247 std::string
Name(ND
->getNameAsString());
5248 std::string RecName
;
5249 RewriteByRefString(RecName
, Name
, ND
);
5250 IdentifierInfo
*II
= &Context
->Idents
.get(RecName
.c_str()
5251 + sizeof("struct"));
5252 RecordDecl
*RD
= RecordDecl::Create(*Context
, TTK_Struct
, TUDecl
,
5253 SourceLocation(), II
);
5254 assert(RD
&& "SynthBlockInitExpr(): Can't find RecordDecl");
5255 QualType castT
= Context
->getPointerType(Context
->getTagDeclType(RD
));
5257 FD
= SynthBlockInitFunctionDecl((*I
)->getNameAsCString());
5258 Exp
= new (Context
) DeclRefExpr(FD
, FD
->getType(), SourceLocation());
5259 Exp
= new (Context
) UnaryOperator(Exp
, UnaryOperator::AddrOf
,
5260 Context
->getPointerType(Exp
->getType()),
5262 Exp
= NoTypeInfoCStyleCastExpr(Context
, castT
, CastExpr::CK_Unknown
, Exp
);
5263 InitExprs
.push_back(Exp
);
5266 if (ImportedBlockDecls
.size()) {
5267 // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
5268 int flag
= (BLOCK_HAS_COPY_DISPOSE
| BLOCK_HAS_DESCRIPTOR
);
5270 static_cast<unsigned>(Context
->getTypeSize(Context
->IntTy
));
5271 Expr
*FlagExp
= new (Context
) IntegerLiteral(llvm::APInt(IntSize
, flag
),
5272 Context
->IntTy
, SourceLocation());
5273 InitExprs
.push_back(FlagExp
);
5275 NewRep
= new (Context
) CallExpr(*Context
, DRE
, &InitExprs
[0], InitExprs
.size(),
5276 FType
, SourceLocation());
5277 NewRep
= new (Context
) UnaryOperator(NewRep
, UnaryOperator::AddrOf
,
5278 Context
->getPointerType(NewRep
->getType()),
5280 NewRep
= NoTypeInfoCStyleCastExpr(Context
, FType
, CastExpr::CK_Unknown
,
5282 BlockDeclRefs
.clear();
5283 BlockByRefDecls
.clear();
5284 BlockByRefDeclsPtrSet
.clear();
5285 BlockByCopyDecls
.clear();
5286 BlockByCopyDeclsPtrSet
.clear();
5287 ImportedBlockDecls
.clear();
5291 //===----------------------------------------------------------------------===//
5292 // Function Body / Expression rewriting
5293 //===----------------------------------------------------------------------===//
5295 // This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer().
5296 // The allows the main rewrite loop to associate all ObjCPropertyRefExprs with
5297 // their respective BinaryOperator. Without this knowledge, we'd need to rewrite
5298 // the ObjCPropertyRefExpr twice (once as a getter, and later as a setter).
5299 // Since the rewriter isn't capable of rewriting rewritten code, it's important
5300 // we get this right.
5301 void RewriteObjC::CollectPropertySetters(Stmt
*S
) {
5302 // Perform a bottom up traversal of all children.
5303 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
5306 CollectPropertySetters(*CI
);
5308 if (BinaryOperator
*BinOp
= dyn_cast
<BinaryOperator
>(S
)) {
5309 if (BinOp
->isAssignmentOp()) {
5310 if (ObjCPropertyRefExpr
*PRE
= dyn_cast
<ObjCPropertyRefExpr
>(BinOp
->getLHS()))
5311 PropSetters
[PRE
] = BinOp
;
5316 Stmt
*RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt
*S
) {
5317 if (isa
<SwitchStmt
>(S
) || isa
<WhileStmt
>(S
) ||
5318 isa
<DoStmt
>(S
) || isa
<ForStmt
>(S
))
5320 else if (isa
<ObjCForCollectionStmt
>(S
)) {
5322 ObjCBcLabelNo
.push_back(++BcLabelCount
);
5325 SourceRange OrigStmtRange
= S
->getSourceRange();
5327 // Perform a bottom up rewrite of all children.
5328 for (Stmt::child_iterator CI
= S
->child_begin(), E
= S
->child_end();
5333 if (ObjCIvarRefExpr
*IvarRefExpr
= dyn_cast
<ObjCIvarRefExpr
>(S
)) {
5334 Expr
*OldBase
= IvarRefExpr
->getBase();
5335 bool replaced
= false;
5336 newStmt
= RewriteObjCNestedIvarRefExpr(S
, replaced
);
5338 if (ObjCIvarRefExpr
*IRE
= dyn_cast
<ObjCIvarRefExpr
>(newStmt
))
5339 ReplaceStmt(OldBase
, IRE
->getBase());
5341 ReplaceStmt(S
, newStmt
);
5345 newStmt
= RewriteFunctionBodyOrGlobalInitializer(S
);
5350 if (BlockExpr
*BE
= dyn_cast
<BlockExpr
>(S
)) {
5351 llvm::SmallVector
<BlockDeclRefExpr
*, 8> InnerBlockDeclRefs
;
5352 llvm::SmallPtrSet
<const DeclContext
*, 8> InnerContexts
;
5353 InnerContexts
.insert(BE
->getBlockDecl());
5354 ImportedLocalExternalDecls
.clear();
5355 GetInnerBlockDeclRefExprs(BE
->getBody(),
5356 InnerBlockDeclRefs
, InnerContexts
);
5357 // Rewrite the block body in place.
5358 RewriteFunctionBodyOrGlobalInitializer(BE
->getBody());
5359 ImportedLocalExternalDecls
.clear();
5360 // Now we snarf the rewritten text and stash it away for later use.
5361 std::string Str
= Rewrite
.getRewrittenText(BE
->getSourceRange());
5362 RewrittenBlockExprs
[BE
] = Str
;
5364 Stmt
*blockTranscribed
= SynthBlockInitExpr(BE
, InnerBlockDeclRefs
);
5366 //blockTranscribed->dump();
5367 ReplaceStmt(S
, blockTranscribed
);
5368 return blockTranscribed
;
5370 // Handle specific things.
5371 if (ObjCEncodeExpr
*AtEncode
= dyn_cast
<ObjCEncodeExpr
>(S
))
5372 return RewriteAtEncode(AtEncode
);
5374 if (ObjCPropertyRefExpr
*PropRefExpr
= dyn_cast
<ObjCPropertyRefExpr
>(S
)) {
5375 BinaryOperator
*BinOp
= PropSetters
[PropRefExpr
];
5377 // Because the rewriter doesn't allow us to rewrite rewritten code,
5378 // we need to rewrite the right hand side prior to rewriting the setter.
5379 DisableReplaceStmt
= true;
5380 // Save the source range. Even if we disable the replacement, the
5381 // rewritten node will have been inserted into the tree. If the synthesized
5382 // node is at the 'end', the rewriter will fail. Consider this:
5383 // self.errorHandler = handler ? handler :
5384 // ^(NSURL *errorURL, NSError *error) { return (BOOL)1; };
5385 SourceRange SrcRange
= BinOp
->getSourceRange();
5386 Stmt
*newStmt
= RewriteFunctionBodyOrGlobalInitializer(BinOp
->getRHS());
5387 DisableReplaceStmt
= false;
5389 // Unlike the main iterator, we explicily avoid changing 'BinOp'. If
5390 // we changed the RHS of BinOp, the rewriter would fail (since it needs
5391 // to see the original expression). Consider this example:
5393 // Foo *obj1, *obj2;
5395 // obj1.i = [obj2 rrrr];
5397 // 'BinOp' for the previous expression looks like:
5399 // (BinaryOperator 0x231ccf0 'int' '='
5400 // (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef Property="i"
5401 // (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0))
5402 // (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr
5403 // (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0)))
5405 // 'newStmt' represents the rewritten message expression. For example:
5407 // (CallExpr 0x231d300 'id':'struct objc_object *'
5408 // (ParenExpr 0x231d2e0 'int (*)(id, SEL)'
5409 // (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)'
5410 // (CStyleCastExpr 0x231d220 'void *'
5411 // (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0))))
5413 // Note that 'newStmt' is passed to RewritePropertySetter so that it
5414 // can be used as the setter argument. ReplaceStmt() will still 'see'
5415 // the original RHS (since we haven't altered BinOp).
5417 // This implies the Rewrite* routines can no longer delete the original
5418 // node. As a result, we now leak the original AST nodes.
5420 return RewritePropertySetter(BinOp
, dyn_cast
<Expr
>(newStmt
), SrcRange
);
5422 return RewritePropertyGetter(PropRefExpr
);
5425 if (ObjCSelectorExpr
*AtSelector
= dyn_cast
<ObjCSelectorExpr
>(S
))
5426 return RewriteAtSelector(AtSelector
);
5428 if (ObjCStringLiteral
*AtString
= dyn_cast
<ObjCStringLiteral
>(S
))
5429 return RewriteObjCStringLiteral(AtString
);
5431 if (ObjCMessageExpr
*MessExpr
= dyn_cast
<ObjCMessageExpr
>(S
)) {
5433 // Before we rewrite it, put the original message expression in a comment.
5434 SourceLocation startLoc
= MessExpr
->getLocStart();
5435 SourceLocation endLoc
= MessExpr
->getLocEnd();
5437 const char *startBuf
= SM
->getCharacterData(startLoc
);
5438 const char *endBuf
= SM
->getCharacterData(endLoc
);
5440 std::string messString
;
5441 messString
+= "// ";
5442 messString
.append(startBuf
, endBuf
-startBuf
+1);
5445 // FIXME: Missing definition of
5446 // InsertText(clang::SourceLocation, char const*, unsigned int).
5447 // InsertText(startLoc, messString.c_str(), messString.size());
5448 // Tried this, but it didn't work either...
5449 // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
5451 return RewriteMessageExpr(MessExpr
);
5454 if (ObjCAtTryStmt
*StmtTry
= dyn_cast
<ObjCAtTryStmt
>(S
))
5455 return RewriteObjCTryStmt(StmtTry
);
5457 if (ObjCAtSynchronizedStmt
*StmtTry
= dyn_cast
<ObjCAtSynchronizedStmt
>(S
))
5458 return RewriteObjCSynchronizedStmt(StmtTry
);
5460 if (ObjCAtThrowStmt
*StmtThrow
= dyn_cast
<ObjCAtThrowStmt
>(S
))
5461 return RewriteObjCThrowStmt(StmtThrow
);
5463 if (ObjCProtocolExpr
*ProtocolExp
= dyn_cast
<ObjCProtocolExpr
>(S
))
5464 return RewriteObjCProtocolExpr(ProtocolExp
);
5466 if (ObjCForCollectionStmt
*StmtForCollection
=
5467 dyn_cast
<ObjCForCollectionStmt
>(S
))
5468 return RewriteObjCForCollectionStmt(StmtForCollection
,
5469 OrigStmtRange
.getEnd());
5470 if (BreakStmt
*StmtBreakStmt
=
5471 dyn_cast
<BreakStmt
>(S
))
5472 return RewriteBreakStmt(StmtBreakStmt
);
5473 if (ContinueStmt
*StmtContinueStmt
=
5474 dyn_cast
<ContinueStmt
>(S
))
5475 return RewriteContinueStmt(StmtContinueStmt
);
5477 // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
5479 if (DeclStmt
*DS
= dyn_cast
<DeclStmt
>(S
)) {
5480 // FIXME: What we're doing here is modifying the type-specifier that
5481 // precedes the first Decl. In the future the DeclGroup should have
5482 // a separate type-specifier that we can rewrite.
5483 // NOTE: We need to avoid rewriting the DeclStmt if it is within
5484 // the context of an ObjCForCollectionStmt. For example:
5485 // NSArray *someArray;
5486 // for (id <FooProtocol> index in someArray) ;
5487 // This is because RewriteObjCForCollectionStmt() does textual rewriting
5488 // and it depends on the original text locations/positions.
5489 if (Stmts
.empty() || !isa
<ObjCForCollectionStmt
>(Stmts
.back()))
5490 RewriteObjCQualifiedInterfaceTypes(*DS
->decl_begin());
5492 // Blocks rewrite rules.
5493 for (DeclStmt::decl_iterator DI
= DS
->decl_begin(), DE
= DS
->decl_end();
5496 if (ValueDecl
*ND
= dyn_cast
<ValueDecl
>(SD
)) {
5497 if (isTopLevelBlockPointerType(ND
->getType()))
5498 RewriteBlockPointerDecl(ND
);
5499 else if (ND
->getType()->isFunctionPointerType())
5500 CheckFunctionPointerDecl(ND
->getType(), ND
);
5501 if (VarDecl
*VD
= dyn_cast
<VarDecl
>(SD
)) {
5502 if (VD
->hasAttr
<BlocksAttr
>()) {
5503 static unsigned uniqueByrefDeclCount
= 0;
5504 assert(!BlockByRefDeclNo
.count(ND
) &&
5505 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
5506 BlockByRefDeclNo
[ND
] = uniqueByrefDeclCount
++;
5507 RewriteByRefVar(VD
);
5510 RewriteTypeOfDecl(VD
);
5513 if (TypedefDecl
*TD
= dyn_cast
<TypedefDecl
>(SD
)) {
5514 if (isTopLevelBlockPointerType(TD
->getUnderlyingType()))
5515 RewriteBlockPointerDecl(TD
);
5516 else if (TD
->getUnderlyingType()->isFunctionPointerType())
5517 CheckFunctionPointerDecl(TD
->getUnderlyingType(), TD
);
5522 if (CStyleCastExpr
*CE
= dyn_cast
<CStyleCastExpr
>(S
))
5523 RewriteObjCQualifiedInterfaceTypes(CE
);
5525 if (isa
<SwitchStmt
>(S
) || isa
<WhileStmt
>(S
) ||
5526 isa
<DoStmt
>(S
) || isa
<ForStmt
>(S
)) {
5527 assert(!Stmts
.empty() && "Statement stack is empty");
5528 assert ((isa
<SwitchStmt
>(Stmts
.back()) || isa
<WhileStmt
>(Stmts
.back()) ||
5529 isa
<DoStmt
>(Stmts
.back()) || isa
<ForStmt
>(Stmts
.back()))
5530 && "Statement stack mismatch");
5533 // Handle blocks rewriting.
5534 if (BlockDeclRefExpr
*BDRE
= dyn_cast
<BlockDeclRefExpr
>(S
)) {
5535 if (BDRE
->isByRef())
5536 return RewriteBlockDeclRefExpr(BDRE
);
5538 if (DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(S
)) {
5539 ValueDecl
*VD
= DRE
->getDecl();
5540 if (VD
->hasAttr
<BlocksAttr
>())
5541 return RewriteBlockDeclRefExpr(DRE
);
5542 if (HasLocalVariableExternalStorage(VD
))
5543 return RewriteLocalVariableExternalStorage(DRE
);
5546 if (CallExpr
*CE
= dyn_cast
<CallExpr
>(S
)) {
5547 if (CE
->getCallee()->getType()->isBlockPointerType()) {
5548 Stmt
*BlockCall
= SynthesizeBlockCall(CE
, CE
->getCallee());
5549 ReplaceStmt(S
, BlockCall
);
5553 if (CStyleCastExpr
*CE
= dyn_cast
<CStyleCastExpr
>(S
)) {
5554 RewriteCastExpr(CE
);
5557 if (ImplicitCastExpr
*ICE
= dyn_cast
<ImplicitCastExpr
>(S
)) {
5558 CastExpr
*Replacement
= new (Context
) CastExpr(ICE
->getType(),
5561 // Get the new text.
5563 llvm::raw_string_ostream
Buf(SStr
);
5564 Replacement
->printPretty(Buf
, *Context
);
5565 const std::string
&Str
= Buf
.str();
5567 printf("CAST = %s\n", &Str
[0]);
5568 InsertText(ICE
->getSubExpr()->getLocStart(), &Str
[0], Str
.size());
5573 // Return this stmt unmodified.
5577 void RewriteObjC::RewriteRecordBody(RecordDecl
*RD
) {
5578 for (RecordDecl::field_iterator i
= RD
->field_begin(),
5579 e
= RD
->field_end(); i
!= e
; ++i
) {
5581 if (isTopLevelBlockPointerType(FD
->getType()))
5582 RewriteBlockPointerDecl(FD
);
5583 if (FD
->getType()->isObjCQualifiedIdType() ||
5584 FD
->getType()->isObjCQualifiedInterfaceType())
5585 RewriteObjCQualifiedInterfaceTypes(FD
);
5589 /// HandleDeclInMainFile - This is called for each top-level decl defined in the
5590 /// main file of the input.
5591 void RewriteObjC::HandleDeclInMainFile(Decl
*D
) {
5592 if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(D
)) {
5593 if (FD
->isOverloadedOperator())
5596 // Since function prototypes don't have ParmDecl's, we check the function
5597 // prototype. This enables us to rewrite function declarations and
5598 // definitions using the same code.
5599 RewriteBlocksInFunctionProtoType(FD
->getType(), FD
);
5601 // FIXME: If this should support Obj-C++, support CXXTryStmt
5602 if (CompoundStmt
*Body
= dyn_cast_or_null
<CompoundStmt
>(FD
->getBody())) {
5603 CurFunctionDef
= FD
;
5604 CurFunctionDeclToDeclareForBlock
= FD
;
5605 CollectPropertySetters(Body
);
5608 cast_or_null
<CompoundStmt
>(RewriteFunctionBodyOrGlobalInitializer(Body
));
5611 if (PropParentMap
) {
5612 delete PropParentMap
;
5615 // This synthesizes and inserts the block "impl" struct, invoke function,
5616 // and any copy/dispose helper functions.
5617 InsertBlockLiteralsWithinFunction(FD
);
5619 CurFunctionDeclToDeclareForBlock
= 0;
5623 if (ObjCMethodDecl
*MD
= dyn_cast
<ObjCMethodDecl
>(D
)) {
5624 if (CompoundStmt
*Body
= MD
->getCompoundBody()) {
5626 CollectPropertySetters(Body
);
5629 cast_or_null
<CompoundStmt
>(RewriteFunctionBodyOrGlobalInitializer(Body
));
5632 if (PropParentMap
) {
5633 delete PropParentMap
;
5636 InsertBlockLiteralsWithinMethod(MD
);
5640 if (ObjCImplementationDecl
*CI
= dyn_cast
<ObjCImplementationDecl
>(D
))
5641 ClassImplementation
.push_back(CI
);
5642 else if (ObjCCategoryImplDecl
*CI
= dyn_cast
<ObjCCategoryImplDecl
>(D
))
5643 CategoryImplementation
.push_back(CI
);
5644 else if (ObjCClassDecl
*CD
= dyn_cast
<ObjCClassDecl
>(D
))
5645 RewriteForwardClassDecl(CD
);
5646 else if (VarDecl
*VD
= dyn_cast
<VarDecl
>(D
)) {
5647 RewriteObjCQualifiedInterfaceTypes(VD
);
5648 if (isTopLevelBlockPointerType(VD
->getType()))
5649 RewriteBlockPointerDecl(VD
);
5650 else if (VD
->getType()->isFunctionPointerType()) {
5651 CheckFunctionPointerDecl(VD
->getType(), VD
);
5652 if (VD
->getInit()) {
5653 if (CStyleCastExpr
*CE
= dyn_cast
<CStyleCastExpr
>(VD
->getInit())) {
5654 RewriteCastExpr(CE
);
5657 } else if (VD
->getType()->isRecordType()) {
5658 RecordDecl
*RD
= VD
->getType()->getAs
<RecordType
>()->getDecl();
5659 if (RD
->isDefinition())
5660 RewriteRecordBody(RD
);
5662 if (VD
->getInit()) {
5664 CollectPropertySetters(VD
->getInit());
5665 CurrentBody
= VD
->getInit();
5666 RewriteFunctionBodyOrGlobalInitializer(VD
->getInit());
5668 if (PropParentMap
) {
5669 delete PropParentMap
;
5672 SynthesizeBlockLiterals(VD
->getTypeSpecStartLoc(),
5673 VD
->getNameAsCString());
5676 // This is needed for blocks.
5677 if (CStyleCastExpr
*CE
= dyn_cast
<CStyleCastExpr
>(VD
->getInit())) {
5678 RewriteCastExpr(CE
);
5683 if (TypedefDecl
*TD
= dyn_cast
<TypedefDecl
>(D
)) {
5684 if (isTopLevelBlockPointerType(TD
->getUnderlyingType()))
5685 RewriteBlockPointerDecl(TD
);
5686 else if (TD
->getUnderlyingType()->isFunctionPointerType())
5687 CheckFunctionPointerDecl(TD
->getUnderlyingType(), TD
);
5690 if (RecordDecl
*RD
= dyn_cast
<RecordDecl
>(D
)) {
5691 if (RD
->isDefinition())
5692 RewriteRecordBody(RD
);
5698 void RewriteObjC::HandleTranslationUnit(ASTContext
&C
) {
5699 if (Diags
.hasErrorOccurred())
5704 // Here's a great place to add any extra declarations that may be needed.
5705 // Write out meta data for each @protocol(<expr>).
5706 for (llvm::SmallPtrSet
<ObjCProtocolDecl
*,8>::iterator I
= ProtocolExprDecls
.begin(),
5707 E
= ProtocolExprDecls
.end(); I
!= E
; ++I
)
5708 RewriteObjCProtocolMetaData(*I
, "", "", Preamble
);
5710 InsertText(SM
->getLocForStartOfFile(MainFileID
), Preamble
, false);
5711 if (ClassImplementation
.size() || CategoryImplementation
.size())
5712 RewriteImplementations();
5714 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
5716 if (const RewriteBuffer
*RewriteBuf
=
5717 Rewrite
.getRewriteBufferFor(MainFileID
)) {
5718 //printf("Changed:\n");
5719 *OutFile
<< std::string(RewriteBuf
->begin(), RewriteBuf
->end());
5721 llvm::errs() << "No changes\n";
5724 if (ClassImplementation
.size() || CategoryImplementation
.size() ||
5725 ProtocolExprDecls
.size()) {
5726 // Rewrite Objective-c meta data*
5727 std::string ResultStr
;
5728 SynthesizeMetaDataIntoBuffer(ResultStr
);
5730 *OutFile
<< ResultStr
;