xref: /llvm-project/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp (revision 0fb84bc7fdec1c20c2461e54d5c994939fe5b47f)
1 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
2 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
3 // RUN: %clang_cc1 -std=c++14 -verify -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 
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 #else
18     auto f1 = [=] { int var = 1; };  // expected-warning {{declaration shadows a local variable}}
19     auto f2 = [&] { int var = 2; };  // expected-warning {{declaration shadows a local variable}}
20     auto f3 = [=] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
21     auto f4 = [&] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
22 #endif
23   }
24 
25   // Warn for variables that are implicitly captured.
26   {
27     auto f1 = [=] () {
28       {
29         int var = 1; // expected-warning {{declaration shadows a local variable}}
30       }
31       int x = var; // expected-note {{variable 'var' is captured here}}
32     };
33     auto f2 = [&]
34 #ifdef AVOID
35       (int param) {
36 #else
37       (int param) { // expected-warning {{declaration shadows a local variable}}
38 #endif
39       int x = var; // expected-note {{variable 'var' is captured here}}
40       int var = param; // expected-warning {{declaration shadows a local variable}}
41     };
42   }
43 
44   // Warn for variables that are explicitly captured when a lambda has a default
45   // capture specifier.
46   {
47     auto f1 = [=, &var] () { // expected-note {{variable 'var' is captured here}}
48       int x = param; // expected-note {{variable 'param' is captured here}}
49       int var = 0; // expected-warning {{declaration shadows a local variable}}
50       int param = 0; // expected-warning {{declaration shadows a local variable}}
51     };
52   }
53 
54   // Warn normally inside of lambdas.
55   auto l1 = [] { // expected-note {{previous declaration is here}}
56       int x = 1; // expected-note {{previous declaration is here}}
57       { int x = 2; } // expected-warning {{declaration shadows a local variable}}
58   };
59   auto l2 = [] (int x) { // expected-note {{previous declaration is here}}
60     { int x = 1; } // expected-warning {{declaration shadows a local variable}}
61   };
62 
63   // Avoid warnings for variables that aren't explicitly captured.
64   {
65 #ifdef AVOID
66     auto f1 = [] { int var = 1; }; // no warning
67     auto f2 = [] (int param) { ; }; // no warning
68     auto f3 = [param] () { int var = 1; }; // no warning
69     auto f4 = [var] (int param) { ; }; // no warning
70 #else
71     auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
72     auto f2 = [] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
73     auto f3 = [param] () { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
74     auto f4 = [var] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
75 #endif
76   };
77 
78   // Warn for variables that are explicitly captured.
79   {
80     auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
81       int var = 1; // expected-warning {{declaration shadows a local variable}}
82     };
83     auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
84      (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
85   }
86 
87   // Warn for variables defined in the capture list.
88   auto l3 = [z = var] { // expected-note {{previous declaration is here}}
89 #ifdef AVOID
90     int var = 1; // no warning
91 #else
92     int var = 1; // expected-warning {{declaration shadows a local variable}}
93 #endif
94     { int z = 1; } // expected-warning {{declaration shadows a local variable}}
95   };
96 #ifdef AVOID
97   auto l4 = [var = param] (int param) { ; }; // no warning
98 #else
99   auto l4 = [var = param](int param) { ; }; // expected-warning 2{{declaration shadows a local variable}}
100 #endif
101 
102   // Make sure that inner lambdas work as well.
103   auto l5 = [var, l1] { // expected-note {{variable 'l1' is explicitly captured here}}
104     auto l1 = [] { // expected-warning {{declaration shadows a local variable}}
105 #ifdef AVOID
106       int var = 1; // no warning
107 #else
108       int var = 1; // expected-warning {{declaration shadows a local variable}}
109 #endif
110     };
111 #ifdef AVOID
112     auto f1 = [] { int var = 1; }; // no warning
113     auto f2 = [=] { int var = 1; }; // no warning
114 #else
115     auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
116     auto f2 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
117 #endif
118     auto f3 = [var] // expected-note {{variable 'var' is explicitly captured here}}
119       { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
120     auto f4 = [&] {
121       int x = var; // expected-note {{variable 'var' is captured here}}
122       int var = 2; // expected-warning {{declaration shadows a local variable}}
123     };
124   };
125   auto l6 = [&] {
126     auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}}
127       int param = 0; // expected-warning {{declaration shadows a local variable}}
128     };
129   };
130 
131   // Generic lambda arguments should work.
132 #ifdef AVOID
133   auto g1 = [](auto param) { ; }; // no warning
134   auto g2 = [=](auto param) { ; }; // no warning
135 #else
136   auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
137   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
138 #endif
139   auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
140    (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
141 }
142 
143 void avoidWarningWhenRedefining() {
144   int a = 1;
145   auto l = [b = a] { // expected-note {{previous definition is here}}
146     // Don't warn on redefinitions.
147     int b = 0; // expected-error {{redefinition of 'b'}}
148   };
149 }
150 
151 namespace GH61105 {
152 void f() {
153   int y = 0;
154   int x = 0;
155 #if __cplusplus >= 202002L
156   auto l1 = [y]<typename y>(y) { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
157                                               // expected-note {{template parameter is declared here}}
158   auto l2 = [=]<typename y>() { int a = y; return 0; }; // expected-error {{'y' does not refer to a value}} \
159                                                         // expected-note {{declared here}}
160   auto l3 = [&, y]<typename y, typename>(y) { int a = x; return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
161                                                                       // expected-note {{template parameter is declared here}}
162   auto l4 = [x, y]<typename y, int x>() { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
163                                                        // expected-error {{declaration of 'x' shadows template parameter}} \
164                                                        // expected-note 2{{template parameter is declared here}}
165   auto l5 = []<typename y>(y) { return 0; }; // No diagnostic
166 #endif
167 }
168 }
169