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]

Chain incomplete variables off their type, not their scope


This patch changes the way we handle declarations of variables with
incomplete but completable type.  Formerly a list was kept in the
current scope, and finish_struct had to scan the entire list for
anything it might have completed.  This is (a) a potential performance
issue, and (b) highly inelegant.  With the patch, such variables are
attached directly to the type that would have to get completed.  Thus,
no search is necessary in finish_struct.

I believe I got the language semantics right, but a second pair of
eyes would be appreciated.  Also, I am concerned about recycling
TYPE_VFIELD for this purpose.  That slot was formerly always null in
C/ObjC, but it is referenced in dbxout.c and I cannot prove that that
will never see an incomplete type.  (The use in dwarf2out.c appears to
be safe.)  Thus, not checking this in yet, comments solicited.  The
patch *has* survived a full bootstrap on i686-linux.

zw
 
        * c-tree.h (C_TYPE_INCOMPLETE_VARS): New macro.
        * c-decl.c (struct c_scope): Remove "incomplete" field.
        (pushdecl): Attach variables with incomplete types to
        the TYPE_MAIN_VARIANT of the incomplete type in question.
        (finish_struct): Look at C_TYPE_INCOMPLETE_VARS for variables
        to complete, not at current_scope->incomplete.  All such
        variables do need completion.

===================================================================
Index: c-decl.c
--- c-decl.c	23 Aug 2003 22:18:49 -0000	1.435
+++ c-decl.c	27 Aug 2003 01:48:54 -0000
@@ -185,7 +185,7 @@ static int current_extern_inline;
    the end of the list on each insertion, or reverse the lists later,
    we maintain a pointer to the last list entry for each of the lists.
 
-   The order of the tags, shadowed, shadowed_tags, and incomplete
+   The order of the tags, shadowed, and shadowed_tags
    lists does not matter, so we just prepend to these lists.  */
 
 struct c_scope GTY(())
@@ -225,9 +225,6 @@ struct c_scope GTY(())
   tree blocks;
   tree blocks_last;
 
-  /* Variable declarations with incomplete type in this scope.  */
-  tree incomplete;
-
   /* True if we are currently filling this scope with parameter
      declarations.  */
   bool parm_flag : 1;
@@ -1745,14 +1742,15 @@ pushdecl (tree x)
       IDENTIFIER_SYMBOL_VALUE (name) = x;
       C_DECL_INVISIBLE (x) = 0;
 
-      /* Keep list of variables in this scope with incomplete type.
+      /* If x's type is incomplete because it's based on a
+	 structure or union which has not yet been fully declared,
+	 attach it to that structure or union type, so we can go
+	 back and complete the variable declaration later, if the
+	 structure or union gets fully declared.
+
 	 If the input is erroneous, we can have error_mark in the type
 	 slot (e.g. "f(void a, ...)") - that doesn't count as an
-	 incomplete type.
-
-	 FIXME: Chain these off the TYPE_DECL for the incomplete type,
-	 then we don't have to do (potentially quite costly) searches
-	 in finish_struct.  */
+	 incomplete type.  */
       if (TREE_TYPE (x) != error_mark_node
 	  && !COMPLETE_TYPE_P (TREE_TYPE (x)))
 	{
@@ -1760,11 +1758,14 @@ pushdecl (tree x)
 
 	  while (TREE_CODE (element) == ARRAY_TYPE)
 	    element = TREE_TYPE (element);
+	  element = TYPE_MAIN_VARIANT (element);
+
 	  if ((TREE_CODE (element) == RECORD_TYPE
 	       || TREE_CODE (element) == UNION_TYPE)
 	      && (TREE_CODE (x) != TYPE_DECL
 		  || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE))
-	    scope->incomplete = tree_cons (NULL_TREE, x, scope->incomplete);
+	    C_TYPE_INCOMPLETE_VARS (element)
+	      = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
 	}
     }
 
@@ -5143,63 +5144,24 @@ finish_struct (tree t, tree fieldlist, t
 
   /* If this structure or union completes the type of any previous
      variable declaration, lay it out and output its rtl.  */
-
-  if (current_scope->incomplete != NULL_TREE)
-    {
-      tree prev = NULL_TREE;
-
-      for (x = current_scope->incomplete; x; x = TREE_CHAIN (x))
-        {
-	  tree decl = TREE_VALUE (x);
-
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
-	      && TREE_CODE (decl) != TYPE_DECL)
-	    {
-	      layout_decl (decl, 0);
-	      /* This is a no-op in c-lang.c or something real in
-		 objc-act.c.  */
-	      if (c_dialect_objc ())
-		objc_check_decl (decl);
-	      rest_of_decl_compilation (decl, NULL, toplevel, 0);
-	      if (! toplevel)
-		expand_decl (decl);
-	      /* Unlink X from the incomplete list.  */
-	      if (prev)
-		TREE_CHAIN (prev) = TREE_CHAIN (x);
-	      else
-	        current_scope->incomplete = TREE_CHAIN (x);
-	    }
-	  else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
-		   && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-	    {
-	      tree element = TREE_TYPE (decl);
-	      while (TREE_CODE (element) == ARRAY_TYPE)
-		element = TREE_TYPE (element);
-	      if (element == t)
-		{
-		  layout_array_type (TREE_TYPE (decl));
-		  if (TREE_CODE (decl) != TYPE_DECL)
-		    {
-		      layout_decl (decl, 0);
-		      if (c_dialect_objc ())
-			objc_check_decl (decl);
-		      rest_of_decl_compilation (decl, NULL, toplevel, 0);
-		      if (! toplevel)
-			expand_decl (decl);
-		    }
-		  /* Unlink X from the incomplete list.  */
-		  if (prev)
-		    TREE_CHAIN (prev) = TREE_CHAIN (x);
-		  else
-		    current_scope->incomplete = TREE_CHAIN (x);
-		}
-	      else
-		prev = x;
-	    }
-	  else
-	    prev = x;
+  for (x = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
+       x;
+       x = TREE_CHAIN (x))
+    {
+      tree decl = TREE_VALUE (x);
+      if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+	layout_array_type (TREE_TYPE (decl));
+      if (TREE_CODE (decl) != TYPE_DECL)
+	{
+	  layout_decl (decl, 0);
+	  if (c_dialect_objc ())
+	    objc_check_decl (decl);
+	  rest_of_decl_compilation (decl, NULL, toplevel, 0);
+	  if (! toplevel)
+	    expand_decl (decl);
 	}
     }
+  C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
 
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel);
===================================================================
Index: c-tree.h
--- c-tree.h	5 Aug 2003 14:11:42 -0000	1.128
+++ c-tree.h	27 Aug 2003 01:48:54 -0000
@@ -94,6 +94,10 @@ struct lang_decl GTY(())
    nonzero if the definition of the type has already started.  */
 #define C_TYPE_BEING_DEFINED(TYPE) TYPE_LANG_FLAG_0 (TYPE)
 
+/* In an incomplete RECORD_TYPE or UNION_TYPE, a list of variable
+   declarations whose type would be completed by completing that type.  */
+#define C_TYPE_INCOMPLETE_VARS(TYPE) TYPE_VFIELD (TYPE)
+
 /* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
    keyword.  C_RID_CODE (node) is then the RID_* value of the keyword,
    and C_RID_YYCODE is the token number wanted by Yacc.  */


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