// 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 T&& move(T&& t) { return static_cast(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