Skip to content

Commit 4af8e19

Browse files
committed
[clang] CTAD alias: Respecte explicit deduction guides defined after the
first use of the alias template.
1 parent 6fd99de commit 4af8e19

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

clang/lib/Sema/SemaTemplateDeductionGuide.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,24 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
740740
return false;
741741
}
742742

743+
// Returns all source deduction guides associated with the declared
744+
// deduction guides that have the specified deduction guide name.
745+
llvm::DenseSet<const NamedDecl *> getSourceDeductionGuides(DeclarationName Name,
746+
DeclContext *DC) {
747+
assert(Name.getNameKind() ==
748+
DeclarationName::NameKind::CXXDeductionGuideName &&
749+
"name must be a deduction guide name");
750+
llvm::DenseSet<const NamedDecl *> Result;
751+
for (auto *D : DC->lookup(Name)) {
752+
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
753+
D = FTD->getTemplatedDecl();
754+
755+
if (const auto *GD = dyn_cast<CXXDeductionGuideDecl>(D))
756+
Result.insert(GD->getSourceDeductionGuide());
757+
}
758+
return Result;
759+
}
760+
743761
// Build the associated constraints for the alias deduction guides.
744762
// C++ [over.match.class.deduct]p3.3:
745763
// The associated constraints ([temp.constr.decl]) are the conjunction of the
@@ -1191,13 +1209,10 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
11911209
if (AliasTemplate->isInvalidDecl())
11921210
return;
11931211
auto &Context = SemaRef.Context;
1194-
// FIXME: if there is an explicit deduction guide after the first use of the
1195-
// type alias usage, we will not cover this explicit deduction guide. fix this
1196-
// case.
1197-
if (hasDeclaredDeductionGuides(
1198-
Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
1199-
AliasTemplate->getDeclContext()))
1200-
return;
1212+
auto SourceDeductionGuides = getSourceDeductionGuides(
1213+
Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
1214+
AliasTemplate->getDeclContext());
1215+
12011216
auto [Template, AliasRhsTemplateArgs] =
12021217
getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
12031218
if (!Template)
@@ -1210,6 +1225,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
12101225

12111226
for (auto *G : Guides) {
12121227
if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(G)) {
1228+
if (SourceDeductionGuides.contains(DG))
1229+
continue;
12131230
// The deduction guide is a non-template function decl, we just clone it.
12141231
auto *FunctionType =
12151232
SemaRef.Context.getTrivialTypeSourceInfo(DG->getType());
@@ -1252,7 +1269,7 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
12521269
continue;
12531270
}
12541271
FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G);
1255-
if (!F)
1272+
if (!F || SourceDeductionGuides.contains(F->getTemplatedDecl()))
12561273
continue;
12571274
// The **aggregate** deduction guides are handled in a different code path
12581275
// (DeclareAggregateDeductionGuideFromInitList), which involves the tricky

clang/test/SemaCXX/cxx20-ctad-type-alias.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,17 @@ static_assert(__is_same(decltype(s.t), int));
237237
// explicit deduction guide.
238238
Foo(int) -> Foo<X>;
239239
AFoo s2{i};
240-
// FIXME: the type should be X because of the above explicit deduction guide.
241-
static_assert(__is_same(decltype(s2.t), int));
240+
static_assert(__is_same(decltype(s2.t), X));
241+
242+
243+
template<class T>
244+
using BFoo = AFoo<T>;
245+
static_assert(__is_same(decltype(BFoo(i).t), X));
246+
247+
248+
Foo(double) -> Foo<int>;
249+
static_assert(__is_same(decltype(AFoo(1.0).t), int));
250+
static_assert(__is_same(decltype(BFoo(1.0).t), int));
242251
} // namespace test16
243252

244253
namespace test17 {

0 commit comments

Comments
 (0)