From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gnu.wildebeest.org (wildebeest.demon.nl [212.238.236.112]) by sourceware.org (Postfix) with ESMTPS id 87A4E385C411 for ; Mon, 9 Aug 2021 14:24:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 87A4E385C411 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=klomp.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=klomp.org Received: from reform (unknown [83.162.57.182]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id 8790D30291A9; Mon, 9 Aug 2021 16:24:51 +0200 (CEST) Received: by reform (Postfix, from userid 1000) id F35FE2E80641; Mon, 9 Aug 2021 16:24:47 +0200 (CEST) Date: Mon, 9 Aug 2021 16:24:47 +0200 From: Mark Wielaard To: Philip Herron Cc: gcc-rust@gcc.gnu.org Subject: Re: [PATCH] Pass pratt parsed token to expr parser functions to fix expr locus Message-ID: References: <20210728221342.77649-1-mark@klomp.org> <01C0429E-15F9-45A7-B800-400EEBDF13CD@gmail.com> <9c9db19145176d664a6e944c1ff7108ce61215ae.camel@klomp.org> <87r1fh9mhx.fsf@euler.schwinge.homeip.net> <32bcf8f9-881e-d57f-470e-5f48fe78e200@embecosm.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="vqdMcMVc/POrF+Lr" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-rust@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: gcc-rust mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Aug 2021 14:24:57 -0000 --vqdMcMVc/POrF+Lr Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, On Sat, Aug 07, 2021 at 03:01:39AM +0200, Mark Wielaard wrote: > > Sorry for lack of reply on this. After looking into this and also > > getting Arthur Cohen to review, I think: > > > > * Token passing: If we end up using the token for more than the > > location this might be useful but at present I can't think of a > > use-case for the token. If we do need it maybe we could look into > > passing it by reference. > > * Location passing: I think this is the best solution and is directly > > associated with the issue you have fixed. The function says that you > > can call me but tell me the location as well so its up to the caller > > to handle this. We should add a comment to the function prototypes > > to say what the location is but that's it. > > > > What do you think? > > OK, lets go with the location passing. I added a comment to the > function prototypes in rust-parse.h about the passed in > pratt_parsed_token. > > https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-token Looks like I said I'll do B, then did A anyway... duh. Sorry. Here is the patch as I said I would do it, also on this branch, rebased against upstream: https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-loc Cheers, Mark --vqdMcMVc/POrF+Lr Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0001-Pass-pratt-parsed-location-to-expr-parser-functions-.patch" Content-Transfer-Encoding: 8bit >From 5b0bbf4509776b5ce3e5f82b8365f62110f91641 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 29 Jul 2021 00:00:55 +0200 Subject: [PATCH] Pass pratt parsed location to expr parser functions to fix expr locus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pratt parser skips the first token of an expression before invoking the actual expression parsing function. This makes getting the correct starting location of a pratt parsed expression hard. The "correction" of the location by subtracting an integer is often wrong (since there may be arbitrary whitespace or comments between tokens). Fix this by passing the location of the skipped token to the expression parsing functions (instead of just providing a pratt_parse boolean). Use this location to set the start of the expression (and as indicator to not try to parse the first token of the expression). Before gccrs would generate the following error message: return.rs:3:22: error: cannot ‘break’ outside of a loop 3 | let x = 5 - break return (16 + 2); | ^~~~~~~~~~~~~~~~~ Now we get: return.rs:3:17: error: cannot ‘break’ outside of a loop 3 | let x = 5 - break return (16 + 2); | ^ --- gcc/rust/parse/rust-parse-impl.h | 177 +++++++++++-------------------- gcc/rust/parse/rust-parse.h | 72 ++++++++----- 2 files changed, 104 insertions(+), 145 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index ccfff841784..c94c637e45c 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -6586,7 +6586,7 @@ Parser::parse_path_expr_segment () template AST::QualifiedPathInExpression Parser::parse_qualified_path_in_expression ( - bool pratt_parse) + Location pratt_parsed_loc) { /* Note: the Rust grammar is defined in such a way that it is impossible to * determine whether a prospective qualified path is a @@ -6601,7 +6601,7 @@ Parser::parse_qualified_path_in_expression ( // parse the qualified path type (required) AST::QualifiedPathType qual_path_type - = parse_qualified_path_type (pratt_parse); + = parse_qualified_path_type (pratt_parsed_loc); if (qual_path_type.is_error ()) { // TODO: should this create a parse error? @@ -6667,12 +6667,13 @@ Parser::parse_qualified_path_in_expression ( // Parses the type syntactical construction at the start of a qualified path. template AST::QualifiedPathType -Parser::parse_qualified_path_type (bool pratt_parse) +Parser::parse_qualified_path_type ( + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); + Location locus = pratt_parsed_loc; /* TODO: should this actually be error? is there anywhere where this could be * valid? */ - if (!pratt_parse) + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); if (!skip_token (LEFT_ANGLE)) @@ -6681,11 +6682,6 @@ Parser::parse_qualified_path_type (bool pratt_parse) return AST::QualifiedPathType::create_error (); } } - else - { - // move back by 1 if pratt parsing due to skipping '<' - locus = lexer.peek_token ()->get_locus () - 1; - } // parse type (required) std::unique_ptr type = parse_type (); @@ -7311,10 +7307,10 @@ Parser::parse_expr_without_block (AST::AttrVec outer_attrs) template std::unique_ptr Parser::parse_block_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); if (!skip_token (LEFT_CURLY)) @@ -7323,10 +7319,6 @@ Parser::parse_block_expr (AST::AttrVec outer_attrs, return nullptr; } } - else - { - locus = lexer.peek_token ()->get_locus () - 1; - } AST::AttrVec inner_attrs = parse_inner_attributes (); @@ -7618,21 +7610,14 @@ Parser::parse_literal_expr (AST::AttrVec outer_attrs) template std::unique_ptr Parser::parse_return_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); - skip_token (RETURN_TOK); } - else - { - // minus 7 chars for 6 in return and a space - // or just TODO: pass in location data - locus = lexer.peek_token ()->get_locus () - 7; - } // parse expression to return, if it exists ParseRestrictions restrictions; @@ -7650,21 +7635,14 @@ Parser::parse_return_expr (AST::AttrVec outer_attrs, template std::unique_ptr Parser::parse_break_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); - skip_token (BREAK); } - else - { - // minus 6 chars for 5 in return and a space - // or just TODO: pass in location data - locus = lexer.peek_token ()->get_locus () - 6; - } // parse label (lifetime) if it exists - create dummy first AST::Lifetime label = AST::Lifetime::error (); @@ -7688,21 +7666,14 @@ Parser::parse_break_expr (AST::AttrVec outer_attrs, template std::unique_ptr Parser::parse_continue_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); - skip_token (CONTINUE); } - else - { - // minus 9 chars for 8 in return and a space - // or just TODO: pass in location data - locus = lexer.peek_token ()->get_locus () - 9; - } // parse label (lifetime) if it exists - create dummy first AST::Lifetime label = AST::Lifetime::error (); @@ -7746,11 +7717,11 @@ Parser::parse_loop_label () template std::unique_ptr Parser::parse_if_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { // TODO: make having outer attributes an error? - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); if (!skip_token (IF)) @@ -7759,10 +7730,6 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, return nullptr; } } - else - { - locus = lexer.peek_token ()->get_locus () - 1; - } // detect accidental if let if (lexer.peek_token ()->get_id () == LET) @@ -7908,11 +7875,11 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, template std::unique_ptr Parser::parse_if_let_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { // TODO: make having outer attributes an error? - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); if (!skip_token (IF)) @@ -7921,10 +7888,6 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, return nullptr; } } - else - { - locus = lexer.peek_token ()->get_locus () - 1; - } // detect accidental if expr parsed as if let expr if (lexer.peek_token ()->get_id () != LET) @@ -8100,10 +8063,10 @@ template std::unique_ptr Parser::parse_loop_expr (AST::AttrVec outer_attrs, AST::LoopLabel label, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { if (label.is_error ()) locus = lexer.peek_token ()->get_locus (); @@ -8118,9 +8081,7 @@ Parser::parse_loop_expr (AST::AttrVec outer_attrs, } else { - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus () - 1; - else + if (!label.is_error ()) locus = label.get_locus (); } @@ -8146,10 +8107,10 @@ template std::unique_ptr Parser::parse_while_loop_expr (AST::AttrVec outer_attrs, AST::LoopLabel label, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { if (label.is_error ()) locus = lexer.peek_token ()->get_locus (); @@ -8164,9 +8125,7 @@ Parser::parse_while_loop_expr (AST::AttrVec outer_attrs, } else { - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus () - 1; - else + if (!label.is_error ()) locus = label.get_locus (); } @@ -8423,21 +8382,14 @@ Parser::parse_labelled_loop_expr (AST::AttrVec outer_attrs) template std::unique_ptr Parser::parse_match_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); - skip_token (MATCH_TOK); } - else - { - // TODO: probably just pass in location data as param - // get current pos then move back 6 - 5 for match, 1 for space - locus = lexer.peek_token ()->get_locus () - 6; - } /* parse scrutinee expression, which is required (and HACK to prevent struct * expr) */ @@ -8711,16 +8663,14 @@ Parser::parse_async_block_expr (AST::AttrVec outer_attrs) template std::unique_ptr Parser::parse_unsafe_block_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus; - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); skip_token (UNSAFE); } - else - locus = lexer.peek_token ()->get_locus () - 1; // parse block expression (required) std::unique_ptr block_expr = parse_block_expr (); @@ -8744,19 +8694,14 @@ Parser::parse_unsafe_block_expr (AST::AttrVec outer_attrs, template std::unique_ptr Parser::parse_array_expr (AST::AttrVec outer_attrs, - bool pratt_parse) + Location pratt_parsed_loc) { - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); - skip_token (LEFT_SQUARE); } - else - { - locus = lexer.peek_token ()->get_locus () - 1; - } // parse optional inner attributes AST::AttrVec inner_attrs = parse_inner_attributes (); @@ -8933,20 +8878,15 @@ Parser::parse_closure_param () template std::unique_ptr Parser::parse_grouped_or_tuple_expr ( - AST::AttrVec outer_attrs, bool pratt_parse) + AST::AttrVec outer_attrs, Location pratt_parsed_loc) { // adjustment to allow Pratt parsing to reuse function without copy-paste - Location locus = Linemap::unknown_location (); - if (!pratt_parse) + Location locus = pratt_parsed_loc; + if (locus == Linemap::unknown_location ()) { locus = lexer.peek_token ()->get_locus (); - skip_token (LEFT_PAREN); } - else - { - locus = lexer.peek_token ()->get_locus () - 1; - } // parse optional inner attributes AST::AttrVec inner_attrs = parse_inner_attributes (); @@ -12541,7 +12481,7 @@ Parser::null_denotation (const_TokenPtr tok, // qualified path // HACK: add outer attrs to path AST::QualifiedPathInExpression path - = parse_qualified_path_in_expression (true); + = parse_qualified_path_in_expression (tok->get_locus ()); path.set_outer_attrs (std::move (outer_attrs)); return std::unique_ptr ( new AST::QualifiedPathInExpression (std::move (path))); @@ -12584,7 +12524,8 @@ Parser::null_denotation (const_TokenPtr tok, new AST::LiteralExpr ("false", AST::Literal::BOOL, tok->get_type_hint (), {}, tok->get_locus ())); case LEFT_PAREN: - return parse_grouped_or_tuple_expr (std::move (outer_attrs), true); + return parse_grouped_or_tuple_expr (std::move (outer_attrs), + tok->get_locus ()); /*case PLUS: { // unary plus operator // invoke parse_expr recursively with appropriate priority, etc. for @@ -12816,41 +12757,43 @@ Parser::null_denotation (const_TokenPtr tok, return parse_range_to_inclusive_expr (tok, std::move (outer_attrs)); case RETURN_TOK: // FIXME: is this really a null denotation expression? - return parse_return_expr (std::move (outer_attrs), true); + return parse_return_expr (std::move (outer_attrs), tok->get_locus ()); case BREAK: // FIXME: is this really a null denotation expression? - return parse_break_expr (std::move (outer_attrs), true); + return parse_break_expr (std::move (outer_attrs), tok->get_locus ()); case CONTINUE: - return parse_continue_expr (std::move (outer_attrs), true); + return parse_continue_expr (std::move (outer_attrs), tok->get_locus ()); case LEFT_CURLY: // ok - this is an expression with block for once. - return parse_block_expr (std::move (outer_attrs), true); + return parse_block_expr (std::move (outer_attrs), tok->get_locus ()); case IF: // if or if let, so more lookahead to find out if (lexer.peek_token (1)->get_id () == LET) { // if let expr - return parse_if_let_expr (std::move (outer_attrs), true); + return parse_if_let_expr (std::move (outer_attrs), tok->get_locus ()); } else { // if expr - return parse_if_expr (std::move (outer_attrs), true); + return parse_if_expr (std::move (outer_attrs), tok->get_locus ()); } case LOOP: return parse_loop_expr (std::move (outer_attrs), AST::LoopLabel::error (), - true); + tok->get_locus ()); case WHILE: return parse_while_loop_expr (std::move (outer_attrs), - AST::LoopLabel::error (), true); + AST::LoopLabel::error (), + tok->get_locus ()); case MATCH_TOK: // also an expression with block - return parse_match_expr (std::move (outer_attrs), true); + return parse_match_expr (std::move (outer_attrs), tok->get_locus ()); case LEFT_SQUARE: // array definition expr (not indexing) - return parse_array_expr (std::move (outer_attrs), true); + return parse_array_expr (std::move (outer_attrs), tok->get_locus ()); case UNSAFE: - return parse_unsafe_block_expr (std::move (outer_attrs), true); + return parse_unsafe_block_expr (std::move (outer_attrs), + tok->get_locus ()); default: if (!restrictions.expr_can_be_null) add_error (Error (tok->get_locus (), diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 3920893faf6..86e0d2a6f83 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -121,8 +121,14 @@ private: AST::PathInExpression parse_path_in_expression (); AST::PathExprSegment parse_path_expr_segment (); AST::QualifiedPathInExpression - parse_qualified_path_in_expression (bool pratt_parse = false); - AST::QualifiedPathType parse_qualified_path_type (bool pratt_parse = false); + // When given a pratt_parsed_loc, use it as the location of the + // first token parsed in the expression (the parsing of that first + // token should be skipped). + parse_qualified_path_in_expression (Location pratt_parsed_loc + = Linemap::unknown_location ()); + AST::QualifiedPathType + parse_qualified_path_type (Location pratt_parsed_loc + = Linemap::unknown_location ()); AST::QualifiedPathInType parse_qualified_path_in_type (); // Token tree or macro related @@ -469,32 +475,36 @@ private: parse_expr_with_block (AST::AttrVec outer_attrs); std::unique_ptr parse_expr_without_block (AST::AttrVec outer_attrs = AST::AttrVec ()); - std::unique_ptr parse_block_expr (AST::AttrVec outer_attrs - = AST::AttrVec (), - bool pratt_parse = false); - std::unique_ptr parse_if_expr (AST::AttrVec outer_attrs - = AST::AttrVec (), - bool pratt_parse = false); - std::unique_ptr parse_if_let_expr (AST::AttrVec outer_attrs - = AST::AttrVec (), - bool pratt_parse = false); + // When given a pratt_parsed_loc, use it as the location of the + // first token parsed in the expression (the parsing of that first + // token should be skipped). + std::unique_ptr + parse_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + Location pratt_parsed_loc = Linemap::unknown_location ()); + std::unique_ptr + parse_if_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + Location pratt_parsed_loc = Linemap::unknown_location ()); + std::unique_ptr + parse_if_let_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + Location pratt_parsed_loc = Linemap::unknown_location ()); std::unique_ptr parse_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), AST::LoopLabel label = AST::LoopLabel::error (), - bool pratt_parse = false); + Location pratt_parsed_loc = Linemap::unknown_location ()); std::unique_ptr parse_while_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), AST::LoopLabel label = AST::LoopLabel::error (), - bool pratt_parse = false); + Location pratt_parsed_loc + = Linemap::unknown_location ()); std::unique_ptr parse_while_let_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), AST::LoopLabel label = AST::LoopLabel::error ()); std::unique_ptr parse_for_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), AST::LoopLabel label = AST::LoopLabel::error ()); - std::unique_ptr parse_match_expr (AST::AttrVec outer_attrs - = AST::AttrVec (), - bool pratt_parse = false); + std::unique_ptr + parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + Location pratt_parsed_loc = Linemap::unknown_location ()); AST::MatchArm parse_match_arm (); std::vector > parse_match_arm_patterns (TokenId end_token_id); @@ -510,24 +520,30 @@ private: AST::ClosureParam parse_closure_param (); std::unique_ptr parse_literal_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); - std::unique_ptr parse_return_expr (AST::AttrVec outer_attrs - = AST::AttrVec (), - bool pratt_parse = false); - std::unique_ptr parse_break_expr (AST::AttrVec outer_attrs - = AST::AttrVec (), - bool pratt_parse = false); + // When given a pratt_parsed_loc, use it as the location of the + // first token parsed in the expression (the parsing of that first + // token should be skipped). + std::unique_ptr + parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + Location pratt_parsed_loc = Linemap::unknown_location ()); + std::unique_ptr + parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + Location pratt_parsed_loc = Linemap::unknown_location ()); std::unique_ptr parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - bool pratt_parse = false); + Location pratt_parsed_loc + = Linemap::unknown_location ()); std::unique_ptr parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - bool pratt_parse = false); - std::unique_ptr parse_array_expr (AST::AttrVec outer_attrs - = AST::AttrVec (), - bool pratt_parse = false); + Location pratt_parsed_loc + = Linemap::unknown_location ()); + std::unique_ptr + parse_array_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + Location pratt_parsed_loc = Linemap::unknown_location ()); std::unique_ptr parse_grouped_or_tuple_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - bool pratt_parse = false); + Location pratt_parsed_loc + = Linemap::unknown_location ()); std::unique_ptr parse_struct_expr_field (); bool will_be_expr_with_block (); -- 2.32.0 --vqdMcMVc/POrF+Lr--