Неопределенная ссылка на деструктор в clang - PullRequest
4 голосов
/ 11 октября 2019

Компиляция следующего кода дает «неопределенную ссылку на« A :: ~ A () »:

#include <cstdlib>
#include <memory>

template <typename T>
struct A {
        A() {}
        ~A() {}
};

struct Aggregate {
        using key_vector = A<char>;
        using value_vector = A<int>;

        value_vector vals;
        key_vector keys;
};

int
main()
{
        auto x = malloc(sizeof(Aggregate));
        new (x) Aggregate{};

        return 0;
}

проблема присутствует в clang 7.0 и 6.0 (возможно, также в некоторых версиях oolder). См .: https://godbolt.org/z/GNPk3V

На новых версиях clang и на gcc все работает нормально.

Это ожидаемое или это какая-то ошибка в clang?

1 Ответ

4 голосов
/ 11 октября 2019

Кажется, что это Ошибка 28280 , исправленная https://reviews.llvm.org/D45898:

Если инициализатор в фигурном списке инициализации является классом C ++, который имеет нетривиальныйдеструктор, пометить деструктор как указанный. Это исправляет сбой в CodeGenFunction :: destroyCXXObject, который возникает, когда он пытается отправить вызов деструктору в пути разматывания стека, но CXXRecordDecl этого класса не имеет CXXDestructorDecl для деструктора.

В этом примере действительно используется список фигурных скобок init-list, и он посылает вызов деструктора непосредственно перед вызовом _Unwind_Resume. Деструктор не тривиален. Изменение инициализации для использования () вместо {} устраняет ошибку, поскольку она больше не инициализируется с помощью списка фигурных скобок. Вызов деструктора в моем комментарии может привести к тому, что деструктор будет помечен как ссылка. Возможно, включение оптимизации играет с теми же вещами, которые делают это видимым только для нетривиальных деструкторов.

...