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++ PATCH: PR9683


This patch fixes a silent code-generation regression from GCC 2.95.x.

Tested on i686-pc-linux-gnu, applied on the mainline and on the 3.3
branch.

--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery dot com

2003-02-25  Mark Mitchell  <mark at codesourcery dot com>

	PR c++/9683
	* decl2.c (prune_vars_needing_no_initialization): Do not throw
	away initializations for DECL_EXTERNAL VAR_DECLs.
	(finish_file): Adjust accordingly.
	* pt.c (instantiate_decl): Do not defer VAR_DECLs.

2003-02-25  Mark Mitchell  <mark at codesourcery dot com>

	PR c++/9683
	* g++.dg/template/static3.C: New test.

Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.599
diff -c -5 -p -r1.599 decl2.c
*** cp/decl2.c	15 Feb 2003 18:03:21 -0000	1.599
--- cp/decl2.c	26 Feb 2003 05:32:35 -0000
*************** static void do_static_destruction (tree)
*** 82,92 ****
  static tree start_static_initialization_or_destruction (tree, int);
  static void finish_static_initialization_or_destruction (tree);
  static void generate_ctor_or_dtor_function (bool, int);
  static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node,
                                                            void *);
! static tree prune_vars_needing_no_initialization (tree);
  static void write_out_vars (tree);
  static void import_export_class (tree);
  static tree get_guard_bits (tree);
  
  /* A list of static class variables.  This is needed, because a
--- 82,92 ----
  static tree start_static_initialization_or_destruction (tree, int);
  static void finish_static_initialization_or_destruction (tree);
  static void generate_ctor_or_dtor_function (bool, int);
  static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node,
                                                            void *);
! static tree prune_vars_needing_no_initialization (tree *);
  static void write_out_vars (tree);
  static void import_export_class (tree);
  static tree get_guard_bits (tree);
  
  /* A list of static class variables.  This is needed, because a
*************** do_static_destruction (tree decl)
*** 2398,2440 ****
     VARS is in reverse order of the order in which they should actually
     be initialized.  The list we return is in the unreversed order;
     i.e., the first variable should be initialized first.  */
  
  static tree
! prune_vars_needing_no_initialization (tree vars)
  {
!   tree var;
!   tree result;
  
!   for (var = vars, result = NULL_TREE;
!        var;
!        var = TREE_CHAIN (var))
      {
!       tree decl = TREE_VALUE (var);
!       tree init = TREE_PURPOSE (var);
  
        /* Deal gracefully with error.  */
        if (decl == error_mark_node)
! 	continue;
  
        /* The only things that can be initialized are variables.  */
        my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
  
        /* If this object is not defined, we don't need to do anything
  	 here.  */
        if (DECL_EXTERNAL (decl))
! 	continue;
  
        /* Also, if the initializer already contains errors, we can bail
  	 out now.  */
        if (init && TREE_CODE (init) == TREE_LIST 
  	  && value_member (error_mark_node, init))
! 	continue;
  
        /* This variable is going to need initialization and/or
  	 finalization, so we add it to the list.  */
!       result = tree_cons (init, decl, result);
      }
  
    return result;
  }
  
--- 2398,2450 ----
     VARS is in reverse order of the order in which they should actually
     be initialized.  The list we return is in the unreversed order;
     i.e., the first variable should be initialized first.  */
  
  static tree
! prune_vars_needing_no_initialization (tree *vars)
  {
!   tree *var = vars;
!   tree result = NULL_TREE;
  
!   while (*var)
      {
!       tree t = *var;
!       tree decl = TREE_VALUE (t);
!       tree init = TREE_PURPOSE (t);
  
        /* Deal gracefully with error.  */
        if (decl == error_mark_node)
! 	{
! 	  var = &TREE_CHAIN (t);
! 	  continue;
! 	}
  
        /* The only things that can be initialized are variables.  */
        my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
  
        /* If this object is not defined, we don't need to do anything
  	 here.  */
        if (DECL_EXTERNAL (decl))
! 	{
! 	  var = &TREE_CHAIN (t);
! 	  continue;
! 	}
  
        /* Also, if the initializer already contains errors, we can bail
  	 out now.  */
        if (init && TREE_CODE (init) == TREE_LIST 
  	  && value_member (error_mark_node, init))
! 	{
! 	  var = &TREE_CHAIN (t);
! 	  continue;
! 	}
  
        /* This variable is going to need initialization and/or
  	 finalization, so we add it to the list.  */
!       *var = TREE_CHAIN (t);
!       TREE_CHAIN (t) = result;
!       result = t;
      }
  
    return result;
  }
  
*************** finish_file ()
*** 2623,2634 ****
        /* The list of objects with static storage duration is built up
  	 in reverse order.  We clear STATIC_AGGREGATES so that any new
  	 aggregates added during the initialization of these will be
  	 initialized in the correct order when we next come around the
  	 loop.  */
!       vars = prune_vars_needing_no_initialization (static_aggregates);
!       static_aggregates = NULL_TREE;
  
        if (vars)
  	{
  	  tree v;
  
--- 2633,2643 ----
        /* The list of objects with static storage duration is built up
  	 in reverse order.  We clear STATIC_AGGREGATES so that any new
  	 aggregates added during the initialization of these will be
  	 initialized in the correct order when we next come around the
  	 loop.  */
!       vars = prune_vars_needing_no_initialization (&static_aggregates);
  
        if (vars)
  	{
  	  tree v;
  
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.665
diff -c -5 -p -r1.665 pt.c
*** cp/pt.c	24 Feb 2003 21:51:59 -0000	1.665
--- cp/pt.c	26 Feb 2003 05:32:37 -0000
*************** instantiate_decl (d, defer_ok)
*** 10645,10654 ****
--- 10645,10657 ----
    /* This function should only be used to instantiate templates for
       functions and static member variables.  */
    my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
  		      || TREE_CODE (d) == VAR_DECL, 0);
  
+   if (TREE_CODE (d) == VAR_DECL)
+     defer_ok = 0;
+ 
    /* Don't instantiate cloned functions.  Instead, instantiate the
       functions they cloned.  */
    if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
      d = DECL_CLONED_FUNCTION (d);
  
Index: testsuite/g++.dg/template/static3.C
===================================================================
RCS file: testsuite/g++.dg/template/static3.C
diff -N testsuite/g++.dg/template/static3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/static3.C	26 Feb 2003 05:32:38 -0000
***************
*** 0 ****
--- 1,25 ----
+ template <class data> class foo
+ {
+     public:
+ 	static const int a;
+ 	static const int b;
+ 	static const int c;
+ 	static const int d;
+ };
+ 
+ template <class data> const int foo<data>::a = 1;
+ template <class data> const int foo<data>::b = a;
+ template <class data> const int foo<data>::c = b;
+ template <class data> const int foo<data>::d = c;
+ 
+ typedef foo<int> fooInt;
+ 
+ int main( void )
+ {
+     fooInt *f;
+ 
+     f = new fooInt();
+ 
+     if (f->c != 1 || f->d != 1)
+       return 1;
+ }


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