Bug 55800 - Link failure with thread_local in unnamed namespace
Summary: Link failure with thread_local in unnamed namespace
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: 4.8.3
Assignee: Jason Merrill
URL:
Keywords:
: 59364 (view as bug list)
Depends on:
Blocks: 59994
  Show dependency treegraph
 
Reported: 2012-12-23 20:28 UTC by vlukas
Modified: 2014-01-31 16:26 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.9.0
Known to fail:
Last reconfirmed: 2014-01-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description vlukas 2012-12-23 20:28:26 UTC
Considering this snippet:
-------------------------------------------------------

namespace {
  struct X { X() { } };
  thread_local X x;  
}

int main() { x; }
-----------------------------------------------------

Compiling with "c++ -std=c++0x" results in:
----------------------------------------------------
/tmp/cceAUNGB.o: In function `_ZTWN12_GLOBAL__N_11xE':
thread_local.link_failure.with_main.cc:(.text+0x55): undefined reference to `_ZTHN12_GLOBAL__N_11xE'
collect2: error: ld returned 1 exit status
------------------------------------------------------

Output of c++ -v is:
-----------------------------------------------------------
Using built-in specs.
COLLECT_GCC=/home/lima/vanilla_installs/gcc_and_tools/bin/c++
COLLECT_LTO_WRAPPER=/home/lima/vanilla_installs/gcc_and_tools/lib/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc_svn/configure --prefix=/home/lima/vanilla_installs/gcc_and_tools --enable-__cxa_atexit --enable-languages=c,c++ --disable-nls --disable-multilib
Thread model: posix
gcc version 4.8.0 20121223 (experimental) (GCC)
-----------------------------------------------------------
Comment 1 Marcel Meyer 2013-06-14 22:43:07 UTC
Confirmed for 4.8.1 (using -std=c++11). Seems to be the same as bug #57163.
Comment 2 linedot 2013-10-18 17:05:36 UTC
I have encountered a similar problem

output of gcc -v:
Using built-in specs.
COLLECT_GCC=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.1/g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.8.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-4.8.1-r1/work/gcc-4.8.1/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.1 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.1 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.1/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.1/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --with-cloog --disable-isl-version-check --enable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --enable-multilib --with-multilib-list=m32,m64 --enable-libmudflap --disable-libssp --enable-libgomp --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.8.1/python --enable-checking=release --disable-libgcj --enable-libstdcxx-time --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-targets=all --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.8.1-r1 p1.2, pie-0.5.7'
Thread model: posix
gcc version 4.8.1 (Gentoo 4.8.1-r1 p1.2, pie-0.5.7)

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

Here's a simplified version of the code I was using:
=========================================================================
main.cpp:

#include "xyz.hpp"

int main()
{
    return *xyz::getBla();
}

=========================================================================
xyz.hpp:

#include <memory>

class xyz
{
private:
    static thread_local std::unique_ptr<int> bla;
public:
    static int* getBla()
    {
        if(!bla.get())
        {
            bla.reset(new int(4));
        }
        return bla.get();
    }
};

=========================================================================
xyz.cpp:

#include "xyz.hpp"

thread_local std::unique_ptr<int> xyz::bla;

=========================================================================
If I try to compile this with
g++ -std=c++11 main.cpp xyz.cpp

/tmp/ccLJmEUa.o: In function `_ZTWN3xyz3blaE':
main.cpp:(.text._ZTWN3xyz3blaE[_ZTWN3xyz3blaE]+0x5): undefined reference to `_ZTHN3xyz3blaE'
collect2: error: ld returned 1 exit status

I don't know if the following is any help:
I messed with the assembly output of g++ when compiling xyz.cpp and it looks that _ZTWN3xyz3blaE should be where __tls_init begins - at least adding
.globl  _ZTWN3xyz3blaE
_ZTWN3xyz3blaE = __tls_init

manually at the end of the assembly seems to make the code do what it is supposed to.
Comment 3 Richard Biener 2014-01-30 15:24:10 UTC
Works for me with 4.8.0 and later.
Comment 4 linedot 2014-01-30 15:42:12 UTC
The code from comment 2 still doesn't work with GCC 4.8.2
=========================================================================
gcc -v:
Using built-in specs.
COLLECT_GCC=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.2/gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.8.2/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-4.8.2/work/gcc-4.8.2/configure --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.2 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.2 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.2/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.2/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/include/g++-v4 --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.8.2/python --enable-languages=c,c++,fortran --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.8.2 p1.3, pie-0.5.8' --enable-libstdcxx-time --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-multilib --with-multilib-list=m32,m64 --disable-altivec --disable-fixed-point --enable-targets=all --disable-libgcj --enable-libgomp --enable-libmudflap --disable-libssp --enable-lto --with-cloog --disable-isl-version-check
Thread model: posix
gcc version 4.8.2 (Gentoo 4.8.2 p1.3, pie-0.5.8) 
=========================================================================

output of compiling code from Comment 2:
g++ -std=c++11 main.cpp xyz.cpp

/tmp/cccXvzux.o: In function `TLS wrapper function for xyz::bla':
main.cpp:(.text._ZTWN3xyz3blaE[_ZTWN3xyz3blaE]+0x5): undefined reference to `TLS init function for xyz::bla'
collect2: error: ld returned 1 exit status
=========================================================================
Comment 5 Richard Biener 2014-01-30 15:49:44 UTC
Works with 4.9 though.
Comment 6 Jason Merrill 2014-01-31 15:48:26 UTC
*** Bug 59364 has been marked as a duplicate of this bug. ***
Comment 7 Jason Merrill 2014-01-31 16:26:25 UTC
Fixed for 4.8.3.
Comment 8 Jason Merrill 2014-01-31 16:26:28 UTC
Author: jason
Date: Fri Jan 31 16:25:55 2014
New Revision: 207360

URL: http://gcc.gnu.org/viewcvs?rev=207360&root=gcc&view=rev
Log:
	PR c++/55800
	* decl2.c (get_tls_init_fn): Copy DECL_EXTERNAL from the variable.

Added:
    trunk/gcc/testsuite/g++.dg/tls/thread_local8.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/decl2.c
Comment 9 Jason Merrill 2014-01-31 16:26:34 UTC
Author: jason
Date: Fri Jan 31 16:26:02 2014
New Revision: 207361

URL: http://gcc.gnu.org/viewcvs?rev=207361&root=gcc&view=rev
Log:
	PR c++/55800
	* decl2.c (get_tls_init_fn): Copy DECL_EXTERNAL from the variable.

Added:
    branches/gcc-4_8-branch/gcc/testsuite/g++.dg/tls/thread_local8.C
Modified:
    branches/gcc-4_8-branch/gcc/cp/ChangeLog
    branches/gcc-4_8-branch/gcc/cp/decl2.c