diff mbox

[C++] for PR72457

Message ID CADzB+2kc0_qUtTWEobXxrpronRCwKaserRwf5kFz-B+z84CJMQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill July 29, 2016, 1:56 p.m. UTC
On Thu, Jul 28, 2016 at 2:56 AM, Markus Trippelsdorf
<markus@trippelsdorf.de> wrote:
> On 2016.07.27 at 17:21 -0400, Jason Merrill wrote:
>> On Wed, Jul 27, 2016 at 2:50 AM, Markus Trippelsdorf
>> <markus@trippelsdorf.de> wrote:
>> > On 2016.07.23 at 22:55 -0400, Jason Merrill wrote:
>> >> Using build_value_init in a base initialization is wrong, because it
>> >> calls the complete object constructor and misses protected access.  So
>> >> let's handle list-value-initialization in expand_aggr_init_1.
>> >>
>> >> Tested x86_64-pc-linux-gnu, applying to trunk.
>> >
>> > This patch causes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72457.
>> > And because it was backported, the gcc-6 branch is also affected.
>> >
>> > The following fix was tested on ppc64le. OK for trunk and gcc-6?
>> >
>> > (Unfortunately the reduced testcase is much too big.)
>> >
>> >          PR c++/72457
>> >          *constexpr.c (cx_check_missing_mem_inits): Handle potential
>> >          NULL_TREE.
>> >
>> > diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
>> > index 6bcb41ae8254..83fd9a4896ac 100644
>> > --- a/gcc/cp/constexpr.c
>> > +++ b/gcc/cp/constexpr.c
>> > @@ -734,7 +734,7 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
>> >               || DECL_ARTIFICIAL (index))
>> >             continue;
>> >         }
>> > -      for (; field != index; field = DECL_CHAIN (field))
>> > +      for (; field != NULL_TREE && field != index; field = DECL_CHAIN (field))
>>
>> This is wrong; it ends up just skipping over the rest of the fields,
>> so we don't check whether they were initialized.  Rather, we need to
>> handle seeing two initializers in a row for the same field.
>
> OK. I will let you handle this issue.

This patch fixes the issue in two ways:
1) Avoid adding multiple initializers for the same field when it's
initialized twice.
2) Limiting the earlier change to base initialization.

Tested x86_64-pc-linux-gnu, applying to trunk and 6.
commit 41bc8ce29bc87e0a1a21cefe4bf9ed41f781d484
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jul 28 17:41:44 2016 -0400

    	PR c++/72457 - ICE with list-value-initialized base.
    
    	* init.c (expand_aggr_init_1): Only handle value-init of bases.
    	* constexpr.c (build_data_member_initialization): Handle multiple
    	initializers for the same field.
diff mbox

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 6bcb41a..5871689 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -391,7 +391,12 @@  build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
 	gcc_assert (TREE_TYPE (member) == vtbl_ptr_type_node);
     }
 
-  CONSTRUCTOR_APPEND_ELT (*vec, member, init);
+  /* Value-initialization can produce multiple initializers for the
+     same field; use the last one.  */
+  if (!vec_safe_is_empty (*vec) && (*vec)->last().index == member)
+    (*vec)->last().value = init;
+  else
+    CONSTRUCTOR_APPEND_ELT (*vec, member, init);
   return true;
 }
 
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6362263..1a5766a 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1818,9 +1818,9 @@  expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
     }
 
   /* List-initialization from {} becomes value-initialization for non-aggregate
-     classes with default constructors.  Handle this here so protected access
-     works.  */
-  if (init && TREE_CODE (init) == TREE_LIST)
+     classes with default constructors.  Handle this here when we're
+     initializing a base, so protected access works.  */
+  if (exp != true_exp && init && TREE_CODE (init) == TREE_LIST)
     {
       tree elt = TREE_VALUE (init);
       if (DIRECT_LIST_INIT_P (elt)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-list1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-list1.C
new file mode 100644
index 0000000..f831a11
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-list1.C
@@ -0,0 +1,15 @@ 
+// PR c++/72457
+// { dg-do compile { target c++11 } }
+
+struct A {
+  int i;
+  constexpr A(): i(0) {}
+};
+
+struct B: A { };
+
+struct C
+{
+  B b;
+  constexpr C() : b{} {}
+};