On 12/3/19 12:49 PM, Marek Polacek wrote:
On Tue, Dec 03, 2019 at 02:07:02AM -0500, Jason Merrill wrote:
On 12/2/19 5:09 PM, Marek Polacek wrote:
On Mon, Dec 02, 2019 at 12:09:17PM -0500, Jason Merrill wrote:
On 12/1/19 8:09 PM, Marek Polacek wrote:
+            || (skip_empty
+                && is_really_empty_class (TREE_TYPE (field),

This should probably check DECL_SIZE (field) == size_zero_node instead,
since that will properly distinguish between overlapping and non-overlapping
data members of empty class type.  And please test how this works with data
members of empty class type both with and without [[no_unique_address]].

I don't think that's possible -- empty classes in C++ have sizeof(char), unless
their only member is char[0], then their DECL_SIZE is 0.

I think you're talking about the TYPE_SIZE of the class, and I'm talking
about the DECL_SIZE of the FIELD_DECL.

I'm really looking at the DECL_SIZE:

Breakpoint 5, next_initializable_field (field=<field_decl 0x7fffea90dc78 s>, 
skip_empty=true)
     at /home/mpolacek/src/gcc/gcc/cp/decl.c:5928
5928                     && is_really_empty_class (TREE_TYPE (field),
(gdb) p field
$1 = <field_decl 0x7fffea90dc78 s>
(gdb) p DECL_SIZE($1)
$2 = <integer_cst 0x7fffea8e0f60>
(gdb) pge
8

This is constexpr-init8.C:

struct S {
   constexpr S(int) {}
};

struct W {
   constexpr W(int) : s(8), p() {}

   S s;
   int *p;
};

constexpr auto a = W(42);

I think that's because layout_class_type has:

  6491       else if (might_overlap && is_empty_class (type))
  6492         layout_empty_base_or_field (rli, field, empty_base_offsets);
  6493       else
  6494         layout_nonempty_base_or_field (rli, field, NULL_TREE,
  6495                                        empty_base_offsets);

and here might_overlap is false because 's' doesn't have [[no_unique_address]].
So we emit the FIELD_DECL with size 8.

Yes, that's correct. So I don't think we want to skip 's' in next_initializable_field; it should have a normal initializer.

Its type CLASSTYPE_SIZE is 0 though.
I don't know but I'd rather not mess with this...

I've added two testcases: constexpr-init13.C and constexpr-init14.C.  Is there
another scenario regarding [[no_unique_address]] that you want me to test?

I think the classes with empty base fields need to have another initialized
field after them to have a chance of tripping

   if (idx != field)

And sure enough, that's exactly the case for

struct E {
   constexpr E() = default;
   constexpr E(int) {}
};

struct S {
   E e;
   int i;
   constexpr S() : e{} , i(11) { }
};

constexpr S s;


And that's even without [[no_unique_address]].

So it's a valid concern.  It's unclear to me how this should be resolved.

What does the initializer for s look like in this case?

Jason

Reply via email to