[clang] [clang] CTAD alias: Respecte explicit deduction guides defined after the first use of the alias template. (PR #125478)
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 3 05:30:05 PST 2025
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/125478
>From 62328c6ab0c9965712aea1d484fca4afa1294acd Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Mon, 3 Feb 2025 11:55:17 +0100
Subject: [PATCH 1/2] [clang] CTAD alias: Respecte explicit deduction guides
defined after the first use of the alias template.
---
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 33 ++++++++++++++-----
clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 13 ++++++--
2 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 0d079677eecc56..f5884f964d6fbd 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -740,6 +740,24 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
return false;
}
+// Returns all source deduction guides associated with the declared
+// deduction guides that have the specified deduction guide name.
+llvm::DenseSet<const NamedDecl *> getSourceDeductionGuides(DeclarationName Name,
+ DeclContext *DC) {
+ assert(Name.getNameKind() ==
+ DeclarationName::NameKind::CXXDeductionGuideName &&
+ "name must be a deduction guide name");
+ llvm::DenseSet<const NamedDecl *> Result;
+ for (auto *D : DC->lookup(Name)) {
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ D = FTD->getTemplatedDecl();
+
+ if (const auto *GD = dyn_cast<CXXDeductionGuideDecl>(D))
+ Result.insert(GD->getSourceDeductionGuide());
+ }
+ return Result;
+}
+
// Build the associated constraints for the alias deduction guides.
// C++ [over.match.class.deduct]p3.3:
// The associated constraints ([temp.constr.decl]) are the conjunction of the
@@ -1191,13 +1209,10 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
if (AliasTemplate->isInvalidDecl())
return;
auto &Context = SemaRef.Context;
- // FIXME: if there is an explicit deduction guide after the first use of the
- // type alias usage, we will not cover this explicit deduction guide. fix this
- // case.
- if (hasDeclaredDeductionGuides(
- Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
- AliasTemplate->getDeclContext()))
- return;
+ auto SourceDeductionGuides = getSourceDeductionGuides(
+ Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+ AliasTemplate->getDeclContext());
+
auto [Template, AliasRhsTemplateArgs] =
getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
if (!Template)
@@ -1210,6 +1225,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
for (auto *G : Guides) {
if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(G)) {
+ if (SourceDeductionGuides.contains(DG))
+ continue;
// The deduction guide is a non-template function decl, we just clone it.
auto *FunctionType =
SemaRef.Context.getTrivialTypeSourceInfo(DG->getType());
@@ -1252,7 +1269,7 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
continue;
}
FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G);
- if (!F)
+ if (!F || SourceDeductionGuides.contains(F->getTemplatedDecl()))
continue;
// The **aggregate** deduction guides are handled in a different code path
// (DeclareAggregateDeductionGuideFromInitList), which involves the tricky
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index 2d43e46b9e3d76..6a004769a6d4d6 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -237,8 +237,17 @@ static_assert(__is_same(decltype(s.t), int));
// explicit deduction guide.
Foo(int) -> Foo<X>;
AFoo s2{i};
-// FIXME: the type should be X because of the above explicit deduction guide.
-static_assert(__is_same(decltype(s2.t), int));
+static_assert(__is_same(decltype(s2.t), X));
+
+
+template<class T>
+using BFoo = AFoo<T>;
+static_assert(__is_same(decltype(BFoo(i).t), X));
+
+
+Foo(double) -> Foo<int>;
+static_assert(__is_same(decltype(AFoo(1.0).t), int));
+static_assert(__is_same(decltype(BFoo(1.0).t), int));
} // namespace test16
namespace test17 {
>From 49be6d421bb2994d2c775a9f849d977d48d19f93 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Mon, 3 Feb 2025 14:29:06 +0100
Subject: [PATCH 2/2] Address review comments.
---
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index f5884f964d6fbd..e5931f4684a57d 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -752,8 +752,12 @@ llvm::DenseSet<const NamedDecl *> getSourceDeductionGuides(DeclarationName Name,
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
D = FTD->getTemplatedDecl();
- if (const auto *GD = dyn_cast<CXXDeductionGuideDecl>(D))
+ if (const auto *GD = dyn_cast<CXXDeductionGuideDecl>(D)) {
+ assert(GD->getSourceDeductionGuide() &&
+ "deduction guide for alias template must have a source deduction "
+ "guide");
Result.insert(GD->getSourceDeductionGuide());
+ }
}
return Result;
}
@@ -1209,14 +1213,14 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
if (AliasTemplate->isInvalidDecl())
return;
auto &Context = SemaRef.Context;
- auto SourceDeductionGuides = getSourceDeductionGuides(
- Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
- AliasTemplate->getDeclContext());
-
auto [Template, AliasRhsTemplateArgs] =
getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
if (!Template)
return;
+ auto SourceDeductionGuides = getSourceDeductionGuides(
+ Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+ AliasTemplate->getDeclContext());
+
DeclarationNameInfo NameInfo(
Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
More information about the cfe-commits
mailing list