[PATCH][RFC] Fix PR55890

Richard Biener rguenther@suse.de
Mon Jan 7 13:57:00 GMT 2013


Since we freely propagate function addresses we can end up with
call statements with mismatched number and type of arguments
than what the function decl referenced says.  This is a problem
for builtin decls and all code that tries to examine their
arguments (which may not be there or be of bogus type).  The
following provides an easy means to not even consider such bogus
calls as calls to builtins.

Only PTA fixed up, other cases should add some more testcases
(IIRC Jakub had one for strlen-opt).

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

Richard.

2013-01-07  Richard Biener  <rguenther@suse.de>

	PR middle-end/55890
	* gimple.h (gimple_call_builtin_p): New overload.
	* gimple.c (validate_call): New function.
	(gimple_call_builtin_p): Likewise.
	* tree-ssa-structalias.c (find_func_aliases_for_builtin_call):
	Use gimple_call_builtin_p.
	(find_func_clobbers): Likewise.

	* gcc.dg/torture/pr55890-1.c: New testcase.
	* gcc.dg/torture/pr55890-2.c: Likewise.

Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c	(revision 194964)
--- gcc/gimple.c	(working copy)
*************** is_gimple_builtin_call (gimple stmt)
*** 4137,4152 ****
    return false;
  }
  
! /* Return true when STMT is builtins call to CODE.  */
  
  bool
  gimple_call_builtin_p (gimple stmt, enum built_in_function code)
  {
    tree fndecl;
!   return (is_gimple_call (stmt)
! 	  && (fndecl = gimple_call_fndecl (stmt)) != NULL
! 	  && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
! 	  && DECL_FUNCTION_CODE (fndecl) == code);
  }
  
  /* Return true if STMT clobbers memory.  STMT is required to be a
--- 4137,4196 ----
    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)
!     {
!       /* Variadic args follow.  */
!       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);
!     }
!   if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
!     return false;
!   return true;
! }
! 
! /* Return true when STMT is builtins call to CLASS.  */
! 
! bool
! gimple_call_builtin_p (gimple stmt, enum built_in_class klass)
! {
!   tree fndecl;
!   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;
! }
! 
! /* Return true when STMT is builtins call to CODE of CLASS.  */
  
  bool
  gimple_call_builtin_p (gimple stmt, enum built_in_function code)
  {
    tree fndecl;
!   if (is_gimple_call (stmt)
!       && (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;
  }
  
  /* Return true if STMT clobbers memory.  STMT is required to be a
Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h	(revision 194964)
--- gcc/gimple.h	(working copy)
*************** extern bool walk_stmt_load_store_ops (gi
*** 893,898 ****
--- 893,899 ----
  				      bool (*)(gimple, tree, void *),
  				      bool (*)(gimple, tree, void *));
  extern bool gimple_ior_addresses_taken (bitmap, 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/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c	(revision 194964)
--- gcc/tree-ssa-structalias.c	(working copy)
*************** find_func_aliases_for_builtin_call (gimp
*** 4014,4021 ****
    vec<ce_s> rhsc = vNULL;
    varinfo_t fi;
  
!   if (fndecl != NULL_TREE
!       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
      /* ???  All builtins that are handled here need to be handled
         in the alias-oracle query functions explicitly!  */
      switch (DECL_FUNCTION_CODE (fndecl))
--- 4014,4020 ----
    vec<ce_s> rhsc = vNULL;
    varinfo_t fi;
  
!   if (gimple_call_builtin_p (t, BUILT_IN_NORMAL))
      /* ???  All builtins that are handled here need to be handled
         in the alias-oracle query functions explicitly!  */
      switch (DECL_FUNCTION_CODE (fndecl))
*************** find_func_clobbers (gimple origt)
*** 4768,4775 ****
  
        /* For builtins we do not have separate function info.  For those
  	 we do not generate escapes for we have to generate clobbers/uses.  */
!       if (decl
! 	  && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
  	switch (DECL_FUNCTION_CODE (decl))
  	  {
  	  /* The following functions use and clobber memory pointed to
--- 4767,4773 ----
  
        /* For builtins we do not have separate function info.  For those
  	 we do not generate escapes for we have to generate clobbers/uses.  */
!       if (gimple_call_builtin_p (t, BUILT_IN_NORMAL))
  	switch (DECL_FUNCTION_CODE (decl))
  	  {
  	  /* The following functions use and clobber memory pointed to
Index: gcc/testsuite/gcc.dg/torture/pr55890-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55890-1.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55890-1.c	(working copy)
***************
*** 0 ****
--- 1,6 ----
+ /* { dg-do compile } */
+ 
+ extern void *memmove(void *, void *, long unsigned int);
+ typedef int (*_TEST_fun_) ();
+ static _TEST_fun_ i = (_TEST_fun_) memmove;
+ main() { i(); }
Index: gcc/testsuite/gcc.dg/torture/pr55890-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55890-2.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55890-2.c	(working copy)
***************
*** 0 ****
--- 1,4 ----
+ /* { dg-do compile } */
+ 
+ extern void *memcpy();
+ main() { memcpy(); }



More information about the Gcc-patches mailing list