From richardsmith at google.com Fri May 6 21:29:51 2016 From: richardsmith at google.com (Richard Smith) Date: Fri, 6 May 2016 14:29:51 -0700 Subject: [cxx-abi-dev] ABI for new inheriting constructor rules Message-ID: 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: Approach A: synthesize a fake constructor of the derived class Strawman: add a new form of mangled name for a fake constructor that forwards to a base class constructor, whose is that of the base class constructor, except that the is that of the derived class and the is ::= CI This would give code largely similar to what we generate with the C++11 inheriting constructor rules, except that the additional copy constructions and destructions for parameters would be removed. The downsides are that this only works if we can forward all the arguments (and in particular, we can't do this for varargs constructors), and generates one additional copy of the derived class default initialization code for each base class constructor. Approach B: factor out the duplicated portion of the construction Strawman: add three new forms of mangled name for these constructor fragments: ::= CP [] _ # default constructor prefix ::= CS [] _ # default constructor suffix ::= DP [] _ # default constructor cleanup prefix where in the first and third case the represents the position of the last virtual or direct base class that is constructed or destroyed by the function, and in the second case it represents the position of the last virtual or direct base class that is not constructed by the function (where in each case the base classes are enumerated in the order in which they would be constructed). The CS symbols would destroy the entire class object if an exception is thrown. (I think it'd be fine except in pathological cases to provide only the CS symbols; maybe we could drop the CP/DP ones.) Or perhaps a hybrid of these (it may be reasonable for the constructors from approach A to call the fragments from approach B, especially when optimizing for code size). In any case, use of these new symbols would be optional; implementations could instead choose to emit the code inline. Thoughts? -------------- next part -------------- An HTML attachment was scrubbed... URL: From rjmccall at apple.com Thu May 12 18:45:25 2016 From: rjmccall at apple.com (John McCall) Date: Thu, 12 May 2016 11:45:25 -0700 Subject: [cxx-abi-dev] ABI for new inheriting constructor rules In-Reply-To: References: Message-ID: > On May 6, 2016, at 2:29 PM, Richard Smith 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. 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. (A) has to deal with both constructor variants, though. 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? John. > > > Approach A: synthesize a fake constructor of the derived class > > Strawman: add a new form of mangled name for a fake constructor that forwards to a base class constructor, whose is that of the base class constructor, except that the is that of the derived class and the is > > ::= CI > > This would give code largely similar to what we generate with the C++11 inheriting constructor rules, except that the additional copy constructions and destructions for parameters would be removed. The downsides are that this only works if we can forward all the arguments (and in particular, we can't do this for varargs constructors), and generates one additional copy of the derived class default initialization code for each base class constructor. > > > Approach B: factor out the duplicated portion of the construction > > Strawman: add three new forms of mangled name for these constructor fragments: > > ::= CP [] _ # default constructor prefix > ::= CS [] _ # default constructor suffix > ::= DP [] _ # default constructor cleanup prefix > > where in the first and third case the represents the position of the last virtual or direct base class that is constructed or destroyed by the function, and in the second case it represents the position of the last virtual or direct base class that is not constructed by the function (where in each case the base classes are enumerated in the order in which they would be constructed). > > The CS symbols would destroy the entire class object if an exception is thrown. (I think it'd be fine except in pathological cases to provide only the CS symbols; maybe we could drop the CP/DP ones.) > > > Or perhaps a hybrid of these (it may be reasonable for the constructors from approach A to call the fragments from approach B, especially when optimizing for code size). In any case, use of these new symbols would be optional; implementations could instead choose to emit the code inline. Thoughts? > _______________________________________________ > cxx-abi-dev mailing list > cxx-abi-dev at codesourcery.com > http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From richardsmith at google.com Thu May 12 19:07:44 2016 From: richardsmith at google.com (Richard Smith) Date: Thu, 12 May 2016 12:07:44 -0700 Subject: [cxx-abi-dev] ABI for new inheriting constructor rules In-Reply-To: References: Message-ID: On 12 May 2016 at 11:45, John McCall wrote: > On May 6, 2016, at 2:29 PM, Richard Smith 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. (A) has to deal with both constructor variants, though. > Good point. Maybe CI1 / CI2? > 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 A(int); }; struct B { template 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). John. > > > > > > Approach A: synthesize a fake constructor of the derived class > > Strawman: add a new form of mangled name for a fake constructor that > forwards to a base class constructor, whose is that of the base > class constructor, except that the is that of the derived > class and the is > > ::= CI > > This would give code largely similar to what we generate with the C++11 > inheriting constructor rules, except that the additional copy constructions > and destructions for parameters would be removed. The downsides are that > this only works if we can forward all the arguments (and in particular, we > can't do this for varargs constructors), and generates one additional copy > of the derived class default initialization code for each base class > constructor. > > > > Approach B: factor out the duplicated portion of the construction > > Strawman: add three new forms of mangled name for these constructor > fragments: > > ::= CP [] _ # default constructor prefix > ::= CS [] _ # default constructor suffix > ::= DP [] _ # default constructor cleanup > prefix > > where in the first and third case the represents the position of > the last virtual or direct base class that is constructed or destroyed by > the function, and in the second case it represents the position of the last > virtual or direct base class that is not constructed by the function (where > in each case the base classes are enumerated in the order in which they > would be constructed). > > The CS symbols would destroy the entire class object if an exception is > thrown. (I think it'd be fine except in pathological cases to provide only > the CS symbols; maybe we could drop the CP/DP ones.) > > > Or perhaps a hybrid of these (it may be reasonable for the constructors > from approach A to call the fragments from approach B, especially when > optimizing for code size). In any case, use of these new symbols would be > optional; implementations could instead choose to emit the code inline. > Thoughts? > _______________________________________________ > cxx-abi-dev mailing list > cxx-abi-dev at codesourcery.com > http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rjmccall at apple.com Thu May 12 20:34:25 2016 From: rjmccall at apple.com (John McCall) Date: Thu, 12 May 2016 13:34:25 -0700 Subject: [cxx-abi-dev] ABI for new inheriting constructor rules In-Reply-To: References: Message-ID: <790EE470-52FC-43EA-9047-7972B8D33AD2@apple.com> > On May 12, 2016, at 12:07 PM, Richard Smith wrote: > On 12 May 2016 at 11:45, John McCall > wrote: >> On May 6, 2016, at 2:29 PM, Richard Smith > 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 / CI2? 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 A(int); }; > struct B { template 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. :) 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. John. -------------- next part -------------- An HTML attachment was scrubbed... URL: From richardsmith at google.com Thu May 12 21:47:20 2016 From: richardsmith at google.com (Richard Smith) Date: Thu, 12 May 2016 14:47:20 -0700 Subject: [cxx-abi-dev] ABI for new inheriting constructor rules In-Reply-To: <790EE470-52FC-43EA-9047-7972B8D33AD2@apple.com> References: <790EE470-52FC-43EA-9047-7972B8D33AD2@apple.com> Message-ID: On 12 May 2016 at 13:34, John McCall wrote: > On May 12, 2016, at 12:07 PM, Richard Smith > wrote: > On 12 May 2016 at 11:45, John McCall wrote: > >> On May 6, 2016, at 2:29 PM, Richard Smith >> 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 / CI2? > > > 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 A(int); }; > struct B { template 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: From rjmccall at apple.com Thu May 12 22:08:25 2016 From: rjmccall at apple.com (John McCall) Date: Thu, 12 May 2016 15:08:25 -0700 Subject: [cxx-abi-dev] ABI for new inheriting constructor rules In-Reply-To: References: <790EE470-52FC-43EA-9047-7972B8D33AD2@apple.com> Message-ID: > On May 12, 2016, at 2:47 PM, Richard Smith wrote: > On 12 May 2016 at 13:34, John McCall > wrote: >> On May 12, 2016, at 12:07 PM, Richard Smith > wrote: >> On 12 May 2016 at 11:45, John McCall > wrote: >>> On May 6, 2016, at 2:29 PM, Richard Smith > 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 / CI2? > > 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 A(int); }; >> struct B { template 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. Alright, I accept that we should mangle these differently, and 'CI' seems reasonable. John. -------------- next part -------------- An HTML attachment was scrubbed... URL: