This is the mail archive of the gcc@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]

Why warning on static local variables ... ?


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;
}


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