On Mon, Sep 20, 2021 at 12:15 AM apinski--- via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > From: Andrew Pinski <apin...@marvell.com> > > 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. > --- > gcc/c/c-parser.c | 2 +- > gcc/c/c-tree.h | 2 +- > gcc/c/c-typeck.c | 11 ++++++++++- > gcc/testsuite/gcc.dg/comp-goto-5.c | 11 +++++++++++ > gcc/testsuite/gcc.dg/comp-goto-6.c | 6 ++++++ > 5 files changed, 29 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/comp-goto-5.c > create mode 100644 gcc/testsuite/gcc.dg/comp-goto-6.c > > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c > index fb1399e300d..bcd8a05489f 100644 > --- a/gcc/c/c-parser.c > +++ b/gcc/c/c-parser.c > @@ -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 %<*%>"); > diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h > index d50d0cb7f2d..a046c6b0926 100644 > --- a/gcc/c/c-tree.h > +++ b/gcc/c/c-tree.h > @@ -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); > diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c > index 49d1bb067a0..b472e448011 100644 > --- a/gcc/c/c-typeck.c > +++ b/gcc/c/c-typeck.c > @@ -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); > diff --git a/gcc/testsuite/gcc.dg/comp-goto-5.c > b/gcc/testsuite/gcc.dg/comp-goto-5.c > new file mode 100644 > index 00000000000..d487729a5d4 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/comp-goto-5.c > @@ -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" } */ > +} > + > diff --git a/gcc/testsuite/gcc.dg/comp-goto-6.c > b/gcc/testsuite/gcc.dg/comp-goto-6.c > new file mode 100644 > index 00000000000..497f6cd76ca > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/comp-goto-6.c > @@ -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; } > + > -- > 2.17.1 >
Maybe add to one of the testcases a test to ensure that the cast-to-void workaround works successfully? e.g. void foo2(void *a) { goto *(void *)10000000; } /* { dg-bogus "computed goto must be pointer type" } */