[cxx-abi-dev] manglings for exception specifications in function types
Richard Smith
richardsmith at google.com
Wed Oct 12 18:58:14 UTC 2016
On 11 October 2016 at 19:20, John McCall <rjmccall at apple.com> wrote:
> On Oct 11, 2016, at 4:20 PM, Richard Smith <richardsmith at google.com>
> wrote:
> On 11 October 2016 at 15:17, John McCall <rjmccall at apple.com> wrote:
>
>> On Oct 11, 2016, at 2:11 PM, Richard Smith <richardsmith at google.com>
>> wrote:
>> Under
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html
>>
>> the noexceptness of a function type is now part of the type. As a result,
>> we need manglings for exception-specifications on function
>> pointer/reference types:
>>
>> void f(void()) {}
>> void f(void() noexcept) {} // ok, overload not redefinition
>>
>> (It's not clear to me whether or not this was also necessary prior to
>> C++17 to handle dependent exception specifications that appear lexically
>> within the parameter list of a function template, and actual implementation
>> practice varies as to whether such exception specifications are SFINAEable.)
>>
>>
>> In order to handle overloading/SFINAE on exception specifications in
>> dependent cases, we need to be able to mangle not only "noexcept", but also
>> "noexcept(expression)" and "throw(<types>)". Suggestion for manglings:
>>
>> <exception-spec> ::=
>> nx -- non-throwing exception specification
>> nX <expression> E -- computed (value-dependent) noexcept
>> tw <type>* E -- throw (types)
>>
>> <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y]
>> <bare-function-type> [<ref-qualifier>] E
>>
>> In the case of throw(a, b, c), we could omit types that are neither
>> instantiation-dependent nor pack expansions (if that omits all types, we
>> can use the 'nx' mangling instead), since C++17 says you can't overload on
>> the actual types in the dynamic exception specification, and we otherwise
>> only need them to be present if they might result in a substitution failure.
>>
>> Thoughts?
>>
>>
>> I think this is an amazingly late change to the language with pretty thin
>> justification; does that count?
>>
>> This really is a major change which can reasonably be expected to cause
>> substantial source and binary breakage. The proposal mentions
>> transaction_safe as a feature that added similar complexity, but that
>> analogy is weak because (1) TM is expected to be an optional TS, whereas
>> noexcept is a mandatory core language feature, and (2) existing code does
>> not use the transaction_safe attribute, whereas noexcept and throw() have
>> seen widespread adoption, in the latter case for years.
>>
>> If it is a goal of this proposal to eliminate the underspecified fake
>> type system around exception specifications, it is worth noting that it
>> completely fails to do so, since the checking rules for direct function
>> pointer assignments are still quite a bit stronger than those provided by
>> the new type system.
>>
>
> That was indeed a goal here. Can you expand on how it fails? Ignoring the
> (deprecated) dynamic exception specifications, this new approach seems
> stronger than the old type system, since it works for function types being
> arbitrarily nested within other types, not just one level deep within
> function types and pointers.
>
>
> Are there any implementations which actually plan to throw out the dynamic
> exception specification matching logic?
>
*shrug* Maybe MSVC? Any conforming C++17 implementation will need to demote
that side of their enforcement to a warning. And I think there are NB
comments for C++17 proposing that we apply
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0003r4.html for
C++17 rather than waiting for C++20.
> Hmm, I thought we had added a rule to allow B to be deduced in
>
> template<class R, class ...A, bool B> void f(R(A...) noexcept(B));
>
> but it looks like we actually didn't. =(
>
>
> Hmm, that would work pretty well for this case.
>
> Yes, the above is a problem, if noexcept function types start to appear in
> existing code (for instance through use of decltype or by code that passes
> around noexcept function pointers).
>
>
> Well, recall that noexcept function types have always been writable; they
> just didn't necessarily get enforced reliably. Also, noexcept and throw()
> are pretty popular, and aren't there proposals to infer them in more cases?
>
Proposals, yes, but nothing in C++17.
> It's really hard to say abstractly how much impact this will have.
> There's a lot of potential for breakage, but it's also quite possible that
> there won't be many changes and that almost all of them will be lost in the
> great grey expanse of C++ binary compatibility.
>
We'll have an implementation soon, and then we can find out whether this is
a problem in practice.
> You will note that I have omitted the necessary specializations for
>> "transaction_safe", as well as the incredibly common extension of
>> specialized calling conventions.
>>
>> This also breaks source compatibility for template matching, and
>> basically every function template in the standard library is going to
>> change manglings (and become *much* larger) due to noexcept expressions now
>> being mangled.
>>
>
> It's a problem, but I don't think it's as bad as you claim. The mangling
> of a function still wouldn't include its exception specification; this
> would only affect mangling in cases where a parameter or return type or
> template argument involves a function type with an exception-specification
> -- a lot less common than every function template in the standard library,
> but this still does change manglings for existing code.
>
>
> Okay, so it only triggers SFINAE failures in nested function types, and
> you can't overload templates by it? I agree that that helps a lot.
>
> And the entire proposal seems to have forgotten about
>> reference-to-function types.
>>
>
> The change to [dcl.init.ref]p4 allows a reference to non-noexcept function
> to bind to a noexcept function, and this indirectly allows the same during
> overload resolution, casts, and so on. What additional considerations were
> missed?
>
>
> I hadn't realized that the expression logic was so consistent about
> defining e.g. the behavior of the conditional operator on l-values in terms
> of reference binding. I apologize.
>
> ...I see that this adds a new special case to exception handling.
>
Yes; I'd forgotten to mention this side of the ABI change.
We'll also need a new flag on type_info objects to model this. In line with
the transaction_safe changes that Jason proposed, I suggest adding a
__noexcept_mask = 0x40 to __pbase_type_info, and representing a pointer to
noexcept function as a pointer with __noexcept_mask bit set to the
corresponding *non-noexcept* function pointer type.
John.
>
> But if we're just talking about manglings, then yes, I think your ABI
>> proposal is basically fine. :) It's a little unfortunate to include this
>> kind of discrimination so early in the mangling, because some object/image
>> file symbol tables optimize for symbols with common prefixes, but our
>> mangling scheme is generally poor at achieving that anyway.
>>
>> John.
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20161012/0ba85506/attachment.html>
More information about the cxx-abi-dev
mailing list