diff options
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 11 | ||||
-rw-r--r-- | gcc/cp/init.c | 48 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/desig2.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/desig3.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/desig4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/array1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/flexary29.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/array28.C | 2 |
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]; }; |