Description
Bugzilla Link | 46699 |
Version | trunk |
OS | All |
CC | @dwblaikie,@DougGregor,@ot,@zygoloid,@rjmccall,@rnk |
Extended Description
Consider the following code:
template <class T> T &&declval() noexcept;
template <class _Functor> struct invoke_result {
template <class _Fn> static decltype(declval<_Fn>()(0)) s_test();
typedef decltype(s_test<_Functor>()) type;
};
template <class T> struct Core {
Core() {}
virtual ~Core() {}
};
template <class FF> auto run(FF &&ff) {
auto lambda = [ff](auto) { return ff(0); };
using T = typename invoke_result<decltype(lambda)>::type;
return lambda(0);
}
class Trivial {};
Core<Trivial> *f() {
return run([](auto) -> Core<Trivial> * { return new Core<Trivial>(); });
}
If I build this with clang, it emits a vtable for Core<Trivial>
that references the complete object and deleting destructors for Core<Trivial>
, but it doesn't actually emit those destructors, which later leads to a link error. As best as I can tell, it should be emitting the destructors; all the relevant types are complete, and there's no key functions. https://godbolt.org/z/czGEzT shows that GCC does emit the destructors (-O2
and -fno-rtti
are just to clean up the assembly, and if you remove the filtering for directives you'll see that GCC is aliasing the complete object destructor to the base object destructor).
The reduction is very sensitive. Removing the explicit return type from the lambda in f
, removing the parameters from the lambdas (so as to make them non-generic lambdas), using FF
instead of decltype(lambda)
in run, and making s_test
in invoke_result
use _Functor
instead of having its own _Fn
template type all make the destructors be emitted. (invoke_result
and declval
are reduced from libstdc++; I'm not fully confident about the validity of my reduction, but GCC is still able to emit the destructors.)