xref: /llvm-project/clang/test/SemaCXX/warn-unused-variables.cpp (revision bd0ed0abc31fa5a49e87eeca7aa872e7f6e4d1e7)
1 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++14-extensions -Wno-c++17-extensions -verify -std=c++11 %s
3 template<typename T> void f() {
4   T t;
5   t = 17;
6 }
7 
8 // PR5407
9 struct A { A(); };
10 struct B { ~B(); };
11 void f() {
12   A a;
13   B b;
14 }
15 
16 // PR5531
17 namespace PR5531 {
18   struct A {
19   };
20 
21   struct B {
22     B(int);
23   };
24 
25   struct C {
26     ~C();
27   };
28 
29   void test() {
30     A();
31     B(17);
32     C();
33   }
34 }
35 
36 template<typename T>
37 struct X0 { };
38 
39 template<typename T>
40 void test_dependent_init(T *p) {
41   X0<int> i(p);
42   (void)i;
43 }
44 
45 void unused_local_static() {
46   static int x = 0;
47   static int y = 0; // expected-warning{{unused variable 'y'}}
48 #pragma unused(x)
49 }
50 
51 // PR10168
52 namespace PR10168 {
53   // We expect a warning in the definition only for non-dependent variables, and
54   // a warning in the instantiation only for dependent variables.
55   template<typename T>
56   struct S {
57     void f() {
58       int a; // expected-warning {{unused variable 'a'}}
59       T b; // expected-warning 2{{unused variable 'b'}}
60     }
61   };
62 
63   template<typename T>
64   void f() {
65     int a; // expected-warning {{unused variable 'a'}}
66     T b; // expected-warning 2{{unused variable 'b'}}
67   }
68 
69   void g() {
70     S<int>().f(); // expected-note {{here}}
71     S<char>().f(); // expected-note {{here}}
72     f<int>(); // expected-note {{here}}
73     f<char>(); // expected-note {{here}}
74   }
75 }
76 
77 namespace PR11550 {
78   struct S1 {
79     S1();
80   };
81   S1 makeS1();
82   void testS1(S1 a) {
83     // This constructor call can be elided.
84     S1 x = makeS1(); // expected-warning {{unused variable 'x'}}
85 
86     // This one cannot, so no warning.
87     S1 y;
88 
89     // This call cannot, but the constructor is trivial.
90     S1 z = a; // expected-warning {{unused variable 'z'}}
91   }
92 
93   // The same is true even when we know thet constructor has side effects.
94   void foo();
95   struct S2 {
96     S2() {
97       foo();
98     }
99   };
100   S2 makeS2();
101   void testS2(S2 a) {
102     S2 x = makeS2(); // expected-warning {{unused variable 'x'}}
103     S2 y;
104     S2 z = a; // expected-warning {{unused variable 'z'}}
105   }
106 
107   // Or when the constructor is not declared by the user.
108   struct S3 {
109     S1 m;
110   };
111   S3 makeS3();
112   void testS3(S3 a) {
113     S3 x = makeS3(); // expected-warning {{unused variable 'x'}}
114     S3 y;
115     S3 z = a; // expected-warning {{unused variable 'z'}}
116   }
117 }
118 
119 namespace PR19305 {
120   template<typename T> int n = 0; // no warning
121   int a = n<int>;
122 
123   template<typename T> const int l = 0; // no warning
124   int b = l<int>;
125 
126   // PR19558
127   template<typename T> const int o = 0; // no warning
128   template<typename T> const int o<T*> = 0; // no warning
129   int c = o<int*>;
130 
131   template<> int o<void> = 0; // no warning
132   int d = o<void>;
133 
134   // FIXME: It'd be nice to warn here.
135   template<typename T> int m = 0;
136   template<typename T> int m<T*> = 0;
137 
138   // This has external linkage, so could be referenced by a declaration in a
139   // different translation unit.
140   template<> const int m<void> = 0; // no warning
141 }
142 
143 namespace ctor_with_cleanups {
144   struct S1 {
145     ~S1();
146   };
147   struct S2 {
148     S2(const S1&);
149   };
150   void func() {
151     S2 s((S1()));
152   }
153 }
154 
155 #include "Inputs/warn-unused-variables.h"
156 
157 class NonTriviallyDestructible {
158 public:
159   ~NonTriviallyDestructible() {}
160 };
161 
162 namespace arrayRecords {
163 
164 struct Foo {
165   int x;
166   Foo(int x) : x(x) {}
167 };
168 
169 struct Elidable {
170   Elidable();
171 };
172 
173 void foo(int size) {
174   Elidable elidable; // no warning
175   Elidable elidableArray[2]; // no warning
176   Elidable elidableDynArray[size]; // no warning
177   Elidable elidableNestedArray[1][2][3]; // no warning
178 
179   NonTriviallyDestructible scalar; // no warning
180   NonTriviallyDestructible array[2];  // no warning
181   NonTriviallyDestructible nestedArray[2][2]; // no warning
182 
183   Foo fooScalar = 1; // expected-warning {{unused variable 'fooScalar'}}
184   Foo fooArray[] = {1,2}; // expected-warning {{unused variable 'fooArray'}}
185   Foo fooNested[2][2] = { {1,2}, {3,4} }; // expected-warning {{unused variable 'fooNested'}}
186 }
187 
188 template<int N>
189 void bar() {
190   NonTriviallyDestructible scaler; // no warning
191   NonTriviallyDestructible array[N]; // no warning
192 }
193 
194 void test() {
195   foo(10);
196   bar<2>();
197 }
198 
199 } // namespace arrayRecords
200 
201 #if __cplusplus >= 201103L
202 namespace with_constexpr {
203 template <typename T>
204 struct Literal {
205   T i;
206   Literal() = default;
207   constexpr Literal(T i) : i(i) {}
208 };
209 
210 struct NoLiteral {
211   int i;
212   NoLiteral() = default;
213   constexpr NoLiteral(int i) : i(i) {}
214   ~NoLiteral() {}
215 };
216 
217 static Literal<int> gl1;          // expected-warning {{unused variable 'gl1'}}
218 static Literal<int> gl2(1);       // expected-warning {{unused variable 'gl2'}}
219 static const Literal<int> gl3(0); // expected-warning {{unused variable 'gl3'}}
220 
221 template <typename T>
222 void test(int i) {
223   Literal<int> l1;     // expected-warning {{unused variable 'l1'}}
224   Literal<int> l2(42); // expected-warning {{unused variable 'l2'}}
225   Literal<int> l3(i);  // no-warning
226   Literal<T> l4(0);    // no-warning
227   NoLiteral nl1;       // no-warning
228   NoLiteral nl2(42);   // no-warning
229 }
230 }
231 
232 namespace crash {
233 struct a {
234   a(const char *);
235 };
236 template <typename b>
237 void c() {
238   a d(b::e ? "" : "");
239 }
240 }
241 
242 // Ensure we don't warn on dependent constructor calls.
243 namespace dependent_ctor {
244 struct S {
245   S() = default;
246   S(const S &) = default;
247   S(int);
248 };
249 
250 template <typename T>
251 void foo(T &t) {
252   S s{t};
253 }
254 }
255 #endif
256 
257 // Ensure we do not warn on lifetime extension
258 namespace gh54489 {
259 
260 void f() {
261   const auto &a = NonTriviallyDestructible();
262   const auto &b = a; // expected-warning {{unused variable 'b'}}
263 #if __cplusplus >= 201103L
264   const auto &&c = NonTriviallyDestructible();
265   auto &&d = c; // expected-warning {{unused variable 'd'}}
266 #endif
267 }
268 
269 struct S {
270   S() = default;
271   S(const S &) = default;
272   S(int);
273 };
274 
275 template <typename T>
276 void foo(T &t) {
277   const auto &extended = S{t};
278 }
279 
280 void test_foo() {
281   int i;
282   foo(i);
283 }
284 
285 struct RAIIWrapper {
286   RAIIWrapper();
287   ~RAIIWrapper();
288 };
289 
290 void RAIIWrapperTest() {
291   auto const guard = RAIIWrapper();
292   auto const &guard2 = RAIIWrapper();
293   auto &&guard3 = RAIIWrapper();
294 }
295 
296 } // namespace gh54489
297 
298 namespace inside_condition {
299   void ifs() {
300     if (int hoge = 0) // expected-warning {{unused variable 'hoge'}}
301       return;
302     if (const int const_hoge = 0) // expected-warning {{unused variable 'const_hoge'}}
303       return;
304     else if (int fuga = 0)
305       (void)fuga;
306     else if (int used = 1; int catched = used) // expected-warning {{unused variable 'catched'}}
307       return;
308     else if (int refed = 1; int used = refed)
309       (void)used;
310     else if (int unused1 = 2; int unused2 = 3) // expected-warning {{unused variable 'unused1'}} \
311                                                // expected-warning {{unused variable 'unused2'}}
312       return;
313     else if (int unused = 4; int used = 5) // expected-warning {{unused variable 'unused'}}
314       (void)used;
315     else if (int used = 6; int unused = 7) // expected-warning {{unused variable 'unused'}}
316       (void)used;
317     else if (int used1 = 8; int used2 = 9)
318       (void)(used1 + used2);
319     else if (auto [a, b] = (int[2]){ 1, 2 }; 1) // expected-warning {{unused variable '[a, b]'}}
320       return;
321     else if (auto [a, b] = (int[2]){ 1, 2 }; a)
322       return;
323   }
324 
325   void fors() {
326     for (int i = 0;int unused = 0;); // expected-warning {{unused variable 'i'}} \
327                                      // expected-warning {{unused variable 'unused'}}
328     for (int i = 0;int used = 0;) // expected-warning {{unused variable 'i'}}
329       (void)used;
330       while(int var = 1) // expected-warning {{unused variable 'var'}}
331         return;
332   }
333 
334   void whiles() {
335     while(int unused = 1) // expected-warning {{unused variable 'unused'}}
336       return;
337     while(int used = 1)
338       (void)used;
339   }
340 
341 
342   void switches() {
343     switch(int unused = 1) { // expected-warning {{unused variable 'unused'}}
344       case 1: return;
345     }
346     switch(constexpr int used = 3; int unused = 4) { // expected-warning {{unused variable 'unused'}}
347       case used: return;
348     }
349     switch(int used = 3; int unused = 4) { // expected-warning {{unused variable 'unused'}}
350       case 3: (void)used;
351     }
352     switch(constexpr int used1 = 0; constexpr int used2 = 6) {
353       case (used1+used2): return;
354     }
355     switch(auto [a, b] = (int[2]){ 1, 2 }; 1) { // expected-warning {{unused variable '[a, b]'}}
356       case 1: return;
357     }
358     switch(auto [a, b] = (int[2]){ 1, 2 }; b) {
359       case 1: return;
360     }
361     switch(auto [a, b] = (int[2]){ 1, 2 }; 1) {
362       case 1: (void)a;
363     }
364   }
365   template <typename T>
366   struct Vector {
367     void doIt() {
368       for (auto& e : elements){} // expected-warning {{unused variable 'e'}}
369     }
370     T elements[10];
371   };
372   void ranged_for() {
373     Vector<int>    vector;
374     vector.doIt(); // expected-note {{here}}
375   }
376 
377 
378   struct RAII {
379     int &x;
380     RAII(int &ref) : x(ref) {}
381     ~RAII() { x = 0;}
382     operator int() const { return 1; }
383   };
384   void aggregate() {
385     int x = 10;
386     int y = 10;
387     if (RAII var = x) {}
388     for(RAII var = x; RAII var2 = y;) {}
389     while (RAII var = x) {}
390     switch (RAII var = x) {}
391   }
392 
393   struct TrivialDtor{
394     int &x;
395     TrivialDtor(int &ref) : x(ref) { ref = 32; }
396     operator int() const { return 1; }
397   };
398   void trivial_dtor() {
399     int x = 10;
400     int y = 10;
401     if (TrivialDtor var = x) {} // expected-warning {{unused variable 'var'}}
402     for(TrivialDtor var = x; TrivialDtor var2 = y;) {} // expected-warning {{unused variable 'var'}} \
403                                          // expected-warning {{unused variable 'var2'}}
404     while (TrivialDtor var = x) {} // expected-warning {{unused variable 'var'}}
405     switch (TrivialDtor var = x) {} // expected-warning {{unused variable 'var'}}
406   }
407 
408 } // namespace inside_condition
409