[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