From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 35484 invoked by alias); 23 Oct 2019 20:41:08 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 35470 invoked by uid 89); 23 Oct 2019 20:41:07 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.3 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_NUMSUBJECT autolearn=ham version=3.3.1 spammy=contra, dg-warning, dgwarning, FIELD_DECLs X-HELO: us-smtp-delivery-1.mimecast.com Received: from us-smtp-2.mimecast.com (HELO us-smtp-delivery-1.mimecast.com) (205.139.110.61) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 23 Oct 2019 20:41:05 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571863264; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=vXYmcXY+FWmZOt5+YCJjdMLi1dbyS8LNMLR36cseQXY=; b=KD7QXlCtkVtA3BHI1ybfVCJqPhamYnRszjiU5ESKzWSXmhNmvSknq+/KGst6Cc1l8Hbx+j Pm6UwGjuZsnU6cT1/rmJqTzA1bGxRcuwT8u/E4DxnLiuIl/8Y2e/QdP+ooxHMIsZrnmacB xJIp6U1COfKcRLHnN8919wVJGisNQO4= Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-386-Zm1cW90RN0amBZCw0B5vug-1; Wed, 23 Oct 2019 16:41:02 -0400 Received: by mail-qt1-f198.google.com with SMTP id 44so16108888qtu.20 for ; Wed, 23 Oct 2019 13:41:02 -0700 (PDT) Return-Path: Received: from barrymore.cygnus.csb (209-6-216-142.s141.c3-0.smr-cbr1.sbo-smr.ma.cable.rcncustomer.com. [209.6.216.142]) by smtp.gmail.com with ESMTPSA id h20sm9600376qtp.93.2019.10.23.13.40.59 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Oct 2019 13:40:59 -0700 (PDT) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [C++ PATCH] Implement P1286R2, Contra CWG1778 Date: Wed, 23 Oct 2019 21:01:00 -0000 Message-Id: <20191023204058.14971-1-jason@redhat.com> X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2019-10/txt/msg01699.txt.bz2 The C++11 requirement that an explicit exception-specification on a defaulted function match the implicit one was found to be problematic for std::atomic. This paper, adopted in February, simply removes that requirement: if an explicitly defaulted function has a different exception-specification, that now works just like a user-written function: either it isn't noexcept when it could be, or it is noexcept and will call terminate if an exception is thrown. Tested x86_64-pc-linux-gnu, applying to trunk. * method.c (defaulted_late_check): Don't check explicit exception-specification on defaulted function. (after_nsdmi_defaulted_late_checks): Remove. * parser.h (struct cp_unparsed_functions_entry): Remove classes. * parser.c (unparsed_classes): Remove. (push_unparsed_function_queues, cp_parser_class_specifier_1): Adjust. --- gcc/cp/parser.h | 4 -- gcc/cp/method.c | 69 +++--------------------- gcc/cp/parser.c | 14 +---- gcc/testsuite/g++.dg/DRs/dr1778.C | 7 +++ gcc/testsuite/g++.dg/cpp0x/defaulted23.C | 4 +- gcc/testsuite/g++.dg/cpp0x/defaulted43.C | 10 ++-- 6 files changed, 21 insertions(+), 87 deletions(-) create mode 100644 gcc/testsuite/g++.dg/DRs/dr1778.C diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 91b5916622d..200498281b5 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -163,10 +163,6 @@ struct GTY(()) cp_unparsed_functions_entry { FIELD_DECLs appear in this list in declaration order. */ vec *nsdmis; =20 - /* Nested classes go in this vector, so that we can do some final - processing after parsing any NSDMIs. */ - vec *classes; - /* Functions with noexcept-specifiers that require post-processing. */ vec *noexcepts; }; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 73a01147ff9..b613e5df871 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2204,40 +2204,12 @@ defaulted_late_check (tree fn) return; } =20 - /* 8.4.2/2: An explicitly-defaulted function (...) may have an explicit - exception-specification only if it is compatible (15.4) with the=20 - exception-specification on the implicit declaration. If a function - is explicitly defaulted on its first declaration, (...) it is - implicitly considered to have the same exception-specification as if - it had been implicitly declared. */ - maybe_instantiate_noexcept (fn); - tree fn_spec =3D TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); - if (!fn_spec) - { - if (DECL_DEFAULTED_IN_CLASS_P (fn)) - TREE_TYPE (fn) =3D build_exception_variant (TREE_TYPE (fn), eh_spec); - } - else if (UNEVALUATED_NOEXCEPT_SPEC_P (fn_spec)) - /* Equivalent to the implicit spec. */; - else if (DECL_DEFAULTED_IN_CLASS_P (fn) - && !CLASSTYPE_TEMPLATE_INSTANTIATION (ctx)) - /* We can't compare an explicit exception-specification on a - constructor defaulted in the class body to the implicit - exception-specification until after we've parsed any NSDMI; see - after_nsdmi_defaulted_late_checks. */; - else - { - tree eh_spec =3D get_defaulted_eh_spec (fn); - if (!comp_except_specs (fn_spec, eh_spec, ce_normal)) - { - if (DECL_DEFAULTED_IN_CLASS_P (fn)) - DECL_DELETED_FN (fn) =3D true; - else - error ("function %q+D defaulted on its redeclaration " - "with an exception-specification that differs from " - "the implicit exception-specification %qX", fn, eh_spec); - } - } + /* If a function is explicitly defaulted on its first declaration withou= t an + exception-specification, it is implicitly considered to have the same + exception-specification as if it had been implicitly declared. */ + if (!TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)) + && DECL_DEFAULTED_IN_CLASS_P (fn)) + TREE_TYPE (fn) =3D build_exception_variant (TREE_TYPE (fn), eh_spec); =20 if (DECL_DEFAULTED_IN_CLASS_P (fn) && DECL_DECLARED_CONSTEXPR_P (implicit_fn)) @@ -2264,35 +2236,6 @@ defaulted_late_check (tree fn) } } =20 -/* OK, we've parsed the NSDMI for class T, now we can check any explicit - exception-specifications on functions defaulted in the class body. */ - -void -after_nsdmi_defaulted_late_checks (tree t) -{ - if (uses_template_parms (t)) - return; - if (t =3D=3D error_mark_node) - return; - for (tree fn =3D TYPE_FIELDS (t); fn; fn =3D DECL_CHAIN (fn)) - if (!DECL_ARTIFICIAL (fn) - && DECL_DECLARES_FUNCTION_P (fn) - && DECL_DEFAULTED_IN_CLASS_P (fn)) - { - tree fn_spec =3D TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); - if (UNEVALUATED_NOEXCEPT_SPEC_P (fn_spec)) - continue; - - tree eh_spec =3D get_defaulted_eh_spec (fn); - if (eh_spec =3D=3D error_mark_node) - continue; - - if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)), - eh_spec, ce_normal)) - DECL_DELETED_FN (fn) =3D true; - } -} - /* Returns true iff FN can be explicitly defaulted, and gives any errors if defaulting FN is ill-formed. */ =20 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6433f870b2e..60a46af804d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2005,16 +2005,13 @@ cp_parser_context_new (cp_parser_context* next) parser->unparsed_queues->last ().funs_with_definitions #define unparsed_nsdmis \ parser->unparsed_queues->last ().nsdmis -#define unparsed_classes \ - parser->unparsed_queues->last ().classes #define unparsed_noexcepts \ parser->unparsed_queues->last ().noexcepts =20 static void push_unparsed_function_queues (cp_parser *parser) { - cp_unparsed_functions_entry e =3D { NULL, make_tree_vector (), NULL, NUL= L, - NULL }; + cp_unparsed_functions_entry e =3D { NULL, make_tree_vector (), NULL, NUL= L }; vec_safe_push (parser->unparsed_queues, e); } =20 @@ -23754,7 +23751,6 @@ cp_parser_class_specifier_1 (cp_parser* parser) error recovery (c++/71169, c++/71832). */ vec_safe_truncate (unparsed_funs_with_default_args, 0); vec_safe_truncate (unparsed_nsdmis, 0); - vec_safe_truncate (unparsed_classes, 0); vec_safe_truncate (unparsed_funs_with_definitions, 0); } =20 @@ -23809,12 +23805,6 @@ cp_parser_class_specifier_1 (cp_parser* parser) if (pushed_scope) pop_scope (pushed_scope); =20 - /* Now do some post-NSDMI bookkeeping. */ - FOR_EACH_VEC_SAFE_ELT (unparsed_classes, ix, class_type) - after_nsdmi_defaulted_late_checks (class_type); - vec_safe_truncate (unparsed_classes, 0); - after_nsdmi_defaulted_late_checks (type); - /* If there are noexcept-specifiers that have not yet been processed, take care of them now. */ class_type =3D NULL_TREE; @@ -23885,8 +23875,6 @@ cp_parser_class_specifier_1 (cp_parser* parser) cp_parser_late_parsing_for_member (parser, decl); vec_safe_truncate (unparsed_funs_with_definitions, 0); } - else - vec_safe_push (unparsed_classes, type); =20 /* Put back any saved access checks. */ pop_deferring_access_checks (); diff --git a/gcc/testsuite/g++.dg/DRs/dr1778.C b/gcc/testsuite/g++.dg/DRs/d= r1778.C new file mode 100644 index 00000000000..8db937fc0bf --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr1778.C @@ -0,0 +1,7 @@ +// P1286R2: Contra CWG1778 +// { dg-do compile { target c++11 } } + +struct T { T(); T(T &&) noexcept(false); }; +struct U { T t; U(); U(U &&) noexcept =3D default; }; +U u1; +U u2 =3D static_cast(u1); // OK, calls std::terminate if T::T(T&= &) throws diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C b/gcc/testsuite/g++.d= g/cpp0x/defaulted23.C index dfbdd2f2ed1..23848633c3c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C @@ -10,10 +10,10 @@ A a; =20 struct B { - B() throw (int) =3D default; // { dg-message "exception-specification" "= " { target { ! c++17 } } } + B() throw (int) =3D default; }; // { dg-error "dynamic exception specification" "" { target c++17 } = .-1 } // { dg-warning "deprecated" "" { target { ! c++17 } } .-2 } -B b; // { dg-error "deleted" "" { target { ! c++17 } } } +B b; =20 struct C { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C b/gcc/testsuite/g++.d= g/cpp0x/defaulted43.C index f2846fe390c..1fe7818ec67 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted43.C @@ -17,8 +17,8 @@ struct A T t; }; =20 -A::A() noexcept =3D default; // { dg-error "defaulted" } -A::~A() noexcept =3D default; // { dg-error "defaulted" } +A::A() noexcept =3D default; +A::~A() noexcept =3D default; =20 struct U { @@ -51,10 +51,10 @@ V v; =20 struct C { - C() noexcept =3D default; // { dg-message "exception-specification" } - ~C() noexcept =3D default; // { dg-message "exception-specification" } + C() noexcept =3D default; + ~C() noexcept =3D default; =20 V v; }; =20 -C c; // { dg-error "deleted" } +C c; base-commit: e04a052b62e09874b0d61a217a5eb5b6eae5cdc5 --=20 2.18.1