[LLVMbugs] [Bug 15922] New: [Objective-C++] Class doesn't respond to selector represented by global variable w/ initializer

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Mon May 6 14:05:57 PDT 2013


http://llvm.org/bugs/show_bug.cgi?id=15922

            Bug ID: 15922
           Summary: [Objective-C++] Class doesn't respond to selector
                    represented by global variable w/ initializer
           Product: clang
           Version: 3.1
          Hardware: Macintosh
                OS: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: felixcca at yahoo.ca
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

Created attachment 10475
  --> http://llvm.org/bugs/attachment.cgi?id=10475&action=edit
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:

> selector=<some address>; name=closeWindow; responds=1  
> selector=<some address>; name=closeWindow; responds=1  
> closeWindow called [3 times]

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:
http://stackoverflow.com/questions/16406992/why-does-my-class-respond-to-my-static-selector-only-in-debug-builds

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20130506/37a5bbd1/attachment.html>


More information about the llvm-bugs mailing list