aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-04-07 09:10:58 +0200
committerJakub Jelinek <jakub@redhat.com>2022-04-07 09:10:58 +0200
commit973a2ce71f8dab559fbbfc34b59e39e047df74a6 (patch)
treed64131cc4473fd71c8a1a1a06fb344f5f164baf2
parent54ed6563d22694aa3e1935f89641a4f696a3a9f7 (diff)
downloadgcc-973a2ce71f8dab559fbbfc34b59e39e047df74a6.zip
gcc-973a2ce71f8dab559fbbfc34b59e39e047df74a6.tar.gz
gcc-973a2ce71f8dab559fbbfc34b59e39e047df74a6.tar.bz2
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.
-rw-r--r--gcc/testsuite/gcc.dg/pr105150.c8
-rw-r--r--gcc/tree.cc57
2 files changed, 64 insertions, 1 deletions
diff --git a/gcc/testsuite/gcc.dg/pr105150.c b/gcc/testsuite/gcc.dg/pr105150.c
new file mode 100644
index 0000000..900460c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr105150.c
@@ -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)
diff --git a/gcc/tree.cc b/gcc/tree.cc
index ec200e9..8f83ea1 100644
--- a/gcc/tree.cc
+++ b/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;