switch (E->getMethodFamily()) {
default:
return true;
+ case OMF_autorelease:
+ if (isRemovable(E)) {
+ // An unused autorelease is badness. If we remove it the receiver
+ // will likely die immediately while previously it was kept alive
+ // by the autorelease pool. This is bad practice in general, leave it
+ // and emit an error to force the user to restructure his code.
+ std::string err = "it is not safe to remove an unused '";
+ err += E->getSelector().getAsString() + "'; its receiver may be "
+ "destroyed immediately";
+ Pass.TA.reportError(err, E->getLocStart(), E->getSourceRange());
+ return true;
+ }
+ // Pass through.
case OMF_retain:
case OMF_release:
- case OMF_autorelease:
if (E->getReceiverKind() == ObjCMessageExpr::Instance)
if (Expr *rec = E->getInstanceReceiver()) {
rec = rec->IgnoreParenImpCasts();
if (rec->getType().getObjCLifetime() == Qualifiers::OCL_ExplicitNone){
- std::string err = "It is not safe to remove '";
+ std::string err = "it is not safe to remove '";
err += E->getSelector().getAsString() + "' message on "
"an __unsafe_unretained type";
Pass.TA.reportError(err, rec->getLocStart());
@end
void test1(A *a, BOOL b, struct UnsafeS *unsafeS) {
- [unsafeS->unsafeObj retain]; // expected-error {{It is not safe to remove 'retain' message on an __unsafe_unretained type}} \
+ [unsafeS->unsafeObj retain]; // expected-error {{it is not safe to remove 'retain' message on an __unsafe_unretained type}} \
// expected-error {{ARC forbids explicit message send}}
[a dealloc];
[a retain];
[a retainCount]; // expected-error {{ARC forbids explicit message send of 'retainCount'}}
[a release];
- [a autorelease];
+ [a autorelease]; // expected-error {{it is not safe to remove an unused 'autorelease'; its receiver may be destroyed immediately}} \
+ // expected-error {{ARC forbids explicit message send}}
CFStringRef cfstr;
NSString *str = (NSString *)cfstr; // expected-error {{cast of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type 'NSString *' requires a bridged cast}} \
NSString *s;
foo(NSString *s): s([s retain]){
NSAutoreleasePool *pool = [NSAutoreleasePool new];
- [[NSString string] autorelease];
+ [[[NSString string] retain] release];
[pool drain];
}
~foo(){ [s release]; }
[[self retain] something];
- [[IhaveSideEffect() retain] autorelease];
- [[x retain] autorelease];
+ [[IhaveSideEffect() retain] release];
+ [[x retain] release];
// do stuff with x;
[x release];
return [self retain];