Commit 4ec4afa8 by Nathan Sidwell Committed by Nathan Sidwell

[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
parent 790cc674
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> 2018-02-12 Richard Biener <rguenther@suse.de>
PR c++/84281 PR c++/84281
......
...@@ -14049,12 +14049,7 @@ cp_parser_decltype_expr (cp_parser *parser, ...@@ -14049,12 +14049,7 @@ cp_parser_decltype_expr (cp_parser *parser,
static tree static tree
cp_parser_decltype (cp_parser *parser) cp_parser_decltype (cp_parser *parser)
{ {
tree expr;
bool id_expression_or_member_access_p = false; 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); cp_token *start_token = cp_lexer_peek_token (parser->lexer);
if (start_token->type == CPP_DECLTYPE) if (start_token->type == CPP_DECLTYPE)
...@@ -14073,77 +14068,83 @@ cp_parser_decltype (cp_parser *parser) ...@@ -14073,77 +14068,83 @@ cp_parser_decltype (cp_parser *parser)
if (!parens.require_open (parser)) if (!parens.require_open (parser))
return error_mark_node; return error_mark_node;
/* decltype (auto) */ push_deferring_access_checks (dk_deferred);
tree expr = NULL_TREE;
if (cxx_dialect >= cxx14 if (cxx_dialect >= cxx14
&& cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)) && 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); /* decltype (expression) */
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;
/* And create the new one. */ /* Types cannot be defined in a `decltype' expression. Save away the
parser->type_definition_forbidden_message old message and set the new one. */
= G_("types may not be defined in %<decltype%> expressions"); 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 /* The restrictions on constant-expressions do not apply inside
decltype expressions. */ decltype expressions. */
saved_integral_constant_expression_p bool saved_integral_constant_expression_p
= parser->integral_constant_expression_p; = parser->integral_constant_expression_p;
saved_non_integral_constant_expression_p bool saved_non_integral_constant_expression_p
= parser->non_integral_constant_expression_p; = parser->non_integral_constant_expression_p;
parser->integral_constant_expression_p = false; parser->integral_constant_expression_p = false;
/* Within a parenthesized expression, a `>' token is always /* Within a parenthesized expression, a `>' token is always
the greater-than operator. */ the greater-than operator. */
saved_greater_than_is_operator_p bool saved_greater_than_is_operator_p
= parser->greater_than_is_operator_p; = parser->greater_than_is_operator_p;
parser->greater_than_is_operator_p = true; parser->greater_than_is_operator_p = true;
/* Do not actually evaluate the expression. */ /* Do not actually evaluate the expression. */
++cp_unevaluated_operand; ++cp_unevaluated_operand;
/* Do not warn about problems with the expression. */ /* Do not warn about problems with the expression. */
++c_inhibit_evaluation_warnings; ++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. */ /* Go back to evaluating expressions. */
--cp_unevaluated_operand; --cp_unevaluated_operand;
--c_inhibit_evaluation_warnings; --c_inhibit_evaluation_warnings;
/* The `>' token might be the end of a template-id or /* The `>' token might be the end of a template-id or
template-parameter-list now. */ template-parameter-list now. */
parser->greater_than_is_operator_p parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p; = saved_greater_than_is_operator_p;
/* Restore the old message and the integral constant expression /* Restore the old message and the integral constant expression
flags. */ flags. */
parser->type_definition_forbidden_message = saved_message; parser->type_definition_forbidden_message = saved_message;
parser->integral_constant_expression_p parser->integral_constant_expression_p
= saved_integral_constant_expression_p; = saved_integral_constant_expression_p;
parser->non_integral_constant_expression_p parser->non_integral_constant_expression_p
= saved_non_integral_constant_expression_p; = saved_non_integral_constant_expression_p;
}
/* Parse to the closing `)'. */ /* Parse to the closing `)'. */
if (!parens.require_close (parser)) if (!parens.require_close (parser))
{ {
cp_parser_skip_to_closing_parenthesis (parser, true, false, cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true); /*consume_paren=*/true);
pop_deferring_access_checks ();
return error_mark_node; return error_mark_node;
} }
expr = finish_decltype_type (expr, id_expression_or_member_access_p, if (!expr)
tf_warning_or_error); {
/* 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 /* Replace the decltype with a CPP_DECLTYPE so we don't need to parse
it again. */ it again. */
start_token->type = CPP_DECLTYPE; start_token->type = CPP_DECLTYPE;
...@@ -14153,6 +14154,8 @@ cp_parser_decltype (cp_parser *parser) ...@@ -14153,6 +14154,8 @@ cp_parser_decltype (cp_parser *parser)
start_token->keyword = RID_MAX; start_token->keyword = RID_MAX;
cp_lexer_purge_tokens_after (parser->lexer, start_token); cp_lexer_purge_tokens_after (parser->lexer, start_token);
pop_to_parent_deferring_access_checks ();
return expr; return expr;
} }
2018-02-12 Nathan Sidwell <nathan@acm.org>
* g++.dg/parse/pr84263.C: New.
2018-02-12 Paolo Carlini <paolo.carlini@oracle.com> 2018-02-12 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/79626 PR c++/79626
......
// { 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"}}; }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment