c++: Make braced-init-list as template arg work with aggr init [PR95369]

Barry pointed out to me that our braced-init-list as a template-argument
extension doesn't work as expected when we aggregate-initialize.  Since
aggregate list-initialization is a user-defined conversion sequence, we
allow it as part of a converted constant expression.

Co-authored-by: Jason Merrill <jason@redhat.com>

gcc/cp/ChangeLog:

	PR c++/95369
	* call.c (build_converted_constant_expr_internal): Allow
	list-initialization.

gcc/testsuite/ChangeLog:

	PR c++/95369
	* g++.dg/cpp2a/nontype-class38.C: New test.
This commit is contained in:
Marek Polacek 2020-06-05 14:22:35 -04:00
parent bcd96c9cce
commit cecc73af49
2 changed files with 33 additions and 1 deletions

View file

@ -4348,7 +4348,7 @@ build_converted_constant_expr_internal (tree type, tree expr,
and where the reference binding (if any) binds directly. */
for (conversion *c = conv;
conv && c->kind != ck_identity;
c && c->kind != ck_identity;
c = next_conversion (c))
{
switch (c->kind)
@ -4356,6 +4356,8 @@ build_converted_constant_expr_internal (tree type, tree expr,
/* A conversion function is OK. If it isn't constexpr, we'll
complain later that the argument isn't constant. */
case ck_user:
/* List-initialization is OK. */
case ck_aggr:
/* The lvalue-to-rvalue conversion is OK. */
case ck_rvalue:
/* Array-to-pointer and function-to-pointer. */

View file

@ -0,0 +1,30 @@
// PR c++/95369
// { dg-do compile { target c++20 } }
struct S {
int a;
int b;
};
struct W {
int i;
S s;
};
template <S p>
void fnc()
{
}
template<S s> struct X { };
template<W w> struct Y { };
void f()
{
fnc<{ .a = 10, .b = 20 }>();
fnc<{ 10, 20 }>();
X<{ .a = 1, .b = 2 }> x;
X<{ 1, 2 }> x2;
// Brace elision is likely to be allowed.
Y<{ 1, 2, 3 }> x3;
}