why "missing double brace warning" for BaseClass Aggregate initialisation in Clang 12 but not Clang 13 or GCC 11?

Viewed 91

This code compiles without warning in GCC 11 and Clang 13 (in C++20 mode)

struct A {
    int x, y;

};

struct B : A { };

int main () {
    A a{1,2};
    B b{3,4};  // Clang 12 wants B b{{3,4}}

    return a.x * b.x + a.y * b.y;

}

but in Clang 12 We get

<source>:10:9: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    B b{3,4};

https://godbolt.org/z/Kdnon9575

Might be related to:

Why does Clang 12 refuse to initialize aggregates in the C++20 way?

and these papers

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0960r3.html

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1975r0.html

Are single braces officially supported (without warnings) under C++20 for initialising these simple POD Derived classes? If so, where does the standard say that, so we can rely on it?

In C++17 the double braces are required, to avoid warnings, yes?

And in C++14 single braces are a hard error because a derived struct is not an aggregate, yes?

1 Answers

C++17 as well as C++20, https://timsong-cpp.github.io/cppwp/n4659/dcl.init.aggr#12 and https://timsong-cpp.github.io/cppwp/n4868/dcl.init.aggr#15, respectively, allows brace elision for the initialization of aggregates:

Braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.

Class B in the OP's example is an aggregate in both C++17 and C++20 (as per C++17's P0017R1 and its updates primarily to [dcl.init.aggr]/1), where the requirements for what qualifies as an aggregate has been made more lenient with regard to the base class requirement.

An aggregate is an array or a class ([class]) with

  • [...]
  • (C++14) no base classes
  • (C++17 and C++20) no virtual, private, or protected base classes

Now, the Clang diagnostic was only a warning to begin with, and as of Clang 13 it seems to have (imo correctly) have been removed for braced-elided initalization of aggregates that have base classes. It's possible the warning was a remnant corner case from C++14 where B was not an aggregate, but where the program would be ill-formed due to an invalid form of initialization.

Related