[PATCH] c++: DR2397 - auto specifier for * and & to arrays [PR100975]

Jason Merrill jason@redhat.com
Tue Jun 29 19:50:27 GMT 2021


On 6/29/21 3:25 PM, Marek Polacek wrote:
> This patch implements DR2397, which removes the restriction in
> [dcl.array]p4 that the array element type may not be a placeholder
> type.  We don't need to worry about decltype(auto) here, so this
> allows code like
> 
>    int a[3];
>    auto (*p)[3] = &a;
>    auto (&r)[3] = a;
> 
> However, note that
> 
>    auto (&&r)[2] = { 1, 2 };
>    auto arr[2] = { 1, 2 };
> 
> still doesn't work (although one day it might) and neither does
> 
>    int arr[5];
>    auto x[5] = arr;
> 
> given that auto deduction is performed in terms of function template
> argument deduction, so the array decays to *.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu.  Does this look OK or
> have I missed a case we want to support?
> 
> 	PR c++/100975
> 	DR 2397
> 
> gcc/cp/ChangeLog:
> 
> 	* decl.c (create_array_type_for_decl): Allow array of auto.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/auto24.C: Remove dg-error.
> 	* g++.dg/cpp0x/auto3.C: Adjust dg-error.
> 	* g++.dg/cpp0x/auto42.C: Likewise.
> 	* g++.dg/cpp0x/initlist75.C: Likewise.
> 	* g++.dg/cpp0x/initlist80.C: Likewise.
> 	* g++.dg/diagnostic/auto1.C: Remove dg-error.
> 	* g++.dg/cpp23/auto-array.C: New test.
> ---
>   gcc/cp/decl.c                           | 11 --------
>   gcc/testsuite/g++.dg/cpp0x/auto24.C     |  3 ++-
>   gcc/testsuite/g++.dg/cpp0x/auto3.C      |  2 +-
>   gcc/testsuite/g++.dg/cpp0x/auto42.C     |  2 +-
>   gcc/testsuite/g++.dg/cpp0x/initlist75.C |  2 +-
>   gcc/testsuite/g++.dg/cpp0x/initlist80.C |  2 +-
>   gcc/testsuite/g++.dg/cpp23/auto-array.C | 36 +++++++++++++++++++++++++
>   gcc/testsuite/g++.dg/diagnostic/auto1.C |  3 ++-
>   8 files changed, 44 insertions(+), 17 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-array.C
> 
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index fa6af6fec11..7672947e64a 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -10969,17 +10969,6 @@ create_array_type_for_decl (tree name, tree type, tree size, location_t loc)
>     if (type == error_mark_node || size == error_mark_node)
>       return error_mark_node;
>   
> -  /* 8.3.4/1: If the type of the identifier of D contains the auto
> -     type-specifier, the program is ill-formed.  */
> -  if (type_uses_auto (type))
> -    {
> -      if (name)
> -	error_at (loc, "%qD declared as array of %qT", name, type);
> -      else
> -	error ("creating array of %qT", type);
> -      return error_mark_node;
> -    }
> -
>     /* If there are some types which cannot be array elements,
>        issue an error-message and return.  */
>     switch (TREE_CODE (type))
> diff --git a/gcc/testsuite/g++.dg/cpp0x/auto24.C b/gcc/testsuite/g++.dg/cpp0x/auto24.C
> index 193f92e977a..ac1ba24f72d 100644
> --- a/gcc/testsuite/g++.dg/cpp0x/auto24.C
> +++ b/gcc/testsuite/g++.dg/cpp0x/auto24.C
> @@ -1,5 +1,6 @@
>   // PR c++/48599
>   // { dg-do compile { target c++11 } }
> +// Allowed since DR2397.
>   
>   int v[1];
> -auto (*p)[1] = &v;		// { dg-error "8:.p. declared as array of .auto" }
> +auto (*p)[1] = &v;
> diff --git a/gcc/testsuite/g++.dg/cpp0x/auto3.C b/gcc/testsuite/g++.dg/cpp0x/auto3.C
> index 2cd0520023d..56439408a0b 100644
> --- a/gcc/testsuite/g++.dg/cpp0x/auto3.C
> +++ b/gcc/testsuite/g++.dg/cpp0x/auto3.C
> @@ -10,7 +10,7 @@ auto x;				// { dg-error "auto" }
>   auto i = 42, j = 42.0;		// { dg-error "auto" }
>   
>   // New CWG issue

Let's at least update this comment to quote [dcl.type.auto.deduct]/2: "T 
shall not be an array type".  I guess "unable to deduce" is a suitable 
diagnostic for that error.

