aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2018-02-12 11:58:40 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2018-02-12 11:58:40 +0000
commit4ec4afa8c10837d17eb431a08fb0c16bdac3d3cf (patch)
tree7a110bd311e8c5013a731a8fe37d27b5163b5d58 /gcc/cp/parser.c
parent790cc674b649940c8981023a3249db946b6aced4 (diff)
downloadgcc-4ec4afa8c10837d17eb431a08fb0c16bdac3d3cf.zip
gcc-4ec4afa8c10837d17eb431a08fb0c16bdac3d3cf.tar.gz
gcc-4ec4afa8c10837d17eb431a08fb0c16bdac3d3cf.tar.bz2
[PR c++/84263] GC ICE with decltype
https://gcc.gnu.org/ml/gcc-patches/2018-02/msg00435.html PR c++/84263 * parser.c (cp_parser_decltype): Push and pop deferring_access_checks. Reorganize to avoid goto. * g++.dg/parse/pr84263.C: New. From-SVN: r257584
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c111
1 files changed, 57 insertions, 54 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ac5277d..e1e8741 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14049,12 +14049,7 @@ cp_parser_decltype_expr (cp_parser *parser,
static tree
cp_parser_decltype (cp_parser *parser)
{
- tree expr;
bool id_expression_or_member_access_p = false;
- const char *saved_message;
- bool saved_integral_constant_expression_p;
- bool saved_non_integral_constant_expression_p;
- bool saved_greater_than_is_operator_p;
cp_token *start_token = cp_lexer_peek_token (parser->lexer);
if (start_token->type == CPP_DECLTYPE)
@@ -14073,77 +14068,83 @@ cp_parser_decltype (cp_parser *parser)
if (!parens.require_open (parser))
return error_mark_node;
- /* decltype (auto) */
+ push_deferring_access_checks (dk_deferred);
+
+ tree expr = NULL_TREE;
+
if (cxx_dialect >= cxx14
&& cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
+ /* decltype (auto) */
+ cp_lexer_consume_token (parser->lexer);
+ else
{
- cp_lexer_consume_token (parser->lexer);
- if (!parens.require_close (parser))
- return error_mark_node;
- expr = make_decltype_auto ();
- AUTO_IS_DECLTYPE (expr) = true;
- goto rewrite;
- }
-
- /* Types cannot be defined in a `decltype' expression. Save away the
- old message. */
- saved_message = parser->type_definition_forbidden_message;
+ /* decltype (expression) */
- /* And create the new one. */
- parser->type_definition_forbidden_message
- = G_("types may not be defined in %<decltype%> expressions");
+ /* Types cannot be defined in a `decltype' expression. Save away the
+ old message and set the new one. */
+ const char *saved_message = parser->type_definition_forbidden_message;
+ parser->type_definition_forbidden_message
+ = G_("types may not be defined in %<decltype%> expressions");
- /* The restrictions on constant-expressions do not apply inside
- decltype expressions. */
- saved_integral_constant_expression_p
- = parser->integral_constant_expression_p;
- saved_non_integral_constant_expression_p
- = parser->non_integral_constant_expression_p;
- parser->integral_constant_expression_p = false;
+ /* The restrictions on constant-expressions do not apply inside
+ decltype expressions. */
+ bool saved_integral_constant_expression_p
+ = parser->integral_constant_expression_p;
+ bool saved_non_integral_constant_expression_p
+ = parser->non_integral_constant_expression_p;
+ parser->integral_constant_expression_p = false;
- /* Within a parenthesized expression, a `>' token is always
- the greater-than operator. */
- saved_greater_than_is_operator_p
- = parser->greater_than_is_operator_p;
- parser->greater_than_is_operator_p = true;
+ /* Within a parenthesized expression, a `>' token is always
+ the greater-than operator. */
+ bool saved_greater_than_is_operator_p
+ = parser->greater_than_is_operator_p;
+ parser->greater_than_is_operator_p = true;
- /* Do not actually evaluate the expression. */
- ++cp_unevaluated_operand;
+ /* Do not actually evaluate the expression. */
+ ++cp_unevaluated_operand;
- /* Do not warn about problems with the expression. */
- ++c_inhibit_evaluation_warnings;
+ /* Do not warn about problems with the expression. */
+ ++c_inhibit_evaluation_warnings;
- expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p);
+ expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p);
- /* Go back to evaluating expressions. */
- --cp_unevaluated_operand;
- --c_inhibit_evaluation_warnings;
+ /* Go back to evaluating expressions. */
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
- /* The `>' token might be the end of a template-id or
- template-parameter-list now. */
- parser->greater_than_is_operator_p
- = saved_greater_than_is_operator_p;
+ /* The `>' token might be the end of a template-id or
+ template-parameter-list now. */
+ parser->greater_than_is_operator_p
+ = saved_greater_than_is_operator_p;
- /* Restore the old message and the integral constant expression
- flags. */
- parser->type_definition_forbidden_message = saved_message;
- parser->integral_constant_expression_p
- = saved_integral_constant_expression_p;
- parser->non_integral_constant_expression_p
- = saved_non_integral_constant_expression_p;
+ /* Restore the old message and the integral constant expression
+ flags. */
+ parser->type_definition_forbidden_message = saved_message;
+ parser->integral_constant_expression_p
+ = saved_integral_constant_expression_p;
+ parser->non_integral_constant_expression_p
+ = saved_non_integral_constant_expression_p;
+ }
/* Parse to the closing `)'. */
if (!parens.require_close (parser))
{
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
+ pop_deferring_access_checks ();
return error_mark_node;
}
- expr = finish_decltype_type (expr, id_expression_or_member_access_p,
- tf_warning_or_error);
+ if (!expr)
+ {
+ /* Build auto. */
+ expr = make_decltype_auto ();
+ AUTO_IS_DECLTYPE (expr) = true;
+ }
+ else
+ expr = finish_decltype_type (expr, id_expression_or_member_access_p,
+ tf_warning_or_error);
- rewrite:
/* Replace the decltype with a CPP_DECLTYPE so we don't need to parse
it again. */
start_token->type = CPP_DECLTYPE;
@@ -14153,6 +14154,8 @@ cp_parser_decltype (cp_parser *parser)
start_token->keyword = RID_MAX;
cp_lexer_purge_tokens_after (parser->lexer, start_token);
+ pop_to_parent_deferring_access_checks ();
+
return expr;
}