@@ -3081,7 +3081,13 @@ reduced_constant_expression_p (tree t)
element. */
if (!reduced_constant_expression_p (e.value))
return false;
- /* Empty class field may or may not have an initializer. */
+ /* We want to remove initializers for empty fields in a struct to
+ avoid confusing output_constructor. */
+ if (is_empty_field (e.index)
+ && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
+ return false;
+ /* Check for non-empty fields between initialized fields when
+ CONSTRUCTOR_NO_CLEARING. */
for (; field && e.index != field;
field = next_subobject_field (DECL_CHAIN (field)))
if (!is_really_empty_class (TREE_TYPE (field),
new file mode 100644
@@ -0,0 +1,26 @@
+// PR c++/106369
+// { dg-do compile { target c++17 } }
+
+struct A {
+ int a[256];
+ constexpr int &operator[] (int n) noexcept { return a[n]; }
+ constexpr const int &operator[] (int n) const noexcept { return a[n]; }
+};
+struct B {};
+template <typename T>
+struct C {
+ constexpr T &foo (const char x) noexcept { c = T::d[x]; return static_cast<T &>(*this); }
+ int c;
+};
+struct D : public C<D>, public B
+{
+ D () noexcept = default;
+ static constexpr char e[9] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' };
+ static constexpr A d = [] () constexpr {
+ A f {};
+ for (int i = 0; i < 9; ++i)
+ f[e[i]] = 1;
+ return f;
+ } ();
+};
+constexpr auto g = D{}.foo ('E');