zyn0217 wrote:
> I might be stupid but i still do not get why fold expressions are special,
> they should not be.
Sorry I was inaccurate suggesting fold expressions are special, it's actually
*constraints involving pack expansions* who are special. (I admit inventing
another `collectUnexpandedParameterPacks` overload for `CXXFoldExpr` is odd,
probably insufficent for the solution because we seem to have more problems -
as I observed a similar issue from your first example as well - regarding pack
expansion in terms of the constraints on lambdas.)
>
> ```cpp
> void f(auto...);
> template <class = void> void foo() {
> []<class... Is>() {
> f([]() requires (!C<Is>) {}()...);
> }.template operator()<char, int, float>();
>}
> ```
This is awkward: no compiler currently compiles it.
(https://gcc.godbolt.org/z/rce3rh7jK) And spuriously, both gcc and clang think
that there are no unexpanded parameter packs for expansion.
Regardless of whether this is conforming, the diagnostic here is simple to
explain: we didn't preserve the `ContainsUnexpandedParameterPack` flag while
transforming the LambdaExpr, so as an intuitive solution, we could just retain
the flag from `TransformLambdaExpr`:
(Though I didn't add the following to the patch yet, it doesn't solve the
problem and instead would cause a crash)
```cpp
Expr *TrailingRequires = E->getCallOperator()->getTrailingRequiresClause();
if (TrailingRequires)
LSI->ContainsUnexpandedParameterPack |=
TrailingRequires->containsUnexpandedParameterPack();
```
We still fail to evaluate the constraint because it ends up being dependent
even with proper template arguments. This is because the expression is not
expanded anywhere before evaluating the constraint, which is one step when we
forming up a CallExpr.
The situation could be slightly different (or rather, better?) if a fold
expression gets involved. We would still have a chance to expand the fold
expression into an expanded but unsubstituted state. So we can make them into
the constraint evaluation and substitute arguments there, and get a correct
result. So this is why it's convoluted: we probably miss out on some passes for
constraint packs: Maybe we need to expand them somewhere before evaluation, but
I'm not completely clear.
> ```cpp
> f<[]() requires (!C<Is>) {}()...>();
> //
> f({+[]() requires (!C<Is>) {}()...});
> // I am truly sorry.
> [ ...fs = +[]() requires (!C<Is>) {}()]() {
> (fs(),...);
> }
> ```
(I promise I won't forget them but let's consider them when we get around to
the constraints in the next patch. :)
https://github.com/llvm/llvm-project/pull/86265
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits