xref: /llvm-project/clang/test/SemaCXX/warn-unused-private-field.cpp (revision 5dab5bf0851f523602944355a2c1c17e7f78ef36)
1 // RUN: %clang_cc1 -fsyntax-only -Wunused -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++11 %s
2 // RUN: %clang_cc1 -fsyntax-only -Wunused -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++17 %s
3 // RUN: %clang_cc1 -fsyntax-only -Wunused -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++20 %s
4 
5 #if __cplusplus >= 202002L
6 
7 class EqDefaultCompare {
8   int used;
9 
10 public:
11   EqDefaultCompare(int x) : used(x) {}
12   bool operator==(const EqDefaultCompare &) const = default;
13 };
14 
15 class SpaceShipDefaultCompare {
16   int used;
17 
18 public:
19   SpaceShipDefaultCompare(int x) : used(x) {}
20   int operator<=>(const SpaceShipDefaultCompare &) const = default;
21 };
22 
23 class EqDefaultCompareOutOfClass {
24   int used; // no warning, the compiler generated AST for the comparison operator
25             // references the fields of the class, and this should be considered
26             // a use.
27             // This test case is needed because clang does not emit the body
28             // of the defaulted operator when it is defined in-class until it
29             // finds a call to it. `-Wunused-private-field` is suppressed in
30             // a different way in that case.
31   bool operator==(const EqDefaultCompareOutOfClass &) const;
32 };
33 
34 bool EqDefaultCompareOutOfClass::operator==(const EqDefaultCompareOutOfClass &) const = default;
35 
36 class FriendEqDefaultCompareOutOfClass {
37   int used; // no warning, same reasoning just tested via a friend declaration.
38   friend bool operator==(const FriendEqDefaultCompareOutOfClass &, const FriendEqDefaultCompareOutOfClass &);
39 };
40 
41 bool operator==(const FriendEqDefaultCompareOutOfClass &, const FriendEqDefaultCompareOutOfClass &) = default;
42 
43 class HasUnusedField {
44   int unused_; // expected-warning{{private field 'unused_' is not used}}
45 };
46 
47 class FriendEqDefaultCompare {
48   int used;
49   friend auto operator==(FriendEqDefaultCompare, FriendEqDefaultCompare) -> bool = default;
50 };
51 
52 class UnrelatedFriendEqDefaultCompare {
53   friend auto operator==(UnrelatedFriendEqDefaultCompare, UnrelatedFriendEqDefaultCompare) -> bool = default;
54   int operator<=>(const UnrelatedFriendEqDefaultCompare &) const = default;
55 };
56 
57 #endif
58 
59 class NotFullyDefined {
60  public:
61   NotFullyDefined();
62  private:
63   int y;
64 };
65 
66 class HasUndefinedNestedClass {
67   class Undefined;
68   int unused_;
69 };
70 
71 class HasUndefinedPureVirtualDestructor {
72   virtual ~HasUndefinedPureVirtualDestructor() = 0;
73   int unused_;
74 };
75 
76 class HasDefinedNestedClasses {
77   class DefinedHere {};
78   class DefinedOutside;
79   int unused_; // expected-warning{{private field 'unused_' is not used}}
80 };
81 class HasDefinedNestedClasses::DefinedOutside {};
82 
83 class HasUndefinedFriendFunction {
84   friend void undefinedFriendFunction();
85   int unused_;
86 };
87 
88 class HasUndefinedFriendClass {
89   friend class NotFullyDefined;
90   friend class NotDefined;
91   int unused_;
92 };
93 
94 class HasFriend {
95   friend class FriendClass;
96   friend void friendFunction(HasFriend f);
97   int unused_; // expected-warning{{private field 'unused_' is not used}}
98   int used_by_friend_class_;
99   int used_by_friend_function_;
100 };
101 
102 class ClassWithTemplateFriend {
103   template <typename T> friend class TemplateFriend;
104   int used_by_friend_;
105   int unused_;
106 };
107 
108 template <typename T> class TemplateFriend {
109 public:
110   TemplateFriend(ClassWithTemplateFriend my_friend) {
111     int var = my_friend.used_by_friend_; // expected-warning {{unused variable 'var'}}
112   }
113 };
114 
115 class FriendClass {
116   HasFriend my_friend_;
117   void use() {
118     my_friend_.used_by_friend_class_ = 42;
119   }
120 };
121 
122 void friendFunction(HasFriend my_friend) {
123   my_friend.used_by_friend_function_ = 42;
124 }
125 
126 class NonTrivialConstructor {
127  public:
128   NonTrivialConstructor() {}
129 };
130 
131 class NonTrivialDestructor {
132  public:
133   ~NonTrivialDestructor() {}
134 };
135 
136 class Trivial {
137  public:
138   Trivial() = default;
139   Trivial(int a) {}
140 };
141 
142 int side_effect() {
143   return 42;
144 }
145 
146 class A {
147  public:
148   A() : primitive_type_(42), default_initializer_(), other_initializer_(42),
149         trivial_(), user_constructor_(42),
150         initialized_with_side_effect_(side_effect()) {
151     used_ = 42;
152     attr_used_ = 42; // expected-warning{{'attr_used_' was marked unused but was used}}
153   }
154 
155   A(int x, A* a) : pointer_(a) {}
156 
157  private:
158   int primitive_type_; // expected-warning{{private field 'primitive_type_' is not used}}
159   A* pointer_; // expected-warning{{private field 'pointer_' is not used}}
160   int no_initializer_; // expected-warning{{private field 'no_initializer_' is not used}}
161   int default_initializer_; // expected-warning{{private field 'default_initializer_' is not used}}
162   int other_initializer_; // expected-warning{{private field 'other_initializer_' is not used}}
163   int used_, unused_; // expected-warning{{private field 'unused_' is not used}}
164   int in_class_initializer_ = 42; // expected-warning{{private field 'in_class_initializer_' is not used}}
165   int in_class_initializer_with_side_effect_ = side_effect();
166   Trivial trivial_initializer_ = Trivial(); // expected-warning{{private field 'trivial_initializer_' is not used}}
167   Trivial non_trivial_initializer_ = Trivial(42);
168   int initialized_with_side_effect_;
169   static int static_fields_are_ignored_;
170 
171   Trivial trivial_; // expected-warning{{private field 'trivial_' is not used}}
172   Trivial user_constructor_;
173   NonTrivialConstructor non_trivial_constructor_;
174   NonTrivialDestructor non_trivial_destructor_;
175 
176   int attr_ __attribute__((unused));
177   int attr_used_ __attribute__((unused));
178 };
179 
180 class EverythingUsed {
181  public:
182   EverythingUsed() : as_array_index_(0), var_(by_initializer_) {
183     var_ = sizeof(sizeof_);
184     int *use = &by_reference_; // expected-warning {{unused variable 'use'}}
185     int test[2];
186     test[as_array_index_] = 42;
187     int EverythingUsed::*ptr = &EverythingUsed::by_pointer_to_member_; // expected-warning {{unused variable 'ptr'}}
188   }
189 
190   template<class T>
191   void useStuff(T t) {
192     by_template_function_ = 42;
193   }
194 
195  private:
196   int var_;
197   int sizeof_;
198   int by_reference_;
199   int by_template_function_;
200   int as_array_index_;
201   int by_initializer_;
202   int by_pointer_to_member_;
203 };
204 
205 class HasFeatureTest {
206 #if __has_feature(attribute_unused_on_fields)
207   int unused_; // expected-warning{{private field 'unused_' is not used}}
208   int unused2_ __attribute__((unused)); // no-warning
209 #endif
210 };
211 
212 namespace templates {
213 class B {
214   template <typename T> void f(T t);
215   int a;
216 };
217 }  // namespace templates
218 
219 namespace mutual_friends {
220 // Undefined methods make mutual friends undefined.
221 class A {
222   int a;
223   friend class B;
224   void doSomethingToAOrB();
225 };
226 class B {
227   int b;
228   friend class A;
229 };
230 
231 // Undefined friends do not make a mutual friend undefined.
232 class C {
233   int c;
234   void doSomethingElse() {}
235   friend class E;
236   friend class D;
237 };
238 class D {
239   int d; // expected-warning{{private field 'd' is not used}}
240   friend class C;
241 };
242 
243 // Undefined nested classes make mutual friends undefined.
244 class F {
245   int f;
246   class G;
247   friend class H;
248 };
249 class H {
250   int h;
251   friend class F;
252 };
253 }  // namespace mutual_friends
254 
255 namespace anonymous_structs_unions {
256 class A {
257  private:
258   // FIXME: Look at the DeclContext for anonymous structs/unions.
259   union {
260     int *Aligner;
261     unsigned char Data[8];
262   };
263 };
264 union S {
265  private:
266   int *Aligner;
267   unsigned char Data[8];
268 };
269 }  // namespace anonymous_structs_unions
270 
271 namespace pr13413 {
272 class A {
273   A() : p_(__null), b_(false), a_(this), p2_(nullptr) {}
274   void* p_;  // expected-warning{{private field 'p_' is not used}}
275   bool b_;  // expected-warning{{private field 'b_' is not used}}
276   A* a_;  // expected-warning{{private field 'a_' is not used}}
277   void* p2_;  // expected-warning{{private field 'p2_' is not used}}
278 };
279 }
280 
281 namespace pr13543 {
282   void f(int);
283   void f(char);
284   struct S {
285     S() : p(&f) {}
286   private:
287     void (*p)(int); // expected-warning{{private field 'p' is not used}}
288   };
289 
290   struct A { int n; };
291   struct B {
292     B() : a(A()) {}
293     B(char) {}
294     B(int n) : a{n}, b{(f(n), 0)} {}
295   private:
296     A a = A(); // expected-warning{{private field 'a' is not used}}
297     A b;
298   };
299 
300   struct X { ~X(); };
301   class C {
302     X x[4]; // no-warning
303   };
304 }
305 
306 class implicit_special_member {
307 public:
308   static implicit_special_member make() { return implicit_special_member(); }
309 
310 private:
311   int n; // expected-warning{{private field 'n' is not used}}
312 };
313 
314 class defaulted_special_member {
315 public:
316   defaulted_special_member(const defaulted_special_member&) = default;
317 
318 private:
319   int n; // expected-warning{{private field 'n' is not used}}
320 };
321 
322 namespace pr61334 {
323 class [[maybe_unused]] MaybeUnusedClass {};
324 enum [[maybe_unused]] MaybeUnusedEnum {};
325 typedef int MaybeUnusedTypedef [[maybe_unused]];
326 class C {
327   MaybeUnusedClass c; // no-warning
328   MaybeUnusedEnum e; // no-warning
329   MaybeUnusedTypedef t; // no-warning
330 };
331 }
332 
333 namespace GH62472 {
334 class [[gnu::warn_unused]] S {
335 public:
336   S();
337 };
338 
339 struct [[maybe_unused]] T {};
340 
341 void f() {
342   int i = 0; // expected-warning {{unused variable 'i'}}
343   S s;       // expected-warning {{unused variable 's'}}
344   T t;       // ok
345 }
346 
347 class C {
348 private:
349   const int i = 0; // expected-warning {{private field 'i' is not used}}
350   int j = 0;       // expected-warning {{private field 'j' is not used}}
351   const S s1;      // expected-warning {{private field 's1' is not used}}
352   const T t1;      // ok
353   S s2;            // expected-warning {{private field 's2' is not used}}
354   T t2;            // ok
355 };
356 }
357