Compiler Explorer: https://godbolt.org/z/Tx476nWaM The following c++ code crash gcc trunk with -std=c++20 flag. But clang and 13,14,15 with checking accept this code. Code: ```cpp #include <functional> class C { public: void func1(); void func2(); }; std::vector<std::vector<void (C::*)()>> farr = {{&C::func1, &C::func2}}; ``` Stack dump: ``` In file included from /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/bits/stl_iterator.h:78, from /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/bits/ranges_base.h:39, from /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/bits/ranges_util.h:34, from /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/tuple:46, from /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/functional:71, from <source>:1: in 'constexpr' expansion of '((std::vector<void (C::*)()>*)<anonymous>)->std::vector<void (C::*)()>::~vector()' <source>:7:71: 7 | std::vector<std::vector<void (C::*)()>> farr = {{&C::func1, &C::func2}}; | ^ in 'constexpr' expansion of 'std::_Destroy<void (C::**)(), void (C::*)()>(((std::vector<void (C::*)()>*)this)->std::vector<void (C::*)()>::std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >.std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_M_impl.std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_Vector_impl::std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_Vector_impl_data.std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_Vector_impl_data::_M_start, ((std::vector<void (C::*)()>*)this)->std::vector<void (C::*)()>::std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >.std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_M_impl.std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_Vector_impl::std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_Vector_impl_data.std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_Vector_impl_data::_M_finish, (* &((std::vector<void (C::*)()>*)this)->std::vector<void (C::*)()>::std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >.std::_Vector_base<void (C::*)(), std::allocator<void (C::*)()> >::_M_get_Tp_allocator()))' /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/bits/stl_vector.h:792:15: 792 | std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, | ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 793 | _M_get_Tp_allocator()); | ~~~~~~~~~~~~~~~~~~~~~~ in 'constexpr' expansion of 'std::_Destroy<void (C::**)()>(__first, __last)' /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/bits/alloc_traits.h:1045:20: 1045 | std::_Destroy(__first, __last); | ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~ in 'constexpr' expansion of 'std::destroy_at<void (C::*)()>(std::addressof<void (C::*)()>((* __first)))' /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/bits/stl_construct.h:230:19: 230 | std::destroy_at(std::addressof(*__first)); | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ /cefs/fb/fbb1812a35f407668b457d10_gcc-trunk-20260118/include/c++/16.0.1/bits/stl_construct.h:88:9: internal compiler error: tree check: expected constructor, have ptrmem_cst in cxx_eval_store_expression, at cp/constexpr.cc:8201 88 | __location->~_Tp(); | ^~~~~~~~~~ 0x2950a78 diagnostics::context::diagnostic_impl(rich_location*, diagnostics::metadata const*, diagnostics::option_id, char const*, __va_list_tag (*) [1], diagnostics::kind) ???:0 0x294583b internal_error(char const*, ...) ???:0 0xa234d1 tree_check_failed(tree_node const*, char const*, int, char const*, ...) ???:0 0xb8b38f cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c785 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c2d0 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8ebc4 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c554 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c785 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c2d0 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8b893 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8ebc4 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8ebc4 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8bfd0 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c554 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c785 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c2d0 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c554 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c785 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 0xb8c2d0 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*, value_cat, bool*, bool*, tree_node**) ???:0 Please submit a full bug report, with preprocessed source (by using -freport-bug). Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. Compiler returned: 1 ```
Reduced testcase: ``` struct b { void c(); }; typedef void (b::*a)(); struct bg { constexpr bg(a d) { auto e = new a(d); e->~a(); } } bn { &b::c }; ``` And yes this is valid C++20 (the original was valid C++17 even).
Started with r16-3022-gbc42128330c0ea70a015b74b655cb8c48b6a8c06
Created attachment 63428 [details] gcc16-pr123677.patch Untested fix. The CLOBBER constexpr store code was assuming that for AGGREGATE_TYPE_P if *valp is non-NULL, it must be a CONSTRUCTOR. But that is not the case as the testcase shows, it can be also PTRMEM_CST if TYPE_PTRMEMFUNC_P (type). Rather than adding a special case for that, this patch just verifies it is a CONSTRUCTOR and overwrites it otherwise.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:9abe0b4f76265a062f1646a0bff1f58b70ae5695 commit r16-6954-g9abe0b4f76265a062f1646a0bff1f58b70ae5695 Author: Jakub Jelinek <jakub@redhat.com> Date: Wed Jan 21 14:30:03 2026 +0100 c++: Fix ICE with constant evaluation of a = {CLOBBER} with ptrmemfn [PR123677] The following testcase ICEs when we evaluate a = {CLOBBER} stmt. The code assumes that if type is an aggregate type and *valp is non-NULL, then it must be a CONSTRUCTOR. That is usually the case, but there is one exception, *valp can be a PTRMEM_CST if TYPE_PTRMEMFUNC_P (type) and in that case CONSTRUCTOR_ELTS (*valp) obviously ICEs or misbehaves. Now, while I could do something like if (*valp && (!TYPE_PTRMEMFUNC_P (type) || TREE_CODE (*valp) != PTRMEM_CST)) just making sure TREE_CODE (*valp) == CONSTRUCTOR seems much easier and more readable. 2026-01-21 Jakub Jelinek <jakub@redhat.com> PR c++/123677 * constexpr.cc (cxx_eval_store_expression): Only clear CONSTRUCTOR_ELTS (*valp) if *valp is CONSTRUCTOR. * g++.dg/cpp2a/pr123677.C: New test.
Fixed.