Bug 44855 - Static members not initialised in explicit template instances of library
Summary: Static members not initialised in explicit template instances of library
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-07 07:17 UTC by Prasad H. L.
Modified: 2011-10-02 10:19 UTC (History)
0 users

See Also:
Host: i686-redhat-linux
Target: i686-redhat-linux
Build: i686-redhat-linux
Known to work:
Known to fail:
Last reconfirmed:


Attachments
The test case attached (1021 bytes, application/octet-stream)
2010-07-07 07:22 UTC, Prasad H. L.
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Prasad H. L. 2010-07-07 07:17:32 UTC
Consider the following C++ source code files

=========> testLib.h <===========
#include <stdexcept>
#include <iostream>

#define DEBUG1(X) std::cout<<X;

typedef int IndexType;

namespace Upagraha
{

template<typename X,int Size>
class CompileTimeFixedSizeData
{

protected:
	X _data[Size];		//!< The storage of the data
	static IndexType _size; //!< The size of the data.
public:
	CompileTimeFixedSizeData()
	{
	  DEBUG1("Template value = "<< Size << std::endl);
	  DEBUG1("Static variable value = "<< _size<< std::endl);
	}
	
	virtual ~CompileTimeFixedSizeData()
	{}
};


//setting the value of _size, which is static
template<typename X,int Size>
IndexType CompileTimeFixedSizeData<X,Size>::_size=Size;

/** Create an instance of CompileTimeFixedSizeData and associated functions. 
 */
#define COMPILE_TIME_FIXED_SIZE_DATA_INSTANCE(TYPE,SIZE) \
	template class CompileTimeFixedSizeData<TYPE,SIZE>;

}

=========> testLib.cpp <===========
#include "testLib.h"
namespace Upagraha
{
	COMPILE_TIME_FIXED_SIZE_DATA_INSTANCE(double,3)
}

=========> main.cpp <===========
#include "testLib.h"

namespace Upagraha {
//extern template class CompileTimeFixedSizeData<double,3>;
// FIXME: Uncomment to see a change in behavior
}

int main()
{
	Upagraha::CompileTimeFixedSizeData<double,3> a;
}


=========> makefile <===========

#OPTIONS=-rdynamic -fno-implicit-templates -fPIC
OPTIONS=-rdynamic -fno-implicit-templates
# FIXME: Uncomment the top one to see change in behaviour

test:libtestLib.so testLib.h main.cpp
	g++ $(OPTIONS) $(TOPTIONS) main.cpp -L"${PWD}" -ltestLib -o main 

libtestLib.so: testLib.cpp testLib.h
	g++ $(OPTIONS) $(TOPTIONS) -shared testLib.cpp -o libtestLib.so

clean:
	rm main libtestLib.so *~

====================================

Put the above four files in same the directory and do the following
*) make
*) export LD_LIBRARY_PATH="$PWD"
*) ./main

You'll see the output as 
=====================
Template value = 3
Static variable value = 0
=====================

Now, follow either of the two "FIXME"s and build the program and run to get
=====================
Template value = 3
Static variable value = 3
=====================

Why this difference in behaviour in initialisation of static variable Upagraha::CompileTimeFixedSizeData<X,Size>::_size? Could somebody please explain this?
Comment 1 Prasad H. L. 2010-07-07 07:22:00 UTC
Created attachment 21120 [details]
The test case attached

To simplify the task of whomsoever who wants to see the behaviour, all the files mentioned in my previous post is packaged in a tar.bz2 file attached here.
Comment 2 Jonathan Wakely 2010-07-07 09:18:10 UTC
You need to use -fPIC for a shared object, so the version without that is not valid.
Comment 3 Prasad H. L. 2010-07-07 09:30:32 UTC
Subject: Re:  Static members not initialised in explicit 
	template instances of library

But, as I know, no where is it mentioned to be necessary for static
member initialisation. Why should the compiler allow for such a subtle
error? Or is this documented somewhere?

Besides this issue, I've not faced any other problem in using shared
library by not using -fPIC. Could you please point out the necessary
implications that I am missing here?


On 7 July 2010 14:48, redi at gcc dot gnu dot org
<gcc-bugzilla@gcc.gnu.org> wrote:
>
>
> ------- Comment #2 from redi at gcc dot gnu dot org  2010-07-07 09:18 -------
> You need to use -fPIC for a shared object, so the version without that is not
> valid.
>
>
Comment 4 Andrew Pinski 2010-07-25 02:04:21 UTC
Well for x86_64 we get an error:
/usr/bin/ld: testLib.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
Comment 5 Andrew Pinski 2010-07-25 02:13:52 UTC
Works for me on the trunk and in 4.3.2.

Can you give the output of "gcc -v"?
Comment 6 Prasad H. L. 2010-07-25 06:35:29 UTC
Subject: Re:  Static members not initialised in explicit 
	template instances of library

Output of "gcc -v" is given below. I'm using Fedora 13 (with updates
till July 24, 2010). The error still persists.
===================
Using built-in specs.
Target: i686-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info
--with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap
--enable-shared --enable-threads=posix --enable-checking=release
--with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-gnu-unique-object
--enable-languages=c,c++,objc,obj-c++,java,fortran,ada
--enable-java-awt=gtk --disable-dssi
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre
--enable-libgcj-multifile --enable-java-maintainer-mode
--with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic
--with-arch=i686 --build=i686-redhat-linux
Thread model: posix
gcc version 4.4.4 20100630 (Red Hat 4.4.4-10) (GCC)
===================

On 25 July 2010 07:43, pinskia at gcc dot gnu dot org
<gcc-bugzilla@gcc.gnu.org> wrote:
> ------- Comment #5 from pinskia at gcc dot gnu dot org  2010-07-25 02:13 -------
> Works for me on the trunk and in 4.3.2.
>
> Can you give the output of "gcc -v"?
>
Comment 7 Jonathan Wakely 2011-03-29 19:05:32 UTC
I can reproduce this on Fedora 13

using -fpic or -fPIC fixes it (as well as avoiding SELinux "permission denied" errors when loading the shared object)
Comment 8 Jonathan Wakely 2011-03-29 19:51:15 UTC
I should have read the code properly ... if you've suppressed implicit instantiation in main.cpp and you want the explicit instantiation in a shared object to be used I would expect that you need to *either* use -fpic so the instantiation in the .so is used *or* declare the explicit instantiation by uncommenting the "extern template" declaration.

So I think the behaviour you're seeing is normal
Comment 9 Paolo Carlini 2011-10-02 10:19:01 UTC
Closing.