не удается связать переменную шаблона thread_local структуры внутри анонимного пространства имен?

#c #gcc #compiler-errors #compilation #clang

#c #gcc #ошибки компилятора #Сборник #лязг

Вопрос:

В следующем примере программа использует локальную переменную шаблона потока и создает ее экземпляр, используя тип внутри анонимного пространства имен. Это приводит к ошибке компоновщика в gcc . В clang нем фактически компилируется, но выполняется некорректно.

 #include <stdio.h>

template<typename T>
struct container {
    container()  { printf("construct: %pn", this); }
    ~container() { printf("destruct: %pn", this);  }
};

template<typename T>
thread_local container<T> storage;

namespace {
    struct bar {};
}

int main() {
    autoamp; ref1 = storage<bar>;
    autoamp; ref2 = storage<bar>;
}
  

В gcc это приводит к ошибке ссылки:

 a.cpp:6:2: warning: ‘container<T>::~container() noexcept [with T = {anonymous}::bar]’ used but never defined
  ~container() { printf("destruct: %pn", this);  }
  ^
/tmp/ccgh0P15.o: In function `__tls_init':
a.cpp:(.text 0xa9): undefined reference to `container<(anonymous namespace)::bar>::~container()'
  

С clang программа компилируется, но выдает очень тревожный результат:

 construct: 0x7fb8d1c003d0
construct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
  

Есть ли какие-то неровности, связанные с переменными thread_local / templated, с которыми я сталкиваюсь здесь? Мне непонятно, почему это когда-либо приведет к ошибке ссылки (ошибка ссылки исчезает, если я удаляю thread_local). В случае clang как двойное уничтожение объекта со статической продолжительностью хранения может быть чем угодно, кроме ошибки компилятора? В clang проблема исчезает, если я удаляю анонимное пространство имен ИЛИ спецификацию thread_local ИЛИ удаляю одну из ссылок в main() .

Может кто-нибудь пролить некоторый свет на это, мне в основном просто любопытно, если я что-то недопонимаю. Спасибо!

Редактировать:

 clang   -v

Apple LLVM version 10.0.0 (clang-1000.11.45.5)

g   -v

gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
  

Комментарии:

1. Это вся программа.

2. Хорошо, это действительно довольно интересно. Я предполагаю, что вас беспокоит вывод clang в том, что ctor / dtor, по-видимому, выполняется дважды?

3. Да, я должен был быть немного более ясным. Объект создается дважды, а затем дважды уничтожается, что мне определенно кажется недопустимым.

4. Кроме того, не обращайте внимания на мой комментарий из дальнейшего, касающийся UB, я написал это, основываясь на неправильном понимании того, что вы здесь делаете.