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:
NonTrivialConstructor()5   NonTrivialConstructor() {}
6 };
7 
8 class NonTrivialCopyConstructor {
9 public:
10   NonTrivialCopyConstructor() = default;
NonTrivialCopyConstructor(const NonTrivialCopyConstructor &)11   NonTrivialCopyConstructor(const NonTrivialCopyConstructor &) {}
12 };
13 
14 class NonTrivialDestructor {
15 public:
~NonTrivialDestructor()16   ~NonTrivialDestructor() {}
17 };
18 
19 class Trivial {
20 public:
21   Trivial() = default;
Trivial(int a)22   Trivial(int a) {}
23 };
24 
side_effect()25 int side_effect() {
26   return 42;
27 }
28 
test()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 {
test()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 {
test()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 {
test()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 {
test()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>
test_templated()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 
test_use_template()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;
b()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