In C++11 a trivial [cd]tor might not be callable.

* class.c (user_provided_p): A function deleted on its declation
	in the class is not user-provided.
	(type_build_ctor_call): Also force a ctor call if we
	might have a deleted or private trivial ctor.
	(type_build_dtor_call): New.
	(deduce_noexcept_on_destructors): Remove obsolete code.
	* cp-tree.h: Declare type_build_dtor_call.
	* decl.c (expand_static_init): Make sure trivial dtors are callable.
	(cxx_maybe_build_cleanup): Likewise.
	* except.c (build_throw): Likewise.
	* init.c (build_value_init): Handle trivial but not callable ctors.
	(perform_target_ctor): Make sure trivial dtor is callable.
	(perform_member_init): Likewise.
	(expand_cleanup_for_base): Likewise.
	(build_vec_delete_1): Likewise.
	(build_delete): Likewise.
	(push_base_cleanups): Likewise.
	(build_new_1): Avoid redundant error.
	* method.c (synthesized_method_walk): Can't ever exit early in C++11.
	Always process the subobject destructor.
	* semantics.c (finish_compound_literal): Make sure trivial dtor is
	callable.
	* typeck2.c (split_nonconstant_init): Likewise.

From-SVN: r203985
This commit is contained in:
Jason Merrill 2013-10-23 14:08:56 -04:00 committed by Jason Merrill
parent d4c579b561
commit eca7fc5755
24 changed files with 384 additions and 231 deletions

View File

@ -1,3 +1,30 @@
2013-10-23 Jason Merrill <jason@redhat.com>
In C++11 a trivial [cd]tor might not be callable.
* class.c (user_provided_p): A function deleted on its declation
in the class is not user-provided.
(type_build_ctor_call): Also force a ctor call if we
might have a deleted or private trivial ctor.
(type_build_dtor_call): New.
(deduce_noexcept_on_destructors): Remove obsolete code.
* cp-tree.h: Declare type_build_dtor_call.
* decl.c (expand_static_init): Make sure trivial dtors are callable.
(cxx_maybe_build_cleanup): Likewise.
* except.c (build_throw): Likewise.
* init.c (build_value_init): Handle trivial but not callable ctors.
(perform_target_ctor): Make sure trivial dtor is callable.
(perform_member_init): Likewise.
(expand_cleanup_for_base): Likewise.
(build_vec_delete_1): Likewise.
(build_delete): Likewise.
(push_base_cleanups): Likewise.
(build_new_1): Avoid redundant error.
* method.c (synthesized_method_walk): Can't ever exit early in C++11.
Always process the subobject destructor.
* semantics.c (finish_compound_literal): Make sure trivial dtor is
callable.
* typeck2.c (split_nonconstant_init): Likewise.
2013-10-23 Edward Smith-Rowland <3dw4rd@verizon.net>
Implement C++14 [[deprecated]] modulo [[gnu::deprecated]] bugs.

View File

@ -9273,6 +9273,9 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
static_aggregates = tree_cons (NULL_TREE, var,
static_aggregates);
}
else
/* Check whether the dtor is callable. */
cxx_maybe_build_cleanup (var, tf_warning_or_error);
}
*initp = init;

View File

@ -4674,15 +4674,8 @@ deduce_noexcept_on_destructors (tree t)
if (!CLASSTYPE_METHOD_VEC (t))
return;
bool saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
/* Avoid early exit from synthesized_method_walk (c++/57645). */
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true;
for (tree fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
deduce_noexcept_on_destructor (OVL_CURRENT (fns));
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = saved_nontrivial_dtor;
}
/* Subroutine of set_one_vmethod_tm_attributes. Search base classes
@ -4884,7 +4877,8 @@ user_provided_p (tree fn)
return true;
else
return (!DECL_ARTIFICIAL (fn)
&& !DECL_DEFAULTED_IN_CLASS_P (fn));
&& !(DECL_INITIALIZED_IN_CLASS_P (fn)
&& (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn))));
}
/* Returns true iff class T has a user-provided constructor. */
@ -5149,7 +5143,7 @@ type_has_user_declared_move_assign (tree t)
}
/* Nonzero if we need to build up a constructor call when initializing an
object of this class, either because it has a user-provided constructor
object of this class, either because it has a user-declared constructor
or because it doesn't have a default constructor (so we need to give an
error if no initializer is provided). Use TYPE_NEEDS_CONSTRUCTING when
what you care about is whether or not an object can be produced by a
@ -5165,8 +5159,46 @@ type_build_ctor_call (tree t)
if (TYPE_NEEDS_CONSTRUCTING (t))
return true;
inner = strip_array_types (t);
return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)
&& !ANON_AGGR_TYPE_P (inner));
if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner))
return false;
if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (inner))
return true;
/* A user-declared constructor might be private, and a constructor might
be trivial but deleted. */
for (tree fns = lookup_fnfields_slot (inner, complete_ctor_identifier);
fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (!DECL_ARTIFICIAL (fn)
|| DECL_DELETED_FN (fn))
return true;
}
return false;
}
/* Like type_build_ctor_call, but for destructors. */
bool
type_build_dtor_call (tree t)
{
tree inner;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
return true;
inner = strip_array_types (t);
if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner)
|| !COMPLETE_TYPE_P (inner))
return false;
/* A user-declared destructor might be private, and a destructor might
be trivial but deleted. */
for (tree fns = lookup_fnfields_slot (inner, complete_dtor_identifier);
fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (!DECL_ARTIFICIAL (fn)
|| DECL_DELETED_FN (fn))
return true;
}
return false;
}
/* Remove all zero-width bit-fields from T. */

View File

@ -5115,6 +5115,7 @@ extern bool type_has_move_assign (tree);
extern bool type_has_user_declared_move_constructor (tree);
extern bool type_has_user_declared_move_assign(tree);
extern bool type_build_ctor_call (tree);
extern bool type_build_dtor_call (tree);
extern void explain_non_literal_class (tree);
extern void defaulted_late_check (tree);
extern bool defaultable_fn_check (tree);

View File

@ -6897,7 +6897,11 @@ expand_static_init (tree decl, tree init)
/* Some variables require no dynamic initialization. */
if (!init
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
{
/* Make sure the destructor is callable. */
cxx_maybe_build_cleanup (decl, tf_warning_or_error);
return;
}
if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
&& !DECL_FUNCTION_SCOPE_P (decl))
@ -14296,7 +14300,7 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
if (type_build_dtor_call (type))
{
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
@ -14317,6 +14321,8 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
sfk_complete_destructor, flags, 0, complain);
if (call == error_mark_node)
cleanup = error_mark_node;
else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
/* Discard the call. */;
else if (cleanup)
cleanup = cp_build_compound_expr (cleanup, call, complain);
else

View File

@ -868,17 +868,21 @@ build_throw (tree exp)
throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
cleanup = NULL_TREE;
if (type_build_dtor_call (TREE_TYPE (object)))
{
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
tree fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0);
cleanup = BASELINK_FUNCTIONS (cleanup);
mark_used (cleanup);
cxx_mark_addressable (cleanup);
/* Pretend it's a normal function. */
cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
fn = BASELINK_FUNCTIONS (fn);
mark_used (fn);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
{
cxx_mark_addressable (fn);
/* Pretend it's a normal function. */
cleanup = build1 (ADDR_EXPR, cleanup_type, fn);
}
}
else
if (cleanup == NULL_TREE)
cleanup = build_int_cst (cleanup_type, 0);
/* ??? Indicate that this function call throws throw_type. */

View File

