aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-07-04 05:45:01 -0400
committerJason Merrill <jason@redhat.com>2020-07-10 08:36:50 -0400
commit6324c52bba490baa17b6001a6d555ff8bef939d6 (patch)
tree9ecdc93a57d1647235f79b7ae07f94e49f455aa8 /gcc
parent50f071d999374b6dd13149a31f505d4457c9de6d (diff)
downloadgcc-6324c52bba490baa17b6001a6d555ff8bef939d6.zip
gcc-6324c52bba490baa17b6001a6d555ff8bef939d6.tar.gz
gcc-6324c52bba490baa17b6001a6d555ff8bef939d6.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/mangle.c11
-rw-r--r--gcc/cp/tree.c7
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class-union1.C25
3 files changed, 34 insertions, 9 deletions
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 090fb52..ab2d8ec 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9effd27..1fcba55 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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)
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class-union1.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class-union1.C
new file mode 100644
index 0000000..038d46f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class-union1.C
@@ -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)>) { }