diff options
author | Nathan Sidwell <nathan@acm.org> | 2018-02-12 11:58:40 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2018-02-12 11:58:40 +0000 |
commit | 4ec4afa8c10837d17eb431a08fb0c16bdac3d3cf (patch) | |
tree | 7a110bd311e8c5013a731a8fe37d27b5163b5d58 /gcc | |
parent | 790cc674b649940c8981023a3249db946b6aced4 (diff) | |
download | gcc-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')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/parser.c | 111 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/pr84263.C | 36 |
4 files changed, 103 insertions, 54 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bb7e917..2f12a35 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2018-02-12 Nathan Sidwell <nathan@acm.org> + + PR c++/84263 + * parser.c (cp_parser_decltype): Push and pop + deferring_access_checks. Reorganize to avoid goto. + 2018-02-12 Richard Biener <rguenther@suse.de> PR c++/84281 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d11609d..677fed9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-02-12 Nathan Sidwell <nathan@acm.org> + + * g++.dg/parse/pr84263.C: New. + 2018-02-12 Paolo Carlini <paolo.carlini@oracle.com> 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 0000000..e492d8c --- /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 <typename a> struct b { + int c; + a d; +}; +template <typename> class g; +template <class> class initializer_list { + void *e; + __SIZE_TYPE__ f; +}; +class h; +class j { + typedef b<h> i; + +public: + j(); + j(initializer_list<i>); +}; +template <typename> struct m; +template <int k> struct m<char[k]> {}; +class h { +public: + template <typename l> h(l &); +}; +class G { + G(); + j n; +}; +G::G() { n = decltype(n){{0, ""}, {1, ".unoLineArrowEnd"}}; } +} |