From patchwork Sun Oct 29 01:43:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 159319 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp1481445vqb; Sat, 28 Oct 2023 18:44:45 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFpVv7CpPffuCLr1vvLoivCL0IYaBx+VPjDgr8ujDqsN2VFqIJBnXgLk4dK4cZYwVu+SwbV X-Received: by 2002:ad4:4ee3:0:b0:66d:49aa:6844 with SMTP id dv3-20020ad44ee3000000b0066d49aa6844mr10366919qvb.19.1698543885409; Sat, 28 Oct 2023 18:44:45 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1698543885; cv=pass; d=google.com; s=arc-20160816; b=GD12o3boQTdKjo+bdYAqe3HugMevWpjGQZDvyjIDmbSM6mMkJhiLMBrCCelCrjSCVo 3l+LyOzVXQ/rapUvGE8XBL+2gLRhh6fQdUjRPSDnwEYnLrPouOWaUL6eER6nDN1M34ud hP43L60JFuabbLlCKs7G1vgfOhS3eY1weFvOE5pyLcbvcbn/F0qyMSITAR+Q+OKVP6v3 3AxxTzNwPi71sdSfOtCMvcTmC4nQS1wZg0ZKGToA04dlSDi8CunoAo+GcxndFb1wohUm QXFr0//mnd62bGtt9VfKTYHTXfuTSMyLT5UQLakcqDDS4AhCYK9zdVrRF6WdiEqaMHCG r/Bw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-disposition :mime-version:subject:cc:to:from:date:message-id:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=CoxCaKz4VyWURaAqmgV+ojQwNlQvjDgAC6fluz/zpU4=; fh=Px0ai+PRlAML1LDC3BukPvCf8nEgqik/SD+oF2SuaP0=; b=Qfp3TA3LtvB9j1oE5gafMVWVPjk3VEuA7ivsk6QHsnfKgHvWuCbQDTKUE5fOwGUPBI cdUM4AExjrPrfMF+gE8TLKKtraFgZMIKJUCQ5leaGxgdVXkfOYjCH7mM9ZKLpZblfkHz ks7V4NRnqMVRJw3SpDjHQRZ7wva+8t2aayp590RbQucq3fVeAAoiqRBS/klrs5mkrUyI w5VEbEPOo+gRJW3mcARADylaPKyoG7evVeKDUQRRlj3bhLza2DfO8yQFnW5yevk0dK0E aE5hbnRxuIilA0bIG7mTPZ/nUSiwAVFoRj+479iLNlq02kYyGSpDoXId833C1SudyUEI JNFw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=iNttc9bI; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id m11-20020a0c9d0b000000b0066cf06339basi3308721qvf.234.2023.10.28.18.44.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 Oct 2023 18:44:45 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=iNttc9bI; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 072BA3861885 for ; Sun, 29 Oct 2023 01:44:45 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id 725983857016 for ; Sun, 29 Oct 2023 01:43:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 725983857016 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 725983857016 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698543818; cv=none; b=g8oHrT386e4+fBweoboSyJH1qrfR2dSl8fUigYDImdTIoPffNlYxnwUPq9QaKQMNq5K4vlvPrlIc7/A0P4tXinkQSnNUyrd21iHaU1jjp6pp8QPeaikQf5xArNqDXl0TCpu7GBizKLK7FZqMkkjOHlgg+byd0G0wLrM1oHF8bhg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698543818; c=relaxed/simple; bh=VHIfkZ0nJLrEXFWR31vTsiVwGxQRJ9hB/ZIelfJi4dU=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=HYlZqF+v75WWDwSkMjwenp31/6hii7d6HRZ4qJnqe2thalAAlxSCTzx88t56msuGufLAIK44zPOi6T1QY//0DcaGB9hmtHlbbZ4VN3vQxfKihrALZ2hpKtnZeGfTwAgDsOC4NQp2L+9AzeKZ74DPKNB22LwKFxD1egBvAqJ/1NA= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-1c77449a6daso28816625ad.0 for ; Sat, 28 Oct 2023 18:43:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698543814; x=1699148614; darn=gcc.gnu.org; h=content-disposition:mime-version:subject:cc:to:from:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=CoxCaKz4VyWURaAqmgV+ojQwNlQvjDgAC6fluz/zpU4=; b=iNttc9bIIBpI1VDdwsKaz0ujUDYBXJ+Uo4sl4NNza8CbYatg1DZLMYHPiFWcJuInwJ O02D5pPlg2QnXEMe/pvjzERyff3LmiWc9ETD1DrD6Z1kIY8Kkyt+pimYBVRV/X2BSbV1 pMl0qYCzz/2XvvK2NQ80KeAYMfFKbSCUz/TmZPCSoFQysvWVQIOQ1GKTeuK1WhJ9tkkN GomP6IKoxqZoma2qGhi0S6fPydc/e1IPHNQdt6yee/8qo3BTYHbL0VcwpUvFXxswvtcw pVdA2OHUc4ytO5NT00Z7A87x+FaQKVGXoodcIaFIEGzzBmgU3eZywF/+RYrdk+IWxZ0B 9SCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698543814; x=1699148614; h=content-disposition:mime-version:subject:cc:to:from:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CoxCaKz4VyWURaAqmgV+ojQwNlQvjDgAC6fluz/zpU4=; b=BAV5K78pbnwpZFTq0dv1hBbV+Mq+s4iYZ5uSNymdTohf0OcUqTz+qIoZLeEODWKkdD 0UHOjqav0LXuko3VmzwGqiYT1v4EO/LHoLUSRckPUHc0FOIDA65FuEYZw5uetC+vet8M UAnJAzXSSxQ3HQ6p43vo+oo+YAc9JBHn7q1RJXrZqt01XtFkh98Ed2uqBpAdFBoC0aal v7eUvxmZNPu5fCB1MWot9VDwr0v9dI7HIzsHo0vhxnw8Qg70KO5eSHpojujBa0HvakvU Le+AdA1Y3EKPXXShfv0OhwDtfevXkTUOIZU/9XB74LTMVxs/9oeQm8bgK0Yb6XAFjDy0 omeA== X-Gm-Message-State: AOJu0YzK6BrwOQD1/5avIY2HBJIY28RY7zN4I5iRyzSI2wANLB9CO08H DSllvmaHheTpOhPJM3RZ0yXw6EkempM= X-Received: by 2002:a17:902:f34d:b0:1ca:7086:60ec with SMTP id q13-20020a170902f34d00b001ca708660ecmr5494895ple.65.1698543813886; Sat, 28 Oct 2023 18:43:33 -0700 (PDT) Received: from Thaum. (124-150-88-161.tpgi.com.au. [124.150.88.161]) by smtp.gmail.com with ESMTPSA id d9-20020a170902cec900b001cc307bcdbdsm1984464plg.211.2023.10.28.18.43.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 Oct 2023 18:43:33 -0700 (PDT) Message-ID: <653db8c5.170a0220.c70e1.602f@mx.google.com> X-Google-Original-Message-ID: Date: Sun, 29 Oct 2023 12:43:28 +1100 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill Subject: [PATCH] c++: fix noexcept checking for trivial operations [PR96090] MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1781052353442336339 X-GMAIL-MSGID: 1781052353442336339 Bootstrapped and regtested on x86_64-pc-linux-gnu. -- >8 -- This patch stops eager folding of trivial operations (construction and assignment) from occurring when checking for noexceptness. This was previously done in PR c++/53025, but only for copy/move construction, and the __is_nothrow_xible builtins did not receive the same treatment when they were added. To handle `is_nothrow_default_constructible`, the patch also ensures that when no parameters are passed we do value initialisation instead of just building the constructor call: in particular, value-initialisation doesn't necessarily actually invoke the constructor for trivial default constructors, and so we need to handle this case as well. PR c++/96090 PR c++/100470 gcc/cp/ChangeLog: * call.cc (build_over_call): Prevent folding of trivial special members when checking for noexcept. * method.cc (constructible_expr): Perform value-initialisation for empty parameter lists. (is_nothrow_xible): Treat as noexcept operator. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/noexcept81.C: New test. * g++.dg/ext/is_nothrow_constructible7.C: New test. * g++.dg/ext/is_nothrow_constructible8.C: New test. Signed-off-by: Nathaniel Shead Signed-off-by: Nathaniel Shead --- gcc/cp/call.cc | 17 ++--- gcc/cp/method.cc | 19 ++++-- gcc/testsuite/g++.dg/cpp0x/noexcept81.C | 36 +++++++++++ .../g++.dg/ext/is_nothrow_constructible7.C | 20 ++++++ .../g++.dg/ext/is_nothrow_constructible8.C | 63 +++++++++++++++++++ 5 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept81.C create mode 100644 gcc/testsuite/g++.dg/ext/is_nothrow_constructible7.C create mode 100644 gcc/testsuite/g++.dg/ext/is_nothrow_constructible8.C diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index c1fb8807d3f..ac02b0633ed 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -10231,15 +10231,16 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) /* Avoid actually calling copy constructors and copy assignment operators, if possible. */ - if (! flag_elide_constructors && !force_elide) + if (!force_elide + && (!flag_elide_constructors + /* It's unsafe to elide the operation when handling + a noexcept-expression, it may evaluate to the wrong + value (c++/53025, c++/96090). */ + || cp_noexcept_operand != 0)) /* Do things the hard way. */; - else if (cand->num_convs == 1 - && (DECL_COPY_CONSTRUCTOR_P (fn) - || DECL_MOVE_CONSTRUCTOR_P (fn)) - /* It's unsafe to elide the constructor when handling - a noexcept-expression, it may evaluate to the wrong - value (c++/53025). */ - && (force_elide || cp_noexcept_operand == 0)) + else if (cand->num_convs == 1 + && (DECL_COPY_CONSTRUCTOR_P (fn) + || DECL_MOVE_CONSTRUCTOR_P (fn))) { tree targ; tree arg = argarray[num_artificial_parms_for (fn)]; diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index a70dd5d6adc..3c978e2369d 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -2091,6 +2091,7 @@ constructible_expr (tree to, tree from) { tree expr; cp_unevaluated cp_uneval_guard; + const int len = TREE_VEC_LENGTH (from); if (CLASS_TYPE_P (to)) { tree ctype = to; @@ -2098,11 +2099,16 @@ constructible_expr (tree to, tree from) if (!TYPE_REF_P (to)) to = cp_build_reference_type (to, /*rval*/false); tree ob = build_stub_object (to); - vec_alloc (args, TREE_VEC_LENGTH (from)); - for (tree arg : tree_vec_range (from)) - args->quick_push (build_stub_object (arg)); - expr = build_special_member_call (ob, complete_ctor_identifier, &args, - ctype, LOOKUP_NORMAL, tf_none); + if (len == 0) + expr = build_value_init (ctype, tf_none); + else + { + vec_alloc (args, TREE_VEC_LENGTH (from)); + for (tree arg : tree_vec_range (from)) + args->quick_push (build_stub_object (arg)); + expr = build_special_member_call (ob, complete_ctor_identifier, &args, + ctype, LOOKUP_NORMAL, tf_none); + } if (expr == error_mark_node) return error_mark_node; /* The current state of the standard vis-a-vis LWG 2116 is that @@ -2120,7 +2126,6 @@ constructible_expr (tree to, tree from) } else { - const int len = TREE_VEC_LENGTH (from); if (len == 0) return build_value_init (strip_array_types (to), tf_none); if (len > 1) @@ -2216,7 +2221,9 @@ is_trivially_xible (enum tree_code code, tree to, tree from) bool is_nothrow_xible (enum tree_code code, tree to, tree from) { + ++cp_noexcept_operand; tree expr = is_xible_helper (code, to, from, /*trivial*/false); + --cp_noexcept_operand; if (expr == NULL_TREE || expr == error_mark_node) return false; return expr_noexcept_p (expr, tf_none); diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept81.C b/gcc/testsuite/g++.dg/cpp0x/noexcept81.C new file mode 100644 index 00000000000..a1481613b5d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept81.C @@ -0,0 +1,36 @@ +// { dg-do compile { target c++11 } } +// PR c++/96090 + +struct yesthrow_t { + yesthrow_t() noexcept(false) = default; + yesthrow_t(const yesthrow_t&) noexcept(false) = default; + yesthrow_t(yesthrow_t&&) noexcept(false) = default; + yesthrow_t& operator=(const yesthrow_t&) noexcept(false) = default; + yesthrow_t& operator=(yesthrow_t&&) noexcept(false) = default; +}; + +yesthrow_t yes; +static_assert(not noexcept(yesthrow_t(static_cast(yes))), ""); +static_assert(not noexcept(yesthrow_t(static_cast(yes))), ""); +static_assert(not noexcept(yes = static_cast(yes)), ""); +static_assert(not noexcept(yes = static_cast(yes)), ""); + +// Note: this is value-initialisation, and thus by [dcl.init.general] p9 +// a trivial non-user-provided non-deleted default constructor is not called. +static_assert(noexcept(yesthrow_t()), ""); + +struct nothrow_t { + nothrow_t() noexcept(true) = default; + nothrow_t(const nothrow_t&) noexcept(true) = default; + nothrow_t(nothrow_t&&) noexcept(true) = default; + nothrow_t& operator=(const nothrow_t&) noexcept(true) = default; + nothrow_t& operator=(nothrow_t&&) noexcept(true) = default; +}; + +nothrow_t no; +static_assert(noexcept(nothrow_t()), ""); +static_assert(noexcept(nothrow_t(static_cast(no))), ""); +static_assert(noexcept(nothrow_t(static_cast(no))), ""); +static_assert(noexcept(no = static_cast(no)), ""); +static_assert(noexcept(no = static_cast(no)), ""); + diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible7.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible7.C new file mode 100644 index 00000000000..b63b13ac52f --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible7.C @@ -0,0 +1,20 @@ +// { dg-do compile { target c++11 } } +// PR c++/100470 + +struct S1{ + S1(S1&&) noexcept(false); +}; +struct S2{ + S2(S2&&) noexcept(false) = default; +}; +struct S3{ + S3(S3&&) noexcept(false){} +}; +struct S4{ + S4(S4&&) = default; +}; + +static_assert(!__is_nothrow_constructible(S1, S1), ""); +static_assert(!__is_nothrow_constructible(S2, S2), ""); +static_assert(!__is_nothrow_constructible(S3, S3), ""); +static_assert( __is_nothrow_constructible(S4, S4), ""); diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible8.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible8.C new file mode 100644 index 00000000000..f23d48fa888 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible8.C @@ -0,0 +1,63 @@ +// { dg-do compile { target c++11 } } +// PR c++/96090 + +template +constexpr bool is_nothrow_default_constructible_v + = __is_nothrow_constructible(T); +template +constexpr bool is_nothrow_copy_constructible_v + = __is_nothrow_constructible(T, const T&); +template +constexpr bool is_nothrow_move_constructible_v + = __is_nothrow_constructible(T, T&&); +template +constexpr bool is_nothrow_copy_assignable_v + = __is_nothrow_assignable(T, const T&); +template +constexpr bool is_nothrow_move_assignable_v + = __is_nothrow_assignable(T, T&&); + +struct yesthrow_t { + yesthrow_t() noexcept(false) = default; + yesthrow_t(const yesthrow_t&) noexcept(false) = default; + yesthrow_t(yesthrow_t&&) noexcept(false) = default; + yesthrow_t& operator=(const yesthrow_t&) noexcept(false) = default; + yesthrow_t& operator=(yesthrow_t&&) noexcept(false) = default; +}; + +static_assert(not is_nothrow_copy_constructible_v, ""); +static_assert(not is_nothrow_copy_assignable_v, ""); +static_assert(not is_nothrow_move_constructible_v, ""); +static_assert(not is_nothrow_move_assignable_v, ""); + +// Note: by [meta.unary.prop] p9 this should be value-initialisation, +// and thus by [dcl.init.general] p9 a trivial non-user-provided +// non-deleted default constructor is not called. +static_assert(is_nothrow_default_constructible_v, ""); + +struct nothrow_t { + nothrow_t() noexcept(true) = default; + nothrow_t(const nothrow_t&) noexcept(true) = default; + nothrow_t(nothrow_t&&) noexcept(true) = default; + nothrow_t& operator=(const nothrow_t&) noexcept(true) = default; + nothrow_t& operator=(nothrow_t&&) noexcept(true) = default; +}; + +static_assert(is_nothrow_default_constructible_v, ""); +static_assert(is_nothrow_copy_constructible_v, ""); +static_assert(is_nothrow_copy_assignable_v, ""); +static_assert(is_nothrow_move_constructible_v, ""); +static_assert(is_nothrow_move_assignable_v, ""); + +struct A { A() noexcept(false) = default; }; +struct B { B(const B&) noexcept(false) = default; }; +struct C { C(C&&) noexcept(false) = default; }; +struct D { D& operator=(const D&) noexcept(false) = default; }; +struct E { E& operator=(E&&) noexcept(false) = default; }; + +static_assert(is_nothrow_default_constructible_v, ""); // see above +static_assert(not is_nothrow_copy_constructible_v, ""); +static_assert(not is_nothrow_move_constructible_v, ""); +static_assert(not is_nothrow_copy_assignable_v, ""); +static_assert(not is_nothrow_move_assignable_v, ""); +