This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Why warning on static local variables ... ?
- To: egcs at cygnus dot com
- Subject: Why warning on static local variables ... ?
- From: "Munagala V. S. Ramanath" <ram at netcom dot com>
- Date: Sun, 19 Apr 1998 15:56:15 -0700 (PDT)
Hi,
The following program illustrates several puzzling elements in the
behavior of egcs-1.0.2; I'm not sure if they are bugs in my
understanding of templates or bugs in egcs, so I thought I'd ask here:
PROBLEM 1. When compiled as is with "gcc -Wall tmp1.C -lstdc++", I get:
========================================================================
tmp1.C: In function `struct A<int,8> Mul<A<int,8>>(const struct A<int,8> &, const struct A<int,8> &)':
tmp1.C:51: warning: sorry: semantics of inline function static data `int const n' are wrong (you'll wind up with multiple copies)
========================================================================
When I run the resulting executable, I get:
========================================================================
A(int): val = 2560
A(int): val = 2304
Mul: &n = 0x22a0, n = 8
A(int): val = 6553600
Mul: &n = 0x22a0, n = 8
A(int): val = 5308416
f1 = 10, f3 = 25600, f2 = 9, f4 = 20736
========================================================================
Why does it warn about "multiple copies" on static local data in
inline template functions ? I could think of 3 possible situations:
(a) Multiple copies in different specializations. This cannot be the
problem because in that case, "multiple" copies is precisely what
the user wants -- one per specialization.
(b) Multiple copies of the same specialization at multiple call
sites. As the above output shows, it does _not_ in fact create
"multiple" copies since the address of 'n' is 0x22a0 in both
invocations of Mul().
(c) Same as (b) but call sites in different compilation units. Given
the complexity of template code that egcs already correctly
handles, it does not seem that hard to avoid duplicates in this
case.
So I'm really puzzled about this warning and wondering if there is
some way to use static local data in inline template functions
without drawing this warning with -Wall.
PROBLEM 2: As can be seen from the above program output, it seems to
be invoking the wrong constructor [A(int) instead of A(&A)] for the
declaration like: B f3( Mul<B>( f1, f1 ) );
Is there some default rule that I'm overlooking or is it a bug ?
PROBLEM 3: If the "#define WORKS" is commented out, it gets all
confused about instantiationg operator<<; even adding an explicit
instantiation does not help. Here is the initial part of the list of
diagnostics I get:
========================================================================
tmp1.C: In function `struct A<int,8> Mul<A<int,8>>(const struct A<int,8> &, const struct A<int,8> &)':
tmp1.C:51: warning: sorry: semantics of inline function static data `int const n' are wrong (you'll wind up with multiple copies)
tmp1.C: In function `class ostream & operator <<<char[15]>(class ostream &, const char (&)[15])':
tmp1.C:66: request for member `val' in `a', which is of non-aggregate type `char[15]'
tmp1.C:66: `char[15]' is not an aggregate type
tmp1.C:66: warning: control reaches end of non-void function `operator <<<char[15]>(ostream &, const char (&)[15])'
tmp1.C: In function `class ostream & operator <<<char[11]>(class ostream &, const char (&)[11])':
tmp1.C:66: request for member `val' in `a', which is of non-aggregate type `char[11]'
tmp1.C:66: `char[11]' is not an aggregate type
tmp1.C:66: warning: control reaches end of non-void function `operator <<<char[11]>(ostream &, const char (&)[11])'
tmp1.C: In function `class ostream & operator <<<const int *>(class ostream &, const int *const &)':
tmp1.C:66: request for member `val' in `a', which is of non-aggregate type `const int *'
tmp1.C:66: `const int *' is not an aggregate type
tmp1.C:66: warning: control reaches end of non-void function `operator <<<const int *>(ostream &, const int *const &)'
...
========================================================================
Thanks for any help.
Ram
//----------- CUT HERE --------------------- CUT HERE --------------
// illustrates 3 problems in egcs-1.0.2:
// 1. unnecessary warning for static local variables in template
// functions
// 2. seems to invoke the wrong constructor
// 3. templated operator<< declaration needs to be more elaborate than
// necessary.
//
#include <fstream.h>
// forward declarations needed for the friend declarations below
template< class T, int NUM > struct A;
template< class T > inline T Mul( const T &a1, const T &a2 );
// commenting out following line yields diagnostics
#define WORKS
#ifdef WORKS
template< class T, int NUM > ostream &
operator<<( ostream &os, const A< T, NUM > &a );
#else
template< class T > ostream & operator<<( ostream &os, const T &a );
#endif
template< class T, int NUM >
struct A {
friend A Mul< A > ( const A &a1, const A &a2 );
#ifdef WORKS
friend ostream & operator<< < T, NUM >(
ostream &os, const A< T, NUM > &a );
#else
friend ostream & operator<< < T >(
ostream &os, const T &a );
#endif
static const int N = NUM;
static const int ONE = 1 << NUM;
A( const int a ) : val( a << NUM ) {
cerr << "A(int): val = " << val << endl; }
A( const A &a ) : val( a.val ) {
cerr << "A(&A): val = " << val << endl; }
T val;
};
typedef A< int, 8 > B;
template< class T > inline T
Mul( const T &a1, const T &a2 ) {
static const int n = T::N;
cout << "Mul: &n = " << &n << ", n = " << n << endl;
return (a1.val * a2.val) >> n;
}
#ifdef WORKS
template< class T, int NUM > ostream &
operator<<( ostream &os, const A< T, NUM > &a )
{
return os << a.val / static_cast<double>(A<T,NUM>::ONE);
}
#else
template< class T > ostream &
operator<<( ostream &os, const T &a )
{
return os << a.val / static_cast<double>(T::ONE);
}
// even adding an explicit instantiation does not help this case
template ostream &operator<< < B >( ostream &, const B & );
#endif
main()
{
B f1( 10 ), f2( 9 ), f3( Mul<B>( f1, f1 ) ), f4( Mul<B>( f2, f2 ) );
cout << "f1 = " << f1 << ", f3 = " << f3
<< ", f2 = " << f2 << ", f4 = " << f4 << endl;
return 0;
}