> Am 10.01.2026 um 09:33 schrieb Jakub Jelinek <[email protected]>:
>
> Hi!
>
> While gimple_call_combined_fn already do call
> gimple_builtin_call_types_compatible_p and for most of builtins ensures
> the right types of arguments, for type generic builtins it does not,
> from POV of that function those functions are rettype (...).
> Now, while the FE does some number of argument checking for the type
> generic builtins, as the testcase below shows, it can be gamed.
>
> So, this patch checks the number of arguments for type generic builtins
> and does nothing if they have unexpected number of arguments.
> Also for the returns arg verifies it can access the first argument.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
LGTM
Richard
> 2026-01-10 Jakub Jelinek <[email protected]>
>
> PR tree-optimization/123431
> * gimple-range-op.cc (gimple_range_op_handler::maybe_builtin_call):
> Punt if type-generic builtins with a single argument don't have
> exactly one argument. For returns_arg punt if call doesn't have
> at least one argument.
>
> * gcc.dg/pr123431.c: New test.
>
> --- gcc/gimple-range-op.cc.jj 2026-01-02 09:56:10.182336262 +0100
> +++ gcc/gimple-range-op.cc 2026-01-09 15:00:01.166808500 +0100
> @@ -1410,6 +1410,8 @@ gimple_range_op_handler::maybe_builtin_c
> switch (func)
> {
> case CFN_BUILT_IN_CONSTANT_P:
> + if (gimple_call_num_args (call) != 1)
> + return;
> m_op1 = gimple_call_arg (call, 0);
> if (irange::supports_p (TREE_TYPE (m_op1)))
> m_operator = &op_cfn_constant_p;
> @@ -1420,21 +1422,29 @@ gimple_range_op_handler::maybe_builtin_c
> break;
>
> CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT):
> + if (gimple_call_num_args (call) != 1)
> + return;
> m_op1 = gimple_call_arg (call, 0);
> m_operator = &op_cfn_signbit;
> break;
>
> CASE_FLT_FN (CFN_BUILT_IN_ISINF):
> + if (gimple_call_num_args (call) != 1)
> + return;
> m_op1 = gimple_call_arg (call, 0);
> m_operator = &op_cfn_isinf;
> break;
>
> case CFN_BUILT_IN_ISFINITE:
> + if (gimple_call_num_args (call) != 1)
> + return;
> m_op1 = gimple_call_arg (call, 0);
> m_operator = &op_cfn_isfinite;
> break;
>
> case CFN_BUILT_IN_ISNORMAL:
> + if (gimple_call_num_args (call) != 1)
> + return;
> m_op1 = gimple_call_arg (call, 0);
> m_operator = &op_cfn_isnormal;
> break;
> @@ -1565,7 +1575,9 @@ gimple_range_op_handler::maybe_builtin_c
> default:
> {
> unsigned arg;
> - if (gimple_call_fnspec (call).returns_arg (&arg) && arg == 0)
> + if (gimple_call_fnspec (call).returns_arg (&arg)
> + && arg == 0
> + && gimple_call_num_args (call) > 0)
> {
> m_op1 = gimple_call_arg (call, 0);
> m_operator = &op_cfn_pass_through_arg1;
> --- gcc/testsuite/gcc.dg/pr123431.c.jj 2026-01-09 15:10:58.084406597 +0100
> +++ gcc/testsuite/gcc.dg/pr123431.c 2026-01-09 15:10:20.589057380 +0100
> @@ -0,0 +1,19 @@
> +/* PR tree-optimization/123431 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +extern void foo (int);
> +
> +extern inline __attribute__((always_inline)) void
> +bar (int x, ...)
> +{
> + if (__builtin_constant_p (__builtin_va_arg_pack ()))
> + foo (x);
> +}
> +
> +void
> +baz (int x)
> +{
> + bar (1, 2);
> + bar (3, x);
> +}
>
> Jakub
>