================
@@ -1394,7 +1395,22 @@ namespace {
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
bool &ShouldExpand, bool &RetainExpansion,
- std::optional<unsigned> &NumExpansions) {
+ std::optional<unsigned> &NumExpansions,
+ bool ForConstraints = false) {
+ if (ForConstraints) {
+ LambdaScopeInfo *LSI = getSema().getCurLambda();
+ if (LSI) {
+ MultiLevelTemplateArgumentList MLTAL =
+ getSema().getTemplateInstantiationArgs(
+ LSI->CallOperator, /*DC=*/nullptr, /*Final=*/false,
+ /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
+ return getSema().CheckParameterPacksForExpansion(
+ EllipsisLoc, PatternRange, Unexpanded, MLTAL, ShouldExpand,
+ RetainExpansion, NumExpansions);
+ }
----------------
zyn0217 wrote:
This is the most convoluted part in this patch. Basically, this targets for a
situation where unexpanded packs appear in a trailing constraint. On the basis
of our evaluation strategy, we need the complete template arguments, (which are
typically relative to the primary template, as opposed to other instantiation
algorithm where we usually need the template arguments relative to the parent
specializations.) whereas we don't always have them at the time expanding a
CXXFoldExpr.
For example, suppose we have
```cpp
template <class = void> void foo() {
[]<class... Is>() {
([]()
requires (!C<Is>)
{}(),
...);
}.template operator()<char, int, float>();
}
```
We would only have one level template arguments, which is `<char, int, float>`
when the inner fold expression gets expanded. Since we always preserve the
constraint expressions until we evaluate them, we would thereafter have the
inner lambda being unexpanded, which is wrong because, later we need to
evaluate an expanded constraint when forming CallExprs.
So, one way is to teach the transformation to handle the constraints separately:
If we have only a constraint that contains unexpanded packs, we need to
*expand* the expression because we don't actually need to use the constraint
immediately. (in other words, the untransformed constraint shouldn't impact the
expansion)
And vice versa: if we have combined constraints and other unexpanded packs, we
just do the usual: we could hold off on the expansion until we hit the point
where only unexpanded constraints are left, which boils down to the above case.
https://github.com/llvm/llvm-project/pull/86265
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits