aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-10-23 14:08:56 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-10-23 14:08:56 -0400
commiteca7fc5755041ad90a7db18bbd6b3294f5075da7 (patch)
tree42c2ea99646dafa555892877e4e1670084770361 /gcc/cp/init.c
parentd4c579b56109284162f084bf031cd4eea1f1b036 (diff)
downloadgcc-eca7fc5755041ad90a7db18bbd6b3294f5075da7.zip
gcc-eca7fc5755041ad90a7db18bbd6b3294f5075da7.tar.gz
gcc-eca7fc5755041ad90a7db18bbd6b3294f5075da7.tar.bz2
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
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c167
1 files changed, 96 insertions, 71 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index d18dc5e..78ea986 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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);
}
}
}