@ -312,60 +312,55 @@ build_value_init (tree type, tsubst_flags_t complain)
To value-initialize an object of type T means:
- if T is a class type (clause 9) with a user-provided constructor
(12.1), then the default constructor for T is called (and the
initialization is ill-formed if T has no accessible default
constructor);
- if T is a class type (clause 9) with either no default constructor
(12.1) or a default constructor that is user-provided or deleted,
then then the object is default-initialized;
- if T is a non-union class type without a user-provided constructor,
then every non-static data member and base-class component of T is
value-initialized;92)
- if T is a (possibly cv-qualified) class type without a user-provided
or deleted default constructor, then the object is zero-initialized
and the semantic constraints for default-initialization are checked,
and if T has a non-trivial default constructor, the object is
default-initialized;
- if T is an array type, then each element is value-initialized;
- otherwise, the object is zero-initialized.
A program that calls for default-initialization or
value-initialization of an entity of reference type is ill-formed.
92) Value-initialization for such a class object may be implemented by
zero-initializing the object and then calling the default
constructor. */
value-initialization of an entity of reference type is ill-formed. */
/* The AGGR_INIT_EXPR tweaking below breaks in templates. */
gcc_assert (!processing_template_decl
|| (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE));
if (CLASS_TYPE_P (type))
if (type_build_ctor_call (type))
{
/* Instead of the above, only consider the user-providedness of the
default constructor itself so value-initializing a class with an
explicitly defaulted default constructor and another user-provided
constructor works properly (c++std-core-19883). */
if (type_has_user_provided_default_constructor (type)
|| (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
&& type_has_user_provided_constructor (type)))
return build_aggr_init_expr
(type,
build_special_member_call (NULL_TREE, complete_ctor_identifier,
NULL, type, LOOKUP_NORMAL,
complain));
tree ctor = build_aggr_init_expr
(type,
build_special_member_call (NULL_TREE, complete_ctor_identifier,
NULL, type, LOOKUP_NORMAL,
complain));
if (ctor == error_mark_node
|| type_has_user_provided_default_constructor (type))
return ctor;
else if (TYPE_HAS_COMPLEX_DFLT (type))
{
/* This is a class that needs constructing, but doesn't have
a user-provided constructor. So we need to zero-initialize
the object and then call the implicitly defined ctor.
This will be handled in simplify_aggr_init_expr. */
tree ctor = build_special_member_call
(NULL_TREE, complete_ctor_identifier,
NULL, type, LOOKUP_NORMAL, complain);
ctor = build_aggr_init_expr (type, ctor);
if (ctor != error_mark_node)
AGGR_INIT_ZERO_FIRST (ctor) = 1;
AGGR_INIT_ZERO_FIRST (ctor) = 1;
return ctor;
}
}
return build_value_init_noctor (type, complain);
/* Discard any access checking during subobject initialization;
the checks are implied by the call to the ctor which we have
verified is OK (cpp0x/defaulted46.C). */
push_deferring_access_checks (dk_deferred);
tree r = build_value_init_noctor (type, complain);
pop_deferring_access_checks ();
return r;
}
/* Like build_value_init, but don't call the constructor for TYPE. Used
@ -503,14 +498,15 @@ perform_target_ctor (tree init)
finish_expr_stmt (build_aggr_init (decl, init,
LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS,
tf_warning_or_error));
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
if (type_build_dtor_call (type))
{
tree expr = build_delete (type, decl, sfk_complete_destructor,
LOOKUP_NORMAL
|LOOKUP_NONVIRTUAL
|LOOKUP_DESTRUCTOR,
0, tf_warning_or_error);
if (expr != error_mark_node)
if (expr != error_mark_node
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
finish_eh_cleanup (expr);
}
}
@ -732,7 +728,7 @@ perform_member_init (tree member, tree init)
tf_warning_or_error));
}
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
if (type_build_dtor_call (type))
{
tree expr;
@ -744,7 +740,8 @@ perform_member_init (tree member, tree init)
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
tf_warning_or_error);
if (expr != error_mark_node)
if (expr != error_mark_node
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
finish_eh_cleanup (expr);
}
}
@ -1192,7 +1189,7 @@ expand_cleanup_for_base (tree binfo, tree flag)
{
tree expr;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
if (!type_build_dtor_call (BINFO_TYPE (binfo)))
return;
/* Call the destructor. */
@ -1202,6 +1199,10 @@ expand_cleanup_for_base (tree binfo, tree flag)
binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
return;
if (flag)
expr = fold_build3_loc (input_location,
COND_EXPR, void_type_node,
@ -2360,7 +2361,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
is_initialized = (type_build_ctor_call (elt_type) || *init != NULL);
if (*init == NULL)
if (*init == NULL && cxx_dialect < cxx11)
{
bool maybe_uninitialized_error = false;
/* A program that calls for default-initialization [...] of an
@ -3152,8 +3153,21 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
size_exp = size_in_bytes (type);
if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
if (! MAYBE_CLASS_TYPE_P (type))
goto no_destructor;
else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
{
/* Make sure the destructor is callable. */
if (type_build_dtor_call (type))
{
tmp = build_delete (ptype, base, sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
complain);
if (tmp == error_mark_node)
return error_mark_node;
}
goto no_destructor;
}
/* The below is short by the cookie size. */
virtual_size = size_binop (MULT_EXPR, size_exp,
@ -3829,7 +3843,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags,
flags. See cp-tree.h for more info. */
tree
build_delete (tree type, tree addr, special_function_kind auto_delete,
build_delete (tree otype, tree addr, special_function_kind auto_delete,
int flags, int use_global_delete, tsubst_flags_t complain)
{
tree expr;
@ -3837,22 +3851,33 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
if (addr == error_mark_node)
return error_mark_node;
tree type = TYPE_MAIN_VARIANT (otype);
/* Can happen when CURRENT_EXCEPTION_OBJECT gets its type
set to `error_mark_node' before it gets properly cleaned up. */
if (type == error_mark_node)
return error_mark_node;
type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) == POINTER_TYPE)
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
addr = mark_rvalue_use (addr);
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (type) == NULL_TREE)
{
if (complain & tf_error)
error ("unknown array size in delete");
return error_mark_node;
}
return build_vec_delete (addr, array_type_nelts (type),
auto_delete, use_global_delete, complain);
}
if (TYPE_PTR_P (type))
if (TYPE_PTR_P (otype))
{
bool complete_p = true;
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
if (TREE_CODE (type) == ARRAY_TYPE)
goto handle_array;
addr = mark_rvalue_use (addr);
/* We don't want to warn about delete of void*, only other
incomplete types. Deleting other incomplete types
@ -3908,19 +3933,6 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
/* Throw away const and volatile on target type of addr. */
addr = convert_force (build_pointer_type (type), addr, 0, complain);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
handle_array:
if (TYPE_DOMAIN (type) == NULL_TREE)
{
if (complain & tf_error)
error ("unknown array size in delete");
return error_mark_node;
}
return build_vec_delete (addr, array_type_nelts (type),
auto_delete, use_global_delete, complain);
}
else
{
/* Don't check PROTECT here; leave that decision to the
@ -3935,10 +3947,18 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
addr = convert_force (build_pointer_type (type), addr, 0, complain);
}
gcc_assert (MAYBE_CLASS_TYPE_P (type));
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
{
/* Make sure the destructor is callable. */
if (type_build_dtor_call (type))
{
expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
complain),
sfk_complete_destructor, flags, complain);
if (expr == error_mark_node)
return error_mark_node;
}
if (auto_delete != sfk_deleting_destructor)
return void_zero_node;
@ -4062,7 +4082,7 @@ push_base_cleanups (void)
for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
vec_safe_iterate (vbases, i, &base_binfo); i++)
{
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
if (type_build_dtor_call (BINFO_TYPE (base_binfo)))
{
expr = build_special_member_call (current_class_ref,
base_dtor_identifier,
@ -4070,10 +4090,13 @@ push_base_cleanups (void)
base_binfo,
(LOOKUP_NORMAL
| LOOKUP_NONVIRTUAL),
tf_warning_or_error);
expr = build3 (COND_EXPR, void_type_node, cond,
expr, void_zero_node);
finish_decl_cleanup (NULL_TREE, expr);
tf_warning_or_error);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
expr = build3 (COND_EXPR, void_type_node, cond,
expr, void_zero_node);
finish_decl_cleanup (NULL_TREE, expr);
}
}
}
}
@ -4082,8 +4105,8 @@ push_base_cleanups (void)
for (binfo = TYPE_BINFO (current_class_type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
|| BINFO_VIRTUAL_P (base_binfo))
if (BINFO_VIRTUAL_P (base_binfo)
|| !type_build_dtor_call (BINFO_TYPE (base_binfo)))
continue;
expr = build_special_member_call (current_class_ref,
@ -4091,7 +4114,8 @@ push_base_cleanups (void)
NULL, base_binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
finish_decl_cleanup (NULL_TREE, expr);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
finish_decl_cleanup (NULL_TREE, expr);
}
/* Don't automatically destroy union members. */
@ -4108,7 +4132,7 @@ push_base_cleanups (void)
continue;
if (ANON_UNION_TYPE_P (this_type))
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
if (type_build_dtor_call (this_type))
{
tree this_member = (build_class_member_access_expr
(current_class_ref, member,
@ -4119,7 +4143,8 @@ push_base_cleanups (void)
sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
0, tf_warning_or_error);
finish_decl_cleanup (NULL_TREE, expr);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
finish_decl_cleanup (NULL_TREE, expr);
}
}
}

