On 1/3/25 3:00 PM, Simon Martin wrote:
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.
Successfully tested on x86_64-pc-linux-gnu.
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.
---
gcc/cp/constexpr.cc | 8 +++----
gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C | 24 ++++++++++++++++++++
2 files changed, 28 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index c8be5a525ee..e11444438d3 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 vtable inits. */
+ if (TREE_CODE (index) != FIELD_DECL)
continue;
The code after your change no longer skips vtable inits; this should
make the same DECL_FIELD_IS_BASE adjustment as below.
}
@@ -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 00000000000..ecc28693315
--- /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" }
+}