c: [PR32122] Require pointer types for computed gotos
authorAndrew Pinski <apinski@marvell.com>
Fri, 17 Sep 2021 04:59:03 +0000 (04:59 +0000)
committerAndrew Pinski <apinski@marvell.com>
Tue, 28 Sep 2021 20:01:14 +0000 (20:01 +0000)
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
gcc/c/c-tree.h
gcc/c/c-typeck.c
gcc/testsuite/gcc.dg/comp-goto-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/comp-goto-6.c [new file with mode: 0644]

index fa29d2c..21ff25d 100644 (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 %<*%>");
index d50d0cb..a046c6b 100644 (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);
index 49d1bb0..b472e44 100644 (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);
diff --git a/gcc/testsuite/gcc.dg/comp-goto-5.c b/gcc/testsuite/gcc.dg/comp-goto-5.c
new file mode 100644 (file)
index 0000000..d487729
--- /dev/null
@@ -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 (file)
index 0000000..497f6cd
--- /dev/null
@@ -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; }
+