From patchwork Wed Jan 22 02:08:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1226894 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-517962-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=xiBew+IB; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=g/lhrdWd; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 482TNb1gVnz9sPJ for ; Wed, 22 Jan 2020 13:09:02 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=rQXOWdpBC+x0S225 qeXf9LuIDoYhGsjmpbMDITNSX4SaGJs9M6YCYvykvXQbcqKdNzgDICy/LbcG6OnT doGfdpaSC8zZRz70mlD1GZABd1SrSKnHoqApx1MvsjicVEcQ/Xr1Xsia78aCfgrD yjDM/wg9fgtJYs2mtQ2qu+462h0= 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:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=l48Fz/ifoKRg4trP6Na43B vf69g=; b=xiBew+IBHgGJdlKFls9SuKMxS4NZi6pCXuskyU3ofgt2iWFCmcwYFn AFLhVKUkJnIqHvjHBriSNR7nbaLzFR8pxKlj0Tif1IYrIha79oHQ9/5euEpROCD6 16Ns0dehoIPDKuqVhIP5eOCuhg0EGQlULTqalQqFRkiGv5ujhxeFA= Received: (qmail 91063 invoked by alias); 22 Jan 2020 02:08:54 -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 91050 invoked by uid 89); 22 Jan 2020 02:08:53 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy= X-HELO: us-smtp-1.mimecast.com Received: from us-smtp-delivery-1.mimecast.com (HELO us-smtp-1.mimecast.com) (207.211.31.120) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 22 Jan 2020 02:08:51 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1579658930; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bfIMiubgjhudEaEMR6dSOFV7Wl6tsPwqUv7PgA8HJoU=; b=g/lhrdWdun2Vw58Zj0+iR5YGuNF9uYgz/ePT1iYi1lBkraJmvOM7a3wCT4HmJfX4MkQ86K AWC6W0o9AlhOS0r6Ln0w6l7YHPArr3rYdSmBUhBhNPIT8NRNYqgsW5bkDU56RMTwzpU4NX OtipZU3N/ZTfnhH6Rq/ZENaN07iDXDg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-249-Vq2HW2LtPBqQawXrldVZmg-1; Tue, 21 Jan 2020 21:08:43 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id EBC3D1005502 for ; Wed, 22 Jan 2020 02:08:42 +0000 (UTC) Received: from pdp-11.redhat.com (ovpn-121-93.rdu2.redhat.com [10.10.121.93]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5B5F71001B0B; Wed, 22 Jan 2020 02:08:40 +0000 (UTC) From: Marek Polacek To: Jason Merrill , GCC Patches Subject: [C++ PATCH] PR c++/92907 - noexcept does not consider "const" in member functions. Date: Tue, 21 Jan 2020 21:08:26 -0500 Message-Id: <20200122020826.1140392-1-polacek@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Here the problem is that if the noexcept specifier is used in the context of a const member function, const is not considered for the member variables, leading to a bogus error. g's const makes its 'this' const, so the first overload of f should be selected. In cp_parser_noexcept_specification_opt we inject 'this', but always unqualified: 25737 if (current_class_type) 25738 inject_this_parameter (current_class_type, TYPE_UNQUALIFIED); so we need to pass the function's qualifiers down here. In cp_parser_direct_declarator it's easy: use the just parsed cv_quals, in cp_parser_late_noexcept_specifier look at the 'this' parameter to figure it out. Bootstrapped/regtested on x86_64-linux, ok for trunk? Not planning to backport it to 9, this is not really a regression. 2020-01-21 Marek Polacek PR c++/92907 - noexcept does not consider "const" in member functions. * parser.c (cp_parser_lambda_declarator_opt): Pass TYPE_UNQUALIFIED down to cp_parser_exception_specification_opt. (cp_parser_direct_declarator): Pass the function qualifiers to cp_parser_exception_specification_opt. (cp_parser_class_specifier_1): Pass the function declaration to cp_parser_late_noexcept_specifier. (cp_parser_late_noexcept_specifier): Add a tree parameter. Use it to pass the qualifiers of the function to cp_parser_noexcept_specification_opt. (cp_parser_noexcept_specification_opt): New cp_cv_quals parameter. Use it in inject_this_parameter. (cp_parser_exception_specification_opt): New cp_cv_quals parameter. Use it. (cp_parser_transaction): Pass TYPE_UNQUALIFIED to cp_parser_noexcept_specification_opt. (cp_parser_transaction_expression): Likewise. * g++.dg/cpp0x/noexcept56.C: New test. --- gcc/cp/parser.c | 53 +++++++++++++++++-------- gcc/testsuite/g++.dg/cpp0x/noexcept56.C | 10 +++++ 2 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept56.C base-commit: 8e0efc10335bf9bb447f2188254609dcfad7de8a diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index caafbefda8e..e3566f9bd4d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -246,7 +246,7 @@ static void cp_lexer_stop_debugging static cp_token_cache *cp_token_cache_new (cp_token *, cp_token *); static tree cp_parser_late_noexcept_specifier - (cp_parser *, tree); + (cp_parser *, tree, tree); static void noexcept_override_late_checks (tree, tree); @@ -2388,11 +2388,11 @@ static tree cp_parser_exception_declaration static tree cp_parser_throw_expression (cp_parser *); static tree cp_parser_exception_specification_opt - (cp_parser *, cp_parser_flags); + (cp_parser *, cp_parser_flags, cp_cv_quals); static tree cp_parser_type_id_list (cp_parser *); static tree cp_parser_noexcept_specification_opt - (cp_parser *, cp_parser_flags, bool, bool *, bool); + (cp_parser *, cp_parser_flags, bool, bool *, bool, cp_cv_quals); /* GNU Extensions */ @@ -11008,7 +11008,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) /* Parse optional exception specification. */ exception_spec - = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE); + = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE, + TYPE_UNQUALIFIED); std_attrs = cp_parser_std_attribute_spec_seq (parser); @@ -21126,7 +21127,9 @@ cp_parser_direct_declarator (cp_parser* parser, tree tx_qual = cp_parser_tx_qualifier_opt (parser); /* And the exception-specification. */ exception_specification - = cp_parser_exception_specification_opt (parser, flags); + = cp_parser_exception_specification_opt (parser, + flags, + cv_quals); attrs = cp_parser_std_attribute_spec_seq (parser); @@ -23984,7 +23987,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) parser->local_variables_forbidden_p |= THIS_FORBIDDEN; /* Now we can parse the noexcept-specifier. */ - spec = cp_parser_late_noexcept_specifier (parser, spec); + spec = cp_parser_late_noexcept_specifier (parser, spec, decl); if (spec != error_mark_node) TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec); @@ -25611,10 +25614,12 @@ cp_parser_save_noexcept (cp_parser *parser) /* Used for late processing of noexcept-specifiers of member-functions. DEFAULT_ARG is the unparsed operand of a noexcept-specifier which - we saved for later; parse it now. */ + we saved for later; parse it now. DECL is the declaration of the + member function. */ static tree -cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg) +cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg, + tree decl) { /* Make sure we've gotten something that hasn't been parsed yet. */ gcc_assert (TREE_CODE (default_arg) == DEFERRED_PARSE); @@ -25626,13 +25631,20 @@ cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg) cp_token_cache *tokens = DEFPARSE_TOKENS (default_arg); cp_parser_push_lexer_for_tokens (parser, tokens); + /* We need to know if this member function was declared `const'. Look + at the this parameter to figure that out. */ + cp_cv_quals quals; + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + quals = cp_type_quals (class_of_this_parm (TREE_TYPE (decl))); + else + quals = TYPE_UNQUALIFIED; /* Parse the cached noexcept-specifier. */ tree parsed_arg = cp_parser_noexcept_specification_opt (parser, CP_PARSER_FLAGS_NONE, /*require_constexpr=*/true, /*consumed_expr=*/NULL, - /*return_cond=*/false); + /*return_cond=*/false, quals); /* Revert to the main lexer. */ cp_parser_pop_lexer (parser); @@ -25682,14 +25694,16 @@ noexcept_override_late_checks (tree type, tree fndecl) there are no parentheses. CONSUMED_EXPR will be set accordingly. Otherwise, returns a noexcept specification unless RETURN_COND is true, in which case a boolean condition is returned instead. The parser flags - FLAGS is used to control parsing. */ + FLAGS is used to control parsing. QUALS are qualifiers indicating whether + the (member) function is `const'. */ static tree cp_parser_noexcept_specification_opt (cp_parser* parser, cp_parser_flags flags, bool require_constexpr, bool* consumed_expr, - bool return_cond) + bool return_cond, + cp_cv_quals quals) { cp_token *token; const char *saved_message; @@ -25735,7 +25749,7 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, tree save_ccr = current_class_ref; if (current_class_type) - inject_this_parameter (current_class_type, TYPE_UNQUALIFIED); + inject_this_parameter (current_class_type, quals); if (require_constexpr) { @@ -25795,10 +25809,13 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, Returns a TREE_LIST representing the exception-specification. The TREE_VALUE of each node is a type. The parser flags FLAGS is used to - control parsing. */ + control parsing. QUALS are qualifiers indicating whether the (member) + function is `const'. */ static tree -cp_parser_exception_specification_opt (cp_parser* parser, cp_parser_flags flags) +cp_parser_exception_specification_opt (cp_parser* parser, + cp_parser_flags flags, + cp_cv_quals quals) { cp_token *token; tree type_id_list; @@ -25812,7 +25829,7 @@ cp_parser_exception_specification_opt (cp_parser* parser, cp_parser_flags flags) = cp_parser_noexcept_specification_opt (parser, flags, /*require_constexpr=*/true, /*consumed_expr=*/NULL, - /*return_cond=*/false); + /*return_cond=*/false, quals); if (type_id_list != NULL_TREE) return type_id_list; @@ -42964,7 +42981,8 @@ cp_parser_transaction (cp_parser *parser, cp_token *token) CP_PARSER_FLAGS_NONE, /*require_constexpr=*/true, /*consumed_expr=*/NULL, - /*return_cond=*/true); + /*return_cond=*/true, + TYPE_UNQUALIFIED); /* Keep track if we're in the lexical scope of an outer transaction. */ new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); @@ -43028,7 +43046,8 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword) CP_PARSER_FLAGS_NONE, /*require_constexpr=*/false, &noex_expr, - /*return_cond=*/true); + /*return_cond=*/true, + TYPE_UNQUALIFIED); if (!noex || !noex_expr || cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN) diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept56.C b/gcc/testsuite/g++.dg/cpp0x/noexcept56.C new file mode 100644 index 00000000000..8eea6b91f7e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept56.C @@ -0,0 +1,10 @@ +// PR c++/92907 - noexcept does not consider "const" in member functions. +// { dg-do compile { target c++11 } } + +void f(const int&); +void f(int&) = delete; + +struct A { + int i; + void g() const noexcept(noexcept(f(i))); +};