RFC: Add Clang attribute to ensure that fields are initialized explicitly

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?