From patchwork Tue Aug 1 20:21:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 796363 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-459553-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="twXDp+BD"; 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 3xMRgM574Hz9sNV for ; Wed, 2 Aug 2017 05:47:43 +1000 (AEST) 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:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=Zwq8FMJjD37JrOMJj50Dkl1MxGXpajidRE8NgX1PmX6dtJov9VI3p Nydj0ylaJ/L8JSF2N0pGHB+YxEjf/aVW+TqVFcWY4YfZeaqQr9TTU7J4UZw+deSX hCLmXr1Vi3Qd9/Ld55GsZKmffNbLgHypCvAcPtijl2ZCfo+Pd6wSWk= 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:cc:subject:date:message-id:in-reply-to:references; s= default; bh=qCOZEVIuvLHMDx5vjMT77JCkTms=; b=twXDp+BDRtLSFH/1VhlA ZiC9L6uh8qwanHHb7nZnzrtF5CdK5QREPMbdR1vfSoaaWQsbdvHbrAhWvaFdEd7n NRBTjYxwpKt7D1FmLkHWjsnPhA0ifXIWHppihSBEZZtQ2E3uioMpoBEdiDevZr/u Kd2lp77QoskHJOWGypHNSe0= Received: (qmail 37211 invoked by alias); 1 Aug 2017 19:47:16 -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 36980 invoked by uid 89); 1 Aug 2017 19:47:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=spelling, msgid X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 01 Aug 2017 19:47:05 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DAC6AAACC0; Tue, 1 Aug 2017 19:47:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com DAC6AAACC0 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dmalcolm@redhat.com Received: from c64.redhat.com (ovpn-112-25.phx2.redhat.com [10.3.112.25]) by smtp.corp.redhat.com (Postfix) with ESMTP id 83EF817D5F; Tue, 1 Aug 2017 19:47:02 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: Trevor Saunders , David Malcolm Subject: [PATCH 2/3] Matching tokens: C parts (v2) Date: Tue, 1 Aug 2017 16:21:43 -0400 Message-Id: <1501618904-5593-3-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1501618904-5593-1-git-send-email-dmalcolm@redhat.com> References: <20170712131300.u3ofifbzkp52lcxa@ball> <1501618904-5593-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes Changed in v2: * Renamed template argument to traits_t; eliminated subclasses, just using traits struct. * Moved enum constants into struct bodies (string constants can't be without constexpr, which isn't available in C++98). * Fixed typo. OK for trunk? gcc/c/ChangeLog: * c-parser.c (c_parser_error): Rename to... (c_parser_error_richloc): ...this, making static, and adding "richloc" parameter, passing it to the c_parse_error call, rather than calling c_parser_set_source_position_from_token. (c_parser_error): Reintroduce, reimplementing in terms of the above, converting return type from void to bool. (class token_pair): New class. (struct matching_paren_traits): New struct. (matching_parens): New typedef. (struct matching_brace_traits): New struct. (matching_braces): New typedef. (get_matching_symbol): New function. (c_parser_require): Add param MATCHING_LOCATION, using it to highlight matching "opening" tokens for missing "closing" tokens. (c_parser_skip_until_found): Likewise. (c_parser_static_assert_declaration_no_semi): Convert explicit parsing of CPP_OPEN_PAREN and CPP_CLOSE_PAREN to use of class matching_parens, so that the pertinent open parenthesis is highlighted when there are problems locating the close parenthesis. (c_parser_struct_or_union_specifier): Likewise. (c_parser_typeof_specifier): Likewise. (c_parser_alignas_specifier): Likewise. (c_parser_simple_asm_expr): Likewise. (c_parser_braced_init): Likewise, for matching_braces. (c_parser_paren_condition): Likewise, for matching_parens. (c_parser_switch_statement): Likewise. (c_parser_for_statement): Likewise. (c_parser_asm_statement): Likewise. (c_parser_asm_operands): Likewise. (c_parser_cast_expression): Likewise. (c_parser_sizeof_expression): Likewise. (c_parser_alignof_expression): Likewise. (c_parser_generic_selection): Likewise. (c_parser_postfix_expression): Likewise for cases RID_VA_ARG, RID_OFFSETOF, RID_TYPES_COMPATIBLE_P, RID_AT_SELECTOR, RID_AT_PROTOCOL, RID_AT_ENCODE, reindenting as necessary. In case CPP_OPEN_PAREN, pass loc_open_paren to the c_parser_skip_until_found call. (c_parser_objc_class_definition): Use class matching_parens as above. (c_parser_objc_method_decl): Likewise. (c_parser_objc_try_catch_finally_statement): Likewise. (c_parser_objc_synchronized_statement): Likewise. (c_parser_objc_at_property_declaration): Likewise. (c_parser_oacc_wait_list): Likewise. (c_parser_omp_var_list_parens): Likewise. (c_parser_omp_clause_collapse): Likewise. (c_parser_omp_clause_default): Likewise. (c_parser_omp_clause_if): Likewise. (c_parser_omp_clause_num_threads): Likewise. (c_parser_omp_clause_num_tasks): Likewise. (c_parser_omp_clause_grainsize): Likewise. (c_parser_omp_clause_priority): Likewise. (c_parser_omp_clause_hint): Likewise. (c_parser_omp_clause_defaultmap): Likewise. (c_parser_oacc_single_int_clause): Likewise. (c_parser_omp_clause_ordered): Likewise. (c_parser_omp_clause_reduction): Likewise. (c_parser_omp_clause_schedule): Likewise. (c_parser_omp_clause_num_teams): Likewise. (c_parser_omp_clause_thread_limit): Likewise. (c_parser_omp_clause_aligned): Likewise. (c_parser_omp_clause_linear): Likewise. (c_parser_omp_clause_safelen): Likewise. (c_parser_omp_clause_simdlen): Likewise. (c_parser_omp_clause_depend): Likewise. (c_parser_omp_clause_map): Likewise. (c_parser_omp_clause_device): Likewise. (c_parser_omp_clause_dist_schedule): Likewise. (c_parser_omp_clause_proc_bind): Likewise. (c_parser_omp_clause_uniform): Likewise. (c_parser_omp_for_loop): Likewise. (c_parser_cilk_clause_vectorlength): Likewise. (c_parser_cilk_clause_linear): Likewise. (c_parser_transaction_expression): Likewise. * c-parser.h (c_parser_require): Add param matching_location with default UNKNOWN_LOCATION. (c_parser_error): Convert return type from void to bool. (c_parser_skip_until_found): Add param matching_location with default UNKNOWN_LOCATION. gcc/testsuite/ChangeLog: * gcc.dg/unclosed-init.c: New test case. --- gcc/c/c-parser.c | 644 +++++++++++++++++++++++------------ gcc/c/c-parser.h | 8 +- gcc/testsuite/gcc.dg/unclosed-init.c | 3 + 3 files changed, 438 insertions(+), 217 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/unclosed-init.c diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 16cd357..3803154 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -850,21 +850,26 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind, MESSAGE (specified by the caller) is usually of the form "expected OTHER-TOKEN". + Use RICHLOC as the location of the diagnostic. + Do not issue a diagnostic if still recovering from an error. + Return true iff an error was actually emitted. + ??? This is taken from the C++ parser, but building up messages in this way is not i18n-friendly and some other approach should be used. */ -void -c_parser_error (c_parser *parser, const char *gmsgid) +static bool +c_parser_error_richloc (c_parser *parser, const char *gmsgid, + rich_location *richloc) { c_token *token = c_parser_peek_token (parser); if (parser->error) - return; + return false; parser->error = true; if (!gmsgid) - return; + return false; /* If this is actually a conflict marker, report it as such. */ if (token->type == CPP_LSHIFT @@ -875,13 +880,10 @@ c_parser_error (c_parser *parser, const char *gmsgid) if (c_parser_peek_conflict_marker (parser, token->type, &loc)) { error_at (loc, "version control conflict marker in file"); - return; + return true; } } - /* This diagnostic makes more sense if it is tagged to the line of - the token we just peeked at. */ - c_parser_set_source_position_from_token (token); c_parse_error (gmsgid, /* Because c_parse_error does not understand CPP_KEYWORD, keywords are treated like @@ -891,18 +893,157 @@ c_parser_error (c_parser *parser, const char *gmsgid) token, we need to pass 0 here and we will not get the source spelling of some tokens but rather the canonical spelling. */ - token->value, /*flags=*/0); + token->value, /*flags=*/0, richloc); + return true; +} + +/* As c_parser_error_richloc, but issue the message at the + location of PARSER's next token, or at input_location + if the next token is EOF. */ + +bool +c_parser_error (c_parser *parser, const char *gmsgid) +{ + c_token *token = c_parser_peek_token (parser); + c_parser_set_source_position_from_token (token); + rich_location richloc (line_table, input_location); + return c_parser_error_richloc (parser, gmsgid, &richloc); +} + +/* Some tokens naturally come in pairs e.g.'(' and ')'. + This class is for tracking such a matching pair of symbols. + In particular, it tracks the location of the first token, + so that if the second token is missing, we can highlight the + location of the first token when notifying the user about the + problem. */ + +template +class token_pair +{ + public: + /* token_pair's ctor. */ + token_pair () : m_open_loc (UNKNOWN_LOCATION) {} + + /* If the next token is the opening symbol for this pair, consume it and + return true. + Otherwise, issue an error and return false. + In either case, record the location of the opening token. */ + + bool require_open (c_parser *parser) + { + c_token *token = c_parser_peek_token (parser); + if (token) + m_open_loc = token->location; + + return c_parser_require (parser, traits_t::open_token_type, + traits_t::open_gmsgid); + } + + /* Consume the next token from PARSER, recording its location as + that of the opening token within the pair. */ + + void consume_open (c_parser *parser) + { + c_token *token = c_parser_peek_token (parser); + gcc_assert (token->type == traits_t::open_token_type); + m_open_loc = token->location; + c_parser_consume_token (parser); + } + + /* If the next token is the closing symbol for this pair, consume it + and return true. + Otherwise, issue an error, highlighting the location of the + corresponding opening token, and return false. */ + + bool require_close (c_parser *parser) const + { + return c_parser_require (parser, traits_t::close_token_type, + traits_t::close_gmsgid, m_open_loc); + } + + /* Like token_pair::require_close, except that tokens will be skipped + until the desired token is found. An error message is still produced + if the next token is not as expected. */ + + void skip_until_found_close (c_parser *parser) const + { + c_parser_skip_until_found (parser, traits_t::close_token_type, + traits_t::close_gmsgid, m_open_loc); + } + + private: + location_t m_open_loc; +}; + +/* Traits for token_pair for tracking matching pairs of parentheses. */ + +struct matching_paren_traits +{ + static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN; + static const char * const open_gmsgid; + static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN; + static const char * const close_gmsgid; +}; + +const char * const matching_paren_traits::open_gmsgid = "expected %<(%>"; +const char * const matching_paren_traits::close_gmsgid = "expected %<)%>"; + +/* "matching_parens" is a token_pair class for tracking matching + pairs of parentheses. */ + +typedef token_pair matching_parens; + +/* Traits for token_pair for tracking matching pairs of braces. */ + +struct matching_brace_traits +{ + static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE; + static const char * const open_gmsgid; + static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE; + static const char * const close_gmsgid; +}; + +const char * const matching_brace_traits::open_gmsgid = "expected %<{%>"; +const char * const matching_brace_traits::close_gmsgid = "expected %<}%>"; + +/* "matching_braces" is a token_pair class for tracking matching + pairs of braces. */ + +typedef token_pair matching_braces; + +/* Get a description of the matching symbol to TYPE e.g. "(" for + CPP_CLOSE_PAREN. */ + +static const char * +get_matching_symbol (enum cpp_ttype type) +{ + switch (type) + { + default: + gcc_unreachable (); + return ""; + case CPP_CLOSE_PAREN: + return "("; + case CPP_CLOSE_BRACE: + return "{"; + } } /* If the next token is of the indicated TYPE, consume it. Otherwise, issue the error MSGID. If MSGID is NULL then a message has already been produced and no message will be produced this time. Returns - true if found, false otherwise. */ + true if found, false otherwise. + + If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it + within any error as the location of an "opening" token matching + the close token TYPE (e.g. the location of the '(' when TYPE is + CPP_CLOSE_PAREN). */ bool c_parser_require (c_parser *parser, enum cpp_ttype type, - const char *msgid) + const char *msgid, + location_t matching_location) { if (c_parser_next_token_is (parser, type)) { @@ -911,7 +1052,24 @@ c_parser_require (c_parser *parser, } else { - c_parser_error (parser, msgid); + location_t next_token_loc = c_parser_peek_token (parser)->location; + gcc_rich_location richloc (next_token_loc); + + /* If matching_location != UNKNOWN_LOCATION, highlight it. + Attempt to consolidate diagnostics by printing it as a + secondary range within the main diagnostic. */ + bool added_matching_location = false; + if (matching_location != UNKNOWN_LOCATION) + added_matching_location + = richloc.add_location_if_nearby (matching_location); + + if (c_parser_error_richloc (parser, msgid, &richloc)) + /* If we weren't able to consolidate matching_location, then + print it as a secondary diagnostic. */ + if (matching_location != UNKNOWN_LOCATION && !added_matching_location) + inform (matching_location, "to match this %qs", + get_matching_symbol (type)); + return false; } } @@ -940,16 +1098,22 @@ c_parser_require_keyword (c_parser *parser, desired token is found. An error message is still produced if the next token is not as expected. If MSGID is NULL then a message has already been produced and no message will be produced this - time. */ + time. + + If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it + within any error as the location of an "opening" token matching + the close token TYPE (e.g. the location of the '(' when TYPE is + CPP_CLOSE_PAREN). */ void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type, - const char *msgid) + const char *msgid, + location_t matching_location) { unsigned nesting_depth = 0; - if (c_parser_require (parser, type, msgid)) + if (c_parser_require (parser, type, msgid, matching_location)) return; /* Skip tokens until the desired token is found. */ @@ -2210,7 +2374,8 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) pedwarn_c99 (assert_loc, OPT_Wpedantic, "ISO C90 does not support %<_Static_assert%>"); c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return; location_t value_tok_loc = c_parser_peek_token (parser)->location; value = c_parser_expr_no_commas (parser, NULL).value; @@ -2237,7 +2402,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) parser->lex_untranslated_string = false; return; } - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (value))) { @@ -2922,7 +3087,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) tree name; gcc_assert (c_dialect_objc ()); c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) goto end_at_defs; if (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME) @@ -2936,8 +3102,7 @@ c_parser_struct_or_union_specifier (c_parser *parser) c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); goto end_at_defs; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); contents = nreverse (objc_get_class_ivars (name)); } end_at_defs: @@ -3224,7 +3389,8 @@ c_parser_typeof_specifier (c_parser *parser) c_parser_consume_token (parser); c_inhibit_evaluation_warnings++; in_typeof++; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { c_inhibit_evaluation_warnings--; in_typeof--; @@ -3265,7 +3431,7 @@ c_parser_typeof_specifier (c_parser *parser) if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec)) ret.spec = c_build_qualified_type (ret.spec, TYPE_UNQUALIFIED); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return ret; } @@ -3291,7 +3457,8 @@ c_parser_alignas_specifier (c_parser * parser) else pedwarn_c99 (loc, OPT_Wpedantic, "ISO C90 does not support %<_Alignas%>"); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return ret; if (c_parser_next_tokens_start_typename (parser, cla_prefer_id)) { @@ -3302,7 +3469,7 @@ c_parser_alignas_specifier (c_parser * parser) } else ret = c_parser_expr_no_commas (parser, NULL).value; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return ret; } @@ -3953,14 +4120,15 @@ c_parser_simple_asm_expr (c_parser *parser) lex_untranslated_string kludge. */ parser->lex_untranslated_string = true; c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { parser->lex_untranslated_string = false; return NULL_TREE; } str = c_parser_asm_string_literal (parser); parser->lex_untranslated_string = false; - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return NULL_TREE; @@ -4395,7 +4563,8 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, location_t brace_loc = c_parser_peek_token (parser)->location; gcc_obstack_init (&braced_init_obstack); gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE)); - c_parser_consume_token (parser); + matching_braces braces; + braces.consume_open (parser); if (nested_p) { finish_implicit_inits (brace_loc, outer_obstack); @@ -4433,7 +4602,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, ret.value = error_mark_node; ret.original_code = ERROR_MARK; ret.original_type = NULL; - c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>"); + braces.skip_until_found_close (parser); pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma); obstack_free (&braced_init_obstack, NULL); return ret; @@ -5456,10 +5625,11 @@ static tree c_parser_paren_condition (c_parser *parser) { tree cond; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return error_mark_node; cond = c_parser_condition (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return cond; } @@ -5728,7 +5898,8 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) c_parser_consume_token (parser); block = c_begin_compound_stmt (flag_isoc99); bool explicit_cast_p = false; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { switch_cond_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) @@ -5743,7 +5914,7 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) "%<_Cilk_spawn%> statement cannot be used as a condition for switch statement", switch_cond_loc)) expr = error_mark_node; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else { @@ -5953,7 +6124,8 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ()); cond = error_mark_node; incr = error_mark_node; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { /* Parse the initialization declaration or expression. */ object_expression = error_mark_node; @@ -6100,7 +6272,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) incr = c_process_expr_stmt (loc, ce.value); } } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } save_break = c_break_label; c_break_label = NULL_TREE; @@ -6194,7 +6366,8 @@ c_parser_asm_statement (c_parser *parser) parser->lex_untranslated_string = true; ret = NULL; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) goto error; str = c_parser_asm_string_literal (parser); @@ -6252,7 +6425,7 @@ c_parser_asm_statement (c_parser *parser) } done_asm: - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); goto error; @@ -6317,7 +6490,8 @@ c_parser_asm_operands (c_parser *parser) if (str == NULL_TREE) return NULL_TREE; parser->lex_untranslated_string = false; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { parser->lex_untranslated_string = true; return NULL_TREE; @@ -6325,7 +6499,7 @@ c_parser_asm_operands (c_parser *parser) expr = c_parser_expression (parser); mark_exp_read (expr.value); parser->lex_untranslated_string = true; - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return NULL_TREE; @@ -6934,9 +7108,10 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) struct c_type_name *type_name; struct c_expr ret; struct c_expr expr; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); type_name = c_parser_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (type_name == NULL) { ret.value = error_mark_node; @@ -7163,10 +7338,11 @@ c_parser_sizeof_expression (c_parser *parser) /* Either sizeof ( type-name ) or sizeof unary-expression starting with a compound literal. */ struct c_type_name *type_name; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); expr_loc = c_parser_peek_token (parser)->location; type_name = c_parser_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); finish = parser->tokens_buf[0].location; if (type_name == NULL) { @@ -7245,11 +7421,12 @@ c_parser_alignof_expression (c_parser *parser) location_t loc; struct c_type_name *type_name; struct c_expr ret; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); loc = c_parser_peek_token (parser)->location; type_name = c_parser_type_name (parser); end_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (type_name == NULL) { struct c_expr ret; @@ -7408,7 +7585,8 @@ c_parser_generic_selection (c_parser *parser) pedwarn_c99 (generic_loc, OPT_Wpedantic, "ISO C90 does not support %<_Generic%>"); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return error_expr; c_inhibit_evaluation_warnings++; @@ -7550,7 +7728,7 @@ c_parser_generic_selection (c_parser *parser) c_parser_consume_token (parser); } - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return error_expr; @@ -7796,7 +7974,7 @@ c_parser_postfix_expression (c_parser *parser) location_t loc_close_paren = c_parser_peek_token (parser)->location; set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + "expected %<)%>", loc_open_paren); } break; case CPP_KEYWORD: @@ -7833,7 +8011,8 @@ c_parser_postfix_expression (c_parser *parser) { location_t start_loc = loc; c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { expr.set_error (); break; @@ -7873,25 +8052,25 @@ c_parser_postfix_expression (c_parser *parser) } break; case RID_OFFSETOF: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - parser->error = true; - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - gcc_assert (parser->error); - if (parser->error) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.set_error (); - break; - } - { + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + parser->error = true; + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + gcc_assert (parser->error); + if (parser->error) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.set_error (); + break; + } tree type = groktypename (t1, NULL, NULL); tree offsetof_ref; if (type == error_mark_node) @@ -8008,34 +8187,34 @@ c_parser_postfix_expression (c_parser *parser) break; } case RID_TYPES_COMPATIBLE_P: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - { - expr.set_error (); - break; - } - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.set_error (); - break; - } - t2 = c_parser_type_name (parser); - if (t2 == NULL) - { - expr.set_error (); - break; - } { + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + { + expr.set_error (); + break; + } + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.set_error (); + break; + } + t2 = c_parser_type_name (parser); + if (t2 == NULL) + { + expr.set_error (); + break; + } location_t close_paren_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); tree e1, e2; e1 = groktypename (t1, NULL, NULL); e2 = groktypename (t2, NULL, NULL); @@ -8201,67 +8380,67 @@ c_parser_postfix_expression (c_parser *parser) break; } case RID_AT_SELECTOR: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } { + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } tree sel = c_parser_objc_selector_arg (parser); location_t close_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); expr.value = objc_build_selector_expr (loc, sel); set_c_expr_source_range (&expr, loc, close_loc); } break; case RID_AT_PROTOCOL: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.set_error (); - break; - } { + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.set_error (); + break; + } tree id = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); location_t close_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); expr.value = objc_build_protocol_expr (id); set_c_expr_source_range (&expr, loc, close_loc); } break; case RID_AT_ENCODE: - /* Extension to support C-structures in the archiver. */ - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - { - expr.set_error (); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - break; - } { + /* Extension to support C-structures in the archiver. */ + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + { + expr.set_error (); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + break; + } location_t close_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); tree type = groktypename (t1, NULL, NULL); expr.value = objc_build_encode_expr (type); set_c_expr_source_range (&expr, loc, close_loc); @@ -8854,7 +9033,8 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) /* We have a category or class extension. */ tree id2; tree proto = NULL_TREE; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) @@ -8874,7 +9054,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) id2 = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!iface_p) { objc_start_category_implementation (id1, id2); @@ -9408,9 +9588,10 @@ c_parser_objc_method_decl (c_parser *parser, bool is_class_method, *attributes = NULL_TREE; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); type = c_parser_objc_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } sel = c_parser_objc_selector (parser); /* If there is no selector, or a colon follows, we have an @@ -9616,7 +9797,8 @@ c_parser_objc_try_catch_finally_statement (c_parser *parser) bool seen_open_paren = false; c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) seen_open_paren = true; if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) { @@ -9639,7 +9821,7 @@ c_parser_objc_try_catch_finally_statement (c_parser *parser) parameter_declaration = grokparm (parm, NULL); } if (seen_open_paren) - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); else { /* If there was no open parenthesis, we are recovering from @@ -9688,13 +9870,14 @@ c_parser_objc_synchronized_statement (c_parser *parser) c_parser_consume_token (parser); loc = c_parser_peek_token (parser)->location; objc_maybe_warn_exceptions (loc); - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { struct c_expr ce = c_parser_expression (parser); ce = convert_lvalue_to_rvalue (loc, ce, false, false); expr = ce.value; expr = c_fully_fold (expr, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else expr = error_mark_node; @@ -9988,9 +10171,11 @@ c_parser_objc_at_property_declaration (c_parser *parser) /* Parse the optional attribute list... */ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { + matching_parens parens; + /* Eat the '(' */ - c_parser_consume_token (parser); - + parens.consume_open (parser); + /* Property attribute keywords are valid now. */ parser->objc_property_attr_context = true; @@ -10078,7 +10263,7 @@ c_parser_objc_at_property_declaration (c_parser *parser) break; } parser->objc_property_attr_context = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } /* ... and the property declaration(s). */ properties = c_parser_struct_declaration (parser); @@ -10738,7 +10923,8 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list) vec *args; tree t, args_tree; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; args = c_parser_expr_list (parser, false, true, NULL, NULL, NULL, NULL); @@ -10775,7 +10961,7 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list) } release_tree_vector (args); - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); return list; } @@ -10933,10 +11119,11 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, /* The clauses location. */ location_t loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { list = c_parser_omp_variable_list (parser, loc, kind, list); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } return list; } @@ -11073,10 +11260,11 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list) check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile"); loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { num = c_parser_expr_no_commas (parser, NULL).value; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } if (num == error_mark_node) return list; @@ -11128,7 +11316,8 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc) location_t loc = c_parser_peek_token (parser)->location; tree c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -11168,7 +11357,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc) else c_parser_error (parser, "expected % or %"); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED) return list; @@ -11231,7 +11420,8 @@ c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp) location_t location = c_parser_peek_token (parser)->location; enum tree_code if_modifier = ERROR_MARK; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (is_omp && c_parser_next_token_is (parser, CPP_NAME)) @@ -11312,7 +11502,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp) } tree t = c_parser_condition (parser), c; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF) @@ -11411,7 +11601,8 @@ static tree c_parser_omp_clause_num_threads (c_parser *parser, tree list) { location_t num_threads_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11419,7 +11610,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11456,7 +11647,8 @@ static tree c_parser_omp_clause_num_tasks (c_parser *parser, tree list) { location_t num_tasks_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11464,7 +11656,7 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11501,7 +11693,8 @@ static tree c_parser_omp_clause_grainsize (c_parser *parser, tree list) { location_t grainsize_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11509,7 +11702,7 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11546,7 +11739,8 @@ static tree c_parser_omp_clause_priority (c_parser *parser, tree list) { location_t priority_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11554,7 +11748,7 @@ c_parser_omp_clause_priority (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11592,7 +11786,8 @@ static tree c_parser_omp_clause_hint (c_parser *parser, tree list) { location_t hint_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11600,7 +11795,7 @@ c_parser_omp_clause_hint (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11629,7 +11824,8 @@ c_parser_omp_clause_defaultmap (c_parser *parser, tree list) tree c; const char *p; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!c_parser_next_token_is (parser, CPP_NAME)) { @@ -11657,14 +11853,14 @@ c_parser_omp_clause_defaultmap (c_parser *parser, tree list) goto out_err; } c_parser_consume_token (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULTMAP, "defaultmap"); c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP); OMP_CLAUSE_CHAIN (c) = list; return c; out_err: - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -11701,7 +11897,8 @@ c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code, { location_t loc = c_parser_peek_token (parser)->location; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; location_t expr_loc = c_parser_peek_token (parser)->location; @@ -11710,7 +11907,7 @@ c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code, tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (t == error_mark_node) return list; @@ -12040,9 +12237,10 @@ c_parser_omp_clause_ordered (c_parser *parser, tree list) location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); num = c_parser_expr_no_commas (parser, NULL).value; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } if (num == error_mark_node) return list; @@ -12096,7 +12294,8 @@ static tree c_parser_omp_clause_reduction (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { enum tree_code code = ERROR_MARK; tree reduc_id = NULL_TREE; @@ -12194,7 +12393,7 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list) list = nl; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } return list; } @@ -12222,7 +12421,8 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) location_t loc = c_parser_peek_token (parser)->location; int modifiers = 0, nmodifiers = 0; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE); @@ -12333,7 +12533,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) else c_parser_error (parser, "expected integer expression"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, @@ -12446,7 +12646,8 @@ static tree c_parser_omp_clause_num_teams (c_parser *parser, tree list) { location_t num_teams_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -12454,7 +12655,7 @@ c_parser_omp_clause_num_teams (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -12490,7 +12691,8 @@ static tree c_parser_omp_clause_thread_limit (c_parser *parser, tree list) { location_t num_thread_limit_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -12498,7 +12700,7 @@ c_parser_omp_clause_thread_limit (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -12538,7 +12740,8 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list) location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; nl = c_parser_omp_variable_list (parser, clause_loc, @@ -12565,7 +12768,7 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list) OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; } @@ -12584,7 +12787,8 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) tree nl, c, step; enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!is_cilk_simd_fn @@ -12607,7 +12811,7 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) OMP_CLAUSE_LINEAR, list); if (kind != OMP_CLAUSE_LINEAR_DEFAULT) - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -12639,7 +12843,7 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) OMP_CLAUSE_LINEAR_KIND (c) = kind; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; } @@ -12652,7 +12856,8 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list) location_t clause_loc = c_parser_peek_token (parser)->location; tree c, t; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; location_t expr_loc = c_parser_peek_token (parser)->location; @@ -12669,7 +12874,7 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list) t = NULL_TREE; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (t == NULL_TREE || t == error_mark_node) return list; @@ -12690,7 +12895,8 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list) location_t clause_loc = c_parser_peek_token (parser)->location; tree c, t; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; location_t expr_loc = c_parser_peek_token (parser)->location; @@ -12707,7 +12913,7 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list) t = NULL_TREE; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (t == NULL_TREE || t == error_mark_node) return list; @@ -12819,7 +13025,8 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT; tree nl, c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -12849,7 +13056,7 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) OMP_CLAUSE_DEPEND_KIND (c) = kind; OMP_CLAUSE_DECL (c) = NULL_TREE; OMP_CLAUSE_CHAIN (c) = list; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return c; } @@ -12867,13 +13074,13 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) OMP_CLAUSE_DEPEND_KIND (c) = kind; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; invalid_kind: c_parser_error (parser, "invalid depend kind"); resync_fail: - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -12901,7 +13108,8 @@ c_parser_omp_clause_map (c_parser *parser, tree list) tree always_id = NULL_TREE; tree nl, c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -12968,7 +13176,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list) if (always_id_kind != C_ID_ID) { c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -12988,7 +13196,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list) } if (always == 1) { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } } @@ -12998,7 +13206,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list) for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_SET_MAP_KIND (c, kind); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; } @@ -13009,7 +13217,8 @@ static tree c_parser_omp_clause_device (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expr_no_commas (parser, NULL); @@ -13017,7 +13226,7 @@ c_parser_omp_clause_device (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -13046,7 +13255,8 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) tree c, t = NULL_TREE; location_t loc = c_parser_peek_token (parser)->location; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!c_parser_next_token_is_keyword (parser, RID_STATIC)) @@ -13067,7 +13277,7 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, @@ -13096,7 +13306,8 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list) enum omp_clause_proc_bind_kind kind; tree c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -13115,7 +13326,7 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list) goto invalid_kind; c_parser_consume_token (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND); OMP_CLAUSE_PROC_BIND_KIND (c) = kind; OMP_CLAUSE_CHAIN (c) = list; @@ -13123,7 +13334,7 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list) invalid_kind: c_parser_error (parser, "invalid proc_bind kind"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -13154,11 +13365,12 @@ c_parser_omp_clause_uniform (c_parser *parser, tree list) /* The clauses location. */ location_t loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM, list); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } return list; } @@ -14951,7 +15163,8 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, { int bracecount = 0; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) goto pop_scopes; /* Parse the initialization declaration or expression. */ @@ -15058,7 +15271,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, incr = c_process_expr_stmt (incr_loc, c_parser_expression (parser).value); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (decl == NULL || decl == error_mark_node || init == error_mark_node) fail = true; @@ -17565,7 +17778,8 @@ c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, clause. Represent it in OpenMP terms. */ check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return clauses; location_t loc = c_parser_peek_token (parser)->location; @@ -17601,7 +17815,7 @@ c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, } } - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); return clauses; } @@ -17623,7 +17837,8 @@ c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, static tree c_parser_cilk_clause_linear (c_parser *parser, tree clauses) { - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return clauses; location_t loc = c_parser_peek_token (parser)->location; @@ -17685,7 +17900,7 @@ c_parser_cilk_clause_linear (c_parser *parser, tree clauses) c_parser_consume_token (parser); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return clauses; } @@ -18049,7 +18264,8 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword) } parser->in_transaction = this_in; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { tree expr = c_parser_expression (parser).value; ret.original_type = TREE_TYPE (expr); @@ -18058,7 +18274,7 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword) TRANSACTION_EXPR_RELAXED (ret.value) = 1; SET_EXPR_LOCATION (ret.value, loc); ret.original_code = TRANSACTION_EXPR; - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); goto error; diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h index 1e344c4..01a7b72 100644 --- a/gcc/c/c-parser.h +++ b/gcc/c/c-parser.h @@ -136,11 +136,13 @@ extern c_token * c_parser_peek_token (c_parser *parser); extern c_token * c_parser_peek_2nd_token (c_parser *parser); extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n); extern bool c_parser_require (c_parser *parser, enum cpp_ttype type, - const char *msgid); -extern void c_parser_error (c_parser *parser, const char *gmsgid); + const char *msgid, + location_t matching_location = UNKNOWN_LOCATION); +extern bool c_parser_error (c_parser *parser, const char *gmsgid); extern void c_parser_consume_token (c_parser *parser); extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type, - const char *msgid); + const char *msgid, + location_t = UNKNOWN_LOCATION); extern bool c_parser_next_token_starts_declspecs (c_parser *parser); bool c_parser_next_tokens_start_declaration (c_parser *parser); bool c_token_starts_typename (c_token *token); diff --git a/gcc/testsuite/gcc.dg/unclosed-init.c b/gcc/testsuite/gcc.dg/unclosed-init.c new file mode 100644 index 0000000..c0e4dd8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/unclosed-init.c @@ -0,0 +1,3 @@ +int unclosed[] = { /* { dg-message "18: to match this '.'" } */ + 42 + /* { dg-error "0: expected '.' at end of input" } */