1 | // RUN: %clang_cc1 -fsyntax-only -Wunused-private-field -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++11 %s |
2 | // RUN: %clang_cc1 -fsyntax-only -Wunused-private-field -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++17 %s |
3 | |
4 | class NotFullyDefined { |
5 | public: |
6 | NotFullyDefined(); |
7 | private: |
8 | int y; |
9 | }; |
10 | |
11 | class HasUndefinedNestedClass { |
12 | class Undefined; |
13 | int unused_; |
14 | }; |
15 | |
16 | class HasUndefinedPureVirtualDestructor { |
17 | virtual ~HasUndefinedPureVirtualDestructor() = 0; |
18 | int unused_; |
19 | }; |
20 | |
21 | class HasDefinedNestedClasses { |
22 | class DefinedHere {}; |
23 | class DefinedOutside; |
24 | int unused_; // expected-warning{{private field 'unused_' is not used}} |
25 | }; |
26 | class HasDefinedNestedClasses::DefinedOutside {}; |
27 | |
28 | class HasUndefinedFriendFunction { |
29 | friend void undefinedFriendFunction(); |
30 | int unused_; |
31 | }; |
32 | |
33 | class HasUndefinedFriendClass { |
34 | friend class NotFullyDefined; |
35 | friend class NotDefined; |
36 | int unused_; |
37 | }; |
38 | |
39 | class HasFriend { |
40 | friend class FriendClass; |
41 | friend void friendFunction(HasFriend f); |
42 | int unused_; // expected-warning{{private field 'unused_' is not used}} |
43 | int used_by_friend_class_; |
44 | int used_by_friend_function_; |
45 | }; |
46 | |
47 | class ClassWithTemplateFriend { |
48 | template <typename T> friend class TemplateFriend; |
49 | int used_by_friend_; |
50 | int unused_; |
51 | }; |
52 | |
53 | template <typename T> class TemplateFriend { |
54 | public: |
55 | TemplateFriend(ClassWithTemplateFriend my_friend) { |
56 | int var = my_friend.used_by_friend_; |
57 | } |
58 | }; |
59 | |
60 | class FriendClass { |
61 | HasFriend my_friend_; |
62 | void use() { |
63 | my_friend_.used_by_friend_class_ = 42; |
64 | } |
65 | }; |
66 | |
67 | void friendFunction(HasFriend my_friend) { |
68 | my_friend.used_by_friend_function_ = 42; |
69 | } |
70 | |
71 | class NonTrivialConstructor { |
72 | public: |
73 | NonTrivialConstructor() {} |
74 | }; |
75 | |
76 | class NonTrivialDestructor { |
77 | public: |
78 | ~NonTrivialDestructor() {} |
79 | }; |
80 | |
81 | class Trivial { |
82 | public: |
83 | Trivial() = default; |
84 | Trivial(int a) {} |
85 | }; |
86 | |
87 | int side_effect() { |
88 | return 42; |
89 | } |
90 | |
91 | class A { |
92 | public: |
93 | A() : primitive_type_(42), default_initializer_(), other_initializer_(42), |
94 | trivial_(), user_constructor_(42), |
95 | initialized_with_side_effect_(side_effect()) { |
96 | used_ = 42; |
97 | attr_used_ = 42; // expected-warning{{'attr_used_' was marked unused but was used}} |
98 | } |
99 | |
100 | A(int x, A* a) : pointer_(a) {} |
101 | |
102 | private: |
103 | int primitive_type_; // expected-warning{{private field 'primitive_type_' is not used}} |
104 | A* pointer_; // expected-warning{{private field 'pointer_' is not used}} |
105 | int no_initializer_; // expected-warning{{private field 'no_initializer_' is not used}} |
106 | int default_initializer_; // expected-warning{{private field 'default_initializer_' is not used}} |
107 | int other_initializer_; // expected-warning{{private field 'other_initializer_' is not used}} |
108 | int used_, unused_; // expected-warning{{private field 'unused_' is not used}} |
109 | int in_class_initializer_ = 42; // expected-warning{{private field 'in_class_initializer_' is not used}} |
110 | int in_class_initializer_with_side_effect_ = side_effect(); |
111 | Trivial trivial_initializer_ = Trivial(); // expected-warning{{private field 'trivial_initializer_' is not used}} |
112 | Trivial non_trivial_initializer_ = Trivial(42); |
113 | int initialized_with_side_effect_; |
114 | static int static_fields_are_ignored_; |
115 | |
116 | Trivial trivial_; // expected-warning{{private field 'trivial_' is not used}} |
117 | Trivial user_constructor_; |
118 | NonTrivialConstructor non_trivial_constructor_; |
119 | NonTrivialDestructor non_trivial_destructor_; |
120 | |
121 | int attr_ __attribute__((unused)); |
122 | int attr_used_ __attribute__((unused)); |
123 | }; |
124 | |
125 | class EverythingUsed { |
126 | public: |
127 | EverythingUsed() : as_array_index_(0), var_(by_initializer_) { |
128 | var_ = sizeof(sizeof_); |
129 | int *use = &by_reference_; |
130 | int test[2]; |
131 | test[as_array_index_] = 42; |
132 | int EverythingUsed::*ptr = &EverythingUsed::by_pointer_to_member_; |
133 | } |
134 | |
135 | template<class T> |
136 | void useStuff(T t) { |
137 | by_template_function_ = 42; |
138 | } |
139 | |
140 | private: |
141 | int var_; |
142 | int sizeof_; |
143 | int by_reference_; |
144 | int by_template_function_; |
145 | int as_array_index_; |
146 | int by_initializer_; |
147 | int by_pointer_to_member_; |
148 | }; |
149 | |
150 | class HasFeatureTest { |
151 | #if __has_feature(attribute_unused_on_fields) |
152 | int unused_; // expected-warning{{private field 'unused_' is not used}} |
153 | int unused2_ __attribute__((unused)); // no-warning |
154 | #endif |
155 | }; |
156 | |
157 | namespace templates { |
158 | class B { |
159 | template <typename T> void f(T t); |
160 | int a; |
161 | }; |
162 | } // namespace templates |
163 | |
164 | namespace mutual_friends { |
165 | // Undefined methods make mutual friends undefined. |
166 | class A { |
167 | int a; |
168 | friend class B; |
169 | void doSomethingToAOrB(); |
170 | }; |
171 | class B { |
172 | int b; |
173 | friend class A; |
174 | }; |
175 | |
176 | // Undefined friends do not make a mutual friend undefined. |
177 | class C { |
178 | int c; |
179 | void doSomethingElse() {} |
180 | friend class E; |
181 | friend class D; |
182 | }; |
183 | class D { |
184 | int d; // expected-warning{{private field 'd' is not used}} |
185 | friend class C; |
186 | }; |
187 | |
188 | // Undefined nested classes make mutual friends undefined. |
189 | class F { |
190 | int f; |
191 | class G; |
192 | friend class H; |
193 | }; |
194 | class H { |
195 | int h; |
196 | friend class F; |
197 | }; |
198 | } // namespace mutual_friends |
199 | |
200 | namespace anonymous_structs_unions { |
201 | class A { |
202 | private: |
203 | // FIXME: Look at the DeclContext for anonymous structs/unions. |
204 | union { |
205 | int *Aligner; |
206 | unsigned char Data[8]; |
207 | }; |
208 | }; |
209 | union S { |
210 | private: |
211 | int *Aligner; |
212 | unsigned char Data[8]; |
213 | }; |
214 | } // namespace anonymous_structs_unions |
215 | |
216 | namespace pr13413 { |
217 | class A { |
218 | A() : p_(__null), b_(false), a_(this), p2_(nullptr) {} |
219 | void* p_; // expected-warning{{private field 'p_' is not used}} |
220 | bool b_; // expected-warning{{private field 'b_' is not used}} |
221 | A* a_; // expected-warning{{private field 'a_' is not used}} |
222 | void* p2_; // expected-warning{{private field 'p2_' is not used}} |
223 | }; |
224 | } |
225 | |
226 | namespace pr13543 { |
227 | void f(int); |
228 | void f(char); |
229 | struct S { |
230 | S() : p(&f) {} |
231 | private: |
232 | void (*p)(int); // expected-warning{{private field 'p' is not used}} |
233 | }; |
234 | |
235 | struct A { int n; }; |
236 | struct B { |
237 | B() : a(A()) {} |
238 | B(char) {} |
239 | B(int n) : a{n}, b{(f(n), 0)} {} |
240 | private: |
241 | A a = A(); // expected-warning{{private field 'a' is not used}} |
242 | A b; |
243 | }; |
244 | |
245 | struct X { ~X(); }; |
246 | class C { |
247 | X x[4]; // no-warning |
248 | }; |
249 | } |
250 | |
251 | class implicit_special_member { |
252 | public: |
253 | static implicit_special_member make() { return implicit_special_member(); } |
254 | |
255 | private: |
256 | int n; // expected-warning{{private field 'n' is not used}} |
257 | }; |
258 | |
259 | class defaulted_special_member { |
260 | public: |
261 | defaulted_special_member(const defaulted_special_member&) = default; |
262 | |
263 | private: |
264 | int n; // expected-warning{{private field 'n' is not used}} |
265 | }; |
266 | |