View File

@ -1265,8 +1265,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
class versions and other properties of the type. But a subobject
class can be trivially copyable and yet have overload resolution
choose a template constructor for initialization, depending on
rvalueness and cv-quals. So we can't exit early for copy/move
methods in C++0x. The same considerations apply in C++98/03, but
rvalueness and cv-quals. And furthermore, a member in a base might
be trivial but deleted or otherwise not callable. So we can't exit
early in C++0x. The same considerations apply in C++98/03, but
there the definition of triviality does not consider overload
resolution, so a constructor can be trivial even if it would otherwise
call a non-trivial constructor. */
@ -1282,7 +1283,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
inform (input_location, "defaulted default constructor does "
"not initialize any non-static data member");
}
if (!diag)
if (!diag && cxx_dialect < cxx11)
return;
}
@ -1323,7 +1324,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
process_subob_fn (rval, spec_p, trivial_p, deleted_p,
constexpr_p, diag, basetype);
if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
if (ctor_p)
{
/* In a constructor we also need to check the subobject
destructors for cleanup of partially constructed objects. */

View File

@ -2521,6 +2521,10 @@ finish_compound_literal (tree type, tree compound_literal,
decl = pushdecl_top_level (decl);
DECL_NAME (decl) = make_anon_name ();
SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
/* Make sure the destructor is callable. */
tree clean = cxx_maybe_build_cleanup (decl, complain);
if (clean == error_mark_node)
return error_mark_node;
return decl;
}
else

View File

@ -640,12 +640,13 @@ split_nonconstant_init_1 (tree dest, tree init)
code = build_stmt (input_location, EXPR_STMT, code);
code = maybe_cleanup_point_expr_void (code);
add_stmt (code);
if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
if (type_build_dtor_call (inner_type))
{
code = (build_special_member_call
(sub, complete_dtor_identifier, NULL, inner_type,
LOOKUP_NORMAL, tf_warning_or_error));
finish_eh_cleanup (code);
if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
finish_eh_cleanup (code);
}
num_split_elts++;

View File

@ -1,5 +1,6 @@
// We allocate a cookie to help us run the destructor even if it's deleted.
// { dg-options -std=c++11 }
// We don't allocate a cookie to help us run the destructor if it's trivial,
// even if it's deleted.
// { dg-options "-std=c++11" }
// { dg-do run }
struct A
@ -17,5 +18,5 @@ void *operator new[](__SIZE_TYPE__ t)
int main()
{
A* ap = new A[5];
return ap == p;
return ap != p;
}

View File

@ -0,0 +1,24 @@
// We allocate a cookie to help us run the destructor if it's non-trivial,
// even if it's deleted.
// { dg-options "-std=c++0x" }
// { dg-do run }
struct B { ~B() {} };
struct A
{
B b;
~A() = delete;
};
void *p = 0;
void *operator new[](__SIZE_TYPE__ t)
{
p = ::operator new (t);
return p;
}
int main()
{
A* ap = new A[5];
return ap == p;
}

View File

@ -62,7 +62,7 @@ int main()
{
F f;
F f2(f); // { dg-error "use" }
B* b = new const B; // { dg-error "uninitialized const" }
const B* b = new const B; // { dg-error "uninitialized const" }
U u; // { dg-error "deleted" }
}

View File

@ -0,0 +1,17 @@
// { dg-require-effective-target c++11 }
struct A
{
protected:
A() = default;
int i;
};
struct B: A {
B() = default;
};
int main()
{
B();
}

View File

@ -12,6 +12,6 @@ struct B: A { }; // { dg-error "deleted" }
extern B eb;
int main()
{
B* b1 = new B; // { dg-error "use of deleted function" "" { xfail *-*-* } }
B* b1 = new B; // { dg-error "use of deleted function" }
B* b2 = new B(eb); // { dg-error "use of deleted function" }
}

View File

@ -9,6 +9,10 @@ char f(int);
template<class>
char (&f(...))[2];
struct ND { ND() = delete; };
struct ND {
// Make ND() non-aggregate.
virtual void f();
ND() = delete;
};
static_assert(sizeof(f<ND[1]>(0)) != 1, "Error");

View File

@ -1,5 +1,5 @@
// PR c++/14401
struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
struct { struct { int& i ; } bar ; } foo ; // { dg-error "deleted|uninitialized" "uninit" }
// { dg-warning "anonymous" "anon" { target c++98 } 3 }
// { dg-message "should be initialized" "ref-uninit" { target *-*-* } 3 }
// { dg-message "should be initialized" "ref-uninit" { target c++98 } 3 }

View File

@ -1,9 +1,10 @@
// PR c++/29039
typedef struct S {
typedef struct S { // { dg-error "reference" "" { target c++11 } }
int &r;
}; // { dg-warning "'typedef' was ignored" }
S f () {
return S (); // { dg-error "reference" }
return S (); // { dg-error "reference|deleted" }
}

View File

@ -1,51 +1,51 @@
// PR c++/25811
// { dg-do compile }
struct A1
struct A1 // { dg-error "uninitialized" "" { target c++11 } }
{
int const j; // { dg-message "should be initialized" }
int const j; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A2
struct A2 // { dg-error "uninitialized" "" { target c++11 } }
{
int const volatile i; // { dg-message "should be initialized" }
int const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A3
struct A3 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A4
struct A4 // { dg-error "uninitialized" "" { target c++11 } }
{
int const& ref; // { dg-message "should be initialized" }
int const& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A5
struct A5 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S1
template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } }
{
T const i; // { dg-message "should be initialized" }
T const i; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S2
template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } }
{
T const volatile i; // { dg-message "should be initialized" }
T const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S3
template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } }
{
T& ref; // { dg-message "should be initialized" }
T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S4
template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } }
{
T const i; // { dg-message "should be initialized" }
T& ref; // { dg-message "should be initialized" }
T const i; // { dg-message "should be initialized" "" { target c++98 } }
T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct X
@ -55,44 +55,44 @@ struct X
int const& r;
};
struct Y11
struct Y11 // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Y1
struct Y1 // { dg-error "deleted" "" { target c++11 } }
{
Y11 a[1];
};
struct Y22
struct Y22 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Y2
struct Y2 // { dg-error "deleted" "" { target c++11 } }
{
Y22 a[1];
};
struct Z1
struct Z1 // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z2
struct Z2 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z3
struct Z3 // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z4
struct Z4 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z5
@ -100,7 +100,7 @@ struct Z5
int i;
};
struct Z
struct Z // { dg-error "deleted" "" { target c++11 } }
{
Z1 z1;
Z2 z2;
@ -109,54 +109,54 @@ struct Z
Z5 z5;
};
union U
union U // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
void f1 ()
{
new A1; // { dg-error "uninitialized const member" }
new A1; // { dg-error "deleted|uninitialized const member" }
}
void f2 ()
{
new A2; // { dg-error "uninitialized const member" }
new A2; // { dg-error "deleted|uninitialized const member" }
}
void f3 ()
{
new A3; // { dg-error "uninitialized reference member" }
new A3; // { dg-error "deleted|uninitialized reference member" }
}
void f4 ()
{
new A4; // { dg-error "uninitialized reference member" }
new A4; // { dg-error "deleted|uninitialized reference member" }
}
void f5 ()
{
new A5; // { dg-error "uninitialized reference member|uninitialized const member" }
new A5; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
}
void f6 ()
{
new S1<int>; // { dg-error "uninitialized const member" }
new S1<int>; // { dg-error "deleted|uninitialized const member" }
}
void f7 ()
{
new S2<int>; // { dg-error "uninitialized const member" }
new S2<int>; // { dg-error "deleted|uninitialized const member" }
}
void f8 ()
{
new S3<int>; // { dg-error "uninitialized reference member" }
new S3<int>; // { dg-error "deleted|uninitialized reference member" }
}
void f9 ()
{
new S4<int>; // { dg-error "uninitialized reference member|uninitialized const member" }
new S4<int>; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
}
void f10 ()
@ -166,30 +166,30 @@ void f10 ()
void f11 ()
{
new A1[1]; // { dg-error "uninitialized const member" }
new A1[1]; // { dg-error "deleted|uninitialized const member" }
}
void f12 ()
{
new A3[1]; // { dg-error "uninitialized reference member" }
new A3[1]; // { dg-error "deleted|uninitialized reference member" }
}
void f13 ()
{
new Y1; // { dg-error "uninitialized const member" }
new Y1; // { dg-error "deleted|uninitialized const member" }
}
void f14 ()
{
new Y2; // { dg-error "uninitialized reference member" }
new Y2; // { dg-error "deleted|uninitialized reference member" }
}
void f15 ()
{
new Z; // { dg-error "uninitialized reference member|uninitialized const member" }
new Z; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
}
void f16 ()
{
new U; // { dg-error "uninitialized const member" }
new U; // { dg-error "deleted|uninitialized const member" }
}

