4

Put this in a file called t.hpp:

#include <unordered_map>

extern template class std::unordered_map<int, int>;

std::unordered_map<int, int> getMap();

And this in t.cpp:

#include "t.hpp"

std::unordered_map<int, int> getMap()
{
    return std::unordered_map<int, int>();
}

template class std::unordered_map<int, int>;

Then build it (on Linux):

g++ -std=c++11 -shared -fPIC -o t.so t.cpp

Then look at the constructors in the shared object:

objdump --syms --demangle t.so | grep '::unordered_map()'

If you compiled with GCC 4.9 it should show nothing at all. With GCC 5.1 or 5.3, it should show something like this:

8a w F .text 1b std::unordered_map<int, int>::unordered_map()

But with GCC 6.1 it shows something like this:

0 *UND* 0 std::unordered_map<int, int>::unordered_map()

That means the default constructor for the map is not emitted in the shared object, though it needs to be. This causes linking failures later, when using the shared object in an executable.

If you compile with -O1 or higher, the problem goes away (the constructor is inlined).

It seems like the explicit template instantiation in t.cpp is inhibited by the no-implicit declaration in t.hpp. A workaround I came up with is to #define SOMETHING in t.cpp before #include "t.hpp" then use #ifndef SOMETHING to guard the no-implicit declaration in t.hpp. But this wasn't necessary with GCC before version 6, and I'm not sure it should be.

Is this a bug in GCC 6.1? Or is the code wrong?

Edit: I found this bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57728 which might be related, but it was reported against GCC 4.8, while my problem doesn't occur until 6.1. GCC 5.1 vs 4.9 did introduce a nullary default constructor with = default instead of default arguments on a multi-argument one, but again, it isn't until GCC 6.1 that my problem appears.

bogdan
  • 9,229
  • 2
  • 33
  • 48
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    Definitely looks like 57728 to me and appears to be fixed on trunk. Maybe some other change between 5 and 6 revealed the latent bug in 5. – T.C. Oct 03 '16 at 14:56
  • @T.C.: 57728 manifests in GCC 4.7 and 4.9 as well...whereas my issue does not. I'm still not sure it's related. – John Zwinck Oct 13 '16 at 04:54
  • 1
    57728 breaks only with a defaulted function, so if GCC 4.7/4.9's `unordered_map` doesn't have a defaulted default ctor then it's unsurprising you didn't observe the issue. – T.C. Oct 13 '16 at 05:09
  • @T.C.: Fair point. I narrowed it down some more: it worked until 5.3, broke in 5.4, is still broken in 6.2, but fixed in 7: https://godbolt.org/g/zSdGJw – John Zwinck Oct 13 '16 at 05:16
  • I flagged this as a duplicate of question 38929950 even though this question is older because 1) it has more views 2) it has no STL-type dependency, which narrows the problem down 3) also mentions that Clang was affected as well – suluke Sep 22 '18 at 15:29

0 Answers0