Message ID | 20220126235525.571059-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: new-expr of array of deduced class tmpl [PR101988] | expand |
On 1/26/22 18:55, Marek Polacek wrote: > In r12-1933 I attempted to implement DR2397 aka allowing > > int a[3]; > auto (&r)[3] = a; > > by removing the type_uses_auto check in create_array_type_for_decl. > That may have gone too far, because it also allows arrays of > CLASS_PLACEHOLDER_TEMPLATE and it looks like [dcl.type.class.deduct] > prohibits that: "...the declared type of the variable shall be cv T, > where T is the placeholder." However, in /2 it explicitly states that > "A placeholder for a deduced class type can also be used in the > type-specifier-seq in the new-type-id or type-id of a new-expression." > > In this PR, it manifested by making us accept invalid > > template<class T> struct A { A(T); }; > auto p = new A[]{1}; > > [expr.new]/2 says that such a construct is treated as an invented > declaration of the form > > A x[]{1}; > > but, I think, that ought to be ill-formed as per above. So this patch > sort of restores the create_array_type_for_decl check. I should mention > that the difference between [] and [1] is due to cp_parser_new_type_id: > > if (*nelts == NULL_TREE) > /* Leave [] in the declarator. */; > > and groktypename returning different types based on that. > > Does this make sense? Bootstrapped/regtested on x86_64-pc-linux-gnu. OK. > PR c++/101988 > > gcc/cp/ChangeLog: > > * decl.cc (create_array_type_for_decl): Reject forming an array of > placeholder for a deduced class type. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1z/class-deduction-new1.C: New test. > * g++.dg/cpp23/auto-array2.C: New test. > --- > gcc/cp/decl.cc | 12 ++++++++++++ > .../g++.dg/cpp1z/class-deduction-new1.C | 16 ++++++++++++++++ > gcc/testsuite/g++.dg/cpp23/auto-array2.C | 11 +++++++++++ > 3 files changed, 39 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-array2.C > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc > index 6534a7fd320..10e6956117e 100644 > --- a/gcc/cp/decl.cc > +++ b/gcc/cp/decl.cc > @@ -11087,6 +11087,18 @@ 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; > > + /* [dcl.type.class.deduct] prohibits forming an array of placeholder > + for a deduced class type. */ > + if (is_auto (type) && CLASS_PLACEHOLDER_TEMPLATE (type)) > + { > + if (name) > + error_at (loc, "%qD declared as array of template placeholder " > + "type %qT", name, type); > + else > + error ("creating array of template placeholder type %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/cpp1z/class-deduction-new1.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C > new file mode 100644 > index 00000000000..70283353619 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C > @@ -0,0 +1,16 @@ > +// PR c++/101988 > +// { dg-do compile { target c++17 } } > + > +template<typename T> > +struct A { > + A(T); > + A(); > +}; > +auto p1 = new A[]{1}; // { dg-error "creating array of template placeholder type" } > +auto p2 = new A[1]{1}; // { dg-error "invalid use of placeholder" } > +auto p3 = new A<int>[]{1}; > +auto p4 = new A<int>[1]{1}; > +auto p5 = new A[]{1, 2}; // { dg-error "creating array of template placeholder type" } > +auto p6 = new A<int>[]{1, 2}; > +auto p7 = new A<int>[]{A(1), A(1)}; > +auto p8 = new A<int>[2]{A(1), A(1)}; > diff --git a/gcc/testsuite/g++.dg/cpp23/auto-array2.C b/gcc/testsuite/g++.dg/cpp23/auto-array2.C > new file mode 100644 > index 00000000000..06431685b30 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/auto-array2.C > @@ -0,0 +1,11 @@ > +// PR c++/101988 > +// { dg-do compile { target c++17 } } > + > +template<class T> struct A { A(); }; > +A<int> a[3]; > +auto (*p)[3] = &a; > +A<int> (*p2)[3] = &a; > +A (*p3)[3] = &a; // { dg-error "template placeholder type" } > +auto (&r)[3] = a; > +A<int> (&r2)[3] = a; > +A (&r3)[3] = a; // { dg-error "template placeholder type" } > > base-commit: fd5b0488ad5e4f29b65238e06a2d65b7de120235
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 6534a7fd320..10e6956117e 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -11087,6 +11087,18 @@ 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; + /* [dcl.type.class.deduct] prohibits forming an array of placeholder + for a deduced class type. */ + if (is_auto (type) && CLASS_PLACEHOLDER_TEMPLATE (type)) + { + if (name) + error_at (loc, "%qD declared as array of template placeholder " + "type %qT", name, type); + else + error ("creating array of template placeholder type %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/cpp1z/class-deduction-new1.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C new file mode 100644 index 00000000000..70283353619 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C @@ -0,0 +1,16 @@ +// PR c++/101988 +// { dg-do compile { target c++17 } } + +template<typename T> +struct A { + A(T); + A(); +}; +auto p1 = new A[]{1}; // { dg-error "creating array of template placeholder type" } +auto p2 = new A[1]{1}; // { dg-error "invalid use of placeholder" } +auto p3 = new A<int>[]{1}; +auto p4 = new A<int>[1]{1}; +auto p5 = new A[]{1, 2}; // { dg-error "creating array of template placeholder type" } +auto p6 = new A<int>[]{1, 2}; +auto p7 = new A<int>[]{A(1), A(1)}; +auto p8 = new A<int>[2]{A(1), A(1)}; diff --git a/gcc/testsuite/g++.dg/cpp23/auto-array2.C b/gcc/testsuite/g++.dg/cpp23/auto-array2.C new file mode 100644 index 00000000000..06431685b30 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-array2.C @@ -0,0 +1,11 @@ +// PR c++/101988 +// { dg-do compile { target c++17 } } + +template<class T> struct A { A(); }; +A<int> a[3]; +auto (*p)[3] = &a; +A<int> (*p2)[3] = &a; +A (*p3)[3] = &a; // { dg-error "template placeholder type" } +auto (&r)[3] = a; +A<int> (&r2)[3] = a; +A (&r3)[3] = a; // { dg-error "template placeholder type" }