From patchwork Tue Nov 3 16:48:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1393208 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=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=kDjVbRhO; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CQbN350Dcz9sSn for ; Wed, 4 Nov 2020 03:49:06 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3713F398680C; Tue, 3 Nov 2020 16:49:04 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qt1-x82a.google.com (mail-qt1-x82a.google.com [IPv6:2607:f8b0:4864:20::82a]) by sourceware.org (Postfix) with ESMTPS id 70DE83854806 for ; Tue, 3 Nov 2020 16:49:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 70DE83854806 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qt1-x82a.google.com with SMTP id t5so3496099qtp.2 for ; Tue, 03 Nov 2020 08:49:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=cjcb93iOBUhk1rJgvXBZB5dOygHcmcJ26IMrB2v+ee0=; b=kDjVbRhO/aaSNl+mQeLc9ys+vZgoWH2D3XUx96+n5nAC/fFLQ+73UAUu8cxvaBHNhc GvvVqgAxUjhbDl84uuMe9Dy/l6wo+mq8CUNQPuCwbKnAGbSBl0HBT73bLz7R8tSdvxn5 suBSJ6qdBk/ImmJF05NRw19Xbolzy8AWS1iAQ6DSn7BwJPu9euZ0H+x+4Pd7hZrTrzbm aY6wpjhYX6OvA2N6Er4U/X9PhKJd8f047kXHPXUWCDsHFpAXiyQdECRCjeV7LXT0Pymo AsZ8dMGPaPNsDrYqi4Ehh+C/CXthQO7G1vZqf33JfHPN7mckvXmMJ1WTVrwDThhvg4IW AJuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=cjcb93iOBUhk1rJgvXBZB5dOygHcmcJ26IMrB2v+ee0=; b=IDbmpeHGEVUD0bJC/d3IyCH0N5FkAXttOy34IWhHDsk6+5tMM933DBW5M6AhODA/Eo xuLuQLB85RwgAIbR2qEV7cG3dn6jj9OAvD7ZASVbyi4RxL8dYkLOfMkuO7eyHqcspDEy oOGu1xkSfQdoiMpVCRPybbmz/CZhZttvWewc8xgbZDYdAlaTlq86koU0HCLWp6+CmUX+ vzUwZAlWk0uKJL12qpHusRfBS1b/072DaU46LjikRhkMjVouUE1vZ+4NEBVGZuiVAn8R 3dfvKbHIXdpwl13R9G7glATNCUbee5GwSKk17H7H4+qFLJH+FqqnBBalnBrAqB3Rui4b OvxQ== X-Gm-Message-State: AOAM531z/XEEtRVjahDnrI19EdQ9SnfW0LdxSOuqVOav7rH2ejGiceS4 6TgPJXNdbCnJ+PHDYrm6Dg0= X-Google-Smtp-Source: ABdhPJzX03RaVJUcX8c4KzhYb3aRNyOmwncjTHeaBxwWhWwYT+O4crojdL1UtTqlht/7jYhnM2ToSg== X-Received: by 2002:ac8:7604:: with SMTP id t4mr16509255qtq.366.1604422140826; Tue, 03 Nov 2020 08:49:00 -0800 (PST) Received: from ?IPv6:2620:10d:c0a8:1102:e5ef:7eb4:1609:98bb? ([2620:10d:c091:480::1:bc2d]) by smtp.googlemail.com with ESMTPSA id z13sm10748290qkl.2.2020.11.03.08.48.59 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 03 Nov 2020 08:48:59 -0800 (PST) To: GCC Patches From: Nathan Sidwell Subject: c++: Directly fixup deferred eh-specs Message-ID: <01a8f683-e565-6518-2e8d-731ef32b3eca@acm.org> Date: Tue, 3 Nov 2020 11:48:58 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" eh-specifiers in a class definition are complete-definition contexts, and we sometimes need to deferr their parsing. We create a deferred eh specifier, which can end up persisting in the type system due to variants being created before the deferred parse. This causes problems in modules handling. This patch adds fixup_deferred_exception_variants, which directly modifies the variants of such an eh spec once parsed. As commented, the general case is quite hard, so it doesn't deal with everything. But I do catch the cases I encountered (from the std library). gcc/cp/ * cp-tree.h (fixup_deferred_exception_variants): Declare. * parser.c (cp_parser_class_specifier_1): Call it when completing deferred parses rather than creating a variant. (cp_parser_member_declaration): Move comment from ... (cp_parser_noexcept_specification_opt): ... here. Refactor the deferred parse. * tree.c (fixup_deferred_exception_variants): New. pushing to trunk diff --git i/gcc/cp/cp-tree.h w/gcc/cp/cp-tree.h index 334424770ef..26852f6f2e3 100644 --- i/gcc/cp/cp-tree.h +++ w/gcc/cp/cp-tree.h @@ -7360,6 +7360,7 @@ extern const char *cxx_printable_name_translate (tree, int); extern tree canonical_eh_spec (tree); extern tree build_cp_fntype_variant (tree, cp_ref_qualifier, tree, bool); extern tree build_exception_variant (tree, tree); +extern void fixup_deferred_exception_variants (tree, tree); extern tree bind_template_template_parm (tree, tree); extern tree array_type_nelts_total (tree); extern tree array_type_nelts_top (tree); diff --git i/gcc/cp/parser.c w/gcc/cp/parser.c index dd8c4b56bd0..274797f1879 100644 --- i/gcc/cp/parser.c +++ w/gcc/cp/parser.c @@ -24334,8 +24334,12 @@ cp_parser_class_specifier_1 (cp_parser* parser) /* Now we can parse the noexcept-specifier. */ spec = cp_parser_late_noexcept_specifier (parser, spec); - if (spec != error_mark_node) - TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec); + if (spec == error_mark_node) + spec = NULL_TREE; + + /* Update the fn's type directly -- it might have escaped + beyond this decl :( */ + fixup_deferred_exception_variants (TREE_TYPE (decl), spec); /* Restore the state of local_variables_forbidden_p. */ parser->local_variables_forbidden_p = local_variables_forbidden_p; @@ -25371,6 +25375,9 @@ cp_parser_member_declaration (cp_parser* parser) int ctor_dtor_or_conv_p; bool static_p = (decl_specifiers.storage_class == sc_static); cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; + /* We can't delay parsing for friends, + alias-declarations, and typedefs, even though the + standard seems to require it. */ if (!friend_p && !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; @@ -26059,19 +26066,14 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, a class. So, if the noexcept-specifier has the optional expression, just save the tokens, and reparse this after we're done with the class. */ - const bool literal_p - = ((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER) - || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD)) - && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN)); - if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN) + if ((flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN) /* No need to delay parsing for a number literal or true/false. */ - && !literal_p + && !((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER) + || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD)) + && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN)) && at_class_scope_p () - /* We don't delay parsing for friend member functions, - alias-declarations, and typedefs, even though the standard seems - to require it. */ - && (flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT) && TYPE_BEING_DEFINED (current_class_type) && !LAMBDA_TYPE_P (current_class_type)) return cp_parser_save_noexcept (parser); diff --git i/gcc/cp/tree.c w/gcc/cp/tree.c index 3087c4ab52c..7e763479f7a 100644 --- i/gcc/cp/tree.c +++ w/gcc/cp/tree.c @@ -2676,6 +2676,52 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier rqual, return v; } +/* TYPE is a function or method type with a deferred exception + specification that has been parsed to RAISES. Fixup all the type + variants that are affected in place. Via decltype &| noexcept + tricks, the unparsed spec could have escaped into the type system. + The general case is hard to fixup canonical types for. */ + +void +fixup_deferred_exception_variants (tree type, tree raises) +{ + tree original = TYPE_RAISES_EXCEPTIONS (type); + tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE; + + gcc_checking_assert (TREE_CODE (TREE_PURPOSE (original)) + == DEFERRED_PARSE); + + /* Though sucky, this walk will process the canonical variants + first. */ + for (tree variant = TYPE_MAIN_VARIANT (type); + variant; variant = TYPE_NEXT_VARIANT (variant)) + if (TYPE_RAISES_EXCEPTIONS (variant) == original) + { + gcc_checking_assert (variant != TYPE_MAIN_VARIANT (type)); + + if (!TYPE_STRUCTURAL_EQUALITY_P (variant)) + { + cp_cv_quals var_quals = TYPE_QUALS (variant); + cp_ref_qualifier rqual = type_memfn_rqual (variant); + + tree v = TYPE_MAIN_VARIANT (type); + for (; v; v = TYPE_NEXT_VARIANT (v)) + if (TYPE_CANONICAL (v) == v + && cp_check_qualified_type (v, variant, var_quals, + rqual, cr, false)) + break; + TYPE_RAISES_EXCEPTIONS (variant) = raises; + + if (!v) + v = build_cp_fntype_variant (TYPE_CANONICAL (variant), + rqual, cr, false); + TYPE_CANONICAL (variant) = v; + } + else + TYPE_RAISES_EXCEPTIONS (variant) = raises; + } +} + /* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions listed in RAISES. */