c++: new-expr of array of deduced class tmpl [PR101988]

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.

	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.
This commit is contained in:
Marek Polacek 2022-01-26 17:29:19 -05:00
parent 76ef38e317
commit 0c0f453c4a
3 changed files with 39 additions and 0 deletions

View File

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

View File

@ -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)};

View File

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