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