xref: /llvm-project/clang/test/SemaCXX/warn-unused-variables.cpp (revision dd2bf3b840df260d794e37cc96d4498372aa08f6)
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++1y-extensions -verify=expected,cxx98-14 -std=gnu++11 %s
3 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify=expected,cxx98-14 -std=gnu++14 %s
4 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=gnu++17 %s
5 
6 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s -fexperimental-new-constant-interpreter
7 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify=expected,cxx98-14 -std=gnu++11 %s -fexperimental-new-constant-interpreter
8 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify=expected,cxx98-14 -std=gnu++14 %s -fexperimental-new-constant-interpreter
9 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=gnu++17 %s -fexperimental-new-constant-interpreter
10 
11 template<typename T> void f() {
12   T t;
13   t = 17;
14 }
15 
16 // PR5407
17 struct A { A(); };
18 struct B { ~B(); };
19 void f() {
20   A a;
21   B b;
22 }
23 
24 // PR5531
25 namespace PR5531 {
26   struct A {
27   };
28 
29   struct B {
30     B(int);
31   };
32 
33   struct C {
34     ~C();
35   };
36 
37   void test() {
38     A();
39     B(17);
40     C();
41   }
42 }
43 
44 template<typename T>
45 struct X0 { };
46 
47 template<typename T>
48 void test_dependent_init(T *p) {
49   X0<int> i(p);
50   (void)i;
51 }
52 
53 void unused_local_static() {
54   static int x = 0;
55   static int y = 0; // expected-warning{{unused variable 'y'}}
56 #pragma unused(x)
57   static __attribute__((used)) int z;
58   static __attribute__((unused)) int w;
59   [[maybe_unused]] static int v;
60 }
61 
62 // PR10168
63 namespace PR10168 {
64   // We expect a warning in the definition only for non-dependent variables, and
65   // a warning in the instantiation only for dependent variables.
66   template<typename T>
67   struct S {
68     void f() {
69       int a; // expected-warning {{unused variable 'a'}}
70       T b; // expected-warning 2{{unused variable 'b'}}
71     }
72   };
73 
74   template<typename T>
75   void f() {
76     int a; // expected-warning {{unused variable 'a'}}
77     T b; // expected-warning 2{{unused variable 'b'}}
78   }
79 
80   void g() {
81     S<int>().f(); // expected-note {{here}}
82     S<char>().f(); // expected-note {{here}}
83     f<int>(); // expected-note {{here}}
84     f<char>(); // expected-note {{here}}
85   }
86 }
87 
88 namespace PR11550 {
89   struct S1 {
90     S1();
91   };
92   S1 makeS1();
93   void testS1(S1 a) {
94     // This constructor call can be elided.
95     S1 x = makeS1(); // expected-warning {{unused variable 'x'}}
96 
97     // This one cannot, so no warning.
98     S1 y;
99 
100     // This call cannot, but the constructor is trivial.
101     S1 z = a; // expected-warning {{unused variable 'z'}}
102   }
103 
104   // The same is true even when we know thet constructor has side effects.
105   void foo();
106   struct S2 {
107     S2() {
108       foo();
109     }
110   };
111   S2 makeS2();
112   void testS2(S2 a) {
113     S2 x = makeS2(); // expected-warning {{unused variable 'x'}}
114     S2 y;
115     S2 z = a; // expected-warning {{unused variable 'z'}}
116   }
117 
118   // Or when the constructor is not declared by the user.
119   struct S3 {
120     S1 m;
121   };
122   S3 makeS3();
123   void testS3(S3 a) {
124     S3 x = makeS3(); // expected-warning {{unused variable 'x'}}
125     S3 y;
126     S3 z = a; // expected-warning {{unused variable 'z'}}
127   }
128 }
129 
130 namespace PR19305 {
131   template<typename T> int n = 0; // no warning
132   int a = n<int>;
133 
134   template<typename T> const int l = 0; // no warning
135   int b = l<int>;
136 
137   // PR19558
138   template<typename T> const int o = 0; // no warning
139   template<typename T> const int o<T*> = 0; // no warning
140   int c = o<int*>;
141 
142   template<> int o<void> = 0; // no warning
143   int d = o<void>;
144 
145   // FIXME: It'd be nice to warn here.
146   template<typename T> int m = 0;
147   template<typename T> int m<T*> = 0;
148 
149   // This has external linkage, so could be referenced by a declaration in a
150   // different translation unit.
151   template<> const int m<void> = 0; // no warning
152 }
153 
154 namespace ctor_with_cleanups {
155   struct S1 {
156     ~S1();
157   };
158   struct S2 {
159     S2(const S1&);
160   };
161   void func() {
162     S2 s((S1()));
163   }
164 }
165 
166 #include "Inputs/warn-unused-variables.h"
167 
168 class NonTriviallyDestructible {
169 public:
170   ~NonTriviallyDestructible() {}
171 };
172 
173 namespace arrayRecords {
174 
175 struct Foo {
176   int x;
177   Foo(int x) : x(x) {}
178 };
179 
180 struct Elidable {
181   Elidable();
182 };
183 
184 void foo(int size) {
185   Elidable elidable; // no warning
186   Elidable elidableArray[2]; // no warning
187   Elidable elidableDynArray[size]; // no warning
188   Elidable elidableNestedArray[1][2][3]; // no warning
189 
190   NonTriviallyDestructible scalar; // no warning
191   NonTriviallyDestructible array[2];  // no warning
192   NonTriviallyDestructible nestedArray[2][2]; // no warning
193 
194   // Copy initialzation gives warning before C++17
195   Foo fooScalar = 1; // cxx98-14-warning {{unused variable 'fooScalar'}}
196   Foo fooArray[] = {1,2}; // expected-warning {{unused variable 'fooArray'}}
197   Foo fooNested[2][2] = { {1,2}, {3,4} }; // expected-warning {{unused variable 'fooNested'}}
198 }
199 
200 template<int N>
201 void bar() {
202   NonTriviallyDestructible scaler; // no warning
203   NonTriviallyDestructible array[N]; // no warning
204 }
205 
206 void test() {
207   foo(10);
208   bar<2>();
209 }
210 
211 } // namespace arrayRecords
212 
213 #if __cplusplus >= 201103L
214 namespace with_constexpr {
215 template <typename T>
216 struct Literal {
217   T i;
218   Literal() = default;
219   constexpr Literal(T i) : i(i) {}
220 };
221 
222 struct NoLiteral {
223   int i;
224   NoLiteral() = default;
225   constexpr NoLiteral(int i) : i(i) {}
226   ~NoLiteral() {}
227 };
228 
229 static Literal<int> gl1;          // expected-warning {{unused variable 'gl1'}}
230 static Literal<int> gl2(1);       // expected-warning {{unused variable 'gl2'}}
231 static const Literal<int> gl3(0); // expected-warning {{unused variable 'gl3'}}
232 
233 template <typename T>
234 void test(int i) {
235   Literal<int> l1;     // expected-warning {{unused variable 'l1'}}
236   Literal<int> l2(42); // expected-warning {{unused variable 'l2'}}
237   Literal<int> l3(i);  // no-warning
238   Literal<T> l4(0);    // no-warning
239   NoLiteral nl1;       // no-warning
240   NoLiteral nl2(42);   // no-warning
241 }
242 }
243 
244 namespace crash {
245 struct a {
246   a(const char *);
247 };
248 template <typename b>
249 void c() {
250   a d(b::e ? "" : "");
251 }
252 }
253 
254 // Ensure we don't warn on dependent constructor calls.
255 namespace dependent_ctor {
256 struct S {
257   S() = default;
258   S(const S &) = default;
259   S(int);
260 };
261 
262 template <typename T>
263 void foo(T &t) {
264   S s{t};
265 }
266 }
267 #endif
268 
269 // Ensure we do not warn on lifetime extension
270 namespace gh54489 {
271 
272 void f() {
273   const auto &a = NonTriviallyDestructible();
274   const auto &b = a; // expected-warning {{unused variable 'b'}}
275 #if __cplusplus >= 201103L
276   const auto &&c = NonTriviallyDestructible();
277   auto &&d = c; // expected-warning {{unused variable 'd'}}
278 #endif
279 }
280 
281 struct S {
282   S() = default;
283   S(const S &) = default;
284   S(int);
285 };
286 
287 template <typename T>
288 void foo(T &t) {
289   const auto &extended = S{t};
290 }
291 
292 void test_foo() {
293   int i;
294   foo(i);
295 }
296 
297 struct RAIIWrapper {
298   RAIIWrapper();
299   ~RAIIWrapper();
300 };
301 
302 void RAIIWrapperTest() {
303   auto const guard = RAIIWrapper();
304   auto const &guard2 = RAIIWrapper();
305   auto &&guard3 = RAIIWrapper();
306 }
307 
308 } // namespace gh54489
309 
310 // Ensure that -Wunused-variable does not emit warning
311 // on copy constructors with side effects (C++17 and later)
312 #if __cplusplus >= 201703L
313 namespace gh79518 {
314 
315 struct S {
316     S(int);
317 };
318 
319 // With an initializer list
320 struct A {
321   int x;
322   A(int x) : x(x) {}
323 };
324 
325 void foo() {
326     S s(0); // no warning
327     S s2 = 0; // no warning
328     S s3{0}; // no warning
329 
330     A a = 1; // no warning
331 }
332 
333 } // namespace gh79518
334 #endif
335