aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-03-03 09:55:19 +0100
committerJakub Jelinek <jakub@redhat.com>2021-03-03 09:55:19 +0100
commitba09d11a9d0ae2382bab715b102a7746d20dea6d (patch)
treef44640d66c203477a0a7bf3fc80e292093920e72
parentb5040344b9ca609e19ee59ba56cd4af9697a1692 (diff)
downloadgcc-ba09d11a9d0ae2382bab715b102a7746d20dea6d.zip
gcc-ba09d11a9d0ae2382bab715b102a7746d20dea6d.tar.gz
gcc-ba09d11a9d0ae2382bab715b102a7746d20dea6d.tar.bz2
c-family: Avoid ICE on va_arg [PR99324]
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.
-rw-r--r--gcc/c-family/c-common.c6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr99324.c19
2 files changed, 22 insertions, 3 deletions
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 088626d..d227686 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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
index 0000000..7a41e5c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr99324.c
@@ -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;
+}