2018-02-08 Nathan Sidwell <nathan@acm.org>
PR c++/84263
* parser.c (cp_parser_decltype): Push and pop
deferring_access_checks. Reorganize to avoid goto.
* g++.dg/parse/pr84263.C: New.
===================================================================
@@ -14049,12 +14049,7 @@ cp_parser_decltype_expr (cp_parser *pars
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;
- }
+ /* decltype (expression) */
- /* Types cannot be defined in a `decltype' expression. Save away the
- old message. */
- saved_message = parser->type_definition_forbidden_message;
-
- /* And create the new one. */
- 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;
-
- /* 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;
-
- /* Do not actually evaluate the expression. */
- ++cp_unevaluated_operand;
-
- /* Do not warn about problems with the expression. */
- ++c_inhibit_evaluation_warnings;
-
- expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p);
-
- /* 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;
-
- /* 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;
+ /* 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. */
+ 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. */
+ 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 warn about problems with the expression. */
+ ++c_inhibit_evaluation_warnings;
+
+ expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p);
+
+ /* 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;
+
+ /* 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;
}
===================================================================
@@ -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"}}; }
+}