Incorrect codegen with ARC, @autoreleasepool, an if statement, and -O3
| Originator: | michael.ash | ||
| Number: | rdar://11207070 | Date Originated: | 07-Apr-2012 11:46 PM |
| Status: | Open | Resolved: | |
| Product: | Mac OS X SDK | Product Version: | Xcode 4.3.2 |
| Classification: | Crash | Reproducible: | Always |
Summary:
In a method with an @autoreleasepool, an if statement, and a return within the if statement, clang can emit code that autoreleases the return value before popping the autorelease pool, causing a crash.
Steps to Reproduce:
Compile and run the following program with clang -O3:
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
+ (id)test: (int)x;
@end
@implementation MyClass
+ (id)test: (int)x
{
@autoreleasepool
{
if (x)
return [NSMutableDictionary dictionary];
return nil;
}
}
@end
int main()
{
@autoreleasepool
{
NSLog(@"%@", [MyClass test: 1]);
}
}
Expected Results:
It should print an empty dictionary.
Actual Results:
It crashes with a segmentation fault. The problem is obvious in a disassembly of the binary:
0000000100000e23 callq 0x100000ec0 ; symbol stub for: _objc_retainAutoreleasedReturnValue
0000000100000e28 movq %rax,%rdi
0000000100000e2b callq 0x100000eb4 ; symbol stub for: _objc_autoreleaseReturnValue
0000000100000e30 movq %r14,%rdi
0000000100000e33 callq 0x100000ea8 ; symbol stub for: _objc_autoreleasePoolPop
0000000100000e38 movq %rbx,%rax
0000000100000e3b popq %rbx
0000000100000e3c popq %r14
0000000100000e3e popq %rbp
0000000100000e3f ret
Note the autoreleaseReturnValue before the autoreleasePoolPop. This means the return value is destroyed before being returned to the caller. When the caller tries to use it, it crashes.
Regression:
Unknown.
Notes:
B flat, A.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!