ychen updated this revision to Diff 521978.
ychen added a comment.

- Fix bitfield on Windows


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139837/new/

https://reviews.llvm.org/D139837

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/DeclBase.h
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/Sema/Sema.h
  clang/include/clang/Sema/TemplateDeduction.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Decl.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/lib/Serialization/ASTReaderDecl.cpp
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1246,7 +1246,7 @@
     <tr>
       <td rowspan=2>Class template argument deduction for aggregates</td>
       <td><a href="https://wg21.link/p1816r0";>P1816R0</a></td>
-      <td rowspan=2 class="none" align="center">No</td>
+      <td rowspan=2 class="unreleased" align="center">Clang 17</td>
     </tr>
       <tr> <!-- from Prague -->
         <td><a href="https://wg21.link/p2082r1";>P2082R1</a></td>
Index: clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
@@ -0,0 +1,298 @@
+// RUN: %clang_cc1 -std=c++20 -verify -ast-dump -ast-dump-decl-types -ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace
+
+namespace Basic {
+  template<class T> struct A {
+    T x;
+    T y;
+  };
+
+  A a1{3.0, 4.0};
+  A a2{.x = 3.0, .y = 4.0};
+
+  // CHECK-LABEL: Dumping Basic::<deduction guide for A>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for A>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 T
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for A> 'auto (T, T) -> A<T>'
+  // CHECK: | |-ParmVarDecl {{.*}} 'T'
+  // CHECK: | `-ParmVarDecl {{.*}} 'T'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for A> 'auto (double, double) -> Basic::A<double>'
+  // CHECK:   |-TemplateArgument type 'double'
+  // CHECK:   | `-BuiltinType {{.*}} 'double'
+  // CHECK:   |-ParmVarDecl {{.*}} 'double':'double'
+  // CHECK:   `-ParmVarDecl {{.*}} 'double':'double'
+  // CHECK: FunctionProtoType {{.*}} 'auto (T, T) -> A<T>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'A<T>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'A'
+  // CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK: | `-TemplateTypeParm {{.*}} 'T'
+  // CHECK: `-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK:   `-TemplateTypeParm {{.*}} 'T'
+
+  template <typename T> struct S {
+    T x;
+    T y;
+  };
+
+  template <typename T> struct C { // expected-note 5 {{candidate}}
+    S<T> s;
+    T t;
+  };
+
+  template <typename T> struct D { // expected-note 3 {{candidate}}
+    S<int> s;
+    T t;
+  };
+
+  C c1 = {1, 2}; // expected-error {{no viable}}
+  C c2 = {1, 2, 3}; // expected-error {{no viable}}
+  C c3 = {{1u, 2u}, 3};
+
+  D d1 = {1, 2}; // expected-error {{no viable}}
+  D d2 = {1, 2, 3};
+
+  // CHECK-LABEL: Dumping Basic::<deduction guide for C>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for C>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for C> 'auto (S<T>, T) -> C<T>'
+  // CHECK: | |-ParmVarDecl {{.*}} 'S<T>':'S<T>'
+  // CHECK: | `-ParmVarDecl {{.*}} 'T'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for C> 'auto (S<int>, int) -> Basic::C<int>'
+  // CHECK:   |-TemplateArgument type 'int'
+  // CHECK:   | `-BuiltinType {{.*}} 'int'
+  // CHECK:   |-ParmVarDecl {{.*}} 'S<int>':'Basic::S<int>'
+  // CHECK:   `-ParmVarDecl {{.*}} 'int':'int'
+  // CHECK: FunctionProtoType {{.*}} 'auto (S<T>, T) -> C<T>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'C<T>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'C'
+  // CHECK: |-ElaboratedType {{.*}} 'S<T>' sugar dependent
+  // CHECK: | `-TemplateSpecializationType {{.*}} 'S<T>' dependent S
+  // CHECK: |   `-TemplateArgument type 'T'
+  // CHECK: |     `-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK: |       `-TemplateTypeParm {{.*}} 'T'
+  // CHECK: `-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK:   `-TemplateTypeParm {{.*}} 'T'
+
+  // CHECK-LABEL: Dumping Basic::<deduction guide for D>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for D>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for D> 'auto (int, int) -> D<T>'
+  // CHECK:   |-ParmVarDecl {{.*}} 'int':'int'
+  // CHECK:   `-ParmVarDecl {{.*}} 'int':'int'
+  // CHECK: FunctionProtoType {{.*}} 'auto (int, int) -> D<T>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'D<T>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'D'
+  // CHECK: |-SubstTemplateTypeParmType {{.*}} 'int' sugar typename depth 0 index 0 T
+  // CHECK: | |-ClassTemplateSpecialization {{.*}} 'S'
+  // CHECK: | `-BuiltinType {{.*}} 'int'
+  // CHECK: `-SubstTemplateTypeParmType {{.*}} 'int' sugar typename depth 0 index 0 T
+  // CHECK:   |-ClassTemplateSpecialization {{.*}} 'S'
+  // CHECK:   `-BuiltinType {{.*}} 'int'
+
+  template <typename T> struct E {
+    T t;
+    decltype(t) t2;
+  };
+
+  E e1 = {1, 2};
+
+  // CHECK-LABEL: Dumping Basic::<deduction guide for E>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for E>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for E> 'auto (T, decltype(t)) -> E<T>'
+  // CHECK: | |-ParmVarDecl {{.*}} 'T'
+  // CHECK: | `-ParmVarDecl {{.*}} 'decltype(t)'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for E> 'auto (int, decltype(t)) -> Basic::E<int>'
+  // CHECK:   |-TemplateArgument type 'int'
+  // CHECK:   | `-BuiltinType {{.*}} 'int'
+  // CHECK:   |-ParmVarDecl {{.*}} 'int':'int'
+  // CHECK:   `-ParmVarDecl {{.*}} 'decltype(t)':'int'
+  // CHECK: FunctionProtoType {{.*}} 'auto (T, decltype(t)) -> E<T>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'E<T>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'E'
+  // CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK: | `-TemplateTypeParm {{.*}} 'T'
+  // CHECK: `-DecltypeType {{.*}} 'decltype(t)' dependent
+  // CHECK:   `-DeclRefExpr {{.*}} 'T' lvalue Field {{.*}} 't' 'T' non_odr_use_unevaluated
+}
+
+namespace Array {
+  typedef __SIZE_TYPE__ size_t;
+  template <typename T, size_t N> struct A {
+    T array[N];
+  };
+
+  A a1 = {{1, 2, 3}};
+  A a2 = {"meow"};
+  A a3 = {("meow")};
+
+  // CHECK-LABEL: Dumping Array::<deduction guide for A>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for A>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
+  // CHECK: |-NonTypeTemplateParmDecl {{.*}} 'size_t':'unsigned long' depth 0 index 1 N
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for A> 'auto (T (&&)[N]) -> A<T, N>'
+  // CHECK: | `-ParmVarDecl {{.*}} 'T (&&)[N]'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for A> 'auto (int (&&)[3]) -> Array::A<int, 3>'
+  // CHECK:   |-TemplateArgument type 'int'
+  // CHECK:   | `-BuiltinType {{.*}} 'int'
+  // CHECK:   |-TemplateArgument integral 3
+  // CHECK:   `-ParmVarDecl {{.*}} 'int (&&)[3]'
+  // CHECK: FunctionProtoType {{.*}} 'auto (T (&&)[N]) -> A<T, N>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'A<T, N>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'A'
+  // CHECK: `-RValueReferenceType {{.*}} 'T (&&)[N]' dependent
+  // CHECK:   `-DependentSizedArrayType {{.*}} 'T[N]' dependent
+  // CHECK:     |-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK:     | `-TemplateTypeParm {{.*}} 'T'
+  // CHECK:     `-DeclRefExpr {{.*}} 'size_t':'unsigned long' NonTypeTemplateParm {{.*}} 'N' 'size_t':'unsigned long'
+
+  // CHECK: Dumping Array::<deduction guide for A>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for A>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
+  // CHECK: |-NonTypeTemplateParmDecl {{.*}} 'size_t':'unsigned long' depth 0 index 1 N
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for A> 'auto (T (&)[N]) -> A<T, N>'
+  // CHECK: | `-ParmVarDecl {{.*}} 'T (&)[N]'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for A> 'auto (const char (&)[5]) -> Array::A<const char, 5>'
+  // CHECK:   |-TemplateArgument type 'const char'
+  // CHECK:   | `-QualType {{.*}} 'const char' const
+  // CHECK:   |   `-BuiltinType {{.*}} 'char'
+  // CHECK:   |-TemplateArgument integral 5
+  // CHECK:   `-ParmVarDecl {{.*}} 'const char (&)[5]'
+  // CHECK: FunctionProtoType {{.*}} 'auto (T (&)[N]) -> A<T, N>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'A<T, N>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'A'
+  // CHECK: `-LValueReferenceType {{.*}} 'T (&)[N]' dependent
+  // CHECK:   `-DependentSizedArrayType {{.*}} 'T[N]' dependent
+  // CHECK:     |-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK:     | `-TemplateTypeParm {{.*}} 'T'
+  // CHECK:     `-DeclRefExpr {{.*}} 'size_t':'unsigned long' NonTypeTemplateParm {{.*}} 'N' 'size_t':'unsigned long'
+}
+
+namespace BraceElision {
+  template <typename T> struct A {
+    T array[2];
+  };
+
+  A a = {0, 1};
+
+  // CHECK-LABEL: Dumping BraceElision::<deduction guide for A>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for A>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for A> 'auto (T, T) -> A<T>'
+  // CHECK: | |-ParmVarDecl {{.*}} 'T'
+  // CHECK: | `-ParmVarDecl {{.*}} 'T'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for A> 'auto (int, int) -> BraceElision::A<int>'
+  // CHECK:   |-TemplateArgument type 'int'
+  // CHECK:   | `-BuiltinType {{.*}} 'int'
+  // CHECK:   |-ParmVarDecl {{.*}} 'int':'int'
+  // CHECK:   `-ParmVarDecl {{.*}} 'int':'int'
+  // CHECK: FunctionProtoType {{.*}} 'auto (T, T) -> A<T>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'A<T>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'A'
+  // CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK: | `-TemplateTypeParm {{.*}} 'T'
+  // CHECK: `-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK:   `-TemplateTypeParm {{.*}} 'T'
+}
+
+namespace TrailingPack {
+  template<typename... T> struct A : T... {
+  };
+
+  A a = {
+    []{ return 1; },
+    []{ return 2; }
+  };
+
+  // CHECK-LABEL: Dumping TrailingPack::<deduction guide for A>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for A>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 ... T
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for A> 'auto (T...) -> A<T...>'
+  // CHECK: | `-ParmVarDecl {{.*}} 'T...' pack
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for A> 
+  // CHECK-SAME: 'auto (TrailingPack::(lambda at {{.*}}), TrailingPack::(lambda at {{.*}})) -> 
+  // CHECK-SAME:     TrailingPack::A<TrailingPack::(lambda at {{.*}}), TrailingPack::(lambda at {{.*}})>'
+  // CHECK: |-TemplateArgument pack
+  // CHECK: | |-TemplateArgument type 'TrailingPack::(lambda at {{.*}})'
+  // CHECK: | | `-RecordType {{.*}} 'TrailingPack::(lambda at {{.*}})'
+  // CHECK: | |   `-CXXRecord {{.*}} ''
+  // CHECK: | `-TemplateArgument type 'TrailingPack::(lambda at {{.*}})'
+  // CHECK: |   `-RecordType {{.*}} 'TrailingPack::(lambda at {{.*}})'
+  // CHECK: |     `-CXXRecord {{.*}} ''
+  // CHECK: |-ParmVarDecl {{.*}} 'TrailingPack::(lambda at {{.*}})':'TrailingPack::(lambda at {{.*}})'
+  // CHECK: `-ParmVarDecl {{.*}} 'TrailingPack::(lambda at {{.*}})':'TrailingPack::(lambda at {{.*}})'
+  // CHECK: FunctionProtoType {{.*}} 'auto (T...) -> A<T...>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'A<T...>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'A'
+  // CHECK: `-PackExpansionType {{.*}} 'T...' dependent
+  // CHECK:   `-TemplateTypeParmType {{.*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
+  // CHECK:     `-TemplateTypeParm {{.*}} 'T'
+}
+
+namespace NonTrailingPack {
+  template<typename... T> struct A : T... { // expected-note 2 {{candidate}}
+    int a;
+  };
+
+  A a = { // expected-error {{no viable}}
+    []{ return 1; },
+    []{ return 2; }
+  };
+}
+
+namespace DeduceArity {
+  template <typename... T> struct Types {};
+  template <typename... T> struct F : Types<T...>, T... {}; // expected-note 6 {{candidate}}
+
+  struct X {};
+  struct Y {};
+  struct Z {};
+  struct W { operator Y(); };
+
+  F f1 = {Types<X, Y, Z>{}, {}, {}};
+  F f2 = {Types<X, Y, Z>{}, X{}, Y{}};
+  F f3 = {Types<X, Y, Z>{}, X{}, W{}}; // expected-error {{no viable}}
+  F f4 = {Types<X>{}, {}, {}}; // expected-error {{no viable}}
+
+  // CHECK-LABEL: Dumping DeduceArity::<deduction guide for F>:
+  // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for F>
+  // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 ... T
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (Types<T...>, T...) -> F<T...>'
+  // CHECK: | |-ParmVarDecl {{.*}} 'Types<T...>':'Types<T...>'
+  // CHECK: | `-ParmVarDecl {{.*}} 'T...' pack
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for F> 
+  // CHECK-SAME: 'auto (Types<X, Y, Z>, DeduceArity::X, DeduceArity::Y, DeduceArity::Z) -> 
+  // CHECK-SAME:     DeduceArity::F<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
+  // CHECK: | |-TemplateArgument pack
+  // CHECK: | | |-TemplateArgument type 'DeduceArity::X'
+  // CHECK: | | | `-RecordType {{.*}} 'DeduceArity::X'
+  // CHECK: | | |   `-CXXRecord {{.*}} 'X'
+  // CHECK: | | |-TemplateArgument type 'DeduceArity::Y'
+  // CHECK: | | | `-RecordType {{.*}} 'DeduceArity::Y'
+  // CHECK: | | |   `-CXXRecord {{.*}} 'Y'
+  // CHECK: | | `-TemplateArgument type 'DeduceArity::Z'
+  // CHECK: | |   `-RecordType {{.*}} 'DeduceArity::Z'
+  // CHECK: | |     `-CXXRecord {{.*}} 'Z'
+  // CHECK: | |-ParmVarDecl {{.*}} 'Types<X, Y, Z>':'DeduceArity::Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
+  // CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::X':'DeduceArity::X'
+  // CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::Y':'DeduceArity::Y'
+  // CHECK: | `-ParmVarDecl {{.*}} 'DeduceArity::Z':'DeduceArity::Z'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (Types<X>, DeduceArity::X) -> DeduceArity::F<DeduceArity::X>'
+  // CHECK:   |-TemplateArgument pack
+  // CHECK:   | `-TemplateArgument type 'DeduceArity::X'
+  // CHECK:   |   `-RecordType {{.*}} 'DeduceArity::X'
+  // CHECK:   |     `-CXXRecord {{.*}} 'X'
+  // CHECK:   |-ParmVarDecl {{.*}} 'Types<X>':'DeduceArity::Types<DeduceArity::X>'
+  // CHECK:   `-ParmVarDecl {{.*}} 'DeduceArity::X':'DeduceArity::X'
+  // CHECK: FunctionProtoType {{.*}} 'auto (Types<T...>, T...) -> F<T...>' dependent trailing_return cdecl
+  // CHECK: |-InjectedClassNameType {{.*}} 'F<T...>' dependent
+  // CHECK: | `-CXXRecord {{.*}} 'F'
+  // CHECK: |-ElaboratedType {{.*}} 'Types<T...>' sugar dependent
+  // CHECK: | `-TemplateSpecializationType {{.*}} 'Types<T...>' dependent Types
+  // CHECK: |   `-TemplateArgument type 'T...'
+  // CHECK: |     `-PackExpansionType {{.*}} 'T...' dependent
+  // CHECK: |       `-TemplateTypeParmType {{.*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
+  // CHECK: |         `-TemplateTypeParm {{.*}} 'T'
+  // CHECK: `-PackExpansionType {{.*}} 'T...' dependent
+  // CHECK:   `-TemplateTypeParmType {{.*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
+  // CHECK:     `-TemplateTypeParm {{.*}} 'T'
+}
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -580,7 +580,7 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 29,
+  static_assert(DeclContext::NumFunctionDeclBits == 30,
                 "You need to update the serializer after you change the "
                 "FunctionDeclBits");
 