> -auto a[2] = { 1, 2 };		// { dg-error "6:.a. declared as array of .auto" }
> +auto a[2] = { 1, 2 };		// { dg-error "20:unable to deduce" }
>   
>   template<class T>
>   struct A { };
> diff --git a/gcc/testsuite/g++.dg/cpp0x/auto42.C b/gcc/testsuite/g++.dg/cpp0x/auto42.C
> index 8d15fc96f09..5b2f6779aaf 100644
> --- a/gcc/testsuite/g++.dg/cpp0x/auto42.C
> +++ b/gcc/testsuite/g++.dg/cpp0x/auto42.C
> @@ -5,5 +5,5 @@
>   
>   void foo(int i)
>   {
> -  auto x[1] = { 0 };		// { dg-error "8:.x. declared as array of .auto" }
> +  auto x[1] = { 0 };		// { dg-error "19:unable to deduce" }
>   }
> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist75.C b/gcc/testsuite/g++.dg/cpp0x/initlist75.C
> index 9a45087c5e4..f572f5181ad 100644
> --- a/gcc/testsuite/g++.dg/cpp0x/initlist75.C
> +++ b/gcc/testsuite/g++.dg/cpp0x/initlist75.C
> @@ -3,4 +3,4 @@
>   
>   #include <initializer_list>
>   
> -auto foo[] = {};    // { dg-error "6:.foo. declared as array of .auto" }
> +auto foo[] = {};    // { dg-error "15:unable to deduce" }
> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist80.C b/gcc/testsuite/g++.dg/cpp0x/initlist80.C
> index 15723be16f8..a6ab40ca349 100644
> --- a/gcc/testsuite/g++.dg/cpp0x/initlist80.C
> +++ b/gcc/testsuite/g++.dg/cpp0x/initlist80.C
> @@ -3,4 +3,4 @@
>   
>   #include <initializer_list>
>   
> -auto x[2] = {};			// { dg-error "6:.x. declared as array of .auto" }
> +auto x[2] = {};			// { dg-error "14:unable to deduce" }
> diff --git a/gcc/testsuite/g++.dg/cpp23/auto-array.C b/gcc/testsuite/g++.dg/cpp23/auto-array.C
> new file mode 100644
> index 00000000000..42f2b0c5cf4
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp23/auto-array.C
> @@ -0,0 +1,36 @@
> +// PR c++/100975
> +// DR 2397 - auto specifier for pointers and references to arrays
> +// { dg-do compile { target c++11 } }
> +
> +struct false_type { static constexpr bool value = false; };
> +struct true_type { static constexpr bool value = true; };
> +template<class T, class U>
> +struct is_same : false_type {};
> +template<class T>
> +struct is_same<T, T> : true_type {};
> +
> +using U = int[3];
> +
> +void
> +g ()
> +{
> +  int a[3];
> +  auto (*p)[3] = &a;
> +  auto (&r)[3] = a;
> +  int aa[3][3];
> +  auto (*pp)[3][3] = &aa;
> +  auto (&rr)[3][3] = aa;
> +
> +  auto (&&rv)[3] = U{};
> +
> +  static_assert (is_same<decltype (p), int(*)[3]>::value, "");
> +  static_assert (is_same<decltype (pp), int(*)[3][3]>::value, "");
> +  static_assert (is_same<decltype (r), int(&)[3]>::value, "");
> +  static_assert (is_same<decltype (rv), int(&&)[3]>::value, "");
> +  static_assert (is_same<decltype (rr), int(&)[3][3]>::value, "");
> +
> +#if __cplusplus >= 201402L
> +  // In a generic lambda parameter this was OK even before.
> +  auto l = [](auto (&arr)[5]) { return arr[0]; };
> +#endif
> +}
> diff --git a/gcc/testsuite/g++.dg/diagnostic/auto1.C b/gcc/testsuite/g++.dg/diagnostic/auto1.C
> index ee2eefd59aa..9d9979e3fdc 100644
> --- a/gcc/testsuite/g++.dg/diagnostic/auto1.C
> +++ b/gcc/testsuite/g++.dg/diagnostic/auto1.C
> @@ -1,4 +1,5 @@
>   // PR c++/86915
>   // { dg-do compile { target c++17 } }
> +// Allowed since DR2397.

Well, not really; any attempt to use this template should hit the same 
problem as above of trying to do auto deduction where T is an array 
type.  Please add to the testcase to get the error.

> -template<auto [1]> struct S; // { dg-error "creating array of .auto." }
> +template<auto [1]> struct S;
> 
> base-commit: 8a8a7d332d5d01db5aea7336a36d9fd71a679fb1



More information about the Gcc-patches mailing list