(C++) patch to hack_incomplete_structures

Jason Merrill jason@cygnus.com
Mon Feb 7 12:21:00 GMT 2000


hack_incomplete_structures tries to find variables of newly-completed
class type so they can be laid out appropriately, but it was copied
directly from the C frontend and is woefully inadequate for C++.  It
fails to consider namespaces, and it only looks in the current binding
level, so if you have a local variable with a cleanup the artificial
binding level thus introduced will stop the search.  This patch fixes
both problems.

2000-02-07  Jason Merrill  <jason@casey.cygnus.com>

	* cp-tree.h (struct saved_scope): Add incomplete field.
	(namespace_scope_incomplete): New macro.
	* decl.c (pushdecl): Use it.
	(hack_incomplete_structures): Use it.  See through artificial
	binding levels.
	(mark_saved_scope): Mark it.

Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.400
diff -c -p -r1.400 cp-tree.h
*** cp-tree.h	2000/01/31 21:00:01	1.400
--- cp-tree.h	2000/02/07 20:15:38
*************** struct saved_scope {
*** 714,719 ****
--- 715,722 ----
    tree x_previous_class_type;
    tree x_previous_class_values;
    tree x_saved_tree;
+   tree incomplete;
  
    HOST_WIDE_INT x_processing_template_decl;
    int x_processing_specialization;
*************** struct saved_scope {
*** 774,779 ****
--- 777,790 ----
  
  #define previous_class_values scope_chain->x_previous_class_values
  
+ /* A list of the declarations with incomplete type at namespace scope.  */
+ 
+ #define namespace_scope_incomplete scope_chain->incomplete
+ 
  extern struct saved_scope *scope_chain;
  
  /* Global state pertinent to the current function.  */
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.541
diff -c -p -r1.541 decl.c
*** decl.c	2000/01/29 19:10:00	1.541
--- decl.c	2000/02/07 20:15:49
*************** mark_saved_scope (arg)
*** 2278,2283 ****
--- 2283,2290 ----
        ggc_mark_tree (t->x_previous_class_type);
        ggc_mark_tree (t->x_previous_class_values);
        ggc_mark_tree (t->x_saved_tree);
+       ggc_mark_tree (t->incomplete);
  
        mark_stmt_tree (&t->x_stmt_tree);
        mark_binding_level (&t->bindings);
*************** pushdecl (x)
*** 4033,4040 ****
  	      /* RTTI TD entries are created while defining the type_info.  */
  	      || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
  		  && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
! 	current_binding_level->incomplete
! 	  = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
      }
  
    if (need_new_binding)
--- 4040,4053 ----
  	      /* RTTI TD entries are created while defining the type_info.  */
  	      || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
  		  && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
! 	{
! 	  if (namespace_bindings_p ())
! 	    namespace_scope_incomplete
! 	      = tree_cons (NULL_TREE, x, namespace_scope_incomplete);
! 	  else
! 	    current_binding_level->incomplete
! 	      = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
! 	}
      }
  
    if (need_new_binding)
*************** hack_incomplete_structures (type)
*** 14222,14262 ****
       tree type;
  {
    tree *list;
! 
!   if (current_binding_level->incomplete == NULL_TREE)
!     return;
  
    if (!type) /* Don't do this for class templates.  */
      return;
  
!   for (list = &current_binding_level->incomplete; *list; )
      {
!       tree decl = TREE_VALUE (*list);
!       if ((decl && TREE_TYPE (decl) == type)
! 	  || (TREE_TYPE (decl)
! 	      && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
! 	      && TREE_TYPE (TREE_TYPE (decl)) == type))
! 	{
! 	  int toplevel = toplevel_bindings_p ();
! 	  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
! 	      && TREE_TYPE (TREE_TYPE (decl)) == type)
! 	    layout_type (TREE_TYPE (decl));
! 	  layout_decl (decl, 0);
! 	  rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
! 	  if (! toplevel)
! 	    {
! 	      tree cleanup;
! 	      expand_decl (decl);
! 	      cleanup = maybe_build_cleanup (decl);
! 	      expand_decl_init (decl);
! 	      if (! expand_decl_cleanup (decl, cleanup))
! 		cp_error ("parser lost in parsing declaration of `%D'",
! 			  decl);
  	    }
! 	  *list = TREE_CHAIN (*list);
  	}
        else
! 	list = &TREE_CHAIN (*list);
      }
  }
  
--- 14243,14305 ----
       tree type;
  {
    tree *list;
!   struct binding_level *level;
  
    if (!type) /* Don't do this for class templates.  */
      return;
  
!   if (namespace_bindings_p ())
      {
!       level = 0;
!       list = &namespace_scope_incomplete;
!     }
!   else
!     {
!       level = innermost_nonclass_level ();
!       list = &level->incomplete;
!     }
! 
!   while (1)
!     {
!       while (*list)
! 	{
! 	  tree decl = TREE_VALUE (*list);
! 	  if ((decl && TREE_TYPE (decl) == type)
! 	      || (TREE_TYPE (decl)
! 		  && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
! 		  && TREE_TYPE (TREE_TYPE (decl)) == type))
! 	    {
! 	      int toplevel = toplevel_bindings_p ();
! 	      if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
! 		  && TREE_TYPE (TREE_TYPE (decl)) == type)
! 		layout_type (TREE_TYPE (decl));
! 	      layout_decl (decl, 0);
! 	      rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
! 	      if (! toplevel)
! 		{
! 		  tree cleanup;
! 		  expand_decl (decl);
! 		  cleanup = maybe_build_cleanup (decl);
! 		  expand_decl_init (decl);
! 		  if (! expand_decl_cleanup (decl, cleanup))
! 		    cp_error ("parser lost in parsing declaration of `%D'",
! 			      decl);
! 		}
! 	      *list = TREE_CHAIN (*list);
  	    }
! 	  else
! 	    list = &TREE_CHAIN (*list);
! 	}
! 
!       /* Keep looking through artificial binding levels generated
! 	 for local variables.  */
!       if (level && level->keep == 2)
! 	{
! 	  level = level->level_chain;
! 	  list = &level->incomplete;
  	}
        else
! 	break;
      }
  }
  



More information about the Gcc-patches mailing list