Hi, the following code gets properly optimized-out if erasedTypeVTable is initialized with &dtor<T> (case [2]), but it is not optimized if initialized with lambda (case [1]). #include <type_traits> #include <new> namespace { struct ErasedTypeVTable { using destructor_t = void (*)(void *obj); destructor_t dtor; }; template <typename T> void dtor(void *obj) { return static_cast<T *>(obj)->~T(); } template <typename T> static const ErasedTypeVTable erasedTypeVTable = { /* 1 */ [] (void *obj) { return static_cast<T *>(obj)->~T(); } /* 2 */ // &dtor<T> }; struct myType { int a; }; void meow() { std::aligned_storage<sizeof(myType)>::type storage; auto *ptr = new ((char *)(&storage)) myType{5}; ptr->a = 10; erasedTypeVTable<myType>.dtor(ptr); } } int main() { meow(); } Compiled with -O3 -std=c++14 flags. g++ --version: g++ (Ubuntu 6-20160405-0ubuntu1) 6.0.0 20160405 (experimental) [trunk revision 234749] FWIW, clang 3.8 optimizes both versions.
The initializer of erasedTypeVTable is not statically available but involves runtime computation: ;; Function void __static_initialization_and_destruction_0(int, int) (null) ;; enabled by -tree-original if (__initialize_p == 1) { if (__priority == 65535) { <<cleanup_point <<< Unknown tree: expr_stmt erasedTypeVTable.dtor = {anonymous}::<lambda(void*)>::operator void (*)(void*) (&TARGET_EXPR <D.5974, {}>) >>>>>; <<< Unknown tree: expr_stmt <<< Unknown tree: void_cst >>> >>>; } } ;; Function (static initializers for t.C) (null) ;; enabled by -tree-original <<cleanup_point <<< Unknown tree: expr_stmt __static_initialization_and_destruction_0 (1, 65535) >>>>>; thats probably because the lambda is not evaluated in a constexpr context. If I make erasedTypeVTable a constexpr I get t.C: In instantiation of ‘constexpr const {anonymous}::ErasedTypeVTable {anonymous}::erasedTypeVTable<{anonymous}::myType>’: t.C:36:7: required from here t.C:20:41: error: call to non-constexpr function ‘{anonymous}::<lambda(void*)>::operator void (*)(void*)() const’ static constexpr ErasedTypeVTable erasedTypeVTable = { ^~~~~~~~~~~~~~~~ not sure how I would make the lambda a constexpr. There is no pass in GCC that would try to turn the runtime initialization into static init again (optimizing the runtime initializers and parsing them back to static initializers).
If that's the case then it should get automatically resolved once C++17 is implemented - C++17 introduces constexpr lambdas. But it would be great to have this optimization also in C++14 mode.
(In reply to Richard Biener from comment #1) > There is no pass in GCC that would try to turn the runtime initialization > into static init again (optimizing the runtime initializers and parsing > them back to static initializers). PR65197 contains links to a few related PRs (no particular patch/idea IIRC, just more examples).
With -std=c++17 (which is the default now), the code is optimized as expected. With -std=c++14, the dynamic initializer comes into play; there are a few other bugs dealing with that already too.
*** Bug 79189 has been marked as a duplicate of this bug. ***