Our implementation of the CWG 2273 inheritedness tiebreaker seems to be incorrectly considering all inherited members, not just inherited constructors. This patch restricts the tiebreaker accordingly.
DR 2273 gcc/cp/ChangeLog: * call.cc (joust): Restrict inheritedness tiebreaker to constructors. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/using1.C: Expect ambiguity for non-constructor call. * g++.dg/overload/using5.C: Likewise. --- gcc/cp/call.cc | 12 +++++------- gcc/testsuite/g++.dg/cpp1z/using1.C | 7 +++---- gcc/testsuite/g++.dg/overload/using5.C | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 3f753e2d2f9..87b54291b51 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -13350,13 +13350,11 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, } } - /* F1 is a member of a class D, F2 is a member of a base class B of D, and - for all arguments the corresponding parameters of F1 and F2 have the same - type (CWG 2273/2277). */ - if (DECL_P (cand1->fn) && DECL_CLASS_SCOPE_P (cand1->fn) - && !DECL_CONV_FN_P (cand1->fn) - && DECL_P (cand2->fn) && DECL_CLASS_SCOPE_P (cand2->fn) - && !DECL_CONV_FN_P (cand2->fn)) + /* F1 is a constructor for a class D, F2 is a constructor for a base class B + of D, and for all arguments the corresponding parameters of F1 and F2 have + the same type (CWG 2273/2277). */ + if (DECL_P (cand1->fn) && DECL_CONSTRUCTOR_P (cand1->fn) + && DECL_P (cand2->fn) && DECL_CONSTRUCTOR_P (cand2->fn)) { tree base1 = DECL_CONTEXT (strip_inheriting_ctors (cand1->fn)); tree base2 = DECL_CONTEXT (strip_inheriting_ctors (cand2->fn)); diff --git a/gcc/testsuite/g++.dg/cpp1z/using1.C b/gcc/testsuite/g++.dg/cpp1z/using1.C index 1ed939d45fd..c7278ec880a 100644 --- a/gcc/testsuite/g++.dg/cpp1z/using1.C +++ b/gcc/testsuite/g++.dg/cpp1z/using1.C @@ -1,5 +1,4 @@ -// Test for hiding of used base functions when all the conversion sequences are -// equivalent, needed to avoid a regression on inherited default ctors. +// Test the CWG 2237 resolution doesn't apply to inherited non-constructors. struct A { @@ -17,7 +16,7 @@ struct B:A int main() { - B().f(1); // OK, derived f hides base f for single arg + B().f(1); // { dg-error "ambiguous" } B().f(1,2); // OK, base f can still be called with two args - B().g(1); // { dg-error "" } signatures differ, ambiguous + B().g(1); // { dg-error "ambiguous" } signatures differ } diff --git a/gcc/testsuite/g++.dg/overload/using5.C b/gcc/testsuite/g++.dg/overload/using5.C index ad17c78a561..0933a9f0fac 100644 --- a/gcc/testsuite/g++.dg/overload/using5.C +++ b/gcc/testsuite/g++.dg/overload/using5.C @@ -24,5 +24,5 @@ struct C: B { int main() { C c (42); - c.f(); + c.f(); // { dg-error "ambiguous" } } -- 2.46.1.544.g3fb745257b