未定义的对 clang 中析构函数的引用

Undefined reference to a destructor in clang

编译以下代码得到 "undefined reference to `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(可能还有一些较旧的版本)。参见:https://godbolt.org/z/GNPk3V

在较新的 clang 版本和 gcc 上它工作正常。

这是预期的还是 clang 中的某种错误?

这似乎是 Bug 28280, fixed by https://reviews.llvm.org/D45898:

If an initializer in a braced-init-list is a C++ class that has a non-trivial destructor, mark the destructor as referenced. This fixes a crash in CodeGenFunction::destroyCXXObject that occurs when it tries to emit a call to the destructor on the stack unwinding path but the CXXRecordDecl of the class doesn't have a CXXDestructorDecl for the destructor.

此示例确实使用了花括号初始化列表并在调用 _Unwind_Resume 之前发出析构函数调用。析构函数不是微不足道的。将初始化更改为使用 () 而不是 {} 会使错误消失,因为它不再使用花括号初始化列表进行初始化。我评论中的析构函数调用可能会导致析构函数被标记为已引用。也许启用优化与使它只出现在非平凡的析构函数中的东西相同。