<html>
<head>
<base href="http://llvm.org/bugs/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - [Objective-C++] Class doesn't respond to selector represented by global variable w/ initializer"
href="http://llvm.org/bugs/show_bug.cgi?id=15922">15922</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>[Objective-C++] Class doesn't respond to selector represented by global variable w/ initializer
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>3.1
</td>
</tr>
<tr>
<th>Hardware</th>
<td>Macintosh
</td>
</tr>
<tr>
<th>OS</th>
<td>MacOS X
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>-New Bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>felixcca@yahoo.ca
</td>
</tr>
<tr>
<th>CC</th>
<td>llvmbugs@cs.uiuc.edu
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>Created <span class=""><a href="attachment.cgi?id=10475" name="attach_10475" title="Xcode project reproducing the issue">attachment 10475</a> <a href="attachment.cgi?id=10475&action=edit" title="Xcode project reproducing the issue">[details]</a></span>
Xcode project reproducing the issue
Consider this runnable Objective-C++ snippet:
#import <Foundation/Foundation.h>
@interface Foo : NSObject
-(void)closeWindow;
@end
@implementation Foo
-(void)closeWindow { puts("closeWindow called"); }
@end
static SEL globalSelector = @selector(closeWindow);
void printSelectorInfo(id target, SEL sel) {
const char* name = sel_getName(sel);
BOOL responds = [target respondsToSelector:sel];
printf("selector=%p; name=%s; responds=%hhu\n", sel, name, responds);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
SEL localSelector = @selector(closeWindow);
Foo* foo = [[Foo alloc] init];
printSelectorInfo(foo, localSelector);
printSelectorInfo(foo, globalSelector);
[foo closeWindow];
[foo performSelector:localSelector];
[foo performSelector:globalSelector];
}
}
In normal Objective-C, global variables must have a constant initializer as
dictated by C, and therefore `static SEL globalSelector =
@selector(closeWindow)` wouldn't be valid. This restriction is lifted in
C++/Objective-C++, and it compiles without issues.
This would be the expected output:
<span class="quote">> selector=<some address>; name=closeWindow; responds=1
> selector=<some address>; name=closeWindow; responds=1
> closeWindow called [3 times]</span >
And it's indeed what I get in Debug configuration (in Xcode):
selector=0x7fff952d63a1; name=closeWindow; responds=1
selector=0x7fff952d63a1; name=closeWindow; responds=1
closeWindow called
closeWindow called
closeWindow called
However, things go wrong in Release configuration:
selector=0x7fff952d63a1; name=closeWindow; responds=1
selector=0x100000eca; name=closeWindow; responds=0
closeWindow called
closeWindow called
2013-05-06 16:40:11.960 selectors[5048:303] *** NSForwarding: warning:
selector (0x100000eca) for message 'closeWindow' does not match selector known
to Objective C runtime (0x7fff952d63a1)-- abort
2013-05-06 16:40:11.964 selectors[5048:303] -[Foo closeWindow]:
unrecognized selector sent to instance 0x100108240
2013-05-06 16:40:11.966 selectors[5048:303] *** Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[Foo closeWindow]:
unrecognized selector sent to instance 0x100108240'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff91116b06
__exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff904843f0
objc_exception_throw + 43
2 CoreFoundation 0x00007fff911ad40a
-[NSObject(NSObject) doesNotRecognizeSelector:] + 186
3 CoreFoundation 0x00007fff9110502e
___forwarding___ + 414
4 CoreFoundation 0x00007fff91104e18
_CF_forwarding_prep_0 + 232
5 selectors 0x0000000100000e14 main + 234
6 libdyld.dylib 0x00007fff944a77e1 start + 0
7 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminate called throwing an exception
Notice that now, while they still have the same name, the selectors don't have
the same address, and `Foo` only responds to the selector in the local
variable.
Interestingly enough, the issue seems to be name-sensitive. If I change the
name of the method to, say, `foo`, it works correctly.
The parameter list passed to clang by Xcode is a little scary, but here are the
differences:
* Debug passes `-O0`; release passes `-Os`;
* Debug has `-DDEBUG=1`;
* Release has `fvisibility=hidden`;
* The name of the configuration is included in `-iquote`, `-I`, `-MF`,
`--serialize-diagnostics` and `-o` params (so they say Debug in debug
configuration and Release in release configuration).
If I'm being dumb and it's actually not a bug, consider explaining why on this
Stack Overflow question:
<a href="http://stackoverflow.com/questions/16406992/why-does-my-class-respond-to-my-static-selector-only-in-debug-builds">http://stackoverflow.com/questions/16406992/why-does-my-class-respond-to-my-static-selector-only-in-debug-builds</a></pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>