-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][Sema] Avoid non-empty unexpanded pack assertion for FunctionParmPackExpr #69224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: None (zyn0217) Changes…ctUnexpandedParameterPacksVisitor Closes #61460. We have FunctionParmPackExpr that serves as the unexpanded expression but from which the visitor collects none, which may lead to assertion failure during the template instantiation. Actually, we don't need to assert this condition since we would do nothing in the subsequent DiagnoseUnexpandedParameterPacks call even if unsatisfied. Full diff: https://github.com/llvm/llvm-project/pull/69224.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9782c123f4c9372..0c70ddf0e9a8b1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -397,6 +397,8 @@ Bug Fixes in This Version
operator in C. No longer issuing a confusing diagnostic along the lines of
"incompatible operand types ('foo' and 'foo')" with extensions such as matrix
types. Fixes (`#69008 <https://github.com/llvm/llvm-project/issues/69008>`_)
+- Fixed an issue that a benign assertion might hit when instantiating a pack expansion
+ inside a lambda. (`#61460 <https://github.com/llvm/llvm-project/issues/61460>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index dfcc78dafdc4c31..b8912b2ad8a372d 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -388,9 +388,8 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
return false;
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
- T->getTypeLoc());
- assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseTypeLoc(T->getTypeLoc());
return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
}
@@ -404,7 +403,6 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
- assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded);
}
@@ -442,8 +440,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
- .TraverseNestedNameSpecifier(SS.getScopeRep());
- assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ .TraverseNestedNameSpecifier(SS.getScopeRep());
return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(),
UPPC, Unexpanded);
}
@@ -479,8 +476,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
- .TraverseType(NameInfo.getName().getCXXNameType());
- assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ .TraverseType(NameInfo.getName().getCXXNameType());
return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded);
}
@@ -493,8 +489,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
- .TraverseTemplateName(Template);
- assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ .TraverseTemplateName(Template);
return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
}
@@ -506,8 +501,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded)
- .TraverseTemplateArgumentLoc(Arg);
- assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ .TraverseTemplateArgumentLoc(Arg);
return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded);
}
diff --git a/clang/test/SemaCXX/pr61460.cpp b/clang/test/SemaCXX/pr61460.cpp
new file mode 100644
index 000000000000000..ee9d1db4bb09486
--- /dev/null
+++ b/clang/test/SemaCXX/pr61460.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++17 %s -fsyntax-only -verify
+// expected-no-diagnostics
+template <typename... Ts> void g(Ts... p1s) {
+ (void)[&](auto... p2s) { ([&] { p1s; p2s; }, ...); };
+}
+void f1() {
+ g();
+}
|
@cor3ntin : Lambda stuff, I think you're more familiar than I am with this. Mind taking a pass? |
I think the issue here is that we make the assumption that a full expression cannot contain an unexpanded pack Maybe instead of removing the assert entirely we could check whether one of the enclosing scope is a lambda. While I think the change would be correct, i also think the assert is useful and I'm a bit concerned that removing it entirely will create problems down the line. so i would encouraging researching assert((!Unexpanded.empty() || enclosedInAnOtherExpression()) && "Unable to find unexpanded parameter packs"); where Can we run into similar problems with statement expressions ? (I don't think so as they don't have parameter or capture list) |
Sorry for my late update - I've had a busy week ;)
+1. and it looks like we don't allow expanding a pack outside a statement expression, which more or less prevents the appearance of
Instead of putting it inside an assertion, how about adding a check for FunctionParmPackExpr separately? I mean, if (auto *Expr = dyn_cast<FunctionParmPackExpr>(E); Expr && getEnclosingLambda())
return false; to bail out only inside the |
If that works it would be fine with me, yes |
697d116
to
8cf9e71
Compare
Looks generally good to me. can you remove the whitespace only changes? thanks! |
Done. Sorry for leaving irrelevant changes ;) |
// Exception: The `CollectUnexpandedParameterPacksVisitor` collects nothing | ||
// from a FunctionParmPackExpr. In the context where the collector is being | ||
// used such as `collectUnexpandedParameterPacks`, this type of expression | ||
// is not expected to be collected. | ||
// | ||
// Nonetheless, this function for diagnosis is still called anyway during | ||
// template instantiation, with an expression of such a type if we're inside a | ||
// lambda with unexpanded parameters. | ||
// | ||
// Rule out this case to prevent the assertion failure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Exception: The `CollectUnexpandedParameterPacksVisitor` collects nothing | |
// from a FunctionParmPackExpr. In the context where the collector is being | |
// used such as `collectUnexpandedParameterPacks`, this type of expression | |
// is not expected to be collected. | |
// | |
// Nonetheless, this function for diagnosis is still called anyway during | |
// template instantiation, with an expression of such a type if we're inside a | |
// lambda with unexpanded parameters. | |
// | |
// Rule out this case to prevent the assertion failure. | |
// CollectUnexpandedParameterPacksVisitor does not expect to see a FunctionParmPackExpr, but | |
// diagnosing unexpected parameter packs may still see such an expression in a lambda body. We'll | |
// bail out early in this case to avoid triggering an assertion. |
Slight rewording.
…armPackExpr Closes llvm#61460. We have FunctionParmPackExpr that serves as the unexpanded expression but from which the visitor collects none, which may lead to assertion failure during the template instantiation.
Thank you folks for the suggestions! I've updated, PTAL. :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks
…armPackExpr (llvm#69224) Closes llvm#61460. We have FunctionParmPackExpr that serves as the unexpanded expression but from which the visitor collects none, which may lead to assertion failure during the template instantiation.
…edParameterPack This is a follow-up for llvm#69224, where the previous fix failed to handle the parentheses around the expression. Fixes llvm#86361.
`FunctionParmPackExpr`s are peculiar in that they have to be of unexpanded dependency while they don't introduce any unexpanded packs. So this patch rules them out in the non-empty pack assertion in `DiagnoseUnexpandedParameterPack()`. There was a fix #69224, but that turned out to be insufficient. I also moved the separate tests to a pre-existing file. Fixes #86361
Closes #61460.
We have FunctionParmPackExpr that serves as the unexpanded expression but from which the visitor collects none, which may lead to assertion failure during the template instantiation.