Skip to content

Commit 9da379e

Browse files
committed
Address comments
1 parent fb9fa67 commit 9da379e

File tree

3 files changed

+79
-50
lines changed

3 files changed

+79
-50
lines changed

clang/lib/Sema/SemaTemplateDeductionGuide.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,16 +1072,25 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
10721072
AliasRhsTemplateArgs, TDeduceInfo, DeduceResults,
10731073
/*NumberOfArgumentsMustMatch=*/false);
10741074

1075+
static auto IsNonDeducedArgument = [&](const DeducedTemplateArgument &TA) {
1076+
// The following cases indicate the template argument is non-deducible:
1077+
// 1. The result is null. E.g. When it comes from a default template
1078+
// argument that doesn't appear in the alias declaration.
1079+
// 2. The template parameter is a pack and that cannot be deduced from
1080+
// the arguments within the alias declaration.
1081+
// Non-deducible template parameters will persist in the transformed
1082+
// deduction guide.
1083+
return TA.isNull() || (TA.getKind() == TemplateArgument::Pack &&
1084+
TA.pack_size() == 1 && TA.pack_begin()->isNull());
1085+
};
1086+
10751087
SmallVector<TemplateArgument> DeducedArgs;
10761088
SmallVector<unsigned> NonDeducedTemplateParamsInFIndex;
10771089
// !!NOTE: DeduceResults respects the sequence of template parameters of
10781090
// the deduction guide f.
10791091
for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
10801092
const auto &D = DeduceResults[Index];
1081-
bool NonDeduced =
1082-
D.isNull() || (D.getKind() == TemplateArgument::Pack &&
1083-
D.pack_size() == 1 && D.pack_begin()->isNull());
1084-
if (!NonDeduced)
1093+
if (!IsNonDeducedArgument(D))
10851094
DeducedArgs.push_back(D);
10861095
else
10871096
NonDeducedTemplateParamsInFIndex.push_back(Index);
@@ -1145,10 +1154,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
11451154
Args.addOuterTemplateArguments(TransformedDeducedAliasArgs);
11461155
for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
11471156
const auto &D = DeduceResults[Index];
1148-
bool NonDeduced =
1149-
D.isNull() || (D.getKind() == TemplateArgument::Pack &&
1150-
D.pack_size() == 1 && D.pack_begin()->isNull());
1151-
if (NonDeduced) {
1157+
if (IsNonDeducedArgument(D)) {
11521158
// 2): Non-deduced template parameters would be substituted later.
11531159
continue;
11541160
}

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1487,7 +1487,7 @@ namespace {
14871487
return TA;
14881488
if (SemaRef.ArgumentPackSubstitutionIndex != -1)
14891489
return getPackSubstitutedTemplateArgument(SemaRef, TA);
1490-
assert(TA.pack_size() == 1 &&
1490+
assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
14911491
"unexpected pack arguments in template rewrite");
14921492
TemplateArgument Arg = *TA.pack_begin();
14931493
if (Arg.isPackExpansion())
@@ -1669,6 +1669,23 @@ namespace {
16691669
return inherited::TransformTemplateArgument(Input, Output, Uneval);
16701670
}
16711671

1672+
std::optional<unsigned> ComputeSizeOfPackExprWithoutSubstitution(
1673+
ArrayRef<TemplateArgument> PackArgs) {
1674+
// Don't do this when rewriting template parameters for CTAD:
1675+
// 1) The heuristic needs the unpacked Subst* nodes to figure out the
1676+
// expanded size, but this never applies since Subst* nodes are not
1677+
// created in rewrite scenarios.
1678+
//
1679+
// 2) The heuristic substitutes into the pattern with pack expansion
1680+
// suppressed, which does not meet the requirements for argument
1681+
// rewriting when template arguments include a non-pack matching against
1682+
// a pack, particularly when rewriting an alias CTAD.
1683+
if (TemplateArgs.isRewrite())
1684+
return std::nullopt;
1685+
1686+
return inherited::ComputeSizeOfPackExprWithoutSubstitution(PackArgs);
1687+
}
1688+
16721689
template<typename Fn>
16731690
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
16741691
FunctionProtoTypeLoc TL,

clang/lib/Sema/TreeTransform.h

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3660,7 +3660,8 @@ class TreeTransform {
36603660
return SemaRef.BuildCXXNoexceptExpr(Range.getBegin(), Arg, Range.getEnd());
36613661
}
36623662

3663-
bool HeuristicallyComputeSizeOfPackExpr() const { return true; }
3663+
std::optional<unsigned>
3664+
ComputeSizeOfPackExprWithoutSubstitution(ArrayRef<TemplateArgument> PackArgs);
36643665

36653666
/// Build a new expression to compute the length of a parameter pack.
36663667
ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack,
@@ -16030,6 +16031,49 @@ TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) {
1603016031
E->getNumExpansions());
1603116032
}
1603216033

