diff options
author | Jason Merrill <jason@redhat.com> | 2013-10-23 14:08:56 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-10-23 14:08:56 -0400 |
commit | eca7fc5755041ad90a7db18bbd6b3294f5075da7 (patch) | |
tree | 42c2ea99646dafa555892877e4e1670084770361 /gcc | |
parent | d4c579b56109284162f084bf031cd4eea1f1b036 (diff) | |
download | gcc-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')
-rw-r--r-- | gcc/cp/ChangeLog | 27 | ||||
-rw-r--r-- | gcc/cp/call.c | 3 | ||||
-rw-r--r-- | gcc/cp/class.c | 54 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 10 | ||||
-rw-r--r-- | gcc/cp/except.c | 20 | ||||
-rw-r--r-- | gcc/cp/init.c | 167 | ||||
-rw-r--r-- | gcc/cp/method.c | 9 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/defaulted19.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/defaulted19a.C | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/defaulted2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/defaulted46.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/implicit11.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/sfinae21.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/anon-struct4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/ctor8.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/pr25811.C | 104 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/pr29043.C | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/pr43719.C | 104 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/pr44086.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/ref14.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/uninitialized1.C | 8 |
24 files changed, 384 insertions, 231 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c17e19d..99269af 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 3ed73b8..cd90140 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c587e55..43f90d7 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b1347e2..507b389 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index fe8fe4e..1e92f2a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 diff --git a/gcc/cp/except.c b/gcc/cp/except.c index c76d944..daac0fd 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -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. */ 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); } } } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 4ac533e..593a4a6 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e56052d..052746c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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 diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 011406c..4b71a76 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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++; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C index 5603632..f7de073 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C @@ -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; } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C new file mode 100644 index 0000000..6d2a26a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C @@ -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; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C index 8a8c874..3cef600 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted46.C b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C new file mode 100644 index 0000000..d4562c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C @@ -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(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit11.C b/gcc/testsuite/g++.dg/cpp0x/implicit11.C index 3b536e7..9f5841d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit11.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit11.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C index 3eab43c..62c003a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C @@ -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"); diff --git a/gcc/testsuite/g++.dg/ext/anon-struct4.C b/gcc/testsuite/g++.dg/ext/anon-struct4.C index 5d0bf71..9c8e887 100644 --- a/gcc/testsuite/g++.dg/ext/anon-struct4.C +++ b/gcc/testsuite/g++.dg/ext/anon-struct4.C @@ -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 } diff --git a/gcc/testsuite/g++.dg/init/ctor8.C b/gcc/testsuite/g++.dg/init/ctor8.C index 3491f6a..7eb72eb 100644 --- a/gcc/testsuite/g++.dg/init/ctor8.C +++ b/gcc/testsuite/g++.dg/init/ctor8.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C index c906a9b..e8945da 100644 --- a/gcc/testsuite/g++.dg/init/pr25811.C +++ b/gcc/testsuite/g++.dg/init/pr25811.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/init/pr29043.C b/gcc/testsuite/g++.dg/init/pr29043.C index 6ed31b5..f868dfb 100644 --- a/gcc/testsuite/g++.dg/init/pr29043.C +++ b/gcc/testsuite/g++.dg/init/pr29043.C @@ -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 ]; }; diff --git a/gcc/testsuite/g++.dg/init/pr43719.C b/gcc/testsuite/g++.dg/init/pr43719.C index d3487c9..13a8221 100644 --- a/gcc/testsuite/g++.dg/init/pr43719.C +++ b/gcc/testsuite/g++.dg/init/pr43719.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/init/pr44086.C b/gcc/testsuite/g++.dg/init/pr44086.C index e3304f4..b4b0833 100644 --- a/gcc/testsuite/g++.dg/init/pr44086.C +++ b/gcc/testsuite/g++.dg/init/pr44086.C @@ -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 } } } diff --git a/gcc/testsuite/g++.dg/init/ref14.C b/gcc/testsuite/g++.dg/init/ref14.C index 212e6e9..6ac4241 100644 --- a/gcc/testsuite/g++.dg/init/ref14.C +++ b/gcc/testsuite/g++.dg/init/ref14.C @@ -1,4 +1,6 @@ // PR c++/33459 +// { dg-prune-output "uninitialized" } +// { dg-prune-output "deleted" } union A { diff --git a/gcc/testsuite/g++.dg/init/uninitialized1.C b/gcc/testsuite/g++.dg/init/uninitialized1.C index 200c424..1e4f7ae 100644 --- a/gcc/testsuite/g++.dg/init/uninitialized1.C +++ b/gcc/testsuite/g++.dg/init/uninitialized1.C @@ -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'" } |