re PR c++/69131 (default constructor of union incorrectly deleted)
authorJason Merrill <jason@redhat.com>
Mon, 11 Jan 2016 20:53:07 +0000 (15:53 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 11 Jan 2016 20:53:07 +0000 (15:53 -0500)
PR c++/69131
* method.c (walk_field_subobs): Add dtor_from_ctor parm.
(process_subob_fn): Likewise.  Don't consider triviality if true.
(synthesize_method_walk): Pass it.

From-SVN: r232243

gcc/cp/ChangeLog
gcc/cp/method.c
gcc/testsuite/g++.dg/cpp0x/union7.C [new file with mode: 0644]

index 023ed6489b0ab9c0139c67f63d2f1fbdb4be7ab6..ba7cf58552cf341f8e7d81f8d6e952aab8843c23 100644 (file)
@@ -1,3 +1,10 @@
+2016-01-11  Jason Merrill  <jason@redhat.com>
+
+       PR c++/69131
+       * method.c (walk_field_subobs): Add dtor_from_ctor parm.
+       (process_subob_fn): Likewise.  Don't consider triviality if true.
+       (synthesize_method_walk): Pass it.
+
 2016-01-11  David Malcolm  <dmalcolm@redhat.com>
 
        PR c++/68795
index bcf0a6cdee24056e5e23b7d879e8deacd6dadd2a..e358ebd1c8c0408b14ae3b0f8bfcb7952be472b5 100644 (file)
@@ -1097,7 +1097,7 @@ is_trivially_xible (enum tree_code code, tree to, tree from)
 static void
 process_subob_fn (tree fn, tree *spec_p, bool *trivial_p,
                  bool *deleted_p, bool *constexpr_p,
-                 bool diag, tree arg)
+                 bool diag, tree arg, bool dtor_from_ctor = false)
 {
   if (!fn || fn == error_mark_node)
     goto bad;
@@ -1109,7 +1109,7 @@ process_subob_fn (tree fn, tree *spec_p, bool *trivial_p,
       *spec_p = merge_exception_specifiers (*spec_p, raises);
     }
 
-  if (!trivial_fn_p (fn))
+  if (!trivial_fn_p (fn) && !dtor_from_ctor)
     {
       if (trivial_p)
        *trivial_p = false;
@@ -1142,14 +1142,17 @@ process_subob_fn (tree fn, tree *spec_p, bool *trivial_p,
 }
 
 /* Subroutine of synthesized_method_walk to allow recursion into anonymous
-   aggregates.  */
+   aggregates.  If DTOR_FROM_CTOR is true, we're walking subobject destructors
+   called from a synthesized constructor, in which case we don't consider
+   the triviality of the subobject destructor.  */
 
 static void
 walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
                   int quals, bool copy_arg_p, bool move_p,
                   bool assign_p, tree *spec_p, bool *trivial_p,
                   bool *deleted_p, bool *constexpr_p,
-                  bool diag, int flags, tsubst_flags_t complain)
+                  bool diag, int flags, tsubst_flags_t complain,
+                  bool dtor_from_ctor)
 {
   tree field;
   for (field = fields; field; field = DECL_CHAIN (field))
@@ -1268,7 +1271,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
          walk_field_subobs (TYPE_FIELDS (mem_type), fnname, sfk, quals,
                             copy_arg_p, move_p, assign_p, spec_p, trivial_p,
                             deleted_p, constexpr_p,
-                            diag, flags, complain);
+                            diag, flags, complain, dtor_from_ctor);
          continue;
        }
 
@@ -1285,7 +1288,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
       rval = locate_fn_flags (mem_type, fnname, argtype, flags, complain);
 
       process_subob_fn (rval, spec_p, trivial_p, deleted_p,
-                       constexpr_p, diag, field);
+                       constexpr_p, diag, field, dtor_from_ctor);
     }
 }
 
@@ -1468,7 +1471,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
             dtors would be a double-fault).  */
          process_subob_fn (rval, NULL, NULL,
                            deleted_p, NULL, false,
-                           basetype);
+                           basetype, /*dtor_from_ctor*/true);
        }
 
       if (check_vdtor && type_has_virtual_destructor (basetype))
@@ -1515,7 +1518,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
                                      NULL_TREE, flags, complain);
              process_subob_fn (rval, NULL, NULL,
                                deleted_p, NULL, false,
-                               basetype);
+                               basetype, /*dtor_from_ctor*/true);
            }
        }
     }
@@ -1524,13 +1527,13 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
   walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals,
                     copy_arg_p, move_p, assign_p, spec_p, trivial_p,
                     deleted_p, constexpr_p,
-                    diag, flags, complain);
+                    diag, flags, complain, /*dtor_from_ctor*/false);
   if (ctor_p)
     walk_field_subobs (TYPE_FIELDS (ctype), complete_dtor_identifier,
                       sfk_destructor, TYPE_UNQUALIFIED, false,
                       false, false, NULL, NULL,
                       deleted_p, NULL,
-                      false, flags, complain);
+                      false, flags, complain, /*dtor_from_ctor*/true);
 
   pop_scope (scope);
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/union7.C b/gcc/testsuite/g++.dg/cpp0x/union7.C
new file mode 100644 (file)
index 0000000..c42d217
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/69131
+// { dg-do compile { target c++11 } }
+
+struct X
+{
+  ~X() {}
+};
+
+union U
+{
+  X x;
+  ~U() {}
+};
+
+U u;