c-family: Avoid ICE on va_arg [PR99324]
authorJakub Jelinek <jakub@redhat.com>
Wed, 3 Mar 2021 08:55:19 +0000 (09:55 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 3 Mar 2021 08:55:19 +0000 (09:55 +0100)
build_va_arg calls the middle-end mark_addressable, which e.g. requires that
cfun is non-NULL.  The following patch calls instead c_common_mark_addressable_vec
which is the c-family variant similarly to the FE c_mark_addressable and
cxx_mark_addressable, except that it doesn't error on addresses of register
variables.  As the taking of the address is artificial for the .VA_ARG
ifn and when that is lowered goes away, it is similar case to the vector
subscripting for which c_common_mark_addressable_vec has been added.

2021-03-03  Jakub Jelinek  <jakub@redhat.com>

PR c/99324
* c-common.c (build_va_arg): Call c_common_mark_addressable_vec
instead of mark_addressable.  Fix a comment typo -
neutrallly -> neutrally.

* gcc.c-torture/compile/pr99324.c: New test.

gcc/c-family/c-common.c
gcc/testsuite/gcc.c-torture/compile/pr99324.c [new file with mode: 0644]

index 088626d..d227686 100644 (file)
@@ -4553,7 +4553,7 @@ build_va_arg (location_t loc, tree expr, tree type)
       if (canon_va_type == NULL_TREE)
        error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
 
-      /* Let's handle things neutrallly, if expr:
+      /* Let's handle things neutrally, if expr:
         - has undeclared type, or
         - is not an va_list type.  */
       return build_va_arg_1 (loc, type, error_mark_node);
@@ -4565,7 +4565,7 @@ build_va_arg (location_t loc, tree expr, tree type)
 
       /* Take the address, to get '&ap'.  Note that &ap is not a va_list
         type.  */
-      mark_addressable (expr);
+      c_common_mark_addressable_vec (expr);
       expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (expr)), expr);
 
       return build_va_arg_1 (loc, type, expr);
@@ -4627,7 +4627,7 @@ build_va_arg (location_t loc, tree expr, tree type)
 
       /* Take the address, to get '&ap'.  Make sure it's a pointer to array
         elem type.  */
-      mark_addressable (expr);
+      c_common_mark_addressable_vec (expr);
       expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (canon_va_type)),
                     expr);
 
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr99324.c b/gcc/testsuite/gcc.c-torture/compile/pr99324.c
new file mode 100644 (file)
index 0000000..7a41e5c
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR c/99324 */
+
+#include <stdarg.h>
+
+int
+foo (int x, ...)
+{
+  va_list a;
+  va_start (a, x);
+  int b[6] = {};
+  int bar (c)
+    int c[1][va_arg (a, int)];
+  {
+    return sizeof c[0];
+  }
+  int r = bar (b);
+  va_end (a);
+  return r;
+}