This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR9683
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 25 Feb 2003 21:40:57 -0800
- Subject: C++ PATCH: PR9683
- Reply-to: mark at codesourcery dot com
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;
+ }