Open
Description
On this code:
struct tuple {
int x[3];
};
template <class F>
void apply(F f, tuple v) {
return f(v.x[0], v.x[1], v.x[2]);
}
void Cartesian(auto x, auto y) {
apply([&](auto... xs) {
(apply([xs](auto... ys) {
(ys + ...);
}, y), ...);
}, x);
}
int main() {
auto x = tuple({1, 2, 3});
auto y = tuple({4, 5, 6});
Cartesian(x, y);
}
Clang will crash with a following assertion error:
clang++: /root/llvm-project/clang/lib/Sema/TreeTransform.h:15248: clang::ExprResult clang::TreeTransform<Derived>::TransformCXXFoldExpr(clang::CXXFoldExpr*) [with Derived = {anonymous}::TemplateInstantiator; clang::ExprResult = clang::ActionResult<clang::Expr*>]: Assertion `!Unexpanded.empty() && "Pack expansion without parameter packs?"' failed.
The problem arises because when substituting into inner lambdas, Clang will incorrectly loose the ContainsUnexpandedPack
dependency on a lambda expression. In turn, this confuses the CXXFoldExpr
that relies in this flag to distinguish left and right folds, which will pass the nullptr
expr to CollectUnexpandedParameterPacks
and cause it to not find any packs when transforming the fold expression, leading to an asssertion.
I have already been working on a fix for a few days and more sophisticated tests, so assigning to myself right away.