The following testcase gets miscompiled on GCC 9 and on GCC 10 with -DUSE_CONSTEXPR due to (I believe) the constexpr virtual evaluation incorrectly resolving the dynamic type of ((A *)this) to C rather than B inside B's constructor. $ cat virtual-2.cc #if defined USE_CONSTEXPR # define CONSTEXPR constexpr #else # define CONSTEXPR #endif struct A { virtual CONSTEXPR char f () const { return 'A'; } }; struct B : A { char x; constexpr B () : x (0) { x = ((A *)this)->f(); } virtual CONSTEXPR char f () const { return 'B'; } }; struct C : B { virtual CONSTEXPR char f () const { return 'C'; } }; int main () { CONSTEXPR C c; if (c.x != 'B') __builtin_abort (); } $ g++ -std=c++2a virtual-2.cc $ ./a.out $ g++ -std=c++2a virtual-2.cc -DUSE_CONSTEXPR $ ./a.out zsh: abort ./a.out
Confirmed.
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:7ece3bd8088983289731450826c238eb2bdd2db5 commit r11-955-g7ece3bd8088983289731450826c238eb2bdd2db5 Author: Jason Merrill <jason@redhat.com> Date: Wed Jun 3 23:50:50 2020 -0400 c++: Fix complex constexpr virtual cases [PR93310]. The code in constexpr for looking up the actual type of the object and then getting the virtual function from there broke for both of these tests: for 16, it assumed incorrectly that the DECL_VINDEX would apply to the most derived type's vtable; for 17, it failed to consider that during construction the base subobject is treated as being of the base type. Fixed by just doing constant evaluation of the expression that looks up the function in the vtable. This means that a virtual call will involve loading the vptr, so we will reject some calls through non-constexpr variables that we previously accepted, but this seems appropriate to me. None of our testcases were affected. gcc/cp/ChangeLog: PR c++/93310 * constexpr.c (cxx_eval_constant_expression) [OBJ_TYPE_REF]: Evaluate OBJ_TYPE_REF_EXPR. gcc/testsuite/ChangeLog: PR c++/93310 * g++.dg/cpp2a/constexpr-virtual16.C: New test. * g++.dg/cpp2a/constexpr-virtual17.C: New test. * g++.dg/cpp2a/constexpr-new12.C: Adjust diagnostic.
The releases/gcc-10 branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:6b45b400c51be06f2d0e37a7b461cbd4ce9fe37d commit r10-8243-g6b45b400c51be06f2d0e37a7b461cbd4ce9fe37d Author: Jason Merrill <jason@redhat.com> Date: Wed Jun 3 23:50:50 2020 -0400 c++: Fix complex constexpr virtual cases [PR93310]. The code in constexpr for looking up the actual type of the object and then getting the virtual function from there broke for both of these tests: for 16, it assumed incorrectly that the DECL_VINDEX would apply to the most derived type's vtable; for 17, it failed to consider that during construction the base subobject is treated as being of the base type. Fixed by just doing constant evaluation of the expression that looks up the function in the vtable. This means that a virtual call will involve loading the vptr, so we will reject some calls through non-constexpr variables that we previously accepted, but this seems appropriate to me. None of our testcases were affected. gcc/cp/ChangeLog: PR c++/93310 * constexpr.c (cxx_eval_constant_expression) [OBJ_TYPE_REF]: Evaluate OBJ_TYPE_REF_EXPR. gcc/testsuite/ChangeLog: PR c++/93310 * g++.dg/cpp2a/constexpr-virtual16.C: New test. * g++.dg/cpp2a/constexpr-virtual17.C: New test. * g++.dg/cpp2a/constexpr-new12.C: Adjust diagnostic.
Fixed in 10.2/11. I doubt anyone is still using GCC 9 for C++20 code.