From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 88059 invoked by alias); 28 May 2019 15:47:00 -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 87715 invoked by uid 89); 28 May 2019 15:46:59 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.1 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=Coming, throwing, error_mark_node X-HELO: mail-vs1-f68.google.com Received: from mail-vs1-f68.google.com (HELO mail-vs1-f68.google.com) (209.85.217.68) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 28 May 2019 15:46:57 +0000 Received: by mail-vs1-f68.google.com with SMTP id y6so492224vsb.0 for ; Tue, 28 May 2019 08:46:57 -0700 (PDT) Return-Path: Received: from [192.168.1.116] (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 d5sm8600782vka.34.2019.05.28.08.46.54 (version=TLS1_3 cipher=AEAD-AES128-GCM-SHA256 bits=128/128); Tue, 28 May 2019 08:46:54 -0700 (PDT) Subject: Re: C++ PATCH to implement deferred parsing of noexcept-specifiers (c++/86476, c++/52869) To: Marek Polacek Cc: GCC Patches References: <20181219202731.GL21364@redhat.com> <90c62261-b25e-0611-696d-044d319571cc@redhat.com> <20190510192133.GC20687@redhat.com> From: Jason Merrill Message-ID: <2a193c49-75c7-4407-1f1f-3748a69ab560@redhat.com> Date: Tue, 28 May 2019 15:48:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <20190510192133.GC20687@redhat.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2019-05/txt/msg01840.txt.bz2 On 5/10/19 3:21 PM, Marek Polacek wrote: > Coming back to this. I didn't think this was suitable for GCC 9. > > On Mon, Jan 07, 2019 at 10:44:37AM -0500, Jason Merrill wrote: >> On 12/19/18 3:27 PM, Marek Polacek wrote: >>> Prompted by Jon's observation in 52869, I noticed that we don't treat >>> a noexcept-specifier as a complete-class context of a class ([class.mem]/6). >>> As with member function bodies, default arguments, and NSDMIs, names used in >>> a noexcept-specifier of a member-function can be declared later in the class >>> body, so we need to wait and parse them at the end of the class. >>> For that, I've made use of DEFAULT_ARG (now best to be renamed to UNPARSED_ARG). >> >> Or DEFERRED_PARSE, yes. > > I didn't change the name but I'm happy to do it as a follow up. > >>> + /* We can't compare unparsed noexcept-specifiers. Save the old decl >>> + and check this again after we've parsed the noexcept-specifiers >>> + for real. */ >>> + if (UNPARSED_NOEXCEPT_SPEC_P (new_exceptions)) >>> + { >>> + vec_safe_push (DEFARG_INSTANTIATIONS (TREE_PURPOSE (new_exceptions)), >>> + copy_decl (old_decl)); >>> + return; >>> + } >> >> Why copy_decl? > > This is so that we don't lose the diagnostic in noexcept46.C. If I don't use > copy_decl then the tree is shared and subsequent changes to it make us not > detect discrepancies like noexcept(false) vs. noexcept(true) on the same decl. OK, fair enough. > @@ -20515,7 +20524,13 @@ cp_parser_init_declarator (cp_parser* parser, > /*asmspec=*/NULL_TREE, > attr_chainon (attributes, prefix_attributes)); > if (decl && TREE_CODE (decl) == FUNCTION_DECL) > - cp_parser_save_default_args (parser, decl); > + { > + cp_parser_save_default_args (parser, decl); > + /* Remember if there is a noexcept-specifier to post process. */ > + tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)); > + if (UNPARSED_NOEXCEPT_SPEC_P (spec)) > + vec_safe_push (unparsed_noexcepts, decl); Can we handle this in cp_parser_save_default_args rather than all its callers? > +/* Make sure that any member-function parameters are in scope. > + For instance, a function's noexcept-specifier can use the function's > + parameters: > + > + struct S { > + void fn (int p) noexcept(noexcept(p)); > + }; > + > + so we need to make sure name lookup can find them. This is used > + when we delay parsing of the noexcept-specifier. */ > + > +static void > +inject_parm_decls (tree decl) > +{ > + begin_scope (sk_function_parms, decl); > + tree args = DECL_ARGUMENTS (decl); > + args = nreverse (args); > + > + tree next; > + for (tree parm = args; parm; parm = next) > + { > + next = DECL_CHAIN (parm); > + if (TREE_CODE (parm) == PARM_DECL) > + pushdecl (parm); > + } > + /* Get the decls in their original chain order and record in the > + function. This is all and only the PARM_DECLs that were > + pushed into scope by the loop above. */ > + DECL_ARGUMENTS (decl) = get_local_decls (); > +} Can we share this code with store_parm_decls instead of having two copies? > @@ -25227,6 +25431,18 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, > + /* [class.mem]/6 says that a noexcept-specifer (within the > + member-specification of the class) is a complete-class context of > + 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. */ > + if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_PAREN > + && at_class_scope_p () > + && TYPE_BEING_DEFINED (current_class_type) > + && !LAMBDA_TYPE_P (current_class_type)) > + return cp_parser_save_noexcept (parser); We might optimize the noexcept() case, which should be pretty common. > +maybe_check_throw_specifier (tree overrider, tree basefn) maybe_check_overriding_exception_spec > diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c > index df002a1664c..8cbc48fb44f 100644 > --- gcc/cp/typeck2.c > +++ gcc/cp/typeck2.c > @@ -2393,6 +2393,12 @@ merge_exception_specifiers (tree list, tree add) > if (list == error_mark_node || add == error_mark_node) > return error_mark_node; > > + /* We don't want to lose the unparsed operand lest we miss diagnostics. */ > + if (UNPARSED_NOEXCEPT_SPEC_P (list)) > + return list; > + else if (UNPARSED_NOEXCEPT_SPEC_P (add)) > + return add; Here you're throwing away the other side, which seems wrong. Jason