-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[clang] Avoid -Wshadow warning when init-capture named same as class field #74512
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
…field Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes llvm#71976
@llvm/pr-subscribers-clang Author: Mariya Podchishchaeva (Fznamznon) ChangesShadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes #71976 Full diff: https://github.com/llvm/llvm-project/pull/74512.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 828dd10e3d6db..7ac81e16492d1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -655,6 +655,9 @@ Bug Fixes in This Version
Fixes (`#64467 <https://github.com/llvm/llvm-project/issues/64467>`_)
- Clang's ``-Wchar-subscripts`` no longer warns on chars whose values are known non-negative constants.
Fixes (`#18763 <https://github.com/llvm/llvm-project/issues/18763>`_)
+- Clang's ``-Wshadow`` no longer warns when init-capture named same as class
+ field.
+ Fixes (`#71976 <https://github.com/llvm/llvm-project/issues/71976>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f12424d33b7da..65d095b2431dd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8395,10 +8395,11 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
unsigned WarningDiag = diag::warn_decl_shadow;
SourceLocation CaptureLoc;
- if (isa<VarDecl>(D) && isa<VarDecl>(ShadowedDecl) && NewDC &&
- isa<CXXMethodDecl>(NewDC)) {
+ if (isa<VarDecl>(D) && NewDC && isa<CXXMethodDecl>(NewDC)) {
if (const auto *RD = dyn_cast<CXXRecordDecl>(NewDC->getParent())) {
if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent())) {
+ if (!isa<VarDecl>(ShadowedDecl))
+ return;
if (RD->getLambdaCaptureDefault() == LCD_None) {
// Try to avoid warnings for lambdas with an explicit capture list.
const auto *LSI = cast<LambdaScopeInfo>(getCurFunction());
@@ -8416,7 +8417,8 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
}
}
- if (cast<VarDecl>(ShadowedDecl)->hasLocalStorage()) {
+ if (const auto *VD = dyn_cast<VarDecl>(ShadowedDecl);
+ VD && VD->hasLocalStorage()) {
// A variable can't shadow a local variable in an enclosing scope, if
// they are separated by a non-capturing declaration context.
for (DeclContext *ParentDC = NewDC;
diff --git a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
index bda6a65c02168..58af7a2e65c55 100644
--- a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -179,3 +179,21 @@ void f() {
#endif
}
}
+
+namespace GH71976 {
+struct A {
+ int b = 5;
+ int foo() {
+ return [b = b]() { return b; }();
+ }
+};
+
+struct B {
+ int a;
+ void foo() {
+ auto b = [a = this->a] {
+
+ };
+ }
+};
+}
|
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 modulo nitpick.
Thanks a lot for the quick fix
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 w/ minor comments
clang/lib/Sema/SemaDecl.cpp
Outdated
if (const auto *RD = dyn_cast<CXXRecordDecl>(NewDC->getParent())) { | ||
if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent())) { | ||
if (!isa<VarDecl>(ShadowedDecl)) |
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.
Maybe a comment here along the lines of "if it is not VarDecl then it can not shadow" I am not sure if that implies it must be a capture but I think it does.
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.
You mean add a comment saying that it is a case when an init-capture references class field?
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, just a comment to explain why ShadownDecl
not being a VarDecl
matters here.
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.
I changed this all, so probably not relevant anymore.
I seem to be the only one, but I don't understand how this isn't shadowing. The whole point of the shadowing warning is to avoid confusion about which variable is actually used, which IMO could very well be the case here. I think it would be much better to get a new flag to disable this if it's not wanted than to make it impossible to warn on this shadowing constellation. |
In the case that is being fixed, a field is not available in lambda's body without capturing this, so there is no such confusion and no shadowing, I think. |
@cor3ntin , @shafik WDYT about
Should we still emit shadowing warning in case lambda captured this and has an init-capture with the same name as a class field? |
@philnik777 I agree strongly with @Fznamznon.
Yes, we should probably do that. (sorry for the very delayed reply, it fell off my radar) |
I don't disagree that this is technically not shadowing, but I don't think that's clear from a users perspective. e.g. void someFunc(int someVal) {
// assume 100 LoC here
auto someLambda = [](int someVal) {
// another 100 LoC here
return someVal + 40; // IMO it's trivial to confuse this with the `someVal` from `someFunc`
};
} It looks like Clang even has a warning for this specific case and GCC considers it shadowing too: https://godbolt.org/z/Y16njoPxh, which makes me think that people want this - at least as a separate flag. |
I already came across |
I'm struggling with detecting the following case:
Since init capture is checked for shadowing before this capture reached, lambda info doesn't yet know about incoming this capture. There is delayed shadowing reporting for lambdas in |
Ok, now it emits |
Ping. |
Ping! |
if (const auto *RD = dyn_cast<CXXRecordDecl>(NewDC->getParent())) { | ||
if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent())) { | ||
if (RD->getLambdaCaptureDefault() == LCD_None) { | ||
// Try to avoid warnings for lambdas with an explicit capture list. | ||
if (const auto *VD = dyn_cast<VarDecl>(ShadowedDecl)) { |
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.
Structured bindings aren't always VarDecl (But ValueDecl) so I guess we never diagnosed them !
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.
Well, If we want to, I would prefer doing that in a separate PR.
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.
We currently warn on that actually
https://compiler-explorer.com/z/d4W37n9Mn
Can you test that we still do?
The rest of the changes LGTM
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.
Ok, added.
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.
Thanks!
It surprises me that it works, but great!
I looked through and don't see anything of concern to me that you haven't covered. I am on the fence as to whether this warning makes sense to have in this situation. The point of the warning isn't that the language has a problem, it is that it is potentially confusing to readers. And I'm not sure that it STOPS being confusing because of the lack of a capture of 'this'. |
For that reason, I didn't fully disable the warning, and put it under |
Relaxes incorrect shadowing warning for fields detected as being shadowed in lambdas that don't capture `this`.
…field (llvm#74512) Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes llvm#71976
…field (llvm#74512) Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes llvm#71976
…field (llvm#74512) Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes llvm#71976
…field (llvm#74512) Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes llvm#71976
…field (llvm#74512) Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes llvm#71976
…field (llvm#74512) Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this. Fixes llvm#71976
Shadowing warning doesn't make much sense since field is not available in lambda's body without capturing this.
Fixes #71976