@@ -730,7 +730,7 @@
   addExplicitSpecifier(D->getExplicitSpecifier(), Record);
   Record.AddDeclRef(D->Ctor);
   VisitFunctionDecl(D);
-  Record.push_back(D->isCopyDeductionCandidate());
+  Record.push_back(static_cast<uint64_t>(D->getDeductionCandidateKind()));
   Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
 }
 
@@ -1495,7 +1495,7 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 22,
+  static_assert(DeclContext::NumCXXConstructorDeclBits == 21,
                 "You need to update the serializer after you change the "
                 "CXXConstructorDeclBits");
 
Index: clang/lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderDecl.cpp
+++ clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2212,7 +2212,8 @@
   D->setExplicitSpecifier(Record.readExplicitSpec());
   D->Ctor = readDeclAs<CXXConstructorDecl>();
   VisitFunctionDecl(D);
-  D->setIsCopyDeductionCandidate(Record.readInt());
+  D->setDeductionCandidateKind(
+      static_cast<DeductionCandidateKind>(Record.readInt()));
 }
 
 void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2127,8 +2127,8 @@
         SemaRef.Context, DC, D->getInnerLocStart(),
         InstantiatedExplicitSpecifier, NameInfo, T, TInfo,
         D->getSourceRange().getEnd());
