diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-03-19 09:13:32 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-03-19 09:13:32 +0100 |
commit | 8f85b46337f90c3126b9cefd72ffd29eb9a4ebf3 (patch) | |
tree | 1f5071ccba70038dd5558be9a2acfb7968ebfbc4 /gcc | |
parent | 8959ab63f1881a8a4b1921b946d4ea3986bf1063 (diff) | |
download | gcc-8f85b46337f90c3126b9cefd72ffd29eb9a4ebf3.zip gcc-8f85b46337f90c3126b9cefd72ffd29eb9a4ebf3.tar.gz gcc-8f85b46337f90c3126b9cefd72ffd29eb9a4ebf3.tar.bz2 |
rs6000: Fix up setup_incoming_varargs [PR114175]
The c23-stdarg-8.c test (as well as the new test below added to cover even
more cases) FAIL on powerpc64le-linux and presumably other powerpc* targets
as well.
Like in the r14-9503-g218d174961 change on x86-64 we need to advance
next_cum after the hidden return pointer argument even in case where
there are no user arguments before ... in C23.
The following patch does that.
There is another TYPE_NO_NAMED_ARGS_STDARG_P use later on:
if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))
&& targetm.calls.must_pass_in_stack (arg))
first_reg_offset += rs6000_arg_size (TYPE_MODE (arg.type), arg.type);
but I believe it was added there in r13-3549-g4fe34cdc unnecessarily,
when there is no hidden return pointer argument, arg.type is NULL and
must_pass_in_stack_var_size as well as must_pass_in_stack_var_size_or_pad
return false in that case, and for the TYPE_NO_NAMED_ARGS_STDARG_P
case with hidden return pointer argument that argument should have pointer
type and it is the first argument, so must_pass_in_stack shouldn't be true
for it either.
2024-03-19 Jakub Jelinek <jakub@redhat.com>
PR target/114175
* config/rs6000/rs6000-call.cc (setup_incoming_varargs): Only skip
rs6000_function_arg_advance_1 for TYPE_NO_NAMED_ARGS_STDARG_P functions
if arg.type is NULL.
* gcc.dg/c23-stdarg-9.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/rs6000/rs6000-call.cc | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c23-stdarg-9.c | 284 |
2 files changed, 286 insertions, 1 deletions
diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc index 8c59090..1f8f93a 100644 --- a/gcc/config/rs6000/rs6000-call.cc +++ b/gcc/config/rs6000/rs6000-call.cc @@ -2253,7 +2253,8 @@ setup_incoming_varargs (cumulative_args_t cum, /* Skip the last named argument. */ next_cum = *get_cumulative_args (cum); - if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))) + if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)) + || arg.type != NULL_TREE) rs6000_function_arg_advance_1 (&next_cum, arg.mode, arg.type, arg.named, 0); diff --git a/gcc/testsuite/gcc.dg/c23-stdarg-9.c b/gcc/testsuite/gcc.dg/c23-stdarg-9.c new file mode 100644 index 0000000..e2839e7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-stdarg-9.c @@ -0,0 +1,284 @@ +/* Test C23 variadic functions with no named parameters, or last named + parameter with a declaration not allowed in C17. Execution tests. */ +/* { dg-do run } */ +/* { dg-options "-O2 -std=c23 -pedantic-errors" } */ + +#include <stdarg.h> + +struct S { int a[1024]; }; + +int +f1 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +int +f2 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +int +f3 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +int +f4 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +int +f5 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +int +f6 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +int +f7 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +int +f8 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + return r; +} + +struct S +s1 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +struct S +s2 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +struct S +s3 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +struct S +s4 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +struct S +s5 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +struct S +s6 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +struct S +s7 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +struct S +s8 (...) +{ + int r = 0; + va_list ap; + va_start (ap); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + r += va_arg (ap, int); + va_end (ap); + struct S s = {}; + s.a[0] = r; + return s; +} + +int +b1 (void) +{ + return f8 (1, 2, 3, 4, 5, 6, 7, 8); +} + +int +b2 (void) +{ + return s8 (1, 2, 3, 4, 5, 6, 7, 8).a[0]; +} + +int +main () +{ + if (f1 (1) != 1 || f2 (1, 2) != 3 || f3 (1, 2, 3) != 6 + || f4 (1, 2, 3, 4) != 10 || f5 (1, 2, 3, 4, 5) != 15 + || f6 (1, 2, 3, 4, 5, 6) != 21 || f7 (1, 2, 3, 4, 5, 6, 7) != 28 + || f8 (1, 2, 3, 4, 5, 6, 7, 8) != 36) + __builtin_abort (); + if (s1 (1).a[0] != 1 || s2 (1, 2).a[0] != 3 || s3 (1, 2, 3).a[0] != 6 + || s4 (1, 2, 3, 4).a[0] != 10 || s5 (1, 2, 3, 4, 5).a[0] != 15 + || s6 (1, 2, 3, 4, 5, 6).a[0] != 21 + || s7 (1, 2, 3, 4, 5, 6, 7).a[0] != 28 + || s8 (1, 2, 3, 4, 5, 6, 7, 8).a[0] != 36) + __builtin_abort (); +} |