From 8359fa53d8c25c0e8aee4f649b8b9c09a14d207a Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 12 Feb 2018 11:58:40 +0000 Subject: [PATCH] [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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257584 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 6 ++ gcc/cp/parser.c | 111 ++++++++++++++++++----------------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/parse/pr84263.C | 36 ++++++++++++ 4 files changed, 103 insertions(+), 54 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/pr84263.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bb7e9173072..2f12a35a1b5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2018-02-12 Nathan Sidwell + + PR c++/84263 + * parser.c (cp_parser_decltype): Push and pop + deferring_access_checks. Reorganize to avoid goto. + 2018-02-12 Richard Biener PR c++/84281 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ac5277db9ad..e1e8741d21d 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 % 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 % 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d11609de5ef..677fed9da3f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-02-12 Nathan Sidwell + + * g++.dg/parse/pr84263.C: New. + 2018-02-12 Paolo Carlini PR c++/79626 diff --git a/gcc/testsuite/g++.dg/parse/pr84263.C b/gcc/testsuite/g++.dg/parse/pr84263.C new file mode 100644 index 00000000000..e492d8c9e25 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr84263.C @@ -0,0 +1,36 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options "--param ggc-min-expand=0 --param ggc-min-heapsize=0" } +// PR 84263, a GC bug exposed on i686 native compiler (and possibly +// other 32-bit hosts). decltype parsing could create a +// pointer that would be gc-freed by later actions. + +namespace std { +template struct b { + int c; + a d; +}; +template class g; +template class initializer_list { + void *e; + __SIZE_TYPE__ f; +}; +class h; +class j { + typedef b i; + +public: + j(); + j(initializer_list); +}; +template struct m; +template struct m {}; +class h { +public: + template h(l &); +}; +class G { + G(); + j n; +}; +G::G() { n = decltype(n){{0, ""}, {1, ".unoLineArrowEnd"}}; } +} -- 2.11.4.GIT