This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Clean-up C's builtin function type matching.


Continuing in my current run of improvements to GCC's builtin function
handling, the following patch tidies up the fuzzy type checking code
for builtin functions in the C front-end's duplicate_decls.

The major part of this reorganization is to simply move the existing
code from duplicate_decls into its own subroutine.  The significant
enhancement is to extend the "fuzzy" matching from just the first
argument in the existing implementation, to all of the arguments.

For example, immediately following the affected hunk in c-decl.c's
duplicate_decls is additional code purely to handle bcmp, bzero and
fputs.  This is only required because we don't allow fuzzy matching
on the second and later arguments.  Indeed, the only reason builtins.def
contains "fallback" builtins at all is because of this same limitation.
I can clean all of this up once this patch is approved.

>From the type safety perspective, moving this logic into its own
much-easier-to-understand function simplifies potential future
improvements.  For example, I'm surprised that the existing code
only compares type modes.  For example, it would be easy to allow
a void* in the builtin's prototype to match any pointer type, but
require that all other pointer types, and all other arguments'
types match exactly.

However for the time being I thought it much more managable to keep
the current tried-and-tested "fuzzy" type checking and just extend
its use (which will allow significant simplification in other parts
of GCC), and leave possible additional refinements to others.  One
possible follow-up, which I personally have absolutely no interest
in implementing, is to potentially fold this new function into C's
comptypes routine, using an additional bit in its flags argument.
My best wishes in advance to anyone willing to undertake such a task.


The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?


2003-07-20  Roger Sayle  <roger@eyesopen.com>

	* c-decl.c (match_builtin_function_types): New subroutine of
	duplicate_decls to test whether a redeclaration of a builtin
	function is suitably close, i.e. the return type and all of
	the argument types have the same modes as the builtin expects.
	(duplicate_decls): Fuzzy type matching for builtin functions
	moved to match_builtin_function_types.


Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.411
diff -c -3 -p -r1.411 c-decl.c
*** c-decl.c	19 Jul 2003 23:32:53 -0000	1.411
--- c-decl.c	20 Jul 2003 18:37:10 -0000
*************** tree static_ctors, static_dtors;
*** 264,269 ****
--- 264,270 ----

  static struct binding_level *make_binding_level (void);
  static void pop_binding_level (void);
+ static tree match_builtin_function_types (tree, tree);
  static int duplicate_decls (tree, tree, int, int);
  static int redeclaration_error_message (tree, tree);
  static tree make_label (tree, location_t);
*************** pushtag (tree name, tree type)
*** 695,700 ****
--- 696,741 ----
    TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
  }

+ /* Subroutine of duplicate_decls.  Allow harmless mismatches in return
+    and argument types provided that the type modes match.  This function
+    return a unified type given a suitable match, and 0 otherwise.  */
+
+ static tree
+ match_builtin_function_types (tree oldtype, tree newtype)
+ {
+   tree newrettype, oldrettype;
+   tree newargs, oldargs;
+   tree trytype, tryargs;
+
+   /* Accept the return type of the new declaration if same modes.  */
+   oldrettype = TREE_TYPE (oldtype);
+   newrettype = TREE_TYPE (newtype);
+
+   if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype))
+     return 0;
+
+   oldargs = TYPE_ARG_TYPES (oldtype);
+   newargs = TYPE_ARG_TYPES (newargs);
+   tryargs = newargs;
+
+   while (oldargs || newargs)
+     {
+       if (! oldargs
+ 	  || ! newargs
+ 	  || ! TREE_VALUE (oldargs)
+ 	  || ! TREE_VALUE (newargs)
+ 	  || TYPE_MODE (TREE_VALUE (oldargs))
+ 	     != TYPE_MODE (TREE_VALUE (newargs)))
+ 	return 0;
+
+       oldargs = TREE_CHAIN (oldargs);
+       newargs = TREE_CHAIN (newargs);
+     }
+
+   trytype = build_function_type (newrettype, tryargs);
+   return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
+ }
+
  /* Handle when a new declaration NEWDECL
     has the same name as an old one OLDDECL
     in the same binding contour.
*************** duplicate_decls (tree newdecl, tree oldd
*** 826,874 ****
  	}
        else if (!types_match)
  	{
! 	  /* Accept the return type of the new declaration if same modes.  */
! 	  tree oldreturntype = TREE_TYPE (oldtype);
! 	  tree newreturntype = TREE_TYPE (newtype);
!
! 	  if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
! 	    {
! 	      /* Function types may be shared, so we can't just modify
! 		 the return type of olddecl's function type.  */
! 	      tree trytype
! 		= build_function_type (newreturntype,
! 				       TYPE_ARG_TYPES (oldtype));
! 	      trytype = build_type_attribute_variant (trytype,
! 						      TYPE_ATTRIBUTES (oldtype));
!
!               types_match = comptypes (newtype, trytype, comptype_flags);
! 	      if (types_match)
! 		oldtype = trytype;
! 	    }
! 	  /* Accept harmless mismatch in first argument type also.
  	     This is for the ffs and fprintf builtins.  */
! 	  if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0
! 	      && TYPE_ARG_TYPES (oldtype) != 0
! 	      && TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0
! 	      && TREE_VALUE (TYPE_ARG_TYPES (oldtype)) != 0
! 	      && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (newtype)))
! 		  == TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (oldtype)))))
! 	    {
! 	      /* Function types may be shared, so we can't just modify
! 		 the return type of olddecl's function type.  */
! 	      tree trytype
! 		= build_function_type (TREE_TYPE (oldtype),
! 				       tree_cons (NULL_TREE,
! 						  TREE_VALUE (TYPE_ARG_TYPES (newtype)),
! 						  TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
! 	      trytype = build_type_attribute_variant (trytype,
! 						      TYPE_ATTRIBUTES (oldtype));

  	      types_match = comptypes (newtype, trytype, comptype_flags);
  	      if (types_match)
  		oldtype = trytype;
  	    }
- 	  if (! different_binding_level)
- 	    TREE_TYPE (olddecl) = oldtype;
  	}
        else if (TYPE_ARG_TYPES (oldtype) == NULL
  	       && TYPE_ARG_TYPES (newtype) != NULL)
--- 867,884 ----
  	}
        else if (!types_match)
  	{
! 	  /* Accept harmless mismatch in function types.
  	     This is for the ffs and fprintf builtins.  */
! 	  tree trytype = match_builtin_function_types (oldtype, newtype);

+ 	  if (trytype)
+ 	    {
  	      types_match = comptypes (newtype, trytype, comptype_flags);
  	      if (types_match)
  		oldtype = trytype;
+ 	      if (! different_binding_level)
+ 		TREE_TYPE (olddecl) = oldtype;
  	    }
  	}
        else if (TYPE_ARG_TYPES (oldtype) == NULL
  	       && TYPE_ARG_TYPES (newtype) != NULL)

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]