diff mbox series

[v2] c++: Fall through for arrays of T vs T cv [PR104996]

Message ID 2ed200df-ec89-4dfb-8855-80e6f1409b72@www.fastmail.com
State New
Headers show
Series [v2] c++: Fall through for arrays of T vs T cv [PR104996] | expand

Commit Message

Ed Catmur April 18, 2022, 10:09 p.m. UTC
If two arrays do not have the exact same element type including qualification, this could be e.g. f(int (&&)[]) vs. f(int const (&)[]), which can still be distinguished by the lvalue-rvalue tiebreaker.

By tightening this branch (in accordance with the letter of the Standard) we fall through to the next branch, which tests whether they have different element type ignoring qualification and returns 0 in that case; thus we only actually fall through in the T[...] vs. T cv[...] case, eventually considering the lvalue-rvalue tiebreaker at the end of compare_ics.

Bootstrapped and tested on x86_64-pc-linux-gnu.

Signed-off-by: Ed Catmur <ed@catmur.uk>

	PR c++/104996

gcc/cp/ChangeLog:

	* call.cc (compare_ics): When comparing list-initialization sequences, do not return early.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/initlist129.C: New test.
---
 gcc/cp/call.cc                           | 7 ++-----
 gcc/testsuite/g++.dg/cpp0x/initlist129.C | 6 ++++++
 2 files changed, 8 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist129.C

Comments

Jason Merrill April 21, 2022, 12:48 p.m. UTC | #1
On 4/18/22 18:09, Ed Catmur wrote:
> If two arrays do not have the exact same element type including qualification, this could be e.g. f(int (&&)[]) vs. f(int const (&)[]), which can still be distinguished by the lvalue-rvalue tiebreaker.
> 
> By tightening this branch (in accordance with the letter of the Standard) we fall through to the next branch, which tests whether they have different element type ignoring qualification and returns 0 in that case; thus we only actually fall through in the T[...] vs. T cv[...] case, eventually considering the lvalue-rvalue tiebreaker at the end of compare_ics.
> 
> Bootstrapped and tested on x86_64-pc-linux-gnu.
> 
> Signed-off-by: Ed Catmur <ed@catmur.uk>

Applied, thanks.

> 	PR c++/104996
> 
> gcc/cp/ChangeLog:
> 
> 	* call.cc (compare_ics): When comparing list-initialization sequences, do not return early.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/initlist129.C: New test.
> ---
>   gcc/cp/call.cc                           | 7 ++-----
>   gcc/testsuite/g++.dg/cpp0x/initlist129.C | 6 ++++++
>   2 files changed, 8 insertions(+), 5 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist129.C
> 
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 51d8f6c3fb1..fa18d7f8f9d 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -11546,12 +11546,9 @@ compare_ics (conversion *ics1, conversion *ics2)
>   	 P0388R4.)  */
>         else if (t1->kind == ck_aggr
>   	       && TREE_CODE (t1->type) == ARRAY_TYPE
> -	       && TREE_CODE (t2->type) == ARRAY_TYPE)
> +	       && TREE_CODE (t2->type) == ARRAY_TYPE
> +	       && same_type_p (TREE_TYPE (t1->type), TREE_TYPE (t2->type)))
>   	{
> -	  /* The type of the array elements must be the same.  */
> -	  if (!same_type_p (TREE_TYPE (t1->type), TREE_TYPE (t2->type)))
> -	    return 0;
> -
>   	  tree n1 = nelts_initialized_by_list_init (t1);
>   	  tree n2 = nelts_initialized_by_list_init (t2);
>   	  if (tree_int_cst_lt (n1, n2))
> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist129.C b/gcc/testsuite/g++.dg/cpp0x/initlist129.C
> new file mode 100644
> index 00000000000..4d4faa9e08d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/initlist129.C
> @@ -0,0 +1,6 @@
> +// PR c++/104996
> +// { dg-do compile { target c++11 } }
> +
> +template<unsigned size> char f(int (&&)[size]);
> +template<unsigned size> int f(int const (&)[size]);
> +static_assert(sizeof(f({1, 2, 3})) == 1, "");
diff mbox series

Patch

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 51d8f6c3fb1..fa18d7f8f9d 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -11546,12 +11546,9 @@  compare_ics (conversion *ics1, conversion *ics2)
 	 P0388R4.)  */
       else if (t1->kind == ck_aggr
 	       && TREE_CODE (t1->type) == ARRAY_TYPE
-	       && TREE_CODE (t2->type) == ARRAY_TYPE)
+	       && TREE_CODE (t2->type) == ARRAY_TYPE
+	       && same_type_p (TREE_TYPE (t1->type), TREE_TYPE (t2->type)))
 	{
-	  /* The type of the array elements must be the same.  */
-	  if (!same_type_p (TREE_TYPE (t1->type), TREE_TYPE (t2->type)))
-	    return 0;
-
 	  tree n1 = nelts_initialized_by_list_init (t1);
 	  tree n2 = nelts_initialized_by_list_init (t2);
 	  if (tree_int_cst_lt (n1, n2))
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist129.C b/gcc/testsuite/g++.dg/cpp0x/initlist129.C
new file mode 100644
index 00000000000..4d4faa9e08d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist129.C
@@ -0,0 +1,6 @@ 
+// PR c++/104996
+// { dg-do compile { target c++11 } }
+
+template<unsigned size> char f(int (&&)[size]);
+template<unsigned size> int f(int const (&)[size]);
+static_assert(sizeof(f({1, 2, 3})) == 1, "");