From patchwork Wed Oct 23 18:05:13 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 285714 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 661AE2C00F9 for ; Thu, 24 Oct 2013 05:05:27 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=PKU6gqCxjN0S1s66GCGb7R+0XAVJRJQly2NvyoR9VHq9/v yEwRjJ0OmU5R5Jr5Ku7Zu0MIexHxeRWNClPFEy8JCgUte+i/GLQqqoYnUDcvXcPH x7YFu6s+FY1AfOHROPzjnkpgLvkFymk81+4A/LPoDQQs+QFLvboUKXKR0x+Xs= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=OsQX0xD85Y7ZYM+MA8Ff6DghaFc=; b=q8nvtJPm092dvUT6Kz0F RD5cbdXo1wGAAjsTLlQZo3HAMRLds1ptmOdKwaIFnCHazb0VjQlVTyd9hUHKad6r SEXc2xkg5iLTapqqWKx5MU/vx/ZW0pcQ5yhbQ78W7E5NfGb7wSYZVxoWbr2uqaEx DRxwkSPBQZyAw8m5l6j5Xx8= Received: (qmail 23284 invoked by alias); 23 Oct 2013 18:05:20 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 23269 invoked by uid 89); 23 Oct 2013 18:05:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.4 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 23 Oct 2013 18:05:15 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r9NI5EUZ008957 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 23 Oct 2013 14:05:14 -0400 Received: from [10.10.116.20] ([10.10.116.20]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r9NI5DnZ016198 for ; Wed, 23 Oct 2013 14:05:13 -0400 Message-ID: <52680FD9.7040302@redhat.com> Date: Wed, 23 Oct 2013 14:05:13 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH to deal with trivial but non-callable [cd]tors Late in the C++11 process it was decided that a constructor or destructor can be trivial but not callable; as a result, everywhere that assumed that a call to a trivial function didn't need any processing needed to be updated. This patch does that. Tested x86_64-pc-linux-gnu, applying to trunk. commit cbc14ce6b840e6311b8c580564f8c836f8dc18ae Author: Jason Merrill Date: Tue Oct 22 16:38:01 2013 -0400 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. 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 **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 **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 char (&f(...))[2]; -struct ND { ND() = delete; }; +struct ND { + // Make ND() non-aggregate. + virtual void f(); + ND() = delete; +}; static_assert(sizeof(f(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 struct S1 +template 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 struct S2 +template 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 struct S3 +template 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 struct S4 +template 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; // { dg-error "uninitialized const member" } + new S1; // { dg-error "deleted|uninitialized const member" } } void f7 () { - new S2; // { dg-error "uninitialized const member" } + new S2; // { dg-error "deleted|uninitialized const member" } } void f8 () { - new S3; // { dg-error "uninitialized reference member" } + new S3; // { dg-error "deleted|uninitialized reference member" } } void f9 () { - new S4; // { dg-error "uninitialized reference member|uninitialized const member" } + new S4; // { 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 struct S1 +template 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 struct S2 +template 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 struct S3 +template 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 struct S4 +template 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 s; // { dg-error "uninitialized const member" } + S1 s; // { dg-error "uninitialized const member|deleted" } } void f7 () { - S2 s; // { dg-error "uninitialized const member" } + S2 s; // { dg-error "uninitialized const member|deleted" } } void f8 () { - S3 s; // { dg-error "uninitialized reference member" } + S3 s; // { dg-error "uninitialized reference member|deleted" } } void f9 () { - S4 s; // { dg-error "uninitialized reference member|uninitialized const member" } + S4 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'" }