c: tree: target: C2x (...) function prototypes and va_start relaxation
authorJoseph Myers <joseph@codesourcery.com>
Fri, 28 Oct 2022 14:40:25 +0000 (14:40 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Fri, 28 Oct 2022 14:40:25 +0000 (14:40 +0000)
commit4fe34cdcc80ac225b80670eabc38ac5e31ce8a5a
treedb3484b3bd407d4efbe918ca7303aa09d68d818a
parent988dd22ec6665117e8587389ac85389f1c321c45
c: tree: target: C2x (...) function prototypes and va_start relaxation

C2x allows function prototypes to be given as (...), a prototype
meaning a variable-argument function with no named arguments.  To
allow such functions to access their arguments, requirements for
va_start calls are relaxed so it ignores all but its first argument
(i.e. subsequent arguments, if any, can be arbitrary pp-token
sequences).

Implement this feature accordingly.  The va_start relaxation in
<stdarg.h> is itself easy: __builtin_va_start already supports a
second argument of 0 instead of a parameter name, and calls get
converted internally to the form using 0 for that argument, so
<stdarg.h> just needs changing to use a variadic macro that passes 0
as the second argument of __builtin_va_start.  (This is done only in
C2x mode, on the expectation that users of older standard would expect
unsupported uses of va_start to be diagnosed.)

For the (...) functions, it's necessary to distinguish these from
unprototyped functions, whereas previously C++ (...) functions and
unprototyped functions both used NULL TYPE_ARG_TYPES.  A flag is added
to tree_type_common to mark the (...) functions; as discussed on gcc@,
doing things this way is likely to be safer for unchanged code in GCC
than adding a different form of representation in TYPE_ARG_TYPES, or
adding a flag that instead signals that the function is unprototyped.

There was previously an option
-fallow-parameterless-variadic-functions to enable support for (...)
prototypes.  The support was incomplete - it treated the functions as
unprototyped, and only parsed some declarations, not e.g.
"int g (int (...));".  This option is changed into a no-op ignored
option; (...) is always accepted syntactically, with a pedwarn_c11
call to given required diagnostics when appropriate.  The peculiarity
of a parameter list with __attribute__ followed by '...' being
accepted with that option is removed.

Interfaces in tree.cc that create function types are adjusted to set
this flag as appropriate.  It is of course possible that some existing
users of the functions to create variable-argument functions actually
wanted unprototyped functions in the no-named-argument case, rather
than functions with a (...) prototype; some such cases in c-common.cc
(for built-in functions and implicit function declarations) turn out
to need updating for that reason.

I didn't do anything to change how the C++ front end creates (...)
function types.  It's very likely there are unchanged places in the
compiler that in fact turn out to need changes to work properly with
(...) function prototypes.

Target setup_incoming_varargs hooks, where they used the information
passed about the last named argument, needed updating to avoid using
that information in the (...) case.  Note that apart from the x86
changes, I haven't done any testing of those target changes beyond
building cc1 to check for syntax errors.  It's possible further
target-specific fixes will be needed; target maintainers should watch
out for failures of c2x-stdarg-4.c or c2x-stdarg-split-1a.c, the
execution tests, which would indicate that this feature is not working
correctly.  Those tests also verify the case where there are named
arguments but the last named argument has a declaration that results
in undefined behavior in previous C standard versions, such as a type
changed by the default argument promotions.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

gcc/
* config/aarch64/aarch64.cc (aarch64_setup_incoming_varargs):
Check TYPE_NO_NAMED_ARGS_STDARG_P.
* config/alpha/alpha.cc (alpha_setup_incoming_varargs): Likewise.
* config/arc/arc.cc (arc_setup_incoming_varargs): Likewise.
* config/arm/arm.cc (arm_setup_incoming_varargs): Likewise.
* config/csky/csky.cc (csky_setup_incoming_varargs): Likewise.
* config/epiphany/epiphany.cc (epiphany_setup_incoming_varargs):
Likewise.
* config/fr30/fr30.cc (fr30_setup_incoming_varargs): Likewise.
* config/frv/frv.cc (frv_setup_incoming_varargs): Likewise.
* config/ft32/ft32.cc (ft32_setup_incoming_varargs): Likewise.
* config/i386/i386.cc (ix86_setup_incoming_varargs): Likewise.
* config/ia64/ia64.cc (ia64_setup_incoming_varargs): Likewise.
* config/loongarch/loongarch.cc
(loongarch_setup_incoming_varargs): Likewise.
* config/m32r/m32r.cc (m32r_setup_incoming_varargs): Likewise.
* config/mcore/mcore.cc (mcore_setup_incoming_varargs): Likewise.
* config/mips/mips.cc (mips_setup_incoming_varargs): Likewise.
* config/mmix/mmix.cc (mmix_setup_incoming_varargs): Likewise.
* config/nds32/nds32.cc (nds32_setup_incoming_varargs): Likewise.
* config/nios2/nios2.cc (nios2_setup_incoming_varargs): Likewise.
* config/riscv/riscv.cc (riscv_setup_incoming_varargs): Likewise.
* config/rs6000/rs6000-call.cc (setup_incoming_varargs): Likewise.
* config/sh/sh.cc (sh_setup_incoming_varargs): Likewise.
* config/visium/visium.cc (visium_setup_incoming_varargs):
Likewise.
* config/vms/vms-c.cc (vms_c_common_override_options): Do not set
flag_allow_parameterless_variadic_functions.
* doc/invoke.texi (-fallow-parameterless-variadic-functions): Do
not document option.
* function.cc (assign_parms): Call assign_parms_setup_varargs for
TYPE_NO_NAMED_ARGS_STDARG_P case.
* ginclude/stdarg.h [__STDC_VERSION__ > 201710L] (va_start): Make
variadic macro.  Pass second argument of 0 to __builtin_va_start.
* target.def (setup_incoming_varargs): Update documentation.
* doc/tm.texi: Regenerate.
* tree-core.h (struct tree_type_common): Add
no_named_args_stdarg_p.
* tree-streamer-in.cc (unpack_ts_type_common_value_fields): Unpack
TYPE_NO_NAMED_ARGS_STDARG_P.
* tree-streamer-out.cc (pack_ts_type_common_value_fields): Pack
TYPE_NO_NAMED_ARGS_STDARG_P.
* tree.cc (type_cache_hasher::equal): Compare
TYPE_NO_NAMED_ARGS_STDARG_P.
(build_function_type): Add argument no_named_args_stdarg_p.
(build_function_type_list_1, build_function_type_array_1)
(reconstruct_complex_type): Update calls to build_function_type.
(stdarg_p, prototype_p): Return true for (...) functions.
(gimple_canonical_types_compatible_p): Compare
TYPE_NO_NAMED_ARGS_STDARG_P.
* tree.h (TYPE_NO_NAMED_ARGS_STDARG_P): New.
(build_function_type): Update prototype.

gcc/c-family/
* c-common.cc (def_fn_type): Call build_function_type for
zero-argument variable-argument function.
(c_common_nodes_and_builtins): Build default_function_type with
build_function_type.
* c.opt (fallow-parameterless-variadic-functions): Mark as ignored
option.

gcc/c/
* c-decl.cc (grokdeclarator): Pass
arg_info->no_named_args_stdarg_p to build_function_type.
(grokparms): Check arg_info->no_named_args_stdarg_p before
converting () to (void).
(build_arg_info): Initialize no_named_args_stdarg_p.
(get_parm_info): Set no_named_args_stdarg_p.
(start_function): Pass TYPE_NO_NAMED_ARGS_STDARG_P to
build_function_type.
(store_parm_decls): Count (...) functions as prototyped.
* c-parser.cc (c_parser_direct_declarator): Allow '...' after open
parenthesis to start parameter list.
(c_parser_parms_list_declarator): Always allow '...' with no
arguments, call pedwarn_c11 and set no_named_args_stdarg_p.
* c-tree.h (struct c_arg_info): Add field no_named_args_stdarg_p.
* c-typeck.cc (composite_type): Handle
TYPE_NO_NAMED_ARGS_STDARG_P.
(function_types_compatible_p): Compare
TYPE_NO_NAMED_ARGS_STDARG_P.

gcc/fortran/
* trans-types.cc (gfc_get_function_type): Do not use
build_varargs_function_type_vec for unprototyped function.

gcc/lto/
* lto-common.cc (compare_tree_sccs_1): Compare
TYPE_NO_NAMED_ARGS_STDARG_P.

gcc/objc/
* objc-next-runtime-abi-01.cc (build_next_objc_exception_stuff):
Use build_function_type to build type of objc_setjmp_decl.

gcc/testsuite/
* gcc.dg/c11-stdarg-1.c, gcc.dg/c11-stdarg-2.c,
gcc.dg/c11-stdarg-3.c, gcc.dg/c2x-stdarg-1.c,
gcc.dg/c2x-stdarg-2.c, gcc.dg/c2x-stdarg-3.c,
gcc.dg/c2x-stdarg-4.c, gcc.dg/gnu2x-stdarg-1.c,
gcc.dg/torture/c2x-stdarg-split-1a.c,
gcc.dg/torture/c2x-stdarg-split-1b.c: New tests.
* gcc.dg/Wold-style-definition-2.c, gcc.dg/format/sentinel-1.c:
Update expected diagnostics.
* gcc.dg/c2x-nullptr-1.c (test5): Cast unused parameter to (void).
* gcc.dg/diagnostic-token-ranges.c: Use -pedantic.  Expect warning
in place of error.
56 files changed:
gcc/c-family/c-common.cc
gcc/c-family/c.opt
gcc/c/c-decl.cc
gcc/c/c-parser.cc
gcc/c/c-tree.h
gcc/c/c-typeck.cc
gcc/config/aarch64/aarch64.cc
gcc/config/alpha/alpha.cc
gcc/config/arc/arc.cc
gcc/config/arm/arm.cc
gcc/config/csky/csky.cc
gcc/config/epiphany/epiphany.cc
gcc/config/fr30/fr30.cc
gcc/config/frv/frv.cc
gcc/config/ft32/ft32.cc
gcc/config/i386/i386.cc
gcc/config/ia64/ia64.cc
gcc/config/loongarch/loongarch.cc
gcc/config/m32r/m32r.cc
gcc/config/mcore/mcore.cc
gcc/config/mips/mips.cc
gcc/config/mmix/mmix.cc
gcc/config/nds32/nds32.cc
gcc/config/nios2/nios2.cc
gcc/config/riscv/riscv.cc
gcc/config/rs6000/rs6000-call.cc
gcc/config/sh/sh.cc
gcc/config/visium/visium.cc
gcc/config/vms/vms-c.cc
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/fortran/trans-types.cc
gcc/function.cc
gcc/ginclude/stdarg.h
gcc/lto/lto-common.cc
gcc/objc/objc-next-runtime-abi-01.cc
gcc/target.def
gcc/testsuite/gcc.dg/Wold-style-definition-2.c
gcc/testsuite/gcc.dg/c11-stdarg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c11-stdarg-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c11-stdarg-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-nullptr-1.c
gcc/testsuite/gcc.dg/c2x-stdarg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-stdarg-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-stdarg-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-stdarg-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
gcc/testsuite/gcc.dg/format/sentinel-1.c
gcc/testsuite/gcc.dg/gnu2x-stdarg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/c2x-stdarg-split-1b.c [new file with mode: 0644]
gcc/tree-core.h
gcc/tree-streamer-in.cc
gcc/tree-streamer-out.cc
gcc/tree.cc
gcc/tree.h