tree.cc: Add tree_builtin_call_types_compatible_p [PR105150]
And here is the follow-up patch that does the argument checking on GENERIC. It ensures TYPE_MAIN_VARIANT == TYPE_MAIN_VARIANT compatibility on the arguments, except for pointer arguments where both builtin's prototype and actual arguments have to be pointers and satisfy tree_nop_conversion_p, and for promoted char/short arguments where argument need to have integral signed type tree_nop_conversion_p compatible with integer_type_node. 2022-04-07 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/105150 * tree.cc (tree_builtin_call_types_compatible_p): New function. (get_call_combined_fn): Use it. * gcc.dg/pr105150.c: New test.
This commit is contained in:
parent
54ed6563d2
commit
973a2ce71f
8
gcc/testsuite/gcc.dg/pr105150.c
Normal file
8
gcc/testsuite/gcc.dg/pr105150.c
Normal file
@ -0,0 +1,8 @@
|
||||
/* PR tree-optimization/105150 */
|
||||
/* { dg-options "-w -Ofast" } */
|
||||
|
||||
#define A(name) __typeof (__builtin_##name (0)) name (); \
|
||||
float name##1 () { return !name (1); } \
|
||||
double name##2 () { return name (1.0L); }
|
||||
#define B(name) A(name) A(name##l)
|
||||
B (sqrt)
|
57
gcc/tree.cc
57
gcc/tree.cc
@ -8406,6 +8406,59 @@ get_callee_fndecl (const_tree call)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Return true when STMTs arguments and return value match those of FNDECL,
|
||||
a decl of a builtin function. */
|
||||
|
||||
static bool
|
||||
tree_builtin_call_types_compatible_p (const_tree call, tree fndecl)
|
||||
{
|
||||
gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
|
||||
|
||||
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
|
||||
if (tree decl = builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl)))
|
||||
fndecl = decl;
|
||||
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (call))
|
||||
!= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))))
|
||||
return false;
|
||||
|
||||
tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
|
||||
unsigned nargs = call_expr_nargs (call);
|
||||
for (unsigned i = 0; i < nargs; ++i, targs = TREE_CHAIN (targs))
|
||||
{
|
||||
/* Variadic args follow. */
|
||||
if (!targs)
|
||||
return true;
|
||||
tree arg = CALL_EXPR_ARG (call, i);
|
||||
tree type = TREE_VALUE (targs);
|
||||
if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
|
||||
{
|
||||
/* For pointer arguments be more forgiving, e.g. due to
|
||||
FILE * vs. fileptr_type_node, or say char * vs. const char *
|
||||
differences etc. */
|
||||
if (POINTER_TYPE_P (type)
|
||||
&& POINTER_TYPE_P (TREE_TYPE (arg))
|
||||
&& tree_nop_conversion_p (type, TREE_TYPE (arg)))
|
||||
continue;
|
||||
/* char/short integral arguments are promoted to int
|
||||
by several frontends if targetm.calls.promote_prototypes
|
||||
is true. Allow such promotion too. */
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (arg))
|
||||
&& !TYPE_UNSIGNED (TREE_TYPE (arg))
|
||||
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl))
|
||||
&& tree_nop_conversion_p (integer_type_node,
|
||||
TREE_TYPE (arg)))
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If CALL_EXPR CALL calls a normal built-in function or an internal function,
|
||||
return the associated function code, otherwise return CFN_LAST. */
|
||||
|
||||
@ -8419,7 +8472,9 @@ get_call_combined_fn (const_tree call)
|
||||
return as_combined_fn (CALL_EXPR_IFN (call));
|
||||
|
||||
tree fndecl = get_callee_fndecl (call);
|
||||
if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
|
||||
if (fndecl
|
||||
&& fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
|
||||
&& tree_builtin_call_types_compatible_p (call, fndecl))
|
||||
return as_combined_fn (DECL_FUNCTION_CODE (fndecl));
|
||||
|
||||
return CFN_LAST;
|
||||
|
Loading…
Reference in New Issue
Block a user