-    if (DGuide->isCopyDeductionCandidate())
-      cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
+    cast<CXXDeductionGuideDecl>(Function)->setDeductionCandidateKind(
+        DGuide->getDeductionCandidateKind());
     Function->setAccess(D->getAccess());
   } else {
     Function = FunctionDecl::Create(
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -212,7 +212,8 @@
 static DeducedTemplateArgument
 checkDeducedTemplateArguments(ASTContext &Context,
                               const DeducedTemplateArgument &X,
-                              const DeducedTemplateArgument &Y) {
+                              const DeducedTemplateArgument &Y,
+                              bool AggregateCandidateDeduction = false) {
   // We have no deduction for one or both of the arguments; they're compatible.
   if (X.isNull())
     return Y;
@@ -350,20 +351,24 @@
 
   case TemplateArgument::Pack: {
     if (Y.getKind() != TemplateArgument::Pack ||
-        X.pack_size() != Y.pack_size())
+        (!AggregateCandidateDeduction && X.pack_size() != Y.pack_size()))
       return DeducedTemplateArgument();
 
     llvm::SmallVector<TemplateArgument, 8> NewPack;
-    for (TemplateArgument::pack_iterator XA = X.pack_begin(),
-                                      XAEnd = X.pack_end(),
-                                         YA = Y.pack_begin();
+    for (TemplateArgument::pack_iterator
+             XA = X.pack_begin(),
+             XAEnd = X.pack_end(), YA = Y.pack_begin(), YAEnd = Y.pack_end();
          XA != XAEnd; ++XA, ++YA) {
-      TemplateArgument Merged = checkDeducedTemplateArguments(
-          Context, DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
-          DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()));
-      if (Merged.isNull() && !(XA->isNull() && YA->isNull()))
-        return DeducedTemplateArgument();
-      NewPack.push_back(Merged);
+      if (YA != YAEnd) {
+        TemplateArgument Merged = checkDeducedTemplateArguments(
+            Context, DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
+            DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()));
+        if (Merged.isNull() && !(XA->isNull() && YA->isNull()))
+          return DeducedTemplateArgument();
+        NewPack.push_back(Merged);
+      } else {
+        NewPack.push_back(*XA);
+      }
     }
 
     return DeducedTemplateArgument(
@@ -694,8 +699,10 @@
   /// Prepare to deduce the packs named within Pattern.
   PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
                      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                     TemplateDeductionInfo &Info, TemplateArgument Pattern)
-      : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+                     TemplateDeductionInfo &Info, TemplateArgument Pattern,
+                     bool DeducePackIfNotAlreadyDeduced = false)
+      : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info),
+        DeducePackIfNotAlreadyDeduced(DeducePackIfNotAlreadyDeduced){
     unsigned NumNamedPacks = addPacks(Pattern);
     finishConstruction(NumNamedPacks);
   }
@@ -939,8 +946,13 @@
 
       // Check the new pack matches any previous value.
       DeducedTemplateArgument OldPack = *Loc;
-      DeducedTemplateArgument Result =
-          checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
+      DeducedTemplateArgument Result = checkDeducedTemplateArguments(
+          S.Context, OldPack, NewPack, DeducePackIfNotAlreadyDeduced);
+
+      Info.AggregateDeductionCandidateHasMismatchedArity =
+          OldPack.getKind() == TemplateArgument::Pack &&
+          NewPack.getKind() == TemplateArgument::Pack &&
+          OldPack.pack_size() != NewPack.pack_size() && !Result.isNull();
 
       // If we deferred a deduction of this pack, check that one now too.
       if (!Result.isNull() && !Pack.DeferredDeduction.isNull()) {
@@ -980,6 +992,7 @@
   TemplateDeductionInfo &Info;
   unsigned PackElements = 0;
   bool IsPartiallyExpanded = false;
+  bool DeducePackIfNotAlreadyDeduced = false;
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   std::optional<unsigned> FixedNumExpansions;
 
@@ -4082,7 +4095,7 @@
     FunctionTemplateDecl *FunctionTemplate,
     TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
     FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
-    bool PartialOverloading,
+    bool PartialOverloading, bool AggregateDeductionCandidate,
     llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent) {
   if (FunctionTemplate->isInvalidDecl())
     return TDK_Invalid;
@@ -4169,9 +4182,12 @@
       continue;
     }
 
+    bool IsTrailingPack = ParamIdx + 1 == NumParamTypes;
+
     QualType ParamPattern = ParamExpansion->getPattern();
     PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info,
-                                 ParamPattern);
+                                 ParamPattern,
+                                 AggregateDeductionCandidate && IsTrailingPack);
 
     // C++0x [temp.deduct.call]p1:
     //   For a function parameter pack that occurs at the end of the
@@ -4189,7 +4205,7 @@
     // the length of the explicitly-specified pack if it's expanded by the
     // parameter pack and 0 otherwise, and we treat each deduction as a
     // non-deduced context.
