[clang] [Sema]Substitue parameter packs when deduced from function parameter (PR #79371)
Gábor Spaits via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 24 13:33:18 PST 2024
https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/79371
>From d4ca5c2fcb87f424be23efc4513df491403c3811 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Wed, 24 Jan 2024 21:21:26 +0100
Subject: [PATCH 1/2] [Sema]Substitue template parameter packs when deduced
from function parameter
---
clang/lib/Sema/SemaTemplateDeduction.cpp | 63 +++++++++++++++++++++++-
1 file changed, 62 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..46fa9eece3747a2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -730,6 +730,7 @@ class PackDeductionScope {
void addPack(unsigned Index) {
// Save the deduced template argument for the parameter pack expanded
// by this pack expansion, then clear out the deduction.
+ DeducedFromEarlierParameter = !Deduced[Index].isNull();
DeducedPack Pack(Index);
Pack.Saved = Deduced[Index];
Deduced[Index] = TemplateArgument();
@@ -858,6 +859,29 @@ class PackDeductionScope {
Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
}
+ std::optional<unsigned> getSavedPackSize(unsigned Index,
+ TemplateArgument Pattern) const {
+
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ if (Unexpanded.size() == 0 ||
+ Packs[0].Saved.getKind() != clang::TemplateArgument::Pack)
+ return {};
+ unsigned PackSize = Packs[0].Saved.pack_size();
+
+ if (std::all_of(Packs.begin() + 1, Packs.end(),
+ [&PackSize](auto P) {
+ return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+ }))
+ return PackSize;
+ return {};
+ }
+
+ /// Determine whether this pack has already been deduced from a previous
+ /// argument.
+ bool isDeducedFromEarlierParameter() const {return DeducedFromEarlierParameter;}
+
/// Determine whether this pack has already been partially expanded into a
/// sequence of (prior) function parameters / template arguments.
bool isPartiallyExpanded() { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
NewPack = Pack.DeferredDeduction;
Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
}
-
NamedDecl *Param = TemplateParams->getParam(Pack.Index);
if (Result.isNull()) {
Info.Param = makeTemplateParameter(Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
unsigned PackElements = 0;
bool IsPartiallyExpanded = false;
bool DeducePackIfNotAlreadyDeduced = false;
+ bool DeducedFromEarlierParameter = false;
+
/// The number of expansions, if we have a fully-expanded pack in this scope.
std::optional<unsigned> FixedNumExpansions;
+
SmallVector<DeducedPack, 2> Packs;
};
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// corresponding argument is a list?
PackScope.nextPackElement();
}
+ } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded() &&
+ PackScope.isDeducedFromEarlierParameter() &&
+ !isa<PackExpansionType>(ParamTypes[ParamIdx + 1])) {
+ // [temp.deduct.general#3]
+ // When all template arguments have been deduced
+ // or obtained from default template arguments, all uses of template
+ // parameters in the template parameter list of the template are
+ // replaced with the corresponding deduced or default argument values
+ //
+ // If we have a trailing parameter pack, that has been deduced perviously
+ // we substitute the pack here in a similar fashion as seen above with
+ // the trailing parameter packs. The main difference here is that, in
+ // this case we are not processing all of the remaining arguments. We
+ // are only process as many arguments as much we have in the already
+ // deduced parameter.
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+ if (Unexpanded.size() == 0)
+ continue;
+
+ std::optional<unsigned> ArgPosAfterSubstitution =
+ PackScope.getSavedPackSize(getDepthAndIndex(Unexpanded[0]).second,
+ ParamPattern);
+ if (!ArgPosAfterSubstitution)
+ continue;
+
+ unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
+ for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) {
+ ParamTypesForArgChecking.push_back(ParamPattern);
+ if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx,
+ /*ExplicitObjetArgument=*/false))
+ return Result;
+
+ PackScope.nextPackElement();
+ }
}
}
>From 52de421b998481105e5522a04ad9e39a4a6cbb82 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Wed, 24 Jan 2024 22:33:02 +0100
Subject: [PATCH 2/2] Format changes
---
clang/lib/Sema/SemaTemplateDeduction.cpp | 25 ++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 46fa9eece3747a2..e682ca6dc0f7d45 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -869,18 +869,19 @@ class PackDeductionScope {
return {};
unsigned PackSize = Packs[0].Saved.pack_size();
- if (std::all_of(Packs.begin() + 1, Packs.end(),
- [&PackSize](auto P) {
- return P.Saved.getKind() == TemplateArgument::Pack &&
- P.Saved.pack_size() == PackSize;
- }))
+ if (std::all_of(Packs.begin() + 1, Packs.end(), [&PackSize](auto P) {
+ return P.Saved.getKind() == TemplateArgument::Pack &&
+ P.Saved.pack_size() == PackSize;
+ }))
return PackSize;
return {};
}
/// Determine whether this pack has already been deduced from a previous
/// argument.
- bool isDeducedFromEarlierParameter() const {return DeducedFromEarlierParameter;}
+ bool isDeducedFromEarlierParameter() const {
+ return DeducedFromEarlierParameter;
+ }
/// Determine whether this pack has already been partially expanded into a
/// sequence of (prior) function parameters / template arguments.
@@ -4406,12 +4407,12 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// parameters in the template parameter list of the template are
// replaced with the corresponding deduced or default argument values
//
- // If we have a trailing parameter pack, that has been deduced perviously
- // we substitute the pack here in a similar fashion as seen above with
- // the trailing parameter packs. The main difference here is that, in
- // this case we are not processing all of the remaining arguments. We
- // are only process as many arguments as much we have in the already
- // deduced parameter.
+ // If we have a trailing parameter pack, that has been deduced
+ // perviously we substitute the pack here in a similar fashion as seen
+ // above with the trailing parameter packs. The main difference here is
+ // that, in this case we are not processing all of the remaining
+ // arguments. We are only process as many arguments as much we have in
+ // the already deduced parameter.
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
if (Unexpanded.size() == 0)
More information about the cfe-commits
mailing list