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
This commit is contained in:
parent
467649eb69
commit
ea76c60a16
@ -1,5 +1,8 @@
|
|||||||
2010-09-06 Jason Merrill <jason@redhat.com>
|
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
|
* semantics.c (finish_compound_literal): Always build a
|
||||||
TARGET_EXPR.
|
TARGET_EXPR.
|
||||||
|
|
||||||
|
@ -1052,10 +1052,15 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
|
|||||||
int i, quals, flags;
|
int i, quals, flags;
|
||||||
tsubst_flags_t complain;
|
tsubst_flags_t complain;
|
||||||
const char *msg;
|
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)
|
if (spec_p)
|
||||||
*spec_p = (cxx_dialect >= cxx0x
|
*spec_p = cleanup_spec;
|
||||||
? noexcept_true_spec : empty_except_spec);
|
|
||||||
|
|
||||||
if (deleted_p)
|
if (deleted_p)
|
||||||
{
|
{
|
||||||
@ -1109,6 +1114,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ctor_p = false;
|
||||||
assign_p = false;
|
assign_p = false;
|
||||||
check_vdtor = false;
|
check_vdtor = false;
|
||||||
switch (sfk)
|
switch (sfk)
|
||||||
@ -1129,6 +1135,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
|
|||||||
case sfk_constructor:
|
case sfk_constructor:
|
||||||
case sfk_move_constructor:
|
case sfk_move_constructor:
|
||||||
case sfk_copy_constructor:
|
case sfk_copy_constructor:
|
||||||
|
ctor_p = true;
|
||||||
fnname = complete_ctor_identifier;
|
fnname = complete_ctor_identifier;
|
||||||
break;
|
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);
|
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
|
||||||
|
|
||||||
process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p,
|
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))
|
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). */
|
to have a null rval (no class-specific op delete). */
|
||||||
if (rval && rval == error_mark_node && deleted_p)
|
if (rval && rval == error_mark_node && deleted_p)
|
||||||
*deleted_p = true;
|
*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");
|
"or trivial copy constructor");
|
||||||
FOR_EACH_VEC_ELT (tree, vbases, i, base_binfo)
|
FOR_EACH_VEC_ELT (tree, vbases, i, base_binfo)
|
||||||
{
|
{
|
||||||
|
tree basetype = BINFO_TYPE (base_binfo);
|
||||||
if (copy_arg_p)
|
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);
|
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
|
||||||
|
|
||||||
process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p,
|
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)
|
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,
|
walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals,
|
||||||
copy_arg_p, move_p, assign_p, spec_p, trivial_p,
|
copy_arg_p, move_p, assign_p, spec_p, trivial_p,
|
||||||
deleted_p, msg, flags, complain);
|
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);
|
pop_scope (scope);
|
||||||
|
|
||||||
--cp_unevaluated_operand;
|
--cp_unevaluated_operand;
|
||||||
--c_inhibit_evaluation_warnings;
|
--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
|
#ifdef ENABLE_CHECKING
|
||||||
/* If we expected this to be trivial but it isn't, then either we're in
|
/* 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. */
|
C++0x mode and this is a copy/move ctor/op= or there's an error. */
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
2010-09-06 Jason Merrill <jason@redhat.com>
|
2010-09-06 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* g++.dg/cpp0x/implicit9.C: New.
|
||||||
|
|
||||||
* g++.dg/cpp0x/initlist43.C: New.
|
* g++.dg/cpp0x/initlist43.C: New.
|
||||||
|
|
||||||
2010-09-05 Giuseppe Scrivano <gscrivano@gnu.org>
|
2010-09-05 Giuseppe Scrivano <gscrivano@gnu.org>
|
||||||
|
12
gcc/testsuite/g++.dg/cpp0x/implicit9.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/implicit9.C
Normal file
@ -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" }
|
Loading…
Reference in New Issue
Block a user