xref: /llvm-project/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp (revision c90114c993ec1443360769a4d51963e3536de0ef)
1 // RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -D AVOID %s
2 // RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
3 // RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow-all %s
4 // RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
5 // RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -Wshadow-all %s
6 
foo(int param)7 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
8   int var = 0; // expected-note 1+ {{previous declaration is here}}
9 
10   // Avoid warnings for variables that aren't implicitly captured.
11   {
12 #ifdef AVOID
13     auto f1 = [=] { int var = 1; };  // no warning
14     auto f2 = [&] { int var = 2; };  // no warning
15     auto f3 = [=] (int param) { ; }; // no warning
16     auto f4 = [&] (int param) { ; }; // no warning
17     auto f5 = [=] { static int var = 1; };  // no warning
18     auto f6 = [&] { static int var = 2; };  // no warning
19 #else
20     auto f1 = [=] { int var = 1; };  // expected-warning {{declaration shadows a local variable}}
21     auto f2 = [&] { int var = 2; };  // expected-warning {{declaration shadows a local variable}}
22     auto f3 = [=] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
23     auto f4 = [&] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
24     auto f5 = [=] { static int var = 1; };  // expected-warning {{declaration shadows a local variable}}
25     auto f6 = [&] { static int var = 2; };  // expected-warning {{declaration shadows a local variable}}
26 #endif
27   }
28 
29   // Warn for variables that are implicitly captured.
30   {
31     auto f1 = [=] () {
32       {
33         int var = 1; // expected-warning {{declaration shadows a local variable}}
34       }
35       int x = var; // expected-note {{variable 'var' is captured here}}
36     };
37     auto f2 = [&]
38 #ifdef AVOID
39       (int param) {
40 #else
41       (int param) { // expected-warning {{declaration shadows a local variable}}
42 #endif
43       int x = var; // expected-note {{variable 'var' is captured here}}
44       int var = param; // expected-warning {{declaration shadows a local variable}}
45     };
46   }
47 
48   // Warn for variables that are explicitly captured when a lambda has a default
49   // capture specifier.
50   {
51     auto f1 = [=, &var] () { // expected-note {{variable 'var' is captured here}}
52       int x = param; // expected-note {{variable 'param' is captured here}}
53       int var = 0; // expected-warning {{declaration shadows a local variable}}
54       int param = 0; // expected-warning {{declaration shadows a local variable}}
55     };
56   }
57 
58   // Warn normally inside of lambdas.
59   auto l1 = [] { // expected-note {{previous declaration is here}}
60       int x = 1; // expected-note {{previous declaration is here}}
61       { int x = 2; } // expected-warning {{declaration shadows a local variable}}
62   };
63   auto l2 = [] (int x) { // expected-note {{previous declaration is here}}
64     { int x = 1; } // expected-warning {{declaration shadows a local variable}}
65   };
66 
67   // Avoid warnings for variables that aren't explicitly captured.
68   {
69 #ifdef AVOID
70     auto f1 = [] { int var = 1; }; // no warning
71     auto f2 = [] (int param) { ; }; // no warning
72     auto f3 = [param] () { int var = 1; }; // no warning
73     auto f4 = [var] (int param) { ; }; // no warning
74     auto f5 = [param] () { static int var = 1; }; // no warning
75     auto f6 = [] { static int var = 1; }; // no warning
76 #else
77     auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
78     auto f2 = [] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
79     auto f3 = [param] () { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
80     auto f4 = [var] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
81     auto f5 = [param] () { static int var = 1; }; // expected-warning {{declaration shadows a local variable}}
82     auto f6 = [] { static int var = 1; }; // expected-warning {{declaration shadows a local variable}}
83 #endif
84   };
85 
86   // Warn for variables that are explicitly captured.
87   {
88     auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
89       int var = 1; // expected-warning {{declaration shadows a local variable}}
90     };
91     auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
92      (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
93   }
94 
95   // Warn for variables defined in the capture list.
96   auto l3 = [z = var] { // expected-note {{previous declaration is here}}
97 #ifdef AVOID
98     int var = 1; // no warning
99 #else
100     int var = 1; // expected-warning {{declaration shadows a local variable}}
101 #endif
102     { int z = 1; } // expected-warning {{declaration shadows a local variable}}
103   };
104 #ifdef AVOID
105   auto l4 = [var = param] (int param) { ; }; // no warning
106 #else
107   auto l4 = [var = param](int param) { ; }; // expected-warning 2{{declaration shadows a local variable}}
108 #endif
109 
110   // Make sure that inner lambdas work as well.
111   auto l5 = [var, l1] { // expected-note {{variable 'l1' is explicitly captured here}}
112     auto l1 = [] { // expected-warning {{declaration shadows a local variable}}
113 #ifdef AVOID
114       int var = 1; // no warning
115 #else
116       int var = 1; // expected-warning {{declaration shadows a local variable}}
117 #endif
118     };
119 #ifdef AVOID
120     auto f1 = [] { int var = 1; }; // no warning
121     auto f2 = [=] { int var = 1; }; // no warning
122 #else
123     auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
124     auto f2 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
125 #endif
126     auto f3 = [var] // expected-note {{variable 'var' is explicitly captured here}}
127       { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
128     auto f4 = [&] {
129       int x = var; // expected-note {{variable 'var' is captured here}}
130       int var = 2; // expected-warning {{declaration shadows a local variable}}
131     };
132   };
133   auto l6 = [&] {
134     auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}}
135       int param = 0; // expected-warning {{declaration shadows a local variable}}
136     };
137   };
138   auto l7 = [&] {
139     auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}}
140       static int param = 0; // expected-warning {{declaration shadows a local variable}}
141     };
142   };
143 
144   // Generic lambda arguments should work.
145 #ifdef AVOID
146   auto g1 = [](auto param) { ; }; // no warning
147   auto g2 = [=](auto param) { ; }; // no warning
148 #else
149   auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
150   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
151 #endif
152   auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
153    (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
154 }
155 
156 void avoidWarningWhenRedefining() {
157   int a = 1;
158   auto l = [b = a] { // expected-note {{previous definition is here}}
159     // Don't warn on redefinitions.
160     int b = 0; // expected-error {{redefinition of 'b'}}
161   };
162 }
163 
164 namespace GH61105 {
165 void f() {
166   int y = 0;
167   int x = 0;
168 #if __cplusplus >= 202002L
169   auto l1 = [y]<typename y>(y) { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
170                                               // expected-note {{template parameter is declared here}}
171   auto l2 = [=]<typename y>() { int a = y; return 0; }; // expected-error {{'y' does not refer to a value}} \
172                                                         // expected-note {{declared here}}
173   auto l3 = [&, y]<typename y, typename>(y) { int a = x; return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
174                                                                       // expected-note {{template parameter is declared here}}
175   auto l4 = [x, y]<typename y, int x>() { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
176                                                        // expected-error {{declaration of 'x' shadows template parameter}} \
177                                                        // expected-note 2{{template parameter is declared here}}
178   auto l5 = []<typename y>(y) { return 0; }; // No diagnostic
179 #endif
180 }
181 }
182 
183 namespace GH71976 {
184 #ifdef AVOID
185 struct A {
186   int b = 5;
187   int foo() {
188     return [b = b]() { return b; }(); // no -Wshadow diagnostic, init-capture does not shadow b due to not capturing this
189   }
190 };
191 
192 struct B {
193   int a;
194   void foo() {
195     auto b = [a = this->a] {}; // no -Wshadow diagnostic, init-capture does not shadow a due to not capturing his
196   }
197 };
198 
199 struct C {
200   int b = 5;
201   int foo() {
202     return [a = b]() {
203       return [=, b = a]() { // no -Wshadow diagnostic, init-capture does not shadow b due to outer lambda
204         return b;
205       }();
206     }();
207   }
208 };
209 
210 #else
211 struct A {
212   int b = 5; // expected-note {{previous}}
213   int foo() {
214     return [b = b]() { return b; }(); // expected-warning {{declaration shadows a field}}
215   }
216 };
217 
218 struct B {
219   int a; // expected-note {{previous}}
220   void foo() {
221     auto b = [a = this->a] {}; // expected-warning {{declaration shadows a field}}
222   }
223 };
224 
225 struct C {
226   int b = 5; // expected-note {{previous}}
227   int foo() {
228     return [a = b]() {
229       return [=, b = a]() { // expected-warning {{declaration shadows a field}}
230         return b;
231       }();
232     }();
233   }
234 };
235 
236 struct D {
237   int b = 5; // expected-note {{previous}}
238   int foo() {
239     return [b = b, this]() { return b; }(); // expected-warning {{declaration shadows a field}}
240   }
241 };
242 
243 struct E {
244   int b = 5;
245   int foo() {
246     return [a = b]() { // expected-note {{previous}}
247       return [=, a = a]() { // expected-warning {{shadows a local}}
248         return a;
249       }();
250     }();
251   }
252 };
253 
254 #endif
255 
256 struct S {
257     int a ;
258 };
259 
260 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}}
264   }();
265 }
266 
267 }
268