public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [lto] fix redeclaration of builtin functions
@ 2007-11-08 23:26 Nathan Froyd
  0 siblings, 0 replies; only message in thread
From: Nathan Froyd @ 2007-11-08 23:26 UTC (permalink / raw)
  To: gcc-patches; +Cc: zadeck

The patch below fixes a conflict between LTO and builtin function
definitions.  The root problem was that the DWARF includes DIEs for some
functions includes both the actual function and its __builtin_ variant.
In most cases, the types for two DIEs are compatible (e.g. memcpy) can
we just need to check that we might be dealing with a builtin before
complaining about redefinitions.

In other cases, however (e.g. fwrite), the type for the builtin function
uses 'void *' instead of a "proper" type (FILE *) and the LTO machinery
would complain that the types were incompatible.  In these cases, we
borrow a trick and a function from the C front-end--just ensure that the
modes for the result and arguments types match, build a "proper" type
for the builtin function, and try again.

Doing all of this requires that we can tell whether a FUNCTION_DECL is a
builtin, so we need to record source lines for FUNCTION_DECLs when
reading DIEs.  (I understand that we do this again later, but that
information is stored in the LTO bytecode and is constructed too late
for this purpose.)  There seem to be several different ways to inquire
about the builtin-ness of functions; the source line approach was the
easiest way to do in this case.  (I don't know what the pros and cons of
the different approaches are.)

Committed to the LTO branch.

-Nathan

gcc/
	* c-decl.c (match_builtin_function_types): Move this...
	* tree.c (match_builtin_function_types): ...here.
	* tree.h (match_builtin_function_types): Declare it.

gcc/lto/
	* lto.c (lto_read_subroutine_type_subprogram_DIE): Handle
	DW_AT_decl_line.
	* lto-symtab.c (lto_symtab_merge_decl): Handle redefinition of a
	builtin specially.  Move check for attribute compatibility
	earlier.

Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 129966)
+++ gcc/tree.c	(working copy)
@@ -8795,4 +8795,45 @@ block_nonartificial_location (tree block
   return ret;
 }
 
+/* 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.  */
+
+tree
+match_builtin_function_types (tree newtype, tree oldtype)
+{
+  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 (newtype);
+  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));
+}
+
+
 #include "gt-tree.h"
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 129966)
+++ gcc/tree.h	(working copy)
@@ -4889,6 +4889,7 @@ extern void stack_protect_epilogue (void
 extern void recompute_tree_invariant_for_addr_expr (tree);
 extern bool needs_to_live_in_memory (const_tree);
 extern tree reconstruct_complex_type (tree, tree);
+extern tree match_builtin_function_types (tree, tree);
 
 extern int real_onep (const_tree);
 extern int real_twop (const_tree);
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 129966)
+++ gcc/c-decl.c	(working copy)
@@ -970,46 +970,6 @@ pushtag (tree name, tree type)
   TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
 }
 \f
-/* Subroutine of compare_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 newtype, tree oldtype)
-{
-  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 (newtype);
-  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));
-}
-
 /* Subroutine of diagnose_mismatched_decls.  Check for function type
    mismatch involving an empty arglist vs a nonempty one and give clearer
    diagnostics.  */
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 129967)
+++ gcc/lto/lto.c	(working copy)
@@ -2390,6 +2390,7 @@ lto_read_subroutine_type_subprogram_DIE 
   tree saved_scope;
   int inlined = DW_INL_not_inlined;
   tree abstract_origin = NULL_TREE;
+  int line;
 
   gcc_assert (abbrev->tag == DW_TAG_subroutine_type
 	      || abbrev->tag == DW_TAG_subprogram);
@@ -2421,7 +2422,6 @@ lto_read_subroutine_type_subprogram_DIE 
 	{
 	case DW_AT_decl_column:
 	case DW_AT_decl_file:
-	case DW_AT_decl_line:
 	  /* Ignore.  */
 	  break;
 
@@ -2432,6 +2432,10 @@ lto_read_subroutine_type_subprogram_DIE 
 	  /* Ignore.  */
 	  break;
 
+        case DW_AT_decl_line:
+          line = attribute_value_as_int (&attr_data);
+          break;
+
         case DW_AT_declaration:
           declaration = attr_data.u.flag;
           break;
@@ -2545,6 +2549,7 @@ lto_read_subroutine_type_subprogram_DIE 
       DECL_RESULT (result)
 	= build_decl (RESULT_DECL, NULL_TREE,
 		      TYPE_MAIN_VARIANT (ret_type));
+      DECL_SOURCE_LINE (result) = line;
 
       /* If the function has already been declared, merge the
 	 declarations.  */
Index: gcc/lto/lto-symtab.c
===================================================================
--- gcc/lto/lto-symtab.c	(revision 129966)
+++ gcc/lto/lto-symtab.c	(working copy)
@@ -288,6 +288,15 @@ lto_symtab_merge_decl (tree new_decl) 
       if (TREE_CODE (new_decl) == VAR_DECL)
 	merged_type = lto_merge_types (TREE_TYPE (old_decl),
 				       TREE_TYPE (new_decl));
+      else if (TREE_CODE (new_decl) == FUNCTION_DECL
+               && (DECL_IS_BUILTIN (old_decl) || DECL_IS_BUILTIN (new_decl)))
+        {
+          tree candidate = match_builtin_function_types (TREE_TYPE (new_decl),
+                                                         TREE_TYPE (old_decl));
+          merged_type =
+            lto_same_type_p (candidate, TREE_TYPE (new_decl)) ? candidate : NULL_TREE;
+        }
+
       if (!merged_type)
 	{
 	  error ("type of %qD does not match original declaration",
@@ -322,25 +331,30 @@ lto_symtab_merge_decl (tree new_decl) 
 	     new_decl);
       return error_mark_node;
     }
+  if (!lto_compatible_attributes_p (old_decl,
+				    DECL_ATTRIBUTES (old_decl),
+				    DECL_ATTRIBUTES (new_decl)))
+    {
+      error ("attributes applied to %qD are incompatible with original "
+	     "declaration", new_decl);
+      return error_mark_node;
+    }
   /* FIXME: DWARF doesn't include a "weak" attribute, so where is that
      info supposed to come from?  */
   if (!DECL_EXTERNAL (old_decl) && !DECL_EXTERNAL (new_decl)
       && !DECL_WEAK (old_decl) && !DECL_WEAK (new_decl)
       && !(TREE_CODE (new_decl) == FUNCTION_DECL
 	   && DECL_DECLARED_INLINE_P (old_decl)
-	   && DECL_DECLARED_INLINE_P (new_decl)))
+	   && DECL_DECLARED_INLINE_P (new_decl))
+      /* If we have gotten this far, then we are redeclaring a builtin
+         function and we have found the new declaration consistent with
+         the old.  Don't complain.  */
+      && !DECL_IS_BUILTIN (old_decl)
+      && !DECL_IS_BUILTIN (new_decl))
     {
       error ("%qD has already been defined", new_decl);
       return error_mark_node;
     }
-  if (!lto_compatible_attributes_p (old_decl,
-				    DECL_ATTRIBUTES (old_decl),
-				    DECL_ATTRIBUTES (new_decl)))
-    {
-      error ("attributes applied to %qD are incompatible with original "
-	     "declaration", new_decl);
-      return error_mark_node;
-    }
   /* We do not require matches for:
 
      - DECL_NAME

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-11-08 22:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-08 23:26 [lto] fix redeclaration of builtin functions Nathan Froyd

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).