-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
[Clang] Fix handling of placeholder variables name in init captures #107055
Conversation
We were incorrectly not deduplicating results when looking up `_` which, for a lambda init capture, would result in an ambiguous lookup. The same bug caused some diagnostic notes to be emitted twice. Fixes llvm#107024
@llvm/pr-subscribers-clang Author: cor3ntin (cor3ntin) ChangesWe were incorrectly not deduplicating results when looking up The same bug caused some diagnostic notes to be emitted twice. Fixes #107024 Full diff: https://github.com/llvm/llvm-project/pull/107055.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fc940db4813948..af4388eada8e5a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -339,6 +339,7 @@ Bug Fixes to C++ Support
- Template parameter names are considered in the name lookup of out-of-line class template
specialization right before its declaration context. (#GH64082)
- Fixed a constraint comparison bug for friend declarations. (#GH78101)
+- Fix handling of ``_`` as the name of a lambda's init capture variable. (#GH107024)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 7a6a64529f52ec..d3d4bf27ae7283 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -570,7 +570,7 @@ void LookupResult::resolveKind() {
// For non-type declarations, check for a prior lookup result naming this
// canonical declaration.
- if (!D->isPlaceholderVar(getSema().getLangOpts()) && !ExistingI) {
+ if (!ExistingI) {
auto UniqueResult = Unique.insert(std::make_pair(D, I));
if (!UniqueResult.second) {
// We've seen this entity before.
diff --git a/clang/test/SemaCXX/cxx2c-placeholder-vars.cpp b/clang/test/SemaCXX/cxx2c-placeholder-vars.cpp
index 5cf66b48784e91..29ca3b5ef3df72 100644
--- a/clang/test/SemaCXX/cxx2c-placeholder-vars.cpp
+++ b/clang/test/SemaCXX/cxx2c-placeholder-vars.cpp
@@ -50,14 +50,16 @@ void f() {
void lambda() {
(void)[_ = 0, _ = 1] { // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}} \
- // expected-note 4{{placeholder declared here}}
+ // expected-note 2{{placeholder declared here}}
(void)_++; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
};
{
int _ = 12;
- (void)[_ = 0]{}; // no warning (different scope)
+ (void)[_ = 0]{ return _;}; // no warning (different scope)
}
+
+ auto GH107024 = [_ = 42]() { return _; }();
}
namespace global_var {
|
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.
One thing I'm not entirely clear about is why we would end up with two same placeholder Decl
s in LookupResult
.
It seems that IdResolver
results in two same duplicate Decls for such case, but I don't know why.
(However I'd still approve it because this reverts the condition to the state before the placeholder patch.)
I took a cursory look, and it seems that we pushed the same init capture to the scope chain three times:
llvm-project/clang/lib/Sema/SemaLambda.cpp Lines 1324 to 1327 in 6c59dfb
I'm confused if they're all necessary... |
@@ -1323,7 +1323,6 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, | |||
|
|||
if (C->Init.isUsable()) { | |||
addInitCapture(LSI, cast<VarDecl>(Var), C->Kind == LCK_ByRef); | |||
PushOnScopeChains(Var, CurScope, false); |
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.
Yeah, 2 is a duplicate of 1, but 3 is necessary because that constitutes a lambda body scope.
The second was clearly duplicated. But the body introduces a new scope wherein we inject the parameters - and we also need to reinject the captures to make sure they cannot be shadowed by a local variables [a = 0]
// capture scope
{
// body scope
int a = 42; // error!
}``` |
Should we backport this? |
I think so, yes. |
/cherry-pick eec1fac |
Failed to cherry-pick: eec1fac https://github.com/llvm/llvm-project/actions/runs/10688677657 Please manually backport the fix and push it to your github fork. Once this is done, please create a pull request |
…lvm#107055) We were incorrectly not deduplicating results when looking up `_` which, for a lambda init capture, would result in an ambiguous lookup. The same bug caused some diagnostic notes to be emitted twice. Fixes llvm#107024
For reference, the manual cherry pick is #107214. |
…lvm#107055) We were incorrectly not deduplicating results when looking up `_` which, for a lambda init capture, would result in an ambiguous lookup. The same bug caused some diagnostic notes to be emitted twice. Fixes llvm#107024
We were incorrectly not deduplicating results when looking up
_
which, for a lambda init capture, would result in an ambiguous lookup.The same bug caused some diagnostic notes to be emitted twice.
Fixes #107024