[cxx-abi-dev] ABI for new inheriting constructor rules

Richard Smith richardsmith at google.com
Thu May 12 21:47:20 UTC 2016


On 12 May 2016 at 13:34, John McCall <rjmccall at apple.com> wrote:

> On May 12, 2016, at 12:07 PM, Richard Smith <richardsmith at google.com>
> wrote:
> On 12 May 2016 at 11:45, John McCall <rjmccall at apple.com> wrote:
>
>> On May 6, 2016, at 2:29 PM, Richard Smith <richardsmith at google.com>
>> wrote:
>> Per http://wg21.link/p0136r1 an inheriting constructor declaration no
>> longer results in the implicit synthesis of derived class constructors, and
>> instead the behavior of a call to an inherited constructor is that:
>>
>>  1) the portion of a hypothetical defaulted default constructor prior to
>> the base constructor invocation is executed, then
>>  2) the inherited constructor is invoked, then
>>  3) the portion of a hypothetical defaulted default constructor after the
>> base constructor invocation is executed
>>
>> There are a couple of obvious ways we could avoid emitting the code for
>> (1) and (3) in every inherited constructor call site:
>>
>>
>> This only affects interoperation to the extent that it's done with vague
>> linkage, since as far as I know there's no way to give an inherited
>> constructor a strong definition.
>>
>
> Yes.
>
> I think we should recommend using (A) in all cases where it's possible,
>> which as far as I know is everything except variadic constructors, and then
>> just inline all the appropriate initialization for variadics.
>>
>
> OK, sounds fine to me. I don't really think the variadic case will come up
> enough to worry about it. The other benefit of the prefix/suffix functions
> is that we can factor out some of the duplication from the CI functions
> themselves, but that seems very much like a secondary benefit.
>
>
> I mean, if we wanted to, we could apply that as a code-size optimization
> across ordinary constructors when we happen to notice that they have
> equivalent initializers.
>
> (A) has to deal with both constructor variants, though.
>>
>
> Good point. Maybe CI1<type> / CI2<type>?
>
>
> That makes sense to me if we do need to distinguish inherited constructors.
>
>
>
>> Is there a reason we can't just continue to mangle the symbol as a C1 or
>> C2 in the derived class?  Just concern about ODR differences when there
>> happens to be a non-trivially-copyable type passed by value?
>>
>
> For a C2 constructor that inherits a constructor from a virtual base, the
> signature will be different from the old approach, because parameters will
> no longer be passed at all (whereas before they were passed and discarded).
> That's probably fine for most calling conventions, but seems risky in
> general. [As a further optimization, we could share the same C2 constructor
> for all inherited constructors that inherit from the same (set of) virtual
> base(s), but I'm not sure that's worth putting into the ABI.]
>
> I'm also concerned about there being edge cases where overload resolution
> could pick between constructors from two different base classes despite
> them mangling the same. Highly-contrived example:
>
> constexpr int f(), g();
> struct A { template<int = f()> A(int); };
> struct B { template<int = g()> B(int); };
> struct C : A, B {
>   using A::A;
>   using B::B;
> };
>
> TU1:
> constexpr int f() { return 0; }
> C c(0);
> constexpr int g() { return 0; }
>
> TU2:
> constexpr int g() { return 0; }
> C c(0);
> constexpr int f() { return 0; }
>
> I think this is valid, with TU1 calling A(int) and TU2 calling B(int).
>
>
> That is a really amazing example.  I feel enriched. :)
>

C++ truly is a remarkable language.


> I'm surprised that the language model here has changed so much, though.
> The inherited constructors really aren't treated as declarations in the
> derived class?  I would expect it to be a much better language model to
> treat them as declarations that just have non-standard semantics when
> invoked.
>

The new semantic model fixes a whole laundry list of issues caused by
building separate declarations for them -- we want to access-check the
constructor as if it were in the base class, we want to handle default
arguments as we would for the base class overload set, we want failures in
the delegating call in the inheriting constructor count as "immediate
context" for the purposes of SFINAE, and so on (see wg21.link/cwg1573,
wg21.link/cwg1645, wg21.link/cwg1715, wg21.link/cwg1736, wg21.link/cwg1941,
wg21.link/cwg1991). Synthesizing a constructor / constructor template makes
it hard to get these cases right, as well as giving the wrong semantics for
argument passing.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20160512/4a06337b/attachment-0001.html>


More information about the cxx-abi-dev mailing list