This patch fixes the ICE according to comment #10 in the PR.


Bootstrapped and regression tested on x86_64.


When array type is passed to va_arg, this is undefined behavior.
Emit a warning and insert a run-time trap after evaluating side effects,
but return the correct type for sizeof / typeof.  For C90 a VLA is an
error.

        PR c/97986

gcc/c/ChangeLog:
        * c-parser.cc (c_parser_postfix_expression): Adapt.
        * c-typeck.cc (c_build_va_arg): Handle UB.

gcc/testsuite/ChangeLog:
        * gcc.dg/pr97986-1.c: New test.
        * gcc.dg/pr97986-2.c: New test.
---
 gcc/c/c-parser.cc                | 10 ++--------
 gcc/c/c-tree.h                   |  2 +-
 gcc/c/c-typeck.cc                | 31 +++++++++++++++++++++++++++++--
 gcc/testsuite/gcc.dg/pr97986-1.c | 28 ++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/pr97986-2.c | 15 +++++++++++++++
 5 files changed, 75 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr97986-1.c
 create mode 100644 gcc/testsuite/gcc.dg/pr97986-2.c

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 0cf3f92a72c..a559a4e6a06 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -11793,15 +11793,9 @@ c_parser_postfix_expression (c_parser *parser)
            else
              {
                tree type_expr = NULL_TREE;
+               tree type = groktypename (t1, &type_expr, NULL);
                expr.value = c_build_va_arg (start_loc, e1.value, loc,
-                                            groktypename (t1, &type_expr, 
NULL));
-               if (type_expr)
-                 {
-                   expr.value = build2 (C_MAYBE_CONST_EXPR,
-                                        TREE_TYPE (expr.value), type_expr,
-                                        expr.value);
-                   C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
-                 }
+                                            type, type_expr);
                set_c_expr_source_range (&expr, start_loc, end_loc);
              }
          }
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index f367cda35d7..ff63d69e85d 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -917,7 +917,7 @@ extern tree c_omp_finish_mapper_clauses (tree);
 extern tree c_omp_mapper_lookup (tree, tree);
 extern tree c_omp_extract_mapper_directive (tree);
 extern tree c_omp_map_array_section (location_t, tree);
-extern tree c_build_va_arg (location_t, tree, location_t, tree);
+extern tree c_build_va_arg (location_t, tree, location_t, tree, tree);
 extern tree c_finish_transaction (location_t, tree, int);
 extern bool c_tree_equal (tree, tree);
 extern tree c_build_function_call_vec (location_t, const vec<location_t>&,
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index bc0fb6b59e5..b965f9ee416 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -18435,7 +18435,8 @@ c_build_qualified_type (tree type, int type_quals, tree 
orig_qual_type,
 /* Build a VA_ARG_EXPR for the C parser.  */
 
 tree
-c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type)
+c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type,
+               tree type_expr)
 {
   if (error_operand_p (type))
     return error_mark_node;
@@ -18459,10 +18460,36 @@ c_build_va_arg (location_t loc1, tree expr, 
location_t loc2, tree type)
                type);
       return error_mark_node;
     }
+  else if (TREE_CODE (type) == ARRAY_TYPE && C_TYPE_VARIABLE_SIZE (type)
+          && !flag_isoc99)
+    {
+      error_at (loc2, "second argument to %<va_arg%> is an array type %qT",
+               type);
+      return  error_mark_node;
+    }
   else if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE)
     warning_at (loc2, OPT_Wc___compat,
                "C++ requires promoted type, not enum type, in %<va_arg%>");
-  return build_va_arg (loc2, expr, type);
+
+  if (flag_isoc99 && TREE_CODE (type) == ARRAY_TYPE)
+    {
+      warning_at (loc2, 0, "second argument to %<va_arg%> is an array type 
%qT",
+                 type);
+      /* We create a trap but evaluate side effects first.  */
+      tree trapfn = builtin_decl_explicit (BUILT_IN_TRAP);
+      trapfn = build_call_expr_loc (loc2, trapfn, 0);
+      tree e2 = build2 (COMPOUND_EXPR, void_type_node, expr, trapfn);
+      /* Return a compound literal of the right type.  */
+      tree e1 = build_compound_literal (loc2, type, NULL, true, 0, NULL);
+      expr = build2 (COMPOUND_EXPR, type, e2, e1);
+    }
+  else
+    expr = build_va_arg (loc2, expr, type);
+
+  if (type_expr)
+    expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), type_expr, expr);
+
+  return expr;
 }
 
 /* Return truthvalue of whether T1 is the same tree structure as T2.
diff --git a/gcc/testsuite/gcc.dg/pr97986-1.c b/gcc/testsuite/gcc.dg/pr97986-1.c
new file mode 100644
index 00000000000..3824fb4e143
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97986-1.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-std=gnu23" } */
+
+#include <stdarg.h>
+
+int f(int n, ...)
+{
+       __label__ b, d;
+       va_list ap;
+       va_start(ap, n);
+       _Static_assert(5 == sizeof(va_arg(ap, char[5])));       /* { dg-warning 
"array type" } */
+       void g(void) { n++; goto b; }
+       int *a = va_arg((g(), ap), int[n]);     /* { dg-warning "array type" } 
*/
+b:
+       void h(void) { n++; goto d; }
+       typeof(va_arg(ap, int[(h(), n)])) c;    /* { dg-warning "array type" } 
*/
+d:
+       return n;
+}
+
+int main()
+{
+       if (9 != f(7))
+               __builtin_abort();
+       return 0;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/pr97986-2.c b/gcc/testsuite/gcc.dg/pr97986-2.c
new file mode 100644
index 00000000000..fc23a57907c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97986-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c90" } */
+
+#include <stdarg.h>
+
+
+int f(int n, ...)
+{
+       va_list ap;
+       va_start(ap, n);
+       _Static_assert(5 == sizeof(va_arg(ap, char[5])));
+       va_arg(ap, int[n]);                     /* { dg-error "array type" } */
+       int * a = va_arg(ap, int[3]);           /* { dg-error "invalid use of 
non-lvalue array" } */
+}
+
-- 
2.47.3

Reply via email to