On Wed, Nov 27, 2024 at 10:12:25AM +0100, Jakub Jelinek wrote:
> Hi!
>
> Compilation of the following testcase hangs forever after emitting first
> error. The problem is that in one place we just return error_mark_node
> directly rather than going through c_expr_sizeof_expr or c_expr_sizeof_type.
> The parsing of the expression could have called record_maybe_used_decl
> though, but nothing calls pop_maybe_used which needs to be called after
> parsing of every sizeof/typeof, successful or not.
Ah, I see.
> At the end of the toplevel declaration we free the parser_obstack and in
> another function record_maybe_used_decl is called again and due to the
> missing pop_maybe_unused we end up with a cycle in the chain.
>
> The following patch fixes it by just setting error and goto to the
> sizeof_expr:
> c_inhibit_evaluation_warnings--;
> in_sizeof--;
> mark_exp_read (expr.value);
> if (TREE_CODE (expr.value) == COMPONENT_REF
> && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
> error_at (expr_loc, "%<sizeof%> applied to a bit-field");
> result = c_expr_sizeof_expr (expr_loc, expr);
> where c_expr_sizeof_expr will do:
> struct c_expr ret;
> if (expr.value == error_mark_node)
> {
> ret.value = error_mark_node;
> ret.original_code = ERROR_MARK;
> ret.original_type = NULL;
> ret.m_decimal = 0;
> pop_maybe_used (false);
> }
> ...
> return ret;
> which is exactly what the old code did manually except for the missing
> pop_maybe_used call. mark_exp_read does nothing on error_mark_node and
> error_mark_node doesn't have COMPONENT_REF tree_code.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2024-11-27 Jakub Jelinek <[email protected]>
>
> PR c/117745
> * c-parser.cc (c_parser_sizeof_expression): If type_name is NULL,
> just expr.set_error () and goto sizeof_expr instead of doing error
> recovery manually.
>
> * gcc.dg/pr117745.c: New test.
>
> --- gcc/c/c-parser.cc.jj 2024-11-23 13:00:28.328028242 +0100
> +++ gcc/c/c-parser.cc 2024-11-26 11:59:18.036410746 +0100
> @@ -10405,13 +10405,8 @@ c_parser_sizeof_expression (c_parser *pa
> finish = parser->tokens_buf[0].location;
> if (type_name == NULL)
> {
> - struct c_expr ret;
> - c_inhibit_evaluation_warnings--;
> - in_sizeof--;
> - ret.set_error ();
> - ret.original_code = ERROR_MARK;
> - ret.original_type = NULL;
> - return ret;
> + expr.set_error ();
> + goto sizeof_expr;
Patch is OK, though I'd appreciate a comment explaining why we bother to
call c_expr_sizeof_expr. Maybe
/* Let c_expr_sizeof_expr call pop_maybe_used; the parsing of the
expression could have called record_maybe_used_decl. */
or something like that. c_expr_sizeof_type doesn't do it, so that wouldn't
do.
> }
> if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
> {
> --- gcc/testsuite/gcc.dg/pr117745.c.jj 2024-11-26 12:07:11.120756946
> +0100
> +++ gcc/testsuite/gcc.dg/pr117745.c 2024-11-26 12:08:00.031068850 +0100
> @@ -0,0 +1,8 @@
> +/* PR c/117745 */
> +/* { dg-do compile } */
> +/* { dg-options "" } */
> +
> +static int foo (void);
> +void bar (void) { sizeof (int [0 ? foo () : 1); } /* { dg-error
> "expected" } */
> +static int baz (void);
> +void qux (void) { sizeof (sizeof (int[baz ()])); }
>
> Jakub
>
Marek