73 lines · cpp
1// RUN: %clang_cc1 -verify -fsyntax-only -std=c++20 -Wshadow %s2// RUN: %clang_cc1 -verify=all -fsyntax-only -std=c++20 -Wshadow-all %s3 4// Test for issue #68605: Inconsistent shadow warnings for lambda capture of structured bindings.5// 6// The issue was that structured binding lambda captures were incorrectly classified7// as regular shadow warnings (shown with -Wshadow) while regular parameter captures 8// were classified as uncaptured-local warnings (shown only with -Wshadow-all).9//10// This test validates that both VarDecl and BindingDecl lambda captures now 11// behave consistently: no warnings with -Wshadow, but uncaptured-local warnings 12// with -Wshadow-all.13 14namespace std {15 template<typename T> T&& move(T&& t) { return static_cast<T&&>(t); }16}17 18namespace issue_68605 {19 20// Simple pair-like struct for testing21struct Pair {22 int first;23 int second;24 Pair(int f, int s) : first(f), second(s) {}25};26 27// Test case 1: Regular parameter - consistent behavior28void foo1(Pair val) { // all-note {{previous declaration is here}}29 [val = std::move(val)](){}(); // all-warning {{declaration shadows a local variable}}30}31 32// Test case 2: Structured binding - now consistent with regular parameter33void foo2(Pair val) {34 auto [a,b] = val; // all-note {{previous declaration is here}}35 [a = std::move(a)](){}(); // all-warning {{declaration shadows a structured binding}}36}37 38// Test case 3: Multiple captures showing consistent behavior39void foo3() {40 Pair data{42, 100};41 auto [id, value] = data; // all-note 2{{previous declaration is here}}42 43 // Both show consistent uncaptured-local warnings with -Wshadow-all44 auto lambda1 = [id = id](){ return id; }; // all-warning {{declaration shadows a structured binding}}45 auto lambda2 = [value = value](){ return value; }; // all-warning {{declaration shadows a structured binding}}46}47 48// Test case 4: Mixed scenario showing consistent behavior49void foo4() {50 int regular_var = 10; // all-note {{previous declaration is here}}51 Pair pair_data{1, 2};52 auto [x, y] = pair_data; // all-note 2{{previous declaration is here}}53 54 // All captures now show consistent uncaptured-local warnings with -Wshadow-all55 auto lambda1 = [regular_var = regular_var](){}; // all-warning {{declaration shadows a local variable}}56 auto lambda2 = [x = x](){}; // all-warning {{declaration shadows a structured binding}}57 auto lambda3 = [y = y](){}; // all-warning {{declaration shadows a structured binding}}58}59 60// Test case 5: Ensure we don't break existing shadow detection for actual shadowing61void foo5() {62 int outer = 5; // expected-note {{previous declaration is here}} all-note {{previous declaration is here}}63 auto [a, b] = Pair{1, 2}; // expected-note {{previous declaration is here}} all-note {{previous declaration is here}}64 65 // This SHOULD still warn - it's actual shadowing within the lambda body66 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}}67 int outer = 10; // expected-warning {{declaration shadows a local variable}} all-warning {{declaration shadows a local variable}}68 int a = 20; // expected-warning {{declaration shadows a structured binding}} all-warning {{declaration shadows a structured binding}}69 };70}71 72} // namespace issue_6860573