aboutsummaryrefslogtreecommitdiff
path: root/clang/test/SemaCXX/warn-unused-variables.cpp
blob: 216873aa4074b5f3147d1b90981704bc4ad317a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s
// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify=expected,cxx98-14 -std=gnu++11 %s
// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify=expected,cxx98-14 -std=gnu++14 %s
// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=gnu++17 %s

// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s -fexperimental-new-constant-interpreter
// 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
// 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
// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=gnu++17 %s -fexperimental-new-constant-interpreter

template<typename T> void f() {
  T t;
  t = 17;
}

// PR5407
struct A { A(); };
struct B { ~B(); };
void f() {
  A a;
  B b;
}

// PR5531
namespace PR5531 {
  struct A {
  };

  struct B {
    B(int);
  };

  struct C {
    ~C();
  };

  void test() {
    A();
    B(17);
    C();
  }
}

template<typename T>
struct X0 { };

template<typename T>
void test_dependent_init(T *p) {
  X0<int> i(p);
  (void)i;
}

void unused_local_static() {
  static int x = 0;
  static int y = 0; // expected-warning{{unused variable 'y'}}
#pragma unused(x)
  static __attribute__((used)) int z;
  static __attribute__((unused)) int w;
  [[maybe_unused]] static int v;
}

// PR10168
namespace PR10168 {
  // We expect a warning in the definition only for non-dependent variables, and
  // a warning in the instantiation only for dependent variables.
  template<typename T>
  struct S {
    void f() {
      int a; // expected-warning {{unused variable 'a'}}
      T b; // expected-warning 2{{unused variable 'b'}}
    }
  };

  template<typename T>
  void f() {
    int a; // expected-warning {{unused variable 'a'}}
    T b; // expected-warning 2{{unused variable 'b'}}
  }

  void g() {
    S<int>().f(); // expected-note {{here}}
    S<char>().f(); // expected-note {{here}}
    f<int>(); // expected-note {{here}}
    f<char>(); // expected-note {{here}}
  }
}

namespace PR11550 {
  struct S1 {
    S1();
  };
  S1 makeS1();
  void testS1(S1 a) {
    // This constructor call can be elided.
    S1 x = makeS1(); // expected-warning {{unused variable 'x'}}

    // This one cannot, so no warning.
    S1 y;

    // This call cannot, but the constructor is trivial.
    S1 z = a; // expected-warning {{unused variable 'z'}}
  }

  // The same is true even when we know thet constructor has side effects.
  void foo();
  struct S2 {
    S2() {
      foo();
    }
  };
  S2 makeS2();
  void testS2(S2 a) {
    S2 x = makeS2(); // expected-warning {{unused variable 'x'}}
    S2 y;
    S2 z = a; // expected-warning {{unused variable 'z'}}
  }

  // Or when the constructor is not declared by the user.
  struct S3 {
    S1 m;
  };
  S3 makeS3();
  void testS3(S3 a) {
    S3 x = makeS3(); // expected-warning {{unused variable 'x'}}
    S3 y;
    S3 z = a; // expected-warning {{unused variable 'z'}}
  }
}

namespace PR19305 {
  template<typename T> int n = 0; // no warning
  int a = n<int>;

  template<typename T> const int l = 0; // no warning
  int b = l<int>;

  // PR19558
  template<typename T> const int o = 0; // no warning
  template<typename T> const int o<T*> = 0; // no warning
  int c = o<int*>;

  template<> int o<void> = 0; // no warning
  int d = o<void>;

  // FIXME: It'd be nice to warn here.
  template<typename T> int m = 0;
  template<typename T> int m<T*> = 0;

  // This has external linkage, so could be referenced by a declaration in a
  // different translation unit.
  template<> const int m<void> = 0; // no warning
}

namespace ctor_with_cleanups {
  struct S1 {
    ~S1();
  };
  struct S2 {
    S2(const S1&);
  };
  void func() {
    S2 s((S1()));
  }
}

#include "Inputs/warn-unused-variables.h"

