https://gcc.gnu.org/g:bee1910b891f897fcd1789d1dbd3937621354943
commit r15-7209-gbee1910b891f897fcd1789d1dbd3937621354943 Author: Simon Martin <si...@nasilyan.com> Date: Sat Jan 25 18:09:23 2025 +0100 c++: Reinstate check for uninitialized bases with c++ <= 17 [PR118239] We currently accept this code with c++ <= 17 even though it's invalid since the base is not initialized (we properly reject it with c++ >= 20) === cut here === struct NoMut1 { int a, b; }; struct NoMut3 : NoMut1 { constexpr NoMut3(int a, int b) {} }; void mutable_subobjects() { constexpr NoMut3 nm3(1, 2); } === cut here === This is a fallout of r0-118700-gc2b3ec18a494e3, that ignores all fields with DECL_ARTIFICIAL in cx_check_missing_mem_inits, including those that represent base classes, and need to be checked. This patch makes sure that we only skip fields that have DECL_ARTIFICIAL if they don't have DECL_FIELD_IS_BASE. PR c++/118239 gcc/cp/ChangeLog: * constexpr.cc (cx_check_missing_mem_inits): Don't skip fields with DECL_FIELD_IS_BASE. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-base8.C: New test. Diff: --- gcc/cp/constexpr.cc | 8 ++++---- gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 41ff78bbf2b9..94a468056f90 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -839,9 +839,8 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain) if (i < nelts) { index = CONSTRUCTOR_ELT (body, i)->index; - /* Skip base and vtable inits. */ - if (TREE_CODE (index) != FIELD_DECL - || DECL_ARTIFICIAL (index)) + /* Skip vptr adjustment represented with a COMPONENT_REF. */ + if (TREE_CODE (index) != FIELD_DECL) continue; } @@ -852,7 +851,8 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain) continue; if (DECL_UNNAMED_BIT_FIELD (field)) continue; - if (DECL_ARTIFICIAL (field)) + /* Artificial fields can be ignored unless they're bases. */ + if (DECL_ARTIFICIAL (field) && !DECL_FIELD_IS_BASE (field)) continue; if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C new file mode 100644 index 000000000000..ecc28693315e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C @@ -0,0 +1,24 @@ +// PR c++/118239 +// { dg-do "compile" { target c++11 } } + +struct NoMut1 { + int a, b; +}; + +// Reported case. +struct NoMut2 : NoMut1 { + constexpr NoMut2(int a, int b) /*: NoMut1()*/ + {} // { dg-error "must be initialized" "" { target c++17_down } } +}; + +// Variant with explicit initialization of some member. +struct NoMut3 : NoMut1 { + constexpr NoMut3(int a, int b) : c(0) /*, NoMut1()*/ + {} // { dg-error "must be initialized" "" { target c++17_down } } + int c; +}; + +void mutable_subobjects() { + constexpr NoMut2 nm2(1, 2); // { dg-error "constant expression" } + constexpr NoMut3 nm3(1, 2); // { dg-error "constant expression" } +}