16034+
template <typename Derived>
16035+
std::optional<unsigned>
16036+
TreeTransform<Derived>::ComputeSizeOfPackExprWithoutSubstitution(
16037+
ArrayRef<TemplateArgument> PackArgs) {
16038+
std::optional<unsigned> Result = 0;
16039+
for (const TemplateArgument &Arg : PackArgs) {
16040+
if (!Arg.isPackExpansion()) {
16041+
Result = *Result + 1;
16042+
continue;
16043+
}
16044+
16045+
TemplateArgumentLoc ArgLoc;
16046+
InventTemplateArgumentLoc(Arg, ArgLoc);
16047+
16048+
// Find the pattern of the pack expansion.
16049+
SourceLocation Ellipsis;
16050+
std::optional<unsigned> OrigNumExpansions;
16051+
TemplateArgumentLoc Pattern =
16052+
getSema().getTemplateArgumentPackExpansionPattern(ArgLoc, Ellipsis,
16053+
OrigNumExpansions);
16054+
16055+
// Substitute under the pack expansion. Do not expand the pack (yet).
16056+
TemplateArgumentLoc OutPattern;
16057+
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
16058+
if (getDerived().TransformTemplateArgument(Pattern, OutPattern,
16059+
/*Uneval*/ true))
16060+
return true;
16061+
16062+
// See if we can determine the number of arguments from the result.
16063+
std::optional<unsigned> NumExpansions =
16064+
getSema().getFullyPackExpandedSize(OutPattern.getArgument());
16065+
if (!NumExpansions) {
16066+
// No: we must be in an alias template expansion, and we're going to
16067+
// need to actually expand the packs.
16068+
Result = std::nullopt;
16069+
break;
16070+
}
16071+
16072+
Result = *Result + *NumExpansions;
16073+
}
16074+
return Result;
16075+
}
16076+
1603316077
template<typename Derived>
1603416078
ExprResult
1603516079
TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
@@ -16095,46 +16139,8 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
1609516139
}
1609616140

1609716141
// Try to compute the result without performing a partial substitution.
16098-
std::optional<unsigned> Result = 0;
16099-
for (const TemplateArgument &Arg : PackArgs) {
16100-
if (!getDerived().HeuristicallyComputeSizeOfPackExpr()) {
16101-
Result = std::nullopt;
16102-
break;
16103-
}
16104-
if (!Arg.isPackExpansion()) {
16105-
Result = *Result + 1;
16106-
continue;
16107-
}
16108-
16109-
TemplateArgumentLoc ArgLoc;
16110-
InventTemplateArgumentLoc(Arg, ArgLoc);
16111-
16112-
// Find the pattern of the pack expansion.
16113-
SourceLocation Ellipsis;
16114-
std::optional<unsigned> OrigNumExpansions;
16115-
TemplateArgumentLoc Pattern =
16116-
getSema().getTemplateArgumentPackExpansionPattern(ArgLoc, Ellipsis,
16117-
OrigNumExpansions);
16118-
16119-
// Substitute under the pack expansion. Do not expand the pack (yet).
16120-
TemplateArgumentLoc OutPattern;
16121-
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
16122-
if (getDerived().TransformTemplateArgument(Pattern, OutPattern,
16123-
/*Uneval*/ true))
16124-
return true;
16125-
16126-
// See if we can determine the number of arguments from the result.
16127-
std::optional<unsigned> NumExpansions =
16128-
getSema().getFullyPackExpandedSize(OutPattern.getArgument());
16129-
if (!NumExpansions) {
16130-
// No: we must be in an alias template expansion, and we're going to need
16131-
// to actually expand the packs.
16132-
Result = std::nullopt;
16133-
break;
16134-
}
16135-
16136-
Result = *Result + *NumExpansions;
16137-
}
16142+
std::optional<unsigned> Result =
16143+
getDerived().ComputeSizeOfPackExprWithoutSubstitution(PackArgs);
1613816144

1613916145
// Common case: we could determine the number of expansions without
1614016146
// substituting.

0 commit comments

Comments
 (0)