(C++) template statics linkage patch

Jason Merrill jason@cygnus.com
Tue Mar 23 02:32:00 GMT 1999


We weren't emitting template statics in some cases, even with an explicit
instantiation.  Caught by the libstdc++ v3 folks.

1999-03-23  Jason Merrill  <jason@yorick.cygnus.com>

	* decl2.c (finish_file): Set at_eof to 2 after expanding ctors.
	* decl.c (expand_static_init): Make sure we don't add any after
	then.

	* decl.c (cp_finish_decl): Move intelligence about handling
	DECL_COMDAT for variables from here...
	* decl2.c (comdat_linkage): ...to here.
	(maybe_make_one_only): Tweak.
	(import_export_decl): Call comdat_linkage for variables, too.
	(finish_file): Handle template statics properly.

Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.326
diff -c -p -r1.326 decl.c
*** decl.c	1999/03/19 01:21:03	1.326
--- decl.c	1999/03/23 10:09:42
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7774,7804 ****
        else if (TREE_CODE (decl) == VAR_DECL
  	       && DECL_LANG_SPECIFIC (decl)
  	       && DECL_COMDAT (decl))
! 	{
! 	  /* Dynamically initialized vars go into common.  */
! 	  if (DECL_INITIAL (decl) == NULL_TREE
! 	      || DECL_INITIAL (decl) == error_mark_node)
! 	    DECL_COMMON (decl) = 1;
! 	  else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
! 	    {
! 	      DECL_COMMON (decl) = 1;
! 	      DECL_INITIAL (decl) = error_mark_node;
! 	    }
! 	  else
! 	    {
! 	      /* Statically initialized vars are weak or comdat, if
!                  supported.  */
! 	      if (flag_weak)
! 		make_decl_one_only (decl);
! 	      else
! 		{
! 		  /* We can't do anything useful; leave vars for explicit
! 		     instantiation.  */
! 		  DECL_EXTERNAL (decl) = 1;
! 		  DECL_NOT_REALLY_EXTERN (decl) = 0;
! 		}
! 	    }
! 	}
  
        if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
  	make_decl_rtl (decl, NULL_PTR, toplev);
--- 7774,7782 ----
        else if (TREE_CODE (decl) == VAR_DECL
  	       && DECL_LANG_SPECIFIC (decl)
  	       && DECL_COMDAT (decl))
! 	/* Set it up again; we might have set DECL_INITIAL since the
! 	   last time.  */
! 	comdat_linkage (decl);
  
        if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
  	make_decl_rtl (decl, NULL_PTR, toplev);
*************** expand_static_init (decl, init)
*** 8093,8098 ****
--- 8071,8079 ----
       tree init;
  {
    tree oldstatic = value_member (decl, static_aggregates);
+ 
+   /* If at_eof is 2, we're too late.  */
+   my_friendly_assert (at_eof <= 1, 990323);
  
    if (oldstatic)
      {
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.192
diff -c -p -r1.192 decl2.c
*** decl2.c	1999/03/15 13:08:26	1.192
--- decl2.c	1999/03/23 10:09:42
*************** comdat_linkage (decl)
*** 2370,2377 ****
  {
    if (flag_weak)
      make_decl_one_only (decl);
!   else
      TREE_PUBLIC (decl) = 0;
  
    if (DECL_LANG_SPECIFIC (decl))
      DECL_COMDAT (decl) = 1;
--- 2370,2395 ----
  {
    if (flag_weak)
      make_decl_one_only (decl);
!   else if (TREE_CODE (decl) == FUNCTION_DECL)
      TREE_PUBLIC (decl) = 0;
+   else
+     {
+       if (DECL_INITIAL (decl) == 0
+ 	  || DECL_INITIAL (decl) == error_mark_node)
+ 	DECL_COMMON (decl) = 1;
+       else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
+ 	{
+ 	  DECL_COMMON (decl) = 1;
+ 	  DECL_INITIAL (decl) = error_mark_node;
+ 	}
+       else
+ 	{
+ 	  /* We can't do anything useful; leave vars for explicit
+ 	     instantiation.  */
+ 	  DECL_EXTERNAL (decl) = 1;
+ 	  DECL_NOT_REALLY_EXTERN (decl) = 0;
+ 	}
+     }
  
    if (DECL_LANG_SPECIFIC (decl))
      DECL_COMDAT (decl) = 1;
*************** maybe_make_one_only (decl)
*** 2391,2404 ****
      return;
  
    /* We can't set DECL_COMDAT on functions, or finish_file will think
!      we can get away with not emitting them if they aren't used.
!      We can't use make_decl_one_only for variables, because their
!      DECL_INITIAL may not have been set properly yet.  */
  
!   if (TREE_CODE (decl) == FUNCTION_DECL)
!     make_decl_one_only (decl);
!   else
!     comdat_linkage (decl);
  }
  
  /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
--- 2409,2422 ----
      return;
  
    /* We can't set DECL_COMDAT on functions, or finish_file will think
!      we can get away with not emitting them if they aren't used.  We need
!      to for variables so that cp_finish_decl will update their linkage,
!      because their DECL_INITIAL may not have been set properly yet.  */
  
!   make_decl_one_only (decl);
! 
!   if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl))
!     DECL_COMDAT (decl) = 1;
  }
  
  /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
*************** import_export_decl (decl)
*** 2730,2739 ****
  	    /* Templates are allowed to have internal linkage.  See 
  	       [basic.link].  */
  	    ;
- 	  else if (TREE_CODE (decl) == FUNCTION_DECL)
- 	    comdat_linkage (decl);
  	  else
! 	    DECL_COMDAT (decl) = 1;
  	}
        else
  	DECL_NOT_REALLY_EXTERN (decl) = 0;
--- 2748,2755 ----
  	    /* Templates are allowed to have internal linkage.  See 
  	       [basic.link].  */
  	    ;
  	  else
! 	    comdat_linkage (decl);
  	}
        else
  	DECL_NOT_REALLY_EXTERN (decl) = 0;
*************** finish_file ()
*** 3344,3355 ****
    /* Done with C language context needs.  */
    pop_lang_context ();
  
    /* Now write out any static class variables (which may have since
       learned how to be initialized).  */
!   while (pending_statics)
      {
        tree decl = TREE_VALUE (pending_statics);
  
        /* Output DWARF debug information.  */
  #ifdef DWARF_DEBUGGING_INFO
        if (write_symbols == DWARF_DEBUG)
--- 3360,3377 ----
    /* Done with C language context needs.  */
    pop_lang_context ();
  
+   /* Let expand_static_init know it's too late for more ctors.  */
+   at_eof = 2;
+ 
    /* Now write out any static class variables (which may have since
       learned how to be initialized).  */
!   for (; pending_statics; pending_statics = TREE_CHAIN (pending_statics))
      {
        tree decl = TREE_VALUE (pending_statics);
  
+       if (TREE_ASM_WRITTEN (decl))
+ 	continue;
+ 
        /* Output DWARF debug information.  */
  #ifdef DWARF_DEBUGGING_INFO
        if (write_symbols == DWARF_DEBUG)
*************** finish_file ()
*** 3360,3370 ****
  	dwarf2out_decl (decl);
  #endif
  
!       DECL_DEFER_OUTPUT (decl) = 0;
        rest_of_decl_compilation
  	(decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
- 
-       pending_statics = TREE_CHAIN (pending_statics);
      }
  
    this_time = get_run_time ();
--- 3382,3396 ----
  	dwarf2out_decl (decl);
  #endif
  
!       /* We currently handle template statics here.  We ought to handle
! 	 them the same way we do template functions, i.e. only emit them if
! 	 the symbol is needed.  */
!       import_export_decl (decl);
!       if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl))
! 	DECL_EXTERNAL (decl) = 0;
! 
        rest_of_decl_compilation
  	(decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
      }
  
    this_time = get_run_time ();
*************** finish_file ()
*** 3426,3432 ****
  	      continue;
  
  	    if (TREE_ASM_WRITTEN (decl)
! 		|| (DECL_SAVED_INSNS (decl) == 0 && ! DECL_ARTIFICIAL (decl)))
  	      *p = TREE_CHAIN (*p);
  	    else if (DECL_INITIAL (decl) == 0)
  	      p = &TREE_CHAIN (*p);
--- 3452,3459 ----
  	      continue;
  
  	    if (TREE_ASM_WRITTEN (decl)
! 		|| (DECL_SAVED_INSNS (decl) == 0
! 		    && ! DECL_ARTIFICIAL (decl)))
  	      *p = TREE_CHAIN (*p);
  	    else if (DECL_INITIAL (decl) == 0)
  	      p = &TREE_CHAIN (*p);
*************** finish_file ()
*** 3475,3481 ****
    }
  
    /* Now delete from the chain of variables all virtual function tables.
!      We output them all ourselves, because each will be treated specially.  */
  
    walk_vtables ((void (*) PROTO((tree, tree))) 0,
  		prune_vtable_vardecl);
--- 3502,3509 ----
    }
  
    /* Now delete from the chain of variables all virtual function tables.
!      We output them all ourselves, because each will be treated
!      specially.  */
  
    walk_vtables ((void (*) PROTO((tree, tree))) 0,
  		prune_vtable_vardecl);


More information about the Gcc-patches mailing list