1 | // RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++1z %s |
2 | |
3 | class NonTrivialConstructor { |
4 | public: |
5 | NonTrivialConstructor() {} |
6 | }; |
7 | |
8 | class NonTrivialCopyConstructor { |
9 | public: |
10 | NonTrivialCopyConstructor() = default; |
11 | NonTrivialCopyConstructor(const NonTrivialCopyConstructor &) {} |
12 | }; |
13 | |
14 | class NonTrivialDestructor { |
15 | public: |
16 | ~NonTrivialDestructor() {} |
17 | }; |
18 | |
19 | class Trivial { |
20 | public: |
21 | Trivial() = default; |
22 | Trivial(int a) {} |
23 | }; |
24 | |
25 | int side_effect() { |
26 | return 42; |
27 | } |
28 | |
29 | void test() { |
30 | int i = 0; |
31 | const int k = 0; |
32 | |
33 | auto captures_nothing = [] {}; |
34 | |
35 | auto captures_nothing_by_value = [=] {}; |
36 | auto captures_nothing_by_reference = [&] {}; |
37 | |
38 | auto implicit_by_value = [=]() mutable { i++; }; |
39 | auto implicit_by_reference = [&] { i++; }; |
40 | |
41 | auto explicit_by_value_used = [i] { return i + 1; }; |
42 | auto explicit_by_value_used_void = [i] { (void)i; }; |
43 | auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} |
44 | auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} |
45 | auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} |
46 | auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} |
47 | |
48 | auto explicit_by_reference_used = [&i] { i++; }; |
49 | auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}} |
50 | |
51 | auto explicit_initialized_reference_used = [&j = i] { return j + 1; }; |
52 | auto explicit_initialized_reference_unused = [&j = i]{}; // expected-warning{{lambda capture 'j' is not used}} |
53 | |
54 | auto explicit_initialized_value_used = [j = 1] { return j + 1; }; |
55 | auto explicit_initialized_value_unused = [j = 1] {}; // expected-warning{{lambda capture 'j' is not used}} |
56 | auto explicit_initialized_value_non_trivial_constructor = [j = NonTrivialConstructor()]{}; |
57 | auto explicit_initialized_value_non_trivial_destructor = [j = NonTrivialDestructor()]{}; |
58 | auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}} |
59 | auto explicit_initialized_value_non_trivial_init = [j = Trivial(42)]{}; |
60 | auto explicit_initialized_value_with_side_effect = [j = side_effect()]{}; |
61 | |
62 | auto nested = [&i] { |
63 | auto explicit_by_value_used = [i] { return i + 1; }; |
64 | auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} |
65 | }; |
66 | |
67 | Trivial trivial; |
68 | auto explicit_by_value_trivial = [trivial] {}; // expected-warning{{lambda capture 'trivial' is not used}} |
69 | |
70 | NonTrivialConstructor cons; |
71 | auto explicit_by_value_non_trivial_constructor = [cons] {}; // expected-warning{{lambda capture 'cons' is not used}} |
72 | |
73 | NonTrivialCopyConstructor copy_cons; |
74 | auto explicit_by_value_non_trivial_copy_constructor = [copy_cons] {}; |
75 | |
76 | NonTrivialDestructor dest; |
77 | auto explicit_by_value_non_trivial_destructor = [dest] {}; |
78 | |
79 | volatile int v; |
80 | auto explicit_by_value_volatile = [v] {}; |
81 | } |
82 | |
83 | class TrivialThis : Trivial { |
84 | void test() { |
85 | auto explicit_this_used = [this] { return i; }; |
86 | auto explicit_this_used_void = [this] { (void)this; }; |
87 | auto explicit_this_unused = [this] {}; // expected-warning{{lambda capture 'this' is not used}} |
88 | auto explicit_star_this_used = [*this] { return i; }; |
89 | auto explicit_star_this_used_void = [*this] { (void)this; }; |
90 | auto explicit_star_this_unused = [*this] {}; // expected-warning{{lambda capture 'this' is not used}} |
91 | } |
92 | int i; |
93 | }; |
94 | |
95 | class NonTrivialConstructorThis : NonTrivialConstructor { |
96 | void test() { |
97 | auto explicit_this_used = [this] { return i; }; |
98 | auto explicit_this_used_void = [this] { (void)this; }; |
99 | auto explicit_this_unused = [this] {}; // expected-warning{{lambda capture 'this' is not used}} |
100 | auto explicit_star_this_used = [*this] { return i; }; |
101 | auto explicit_star_this_used_void = [*this] { (void)this; }; |
102 | auto explicit_star_this_unused = [*this] {}; // expected-warning{{lambda capture 'this' is not used}} |
103 | } |
104 | int i; |
105 | }; |
106 | |
107 | class NonTrivialCopyConstructorThis : NonTrivialCopyConstructor { |
108 | void test() { |
109 | auto explicit_this_used = [this] { return i; }; |
110 | auto explicit_this_used_void = [this] { (void)this; }; |
111 | auto explicit_this_unused = [this] {}; // expected-warning{{lambda capture 'this' is not used}} |
112 | auto explicit_star_this_used = [*this] { return i; }; |
113 | auto explicit_star_this_used_void = [*this] { (void)this; }; |
114 | auto explicit_star_this_unused = [*this] {}; |
115 | } |
116 | int i; |
117 | }; |
118 | |
119 | class NonTrivialDestructorThis : NonTrivialDestructor { |
120 | void test() { |
121 | auto explicit_this_used = [this] { return i; }; |
122 | auto explicit_this_used_void = [this] { (void)this; }; |
123 | auto explicit_this_unused = [this] {}; // expected-warning{{lambda capture 'this' is not used}} |
124 | auto explicit_star_this_used = [*this] { return i; }; |
125 | auto explicit_star_this_used_void = [*this] { (void)this; }; |
126 | auto explicit_star_this_unused = [*this] {}; |
127 | } |
128 | int i; |
129 | }; |
130 | |
131 | template <typename T> |
132 | void test_templated() { |
133 | int i = 0; |
134 | const int k = 0; |
135 | |
136 | auto captures_nothing = [] {}; |
137 | |
138 | auto captures_nothing_by_value = [=] {}; |
139 | auto captures_nothing_by_reference = [&] {}; |
140 | |
141 | auto implicit_by_value = [=]() mutable { i++; }; |
142 | auto implicit_by_reference = [&] { i++; }; |
143 | |
144 | auto explicit_by_value_used = [i] { return i + 1; }; |
145 | auto explicit_by_value_used_generic = [i](auto c) { return i + 1; }; |
146 | auto explicit_by_value_used_void = [i] { (void)i; }; |
147 | |
148 | auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} |
149 | auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} |
150 | auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}} |
151 | auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} |
152 | auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} |
153 | |
154 | auto explicit_by_reference_used = [&i] { i++; }; |
155 | auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}} |
156 | |
157 | auto explicit_initialized_reference_used = [&j = i] { return j + 1; }; |
158 | auto explicit_initialized_reference_unused = [&j = i]{}; // expected-warning{{lambda capture 'j' is not used}} |
159 | |
160 | auto explicit_initialized_value_used = [j = 1] { return j + 1; }; |
161 | auto explicit_initialized_value_unused = [j = 1] {}; // expected-warning{{lambda capture 'j' is not used}} |
162 | auto explicit_initialized_value_non_trivial_constructor = [j = NonTrivialConstructor()]{}; |
163 | auto explicit_initialized_value_non_trivial_destructor = [j = NonTrivialDestructor()]{}; |
164 | auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}} |
165 | auto explicit_initialized_value_non_trivial_init = [j = Trivial(42)]{}; |
166 | auto explicit_initialized_value_with_side_effect = [j = side_effect()]{}; |
167 | auto explicit_initialized_value_generic_used = [i = 1](auto c) mutable { i++; }; |
168 | auto explicit_initialized_value_generic_unused = [i = 1](auto c) mutable {}; // expected-warning{{lambda capture 'i' is not used}} |
169 | |
170 | auto nested = [&i] { |
171 | auto explicit_by_value_used = [i] { return i + 1; }; |
172 | auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} |
173 | }; |
174 | |
175 | Trivial trivial; |
176 | auto explicit_by_value_trivial = [trivial] {}; // expected-warning{{lambda capture 'trivial' is not used}} |
177 | |
178 | NonTrivialConstructor cons; |
179 | auto explicit_by_value_non_trivial_constructor = [cons] {}; // expected-warning{{lambda capture 'cons' is not used}} |
180 | |
181 | NonTrivialCopyConstructor copy_cons; |
182 | auto explicit_by_value_non_trivial_copy_constructor = [copy_cons] {}; |
183 | |
184 | NonTrivialDestructor dest; |
185 | auto explicit_by_value_non_trivial_destructor = [dest] {}; |
186 | |
187 | volatile int v; |
188 | auto explicit_by_value_volatile = [v] {}; |
189 | } |
190 | |
191 | void test_use_template() { |
192 | test_templated<int>(); // expected-note{{in instantiation of function template specialization 'test_templated<int>' requested here}} |
193 | } |
194 | |
195 | namespace pr35555 { |
196 | int a; |
197 | void b() { |
198 | int c[a]; |
199 | auto vla_used = [&c] { return c[0]; }; |
200 | auto vla_unused = [&c] {}; // expected-warning{{lambda capture 'c' is not used}} |
201 | } |
202 | } // namespace pr35555 |
203 | |