mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 19:11:18 +08:00
c++: Fix ({ ... }) array mem-initializer.
Here, we were going down the wrong path in perform_member_init because of the incorrect parens around the mem-initializer for the array. And then cxx_eval_vec_init_1 didn't know what to do with a CONSTRUCTOR as the initializer. The latter issue was a straightforward fix, but I also wanted to fix us silently accepting the parens, which led to factoring out handling of TREE_LIST and flexarrays. The latter led to adjusting the expected behavior on flexary29.C: we should complain about the initializer, but not complain about a missing initializer. As I commented on PR 92812, in this process I noticed that we weren't handling C++20 parenthesized aggregate initialization as a mem-initializer. So my TREE_LIST handling includes a commented out section that should probably be part of a future fix for that issue; with it uncommented we continue to crash on the testcase in C++20 mode, but should instead complain about the braced-init-list not being a valid initializer for an A. 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.
This commit is contained in:
parent
c422cec54a
commit
a1c9c9ff06
gcc
cp
testsuite/g++.dg
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
24
gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C
Normal file
24
gcc/testsuite/g++.dg/cpp0x/constexpr-array23.C
Normal file
@ -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 () { }
|
@ -15,9 +15,9 @@ private:
|
||||
};
|
||||
|
||||
SomeClass::SomeClass()
|
||||
: member({
|
||||
: member{
|
||||
[INDEX1] = { .field = 0 },
|
||||
[INDEX2] = { .field = 1 }
|
||||
})
|
||||
}
|
||||
{
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ private:
|
||||
};
|
||||
|
||||
SomeClass::SomeClass()
|
||||
: member({
|
||||
: member{
|
||||
[INDEX1] = { .field = 0 },
|
||||
[INDEX2] = { .field = 1 }
|
||||
})
|
||||
}
|
||||
{
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ private:
|
||||
};
|
||||
|
||||
SomeClass::SomeClass()
|
||||
: member({
|
||||
: member{
|
||||
[INDEX1] = { .field = 0 }, // { dg-error "constant expression" }
|
||||
[INDEX2] = { .field = 1 } // { dg-error "constant expression" }
|
||||
})
|
||||
}
|
||||
{
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
class A {
|
||||
public:
|
||||
A() : argc(0), argv() { };
|
||||
A() : argc(0), argv() { }; // { dg-error "flexible array" }
|
||||
private:
|
||||
int argc;
|
||||
char* argv[];
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
struct A
|
||||
{
|
||||
constexpr A() : i(), x() {}
|
||||
constexpr A() : i(), x() {} // { dg-error "flexible" }
|
||||
int i;
|
||||
char x[];
|
||||
};
|
||||
|
@ -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];
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user