[1/2] c++: CWG 2273 and non-constructors

Message ID 20240918205946.4082171-1-ppalka@redhat.com
State New
Headers
Series [1/2] c++: CWG 2273 and non-constructors |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Patrick Palka Sept. 18, 2024, 8:59 p.m. UTC
  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(-)
  

Comments

Patrick Palka Sept. 20, 2024, 2:02 p.m. UTC | #1
On Wed, 18 Sep 2024, Patrick Palka wrote:

> 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))

Here's v2 which refines this condition to check DECL_INHERITED_CTOR
instead.  No functional change, but this more narrow condition seems
cleaner.

-- >8 --

Subject: [PATCH 1/2] c++: CWG 2273 and non-constructors

Our implementation of the CWG 2273 inheritedness tiebreaker seems to be
incorrectly considering all member functions introduced via using, not
just 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                         | 11 ++++-------
 gcc/testsuite/g++.dg/cpp1z/using1.C    |  8 ++++----
 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..6229dc45263 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13350,13 +13350,10 @@ 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_INHERITED_CTOR (cand1->fn) || DECL_INHERITED_CTOR (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..d8a04525579 100644
--- a/gcc/testsuite/g++.dg/cpp1z/using1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/using1.C
@@ -1,5 +1,5 @@
-// 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 2273 inheritedness tiebreaker doesn't apply to
+// non-constructors.
 
 struct A
 {
@@ -17,7 +17,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" }
 }
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" }
 }
  
Jason Merrill Sept. 20, 2024, 2:24 p.m. UTC | #2
On 9/20/24 4:02 PM, Patrick Palka wrote:
> On Wed, 18 Sep 2024, Patrick Palka wrote:
> 
>> 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))
> 
> Here's v2 which refines this condition to check DECL_INHERITED_CTOR
> instead.  No functional change, but this more narrow condition seems
> cleaner.

OK.

> -- >8 --
> 
> Subject: [PATCH 1/2] c++: CWG 2273 and non-constructors
> 
> Our implementation of the CWG 2273 inheritedness tiebreaker seems to be
> incorrectly considering all member functions introduced via using, not
> just 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                         | 11 ++++-------
>   gcc/testsuite/g++.dg/cpp1z/using1.C    |  8 ++++----
>   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..6229dc45263 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -13350,13 +13350,10 @@ 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_INHERITED_CTOR (cand1->fn) || DECL_INHERITED_CTOR (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..d8a04525579 100644
> --- a/gcc/testsuite/g++.dg/cpp1z/using1.C
> +++ b/gcc/testsuite/g++.dg/cpp1z/using1.C
> @@ -1,5 +1,5 @@
> -// 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 2273 inheritedness tiebreaker doesn't apply to
> +// non-constructors.
>   
>   struct A
>   {
> @@ -17,7 +17,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" }
>   }
> 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" }
>   }
  

Patch

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" }
 }