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

Tom Honermann thonermann at coverity.com
Thu Apr 30 09:34:52 PDT 2015


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.

<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);
     ~~~~~~~~~~~~~~~~~~~ ^
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.




More information about the cfe-dev mailing list