-    if (ParamIdx + 1 == NumParamTypes || PackScope.hasFixedArity()) {
+    if (IsTrailingPack || PackScope.hasFixedArity()) {
       for (; ArgIdx < Args.size() && PackScope.hasNextElement();
            PackScope.nextPackElement(), ++ArgIdx) {
         ParamTypesForArgChecking.push_back(ParamPattern);
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -2570,6 +2570,39 @@
 };
 }
 
+FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList(
+    TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
+    SourceLocation Loc) {
+  if (CXXRecordDecl *DefRecord =
+          cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) {
+    TemplateDecl *DescribedTemplate = DefRecord->getDescribedClassTemplate();
+    Template = DescribedTemplate ? DescribedTemplate : Template;
+  }
+
+  DeclContext *DC = Template->getDeclContext();
+  if (DC->isDependentContext())
+    return nullptr;
+
+  ConvertConstructorToDeductionGuideTransform Transform(
+      *this, cast<ClassTemplateDecl>(Template));
+  if (!isCompleteType(Loc, Transform.DeducedType))
+    return nullptr;
+
+  // In case we were expanding a pack when we attempted to declare deduction
+  // guides, turn off pack expansion for everything we're about to do.
+  ArgumentPackSubstitutionIndexRAII SubstIndex(*this,
+                                               /*NewSubstitutionIndex=*/-1);
+  // Create a template instantiation record to track the "instantiation" of
+  // constructors into deduction guides.
+  // FIXME: Add a kind for this to give more meaningful diagnostics.
+  InstantiatingTemplate BuildingDeductionGuides(*this, Loc, Template);
+  if (BuildingDeductionGuides.isInvalid())
+    return nullptr;
+
+  return cast<FunctionTemplateDecl>(
+      Transform.buildSimpleDeductionGuide(ParamTypes));
+}
+
 void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
                                           SourceLocation Loc) {
   if (CXXRecordDecl *DefRecord =
@@ -2599,8 +2632,7 @@
   ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
   // Create a template instantiation record to track the "instantiation" of
   // constructors into deduction guides.
-  // FIXME: Add a kind for this to give more meaningful diagnostics. But can
-  // this substitution process actually fail?
+  // FIXME: Add a kind for this to give more meaningful diagnostics.
   InstantiatingTemplate BuildingDeductionGuides(*this, Loc, Template);
   if (BuildingDeductionGuides.isInvalid())
     return;
@@ -2656,7 +2688,7 @@
       cast<FunctionTemplateDecl>(
           Transform.buildSimpleDeductionGuide(Transform.DeducedType))
           ->getTemplatedDecl())
-      ->setIsCopyDeductionCandidate();
+      ->setDeductionCandidateKind(DeductionCandidateKind::Copy);
 }
 
 /// Diagnose the presence of a default template argument on a
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6468,7 +6468,7 @@
     OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
     bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
     ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions,
