]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/59630 (ICE converting the return type of a builtin function)
authorRichard Biener <rguenther@suse.de>
Wed, 8 Jan 2014 09:06:27 +0000 (09:06 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 8 Jan 2014 09:06:27 +0000 (09:06 +0000)
2014-01-08  Richard Biener  <rguenther@suse.de>

PR middle-end/59630
* gimple.h (is_gimple_builtin_call): Remove.
(gimple_builtin_call_types_compatible_p): New.
(gimple_call_builtin_p): New overload.
* gimple.c (is_gimple_builtin_call): Remove.
(validate_call): Rename to ...
(gimple_builtin_call_types_compatible_p): ... this and export.  Also
check return types.
(validate_type): New static function.
(gimple_call_builtin_p): New overload and adjust.
* gimple-fold.c (gimple_fold_builtin): Fold the return value.
(gimple_fold_call): Likewise.  Use gimple_call_builtin_p.
(gimple_fold_stmt_to_constant_1): Likewise.
* tsan.c (instrument_gimple): Use gimple_call_builtin_p.

* gcc.dg/pr59630.c: New testcase.

From-SVN: r206421

gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple.c
gcc/gimple.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr59630.c [new file with mode: 0644]
gcc/tsan.c

index 1f7c1a504774152d90a3e6d047d8c454d0ca6cef..78a5da489a1f4e159e890e2d34ee1d2eac2be0c0 100644 (file)
@@ -1,3 +1,20 @@
+2014-01-08  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/59630
+       * gimple.h (is_gimple_builtin_call): Remove.
+       (gimple_builtin_call_types_compatible_p): New.
+       (gimple_call_builtin_p): New overload.
+       * gimple.c (is_gimple_builtin_call): Remove.
+       (validate_call): Rename to ...
+       (gimple_builtin_call_types_compatible_p): ... this and export.  Also
+       check return types.
+       (validate_type): New static function.
+       (gimple_call_builtin_p): New overload and adjust.
+       * gimple-fold.c (gimple_fold_builtin): Fold the return value.
+       (gimple_fold_call): Likewise.  Use gimple_call_builtin_p.
+       (gimple_fold_stmt_to_constant_1): Likewise.
+       * tsan.c (instrument_gimple): Use gimple_call_builtin_p.
+
 2014-01-08  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/59471
index dd45a4a169439c713052b6f2c629ddec5abc5d11..91fc2970924cea58695d7afda58489dc3f618028 100644 (file)
@@ -879,8 +879,6 @@ gimple_fold_builtin (gimple stmt)
   int nargs;
   location_t loc = gimple_location (stmt);
 
-  gcc_assert (is_gimple_call (stmt));
-
   ignore = (gimple_call_lhs (stmt) == NULL);
 
   /* First try the generic builtin folder.  If that succeeds, return the
@@ -890,6 +888,8 @@ gimple_fold_builtin (gimple stmt)
     {
       if (ignore)
        STRIP_NOPS (result);
+      else
+       result = fold_convert (gimple_call_return_type (stmt), result);
       return result;
     }
 
@@ -1206,8 +1206,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
 
   /* Check for builtins that CCP can handle using information not
      available in the generic fold routines.  */
-  callee = gimple_call_fndecl (stmt);
-  if (callee && DECL_BUILT_IN (callee))
+  if (gimple_call_builtin_p (stmt))
     {
       tree result = gimple_fold_builtin (stmt);
       if (result)
@@ -1216,7 +1215,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
            gimplify_and_update_call_from_tree (gsi, result);
          changed = true;
        }
-      else if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
+      else if (gimple_call_builtin_p (stmt, BUILT_IN_MD))
        changed |= targetm.gimple_fold_builtin (gsi);
     }
 
@@ -2726,7 +2725,9 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
        fn = (*valueize) (gimple_call_fn (stmt));
        if (TREE_CODE (fn) == ADDR_EXPR
            && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
-           && DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
+           && DECL_BUILT_IN (TREE_OPERAND (fn, 0))
+           && gimple_builtin_call_types_compatible_p (stmt,
+                                                      TREE_OPERAND (fn, 0)))
          {
            tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt));
            tree call, retval;
@@ -2738,8 +2739,11 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
                                         fn, gimple_call_num_args (stmt), args);
            retval = fold_call_expr (EXPR_LOCATION (call), call, false);
            if (retval)
-             /* fold_call_expr wraps the result inside a NOP_EXPR.  */
-             STRIP_NOPS (retval);
+             {
+               /* fold_call_expr wraps the result inside a NOP_EXPR.  */
+               STRIP_NOPS (retval);
+               retval = fold_convert (gimple_call_return_type (stmt), retval);
+             }
            return retval;
          }
        return NULL_TREE;
index 6075e6d512671ccf6d2624e5d56878c6366252dc..e9851ca386a2e75a22104691b1cbf7c244e30a3a 100644 (file)
@@ -2351,27 +2351,37 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
 }
 
 
-/* Return TRUE iff stmt is a call to a built-in function.  */
+/* Return true if TYPE1 and TYPE2 are compatible enough for builtin
+   processing.  */
 
