c: [PR32122] Require pointer types for computed gotos

So GCC has always accepted non-pointer types in computed gotos but
that was wrong based on the documentation:
Any expression of type void * is allowed.

So this fixes the problem by requiring the type to
be a pointer type.

OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.

	PR c/32122

gcc/c/ChangeLog:

	* c-parser.c (c_parser_statement_after_labels): Pass
	the c_expr instead of the tree to c_finish_goto_ptr.
	* c-typeck.c (c_finish_goto_ptr): Change the second
	argument type to c_expr.
	* c-tree.h (c_finish_goto_ptr): Likewise.
	Error out if the expression was not of a pointer type.

gcc/testsuite/ChangeLog:

	* gcc.dg/comp-goto-5.c: New test.
	* gcc.dg/comp-goto-6.c: New test.
This commit is contained in:
Andrew Pinski 2021-09-17 04:59:03 +00:00
parent c44c5f3d9f
commit e12f66d96f
5 changed files with 29 additions and 3 deletions

View file

@ -6141,7 +6141,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_consume_token (parser);
val = c_parser_expression (parser);
val = convert_lvalue_to_rvalue (loc, val, false, true);
stmt = c_finish_goto_ptr (loc, val.value);
stmt = c_finish_goto_ptr (loc, val);
}
else
c_parser_error (parser, "expected identifier or %<*%>");

View file

@ -746,7 +746,7 @@ extern tree c_finish_expr_stmt (location_t, tree);
extern tree c_finish_return (location_t, tree, tree);
extern tree c_finish_bc_stmt (location_t, tree, bool);
extern tree c_finish_goto_label (location_t, tree);
extern tree c_finish_goto_ptr (location_t, tree);
extern tree c_finish_goto_ptr (location_t, c_expr val);
extern tree c_expr_to_decl (tree, bool *, bool *);
extern tree c_finish_omp_construct (location_t, enum tree_code, tree, tree);
extern tree c_finish_oacc_data (location_t, tree, tree);

View file

@ -10783,10 +10783,19 @@ c_finish_goto_label (location_t loc, tree label)
the GOTO. */
tree
c_finish_goto_ptr (location_t loc, tree expr)
c_finish_goto_ptr (location_t loc, c_expr val)
{
tree expr = val.value;
tree t;
pedwarn (loc, OPT_Wpedantic, "ISO C forbids %<goto *expr;%>");
if (expr != error_mark_node
&& !POINTER_TYPE_P (TREE_TYPE (expr))
&& !null_pointer_constant_p (expr))
{
error_at (val.get_location (),
"computed goto must be pointer type");
expr = build_zero_cst (ptr_type_node);
}
expr = c_fully_fold (expr, false, NULL);
expr = convert (ptr_type_node, expr);
t = build1 (GOTO_EXPR, void_type_node, expr);

View file

@ -0,0 +1,11 @@
/* PR c/32122 */
/* { dg-do compile } */
/* { dg-options "" } */
enum {a=1};
void foo()
{
goto *
a; /* { dg-error "computed goto must be pointer type" } */
}

View file

@ -0,0 +1,6 @@
/* PR c/32122 */
/* { dg-do compile } */
/* { dg-options "" } */
void foo(void *a) { goto *10000000; } /* { dg-error "computed goto must be pointer type" } */
void foo1(void *a) { goto *a; }