objc-arc: warn when a 'retain' block property is
declared which does not force a 'copy' of the block literal object. // rdar://9829425 llvm-svn: 139706
This commit is contained in:
parent
f915acc613
commit
1723e17b78
|
@ -494,6 +494,9 @@ def warn_property_attr_mismatch : Warning<
|
|||
def warn_objc_property_copy_missing_on_block : Warning<
|
||||
"'copy' attribute must be specified for the block property "
|
||||
"when -fobjc-gc-only is specified">;
|
||||
def warn_objc_property_retain_of_block : Warning<
|
||||
"retain'ed block property does not copy the block "
|
||||
"- use copy attribute instead">;
|
||||
def warn_atomic_property_rule : Warning<
|
||||
"writable atomic property %0 cannot pair a synthesized setter/getter "
|
||||
"with a user defined setter/getter">;
|
||||
|
|
|
@ -1701,7 +1701,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
|
|||
(Attributes & ObjCDeclSpec::DQ_PR_weak)) {
|
||||
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
|
||||
<< "retain" << "weak";
|
||||
Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
|
||||
Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
|
||||
}
|
||||
else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) &&
|
||||
(Attributes & ObjCDeclSpec::DQ_PR_weak)) {
|
||||
|
@ -1743,4 +1743,10 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
|
|||
&& getLangOptions().getGC() == LangOptions::GCOnly
|
||||
&& PropertyTy->isBlockPointerType())
|
||||
Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
|
||||
else if (getLangOptions().ObjCAutoRefCount &&
|
||||
(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
|
||||
!(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
|
||||
!(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
|
||||
PropertyTy->isBlockPointerType())
|
||||
Diag(Loc, diag::warn_objc_property_retain_of_block);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -fblocks -fobjc-arc -fobjc-nonfragile-abi -verify %s
|
||||
// rdar://9829425
|
||||
|
||||
extern void doSomething();
|
||||
|
||||
@interface Test
|
||||
{
|
||||
@public
|
||||
void (^aBlock)(void);
|
||||
}
|
||||
@property (retain) void (^aBlock)(void); // expected-warning {{retain'ed block property does not copy the block - use copy attribute instead}}
|
||||
@property (weak, retain) void (^aBlockW)(void); // expected-error {{property attributes 'retain' and 'weak' are mutually exclusive}}
|
||||
@property (strong, retain) void (^aBlockS)(void); // OK
|
||||
@property (readonly, retain) void (^aBlockR)(void); // OK
|
||||
@property (copy, retain) void (^aBlockC)(void); // expected-error {{property attributes 'copy' and 'retain' are mutually exclusive}}
|
||||
@property (assign, retain) void (^aBlockA)(void); // expected-error {{property attributes 'assign' and 'retain' are mutually exclusive}}
|
||||
@end
|
||||
|
||||
@implementation Test
|
||||
@synthesize aBlock;
|
||||
@dynamic aBlockW, aBlockS, aBlockR, aBlockC, aBlockA;
|
||||
@end
|
||||
|
||||
int main() {
|
||||
Test *t;
|
||||
t.aBlock = ^{ doSomething(); };
|
||||
t.aBlockW = ^{ doSomething(); };
|
||||
t.aBlockS = ^{ doSomething(); };
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ void test0(Test0 *x) {
|
|||
}
|
||||
|
||||
@interface BlockOwner
|
||||
@property (retain) void (^strong)(void);
|
||||
@property (retain) void (^strong)(void); // expected-warning {{retain'ed block property does not copy the block - use copy attribute instead}}
|
||||
@end
|
||||
|
||||
@interface Test1 {
|
||||
|
|
Loading…
Reference in New Issue