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]

c-decl.c rewrite (2/3) no more different_binding_level/different_tu


After extensive experimentation and testing (thanks everyone who
helped test) I have come to the conclusion that the original version
of this patch is a non-starter.  It just breaks too many assumptions
in the language-independent compiler if we have more than one valid
DECL node for a given object.  (Sorry, Per, I think you're going to
have to come up with a different plan for the compile server.)

So, the point of doing that was that duplicate_decls then didn't have
to care about whether the input decls were in the same binding level
or not.  However, it turns out not to be necessary for it to care
anyway.  The semantics of C allow us to do all the merging anyway.
Hence, this much simpler patch that just does it.  

Having done that, the only thing that different_tu did was enable a
weird little piece of code that, as far as I could tell, shouldn't
ever have gotten executed anyway.  So I ripped that out too.  There is
a decent chance that I am wrong about that, and that multi-translation-
unit mode is now slightly more broken than it was already.  Since it
is already broken, due to problems with C_TYPE_INCOMPLETE_VARS (I
thought there was a PR on the subject but I can't find it) and since
that is a new feature whereas the bugs here are regressions that
affect standards conformance, I am going to leave it for now.

Unlike the previous version, this patch should not be expected to fix
any of the outstanding bugs, since the copy_node call in pushdecl is
still there.  Patch #3 will get it.  There are also speed tweaks in
here, which I'll get to after it's correct.

Bootstrapped i686-linux, applied mainline and 3.4 branch.

zw

        * c-decl.c (merge_decls): Kill different_binding_level and
        different_tu arguments; simplify throughout.
        (duplicate_decls): Likewise.
        (pushdecl, merge_translation_unit_decls): Update calls to
        duplicate_decls.
testsuite:
        * gcc.dg/noncompile/20020213-1.c: Add another dg-warning line.

===================================================================
Index: c-decl.c
--- c-decl.c	13 Jan 2004 02:52:33 -0000	1.470
+++ c-decl.c	21 Jan 2004 10:05:17 -0000
@@ -1252,23 +1252,15 @@ diagnose_mismatched_decls (tree newdecl,
 
 /* Subroutine of duplicate_decls.  NEWDECL has been found to be
    consistent with OLDDECL, but carries new information.  Merge the
-   new information into OLDDECL.  If DIFFERENT_BINDING_LEVEL or
-   DIFFERENT_TU is true, avoid completely merging the decls, as this
-   will break assumptions elsewhere.  This function issues no
+   new information into OLDDECL.  This function issues no
    diagnostics.  */
 
 static void
-merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype,
-	     bool different_binding_level, bool different_tu)
+merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
 {
   int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
 			   && DECL_INITIAL (newdecl) != 0);
 
-  /* When copying info to olddecl, we store into write_olddecl
-     instead.  This allows us to avoid modifying olddecl when
-     different_binding_level is true.  */
-  tree write_olddecl = different_binding_level ? newdecl : olddecl;
-
   /* For real parm decl following a forward decl, return 1 so old decl
      will be reused.  Only allow this to happen once.  */
   if (TREE_CODE (newdecl) == PARM_DECL
@@ -1282,25 +1274,9 @@ merge_decls (tree newdecl, tree olddecl,
     = (*targetm.merge_decl_attributes) (olddecl, newdecl);
 
   /* Merge the data types specified in the two decls.  */
-  if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
-    {
-      if (different_binding_level)
-	{
-	  if (TYPE_ARG_TYPES (oldtype) != 0
-	      && TYPE_ARG_TYPES (newtype) == 0)
-	    TREE_TYPE (newdecl) = common_type (newtype, oldtype);
-	  else
-	    TREE_TYPE (newdecl)
-	      = build_type_attribute_variant
-	      (newtype,
-	       merge_attributes (TYPE_ATTRIBUTES (newtype),
-				 TYPE_ATTRIBUTES (oldtype)));
-	}
-      else
-	TREE_TYPE (newdecl)
-	  = TREE_TYPE (olddecl)
-	  = common_type (newtype, oldtype);
-    }
+  TREE_TYPE (newdecl)
+    = TREE_TYPE (olddecl)
+    = common_type (newtype, oldtype);
 
   /* Lay the type out, unless already done.  */
   if (oldtype != TREE_TYPE (newdecl))
@@ -1331,33 +1307,27 @@ merge_decls (tree newdecl, tree olddecl,
 
   /* Merge the type qualifiers.  */
   if (TREE_READONLY (newdecl))
-    TREE_READONLY (write_olddecl) = 1;
+    TREE_READONLY (olddecl) = 1;
 
   if (TREE_THIS_VOLATILE (newdecl))
     {
-      TREE_THIS_VOLATILE (write_olddecl) = 1;
+      TREE_THIS_VOLATILE (olddecl) = 1;
       if (TREE_CODE (newdecl) == VAR_DECL)
 	make_var_volatile (newdecl);
     }
 
   /* Keep source location of definition rather than declaration.  */
-  /* When called with different_binding_level set, keep the old
-     information so that meaningful diagnostics can be given.  */
-  if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0
-      && ! different_binding_level)
+  if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
     DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
 
   /* Merge the unused-warning information.  */
   if (DECL_IN_SYSTEM_HEADER (olddecl))
     DECL_IN_SYSTEM_HEADER (newdecl) = 1;
   else if (DECL_IN_SYSTEM_HEADER (newdecl))
-    DECL_IN_SYSTEM_HEADER (write_olddecl) = 1;
+    DECL_IN_SYSTEM_HEADER (olddecl) = 1;
 
   /* Merge the initialization information.  */
-  /* When called with different_binding_level set, don't copy over
-     DECL_INITIAL, so that we don't accidentally change function
-     declarations into function definitions.  */
-  if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level)
+   if (DECL_INITIAL (newdecl) == 0)
     DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
 
   /* Merge the section attribute.
@@ -1397,8 +1367,6 @@ merge_decls (tree newdecl, tree olddecl,
       TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
       /* This is since we don't automatically
 	 copy the attributes of NEWDECL into OLDDECL.  */
-      /* No need to worry about different_binding_level here because
-	 then TREE_PUBLIC (newdecl) was true.  */
       TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
       /* If this clears `static', clear it in the identifier too.  */
       if (! TREE_PUBLIC (olddecl))
@@ -1406,24 +1374,15 @@ merge_decls (tree newdecl, tree olddecl,
     }
   if (DECL_EXTERNAL (newdecl))
     {
-      if (! different_binding_level || different_tu)
-	{
-	  /* Don't mess with these flags on local externs; they remain
-	     external even if there's a declaration at file scope which
-	     isn't.  */
-	  TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
-	  DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
-	}
+      TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
+      DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+
       /* An extern decl does not override previous storage class.  */
       TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
       if (! DECL_EXTERNAL (newdecl))
 	{
 	  DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
 	  DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
-	  /* If we have two non-EXTERNAL file-scope decls that are
-	     the same, only one of them should be written out.  */
-	  if (different_tu)
-	    TREE_ASM_WRITTEN (newdecl) = 1;
 	}
     }
   else
@@ -1469,11 +1428,8 @@ merge_decls (tree newdecl, tree olddecl,
 	     definition.  */
 	  if (new_is_definition)
 	    {
-	      if (! different_binding_level)
-		{
-		  TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
-		  DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
-		}
+	      TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
+	      DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
 	    }
 	  else
 	    {
@@ -1488,11 +1444,7 @@ merge_decls (tree newdecl, tree olddecl,
       if (! new_is_definition)
 	{
 	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
-	  /* When called with different_binding_level set, don't copy over
-	     DECL_INITIAL, so that we don't accidentally change function
-	     declarations into function definitions.  */
-	  if (! different_binding_level)
-	    DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+	  DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
 	  DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
 	  DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
 	  DECL_ESTIMATED_INSNS (newdecl) = DECL_ESTIMATED_INSNS (olddecl);
@@ -1504,9 +1456,7 @@ merge_decls (tree newdecl, tree olddecl,
 	    {
 	      DECL_INLINE (newdecl) = 1;
 	      DECL_ABSTRACT_ORIGIN (newdecl)
-		= (different_binding_level
-		   ? DECL_ORIGIN (olddecl)
-		   : DECL_ABSTRACT_ORIGIN (olddecl));
+		= DECL_ABSTRACT_ORIGIN (olddecl);
 	    }
 	}
       else
@@ -1518,8 +1468,6 @@ merge_decls (tree newdecl, tree olddecl,
 	    DECL_INLINE (newdecl) = 1;
 	}
     }
-  if (different_binding_level)
-    return;
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
      But preserve OLDDECL's DECL_UID.  */
@@ -1547,24 +1495,18 @@ merge_decls (tree newdecl, tree olddecl,
    if appropriate.
 
    If safely possible, alter OLDDECL to look like NEWDECL, and return
-   true.  Otherwise, return false.
-
-   When DIFFERENT_BINDING_LEVEL is true, NEWDECL is an external
-   declaration, and OLDDECL is in an outer scope and should thus not
-   be changed.  */
+   true.  Otherwise, return false.  */
 
 static bool
-duplicate_decls (tree newdecl, tree olddecl,
-		 bool different_binding_level, bool different_tu)
+duplicate_decls (tree newdecl, tree olddecl)
 {
   tree newtype, oldtype;
 
   if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
     return false;
 
-  merge_decls (newdecl, olddecl, newtype, oldtype,
-	       different_binding_level, different_tu);
-  return !different_binding_level;
+  merge_decls (newdecl, olddecl, newtype, oldtype);
+  return true;
 }
   
 
@@ -1745,7 +1687,7 @@ pushdecl (tree x)
 		 IDENTIFIER_POINTER (name));
 
       old = lookup_name_current_level (name);
-      if (old && duplicate_decls (x, old, 0, false))
+      if (old && duplicate_decls (x, old))
 	{
 	  /* For PARM_DECLs, old may be a forward declaration.
 	     If so, we want to remove it from its old location
@@ -1773,8 +1715,7 @@ pushdecl (tree x)
  	  tree ext = any_external_decl (name);
 	  if (ext)
 	    {
-	      if (duplicate_decls (x, ext, scope != global_scope,
-				   false))
+	      if (duplicate_decls (x, ext))
 		x = copy_node (ext);
 	    }
 	  else
@@ -6606,7 +6547,7 @@ merge_translation_unit_decls (void)
 
 	  /* Print any appropriate error messages, and partially merge
 	     the decls.  */
-	  (void) duplicate_decls (decl, global_decl, true, true);
+	  (void) duplicate_decls (decl, global_decl);
 	}
 
   htab_delete (link_hash_table);
===================================================================
Index: testsuite/gcc.dg/noncompile/20020213-1.c
--- testsuite/gcc.dg/noncompile/20020213-1.c	11 Jan 2004 01:18:58 -0000	1.2
+++ testsuite/gcc.dg/noncompile/20020213-1.c	21 Jan 2004 10:05:17 -0000
@@ -24,6 +24,7 @@ int main ()
   return 0;
 }
 
+/* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 15 } */
 /* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 16 } */
 /* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 16 } */
 /* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 18 } */


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