[c++20] Implement semantic restrictions for C++20 designated
initializers.

This has some interesting interactions with our existing extensions to
support C99 designated initializers as an extension in C++. Those are
resolved as follows:

 * We continue to permit the full breadth of C99 designated initializers
   in C++, with the exception that we disallow a partial overwrite of an
   initializer with a non-trivially-destructible type. (Full overwrite
   is OK, because we won't run the first initializer at all.)

 * The C99 extensions are disallowed in SFINAE contexts and during
   overload resolution, where they could change the meaning of valid
   programs.

 * C++20 disallows reordering of initializers. We only check for that for
   the simple cases that the C++20 rules permit (designators of the form
   '.field_name =' and continue to allow reordering in other cases).
   It would be nice to improve this behavior in future.

 * All C99 designated initializer extensions produce a warning by
   default in C++20 mode. People are going to learn the C++ rules based
   on what Clang diagnoses, so it's important we diagnose these properly
   by default.

 * In C++ <= 17, we apply the C++20 rules rather than the C99 rules, and
   so still diagnose C99 extensions as described above. We continue to
   accept designated C++20-compatible initializers in C++ <= 17 silently
   by default (but naturally still reject under -pedantic-errors).

This is not a complete implementation of P0329R4. In particular, that
paper introduces new non-C99-compatible syntax { .field { init } }, and
we do not support that yet.

This is based on a previous patch by Don Hinton, though I've made
substantial changes when addressing the above interactions.

Differential Revision: https://reviews.llvm.org/D59754

llvm-svn: 370544
diff --git a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
index 9c438d3..a974f3d 100644
--- a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
+++ b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 -std=c++2a %s -verify
+// RUN: %clang_cc1 -std=c++2a %s -verify=expected,pedantic,override,reorder -pedantic-errors
+// RUN: %clang_cc1 -std=c++2a %s -verify=expected,pedantic -Werror=c99-designator -Wno-reorder -Wno-initializer-overrides
+// RUN: %clang_cc1 -std=c++2a %s -verify=expected,reorder -Wno-c99-designator -Werror=reorder -Wno-initializer-overrides
+// RUN: %clang_cc1 -std=c++2a %s -verify=expected,override -Wno-c99-designator -Wno-reorder -Werror=initializer-overrides
+// RUN: %clang_cc1 -std=c++2a %s -verify -Wno-c99-designator -Wno-reorder -Wno-initializer-overrides
+
 
 namespace class_with_ctor {
   struct A { // expected-note 6{{candidate}}
@@ -21,3 +26,105 @@
   C c1 = {{}, {}}; // ok, call default ctor twice
   C c2 = {{1, 2}, {3, 4}}; // expected-error 2{{no matching constructor}}
 }
+
+namespace designator {
+struct A { int x, y; };
+struct B { A a; };
+
+A a1 = {
+  .y = 1, // reorder-note {{previous initialization for field 'y' is here}}
+  .x = 2 // reorder-error {{ISO C++ requires field designators to be specified in declaration order; field 'y' will be initialized after field 'x'}}
+};
+int arr[3] = {[1] = 5}; // pedantic-error {{array designators are a C99 extension}}
+B b = {.a.x = 0}; // pedantic-error {{nested designators are a C99 extension}}
+A a2 = {
+  .x = 1, // pedantic-error {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}}
+  2 // pedantic-note {{first non-designated initializer is here}}
+};
+A a3 = {
+  1, // pedantic-note {{first non-designated initializer is here}}
+  .y = 2 // pedantic-error {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}}
+};
+A a4 = {
+  .x = 1, // override-note {{previous}}
+  .x = 1 // override-error {{overrides prior initialization}}
+};
+A a5 = {
+  .y = 1, // override-note {{previous}}
+  .y = 1 // override-error {{overrides prior initialization}}
+};
+struct C { int :0, x, :0, y, :0; };
+C c = {
+  .x = 1, // override-note {{previous}}
+  .x = 1, // override-error {{overrides prior initialization}} override-note {{previous}}
+  .y = 1, // override-note {{previous}}
+  .y = 1, // override-error {{overrides prior initialization}}
+  .x = 1, // reorder-error {{declaration order}} override-error {{overrides prior initialization}} override-note {{previous}}
+  .x = 1, // override-error {{overrides prior initialization}}
+};
+}
+
+namespace base_class {
+  struct base {
+    int x;
+  };
+  struct derived : base {
+    int y;
+  };
+  derived d = {.x = 1, .y = 2}; // expected-error {{'x' does not refer to any field}}
+}
+
+namespace union_ {
+  union U { int a, b; };
+  U u = {
+    .a = 1, // override-note {{here}}
+    .b = 2, // override-error {{overrides prior}}
+  };
+}
+
+namespace overload_resolution {
+  struct A { int x, y; };
+  union B { int x, y; };
+
+  void f(A a);
+  void f(B b) = delete;
+  void g() { f({.x = 1, .y = 2}); } // ok, calls non-union overload
+
+  // As an extension of the union case, overload resolution won't pick any
+  // candidate where a field initializer would be overridden.
+  struct A2 { int x, other, y; };
+  int f(A2);
+  void g2() { int k = f({.x = 1, 2, .y = 3}); (void)k; } // pedantic-error {{mixture of designated and non-designated}} pedantic-note {{here}}
+
+  struct C { int x; };
+  void h(A a); // expected-note {{candidate}}
+  void h(C c); // expected-note {{candidate}}
+  void i() {
+    h({.x = 1, .y = 2});
+    h({.y = 1, .x = 2}); // reorder-error {{declaration order}} reorder-note {{previous}}
+    h({.x = 1}); // expected-error {{ambiguous}}
+  }
+
+  struct D { int y, x; };
+  void j(A a); // expected-note {{candidate}}
+  void j(D d); // expected-note {{candidate}}
+  void k() {
+    j({.x = 1, .y = 2}); // expected-error {{ambiguous}}
+  }
+}
+
+namespace deduction {
+  struct A { int x, y; };
+  union B { int x, y; };
+
+  template<typename T, typename U> void f(decltype(T{.x = 1, .y = 2}) = {});
+  template<typename T, typename U> void f(decltype(U{.x = 1, .y = 2}) = {}) = delete;
+  void g() { f<A, B>(); } // ok, calls non-union overload
+
+  struct C { int y, x; };
+  template<typename T, typename U> void h(decltype(T{.y = 1, .x = 2}) = {}) = delete;
+  template<typename T, typename U> void h(decltype(U{.y = 1, .x = 2}) = {});
+  void i() {
+    h<A, C>(); // ok, selects C overload by SFINAE
+  }
+}