View File

@ -1,27 +1,27 @@
// PR c++/29043
// { dg-do compile }
struct S
struct S // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
class C
{
public:
C() {} // { dg-error "uninitialized const member" }
C() {} // { dg-error "uninitialized const member|deleted" }
S s;
};
struct S2
struct S2 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
class C2
{
public:
C2() {} // { dg-error "uninitialized reference member" }
C2() {} // { dg-error "uninitialized reference member|deleted" }
S2 s;
};
@ -33,14 +33,14 @@ class C3
};
};
struct S4
struct S4 // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct C4
{
C4() {} // { dg-error "uninitialized const member" }
C4() {} // { dg-error "uninitialized const member|deleted" }
S4 s4[ 1 ];
};

View File

@ -1,51 +1,51 @@
// PR c++/43719
// { dg-do compile }
struct A1
struct A1 // { dg-error "uninitialized" "" { target c++11 } }
{
int const j; // { dg-message "should be initialized" }
int const j; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A2
struct A2 // { dg-error "uninitialized" "" { target c++11 } }
{
int const volatile i; // { dg-message "should be initialized" }
int const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A3
struct A3 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A4
struct A4 // { dg-error "uninitialized" "" { target c++11 } }
{
int const& ref; // { dg-message "should be initialized" }
int const& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct A5
struct A5 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S1
template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } }
{
T const i; // { dg-message "should be initialized" }
T const i; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S2
template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } }
{
T const volatile i; // { dg-message "should be initialized" }
T const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S3
template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } }
{
T& ref; // { dg-message "should be initialized" }
T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
template <class T> struct S4
template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } }
{
T const i; // { dg-message "should be initialized" }
T& ref; // { dg-message "should be initialized" }
T const i; // { dg-message "should be initialized" "" { target c++98 } }
T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct X
@ -55,44 +55,44 @@ struct X
int const& r;
};
struct Y11
struct Y11 // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Y1
struct Y1 // { dg-error "deleted" "" { target c++11 } }
{
Y11 a[1];
};
struct Y22
struct Y22 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Y2
struct Y2 // { dg-error "deleted" "" { target c++11 } }
{
Y22 a[1];
};
struct Z1
struct Z1 // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z2
struct Z2 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z3
struct Z3 // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z4
struct Z4 // { dg-error "uninitialized" "" { target c++11 } }
{
int& ref; // { dg-message "should be initialized" }
int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z5
@ -100,7 +100,7 @@ struct Z5
int i;
};
struct Z
struct Z // { dg-error "deleted" "" { target c++11 } }
{
Z1 z1;
Z2 z2;
@ -109,55 +109,55 @@ struct Z
Z5 z5;
};
union U
union U // { dg-error "uninitialized" "" { target c++11 } }
{
int const i; // { dg-message "should be initialized" }
int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
void f1 ()
{
A1 a1; // { dg-error "uninitialized const member" }
A1 a1; // { dg-error "uninitialized const member|deleted" }
}
void f2 ()
{
A2 a2; // { dg-error "uninitialized const member" }
A2 a2; // { dg-error "uninitialized const member|deleted" }
}
void f3 ()
{
A3 a3; // { dg-error "uninitialized reference member" }
A3 a3; // { dg-error "uninitialized reference member|deleted" }
}
void f4 ()
{
A4 a4; // { dg-error "uninitialized reference member" }
A4 a4; // { dg-error "uninitialized reference member|deleted" }
}
void f5 ()
{
A5 a5; // { dg-error "uninitialized reference member|uninitialized const member" }
A5 a5; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
}
void f6 ()
{
S1<int> s; // { dg-error "uninitialized const member" }
S1<int> s; // { dg-error "uninitialized const member|deleted" }
}
void f7 ()
{
S2<int> s; // { dg-error "uninitialized const member" }
S2<int> s; // { dg-error "uninitialized const member|deleted" }
}
void f8 ()
{
S3<int> s; // { dg-error "uninitialized reference member" }
S3<int> s; // { dg-error "uninitialized reference member|deleted" }
}
void f9 ()
{
S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member" }
S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
}
void f10 ()
@ -167,31 +167,31 @@ void f10 ()
void f11 ()
{
A1 a[ 1 ]; // { dg-error "uninitialized const member" }
A1 a[ 1 ]; // { dg-error "uninitialized const member|deleted" }
}
void f12 ()
{
A3 a[ 1 ]; // { dg-error "uninitialized reference member" }
A3 a[ 1 ]; // { dg-error "uninitialized reference member|deleted" }
}
void f13 ()
{
Y1 y1; // { dg-error "uninitialized const member" }
Y1 y1; // { dg-error "uninitialized const member|deleted" }
}
void f14 ()
{
Y2 y2; // { dg-error "uninitialized reference member" }
Y2 y2; // { dg-error "uninitialized reference member|deleted" }
}
void f15 ()
{
Z z; // { dg-error "uninitialized reference member|uninitialized const member" }
Z z; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
}
void f16 ()
{
U u; // { dg-error "uninitialized const member" }
U u; // { dg-error "uninitialized const member|deleted" }
}

View File

@ -1,15 +1,15 @@
// PR c++/44086
// { dg-do compile }
struct A
struct A // { dg-error "uninitialized" "" { target c++11 } }
{
int const i : 2; // { dg-message "should be initialized" }
int const i : 2; // { dg-message "should be initialized" "" { target c++98 } }
};
void f()
{
A a; // { dg-error "uninitialized const" }
new A; // { dg-error "uninitialized const" }
A();
new A();
A a; // { dg-error "deleted|uninitialized const" }
new A; // { dg-error "deleted|uninitialized const" }
A(); // { dg-error "deleted" "" { target c++11 } }
new A(); // { dg-error "deleted" "" { target c++11 } }
}

View File

@ -1,4 +1,6 @@
// PR c++/33459
// { dg-prune-output "uninitialized" }
// { dg-prune-output "deleted" }
union A
{

View File

@ -1,12 +1,12 @@
// PR c++/58126
struct A {
struct A { // { dg-error "uninitialized" "" { target c++11 } }
const int value1;
int& value2;
};
struct B : A { };
struct B : A { }; // { dg-error "deleted" "" { target c++11 } }
A a; // { dg-error "uninitialized const member in 'struct A'|uninitialized reference member in 'struct A'" }
A a; // { dg-error "deleted|uninitialized const member in 'struct A'|uninitialized reference member in 'struct A'" }
B b; // { dg-error "uninitialized const member in base 'struct A' of 'struct B'|uninitialized reference member in base 'struct A' of 'struct B'" }
B b; // { dg-error "deleted|uninitialized const member in base 'struct A' of 'struct B'|uninitialized reference member in base 'struct A' of 'struct B'" }