Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6aa3e64

Browse files
committed
[clang][Sema] Fix false positive -Wshadow with structured binding captures
Previously, lambda init captures that captured structured bindings would incorrectly emit shadow warnings, even though regular parameter captures don't emit such warnings. This created inconsistent behavior: ```cpp void foo1(std::pair<int, int> val) { [val = val](){}(); // No warning (correct) } void foo2(std::pair<int, int> val) { auto [a, b] = val; [a = a](){}(); // Warning (incorrect) } ``` The fix modifies getShadowedDeclaration() for VarDecl to return nullptr when a lambda init capture would shadow a BindingDecl, ensuring consistent behavior between regular captures and structured binding captures.
1 parent a0b8d54 commit 6aa3e64

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8410,6 +8410,12 @@ NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D,
84108410
return nullptr;
84118411

84128412
NamedDecl *ShadowedDecl = R.getFoundDecl();
8413+
8414+
// Don't warn when lambda captures shadow structured bindings.
8415+
// This ensures consistency with regular parameter captures.
8416+
if (isa<BindingDecl>(ShadowedDecl) && D->isInitCapture())
8417+
return nullptr;
8418+
84138419
return isa<VarDecl, FieldDecl, BindingDecl>(ShadowedDecl) ? ShadowedDecl
84148420
: nullptr;
84158421
}

clang/test/SemaCXX/PR68605.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// RUN: %clang_cc1 -verify -fsyntax-only -std=c++20 -Wshadow %s
2+
3+
// Test for issue #68605: False positive warning with `-Wshadow` when using
4+
// structured binding and lambda capture.
5+
//
6+
// The issue is that structured bindings should behave consistently with
7+
// regular variables when used in lambda captures - no shadow warning should
8+
// be emitted when a lambda capture variable has the same name as the captured
9+
// structured binding, just like with regular parameters.
10+
11+
namespace std {
12+
template<typename T> T&& move(T&& t) { return static_cast<T&&>(t); }
13+
}
14+
15+
namespace issue_68605 {
16+
17+
// Simple pair-like struct for testing
18+
struct Pair {
19+
int first;
20+
int second;
21+
Pair(int f, int s) : first(f), second(s) {}
22+
};
23+
24+
// Test case 1: Regular parameter - should NOT produce warning (baseline)
25+
void foo1(Pair val) {
26+
[val = std::move(val)](){}(); // No warning expected
27+
}
28+
29+
// Test case 2: Structured binding - should NOT produce warning
30+
void foo2(Pair val) {
31+
auto [a,b] = val;
32+
[a = std::move(a)](){}(); // No warning - consistent with regular parameter behavior
33+
}
34+
35+
// Test case 3: More complex example with multiple captures
36+
void foo3() {
37+
Pair data{42, 100};
38+
auto [id, value] = data;
39+
40+
// Both of these should NOT produce warnings
41+
auto lambda1 = [id = id](){ return id; }; // No warning
42+
auto lambda2 = [value = value](){ return value; }; // No warning
43+
}
44+
45+
// Test case 4: Mixed scenario with regular var and structured binding
46+
void foo4() {
47+
int regular_var = 10;
48+
Pair pair_data{1, 2};
49+
auto [x, y] = pair_data;
50+
51+
// Regular variable capture - no warning expected (current behavior)
52+
auto lambda1 = [regular_var = regular_var](){};
53+
54+
// Structured binding captures - should be consistent
55+
auto lambda2 = [x = x](){}; // No warning - consistent behavior
56+
auto lambda3 = [y = y](){}; // No warning - consistent behavior
57+
}
58+
59+
// Test case 5: Ensure we don't break existing shadow detection for actual shadowing
60+
void foo5() {
61+
int outer = 5; // expected-note {{previous declaration is here}}
62+
auto [a, b] = Pair{1, 2}; // expected-note {{previous declaration is here}}
63+
64+
// This SHOULD still warn - it's actual shadowing within the lambda body
65+
auto lambda = [outer, a](){ // expected-note {{variable 'outer' is explicitly captured here}}
66+
int outer = 10; // expected-warning {{declaration shadows a local variable}}
67+
int a = 20; // expected-warning {{declaration shadows a structured binding}}
68+
};
69+
}
70+
71+
} // namespace issue_68605

clang/test/SemaCXX/warn-shadow-in-lambdas.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,8 @@ struct S {
258258
};
259259

260260
int foo() {
261-
auto [a] = S{0}; // expected-note {{previous}} \
262-
// cxx14-warning {{decomposition declarations are a C++17 extension}}
263-
[a = a] () { // expected-warning {{declaration shadows a structured binding}}
261+
auto [a] = S{0}; // cxx14-warning {{decomposition declarations are a C++17 extension}}
262+
[a = a] () { // No warning - consistent with regular parameter captures
264263
}();
265264
}
266265

0 commit comments

Comments
 (0)