https://github.com/antangelo updated 
https://github.com/llvm/llvm-project/pull/78670

>From 227504aa6da6dd2199c83563b9149dd3873e1a11 Mon Sep 17 00:00:00 2001
From: Antonio Abbatangelo <cont...@antangelo.com>
Date: Thu, 18 Jan 2024 23:27:16 -0500
Subject: [PATCH] Reland "[clang] Fix CTAD for aggregates for nested template
 classes"

Reland of #78387

Use the template pattern in determining whether to synthesize the
aggregate deduction guide, and update DeclareImplicitDeductionGuideFromInitList
to substitute outer template arguments.

The tests in the original patch made an assumption about the size of a
pointer type, and this led to them failing on systems with 32-bit
pointers. The tests have been updated to not depend on the size of any
type. This only requires updates to the test file, no functionality has
otherwise changed between this and the original patch.
---
 clang/docs/ReleaseNotes.rst                   |  3 ++
 clang/lib/Sema/SemaInit.cpp                   |  9 ++++-
 clang/lib/Sema/SemaTemplate.cpp               | 21 +++++++++---
 .../nested-implicit-deduction-guides.cpp      | 34 ++++++++++++++++---
 4 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b400d75095421c..ee431587a7853d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -979,6 +979,9 @@ Bug Fixes to C++ Support
 - Clang now allows parenthesized initialization of arrays in `operator new[]`.
   Fixes: (`#68198 <https://github.com/llvm/llvm-project/issues/68198>`_)
 
+- Fixes CTAD for aggregates on nested template classes. Fixes:
+  (`#77599 <https://github.com/llvm/llvm-project/issues/77599>`_)
+
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 18440a69e3a3d9..457fa377355a97 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -10731,7 +10731,14 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
     bool HasAnyDeductionGuide = false;
 
     auto SynthesizeAggrGuide = [&](InitListExpr *ListInit) {
-      auto *RD = cast<CXXRecordDecl>(Template->getTemplatedDecl());
+      auto *Pattern = Template;
+      while (Pattern->getInstantiatedFromMemberTemplate()) {
+        if (Pattern->isMemberSpecialization())
+          break;
+        Pattern = Pattern->getInstantiatedFromMemberTemplate();
+      }
+
+      auto *RD = cast<CXXRecordDecl>(Pattern->getTemplatedDecl());
       if (!(RD->getDefinition() && RD->isAggregate()))
         return;
       QualType Ty = Context.getRecordType(RD);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 0655d363352067..839d508b911f06 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2418,6 +2418,9 @@ struct ConvertConstructorToDeductionGuideTransform {
     QualType Result = SemaRef.BuildFunctionType(DeducedType, ParamTypes, Loc,
                                                 DeductionGuideName, EPI);
     TypeSourceInfo *TSI = SemaRef.Context.getTrivialTypeSourceInfo(Result, 
Loc);
+    if (NestedPattern)
+      TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,
+                              DeductionGuideName);
 
     FunctionProtoTypeLoc FPTL =
         TSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
@@ -2425,9 +2428,13 @@ struct ConvertConstructorToDeductionGuideTransform {
     // Build the parameters, needed during deduction / substitution.
     SmallVector<ParmVarDecl*, 4> Params;
     for (auto T : ParamTypes) {
-      ParmVarDecl *NewParam = ParmVarDecl::Create(
-          SemaRef.Context, DC, Loc, Loc, nullptr, T,
-          SemaRef.Context.getTrivialTypeSourceInfo(T, Loc), SC_None, nullptr);
+      auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T, Loc);
+      if (NestedPattern)
+        TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,
+                                DeclarationName());
+      ParmVarDecl *NewParam =
+          ParmVarDecl::Create(SemaRef.Context, DC, Loc, Loc, nullptr,
+                              TSI->getType(), TSI, SC_None, nullptr);
       NewParam->setScopeInfo(0, Params.size());
       FPTL.setParam(Params.size(), NewParam);
       Params.push_back(NewParam);
@@ -2670,8 +2677,14 @@ FunctionTemplateDecl 
*Sema::DeclareImplicitDeductionGuideFromInitList(
   if (BuildingDeductionGuides.isInvalid())
     return nullptr;
 
-  return cast<FunctionTemplateDecl>(
+  ClassTemplateDecl *Pattern =
+      Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
+  ContextRAII SavedContext(*this, Pattern->getTemplatedDecl());
+
+  auto *DG = cast<FunctionTemplateDecl>(
       Transform.buildSimpleDeductionGuide(ParamTypes));
+  SavedContext.pop();
+  return DG;
 }
 
 void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
diff --git a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp 
b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
index c44ec6918c7afb..38b6706595a116 100644
--- a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
+++ b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -std=c++20 -verify %s
-// expected-no-diagnostics
 
 template<class T> struct S {
     template<class U> struct N {
@@ -36,11 +35,14 @@ using NonTypeParam = decltype(ntp);
 using NonTypeParam = non_type_param<int>::B<int>;
 
 template<typename A, typename T>
-concept C = (sizeof(T) == sizeof(A));
+concept True = true;
+
+template<typename T>
+concept False = false;
 
 template<class X> struct concepts {
     template<class Y> struct B {
-        template<class K = X, C<K> Z> B(Y, Z);
+        template<class K = X, True<K> Z> B(Y, Z);
     };
 };
 
@@ -50,7 +52,7 @@ using Concepts = concepts<int>::B<int>;
 
 template<class X> struct requires_clause {
     template<class Y> struct B {
-        template<class Z> requires (sizeof(Z) == sizeof(X))
+        template<class Z> requires true
             B(Y, Z);
     };
 };
@@ -58,3 +60,27 @@ template<class X> struct requires_clause {
 requires_clause<int>::B req(1, 2);
 using RC = decltype(req);
 using RC = requires_clause<int>::B<int>;
+
+template<typename X> struct nested_init_list {
+    template<True<X> Y>
+    struct B {
+        X x;
+        Y y;
+    };
+
+    template<False F>
+    struct concept_fail { // #INIT_LIST_INNER_INVALID
+        X x;
+        F f;
+    };
+};
+
+nested_init_list<int>::B nil {1, 2};
+using NIL = decltype(nil);
+using NIL = nested_init_list<int>::B<int>;
+
+// expected-error@+1 {{no viable constructor or deduction guide for deduction 
of template arguments of 'concept_fail'}}
+nested_init_list<int>::concept_fail nil_invalid{1, ""};
+// expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: 
substitution failure [with F = const char *]: constraints not satisfied for 
class template 'concept_fail' [with F = const char *]}}
+// expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not 
viable: requires 1 argument, but 2 were provided}}
+// expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not 
viable: requires 0 arguments, but 2 were provided}}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to