-bool
-is_gimple_builtin_call (gimple stmt)
-{
-  tree callee;
-
-  if (is_gimple_call (stmt)
-      && (callee = gimple_call_fndecl (stmt))
-      && is_builtin_fn (callee)
-      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
-    return true;
-
-  return false;
+static bool
+validate_type (tree type1, tree type2)
+{
+  if (INTEGRAL_TYPE_P (type1)
+      && INTEGRAL_TYPE_P (type2))
+    ;
+  else if (POINTER_TYPE_P (type1)
+          && POINTER_TYPE_P (type2))
+    ;
+  else if (TREE_CODE (type1)
+          != TREE_CODE (type2))
+    return false;
+  return true;
 }
 
-/* Return true when STMTs arguments match those of FNDECL.  */
+/* Return true when STMTs arguments and return value match those of FNDECL,
+   a decl of a builtin function.  */
 
-static bool
-validate_call (gimple stmt, tree fndecl)
+bool
+gimple_builtin_call_types_compatible_p (gimple stmt, tree fndecl)
 {
+  gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
+
+  tree ret = gimple_call_lhs (stmt);
+  if (ret
+      && !validate_type (TREE_TYPE (ret), TREE_TYPE (TREE_TYPE (fndecl))))
+    return false;
+
   tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
   unsigned nargs = gimple_call_num_args (stmt);
   for (unsigned i = 0; i < nargs; ++i)
@@ -2380,14 +2390,7 @@ validate_call (gimple stmt, tree fndecl)
       if (!targs)
        return true;
       tree arg = gimple_call_arg (stmt, i);
-      if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
-         && INTEGRAL_TYPE_P (TREE_VALUE (targs)))
-       ;
-      else if (POINTER_TYPE_P (TREE_TYPE (arg))
-              && POINTER_TYPE_P (TREE_VALUE (targs)))
-       ;
-      else if (TREE_CODE (TREE_TYPE (arg))
-              != TREE_CODE (TREE_VALUE (targs)))
+      if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs)))
        return false;
       targs = TREE_CHAIN (targs);
     }
@@ -2396,6 +2399,19 @@ validate_call (gimple stmt, tree fndecl)
   return true;
 }
 
+/* Return true when STMT is builtins call.  */
+
+bool
+gimple_call_builtin_p (gimple stmt)
+{
+  tree fndecl;
+  if (is_gimple_call (stmt)
+      && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+      && DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN)
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
+  return false;
+}
+
 /* Return true when STMT is builtins call to CLASS.  */
 
 bool
@@ -2405,7 +2421,7 @@ gimple_call_builtin_p (gimple stmt, enum built_in_class klass)
   if (is_gimple_call (stmt)
       && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
       && DECL_BUILT_IN_CLASS (fndecl) == klass)
-    return validate_call (stmt, fndecl);
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
   return false;
 }
 
@@ -2419,7 +2435,7 @@ gimple_call_builtin_p (gimple stmt, enum built_in_function code)
       && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 
       && DECL_FUNCTION_CODE (fndecl) == code)
-    return validate_call (stmt, fndecl);
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
   return false;
 }
 
index df92863699be114b622968a0939d1721620d1911..0e80d2eb700245a6ed268e18940bf747cc613747 100644 (file)
@@ -1253,7 +1253,8 @@ extern tree gimple_unsigned_type (tree);
 extern tree gimple_signed_type (tree);
 extern alias_set_type gimple_get_alias_set (tree);
 extern bool gimple_ior_addresses_taken (bitmap, gimple);
-extern bool is_gimple_builtin_call (gimple stmt);
+extern bool gimple_builtin_call_types_compatible_p (gimple, tree);
+extern bool gimple_call_builtin_p (gimple);
 extern bool gimple_call_builtin_p (gimple, enum built_in_class);
 extern bool gimple_call_builtin_p (gimple, enum built_in_function);
 extern bool gimple_asm_clobbers_memory_p (const_gimple);
index 3ebbab41be344f9eaba103fe987cf53115e88ab2..d113f2a09e46e2eba68cc72c1916d04da220e870 100644 (file)
@@ -1,3 +1,8 @@
+2014-01-08  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/59630
+       * gcc.dg/pr59630.c: New testcase.
+
 2014-01-08  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/59471
diff --git a/gcc/testsuite/gcc.dg/pr59630.c b/gcc/testsuite/gcc.dg/pr59630.c
new file mode 100644 (file)
index 0000000..6a3c725
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+_Bool foo()
+{
+  _Bool (*f)(int) = __builtin_abs; /* { dg-warning "" } */
+  return f(0);
+}
index 2c053bd9e34076ca543f0801c93a6864820ef186..2e32cd2b32f7bb46fd79472e1b4f228607146a17 100644 (file)
@@ -609,7 +609,7 @@ instrument_gimple (gimple_stmt_iterator *gsi)
       && (gimple_call_fndecl (stmt)
          != builtin_decl_implicit (BUILT_IN_TSAN_INIT)))
     {
-      if (is_gimple_builtin_call (stmt))
+      if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
        instrument_builtin_call (gsi);
       return true;
     }