[clang] [clang][Sema] Fix false positive -Wshadow with structured binding captures (PR #157667)
Mariya Podchishchaeva via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 11 02:52:03 PDT 2025
================
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -std=c++20 -Wshadow %s
+// RUN: %clang_cc1 -verify=all -fsyntax-only -std=c++20 -Wshadow-all %s
+
+// Test for issue #68605: Inconsistent shadow warnings for lambda capture of structured bindings.
+//
+// The issue was that structured binding lambda captures were incorrectly classified
+// as regular shadow warnings (shown with -Wshadow) while regular parameter captures
+// were classified as uncaptured-local warnings (shown only with -Wshadow-all).
+//
+// This test validates that both VarDecl and BindingDecl lambda captures now
+// behave consistently: no warnings with -Wshadow, but uncaptured-local warnings
+// with -Wshadow-all.
+
+namespace std {
+ template<typename T> T&& move(T&& t) { return static_cast<T&&>(t); }
+}
+
+namespace issue_68605 {
+
+// Simple pair-like struct for testing
+struct Pair {
+ int first;
+ int second;
+ Pair(int f, int s) : first(f), second(s) {}
+};
+
+// Test case 1: Regular parameter - consistent behavior
+void foo1(Pair val) { // all-note {{previous declaration is here}}
+ [val = std::move(val)](){}(); // all-warning {{declaration shadows a local variable}}
+}
+
+// Test case 2: Structured binding - now consistent with regular parameter
+void foo2(Pair val) {
+ auto [a,b] = val; // all-note {{previous declaration is here}}
+ [a = std::move(a)](){}(); // all-warning {{declaration shadows a structured binding}}
+}
+
+// Test case 3: Multiple captures showing consistent behavior
+void foo3() {
+ Pair data{42, 100};
+ auto [id, value] = data; // all-note 2{{previous declaration is here}}
+
+ // Both show consistent uncaptured-local warnings with -Wshadow-all
+ auto lambda1 = [id = id](){ return id; }; // all-warning {{declaration shadows a structured binding}}
+ auto lambda2 = [value = value](){ return value; }; // all-warning {{declaration shadows a structured binding}}
+}
+
+// Test case 4: Mixed scenario showing consistent behavior
+void foo4() {
+ int regular_var = 10; // all-note {{previous declaration is here}}
+ Pair pair_data{1, 2};
+ auto [x, y] = pair_data; // all-note 2{{previous declaration is here}}
+
+ // All captures now show consistent uncaptured-local warnings with -Wshadow-all
+ auto lambda1 = [regular_var = regular_var](){}; // all-warning {{declaration shadows a local variable}}
+ auto lambda2 = [x = x](){}; // all-warning {{declaration shadows a structured binding}}
+ auto lambda3 = [y = y](){}; // all-warning {{declaration shadows a structured binding}}
+}
+
+// Test case 5: Ensure we don't break existing shadow detection for actual shadowing
+void foo5() {
+ int outer = 5; // expected-note {{previous declaration is here}} all-note {{previous declaration is here}}
+ auto [a, b] = Pair{1, 2}; // expected-note {{previous declaration is here}} all-note {{previous declaration is here}}
+
+ // This SHOULD still warn - it's actual shadowing within the lambda body
+ auto lambda = [outer, a](){ // expected-note {{variable 'outer' is explicitly captured here}} all-note {{variable 'outer' is explicitly captured here}} expected-note {{variable 'a' is explicitly captured here}} all-note {{variable 'a' is explicitly captured here}}
+ int outer = 10; // expected-warning {{declaration shadows a local variable}} all-warning {{declaration shadows a local variable}}
+ int a = 20; // expected-warning {{declaration shadows a structured binding}} all-warning {{declaration shadows a structured binding}}
+ };
+}
+
+} // namespace issue_68605
----------------
Fznamznon wrote:
Please add a newline at the end of the file.
https://github.com/llvm/llvm-project/pull/157667
More information about the cfe-commits
mailing list