[PATCH] Fix PR59630

Richard Biener rguenther@suse.de
Tue Jan 7 14:50:00 GMT 2014


This fixes PR59630 by using the appropriate predicates more and
extending them to also verify builtins have matching return type.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2014-01-07  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.

Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h	(revision 206385)
--- gcc/gimple.h	(working copy)
*************** extern tree gimple_unsigned_type (tree);
*** 1253,1259 ****
  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_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);
--- 1253,1260 ----
  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 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: gcc/gimple.c
===================================================================
*** gcc/gimple.c	(revision 206385)
--- gcc/gimple.c	(working copy)
*************** gimple_ior_addresses_taken (bitmap addre
*** 2351,2377 ****
  }
  
  
! /* Return TRUE iff stmt is a call to a built-in function.  */
  
! 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;
  }
  
! /* Return true when STMTs arguments match those of FNDECL.  */
  
! static bool
! validate_call (gimple stmt, tree fndecl)
  {
    tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
    unsigned nargs = gimple_call_num_args (stmt);
    for (unsigned i = 0; i < nargs; ++i)
--- 2351,2387 ----
  }
  
  
! /* Return true if TYPE1 and TYPE2 are compatible enough for builtin
!    processing.  */
  
! 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 and return value match those of FNDECL,
!    a decl of a builtin function.  */
  
! 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)
*************** validate_call (gimple stmt, tree fndecl)
*** 2380,2393 ****
        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)))
  	return false;
        targs = TREE_CHAIN (targs);
      }
--- 2390,2396 ----
        if (!targs)
  	return true;
        tree arg = gimple_call_arg (stmt, i);
!       if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs)))
  	return false;
        targs = TREE_CHAIN (targs);
      }
*************** validate_call (gimple stmt, tree fndecl)
*** 2396,2401 ****
--- 2399,2417 ----
    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
*************** gimple_call_builtin_p (gimple stmt, enum
*** 2405,2411 ****
    if (is_gimple_call (stmt)
        && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
        && DECL_BUILT_IN_CLASS (fndecl) == klass)
!     return validate_call (stmt, fndecl);
    return false;
  }
  
--- 2421,2427 ----
    if (is_gimple_call (stmt)
        && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
        && DECL_BUILT_IN_CLASS (fndecl) == klass)
!     return gimple_builtin_call_types_compatible_p (stmt, fndecl);
    return false;
  }
  
*************** gimple_call_builtin_p (gimple stmt, enum
*** 2419,2425 ****
        && (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 false;
  }
  
--- 2435,2441 ----
        && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
        && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 
        && DECL_FUNCTION_CODE (fndecl) == code)
!     return gimple_builtin_call_types_compatible_p (stmt, fndecl);
    return false;
  }
  
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c	(revision 206385)
--- gcc/gimple-fold.c	(working copy)
*************** gimple_fold_builtin (gimple stmt)
*** 879,886 ****
    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
--- 879,884 ----
*************** gimple_fold_builtin (gimple stmt)
*** 890,895 ****
--- 888,895 ----
      {
        if (ignore)
  	STRIP_NOPS (result);
+       else
+ 	result = fold_convert (gimple_call_return_type (stmt), result);
        return result;
      }
  
*************** gimple_fold_call (gimple_stmt_iterator *
*** 1206,1213 ****
  
    /* 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))
      {
        tree result = gimple_fold_builtin (stmt);
        if (result)
--- 1206,1212 ----
  
    /* Check for builtins that CCP can handle using information not
       available in the generic fold routines.  */
!   if (gimple_call_builtin_p (stmt))
      {
        tree result = gimple_fold_builtin (stmt);
        if (result)
*************** gimple_fold_call (gimple_stmt_iterator *
*** 1216,1222 ****
  	    gimplify_and_update_call_from_tree (gsi, result);
  	  changed = true;
  	}
!       else if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
  	changed |= targetm.gimple_fold_builtin (gsi);
      }
  
--- 1215,1221 ----
  	    gimplify_and_update_call_from_tree (gsi, result);
  	  changed = true;
  	}
!       else if (gimple_call_builtin_p (stmt, BUILT_IN_MD))
  	changed |= targetm.gimple_fold_builtin (gsi);
      }
  
*************** gimple_fold_stmt_to_constant_1 (gimple s
*** 2726,2732 ****
  	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)))
  	  {
  	    tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt));
  	    tree call, retval;
--- 2725,2733 ----
  	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))
! 	    && gimple_builtin_call_types_compatible_p (stmt,
! 						       TREE_OPERAND (fn, 0)))
  	  {
  	    tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt));
  	    tree call, retval;
*************** gimple_fold_stmt_to_constant_1 (gimple s
*** 2738,2745 ****
  					 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);
  	    return retval;
  	  }
  	return NULL_TREE;
--- 2739,2749 ----
  					 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);
! 		retval = fold_convert (gimple_call_return_type (stmt), retval);
! 	      }
  	    return retval;
  	  }
  	return NULL_TREE;
Index: gcc/tsan.c
===================================================================
*** gcc/tsan.c	(revision 206385)
--- gcc/tsan.c	(working copy)
*************** instrument_gimple (gimple_stmt_iterator
*** 609,615 ****
        && (gimple_call_fndecl (stmt)
  	  != builtin_decl_implicit (BUILT_IN_TSAN_INIT)))
      {
!       if (is_gimple_builtin_call (stmt))
  	instrument_builtin_call (gsi);
        return true;
      }
--- 609,615 ----
        && (gimple_call_fndecl (stmt)
  	  != builtin_decl_implicit (BUILT_IN_TSAN_INIT)))
      {
!       if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
  	instrument_builtin_call (gsi);
        return true;
      }
Index: gcc/testsuite/gcc.dg/pr59630.c
===================================================================
*** gcc/testsuite/gcc.dg/pr59630.c	(revision 0)
--- gcc/testsuite/gcc.dg/pr59630.c	(working copy)
***************
*** 0 ****
--- 1,8 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O" } */
+ 
+ _Bool foo()
+ {
+   _Bool (*f)(int) = __builtin_abs; /* { dg-warning "" } */
+   return f(0);
+ }



More information about the Gcc-patches mailing list