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
|
@ -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 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,
|
/* If CALL_EXPR CALL calls a normal built-in function or an internal function,
|
||||||
return the associated function code, otherwise return CFN_LAST. */
|
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));
|
return as_combined_fn (CALL_EXPR_IFN (call));
|
||||||
|
|
||||||
tree fndecl = get_callee_fndecl (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 as_combined_fn (DECL_FUNCTION_CODE (fndecl));
|
||||||
|
|
||||||
return CFN_LAST;
|
return CFN_LAST;
|
||||||
|
|
Loading…
Reference in New Issue