[cfe-dev] PR15105: __attribute__((noreturn)) and noreturn function types

Richard Smith richard at metafoo.co.uk
Wed Jan 30 12:18:14 PST 2013


On Wed, Jan 30, 2013 at 12:04 PM, Douglas Gregor <dgregor at apple.com> wrote:
>
> On Jan 29, 2013, at 6:36 PM, Richard Smith <richard at metafoo.co.uk> wrote:
>
>> On Tue, Jan 29, 2013 at 4:58 PM, Douglas Gregor <dgregor at apple.com> wrote:
>>>
>>> On Jan 29, 2013, at 4:51 PM, John McCall <rjmccall at apple.com> wrote:
>>>
>>>> On Jan 29, 2013, at 3:41 PM, Richard Smith <richard at metafoo.co.uk> wrote:
>>>>> As PR15105 notes, our implementation of __attribute__((noreturn)) is
>>>>> not entirely GCC-compatible. As far as I can tell, the situation in
>>>>> GCC is:
>>>>>
>>>>> GCC does not have a plain 'noreturn function' type.
>>>>> __attribute__((noreturn)) on a function declaration makes that
>>>>> declaration declare a noreturn function. It does not affect the
>>>>> function's type.
>>>>> __attribute__((noreturn)) on a function pointer or function reference
>>>>> produces a 'pointer/reference to noreturn function' type.
>>>>> GCC allows implicit conversions in either direction between
>>>>> pointer-to-noreturn-function and pointer-to-function.
>>>>>
>>>>> In Clang:
>>>>>
>>>>> Clang *does* have a plain 'noreturn function' type.
>>>>> __attribute__((noreturn)) on a function declaration makes that
>>>>> declaration declare a noreturn function, and *adjusts the function
>>>>> type* to be a noreturn function.
>>>>> __attribute__((noreturn)) on a function pointer or function reference
>>>>> produces a 'pointer/reference to noreturn function' type.
>>>>> Clang allows a pointer-to-noreturn-function to implicitly convert to a
>>>>> pointer-to-function, but not vice versa.
>>>>>
>>>>> So... Clang's approach is more sound and type-safe, but it's not
>>>>> GCC-compatible. The difference reaches into the language semantics
>>>>> (C++ templates can tell the difference between noreturn and
>>>>> not-noreturn functions), and the ABI (GCC has a different mangling for
>>>>> pointer-to-noreturn-function which Clang does not implement).
>>>>>
>>>>> What do people think? Is our improved behavior here sufficient to
>>>>> justify the GCC incompatibility, or should we switch to being GCC
>>>>> compatible? Or pick some middle-ground -- perhaps we could continue to
>>>>> diagnose pointer-to-function to pointer-to-noreturn-function
>>>>> conversions, except where the source expression is directly taking the
>>>>> address of a noreturn function?
>>>>
>>>> We're not guided by language standards here, and GCC's model for this
>>>> is quite bizarre, probably because of the internal representational issues.
>>>> For example, they drop "noreturn" on member functions because volatile
>>>> functions are valid there, and I assume they get the subtype relationship
>>>> wrong because it's generally valid to add the volatile qualifier in
>>>> a pointer conversion.
>>>>
>>>> If their model were any less broken, I might agree with the compatibility
>>>> argument.  As it is, it seems like a major drop in functionality for a pretty
>>>> theoretical interoperation gain.
>>>>
>>>> That said, I see no reason not to adopt their mangling as a special case
>>>> when mangling pointers and references to noreturn functions.
>>>
>>>
>>> Agreed on all points. We designed the model we wanted for noreturn, and I think it's still the right one. Perhaps we can instead convince GCC to fix their non-type-safe model :)
>>
>> OK. The C11 and C++11 noreturn attributes are much closer to GCC's
>> model than to ours (noreturn is not ever part of the type for the
>> standard attributes, so they're the same as GCC's attributes in the
>> places where they're valid). I guess we're going to have to put up
>> with having two different models of 'noreturn' in Clang in perpetuity.
>
> There might be other ways to improve the Clang model and make it more compatible with GCC. For example, remove noreturn from the type of a noreturn function declaration. Then, introduce an implicit conversion from declaration references to noreturn functions to noreturn function pointer/reference types. It's still sound, but closer to GCC.

Yes, that's what I was suggesting in my 'middle-ground' option, and is
still my preferred option. I no longer think the status quo is viable;
PR15105 notes that we're actually rejecting valid code as a result of
our current behavior, because we can't compile this:

  std::bind(std::exit, 0)




More information about the cfe-dev mailing list