First off, thank you for the RFC!
I’d like to make sure I understand the proposal after the (good!) discussion we’ve had around its semantics. Given:
struct S {
[[clang::<name>]] int x;
int y;
int z = 12;
[[clang::<name>]] int q = 100;
};
void foo(S s);
do we expect the following behaviors:
foo(S{1, 2, 3, 4}); // No diagnostics
foo(S{.x = 100, .q = 100}); // No diagnostics
foo(S{.x = 100 }); // Diagnostic about q not being explicitly specified?
S s{.x = 100, .q = 100}; // No diagnostics
S t{.q = 100}; // Diagnostics about x not being explicitly specified
S *ptr = new S; // Diagnostics about x and q not being explicitly specified
S *ptr2 = new S{.x = 100, .q = 100}; // No diagnostics
(Basically, when the attribute is on a field, that field must have an explicitly specified value when constructing the object; implicitly specified values are insufficient such as an in-class initializer?)
If so, I think we may want to carve out some guard rails for misuse, such as:
struct S {
int count;
[[clang::<name>]] struct { // Should it be possible to write on fields with sizeless/effectively empty types?
} inner;
[[clang::<name>]] int : 0; // Not really sensible to try to initialize a zero-width bit-field
[[clang::<name>]] int fam[]; // Definitely *do not want* an explicit initializer here!
};
struct T {
[[clang::<name>]] int x;
T(int val = 12) : x(val) {}
};
T t; // I have no idea what this should do; are default arguments sufficiently explicit?
(Once we open the door to non-aggregates, I think there’s quite a few design questions because constructors can do some pretty complicated stuff, such as delegating constructors, overloaded constructors, etc. I kind of wonder if we should start with aggregates and then expand later.)
And I suppose there’s a question of what this kind of code should do:
struct S {
[[clang::<name>]] int x;
};
void foo(S s = {});
template <S s>
void quux();
void bar() {
foo(); // Gets diagnostics, hopefully?
quux<{}>(); // Gets diagnostics, maybe?
size_t heh = sizeof(S{}); // Should we diagnose in unevaluated contexts?
}
In terms of the name of the attribute, I tend to like requires_explicit_init
over the other options. Do we want a warning when written on an in-class initializer given that such a scenario is pretty confusing?