aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-09-06 00:49:07 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-09-06 00:49:07 -0400
commitea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8 (patch)
treed6d10d6ac7a5494908a3eea84837299d267cc944 /gcc
parent467649eb698b5276610f8509432eb7a5f721c5f3 (diff)
downloadgcc-ea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8.zip
gcc-ea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8.tar.gz
gcc-ea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8.tar.bz2
method.c (synthesized_method_walk): In constructors, also check subobject destructors.
* method.c (synthesized_method_walk): In constructors, also check subobject destructors. From-SVN: r163894
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/method.c49
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit9.C12
4 files changed, 61 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b2da825..357464f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,8 @@
2010-09-06 Jason Merrill <jason@redhat.com>
+ * method.c (synthesized_method_walk): In constructors, also check
+ subobject destructors.
+
* semantics.c (finish_compound_literal): Always build a
TARGET_EXPR.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 359e71d..0ec3826 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1052,10 +1052,15 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
int i, quals, flags;
tsubst_flags_t complain;
const char *msg;
+ bool ctor_p;
+ tree cleanup_spec;
+ bool cleanup_trivial = true;
+ bool cleanup_deleted = false;
+ cleanup_spec
+ = (cxx_dialect >= cxx0x ? noexcept_true_spec : empty_except_spec);
if (spec_p)
- *spec_p = (cxx_dialect >= cxx0x
- ? noexcept_true_spec : empty_except_spec);
+ *spec_p = cleanup_spec;
if (deleted_p)
{
@@ -1109,6 +1114,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
return;
#endif
+ ctor_p = false;
assign_p = false;
check_vdtor = false;
switch (sfk)
@@ -1129,6 +1135,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
case sfk_constructor:
case sfk_move_constructor:
case sfk_copy_constructor:
+ ctor_p = true;
fnname = complete_ctor_identifier;
break;
@@ -1176,7 +1183,16 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p,
- msg, BINFO_TYPE (base_binfo));
+ msg, basetype);
+ if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
+ {
+ /* In a constructor we also need to check the subobject
+ destructors for cleanup of partially constructed objects. */
+ rval = locate_fn_flags (base_binfo, complete_dtor_identifier,
+ NULL_TREE, flags, complain);
+ process_subob_fn (rval, false, &cleanup_spec, &cleanup_trivial,
+ &cleanup_deleted, NULL, basetype);
+ }
if (check_vdtor && type_has_virtual_destructor (basetype))
{
@@ -1186,6 +1202,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
to have a null rval (no class-specific op delete). */
if (rval && rval == error_mark_node && deleted_p)
*deleted_p = true;
+ check_vdtor = false;
}
}
@@ -1206,12 +1223,20 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
"or trivial copy constructor");
FOR_EACH_VEC_ELT (tree, vbases, i, base_binfo)
{
+ tree basetype = BINFO_TYPE (base_binfo);
if (copy_arg_p)
- argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, move_p);
+ argtype = build_stub_type (basetype, quals, move_p);
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p,
- msg, BINFO_TYPE (base_binfo));
+ msg, basetype);
+ if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
+ {
+ rval = locate_fn_flags (base_binfo, complete_dtor_identifier,
+ NULL_TREE, flags, complain);
+ process_subob_fn (rval, false, &cleanup_spec, &cleanup_trivial,
+ &cleanup_deleted, NULL, basetype);
+ }
}
}
if (!diag)
@@ -1225,12 +1250,26 @@ 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, msg, flags, complain);
+ if (ctor_p)
+ walk_field_subobs (TYPE_FIELDS (ctype), complete_dtor_identifier,
+ sfk_destructor, TYPE_UNQUALIFIED, false,
+ false, false, &cleanup_spec, &cleanup_trivial,
+ &cleanup_deleted, NULL, flags, complain);
pop_scope (scope);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
+ /* If the constructor isn't trivial, consider the subobject cleanups. */
+ if (ctor_p && trivial_p && !*trivial_p)
+ {
+ if (deleted_p && cleanup_deleted)
+ *deleted_p = true;
+ if (spec_p)
+ *spec_p = merge_exception_specifiers (*spec_p, cleanup_spec);
+ }
+
#ifdef ENABLE_CHECKING
/* If we expected this to be trivial but it isn't, then either we're in
C++0x mode and this is a copy/move ctor/op= or there's an error. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index eb19f0e..e723af4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,7 @@
2010-09-06 Jason Merrill <jason@redhat.com>
+ * g++.dg/cpp0x/implicit9.C: New.
+
* g++.dg/cpp0x/initlist43.C: New.
2010-09-05 Giuseppe Scrivano <gscrivano@gnu.org>
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit9.C b/gcc/testsuite/g++.dg/cpp0x/implicit9.C
new file mode 100644
index 0000000..3a6dbc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit9.C
@@ -0,0 +1,12 @@
+// Test that private base dtor makes derived ctor deleted
+// { dg-options -std=c++0x }
+
+struct A
+{
+ A();
+private:
+ ~A(); // { dg-error "private" }
+};
+
+struct B: A { }; // { dg-error "implicitly deleted|context" }
+B * b = new B; // { dg-error "deleted" }