From patchwork Fri Jan 7 00:21:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 49683 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id ED5A83858001 for ; Fri, 7 Jan 2022 00:31:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org ED5A83858001 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1641515492; bh=Nb+2ZlI0n1v8NetUKzdciX2tfUOGsBgL5HgEDaytaKs=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=bkF38DZHJ/0ONGsDguorAjbPzYys9ZfyE049D4zSCUGZSXepYQJ2+LfOmSAZhtip8 UGr0gI12inRHDY74gDkoyshk+rBmShf1g/LQC3t+rJ7zcWV0S8RbzJTDtigwID0xtw munWv+edZbnryxwYjDBkuL3oj/W/h1/OYmI47Q8I= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 5CCB03858013 for ; Fri, 7 Jan 2022 00:22:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5CCB03858013 Received: from mail-qv1-f69.google.com (mail-qv1-f69.google.com [209.85.219.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-331-2A1kS31SPMyo2r9nZr_9kA-1; Thu, 06 Jan 2022 19:22:08 -0500 X-MC-Unique: 2A1kS31SPMyo2r9nZr_9kA-1 Received: by mail-qv1-f69.google.com with SMTP id r13-20020a0562140c4d00b004119074a4d9so3552575qvj.12 for ; Thu, 06 Jan 2022 16:22:08 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Nb+2ZlI0n1v8NetUKzdciX2tfUOGsBgL5HgEDaytaKs=; b=J5G+r2/0ax4ofLOqf5AHCstUI7W5wvUXC2L+lOlJbjJvJdpbnPzCqhGBlj6wEy1FVp 9hsVEhcs2mfb6YXkn8sjAn1KwshNPrYObKMMkDmXDoGlKFB8PYL1rEhVBoXaaBvPfcjt x4+0DS+T8XbRSjh/ojWEg19r0RbCIC0I0tp6WPACRhbp771vNDNakKVYanEw/7aRu8OZ 8FP9Du/mQii6MH1ZH6Z2tji0GZyxMyJAtznMSORb2OKkyn0YXyqHiW2L+7+hU5tOOwNK kgd6PlQSUaxHWx1SqzhRCFbkBpJYG+UhUJu/QhLkvJGvqNhx32K93xD0iCgcU2PKgyWP wawA== X-Gm-Message-State: AOAM53298a3FgVDi+eVQANccoT0hM5UNfVEFAHnODS5bWz+yhFTnf5v5 gViZeGAH3X96nRXMT+d1CcEoakIiR7BDhvKR/PIkUs55WBeItjrKBQpjIRmAOSGJJC9RU4I5n1C p5XqGMzeHP1lzjNKWieg+YPETxwaOFPtwvtZiWpqOO+8yB8ctcf+58Hcn6oPCfyoltg== X-Received: by 2002:a05:6214:d0d:: with SMTP id 13mr25666182qvh.15.1641514927726; Thu, 06 Jan 2022 16:22:07 -0800 (PST) X-Google-Smtp-Source: ABdhPJzwTIAHw/bSt+KBcw7pW9th+DJeW+b8bkVbk7PLb9ArYTS/sfj8oUqkSzi5NWECvgxki6a9CA== X-Received: by 2002:a05:6214:d0d:: with SMTP id 13mr25666164qvh.15.1641514927191; Thu, 06 Jan 2022 16:22:07 -0800 (PST) Received: from barrymore.redhat.com (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id s3sm2323785qkp.93.2022.01.06.16.22.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Jan 2022 16:22:06 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [pushed 08/11] c++: clean up ref-extended temp on throwing dtor [PR53868] Date: Thu, 6 Jan 2022 19:21:53 -0500 Message-Id: <20220107002156.2992278-8-jason@redhat.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220107002156.2992278-1-jason@redhat.com> References: <20220107002156.2992278-1-jason@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jason Merrill via Gcc-patches From: Jason Merrill Reply-To: Jason Merrill Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" We have wrap_temporary_cleanups to handle the EH region nesting problems between cleanups for complete variables and cleanups for temporaries used in their construction, but we weren't calling it for temporaries extended from binding to a reference. We still don't want this for array cleanups (since my PR94041 fix), so I move that exception from initialize_local_var to wrap_temporary_cleanups. PR c++/53868 gcc/cp/ChangeLog: * decl.c (cp_finish_decl): Use wrap_temporary_cleanups for cleanups from set_up_extended_ref_temp. (wrap_temporary_cleanups): Ignore array cleanups. (initialize_local_var): Don't check for array here. * cp-tree.h (BIND_EXPR_VEC_DTOR): New. * init.c (build_vec_delete_1): Set it. gcc/testsuite/ChangeLog: * g++.dg/eh/ref-temp1.C: New test. * g++.dg/eh/ref-temp2.C: New test. --- gcc/cp/cp-tree.h | 5 +++ gcc/cp/decl.c | 25 +++++++++++--- gcc/cp/init.c | 1 + gcc/testsuite/g++.dg/eh/ref-temp1.C | 51 +++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/eh/ref-temp2.C | 15 +++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/eh/ref-temp1.C create mode 100644 gcc/testsuite/g++.dg/eh/ref-temp2.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 56e6d661537..e204182da97 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -465,6 +465,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; OVL_USING_P (in OVERLOAD) IMPLICIT_CONV_EXPR_NONTYPE_ARG (in IMPLICIT_CONV_EXPR) BASELINK_FUNCTIONS_MAYBE_INCOMPLETE_P (in BASELINK) + BIND_EXPR_VEC_DTOR (in BIND_EXPR) 2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) @@ -712,6 +713,10 @@ typedef struct ptrmem_cst * ptrmem_cst_t; #define BIND_EXPR_TRY_BLOCK(NODE) \ TREE_LANG_FLAG_0 (BIND_EXPR_CHECK (NODE)) +/* This BIND_EXPR is from build_vec_delete_1. */ +#define BIND_EXPR_VEC_DTOR(NODE) \ + TREE_LANG_FLAG_1 (BIND_EXPR_CHECK (NODE)) + /* Used to mark the block around the member initializers and cleanups. */ #define BIND_EXPR_BODY_BLOCK(NODE) \ TREE_LANG_FLAG_3 (BIND_EXPR_CHECK (NODE)) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b16a4f9ed34..5fe341e0b75 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7451,11 +7451,24 @@ wrap_cleanups_r (tree *stmt_p, int *walk_subtrees, void *data) they are run on the normal path, but not if they are run on the exceptional path. We implement this by telling honor_protect_cleanup_actions to strip the variable cleanup from the - exceptional path. */ + exceptional path. + + Another approach could be to make the variable cleanup region enclose + initialization, but depend on a flag to indicate that the variable is + initialized; that's effectively what we do for arrays. But the current + approach works fine for non-arrays, and has no code overhead in the usual + case where the temporary destructors are noexcept. */ static void wrap_temporary_cleanups (tree init, tree guard) { + if (TREE_CODE (guard) == BIND_EXPR) + { + /* An array cleanup region already encloses any temporary cleanups, + don't wrap it around them again. */ + gcc_checking_assert (BIND_EXPR_VEC_DTOR (guard)); + return; + } cp_walk_tree_without_duplicates (&init, wrap_cleanups_r, (void *)guard); } @@ -7518,8 +7531,8 @@ initialize_local_var (tree decl, tree init) /* If we're only initializing a single object, guard the destructors of any temporaries used in its initializer with - its destructor. But arrays are handled in build_vec_init. */ - if (cleanup && TREE_CODE (type) != ARRAY_TYPE) + its destructor. */ + if (cleanup) wrap_temporary_cleanups (init, cleanup); gcc_assert (building_stmt_list_p ()); @@ -8367,7 +8380,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (cleanups) { for (tree t : *cleanups) - push_cleanup (decl, t, false); + { + push_cleanup (decl, t, false); + /* As in initialize_local_var. */ + wrap_temporary_cleanups (init, t); + } release_tree_vector (cleanups); } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index df63e618394..bfe4ad464bf 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -4092,6 +4092,7 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type, tbase_init = build_stmt (loc, DECL_EXPR, tbase); controller = build3 (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (controller) = 1; + BIND_EXPR_VEC_DTOR (controller) = true; body = build1 (EXIT_EXPR, void_type_node, build2 (EQ_EXPR, boolean_type_node, tbase, diff --git a/gcc/testsuite/g++.dg/eh/ref-temp1.C b/gcc/testsuite/g++.dg/eh/ref-temp1.C new file mode 100644 index 00000000000..2df1a4937b7 --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/ref-temp1.C @@ -0,0 +1,51 @@ +// PR c++/53868 +// { dg-do run { target c++11 } } + +#if __cplusplus > 201100L +#define THROWING noexcept(false) +#else +#define THROWING +#endif + +extern "C" int printf(const char *, ...); +extern "C" void abort(); + +struct SubobjectInA { + SubobjectInA(); + ~SubobjectInA(); +}; + +int a; +struct A : SubobjectInA { + A() = delete; + A(const A &) = delete; + A(A &&) = delete; + A(int); + ~A(); +}; + +#ifdef DEBUG +#define TRACE_FUNC( ... ) \ +{ printf("%s\n", __PRETTY_FUNCTION__); __VA_ARGS__ } +#else +#define TRACE_FUNC( ... ) \ +{ __VA_ARGS__ } +#endif + +struct Q { + Q() : q(0) TRACE_FUNC() + ~Q() THROWING; + int q; +}; + +int main() { + try { const A &a = Q().q; } + catch (...) { if (!a) return 0; } + abort(); +} + +SubobjectInA::SubobjectInA() TRACE_FUNC() +SubobjectInA::~SubobjectInA() TRACE_FUNC() +A::A(int) TRACE_FUNC(++a;) +A::~A() TRACE_FUNC(--a;) +Q::~Q() THROWING TRACE_FUNC( throw 0; ) diff --git a/gcc/testsuite/g++.dg/eh/ref-temp2.C b/gcc/testsuite/g++.dg/eh/ref-temp2.C new file mode 100644 index 00000000000..0c718962d49 --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/ref-temp2.C @@ -0,0 +1,15 @@ +// { dg-do run { target c++11 } } + +struct B { B() {} ~B() noexcept(false) { throw 42; } }; +int a; +struct A { A() { ++a; }; A(B) { ++a; } ~A() { --a; } }; + +using Arr = A[3]; + +int main() +{ + try { + auto&& ref = Arr{B()}; + } catch (...) { } + return a; +}