class NonTriviallyDestructible {
public:
  ~NonTriviallyDestructible() {}
};

namespace arrayRecords {

struct Foo {
  int x;
  Foo(int x) : x(x) {}
};

struct Elidable {
  Elidable();
};

void foo(int size) {
  Elidable elidable; // no warning
  Elidable elidableArray[2]; // no warning
  Elidable elidableDynArray[size]; // no warning
  Elidable elidableNestedArray[1][2][3]; // no warning

  NonTriviallyDestructible scalar; // no warning
  NonTriviallyDestructible array[2];  // no warning
  NonTriviallyDestructible nestedArray[2][2]; // no warning

  // Copy initialzation gives warning before C++17
  Foo fooScalar = 1; // cxx98-14-warning {{unused variable 'fooScalar'}}
  Foo fooArray[] = {1,2}; // expected-warning {{unused variable 'fooArray'}}
  Foo fooNested[2][2] = { {1,2}, {3,4} }; // expected-warning {{unused variable 'fooNested'}}
}

template<int N>
void bar() {
  NonTriviallyDestructible scaler; // no warning
  NonTriviallyDestructible array[N]; // no warning
}

void test() {
  foo(10);
  bar<2>();
}

} // namespace arrayRecords

#if __cplusplus >= 201103L
namespace with_constexpr {
template <typename T>
struct Literal {
  T i;
  Literal() = default;
  constexpr Literal(T i) : i(i) {}
};

struct NoLiteral {
  int i;
  NoLiteral() = default;
  constexpr NoLiteral(int i) : i(i) {}
  ~NoLiteral() {}
};

static Literal<int> gl1;          // expected-warning {{unused variable 'gl1'}}
static Literal<int> gl2(1);       // expected-warning {{unused variable 'gl2'}}
static const Literal<int> gl3(0); // expected-warning {{unused variable 'gl3'}}

template <typename T>
void test(int i) {
  Literal<int> l1;     // expected-warning {{unused variable 'l1'}}
  Literal<int> l2(42); // expected-warning {{unused variable 'l2'}}
  Literal<int> l3(i);  // no-warning
  Literal<T> l4(0);    // no-warning
  NoLiteral nl1;       // no-warning
  NoLiteral nl2(42);   // no-warning
}
}

namespace crash {
struct a {
  a(const char *);
};
template <typename b>
void c() {
  a d(b::e ? "" : "");
}
}

// Ensure we don't warn on dependent constructor calls.
namespace dependent_ctor {
struct S {
  S() = default;
  S(const S &) = default;
  S(int);
};

template <typename T>
void foo(T &t) {
  S s{t};
}
}
#endif

// Ensure we do not warn on lifetime extension
namespace gh54489 {

void f() {
  const auto &a = NonTriviallyDestructible();
  const auto &b = a; // expected-warning {{unused variable 'b'}}
#if __cplusplus >= 201103L
  const auto &&c = NonTriviallyDestructible();
  auto &&d = c; // expected-warning {{unused variable 'd'}}
#endif
}

struct S {
  S() = default;
  S(const S &) = default;
  S(int);
};

template <typename T>
void foo(T &t) {
  const auto &extended = S{t};
}

void test_foo() {
  int i;
  foo(i);
}

struct RAIIWrapper {
  RAIIWrapper();
  ~RAIIWrapper();
};

void RAIIWrapperTest() {
  auto const guard = RAIIWrapper();
  auto const &guard2 = RAIIWrapper();
  auto &&guard3 = RAIIWrapper();
}

} // namespace gh54489

// Ensure that -Wunused-variable does not emit warning
// on copy constructors with side effects (C++17 and later)
#if __cplusplus >= 201703L
namespace gh79518 {

struct S {
    S(int);
};

// With an initializer list
struct A {
  int x;
  A(int x) : x(x) {}
};

void foo() {
    S s(0); // no warning
    S s2 = 0; // no warning
    S s3{0}; // no warning

    A a = 1; // no warning
}

} // namespace gh79518
#endif