Search code examples
c++linkercompiler-constructionclang

Undefined reference to a destructor in clang


Compiling following code gives "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;
}

the problem is present on clang 7.0 and 6.0 (possibly also some oolder versions). See: https://godbolt.org/z/GNPk3V

On newer clang versions and on gcc it works fine.

Is this expected or is it some kind of bug in clang?


Solution

  • This appears to be 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.

    This example does use a braced-init-list and emits the destructor call right before calling _Unwind_Resume. The destructor is not trivial. Changing the initialization to use () instead of {} makes the error go away because it's no longer initialized with a braced-init-list. The destructor call in my comment would presumably cause the destructor to be marked as referenced. Perhaps enabling optimization plays with the same things that make this appear only for non-trivial destructors.