[PATCH] problem with static variables in template functions

scott snyder snyder@d0sgif.fnal.gov
Sun Aug 9 14:20:00 GMT 1998

hi -

The egcs 1.1 test version appears to mishandle static variables
in template functions on Digital Unix.

Here are the version numbers:

>From egcs_1_1_branch, checked out the afternoon of Aug. 6, 1998.
gcc version egcs-2.91.53 19980806 (gcc2 ss-980609 experimental)
Native configuration is alphaev56-dec-osf4.0b

Here's an example:

--- u.hpp --------------------------------------------------------------
template <class T> 
class T2
  static int use_x (int x = 0)
    static int xstatic;
    if (x)
      xstatic = x;
    return xstatic;
--- u1.cpp -------------------------------------------------------------
#include "u.hpp"

void u1 ()
  T2<int>::use_x (1);
--- u2.cpp -------------------------------------------------------------
#include "u.hpp"
#include <iostream.h>

void u1 ();

main ()
  u1 ();
  cout << T2<int>::use_x (0) << "\n";

Compile these two modules together with `g++ -o u u1.cpp u2.cpp'.

When run, this prints `0', rather than `1' as i'd expect
(and which i get with other compilers).

If i look at the symbols which are being generated, 

u1.s:   .lcomm xstatic.4,4
u2.s:   .lcomm xstatic.284,4

An instance of T2<int>::use_x(int) is being generated in each
compilation unit, but the xstatic variable each uses is local.

I also tried this test with the same version of the compiler
built on a linux platform.  There, it worked.  The difference
was that on linux, the template function instantiations were
given weak linkage, so that only one copy was actually linked
into the binary.

I tried rebuilding the test on the digital unix platform with -frepo,
but that didn't help --- gcc still generates two copies of the
use_x() function in the binary.  (The use_x() function itself gets
a module-local symbol.)

Here's a patch which seems to fix it.  In tsubst_expt, i call
build_static_name for static variable declarations, to give static
variables a unique external name.  Then in cp_finish_decl,
static variables of template functions are marked public.

I've applied this patch to the 1.1 branch and tested it on digital
unix and i386/linux platforms.  In both cases, this patch causes no
changes in the test results.  I haven't yet tested this on the main


1998-08-09  scott snyder  <snyder@d0linux01.fnal.gov>

	* pt.c (tsubst_expr): Use build_static_name for static variable
	* decl.c (cp_finish_decl): Turn on TREE_PUBLIC for static
	variables in template functions.

Index: cp/decl.c
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision
diff -u -u -p -r1.152.2.8 decl.c
--- decl.c	1998/07/29 14:56:23
+++ decl.c	1998/08/09 21:06:15
@@ -7236,6 +7236,20 @@ cp_finish_decl (decl, init, asmspec_tree
+      /* Static variables in template functions should have a public
+         name, in case we end up instantiating the template in multiple
+         compilation units. */
+      if (TREE_CODE (decl) == VAR_DECL
+	  && TREE_STATIC (decl)
+	  && ! TREE_ASM_WRITTEN (decl)
+	  && current_function_decl
+	  && DECL_CONTEXT (decl) == current_function_decl
+          && DECL_LANG_SPECIFIC (current_function_decl)
+          && DECL_USE_TEMPLATE (current_function_decl))
+      {
+        TREE_PUBLIC (decl) = 1;
+      }
       if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
 	make_decl_rtl (decl, NULL_PTR, toplev);
       else if (TREE_CODE (decl) == VAR_DECL
Index: cp/pt.c
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision
diff -u -u -p -r1.162.2.5 pt.c
--- pt.c	1998/07/27 11:15:25
+++ pt.c	1998/08/09 21:06:16
@@ -5516,6 +5516,14 @@ tsubst_expr (t, args, in_decl)
 	  (tsubst (TREE_OPERAND (t, 0), args, in_decl),
 	   tsubst (TREE_OPERAND (t, 1), args, in_decl),
+        /* If this is a static variable declaration, give it an external
+           name which is distinguished from other instantiations
+           of this template. */
+        if (TREE_CODE (dcl) == VAR_DECL && TREE_STATIC (dcl))
+          DECL_ASSEMBLER_NAME (dcl) =
+            build_static_name (DECL_CONTEXT (dcl), DECL_NAME (dcl));
 	init = tsubst_expr (TREE_OPERAND (t, 2), args, in_decl);
 	  (dcl, init, NULL_TREE, 1, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);

More information about the Gcc-patches mailing list