mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 19:03:59 +08:00
c++: Support non-type template parms of union type.
Another thing newly allowed by P1907R1. The ABI group has discussed representing unions with designated initializers, and has separately specified how to represent designators; this patch implements both. gcc/cp/ChangeLog: * tree.c (structural_type_p): Allow unions. * mangle.c (write_expression): Express unions with a designator. libiberty/ChangeLog: * cp-demangle.c (cplus_demangle_operators): Add di, dx, dX. (d_expression_1): Handle di and dX. (is_designated_init, d_maybe_print_designated_init): New. (d_print_comp_inner): Use d_maybe_print_designated_init. * testsuite/demangle-expected: Add designator tests. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/nontype-class-union1.C: New test.
This commit is contained in:
parent
50f071d999
commit
6324c52bba
@ -3189,6 +3189,7 @@ write_expression (tree expr)
|
||||
{
|
||||
vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr);
|
||||
unsigned last_nonzero = UINT_MAX, i;
|
||||
constructor_elt *ce;
|
||||
tree val;
|
||||
|
||||
if (!nontriv)
|
||||
@ -3197,12 +3198,18 @@ write_expression (tree expr)
|
||||
last_nonzero = i;
|
||||
|
||||
if (nontriv || last_nonzero != UINT_MAX)
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
|
||||
for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i)
|
||||
{
|
||||
if (i > last_nonzero)
|
||||
break;
|
||||
/* FIXME handle RANGE_EXPR */
|
||||
write_expression (val);
|
||||
if (TREE_CODE (etype) == UNION_TYPE)
|
||||
{
|
||||
/* Express the active member as a designator. */
|
||||
write_string ("di");
|
||||
write_unqualified_name (ce->index);
|
||||
}
|
||||
write_expression (ce->value);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -4534,13 +4534,6 @@ structural_type_p (tree t, bool explain)
|
||||
structural types or (possibly multi-dimensional) array thereof. */
|
||||
if (!CLASS_TYPE_P (t))
|
||||
return false;
|
||||
if (TREE_CODE (t) == UNION_TYPE)
|
||||
{
|
||||
/* FIXME allow (and mangle) unions. */
|
||||
if (explain)
|
||||
inform (location_of (t), "%qT is a union", t);
|
||||
return false;
|
||||
}
|
||||
if (!literal_type_p (t))
|
||||
{
|
||||
if (explain)
|
||||
|
25
gcc/testsuite/g++.dg/cpp2a/nontype-class-union1.C
Normal file
25
gcc/testsuite/g++.dg/cpp2a/nontype-class-union1.C
Normal file
@ -0,0 +1,25 @@
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
template <auto N> struct A {};
|
||||
template <class,class> struct assert_same;
|
||||
template <class T> struct assert_same<T,T> {};
|
||||
|
||||
#define TEQ(X,Y) static_assert(__is_same(A<(X)>,A<(Y)>))
|
||||
#define TNEQ(X,Y) static_assert(!__is_same(A<(X)>,A<(Y)>))
|
||||
|
||||
union U {
|
||||
int i; int j;
|
||||
constexpr U(int i): i(i) {}
|
||||
constexpr U(unsigned u): j(u) {}
|
||||
};
|
||||
|
||||
TEQ(U(0),U(0));
|
||||
|
||||
// Calling the other constructor initializes a different member with the same
|
||||
// value. We need to distinguish these.
|
||||
TNEQ(U(0),U(0u));
|
||||
|
||||
// { dg-final { scan-assembler "_Z1f1AIXtl1Udi1iLi0EEEE" } }
|
||||
void f(A<U(0)>) { }
|
||||
// { dg-final { scan-assembler "_Z1g1AIXtl1Udi1jLi0EEEE" } }
|
||||
void g(A<U(0u)>) { }
|
@ -1809,13 +1809,16 @@ const struct demangle_operator_info cplus_demangle_operators[] =
|
||||
{ "cm", NL (","), 2 },
|
||||
{ "co", NL ("~"), 1 },
|
||||
{ "dV", NL ("/="), 2 },
|
||||
{ "dX", NL ("[...]="), 3 }, /* [expr...expr] = expr */
|
||||
{ "da", NL ("delete[] "), 1 },
|
||||
{ "dc", NL ("dynamic_cast"), 2 },
|
||||
{ "de", NL ("*"), 1 },
|
||||
{ "di", NL ("="), 2 }, /* .name = expr */
|
||||
{ "dl", NL ("delete "), 1 },
|
||||
{ "ds", NL (".*"), 2 },
|
||||
{ "dt", NL ("."), 2 },
|
||||
{ "dv", NL ("/"), 2 },
|
||||
{ "dx", NL ("]="), 2 }, /* [expr] = expr */
|
||||
{ "eO", NL ("^="), 2 },
|
||||
{ "eo", NL ("^"), 2 },
|
||||
{ "eq", NL ("=="), 2 },
|
||||
@ -3291,6 +3294,12 @@ op_is_new_cast (struct demangle_component *op)
|
||||
::= sr <type> <unqualified-name>
|
||||
::= sr <type> <unqualified-name> <template-args>
|
||||
::= <expr-primary>
|
||||
|
||||
<braced-expression> ::= <expression>
|
||||
::= di <field source-name> <braced-expression> # .name = expr
|
||||
::= dx <index expression> <braced-expression> # [expr] = expr
|
||||
::= dX <range begin expression> <range end expression> <braced-expression>
|
||||
# [expr ... expr] = expr
|
||||
*/
|
||||
|
||||
static inline struct demangle_component *
|
||||
@ -3453,6 +3462,8 @@ d_expression_1 (struct d_info *di)
|
||||
else if (code[0] == 'f')
|
||||
/* fold-expression. */
|
||||
left = d_operator_name (di);
|
||||
else if (!strcmp (code, "di"))
|
||||
left = d_unqualified_name (di);
|
||||
else
|
||||
left = d_expression_1 (di);
|
||||
if (!strcmp (code, "cl"))
|
||||
@ -3480,7 +3491,8 @@ d_expression_1 (struct d_info *di)
|
||||
|
||||
if (code == NULL)
|
||||
return NULL;
|
||||
else if (!strcmp (code, "qu"))
|
||||
else if (!strcmp (code, "qu")
|
||||
|| !strcmp (code, "dX"))
|
||||
{
|
||||
/* ?: expression. */
|
||||
first = d_expression_1 (di);
|
||||
@ -4675,6 +4687,64 @@ d_maybe_print_fold_expression (struct d_print_info *dpi, int options,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* True iff DC represents a C99-style designated initializer. */
|
||||
|
||||
static int
|
||||
is_designated_init (struct demangle_component *dc)
|
||||
{
|
||||
if (dc->type != DEMANGLE_COMPONENT_BINARY
|
||||
&& dc->type != DEMANGLE_COMPONENT_TRINARY)
|
||||
return 0;
|
||||
|
||||
struct demangle_component *op = d_left (dc);
|
||||
const char *code = op->u.s_operator.op->code;
|
||||
return (code[0] == 'd'
|
||||
&& (code[1] == 'i' || code[1] == 'x' || code[1] == 'X'));
|
||||
}
|
||||
|
||||
/* If DC represents a C99-style designated initializer, print it and return
|
||||
true; otherwise, return false. */
|
||||
|
||||
static int
|
||||
d_maybe_print_designated_init (struct d_print_info *dpi, int options,
|
||||
struct demangle_component *dc)
|
||||
{
|
||||
if (!is_designated_init (dc))
|
||||
return 0;
|
||||
|
||||
const char *code = d_left (dc)->u.s_operator.op->code;
|
||||
|
||||
struct demangle_component *operands = d_right (dc);
|
||||
struct demangle_component *op1 = d_left (operands);
|
||||
struct demangle_component *op2 = d_right (operands);
|
||||
|
||||
if (code[1] == 'i')
|
||||
d_append_char (dpi, '.');
|
||||
else
|
||||
d_append_char (dpi, '[');
|
||||
|
||||
d_print_comp (dpi, options, op1);
|
||||
if (code[1] == 'X')
|
||||
{
|
||||
d_append_string (dpi, " ... ");
|
||||
d_print_comp (dpi, options, d_left (op2));
|
||||
op2 = d_right (op2);
|
||||
}
|
||||
if (code[1] != 'i')
|
||||
d_append_char (dpi, ']');
|
||||
if (is_designated_init (op2))
|
||||
{
|
||||
/* Don't put '=' or '(' between chained designators. */
|
||||
d_print_comp (dpi, options, op2);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_append_char (dpi, '=');
|
||||
d_print_subexpr (dpi, options, op2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Subroutine to handle components. */
|
||||
|
||||
static void
|
||||
@ -5491,6 +5561,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
|
||||
if (d_maybe_print_fold_expression (dpi, options, dc))
|
||||
return;
|
||||
|
||||
if (d_maybe_print_designated_init (dpi, options, dc))
|
||||
return;
|
||||
|
||||
/* We wrap an expression which uses the greater-than operator in
|
||||
an extra layer of parens so that it does not get confused
|
||||
with the '>' which ends the template parameters. */
|
||||
@ -5548,6 +5621,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
|
||||
}
|
||||
if (d_maybe_print_fold_expression (dpi, options, dc))
|
||||
return;
|
||||
if (d_maybe_print_designated_init (dpi, options, dc))
|
||||
return;
|
||||
{
|
||||
struct demangle_component *op = d_left (dc);
|
||||
struct demangle_component *first = d_left (d_right (dc));
|
||||
|
@ -1456,3 +1456,12 @@ coro1::empty::operator co_await() const
|
||||
|
||||
_ZNK3FoossERKS_
|
||||
Foo::operator<=>(Foo const&) const
|
||||
|
||||
_Z1f1AIXtl1Udi1iLi0EEEE
|
||||
f(A<U{.i=(0)}>)
|
||||
|
||||
_Z1f1AIXtl1Xdi1adi1bdxLi3ELi1EEEE
|
||||
f(A<X{.a.b[3]=(1)}>)
|
||||
|
||||
_Z1f1AIXtl1Xdi1adi1bdXLi3ELi4ELi1EEEE
|
||||
f(A<X{.a.b[3 ... 4]=(1)}>)
|
||||
|
Loading…
Reference in New Issue
Block a user