In the old inheriting constructor scheme, copy constructors were not inherited. In the new scheme we needed a rule to get a similar effect; I proposed that an inherited constructor should not be viable if it has a single parameter of a type reference-related to the derived type. Richard Smith proposed a further refinement that this would apply only if the base type is also reference-related to the parameter type. This testcase demonstrates why this refinement is needed.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 5e1645da2601d0c31a2fd0a5687224d6e3087824 Author: Jason Merrill <ja...@redhat.com> Date: Sun Feb 19 16:22:43 2017 -0500 PR c++/79503 - inherited ctor taking base class * call.c (add_function_candidate): Also check that DECL_INHERITED_CTOR_BASE is reference-related to the parameter type. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4ef444b..d6d3a8f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2057,7 +2057,9 @@ add_function_candidate (struct z_candidate **candidates, { tree ptype = non_reference (TREE_VALUE (parmlist)); tree dtype = DECL_CONTEXT (fn); - if (reference_related_p (ptype, dtype)) + tree btype = DECL_INHERITED_CTOR_BASE (fn); + if (reference_related_p (ptype, dtype) + && reference_related_p (btype, ptype)) { viable = false; reason = inherited_ctor_rejection (); diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor26.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor26.C new file mode 100644 index 0000000..e1e6b9e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor26.C @@ -0,0 +1,21 @@ +// PR c++/79503 +// { dg-do compile { target c++11 } } + +struct payload {}; + +struct base: private payload { + base(payload) {} +}; + +struct derived: base { + using base::base; +}; + +int main() +{ + payload data; + // error: no matching function for call to 'derived::derived(payload&)' + // note: candidate: base::base(payload) + // note: an inherited constructor is not a candidate for initialization from an expression of the same or derived type + derived demo(data); +}