[clang] [clang] Fix CTAD for aggregates for nested template classes (PR #78387)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 16 19:46:13 PST 2024
https://github.com/antangelo created https://github.com/llvm/llvm-project/pull/78387
Use the template pattern in determining whether to synthesize the aggregate deduction guide, and update DeclareImplicitDeductionGuideFromInitList to substitute outer template arguments.
Fixes #77599
>From 50a9a2e9eeb8af3c36035ad167c224302c8ae269 Mon Sep 17 00:00:00 2001
From: Antonio Abbatangelo <contact at antangelo.com>
Date: Mon, 15 Jan 2024 22:50:58 -0500
Subject: [PATCH] [clang] Fix CTAD for aggregates for nested template classes
Use the template pattern in determining whether to synthesize the
aggregate deduction guide, and update DeclareImplicitDeductionGuideFromInitList
to substitute outer template arguments.
---
clang/docs/ReleaseNotes.rst | 3 +++
clang/lib/Sema/SemaInit.cpp | 9 +++++++-
clang/lib/Sema/SemaTemplate.cpp | 21 +++++++++++++++----
.../nested-implicit-deduction-guides.cpp | 19 ++++++++++++++++-
4 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1eba8ab5590c52..db589beb46aadb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -928,6 +928,9 @@ Bug Fixes to C++ Support
(`#57410 <https://github.com/llvm/llvm-project/issues/57410>`_) and
(`#76604 <https://github.com/llvm/llvm-project/issues/57410>`_)
+- 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 408ee5f775804b..48235941f62aa2 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -10718,7 +10718,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 80a48c268a648b..8c2199c36f0fe3 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..f3af6e8d6c17da 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 {
@@ -58,3 +57,21 @@ 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<C<X> Y>
+ struct B { // #INIT_LIST_INNER
+ X x;
+ Y y;
+ };
+};
+
+nested_init_list<int>::B nil {1, 2};
+using NIL = decltype(nil);
+using NIL = nested_init_list<int>::B<int>;
+
+// expected-error at +1 {{no viable constructor or deduction guide for deduction of template arguments of 'B'}}
+nested_init_list<int>::B nil_invalid {1, ""};
+// expected-note@#INIT_LIST_INNER {{candidate template ignored: substitution failure [with Y = const char *]: constraints not satisfied for class template 'B' [with Y = const char *]}}
+// expected-note@#INIT_LIST_INNER {{candidate function template not viable: requires 1 argument, but 2 were provided}}
+// expected-note@#INIT_LIST_INNER {{candidate function template not viable: requires 0 arguments, but 2 were provided}}
More information about the cfe-commits
mailing list