aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/constexpr.c11
-rw-r--r--gcc/cp/init.c48
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/desig2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/desig3.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/desig4.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/array1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/flexary29.C2
-rw-r--r--gcc/testsuite/g++.dg/init/array28.C2
10 files changed, 65 insertions, 44 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ab63ec7..53f414f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2020-02-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/86917
+ * init.c (perform_member_init): Simplify.
+ * constexpr.c (cx_check_missing_mem_inits): Allow uninitialized
+ flexarray.
+ (cxx_eval_vec_init_1): Handle CONSTRUCTOR.
+
2020-02-04 Iain Sandoe <iain@sandoe.co.uk>
* coroutines.cc (find_promise_type): Delete unused forward
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 3962763..c35ec5a 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -826,7 +826,12 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
return true;
continue;
}
- ftype = strip_array_types (TREE_TYPE (field));
+ ftype = TREE_TYPE (field);
+ if (!ftype || !TYPE_P (ftype) || !COMPLETE_TYPE_P (ftype))
+ /* A flexible array can't be intialized here, so don't complain
+ that it isn't. */
+ continue;
+ ftype = strip_array_types (ftype);
if (type_has_constexpr_default_constructor (ftype))
{
/* It's OK to skip a member with a trivial constexpr ctor.
@@ -3784,6 +3789,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
unsigned HOST_WIDE_INT i;
tsubst_flags_t complain = ctx->quiet ? tf_none : tf_warning_or_error;
+ if (init && TREE_CODE (init) == CONSTRUCTOR)
+ return cxx_eval_bare_aggregate (ctx, init, lval,
+ non_constant_p, overflow_p);
+
/* For the default constructor, build up a call to the default
constructor of the element type. We only need to handle class types
here, as for a constructor to be constexpr, all members must be
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 543d127..625062b 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -801,6 +801,17 @@ perform_member_init (tree member, tree init)
member);
}
+ if (maybe_reject_flexarray_init (member, init))
+ return;
+
+ if (init && TREE_CODE (init) == TREE_LIST
+ && (DIRECT_LIST_INIT_P (TREE_VALUE (init))
+ /* FIXME C++20 parenthesized aggregate init (PR 92812). */
+ || !(/* cxx_dialect >= cxx2a ? CP_AGGREGATE_TYPE_P (type) */
+ /* : */CLASS_TYPE_P (type))))
+ init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
+ tf_warning_or_error);
+
if (init == void_type_node)
{
/* mem() means value-initialization. */
@@ -832,12 +843,7 @@ perform_member_init (tree member, tree init)
}
else if (init
&& (TYPE_REF_P (type)
- /* Pre-digested NSDMI. */
- || (((TREE_CODE (init) == CONSTRUCTOR
- && TREE_TYPE (init) == type)
- /* { } mem-initializer. */
- || (TREE_CODE (init) == TREE_LIST
- && DIRECT_LIST_INIT_P (TREE_VALUE (init))))
+ || (TREE_CODE (init) == CONSTRUCTOR
&& (CP_AGGREGATE_TYPE_P (type)
|| is_std_init_list (type)))))
{
@@ -847,10 +853,7 @@ perform_member_init (tree member, tree init)
persists until the constructor exits." */
unsigned i; tree t;
releasing_vec cleanups;
- if (TREE_CODE (init) == TREE_LIST)
- init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
- tf_warning_or_error);
- if (TREE_TYPE (init) != type)
+ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init), type))
{
if (BRACE_ENCLOSED_INITIALIZER_P (init)
&& CP_AGGREGATE_TYPE_P (type))
@@ -876,23 +879,6 @@ perform_member_init (tree member, tree init)
{
if (TREE_CODE (type) == ARRAY_TYPE)
{
- if (init)
- {
- /* Check to make sure the member initializer is valid and
- something like a CONSTRUCTOR in: T a[] = { 1, 2 } and
- if it isn't, return early to avoid triggering another
- error below. */
- if (maybe_reject_flexarray_init (member, init))
- return;
-
- if (TREE_CODE (init) != TREE_LIST || TREE_CHAIN (init))
- init = error_mark_node;
- else
- init = TREE_VALUE (init);
-
- if (BRACE_ENCLOSED_INITIALIZER_P (init))
- init = digest_init (type, init, tf_warning_or_error);
- }
if (init == NULL_TREE
|| same_type_ignoring_top_level_qualifiers_p (type,
TREE_TYPE (init)))
@@ -962,16 +948,10 @@ perform_member_init (tree member, tree init)
/*using_new=*/false,
/*complain=*/true);
}
- else if (TREE_CODE (init) == TREE_LIST)
- /* There was an explicit member initialization. Do some work
- in that case. */
- init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
- tf_warning_or_error);
maybe_warn_list_ctor (member, init);
- /* Reject a member initializer for a flexible array member. */
- if (init && !maybe_reject_flexarray_init (member, init))
+ if (init)
finish_expr_stmt (cp_build_modify_expr (input_location, decl,
INIT_EXPR, init,
tf_warning_or_error));
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C
new file mode 100644
index 0000000..1323271
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C
@@ -0,0 +1,24 @@
+// PR c++/86917
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ constexpr A () : c (0) {}
+ static const A z;
+ unsigned c;
+};
+
+struct B
+{ // This should really be target { ! c++2a }
+ typedef A W[4]; // { dg-error "paren" "" { target *-*-* } .+1 }
+ constexpr B () : w ({ A::z, A::z, A::z, A::z }) {} // { dg-error "constant" }
+ W w;
+};
+
+struct C
+{
+ C ();
+ B w[1];
+};
+
+C::C () { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/desig2.C b/gcc/testsuite/g++.dg/cpp0x/desig2.C
index 5ac2d15..21724e0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/desig2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/desig2.C
@@ -15,9 +15,9 @@ private:
};
SomeClass::SomeClass()
- : member({
+ : member{
[INDEX1] = { .field = 0 },
[INDEX2] = { .field = 1 }
- })
+ }
{
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/desig3.C b/gcc/testsuite/g++.dg/cpp0x/desig3.C
index 0a50b74..5c27833 100644
--- a/gcc/testsuite/g++.dg/cpp0x/desig3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/desig3.C
@@ -13,9 +13,9 @@ private:
};
SomeClass::SomeClass()
- : member({
+ : member{
[INDEX1] = { .field = 0 },
[INDEX2] = { .field = 1 }
- })
+ }
{
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/desig4.C b/gcc/testsuite/g++.dg/cpp0x/desig4.C
index ff88d82..4180e09 100644
--- a/gcc/testsuite/g++.dg/cpp0x/desig4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/desig4.C
@@ -13,9 +13,9 @@ private:
};
SomeClass::SomeClass()
- : member({
+ : member{
[INDEX1] = { .field = 0 }, // { dg-error "constant expression" }
[INDEX2] = { .field = 1 } // { dg-error "constant expression" }
- })
+ }
{
}
diff --git a/gcc/testsuite/g++.dg/ext/array1.C b/gcc/testsuite/g++.dg/ext/array1.C
index 7e54dc9..f4c3630 100644
--- a/gcc/testsuite/g++.dg/ext/array1.C
+++ b/gcc/testsuite/g++.dg/ext/array1.C
@@ -3,7 +3,7 @@
class A {
public:
- A() : argc(0), argv() { };
+ A() : argc(0), argv() { }; // { dg-error "flexible array" }
private:
int argc;
char* argv[];
diff --git a/gcc/testsuite/g++.dg/ext/flexary29.C b/gcc/testsuite/g++.dg/ext/flexary29.C
index a696fd9..8fef06e 100644
--- a/gcc/testsuite/g++.dg/ext/flexary29.C
+++ b/gcc/testsuite/g++.dg/ext/flexary29.C
@@ -4,7 +4,7 @@
struct A
{
- constexpr A() : i(), x() {}
+ constexpr A() : i(), x() {} // { dg-error "flexible" }
int i;
char x[];
};
diff --git a/gcc/testsuite/g++.dg/init/array28.C b/gcc/testsuite/g++.dg/init/array28.C
index 8cf19ba..9869354 100644
--- a/gcc/testsuite/g++.dg/init/array28.C
+++ b/gcc/testsuite/g++.dg/init/array28.C
@@ -2,6 +2,6 @@
struct Foo { explicit Foo(int) { } };
struct Goo {
- Goo() : x(Foo(4), Foo(5)) { } // { dg-error "array" }
+ Goo() : x(Foo(4), Foo(5)) { } // { dg-error "" }
Foo x[2];
};