re PR c++/47067 ([c++0x] ICE in cxx_eval_bare_aggregate, at cp/semantics.c:6352)
authorJason Merrill <jason@redhat.com>
Mon, 17 Jan 2011 22:34:35 +0000 (17:34 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 17 Jan 2011 22:34:35 +0000 (17:34 -0500)
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

gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C [new file with mode: 0644]

index 2f858e062074f4edd1863f03db6e8eee30de4478..249104773f6365dafd2dda0184610606b89ffe6a 100644 (file)
@@ -1,3 +1,11 @@
+2011-01-17  Jason Merrill  <jason@redhat.com>
+
+       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 <rodrigorivascosta@gmail.com>
 
        * parser.c (cp_parser_range_for): Remove the "unused variable" warning
index b9775f4b90903ddf107c45e178c9208fd05bfa5c..285b764e2c7144764eba69055c7ce1353bc73b3e 100644 (file)
@@ -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);
index 33b7c549a3b55273fb6b1ffcc9f77ba3a89d3dc1..e12ba4c532dcdec69ef80feca1c09e99c355dae8 100644 (file)
@@ -1,3 +1,7 @@
+2011-01-17  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/constexpr-virtual.C: New.
+
 2011-01-17  Jakub Jelinek  <jakub@redhat.com>
 
        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 (file)
index 0000000..448ecb1
--- /dev/null
@@ -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;