From: Jason Merrill Date: Mon, 17 Jan 2011 22:34:35 +0000 (-0500) Subject: re PR c++/47067 ([c++0x] ICE in cxx_eval_bare_aggregate, at cp/semantics.c:6352) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d79b88a1feecf5a088c51af49ea3f8fdffeafc21;p=gcc.git re PR c++/47067 ([c++0x] ICE in cxx_eval_bare_aggregate, at cp/semantics.c:6352) PR c++/47067 * semantics.c (base_field_constructor_elt): New fn. (cxx_eval_bare_aggregate): Use it. (build_data_member_initialization): Leave COMPONENT_REF for vfield inits. From-SVN: r168937 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2f858e06207..249104773f6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2011-01-17 Jason Merrill + + PR c++/47067 + * semantics.c (base_field_constructor_elt): New fn. + (cxx_eval_bare_aggregate): Use it. + (build_data_member_initialization): Leave COMPONENT_REF for + vfield inits. + 2011-01-14 Rodrigo Rivas Costa * parser.c (cp_parser_range_for): Remove the "unused variable" warning diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b9775f4b909..285b764e2c7 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5538,7 +5538,11 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec) } if (TREE_CODE (member) == ADDR_EXPR) member = TREE_OPERAND (member, 0); - if (TREE_CODE (member) == COMPONENT_REF) + if (TREE_CODE (member) == COMPONENT_REF + /* If we're initializing a member of a subaggregate, it's a vtable + pointer. Leave it as COMPONENT_REF so we remember the path to get + to the vfield. */ + && TREE_CODE (TREE_OPERAND (member, 0)) != COMPONENT_REF) member = TREE_OPERAND (member, 1); CONSTRUCTOR_APPEND_ELT (*vec, member, init); return true; @@ -6350,6 +6354,36 @@ cxx_eval_logical_expression (const constexpr_call *call, tree t, return r; } +/* REF is a COMPONENT_REF designating a particular field. V is a vector of + CONSTRUCTOR elements to initialize (part of) an object containing that + field. Return a pointer to the constructor_elt corresponding to the + initialization of the field. */ + +static constructor_elt * +base_field_constructor_elt (VEC(constructor_elt,gc) *v, tree ref) +{ + tree aggr = TREE_OPERAND (ref, 0); + tree field = TREE_OPERAND (ref, 1); + HOST_WIDE_INT i; + constructor_elt *ce; + + gcc_assert (TREE_CODE (ref) == COMPONENT_REF); + + if (TREE_CODE (aggr) == COMPONENT_REF) + { + constructor_elt *base_ce + = base_field_constructor_elt (v, aggr); + v = CONSTRUCTOR_ELTS (base_ce->value); + } + + for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) + if (ce->index == field) + return ce; + + gcc_unreachable (); + return NULL; +} + /* Subroutine of cxx_eval_constant_expression. The expression tree T denotes a C-style array or a C-style aggregate. Reduce it to a constant expression. */ @@ -6365,7 +6399,6 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t, constructor_elt *ce; HOST_WIDE_INT i; bool changed = false; - tree type = TREE_TYPE (t); gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (t)); for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) { @@ -6377,23 +6410,13 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t, goto fail; if (elt != ce->value) changed = true; - if (TREE_CODE (type) != ARRAY_TYPE - && !(same_type_ignoring_top_level_qualifiers_p - (DECL_CONTEXT (ce->index), type))) + if (TREE_CODE (ce->index) == COMPONENT_REF) { - /* Push our vtable pointer down into the base where it belongs. */ - tree vptr_base = DECL_CONTEXT (ce->index); - tree base_ctor; - gcc_assert (ce->index == TYPE_VFIELD (type)); - for (base_ctor = VEC_index (constructor_elt, n, 0)->value; ; - base_ctor = CONSTRUCTOR_ELT (base_ctor, 0)->value) - if (TREE_TYPE (base_ctor) == vptr_base) - { - constructor_elt *p = CONSTRUCTOR_ELT (base_ctor, 0); - gcc_assert (p->index == ce->index); - p->value = elt; - break; - } + /* This is an initialization of a vfield inside a base + subaggregate that we already initialized; push this + initialization into the previous initialization. */ + constructor_elt *inner = base_field_constructor_elt (n, ce->index); + inner->value = elt; } else CONSTRUCTOR_APPEND_ELT (n, ce->index, elt); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 33b7c549a3b..e12ba4c532d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-01-17 Jason Merrill + + * g++.dg/cpp0x/constexpr-virtual.C: New. + 2011-01-17 Jakub Jelinek PR fortran/47331 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C new file mode 100644 index 00000000000..448ecb1dc70 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C @@ -0,0 +1,14 @@ +// PR c++/47067 +// { dg-options -std=c++0x } + +struct X { + virtual void x(); + virtual ~X(); +}; + +struct Y { + virtual void y(); + virtual ~Y(); +}; + +struct Z: X, Y {} z;