[cfe-dev] Taking the address of an Objective-C @selector expression

Jonathan Roelofs jonathan at codesourcery.com
Thu Apr 30 10:07:37 PDT 2015



On 4/30/15 10:34 AM, Tom Honermann wrote:
> On 04/29/2015 11:31 AM, Jonathan Roelofs wrote:
>>
>>
>> On 4/27/15 12:21 PM, Tom Honermann wrote:
>>> Objective-C @selector expressions yield an rvalue.  However, Clang
>>> (trunk, r234313) allows taking the address of such an expression:
>>>
>>> $ cat t.m
>>> void f() {
>>>      @selector(AMethod);
>>>      &@selector(AMethod);
>>> }
>>>
>>> $ clang --version
>>> clang version 3.7.0 (trunk 234313)
>>> Target: x86_64-unknown-linux-gnu
>>> Thread model: posix
>>>
>>> $ clang -w -c t.m; echo $?
>>> 0
>>>
>>> Gcc (4.8.0) rejects:
>>> $ gcc -c t.m
>>> t.m: In function ‘main’:
>>> t.m:5:20: error: lvalue required as unary ‘&’ operand
>>>       printf("%p\n", &@selector(AMethod));
>>>                      ^
>
> Oops, clearly I was not consistent in my test file.  That should have been:
>
> $ gcc -c t.m
> t.m: In function ‘f’:
> t.m:3:5: error: lvalue required as unary ‘&’ operand
>       &@selector(AMethod);
>       ^
>
>>> I presume acceptance is a Clang bug.  Any dissenters?
>>
>> Looks like it's intentional, but only to match an older GCC:
>> https://llvm.org/bugs/show_bug.cgi?id=7390
>
> Ah, thanks for digging that up!
>
>> I agree with you, I think it should yeild an rvalue.
>
> The Clang AST still considers it an rvalue even though the parser allows
> the & operator to be used.

In CodeGen, sometimes it's an LValue, other times it's an RValue.

>
> <clang>/include/clang/AST/ExprObjC.h:
>   400   ObjCSelectorExpr(QualType T, Selector selInfo,
>   401                    SourceLocation at, SourceLocation rp)
>   402     : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary,
> false, false,
>   403            false, false),
>   404     SelName(selInfo), AtLoc(at), RParenLoc(rp){}
>
> Note the VK_RValue passed to the base class constructor.
>
>  > Having it as a
>> non-const lvalue allows for this kind of weirdness:
>>
>>    *&@selector(AMethod) = @selector(BMethod);
>
>>
>> which seems 'wrong' in the same way that this is:
>>
>>    @selector(AMethod) = @selector(BMethod);
>
> Clang (trunk, r234313) thankfully rejects both of those:
>
> $ cat t.m
> void f() {
>      @selector(AMethod) = @selector(AMethod);
>      &@selector(AMethod) = @selector(AMethod);
> }
>
> $ clang -c t.m
> t.m:2:24: error: expression is not assignable
>      @selector(AMethod) = @selector(AMethod);
>      ~~~~~~~~~~~~~~~~~~ ^
> t.m:3:25: error: expression is not assignable
>      &@selector(AMethod) = @selector(AMethod);
>      ~~~~~~~~~~~~~~~~~~~ ^

I can't think of any place where it makes sense to assign to the address 
of something (aside from operator&() in c++).

Note that my first example had a '*' deref in it, whereas t.m does not.


Jon

> 2 errors generated.
>
>> It seems GCC was fixed in the opposite direction since PR7390. Do you
>> happen to know when that happened?
>
> No, I don't.  I wasn't aware that gcc previously allowed this syntax.
>
> Tom.

-- 
Jon Roelofs
jonathan at codesourcery.com
CodeSourcery / Mentor Embedded




More information about the cfe-dev mailing list