Closed seanbaxter closed 4 years ago
Ack, I think this is a clang bug.
This code does lifetime extension of the foo_t values in the initializer_list backing stores:
struct foo_t {
int x;
foo_t(int x = 10) : x(x) { printf("foo_t(%d)\n", x); }
~foo_t() { printf("~foo_t(%d)\n", x); }
};
int main() {
bar_t array[] {
{ { 1, 2, 3 } },
{ { 4, 4, 5 } }
};
printf("bar_t complete\n");
}
This code treats the foo_t values as temporaries that are destroyed at the end of the first statement:
int main() {
bar_t array[] {
bar_t{ { 1, 2, 3 } },
bar_t{ { 4, 4, 5 } }
};
printf("bar_t complete\n");
}
Either the behavior is undefined in the standard, or it is defined (yet that language remains unparsable by me) and clang has a bug where the class-name is used, or it is defined and gcc has a bug where the class name is used. All in all, I have little idea what's going on.
Just to add to the confusion, MSVC 2019 follows gcc here. "bar_t complete" printf is sequenced between the construction and destruction of foo_t objects. Although, the foo_t objects are correctly destructed in the reverse order of construction.
bslstl_vector_test2.t.cpp:3732 with TYPE=bsltf::AllocTestType apparently relies on lifetime extension of initializer_list objects through both array and aggregate initializers to match the storage duration of the array declaration.
I put together a demo of the issue here: https://godbolt.org/z/HX3DQw
Clang performs the printf after the foo_t objects have been destroyed. icc performs the printf after the foo_t objects have been destroyed, and it destroys those objects in a different order. gcc performs the printf between the foo_t ctors and dtors (which this BDE test requires to pass).
The Standard is vague here. Lifetime extension is probably more correct, but it also sets up the surprise where if the initializer calls a ctor rather than an aggregate initializer on the array's type, the braced initializer expressions would get immediately materialized and discarded at the end of the full expression.
Am I misreading the BDE test here? It seems like it should fail on clang.