-    OverloadCandidateParamOrder PO) {
+    OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) {
   const FunctionProtoType *Proto
     = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
   assert(Proto && "Functions without a prototype cannot be overloaded");
@@ -6635,7 +6635,8 @@
   // parameter list is truncated on the right, so that there are
   // exactly m parameters.
   unsigned MinRequiredArgs = Function->getMinRequiredArguments();
-  if (Args.size() < MinRequiredArgs && !PartialOverloading) {
+  if (!AggregateCandidateDeduction && Args.size() < MinRequiredArgs &&
+      !PartialOverloading) {
     // Not enough arguments.
     Candidate.Viable = false;
     Candidate.FailureKind = ovl_fail_too_few_arguments;
@@ -7261,7 +7262,8 @@
   ConversionSequenceList Conversions;
   if (TemplateDeductionResult Result = DeduceTemplateArguments(
           MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
-          PartialOverloading, [&](ArrayRef<QualType> ParamTypes) {
+          PartialOverloading, /*AggregateDeductionCandidate=*/false,
+          [&](ArrayRef<QualType> ParamTypes) {
             return CheckNonDependentConversions(
                 MethodTmpl, ParamTypes, Args, CandidateSet, Conversions,
                 SuppressUserConversions, ActingContext, ObjectType,
@@ -7314,7 +7316,7 @@
     TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
     OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
     bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate,
-    OverloadCandidateParamOrder PO) {
+    OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) {
   if (!CandidateSet.isNewCandidate(FunctionTemplate, PO))
     return;
 
@@ -7344,7 +7346,8 @@
   ConversionSequenceList Conversions;
   if (TemplateDeductionResult Result = DeduceTemplateArguments(
           FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
-          PartialOverloading, [&](ArrayRef<QualType> ParamTypes) {
+          PartialOverloading, AggregateCandidateDeduction,
+          [&](ArrayRef<QualType> ParamTypes) {
             return CheckNonDependentConversions(
                 FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions,
                 SuppressUserConversions, nullptr, QualType(), {}, PO);
@@ -7380,7 +7383,8 @@
   AddOverloadCandidate(
       Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
       PartialOverloading, AllowExplicit,
-      /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions, PO);
+      /*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO,
+      Info.AggregateDeductionCandidateHasMismatchedArity);
 }
 
 /// Check that implicit conversion sequences can be formed for each argument
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -12,12 +12,15 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/Designator.h"
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
@@ -25,8 +28,12 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/SemaInternal.h"
 #include "llvm/ADT/APInt.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -304,6 +311,7 @@
   bool InOverloadResolution;
   InitListExpr *FullyStructuredList = nullptr;
   NoInitExpr *DummyExpr = nullptr;
+  SmallVector<QualType, 8> *AggrDeductionCandidateParamTypes = nullptr;
 
   NoInitExpr *getDummyInit() {
     if (!DummyExpr)
@@ -390,6 +398,7 @@
                                    unsigned ExpectedNumInits);
   int numArrayElements(QualType DeclType);
   int numStructUnionElements(QualType DeclType);
+  static RecordDecl *getRecordDecl(QualType DeclType);
 
   ExprResult PerformEmptyInit(SourceLocation Loc,
                               const InitializedEntity &Entity);
@@ -494,7 +503,15 @@
 public:
   InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL,
                   QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid,
-                  bool InOverloadResolution = false);
+                  bool InOverloadResolution = false,
+                  SmallVector<QualType, 8> *AggrDeductionCandidateParamTypes = nullptr);
+  InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL,
+                  QualType &T,
+                  SmallVector<QualType, 8> &AggrDeductionCandidateParamTypes)
+      : InitListChecker(S, Entity, IL, T, true, false, false,
+                        &AggrDeductionCandidateParamTypes) {
+  };
+
   bool HadError() { return hadError; }
 
   // Retrieves the fully-structured initializer list used for
@@ -959,13 +976,14 @@
   return false;
 }
 
-InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
-                                 InitListExpr *IL, QualType &T, bool VerifyOnly,
-                                 bool TreatUnavailableAsInvalid,
-                                 bool InOverloadResolution)
+InitListChecker::InitListChecker(
+    Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T,
+    bool VerifyOnly, bool TreatUnavailableAsInvalid, bool InOverloadResolution,
+    SmallVector<QualType, 8> *AggrDeductionCandidateParamTypes)
     : SemaRef(S), VerifyOnly(VerifyOnly),
       TreatUnavailableAsInvalid(TreatUnavailableAsInvalid),
-      InOverloadResolution(InOverloadResolution) {
+      InOverloadResolution(InOverloadResolution),
+      AggrDeductionCandidateParamTypes(AggrDeductionCandidateParamTypes) {
   if (!VerifyOnly || hasAnyDesignatedInits(IL)) {
     FullyStructuredList =
         createInitListExpr(T, IL->getSourceRange(), IL->getNumInits());
@@ -979,7 +997,7 @@
   CheckExplicitInitList(Entity, IL, T, FullyStructuredList,
                         /*TopLevelObject=*/true);
 
-  if (!hadError && FullyStructuredList) {
+  if (!hadError && !AggrDeductionCandidateParamTypes && FullyStructuredList) {
     bool RequiresSecondPass = false;
     FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass,
                                /*OuterILE=*/nullptr, /*OuterIndex=*/0);
@@ -1015,6 +1033,14 @@
   return InitializableMembers - structDecl->hasFlexibleArrayMember();
 }
 
+RecordDecl *InitListChecker::getRecordDecl(QualType DeclType) {
+  if (DeclType->isRecordType())
+    return DeclType->castAs<RecordType>()->getDecl();
+  if (auto *Inject = dyn_cast<InjectedClassNameType>(DeclType))
+    return Inject->getDecl();
+  return nullptr;
+}
+
 /// Determine whether Entity is an entity for which it is idiomatic to elide
 /// the braces in aggregate initialization.
 static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
@@ -1309,15 +1335,18 @@
   } else if (DeclType->isVectorType()) {
     CheckVectorType(Entity, IList, DeclType, Index,
                     StructuredList, StructuredIndex);
-  } else if (DeclType->isRecordType()) {
-    assert(DeclType->isAggregateType() &&
-           "non-aggregate records should be handed in CheckSubElementType");
-    RecordDecl *RD = DeclType->castAs<RecordType>()->getDecl();
+  } else if (RecordDecl *RD = getRecordDecl(DeclType)) {
     auto Bases =
         CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(),
                                         CXXRecordDecl::base_class_iterator());
-    if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
-      Bases = CXXRD->bases();
+    if (DeclType->isRecordType()) {
+      assert(DeclType->isAggregateType() &&
+             "non-aggregate records should be handed in CheckSubElementType");
+      if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+        Bases = CXXRD->bases();
+    } else {
+      Bases = cast<CXXRecordDecl>(RD)->bases();
+    }
     CheckStructUnionTypes(Entity, IList, DeclType, Bases, RD->field_begin(),
                           SubobjectIsDesignatorContext, Index, StructuredList,
                           StructuredIndex, TopLevelObject);
@@ -1347,6 +1376,13 @@
     // Checks for scalar type are sufficient for these types too.
     CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
                     StructuredIndex);
+  } else if (DeclType->isDependentType()) {
+    // C++ [over.match.class.deduct]p1.5:
+    //   brace elision is not considered for any aggregate element that has a
+    //   dependent non-array type or an array type with a value-dependent bound
+    ++Index;
+    assert(AggrDeductionCandidateParamTypes);
+    AggrDeductionCandidateParamTypes->push_back(DeclType);
   } else {
     if (!VerifyOnly)
       SemaRef.Diag(IList->getBeginLoc(), diag::err_illegal_initializer_type)
@@ -1404,31 +1440,46 @@
             ? InitializedEntity::InitializeTemporary(ElemType)
             : Entity;
 
-    InitializationSequence Seq(SemaRef, TmpEntity, Kind, expr,
-                               /*TopLevelOfInitList*/ true);
+    if (TmpEntity.getType()->isDependentType()) {
+      // C++ [over.match.class.deduct]p1.5:
+      //   brace elision is not considered for any aggregate element that has a
+      //   dependent non-array type or an array type with a value-dependent
+      //   bound
+      assert(AggrDeductionCandidateParamTypes);
+      if (!isa_and_nonnull<ConstantArrayType>(
+              SemaRef.Context.getAsArrayType(ElemType))) {
+        ++Index;
+        AggrDeductionCandidateParamTypes->push_back(ElemType);
+        return;
+      }
+    } else {
+      InitializationSequence Seq(SemaRef, TmpEntity, Kind, expr,
+                                 /*TopLevelOfInitList*/ true);
+      // C++14 [dcl.init.aggr]p13:
+      //   If the assignment-expression can initialize a member, the member is
+      //   initialized. Otherwise [...] brace elision is assumed
+      //
+      // Brace elision is never performed if the element is not an
+      // assignment-expression.
+      if (Seq || isa<InitListExpr>(expr)) {
+        if (!VerifyOnly) {
+          ExprResult Result = Seq.Perform(SemaRef, TmpEntity, Kind, expr);
+          if (Result.isInvalid())
+            hadError = true;
 
-    // C++14 [dcl.init.aggr]p13:
-    //   If the assignment-expression can initialize a member, the member is
-    //   initialized. Otherwise [...] brace elision is assumed
-    //
-    // Brace elision is never performed if the element is not an
-    // assignment-expression.
-    if (Seq || isa<InitListExpr>(expr)) {
-      if (!VerifyOnly) {
-        ExprResult Result = Seq.Perform(SemaRef, TmpEntity, Kind, expr);
-        if (Result.isInvalid())
+          UpdateStructuredListElement(StructuredList, StructuredIndex,
+                                      Result.getAs<Expr>());
+        } else if (!Seq) {
           hadError = true;
-
-        UpdateStructuredListElement(StructuredList, StructuredIndex,
-                                    Result.getAs<Expr>());
-      } else if (!Seq) {
-        hadError = true;
-      } else if (StructuredList) {
-        UpdateStructuredListElement(StructuredList, StructuredIndex,
-                                    getDummyInit());
+        } else if (StructuredList) {
+          UpdateStructuredListElement(StructuredList, StructuredIndex,
+                                      getDummyInit());
+        }
+        ++Index;
+        if (AggrDeductionCandidateParamTypes)
+          AggrDeductionCandidateParamTypes->push_back(ElemType);
+        return;
       }
-      ++Index;
-      return;
     }
 
     // Fall through for subaggregate initialization
@@ -1644,6 +1695,8 @@
   }
   UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
   ++Index;
+  if (AggrDeductionCandidateParamTypes)
+    AggrDeductionCandidateParamTypes->push_back(DeclType);
 }
 
 void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
@@ -1699,6 +1752,8 @@
 
   UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
   ++Index;
+  if (AggrDeductionCandidateParamTypes)
+    AggrDeductionCandidateParamTypes->push_back(DeclType);
 }
 
 void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
@@ -1750,6 +1805,8 @@
       }
       UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
       ++Index;
+      if (AggrDeductionCandidateParamTypes)
+        AggrDeductionCandidateParamTypes->push_back(elementType);
       return;
     }
 
@@ -1911,6 +1968,8 @@
         StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
       }
       ++Index;
+      if (AggrDeductionCandidateParamTypes)
+        AggrDeductionCandidateParamTypes->push_back(DeclType);
       return;
     }
   }
@@ -2070,20 +2129,18 @@
     bool SubobjectIsDesignatorContext, unsigned &Index,
     InitListExpr *StructuredList, unsigned &StructuredIndex,
     bool TopLevelObject) {
-  RecordDecl *structDecl = DeclType->castAs<RecordType>()->getDecl();
+  RecordDecl *RD = getRecordDecl(DeclType);
 
   // If the record is invalid, some of it's members are invalid. To avoid
   // confusion, we forgo checking the initializer for the entire record.
-  if (structDecl->isInvalidDecl()) {
+  if (RD->isInvalidDecl()) {
     // Assume it was supposed to consume a single initializer.
     ++Index;
     hadError = true;
     return;
   }
 
-  if (DeclType->isUnionType() && IList->getNumInits() == 0) {
-    RecordDecl *RD = DeclType->castAs<RecordType>()->getDecl();
-
+  if (RD->isUnion() && IList->getNumInits() == 0) {
     if (!VerifyOnly)
       for (FieldDecl *FD : RD->fields()) {
         QualType ET = SemaRef.Context.getBaseElementType(FD->getType());
@@ -2127,7 +2184,8 @@
   bool InitializedSomething = false;
 
   // If we have any base classes, they are initialized prior to the fields.
-  for (auto &Base : Bases) {
+  for (auto I = Bases.begin(), E = Bases.end(); I != E; ++I) {
+    auto &Base = *I;
     Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr;
 
     // Designated inits always initialize fields, so if we see one, all
@@ -2135,6 +2193,34 @@
     if (Init && isa<DesignatedInitExpr>(Init))
       Init = nullptr;
 
+    // C++ [over.match.class.deduct]p1.6:
+    //   each non-trailing aggregate element that is a pack expansion is assumed
+    //   to correspond to no elements of the initializer list, and (1.7) a
+    //   trailing aggregate element that is a pack expansion is assumed to
+    //   correspond to all remaining elements of the initializer list (if any).
+
+    // C++ [over.match.class.deduct]p1.9:
+    //   ... except that additional parameter packs of the form P_j... are
+    //   inserted into the parameter list in their original aggregate element
+    //   position corresponding to each non-trailing aggregate element of
+    //   type P_j that was skipped because it was a parameter pack, and the
+    //   trailing sequence of parameters corresponding to a trailing
+    //   aggregate element that is a pack expansion (if any) is replaced
+    //   by a single parameter of the form T_n....
+    if (AggrDeductionCandidateParamTypes && Base.isPackExpansion()) {
+      AggrDeductionCandidateParamTypes->push_back(
+          SemaRef.Context.getPackExpansionType(Base.getType(), std::nullopt));
+
+      // Trailing pack expansion
+      if (I + 1 == E && RD->field_empty()) {
+        if (Index < IList->getNumInits())
+          Index = IList->getNumInits();
+        return;
+      }
+
+      continue;
+    }
+
     SourceLocation InitLoc = Init ? Init->getBeginLoc() : IList->getEndLoc();
     InitializedEntity BaseEntity = InitializedEntity::InitializeBase(
         SemaRef.Context, &Base, false, &Entity);
@@ -2157,7 +2243,6 @@
   // anything except look at designated initializers; That's okay,
   // because an error should get printed out elsewhere. It might be
   // worthwhile to skip over the rest of the initializer, though.
-  RecordDecl *RD = DeclType->castAs<RecordType>()->getDecl();
   RecordDecl::field_iterator FieldEnd = RD->field_end();
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
     return isa<FieldDecl>(D) || isa<RecordDecl>(D);
@@ -2241,7 +2326,7 @@
     }
 
     // We've already initialized a member of a union. We're done.
-    if (InitializedSomething && DeclType->isUnionType())
+    if (InitializedSomething && RD->isUnion())
       break;
 
     // If we've hit the flexible array member at the end, we're done.
@@ -2282,7 +2367,7 @@
                         StructuredList, StructuredIndex);
     InitializedSomething = true;
 
-    if (DeclType->isUnionType() && StructuredList) {
+    if (RD->isUnion() && StructuredList) {
       // Initialize the first field within the union.
       StructuredList->setInitializedFieldInUnion(*Field);
     }
@@ -2293,7 +2378,7 @@
   // Emit warnings for missing struct field initializers.
   if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
       Field != FieldEnd && !Field->getType()->isIncompleteArrayType() &&
-      !DeclType->isUnionType()) {
+      !RD->isUnion()) {
     // It is possible we have one or more unnamed bitfields remaining.
     // Find first (if any) named field and emit warning.
     for (RecordDecl::field_iterator it = Field, end = RD->field_end();
@@ -2308,7 +2393,7 @@
 
   // Check that any remaining fields can be value-initialized if we're not
   // building a structured list. (If we are, we'll check this later.)
-  if (!StructuredList && Field != FieldEnd && !DeclType->isUnionType() &&
+  if (!StructuredList && Field != FieldEnd && !RD->isUnion() &&
       !Field->getType()->isIncompleteArrayType()) {
     for (; Field != FieldEnd && !hadError; ++Field) {
       if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
@@ -2347,7 +2432,8 @@
   InitializedEntity MemberEntity =
     InitializedEntity::InitializeMember(*Field, &Entity);
 
-  if (isa<InitListExpr>(IList->getInit(Index)))
+  if (isa<InitListExpr>(IList->getInit(Index)) ||
+      AggrDeductionCandidateParamTypes)
     CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
                         StructuredList, StructuredIndex);
   else
@@ -2405,7 +2491,7 @@
 // the given struct or union.
 class FieldInitializerValidatorCCC final : public CorrectionCandidateCallback {
  public:
-  explicit FieldInitializerValidatorCCC(RecordDecl *RD)
+  explicit FieldInitializerValidatorCCC(const RecordDecl *RD)
       : Record(RD) {}
 
   bool ValidateCandidate(const TypoCorrection &candidate) override {
@@ -2418,7 +2504,7 @@
   }
 
  private:
-  RecordDecl *Record;
+  const RecordDecl *Record;
 };
 
 } // end anonymous namespace
@@ -2494,6 +2580,8 @@
                                     Result.get());
       }
       ++Index;
+      if (AggrDeductionCandidateParamTypes)
+        AggrDeductionCandidateParamTypes->push_back(CurrentObjectType);
       return !Seq;
     }
 
@@ -2587,8 +2675,8 @@
     //   then the current object (defined below) shall have
     //   structure or union type and the identifier shall be the
     //   name of a member of that type.
-    const RecordType *RT = CurrentObjectType->getAs<RecordType>();
-    if (!RT) {
+    RecordDecl *RD = getRecordDecl(CurrentObjectType);
+    if (!RD) {
       SourceLocation Loc = D->getDotLoc();
       if (Loc.isInvalid())
         Loc = D->getFieldLoc();
@@ -2602,7 +2690,7 @@
     FieldDecl *KnownField = D->getFieldDecl();
     if (!KnownField) {
       const IdentifierInfo *FieldName = D->getFieldName();
-      DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
+      DeclContext::lookup_result Lookup = RD->lookup(FieldName);
       for (NamedDecl *ND : Lookup) {
         if (auto *FD = dyn_cast<FieldDecl>(ND)) {
           KnownField = FD;
@@ -2636,11 +2724,11 @@
 
         // Name lookup didn't find anything.
         // Determine whether this was a typo for another field name.
-        FieldInitializerValidatorCCC CCC(RT->getDecl());
+        FieldInitializerValidatorCCC CCC(RD);
         if (TypoCorrection Corrected = SemaRef.CorrectTypo(
                 DeclarationNameInfo(FieldName, D->getFieldLoc()),
                 Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, CCC,
-                Sema::CTK_ErrorRecovery, RT->getDecl())) {
+                Sema::CTK_ErrorRecovery, RD)) {
           SemaRef.diagnoseTypo(
               Corrected,
               SemaRef.PDiag(diag::err_field_designator_unknown_suggest)
@@ -2665,12 +2753,12 @@
     }
 
     unsigned NumBases = 0;
-    if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+    if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
       NumBases = CXXRD->getNumBases();
 
     unsigned FieldIndex = NumBases;
 
-    for (auto *FI : RT->getDecl()->fields()) {
+    for (auto *FI : RD->fields()) {
       if (FI->isUnnamedBitfield())
         continue;
       if (declaresSameEntity(KnownField, FI)) {
@@ -2685,7 +2773,7 @@
 
     // All of the fields of a union are located at the same place in
     // the initializer list.
-    if (RT->getDecl()->isUnion()) {
+    if (RD->isUnion()) {
       FieldIndex = 0;
       if (StructuredList) {
         FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion();
@@ -2740,15 +2828,14 @@
     // cases where a designator takes us backwards too.
     if (IsFirstDesignator && !VerifyOnly && SemaRef.getLangOpts().CPlusPlus &&
         NextField &&
-        (*NextField == RT->getDecl()->field_end() ||
+        (*NextField == RD->field_end() ||
          (*NextField)->getFieldIndex() > Field->getFieldIndex() + 1)) {
       // Find the field that we just initialized.
       FieldDecl *PrevField = nullptr;
-      for (auto FI = RT->getDecl()->field_begin();
-           FI != RT->getDecl()->field_end(); ++FI) {
+      for (auto FI = RD->field_begin(); FI != RD->field_end(); ++FI) {
         if (FI->isUnnamedBitfield())
           continue;
-        if (*NextField != RT->getDecl()->field_end() &&
+        if (*NextField != RD->field_end() &&
             declaresSameEntity(*FI, **NextField))
           break;
         PrevField = *FI;
@@ -2873,7 +2960,7 @@
       return false;
 
     // We've already initialized something in the union; we're done.
-    if (RT->getDecl()->isUnion())
+    if (RD->isUnion())
       return hadError;
 
     // Check the remaining fields within this class/struct/union subobject.
@@ -3181,7 +3268,8 @@
     NumElements = VType->getNumElements();
   } else if (CurrentObjectType->isRecordType()) {
     NumElements = numStructUnionElements(CurrentObjectType);
-  }
+  } else if (CurrentObjectType->isDependentType())
+    NumElements = 1;
 
   Result->reserveInits(SemaRef.Context, NumElements);
 
@@ -10531,6 +10619,72 @@
   bool HasAnyDeductionGuide = false;
   bool AllowExplicit = !Kind.isCopyInit() || ListInit;
 
+  // Return true is the candidate is added successfully, false otherwise.
+  auto addDeductionCandidate = [&](FunctionTemplateDecl *TD,
+                                   CXXDeductionGuideDecl *GD,
+                                   DeclAccessPair FoundDecl,
+                                   bool OnlyListConstructors,
+                                   bool AllowAggregateDeductionCandidate) {
+    // C++ [over.match.ctor]p1: (non-list copy-initialization from non-class)
+    //   For copy-initialization, the candidate functions are all the
+    //   converting constructors (12.3.1) of that class.
+    // C++ [over.match.copy]p1: (non-list copy-initialization from class)
+    //   The converting constructors of T are candidate functions.
+    if (!AllowExplicit) {
+      // Overload resolution checks whether the deduction guide is declared
+      // explicit for us.
+
+      // When looking for a converting constructor, deduction guides that
+      // could never be called with one argument are not interesting to
+      // check or note.
+      if (GD->getMinRequiredArguments() > 1 ||
+          (GD->getNumParams() == 0 && !GD->isVariadic()))
+        return;
+    }
+
+    // C++ [over.match.list]p1.1: (first phase list initialization)
+    //   Initially, the candidate functions are the initializer-list
+    //   constructors of the class T
+    if (OnlyListConstructors && !isInitListConstructor(GD))
+      return;
+
+    if (!AllowAggregateDeductionCandidate &&
+        GD->getDeductionCandidateKind() == DeductionCandidateKind::Aggregate)
+      return;
+
+    // C++ [over.match.list]p1.2: (second phase list initialization)
+    //   the candidate functions are all the constructors of the class T
+    // C++ [over.match.ctor]p1: (all other cases)
+    //   the candidate functions are all the constructors of the class of
+    //   the object being initialized
+
+    // C++ [over.best.ics]p4:
+    //   When [...] the constructor [...] is a candidate by
+    //    - [over.match.copy] (in all cases)
+    // FIXME: The "second phase of [over.match.list] case can also
+    // theoretically happen here, but it's not clear whether we can
+    // ever have a parameter of the right type.
+    bool SuppressUserConversions = Kind.isCopyInit();
+
+    if (TD) {
+      SmallVector<Expr *, 8> TmpInits;
+      for (Expr *E : Inits)
+        if (auto *DI = dyn_cast<DesignatedInitExpr>(E))
+          TmpInits.push_back(DI->getInit());
+        else
+          TmpInits.push_back(E);
+      AddTemplateOverloadCandidate(TD, FoundDecl, /*ExplicitArgs=*/nullptr,
+                                   TmpInits, Candidates,
+                                   SuppressUserConversions,
+                                   /*PartialOverloading=*/false, AllowExplicit,
+                                   ADLCallKind::NotADL, {}, true);
+    } else {
+      AddOverloadCandidate(GD, FoundDecl, Inits, Candidates,
+                           SuppressUserConversions,
+                           /*PartialOverloading*/ false, AllowExplicit);
+    }
+  };
+
   auto tryToResolveOverload =
       [&](bool OnlyListConstructors) -> OverloadingResult {
     Candidates.clear(OverloadCandidateSet::CSK_Normal);
@@ -10550,53 +10704,73 @@
       if (!GD->isImplicit())
         HasAnyDeductionGuide = true;
 
-      // C++ [over.match.ctor]p1: (non-list copy-initialization from non-class)
-      //   For copy-initialization, the candidate functions are all the
-      //   converting constructors (12.3.1) of that class.
-      // C++ [over.match.copy]p1: (non-list copy-initialization from class)
-      //   The converting constructors of T are candidate functions.
-      if (!AllowExplicit) {
-        // Overload resolution checks whether the deduction guide is declared
-        // explicit for us.
-
-        // When looking for a converting constructor, deduction guides that
-        // could never be called with one argument are not interesting to
-        // check or note.
-        if (GD->getMinRequiredArguments() > 1 ||
-            (GD->getNumParams() == 0 && !GD->isVariadic()))
-          continue;
-      }
-
-      // C++ [over.match.list]p1.1: (first phase list initialization)
-      //   Initially, the candidate functions are the initializer-list
-      //   constructors of the class T
-      if (OnlyListConstructors && !isInitListConstructor(GD))
-        continue;
+      addDeductionCandidate(TD, GD, I.getPair(), OnlyListConstructors, false);
+    }
+
+    // C++ [over.match.class.deduct]p1.4:
+    //   if C is defined and its definition satisfies the conditions for an
+    //   aggregate class ([dcl.init.aggr]) with the assumption that any
+    //   dependent base class has no virtual functions and no virtual base
+    //   classes, and the initializer is a non-empty braced-init-list or
+    //   parenthesized expression-list, and there are no deduction-guides for
+    //   C, the set contains an additional function template, called the
+    //   aggregate deduction candidate, defined as follows.
+    if (!HasAnyDeductionGuide && ListInit && ListInit->getNumInits()) {
+      // TODO: support parenthesized expression-list
+      auto *RD = cast<CXXRecordDecl>(Template->getTemplatedDecl());
+      if (RD->getDefinition() && RD->isAggregate()) {
+        QualType Ty = Context.getRecordType(RD);
+        SmallVector<QualType, 8> ElementTypes;
+        InitListChecker CheckInitList(*this, Entity, ListInit, Ty,
+                                      ElementTypes);
+        if (!CheckInitList.HadError()) {
+          // C++ [over.match.class.deduct]p1.8:
+          //   if e_i is of array type and x_i is a braced-init-list, T_i is an
+          //   rvalue reference to the declared type of e_i and
+          // C++ [over.match.class.deduct]p1.9:
+          //   if e_i is of array type and x_i is a bstring-literal, T_i is an
+          //   lvalue reference to the const-qualified declared type of e_i and
+          // C++ [over.match.class.deduct]p1.10:
+          //   otherwise, T_i is the declared type of e_i
+          for (int i = 0, e = ListInit->getNumInits();
+               i < e && !isa<PackExpansionType>(ElementTypes[i]); ++i)
+            if (ElementTypes[i]->isArrayType()) {
+              if (isa<InitListExpr>(ListInit->getInit(i)))
+                ElementTypes[i] =
+                    Context.getRValueReferenceType(ElementTypes[i]);
+              else if (isa<StringLiteral>(
+                           ListInit->getInit(i)->IgnoreParenImpCasts()))
+                ElementTypes[i] =
+                    Context.getLValueReferenceType(ElementTypes[i]);
+            }
 
-      // C++ [over.match.list]p1.2: (second phase list initialization)
-      //   the candidate functions are all the constructors of the class T
-      // C++ [over.match.ctor]p1: (all other cases)
-      //   the candidate functions are all the constructors of the class of
-      //   the object being initialized
-
-      // C++ [over.best.ics]p4:
-      //   When [...] the constructor [...] is a candidate by
-      //    - [over.match.copy] (in all cases)
-      // FIXME: The "second phase of [over.match.list] case can also
-      // theoretically happen here, but it's not clear whether we can
-      // ever have a parameter of the right type.
-      bool SuppressUserConversions = Kind.isCopyInit();
-
-      if (TD)
-        AddTemplateOverloadCandidate(TD, I.getPair(), /*ExplicitArgs*/ nullptr,
-                                     Inits, Candidates, SuppressUserConversions,
-                                     /*PartialOverloading*/ false,
-                                     AllowExplicit);
-      else
-        AddOverloadCandidate(GD, I.getPair(), Inits, Candidates,
-                             SuppressUserConversions,
-                             /*PartialOverloading*/ false, AllowExplicit);
+          llvm::FoldingSetNodeID ID;
+          ID.AddPointer(Template);
+          for (auto &T : ElementTypes)
+            T.getCanonicalType().Profile(ID);
+          unsigned Hash = ID.ComputeHash();
+          if (AggregateDeductionCandidates.count(Hash) == 0) {
+            if (FunctionTemplateDecl *TD =
+                    DeclareImplicitDeductionGuideFromInitList(
+                        Template, ElementTypes,
+                        TSInfo->getTypeLoc().getEndLoc())) {
+              auto *GD = cast<CXXDeductionGuideDecl>(TD->getTemplatedDecl());
+              GD->setDeductionCandidateKind(DeductionCandidateKind::Aggregate);
+              AggregateDeductionCandidates[Hash] = GD;
+              addDeductionCandidate(TD, GD, DeclAccessPair::make(TD, AS_public),
+                                    OnlyListConstructors, true);
+            }
+          } else {
+            CXXDeductionGuideDecl *GD = AggregateDeductionCandidates[Hash];
+            FunctionTemplateDecl *TD = GD->getDescribedFunctionTemplate();
+            assert(TD && "aggregate deduction candidate is function template");
+            addDeductionCandidate(TD, GD, DeclAccessPair::make(TD, AS_public),
+                                  OnlyListConstructors, true);
+          }
+        }
+      }
     }
+
     return Candidates.BestViableFunction(*this, Kind.getLocation(), Best);
   };
 
Index: clang/lib/AST/Decl.cpp
===================================================================
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -3008,7 +3008,8 @@
   FunctionDeclBits.HasSkippedBody = false;
   FunctionDeclBits.WillHaveBody = false;
   FunctionDeclBits.IsMultiVersion = false;
-  FunctionDeclBits.IsCopyDeductionCandidate = false;
+  FunctionDeclBits.DeductionCandidateKind =
+      static_cast<uint64_t>(DeductionCandidateKind::Normal);
   FunctionDeclBits.HasODRHash = false;
   FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
   if (TrailingRequiresClause)
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -3698,7 +3698,7 @@
             NameInfo, T, TInfo, ToEndLoc, Ctor))
       return ToFunction;
     cast<CXXDeductionGuideDecl>(ToFunction)
-        ->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate());
+        ->setDeductionCandidateKind(Guide->getDeductionCandidateKind());
   } else {
     if (GetImportedOrCreateDecl(
             ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
Index: clang/include/clang/Sema/TemplateDeduction.h
===================================================================
--- clang/include/clang/Sema/TemplateDeduction.h
+++ clang/include/clang/Sema/TemplateDeduction.h
@@ -234,6 +234,13 @@
   ///   different argument type from its substituted parameter type.
   unsigned CallArgIndex = 0;
 
+  // C++ [over.match.class.deduct]p5.2:
+  //   During template argument deduction for the aggregate deduction
+  //   candidate, the number of elements in a trailing parameter pack is only
+  //   deduced from the number of remaining function arguments if it is not
+  //   otherwise deduced.
+  bool AggregateDeductionCandidateHasMismatchedArity = false;
+
   /// Information on packs that we're currently expanding.
   ///
   /// FIXME: This should be kept internal to SemaTemplateDeduction.
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3988,7 +3988,8 @@
       bool AllowExplicitConversion = false,
       ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
       ConversionSequenceList EarlyConversions = std::nullopt,
-      OverloadCandidateParamOrder PO = {});
+      OverloadCandidateParamOrder PO = {},
+      bool AggregateCandidateDeduction = false);
   void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
                       ArrayRef<Expr *> Args,
                       OverloadCandidateSet &CandidateSet,
@@ -4029,7 +4030,8 @@
       OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
       bool PartialOverloading = false, bool AllowExplicit = true,
       ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
-      OverloadCandidateParamOrder PO = {});
+      OverloadCandidateParamOrder PO = {},
+      bool AggregateCandidateDeduction = false);
   bool CheckNonDependentConversions(
       FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes,
       ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet,
@@ -9093,7 +9095,7 @@
       FunctionTemplateDecl *FunctionTemplate,
       TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
       FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
-      bool PartialOverloading,
+      bool PartialOverloading, bool AggregateDeductionCandidate,
       llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent);
 
   TemplateDeductionResult
@@ -9149,6 +9151,11 @@
   /// not already done so.
   void DeclareImplicitDeductionGuides(TemplateDecl *Template,
                                       SourceLocation Loc);
+  FunctionTemplateDecl *DeclareImplicitDeductionGuideFromInitList(
+      TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
+      SourceLocation Loc);
+  llvm::DenseMap<unsigned, CXXDeductionGuideDecl *>
+      AggregateDeductionCandidates;
 
   QualType DeduceTemplateSpecializationFromInitializer(
       TypeSourceInfo *TInfo, const InitializedEntity &Entity,
Index: clang/include/clang/AST/DeclCXX.h
===================================================================
--- clang/include/clang/AST/DeclCXX.h
+++ clang/include/clang/AST/DeclCXX.h
@@ -47,6 +47,7 @@
 #include "llvm/Support/TrailingObjects.h"
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <iterator>
 #include <memory>
 #include <vector>
@@ -1948,7 +1949,7 @@
         Ctor(Ctor), ExplicitSpec(ES) {
     if (EndLocation.isValid())
       setRangeEnd(EndLocation);
-    setIsCopyDeductionCandidate(false);
+    setDeductionCandidateKind(DeductionCandidateKind::Normal);
   }
 
   CXXConstructorDecl *Ctor;
@@ -1980,16 +1981,19 @@
 
   /// Get the constructor from which this deduction guide was generated, if
   /// this is an implicit deduction guide.
-  CXXConstructorDecl *getCorrespondingConstructor() const {
-    return Ctor;
+  CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; }
+
+  void setDeductionCandidateKind(DeductionCandidateKind K) {
+    FunctionDeclBits.DeductionCandidateKind = static_cast<uint64_t>(K);
   }
 
-  void setIsCopyDeductionCandidate(bool isCDC = true) {
-    FunctionDeclBits.IsCopyDeductionCandidate = isCDC;
+  DeductionCandidateKind getDeductionCandidateKind() const {
+    return static_cast<DeductionCandidateKind>(
+        FunctionDeclBits.DeductionCandidateKind);
   }
 
   bool isCopyDeductionCandidate() const {
-    return FunctionDeclBits.IsCopyDeductionCandidate;
+    return getDeductionCandidateKind() == DeductionCandidateKind::Copy;
   }
 
   // Implement isa/cast/dyncast/etc.
Index: clang/include/clang/AST/DeclBase.h
===================================================================
--- clang/include/clang/AST/DeclBase.h
+++ clang/include/clang/AST/DeclBase.h
@@ -1382,6 +1382,13 @@
   }
 };
 
+/// Only used by CXXDeductionGuideDecl.
+enum class DeductionCandidateKind : unsigned char {
+  Normal,
+  Copy,
+  Aggregate,
+};
+
 /// DeclContext - This is used only as base class of specific decl types that
 /// can act as declaration contexts. These decls are (only the top classes
 /// that directly derive from DeclContext are mentioned, not their subclasses):
@@ -1620,10 +1627,10 @@
   /// Stores the bits used by FunctionDecl.
   /// If modified NumFunctionDeclBits and the accessor
   /// methods in FunctionDecl and CXXDeductionGuideDecl
-  /// (for IsCopyDeductionCandidate) should be updated appropriately.
+  /// (for DeductionCandidateKind) should be updated appropriately.
   class FunctionDeclBitfields {
     friend class FunctionDecl;
-    /// For IsCopyDeductionCandidate
+    /// For DeductionCandidateKind
     friend class CXXDeductionGuideDecl;
     /// For the bits in DeclContextBitfields.
     uint64_t : NumDeclContextBits;
@@ -1676,10 +1683,10 @@
     /// function using attribute 'target'.
     uint64_t IsMultiVersion : 1;
 
-    /// [C++17] Only used by CXXDeductionGuideDecl. Indicates that
-    /// the Deduction Guide is the implicitly generated 'copy
-    /// deduction candidate' (is used during overload resolution).
-    uint64_t IsCopyDeductionCandidate : 1;
+    /// Only used by CXXDeductionGuideDecl. Indicates the kind
+    /// of the Deduction Guide that is the implicitly generated
+    /// (used during overload resolution).
+    uint64_t DeductionCandidateKind : 2;
 
     /// Store the ODRHash after first calculation.
     uint64_t HasODRHash : 1;
@@ -1693,7 +1700,7 @@
   };
 
   /// Number of non-inherited bits in FunctionDeclBitfields.
-  enum { NumFunctionDeclBits = 29 };
+  enum { NumFunctionDeclBits = 30 };
 
   /// Stores the bits used by CXXConstructorDecl. If modified
   /// NumCXXConstructorDeclBits and the accessor
@@ -1705,12 +1712,12 @@
     /// For the bits in FunctionDeclBitfields.
     uint64_t : NumFunctionDeclBits;
 
-    /// 22 bits to fit in the remaining available space.
+    /// 21 bits to fit in the remaining available space.
     /// Note that this makes CXXConstructorDeclBitfields take
     /// exactly 64 bits and thus the width of NumCtorInitializers
     /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
     /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
-    uint64_t NumCtorInitializers : 19;
+    uint64_t NumCtorInitializers : 18;
     uint64_t IsInheritingConstructor : 1;
 
     /// Whether this constructor has a trail-allocated explicit specifier.
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -94,6 +94,8 @@
 - Clang now implements `[temp.deduct]p9`. Substitution failures inside lambdas from
   unevaluated contexts will be surfaced as errors. They were previously handled as
   SFINAE.
+- Implemented `P1816R0: <https://wg21.link/p1816r0>`_ and `P2082R1: <https://wg21.link/p2082r1>`_,
+  which allows CTAD for aggregates (parenthesized aggregate-initialization is not supported).
 
 C++23 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to