[PATCH 3/3] matching tokens: C++ parts
David Malcolm
dmalcolm@redhat.com
Tue Jul 11 14:51:00 GMT 2017
OK for trunk? (assuming the rest is approved)
gcc/cp/ChangeLog:
* parser.c (cp_parser_error): Update for new param to
c_parse_error.
(class token_pair): New class.
(class matching_parens): New class.
(class matching_braces): New class.
(cp_parser_statement_expr): 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.
(cp_parser_primary_expression): Likewise.
(cp_parser_postfix_expression): Likewise.
(cp_parser_parenthesized_expression_list): Likewise.
(cp_parser_unary_expression): Likewise.
(cp_parser_new_expression): Likewise.
(cp_parser_cast_expression): Likewise.
(cp_parser_builtin_offsetof): Likewise.
(cp_parser_trait_expr): Likewise.
(cp_parser_lambda_declarator_opt): Likewise.
(cp_parser_lambda_body): Likewise, for matching_braces.
(cp_parser_compound_statement): Likewise.
(cp_parser_selection_statement): Likewise, for matching_parens.
(cp_parser_iteration_statement): Likewise.
(cp_parser_already_scoped_statement): Likewise, for
matching_braces.
(cp_parser_linkage_specification): Likewise.
(cp_parser_static_assert): Likewise, for matching_parens.
(cp_parser_decltype): Likewise.
(cp_parser_operator): Likewise.
(cp_parser_enum_specifier): Likewise.
(cp_parser_namespace_definition): Likewise.
(cp_parser_direct_declarator): Likewise.
(cp_parser_braced_list): Likewise.
(cp_parser_class_specifier_1): Likewise, for matching_braces.
(cp_parser_constant_initializer): Likewise.
(cp_parser_noexcept_specification_opt): Likewise, for
matching_parens.
(cp_parser_exception_specification_opt): Likewise.
(cp_parser_handler): Likewise.
(cp_parser_asm_specification_opt): Likewise.
(cp_parser_asm_operand_list): Likewise.
(cp_parser_gnu_attributes_opt): Likewise.
(cp_parser_std_attribute_spec): Likewise.
(cp_parser_requirement_parameter_list): Likewise.
(cp_parser_requirement_body): Likewise, for matching_braces.
(cp_parser_compound_requirement): Likewise.
(cp_parser_template_introduction): Likewise.
(cp_parser_sizeof_pack): Likewise, for matching_parens.
(cp_parser_sizeof_operand): Likewise.
(get_matching_symbol): New function.
(cp_parser_required_error): Add param "matching_location". Remove
calls to cp_parser_error, instead setting a non-NULL gmsgid, and
handling it if set by calling c_parse_error, potentially with a
secondary location if matching_location was set.
(cp_parser_require): Add param "matching_location", with a default
value of UNKNOWN_LOCATION.
(cp_parser_require_keyword): Update for new param of
cp_parser_required_error.
(cp_parser_objc_encode_expression): Update to class matching_parens
as above.
(cp_parser_objc_defs_expression): Likewise.
(cp_parser_objc_protocol_expression): Likewise.
(cp_parser_objc_selector_expression): Likewise.
(cp_parser_objc_typename): Likewise.
(cp_parser_objc_superclass_or_category): Likewise.
(cp_parser_objc_try_catch_finally_statement): Likewise.
(cp_parser_objc_synchronized_statement): Likewise.
(cp_parser_objc_at_property_declaration): Likewise.
(cp_parser_oacc_single_int_clause): Likewise.
(cp_parser_oacc_shape_clause): Likewise.
(cp_parser_omp_clause_collapse): Likewise.
(cp_parser_omp_clause_default): Likewise.
(cp_parser_omp_clause_final): Likewise.
(cp_parser_omp_clause_if): Likewise.
(cp_parser_omp_clause_num_threads): Likewise.
(cp_parser_omp_clause_num_tasks): Likewise.
(cp_parser_omp_clause_grainsize): Likewise.
(cp_parser_omp_clause_priority): Likewise.
(cp_parser_omp_clause_hint): Likewise.
(cp_parser_omp_clause_defaultmap): Likewise.
(cp_parser_omp_clause_ordered): Likewise.
(cp_parser_omp_clause_schedule): Likewise.
(cp_parser_omp_clause_num_teams): Likewise.
(cp_parser_omp_clause_thread_limit): Likewise.
(cp_parser_omp_clause_aligned): Likewise.
(cp_parser_omp_clause_linear): Likewise.
(cp_parser_omp_clause_safelen): Likewise.
(cp_parser_omp_clause_simdlen): Likewise.
(cp_parser_omp_clause_depend): Likewise.
(cp_parser_omp_clause_device): Likewise.
(cp_parser_omp_clause_dist_schedule): Likewise.
(cp_parser_oacc_clause_async): Likewise.
(cp_parser_omp_critical): Likewise.
(cp_parser_omp_for_loop): Likewise.
(cp_parser_omp_sections_scope): Likewise.
(cp_parser_omp_declare_reduction_exprs): Likewise.
Update for new param to cp_parser_required_error.
(cp_parser_oacc_routine): Likewise.
(cp_parser_transaction_expression): Likewise.
(cp_parser_cilk_simd_vectorlength): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/diagnostic/unclosed-extern-c.C: New test case.
* g++.dg/diagnostic/unclosed-function.C: New test case.
* g++.dg/diagnostic/unclosed-namespace.C: New test case.
* g++.dg/diagnostic/unclosed-struct.C: New test case.
* g++.dg/parse/pragma2.C: Update to reflect movement of the
"expected identifier" error.
---
gcc/cp/parser.c | 821 ++++++++++++++-------
.../g++.dg/diagnostic/unclosed-extern-c.C | 3 +
.../g++.dg/diagnostic/unclosed-function.C | 3 +
.../g++.dg/diagnostic/unclosed-namespace.C | 2 +
gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C | 3 +
gcc/testsuite/g++.dg/parse/pragma2.C | 4 +-
6 files changed, 549 insertions(+), 287 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
create mode 100644 gcc/testsuite/g++.dg/diagnostic/unclosed-function.C
create mode 100644 gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C
create mode 100644 gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c81b1a1f..30cdc53 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2551,9 +2551,9 @@ static void set_and_check_decl_spec_loc
static bool cp_parser_friend_p
(const cp_decl_specifier_seq *);
static void cp_parser_required_error
- (cp_parser *, required_token, bool);
+ (cp_parser *, required_token, bool, location_t);
static cp_token *cp_parser_require
- (cp_parser *, enum cpp_ttype, required_token);
+ (cp_parser *, enum cpp_ttype, required_token, location_t = UNKNOWN_LOCATION);
static cp_token *cp_parser_require_keyword
(cp_parser *, enum rid, required_token);
static bool cp_parser_token_starts_function_definition_p
@@ -2804,12 +2804,13 @@ cp_parser_error (cp_parser* parser, const char* gmsgid)
}
}
+ rich_location richloc (line_table, input_location);
c_parse_error (gmsgid,
/* Because c_parser_error does not understand
CPP_KEYWORD, keywords are treated like
identifiers. */
(token->type == CPP_KEYWORD ? CPP_NAME : token->type),
- token->u.value, token->flags);
+ token->u.value, token->flags, &richloc);
}
}
@@ -4503,6 +4504,110 @@ struct tentative_firewall
}
};
+/* 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 <typename token_pair_traits_t>
+class token_pair
+{
+ private:
+ typedef token_pair_traits_t traits_t;
+
+ 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 (cp_parser *parser)
+ {
+ m_open_loc = cp_lexer_peek_token (parser->lexer)->location;
+ return cp_parser_require (parser, traits_t::open_token_type,
+ traits_t::required_token_open);
+ }
+
+ /* Consume the next token from PARSER, recording its location as
+ that of the opening token within the pair. */
+
+ cp_token * consume_open (cp_parser *parser)
+ {
+ cp_token *tok = cp_lexer_consume_token (parser->lexer);
+ gcc_assert (tok->type == traits_t::open_token_type);
+ m_open_loc = tok->location;
+ return tok;
+ }
+
+ /* Peek the next token from PARSER, recording its location as
+ that of the opening token within the pair. */
+
+ void peek_open (cp_parser *parser)
+ {
+ cp_token *tok = cp_lexer_peek_token (parser->lexer);
+ gcc_assert (tok->type == traits_t::open_token_type);
+ m_open_loc = tok->location;
+ }
+
+ /* If the next token is the closing symbol for this pair, consume it
+ and return it.
+ Otherwise, issue an error, highlighting the location of the
+ corrsponding opening token, and return NULL. */
+
+ cp_token *require_close (cp_parser *parser) const
+ {
+ return cp_parser_require (parser, traits_t::close_token_type,
+ traits_t::required_token_close,
+ m_open_loc);
+ }
+
+ private:
+ location_t m_open_loc;
+};
+
+/* A subclass of token_pair for tracking matching pairs of parentheses. */
+
+class matching_parens : public token_pair<matching_parens>
+{
+ public:
+ static const enum cpp_ttype open_token_type;
+ static const enum required_token required_token_open;
+ static const enum cpp_ttype close_token_type;
+ static const enum required_token required_token_close;
+};
+
+/* Constant data for class matching_parens. */
+
+const enum cpp_ttype matching_parens::open_token_type = CPP_OPEN_PAREN;
+const enum required_token matching_parens::required_token_open = RT_OPEN_PAREN;
+const enum cpp_ttype matching_parens::close_token_type = CPP_CLOSE_PAREN;
+const enum required_token matching_parens::required_token_close
+ = RT_CLOSE_PAREN;
+
+/* A subclass of token_pair for tracking matching pairs of braces. */
+
+class matching_braces : public token_pair<matching_braces>
+{
+ public:
+ static const enum cpp_ttype open_token_type;
+ static const enum required_token required_token_open;
+ static const enum cpp_ttype close_token_type;
+ static const enum required_token required_token_close;
+};
+
+/* Constant data for class matching_braces. */
+
+const enum cpp_ttype matching_braces::open_token_type = CPP_OPEN_BRACE;
+const enum required_token matching_braces::required_token_open = RT_OPEN_BRACE;
+const enum cpp_ttype matching_braces::close_token_type = CPP_CLOSE_BRACE;
+const enum required_token matching_braces::required_token_close
+ = RT_CLOSE_BRACE;
+
/* Parse a GNU statement-expression, i.e. ({ stmts }), except for the
enclosing parentheses. */
@@ -4513,7 +4618,8 @@ cp_parser_statement_expr (cp_parser *parser)
/* Consume the '('. */
location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
/* Start the statement-expression. */
tree expr = begin_stmt_expr ();
/* Parse the compound-statement. */
@@ -4522,7 +4628,7 @@ cp_parser_statement_expr (cp_parser *parser)
expr = finish_stmt_expr (expr, false);
/* Consume the ')'. */
location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_end_of_statement (parser);
cp_parser_end_tentative_firewall (parser, start, expr);
@@ -4928,7 +5034,8 @@ cp_parser_primary_expression (cp_parser *parser,
location_t open_paren_loc = token->location;
/* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
/* Within a parenthesized expression, a `>' token is always
the greater-than operator. */
saved_greater_than_is_operator_p
@@ -4976,7 +5083,7 @@ cp_parser_primary_expression (cp_parser *parser,
token = cp_lexer_peek_token (parser->lexer);
location_t close_paren_loc = token->location;
expr.set_range (open_paren_loc, close_paren_loc);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)
+ if (!parens.require_close (parser)
&& !cp_parser_uncommitted_to_tentative_parse_p (parser))
cp_parser_skip_to_end_of_statement (parser);
@@ -5098,7 +5205,8 @@ cp_parser_primary_expression (cp_parser *parser,
`va_arg'. Consume the `__builtin_va_arg' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the opening `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Now, parse the assignment-expression. */
expression = cp_parser_assignment_expression (parser);
/* Look for the `,'. */
@@ -5112,7 +5220,7 @@ cp_parser_primary_expression (cp_parser *parser,
/* Look for the closing `)'. */
location_t finish_loc
= cp_lexer_peek_token (parser->lexer)->location;
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* Using `va_arg' in a constant-expression is not
allowed. */
if (cp_parser_non_integral_constant_expression (parser,
@@ -6465,7 +6573,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
parser->greater_than_is_operator_p = true;
/* And the expression which is being cast. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
expression = cp_parser_expression (parser, & idk, /*cast_p=*/true);
cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN,
RT_CLOSE_PAREN);
@@ -6526,7 +6635,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Consume the `typeid' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the `(' token. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Types cannot be defined in a `typeid' expression. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
@@ -6542,8 +6652,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Look for the `)' token. Otherwise, we can't be sure that
we're not looking at an expression: consider `typeid (int
(3))', for example. */
- cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN,
- RT_CLOSE_PAREN);
+ cp_token *close_paren = parens.require_close (parser);
/* If all went well, simply lookup the type-id. */
if (cp_parser_parse_definitely (parser))
postfix_expression = get_typeid (type, tf_warning_or_error);
@@ -6557,8 +6666,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Compute its typeid. */
postfix_expression = build_typeid (expression, tf_warning_or_error);
/* Look for the `)' token. */
- close_paren
- = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ close_paren = parens.require_close (parser);
}
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
@@ -7561,7 +7669,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
if (non_constant_p)
*non_constant_p = false;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return NULL;
expression_list = make_tree_vector ();
@@ -7657,7 +7766,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
if (close_paren_loc)
*close_paren_loc = cp_lexer_peek_token (parser->lexer)->location;
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
{
int ending;
@@ -7957,7 +8066,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
bool saved_greater_than_is_operator_p;
cp_lexer_consume_token (parser->lexer);
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
@@ -7991,7 +8101,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
parser->type_definition_forbidden_message = saved_message;
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
return finish_noexcept_expr (expr, tf_warning_or_error);
}
@@ -8235,7 +8345,8 @@ cp_parser_new_expression (cp_parser* parser)
const char *saved_message = parser->type_definition_forbidden_message;
/* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
/* Parse the type-id. */
parser->type_definition_forbidden_message
@@ -8247,7 +8358,7 @@ cp_parser_new_expression (cp_parser* parser)
parser->type_definition_forbidden_message = saved_message;
/* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
token = cp_lexer_peek_token (parser->lexer);
/* There should not be a direct-new-declarator in this production,
but GCC used to allowed this, so we check and emit a sensible error
@@ -8787,7 +8898,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
parser->type_definition_forbidden_message
= G_("types may not be defined in casts");
/* Consume the `('. */
- cp_token *open_paren = cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ cp_token *open_paren = parens.consume_open (parser);
location_t open_paren_loc = open_paren->location;
location_t close_paren_loc = UNKNOWN_LOCATION;
@@ -8852,8 +8964,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Look for the type-id. */
type = cp_parser_type_id (parser);
/* Look for the closing `)'. */
- cp_token *close_paren
- = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ cp_token *close_paren = parens.require_close (parser);
if (close_paren)
close_paren_loc = close_paren->location;
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
@@ -9638,7 +9749,8 @@ cp_parser_builtin_offsetof (cp_parser *parser)
/* Consume the "__builtin_offsetof" token. */
cp_lexer_consume_token (parser->lexer);
/* Consume the opening `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Parse the type-id. */
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
type = cp_parser_type_id (parser);
@@ -9688,7 +9800,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
default:
/* Error. We know the following require will fail, but
that gives the proper error message. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
expr = error_mark_node;
goto failure;
@@ -9834,7 +9946,8 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
{
type_id_in_expr_sentinel s (parser);
@@ -9873,7 +9986,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
}
}
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* Complete the trait expression, which may mean either processing
the trait expr now or saving it for template instantiation. */
@@ -10354,7 +10467,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
opening parenthesis if present. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
@@ -10369,7 +10483,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), OPT_Wpedantic,
"default argument specified for lambda parameter");
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
attributes = cp_parser_attributes_opt (parser);
@@ -10526,7 +10640,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
start_lambda_scope (fco);
body = begin_function_body ();
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ matching_braces braces;
+ if (!braces.require_open (parser))
goto out;
/* Push the proxies for any explicit captures. */
@@ -10567,7 +10682,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
expr = cp_parser_expression (parser, &idk);
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
if (cp_parser_parse_definitely (parser))
{
@@ -10591,7 +10706,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
cp_parser_label_declaration (parser);
cp_parser_statement_seq_opt (parser, NULL_TREE);
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
}
finish_compound_stmt (compound_stmt);
@@ -11127,9 +11242,10 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
int bcs_flags, bool function_body)
{
tree compound_stmt;
+ matching_braces braces;
/* Consume the `{'. */
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ if (!braces.require_open (parser))
return error_mark_node;
if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
&& !function_body && cxx_dialect < cxx14)
@@ -11145,7 +11261,7 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
/* Finish the compound-statement. */
finish_compound_stmt (compound_stmt);
/* Consume the `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
return compound_stmt;
}
@@ -11266,7 +11382,8 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
}
/* Look for the `('. */
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
{
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
@@ -11295,7 +11412,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
/* Parse the condition. */
condition = cp_parser_condition (parser);
/* Look for the `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
@@ -12082,12 +12199,13 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep)
/* Begin the while-statement. */
statement = begin_while_stmt ();
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Parse the condition. */
condition = cp_parser_condition (parser);
finish_while_stmt_cond (condition, statement, ivdep);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* Parse the dependent statement. */
parser->in_statement = IN_ITERATION_STMT;
cp_parser_already_scoped_statement (parser, if_p, guard_tinfo);
@@ -12111,13 +12229,14 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep)
/* Look for the `while' keyword. */
cp_parser_require_keyword (parser, RID_WHILE, RT_WHILE);
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Parse the expression. */
expression = cp_parser_expression (parser);
/* We're done with the do-statement. */
finish_do_stmt (expression, statement, ivdep);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* Look for the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
}
@@ -12126,12 +12245,13 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep)
case RID_FOR:
{
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
statement = cp_parser_for (parser, ivdep);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* Parse the body of the for-statement. */
parser->in_statement = IN_ITERATION_STMT;
@@ -12481,13 +12601,14 @@ cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p,
{
/* Avoid calling cp_parser_compound_statement, so that we
don't create a new scope. Do everything else by hand. */
- cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
+ matching_braces braces;
+ braces.require_open (parser);
/* If the next keyword is `__label__' we have a label declaration. */
while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
cp_parser_label_declaration (parser);
/* Parse an (optional) statement-seq. */
cp_parser_statement_seq_opt (parser, NULL_TREE);
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
}
}
@@ -13709,11 +13830,12 @@ cp_parser_linkage_specification (cp_parser* parser)
cp_ensure_no_oacc_routine (parser);
/* Consume the `{' token. */
- cp_lexer_consume_token (parser->lexer);
+ matching_braces braces;
+ braces.consume_open (parser)->location;
/* Parse the declarations. */
cp_parser_declaration_seq_opt (parser);
/* Look for the closing `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
}
/* Otherwise, there's just one declaration. */
else
@@ -13765,7 +13887,8 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
cp_parser_commit_to_tentative_parse (parser);
/* Parse the `(' starting the static assertion condition. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Parse the constant-expression. Allow a non-constant expression
here in order to give better diagnostics in finish_static_assert. */
@@ -13797,7 +13920,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
/*wide_ok=*/true);
/* A `)' completes the static assertion. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
/*or_comma=*/false,
@@ -13951,7 +14074,8 @@ cp_parser_decltype (cp_parser *parser)
return error_mark_node;
/* Parse the opening `('. */
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return error_mark_node;
/* decltype (auto) */
@@ -13959,7 +14083,7 @@ cp_parser_decltype (cp_parser *parser)
&& cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
{
cp_lexer_consume_token (parser->lexer);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
return error_mark_node;
expr = make_decltype_auto ();
AUTO_IS_DECLTYPE (expr) = true;
@@ -14014,7 +14138,7 @@ cp_parser_decltype (cp_parser *parser)
= saved_non_integral_constant_expression_p;
/* Parse to the closing `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
{
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
@@ -14713,11 +14837,14 @@ cp_parser_operator (cp_parser* parser)
break;
case CPP_OPEN_PAREN:
- /* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
- /* Look for the matching `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
- return cp_operator_id (CALL_EXPR);
+ {
+ /* Consume the `('. */
+ matching_parens parens;
+ parens.consume_open (parser);
+ /* Look for the matching `)'. */
+ parens.require_close (parser);
+ return cp_operator_id (CALL_EXPR);
+ }
case CPP_OPEN_SQUARE:
/* Consume the `['. */
@@ -18090,7 +18217,8 @@ cp_parser_enum_specifier (cp_parser* parser)
begin_scope (sk_scoped_enum, type);
/* Consume the opening brace. */
- cp_lexer_consume_token (parser->lexer);
+ matching_braces braces;
+ braces.consume_open (parser);
if (type == error_mark_node)
; /* Nothing to add */
@@ -18123,7 +18251,7 @@ cp_parser_enum_specifier (cp_parser* parser)
cp_parser_enumerator_list (parser, type);
/* Consume the final '}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
if (scoped_enum_p)
finish_scope ();
@@ -18416,13 +18544,14 @@ cp_parser_namespace_definition (cp_parser* parser)
warning (OPT_Wnamespaces, "namespace %qD entered", current_namespace);
/* Look for the `{' to validate starting the namespace. */
- if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ matching_braces braces;
+ if (braces.require_open (parser))
{
/* Parse the body of the namespace. */
cp_parser_namespace_body (parser);
/* Look for the final `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
}
if (has_visibility)
@@ -19803,7 +19932,8 @@ cp_parser_direct_declarator (cp_parser* parser,
cp_parser_parse_tentatively (parser);
/* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
if (first)
{
/* If this is going to be an abstract declarator, we're
@@ -19818,7 +19948,7 @@ cp_parser_direct_declarator (cp_parser* parser,
params = cp_parser_parameter_declaration_clause (parser);
/* Consume the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* If all went well, parse the cv-qualifier-seq,
ref-qualifier and the exception-specification. */
@@ -19914,7 +20044,8 @@ cp_parser_direct_declarator (cp_parser* parser,
parser->in_declarator_p = saved_in_declarator_p;
/* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
/* Parse the nested declarator. */
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
parser->in_type_id_in_expr_p = true;
@@ -19925,7 +20056,7 @@ cp_parser_direct_declarator (cp_parser* parser,
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
first = false;
/* Expect a `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
declarator = cp_error_declarator;
if (declarator == cp_error_declarator)
break;
@@ -21773,7 +21904,8 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Consume the `{' token. */
- cp_lexer_consume_token (parser->lexer);
+ matching_braces braces;
+ braces.consume_open (parser);
/* Create a CONSTRUCTOR to represent the braced-initializer. */
initializer = make_node (CONSTRUCTOR);
/* If it's not a `}', then there is a non-trivial initializer. */
@@ -21790,7 +21922,7 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
*non_constant_p = false;
/* Now, there should be a trailing `}'. */
location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
TREE_TYPE (initializer) = init_list_type_node;
cp_expr result (initializer);
@@ -22217,7 +22349,8 @@ cp_parser_class_specifier_1 (cp_parser* parser)
}
/* Look for the `{'. */
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ matching_braces braces;
+ if (!braces.require_open (parser))
{
pop_deferring_access_checks ();
return error_mark_node;
@@ -22269,7 +22402,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
cp_parser_member_specification_opt (parser);
/* Look for the trailing `}'. */
- closing_brace = cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ closing_brace = braces.require_close (parser);
/* Look for trailing attributes to apply to this class. */
if (cp_parser_allow_gnu_extensions_p (parser))
attributes = cp_parser_gnu_attributes_opt (parser);
@@ -23748,11 +23881,12 @@ cp_parser_constant_initializer (cp_parser* parser)
cp_parser_error (parser,
"a brace-enclosed initializer is not allowed here");
/* Consume the opening brace. */
- cp_lexer_consume_token (parser->lexer);
+ matching_braces braces;
+ braces.consume_open (parser);
/* Skip the initializer. */
cp_parser_skip_to_closing_brace (parser);
/* Look for the trailing `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
return error_mark_node;
}
@@ -24008,7 +24142,8 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
{
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
if (require_constexpr)
{
@@ -24028,7 +24163,7 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
*consumed_expr = true;
}
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
}
else
{
@@ -24082,7 +24217,8 @@ cp_parser_exception_specification_opt (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@@ -24118,7 +24254,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
type_id_list = empty_except_spec;
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
return type_id_list;
}
@@ -24265,10 +24401,11 @@ cp_parser_handler (cp_parser* parser)
cp_parser_require_keyword (parser, RID_CATCH, RT_CATCH);
handler = begin_handler ();
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
declaration = cp_parser_exception_declaration (parser);
finish_handler_parms (declaration, handler);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false);
finish_handler (handler);
}
@@ -24384,13 +24521,14 @@ cp_parser_asm_specification_opt (cp_parser* parser)
/* Consume the `asm' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Look for the string-literal. */
asm_specification = cp_parser_string_literal (parser, false, false);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
return asm_specification;
}
@@ -24442,11 +24580,12 @@ cp_parser_asm_operand_list (cp_parser* parser)
string_literal = cp_parser_string_literal (parser, false, false);
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
/* Parse the expression. */
expression = cp_parser_expression (parser);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
if (name == error_mark_node
|| string_literal == error_mark_node
@@ -24700,8 +24839,10 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
/* Consume the `__attribute__' keyword. */
cp_lexer_consume_token (parser->lexer);
/* Look for the two `(' tokens. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens outer_parens;
+ outer_parens.require_open (parser);
+ matching_parens inner_parens;
+ inner_parens.require_open (parser);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@@ -24714,9 +24855,9 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
attribute_list = NULL;
/* Look for the two `)' tokens. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!inner_parens.require_close (parser))
ok = false;
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!outer_parens.require_close (parser))
ok = false;
if (!ok)
cp_parser_skip_to_end_of_statement (parser);
@@ -25139,7 +25280,8 @@ cp_parser_std_attribute_spec (cp_parser *parser)
cp_lexer_consume_token (parser->lexer);
maybe_warn_cpp0x (CPP0X_ATTRIBUTES);
- if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN) == NULL)
+ matching_parens parens;
+ if (!parens.require_open (parser))
{
cp_parser_error (parser, "expected %<(%>");
return error_mark_node;
@@ -25172,7 +25314,7 @@ cp_parser_std_attribute_spec (cp_parser *parser)
if (alignas_expr == error_mark_node)
return error_mark_node;
- if (cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) == NULL)
+ if (!parens.require_close (parser))
{
cp_parser_error (parser, "expected %<)%>");
return error_mark_node;
@@ -25404,12 +25546,13 @@ cp_parser_requires_expression (cp_parser *parser)
static tree
cp_parser_requirement_parameter_list (cp_parser *parser)
{
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return error_mark_node;
tree parms = cp_parser_parameter_declaration_clause (parser);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
return error_mark_node;
return parms;
@@ -25422,12 +25565,13 @@ cp_parser_requirement_parameter_list (cp_parser *parser)
static tree
cp_parser_requirement_body (cp_parser *parser)
{
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ matching_braces braces;
+ if (!braces.require_open (parser))
return error_mark_node;
tree reqs = cp_parser_requirement_list (parser);
- if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE))
+ if (!braces.require_close (parser))
return error_mark_node;
return reqs;
@@ -25566,14 +25710,15 @@ static tree
cp_parser_compound_requirement (cp_parser *parser)
{
/* Parse an expression enclosed in '{ }'s. */
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ matching_braces braces;
+ if (!braces.require_open (parser))
return error_mark_node;
tree expr = cp_parser_expression (parser, NULL, false, false);
if (!expr || expr == error_mark_node)
return error_mark_node;
- if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE))
+ if (!braces.require_close (parser))
return error_mark_node;
/* Parse the optional noexcept. */
@@ -26644,7 +26789,8 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p)
cp_parser_simulate_error (parser);
/* Look for opening brace for introduction. */
- cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
+ matching_braces braces;
+ braces.require_open (parser);
if (!cp_parser_parse_definitely (parser))
return false;
@@ -26664,7 +26810,7 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p)
}
/* Look for closing brace for introduction. */
- if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE))
+ if (!braces.require_close (parser))
return true;
if (tmpl_decl == error_mark_node)
@@ -27549,9 +27695,10 @@ cp_parser_sizeof_pack (cp_parser *parser)
cp_lexer_consume_token (parser->lexer);
maybe_warn_variadic_templates ();
+ matching_parens parens;
bool paren = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN);
if (paren)
- cp_lexer_consume_token (parser->lexer);
+ parens.consume_open (parser);
else
permerror (cp_lexer_peek_token (parser->lexer)->location,
"%<sizeof...%> argument must be surrounded by parentheses");
@@ -27576,7 +27723,7 @@ cp_parser_sizeof_pack (cp_parser *parser)
PACK_EXPANSION_SIZEOF_P (expr) = true;
if (paren)
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
return expr;
}
@@ -27627,6 +27774,9 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
{
tree type = NULL_TREE;
+ matching_parens parens;
+ parens.peek_open (parser);
+
/* We can't be sure yet whether we're looking at a type-id or an
expression. */
cp_parser_parse_tentatively (parser);
@@ -27643,7 +27793,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
/* Look for the type-id. */
type = cp_parser_type_id (parser);
/* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
}
@@ -27925,187 +28075,245 @@ cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
return decl_spec_seq_has_spec_p (decl_specifiers, ds_friend);
}
+/* Get a description of the matching symbol to TOKEN_DESC e.g. "(" for
+ RT_CLOSE_PAREN. */
+
+static const char *
+get_matching_symbol (required_token token_desc)
+{
+ switch (token_desc)
+ {
+ default:
+ gcc_unreachable ();
+ return "";
+ case RT_CLOSE_BRACE:
+ return "{";
+ case RT_CLOSE_PAREN:
+ return "(";
+ }
+}
+
/* Issue an error message indicating that TOKEN_DESC was expected.
If KEYWORD is true, it indicated this function is called by
cp_parser_require_keword and the required token can only be
- a indicated keyword. */
+ a indicated keyword.
+
+ 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 TOKEN_DESC is
+ RT_CLOSE_PAREN). */
static void
cp_parser_required_error (cp_parser *parser,
required_token token_desc,
- bool keyword)
+ bool keyword,
+ location_t matching_location)
{
+ if (cp_parser_simulate_error (parser))
+ return;
+
+ const char *gmsgid = NULL;
switch (token_desc)
{
case RT_NEW:
- cp_parser_error (parser, "expected %<new%>");
- return;
+ gmsgid = G_("expected %<new%>");
+ break;
case RT_DELETE:
- cp_parser_error (parser, "expected %<delete%>");
- return;
+ gmsgid = G_("expected %<delete%>");
+ break;
case RT_RETURN:
- cp_parser_error (parser, "expected %<return%>");
- return;
+ gmsgid = G_("expected %<return%>");
+ break;
case RT_WHILE:
- cp_parser_error (parser, "expected %<while%>");
- return;
+ gmsgid = G_("expected %<while%>");
+ break;
case RT_EXTERN:
- cp_parser_error (parser, "expected %<extern%>");
- return;
+ gmsgid = G_("expected %<extern%>");
+ break;
case RT_STATIC_ASSERT:
- cp_parser_error (parser, "expected %<static_assert%>");
- return;
+ gmsgid = G_("expected %<static_assert%>");
+ break;
case RT_DECLTYPE:
- cp_parser_error (parser, "expected %<decltype%>");
- return;
+ gmsgid = G_("expected %<decltype%>");
+ break;
case RT_OPERATOR:
- cp_parser_error (parser, "expected %<operator%>");
- return;
+ gmsgid = G_("expected %<operator%>");
+ break;
case RT_CLASS:
- cp_parser_error (parser, "expected %<class%>");
- return;
+ gmsgid = G_("expected %<class%>");
+ break;
case RT_TEMPLATE:
- cp_parser_error (parser, "expected %<template%>");
- return;
+ gmsgid = G_("expected %<template%>");
+ break;
case RT_NAMESPACE:
- cp_parser_error (parser, "expected %<namespace%>");
- return;
+ gmsgid = G_("expected %<namespace%>");
+ break;
case RT_USING:
- cp_parser_error (parser, "expected %<using%>");
- return;
+ gmsgid = G_("expected %<using%>");
+ break;
case RT_ASM:
- cp_parser_error (parser, "expected %<asm%>");
- return;
+ gmsgid = G_("expected %<asm%>");
+ break;
case RT_TRY:
- cp_parser_error (parser, "expected %<try%>");
- return;
+ gmsgid = G_("expected %<try%>");
+ break;
case RT_CATCH:
- cp_parser_error (parser, "expected %<catch%>");
- return;
+ gmsgid = G_("expected %<catch%>");
+ break;
case RT_THROW:
- cp_parser_error (parser, "expected %<throw%>");
- return;
+ gmsgid = G_("expected %<throw%>");
+ break;
case RT_LABEL:
- cp_parser_error (parser, "expected %<__label__%>");
- return;
+ gmsgid = G_("expected %<__label__%>");
+ break;
case RT_AT_TRY:
- cp_parser_error (parser, "expected %<@try%>");
- return;
+ gmsgid = G_("expected %<@try%>");
+ break;
case RT_AT_SYNCHRONIZED:
- cp_parser_error (parser, "expected %<@synchronized%>");
- return;
+ gmsgid = G_("expected %<@synchronized%>");
+ break;
case RT_AT_THROW:
- cp_parser_error (parser, "expected %<@throw%>");
- return;
+ gmsgid = G_("expected %<@throw%>");
+ break;
case RT_TRANSACTION_ATOMIC:
- cp_parser_error (parser, "expected %<__transaction_atomic%>");
- return;
+ gmsgid = G_("expected %<__transaction_atomic%>");
+ break;
case RT_TRANSACTION_RELAXED:
- cp_parser_error (parser, "expected %<__transaction_relaxed%>");
- return;
+ gmsgid = G_("expected %<__transaction_relaxed%>");
+ break;
default:
break;
}
- if (!keyword)
+
+ if (!gmsgid && !keyword)
{
switch (token_desc)
{
case RT_SEMICOLON:
- cp_parser_error (parser, "expected %<;%>");
- return;
+ gmsgid = G_("expected %<;%>");
+ break;
case RT_OPEN_PAREN:
- cp_parser_error (parser, "expected %<(%>");
- return;
+ gmsgid = G_("expected %<(%>");
+ break;
case RT_CLOSE_BRACE:
- cp_parser_error (parser, "expected %<}%>");
- return;
+ gmsgid = G_("expected %<}%>");
+ break;
case RT_OPEN_BRACE:
- cp_parser_error (parser, "expected %<{%>");
- return;
+ gmsgid = G_("expected %<{%>");
+ break;
case RT_CLOSE_SQUARE:
- cp_parser_error (parser, "expected %<]%>");
- return;
+ gmsgid = G_("expected %<]%>");
+ break;
case RT_OPEN_SQUARE:
- cp_parser_error (parser, "expected %<[%>");
- return;
+ gmsgid = G_("expected %<[%>");
+ break;
case RT_COMMA:
- cp_parser_error (parser, "expected %<,%>");
- return;
+ gmsgid = G_("expected %<,%>");
+ break;
case RT_SCOPE:
- cp_parser_error (parser, "expected %<::%>");
- return;
+ gmsgid = G_("expected %<::%>");
+ break;
case RT_LESS:
- cp_parser_error (parser, "expected %<<%>");
- return;
+ gmsgid = G_("expected %<<%>");
+ break;
case RT_GREATER:
- cp_parser_error (parser, "expected %<>%>");
- return;
+ gmsgid = G_("expected %<>%>");
+ break;
case RT_EQ:
- cp_parser_error (parser, "expected %<=%>");
- return;
+ gmsgid = G_("expected %<=%>");
+ break;
case RT_ELLIPSIS:
- cp_parser_error (parser, "expected %<...%>");
- return;
+ gmsgid = G_("expected %<...%>");
+ break;
case RT_MULT:
- cp_parser_error (parser, "expected %<*%>");
- return;
+ gmsgid = G_("expected %<*%>");
+ break;
case RT_COMPL:
- cp_parser_error (parser, "expected %<~%>");
- return;
+ gmsgid = G_("expected %<~%>");
+ break;
case RT_COLON:
- cp_parser_error (parser, "expected %<:%>");
- return;
+ gmsgid = G_("expected %<:%>");
+ break;
case RT_COLON_SCOPE:
- cp_parser_error (parser, "expected %<:%> or %<::%>");
- return;
+ gmsgid = G_("expected %<:%> or %<::%>");
+ break;
case RT_CLOSE_PAREN:
- cp_parser_error (parser, "expected %<)%>");
- return;
+ gmsgid = G_("expected %<)%>");
+ break;
case RT_COMMA_CLOSE_PAREN:
- cp_parser_error (parser, "expected %<,%> or %<)%>");
- return;
+ gmsgid = G_("expected %<,%> or %<)%>");
+ break;
case RT_PRAGMA_EOL:
- cp_parser_error (parser, "expected end of line");
- return;
+ gmsgid = G_("expected end of line");
+ break;
case RT_NAME:
- cp_parser_error (parser, "expected identifier");
- return;
+ gmsgid = G_("expected identifier");
+ break;
case RT_SELECT:
- cp_parser_error (parser, "expected selection-statement");
- return;
+ gmsgid = G_("expected selection-statement");
+ break;
case RT_ITERATION:
- cp_parser_error (parser, "expected iteration-statement");
- return;
+ gmsgid = G_("expected iteration-statement");
+ break;
case RT_JUMP:
- cp_parser_error (parser, "expected jump-statement");
- return;
+ gmsgid = G_("expected jump-statement");
+ break;
case RT_CLASS_KEY:
- cp_parser_error (parser, "expected class-key");
- return;
+ gmsgid = G_("expected class-key");
+ break;
case RT_CLASS_TYPENAME_TEMPLATE:
- cp_parser_error (parser,
- "expected %<class%>, %<typename%>, or %<template%>");
- return;
+ gmsgid = G_("expected %<class%>, %<typename%>, or %<template%>");
+ break;
default:
gcc_unreachable ();
}
}
- else
- gcc_unreachable ();
-}
+ if (gmsgid)
+ {
+ /* Emulate rest of cp_parser_error. */
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ cp_lexer_set_source_position_from_token (token);
+
+ gcc_rich_location richloc (input_location);
+
+ /* 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);
+
+ c_parse_error (gmsgid,
+ (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
+ token->u.value, token->flags, &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 (token_desc));
+ }
+}
/* If the next token is of the indicated TYPE, consume it. Otherwise,
issue an error message indicating that TOKEN_DESC was expected.
Returns the token consumed, if the token had the appropriate type.
- Otherwise, returns NULL. */
+ Otherwise, returns NULL.
+
+ 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 TOKEN_DESC is
+ RT_CLOSE_PAREN). */
static cp_token *
cp_parser_require (cp_parser* parser,
enum cpp_ttype type,
- required_token token_desc)
+ required_token token_desc,
+ location_t matching_location)
{
if (cp_lexer_next_token_is (parser->lexer, type))
return cp_lexer_consume_token (parser->lexer);
@@ -28113,7 +28321,8 @@ cp_parser_require (cp_parser* parser,
{
/* Output the MESSAGE -- unless we're parsing tentatively. */
if (!cp_parser_simulate_error (parser))
- cp_parser_required_error (parser, token_desc, /*keyword=*/false);
+ cp_parser_required_error (parser, token_desc, /*keyword=*/false,
+ matching_location);
return NULL;
}
}
@@ -28215,7 +28424,8 @@ cp_parser_require_keyword (cp_parser* parser,
if (token && token->keyword != keyword)
{
- cp_parser_required_error (parser, token_desc, /*keyword=*/true);
+ cp_parser_required_error (parser, token_desc, /*keyword=*/true,
+ UNKNOWN_LOCATION);
return NULL;
}
@@ -29026,10 +29236,11 @@ cp_parser_objc_encode_expression (cp_parser* parser)
location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
token = cp_lexer_peek_token (parser->lexer);
type = complete_type (cp_parser_type_id (parser));
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
if (!type)
{
@@ -29071,9 +29282,10 @@ cp_parser_objc_defs_expression (cp_parser *parser)
tree name;
cp_lexer_consume_token (parser->lexer); /* Eat '@defs'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
name = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
return objc_get_class_ivars (name);
}
@@ -29092,9 +29304,10 @@ cp_parser_objc_protocol_expression (cp_parser* parser)
location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
proto = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* Build a location of the form:
@protocol(prot)
@@ -29132,7 +29345,8 @@ cp_parser_objc_selector_expression (cp_parser* parser)
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
token = cp_lexer_peek_token (parser->lexer);
while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
@@ -29179,7 +29393,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
}
finish_selector:
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* Build a location of the form:
@@ -29386,7 +29600,8 @@ cp_parser_objc_typename (cp_parser* parser)
{
tree proto_quals, cp_type = NULL_TREE;
- cp_lexer_consume_token (parser->lexer); /* Eat '('. */
+ matching_parens parens;
+ parens.consume_open (parser); /* Eat '('. */
proto_quals = cp_parser_objc_protocol_qualifiers (parser);
/* An ObjC type name may consist of just protocol qualifiers, in which
@@ -29412,7 +29627,7 @@ cp_parser_objc_typename (cp_parser* parser)
}
}
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
type_name = build_tree_list (proto_quals, cp_type);
}
@@ -30026,7 +30241,8 @@ cp_parser_objc_superclass_or_category (cp_parser *parser,
}
else if (next->type == CPP_OPEN_PAREN)
{
- cp_lexer_consume_token (parser->lexer); /* Eat '('. */
+ matching_parens parens;
+ parens.consume_open (parser); /* Eat '('. */
/* If there is no category name, and this is an @interface, we
have a class extension. */
@@ -30038,7 +30254,7 @@ cp_parser_objc_superclass_or_category (cp_parser *parser,
else
*categ = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
}
}
@@ -30226,9 +30442,10 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
cp_parameter_declarator *parm;
tree parameter_declaration = error_mark_node;
bool seen_open_paren = false;
+ matching_parens parens;
cp_lexer_consume_token (parser->lexer);
- if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ if (parens.require_open (parser))
seen_open_paren = true;
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
@@ -30254,7 +30471,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
/*attrlist=*/NULL);
}
if (seen_open_paren)
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
else
{
/* If there was no open parenthesis, we are recovering from
@@ -30308,9 +30525,10 @@ cp_parser_objc_synchronized_statement (cp_parser *parser)
location = cp_lexer_peek_token (parser->lexer)->location;
objc_maybe_warn_exceptions (location);
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
lock = cp_parser_expression (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
/* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
node, lest it get absorbed into the surrounding block. */
@@ -30551,7 +30769,8 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
/* Eat the '('. */
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
while (true)
{
@@ -30639,7 +30858,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
"error: expected â)â before â,â token". This is because
cp_parser_require, unlike the C counterpart, will produce an
error even if we are in error recovery. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
{
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
@@ -31330,13 +31549,14 @@ cp_parser_oacc_single_int_clause (cp_parser *parser, omp_clause_code code,
{
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
tree t = cp_parser_assignment_expression (parser, NULL, false, false);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
{
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
@@ -31383,7 +31603,8 @@ cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind,
if (cp_lexer_next_token_is (lexer, CPP_OPEN_PAREN))
{
- cp_lexer_consume_token (lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
do
{
@@ -31457,7 +31678,7 @@ cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind,
}
while (1);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
goto cleanup_error;
}
@@ -31603,12 +31824,13 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location
HOST_WIDE_INT n;
loc = cp_lexer_peek_token (parser->lexer)->location;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
num = cp_parser_constant_expression (parser);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -31647,7 +31869,8 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
tree c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -31690,7 +31913,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
}
if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -31714,13 +31937,14 @@ cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location)
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_condition (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -31751,7 +31975,8 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
tree t, c;
enum tree_code if_modifier = ERROR_MARK;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
if (is_omp && cp_lexer_next_token_is (parser->lexer, CPP_NAME))
@@ -31834,7 +32059,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
t = cp_parser_condition (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -31929,13 +32154,14 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -31959,13 +32185,14 @@ cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -31989,13 +32216,14 @@ cp_parser_omp_clause_grainsize (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32019,13 +32247,14 @@ cp_parser_omp_clause_priority (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32049,13 +32278,14 @@ cp_parser_omp_clause_hint (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32079,7 +32309,8 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
tree c, id;
const char *p;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
@@ -32111,7 +32342,7 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
goto out_err;
}
cp_lexer_consume_token (parser->lexer);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
goto out_err;
check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULTMAP, "defaultmap",
@@ -32146,11 +32377,12 @@ cp_parser_omp_clause_ordered (cp_parser *parser,
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
num = cp_parser_constant_expression (parser);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32307,7 +32539,8 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location
tree c, t;
int modifiers = 0, nmodifiers = 0;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE);
@@ -32401,7 +32634,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location
else
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
goto resync_fail;
}
else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
@@ -32507,13 +32740,14 @@ cp_parser_omp_clause_num_teams (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32537,13 +32771,14 @@ cp_parser_omp_clause_thread_limit (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32568,7 +32803,8 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
tree nlist, c, alignment = NULL_TREE;
bool colon;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALIGNED, list,
@@ -32578,7 +32814,7 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
{
alignment = cp_parser_constant_expression (parser);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32609,7 +32845,8 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
bool colon;
enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
if (!is_cilk_simd_fn
@@ -32639,7 +32876,7 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
colon = cp_lexer_next_token_is (parser->lexer, CPP_COLON);
if (colon)
cp_parser_require (parser, CPP_COLON, RT_COLON);
- else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ else if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32677,7 +32914,7 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
sorry ("using parameters for %<linear%> step is not supported yet");
step = integer_one_node;
}
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32704,13 +32941,14 @@ cp_parser_omp_clause_safelen (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_constant_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32733,13 +32971,14 @@ cp_parser_omp_clause_simdlen (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_constant_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -32855,7 +33094,8 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
tree nlist, c;
enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
@@ -32887,7 +33127,7 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
OMP_CLAUSE_DEPEND_KIND (c) = kind;
OMP_CLAUSE_DECL (c) = NULL_TREE;
OMP_CLAUSE_CHAIN (c) = list;
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -33018,13 +33258,14 @@ cp_parser_omp_clause_device (cp_parser *parser, tree list,
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -33049,7 +33290,8 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list,
{
tree c, t;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return list;
c = build_omp_clause (location, OMP_CLAUSE_DIST_SCHEDULE);
@@ -33068,7 +33310,7 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list,
goto resync_fail;
OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
goto resync_fail;
}
else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
@@ -33154,11 +33396,12 @@ cp_parser_oacc_clause_async (cp_parser *parser, tree list)
if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
{
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
t = cp_parser_expression (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -34208,12 +34451,13 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
- cp_lexer_consume_token (parser->lexer);
+ matching_parens parens;
+ parens.consume_open (parser);
name = cp_parser_identifier (parser);
if (name == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -34711,7 +34955,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
}
loc = cp_lexer_consume_token (parser->lexer)->location;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return NULL;
init = orig_init = decl = real_decl = NULL;
@@ -34843,7 +35088,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
protected_set_expr_location (incr, input_location);
}
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -35202,7 +35447,8 @@ cp_parser_omp_sections_scope (cp_parser *parser)
bool error_suppress = false;
cp_token *tok;
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ matching_braces braces;
+ if (!braces.require_open (parser))
return NULL_TREE;
stmt = push_stmt_list ();
@@ -35239,7 +35485,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ braces.require_close (parser);
substmt = pop_stmt_list (stmt);
@@ -37101,7 +37347,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
if (strcmp (p, "initializer") == 0)
{
cp_lexer_consume_token (parser->lexer);
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return false;
p = "";
@@ -37192,12 +37439,13 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
if (ctor)
add_decl_expr (omp_orig);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
return false;
}
if (!cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL))
- cp_parser_required_error (parser, RT_PRAGMA_EOL, /*keyword=*/false);
+ cp_parser_required_error (parser, RT_PRAGMA_EOL, /*keyword=*/false,
+ UNKNOWN_LOCATION);
return true;
}
@@ -37625,7 +37873,8 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
/* Look for optional '( name )'. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
- cp_lexer_consume_token (parser->lexer); /* '(' */
+ matching_parens parens;
+ parens.consume_open (parser); /* '(' */
/* We parse the name as an id-expression. If it resolves to
anything other than a non-overloaded function at namespace
@@ -37642,7 +37891,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
cp_parser_name_lookup_error (parser, name, decl, NLE_NULL, name_loc);
if (decl == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ || !parens.require_close (parser))
{
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
parser->oacc_routine = NULL;
@@ -38074,12 +38323,13 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
if (!noex || !noex_expr
|| cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
{
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ matching_parens parens;
+ parens.require_open (parser);
expr = cp_parser_expression (parser);
expr = finish_parenthesized_expr (expr);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ parens.require_close (parser);
}
else
{
@@ -38667,7 +38917,8 @@ cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses,
check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "vectorlength",
loc);
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ matching_parens parens;
+ if (!parens.require_open (parser))
return error_mark_node;
expr = cp_parser_constant_expression (parser);
@@ -38704,7 +38955,7 @@ cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses,
}
}
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ if (!parens.require_close (parser))
return error_mark_node;
return clauses;
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
new file mode 100644
index 0000000..fda3532
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
@@ -0,0 +1,3 @@
+extern "C" { /* { dg-message "12: to match this '.'" } */
+
+void test (void); /* { dg-error "17: expected '.' at end of input" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-function.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-function.C
new file mode 100644
index 0000000..e1e1550
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-function.C
@@ -0,0 +1,3 @@
+void test (void)
+{ /* { dg-message "1: to match this '.'" } */
+ int filler; /* { dg-error "13: expected '.' at end of input" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C
new file mode 100644
index 0000000..ff11322
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C
@@ -0,0 +1,2 @@
+namespace unclosed { /* { dg-message "20: to match this '.'" } */
+int filler; /* { dg-error "11: expected '.' at end of input" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C
new file mode 100644
index 0000000..8c206bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C
@@ -0,0 +1,3 @@
+struct unclosed { /* { dg-message "17: to match this '.'" } */
+ int dummy; /* { dg-error "12: expected '.' at end of input" } */
+ // { dg-error "expected unqualified-id at end of input" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/pragma2.C b/gcc/testsuite/g++.dg/parse/pragma2.C
index c5616ff..3dc5fc1 100644
--- a/gcc/testsuite/g++.dg/parse/pragma2.C
+++ b/gcc/testsuite/g++.dg/parse/pragma2.C
@@ -4,5 +4,5 @@
// does not.
int f(int x,
#pragma interface // { dg-error "not allowed here" }
- // The parser gets confused and issues an error on the next line.
- int y); // { dg-bogus "" "" { xfail *-*-* } }
+ // { dg-bogus "expected identifier" "" { xfail *-*-* } .-1 }
+ int y);
--
1.8.5.3
More information about the Gcc-patches
mailing list