1// RUN: %check_clang_tidy %s cppcoreguidelines-virtual-class-destructor %t -- --fix-notes
2
3// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PrivateVirtualBaseStruct' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor]
4// CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual
5// CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected
6// As we have 2 conflicting fixes in notes, no fix is applied.
7struct PrivateVirtualBaseStruct {
8 virtual void f();
9
10private:
11 virtual ~PrivateVirtualBaseStruct() {}
12};
13
14struct PublicVirtualBaseStruct { // OK
15 virtual void f();
16 virtual ~PublicVirtualBaseStruct() {}
17};
18
19// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'ProtectedVirtualBaseStruct' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
20// CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it protected and non-virtual
21struct ProtectedVirtualBaseStruct {
22 virtual void f();
23
24protected:
25 virtual ~ProtectedVirtualBaseStruct() {}
26 // CHECK-FIXES: ~ProtectedVirtualBaseStruct() {}
27};
28
29// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'ProtectedVirtualDefaultBaseStruct' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
30// CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it protected and non-virtual
31struct ProtectedVirtualDefaultBaseStruct {
32 virtual void f();
33
34protected:
35 virtual ~ProtectedVirtualDefaultBaseStruct() = default;
36 // CHECK-FIXES: ~ProtectedVirtualDefaultBaseStruct() = default;
37};
38
39// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PrivateNonVirtualBaseStruct' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor]
40// CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual
41// CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected
42// As we have 2 conflicting fixes in notes, no fix is applied.
43struct PrivateNonVirtualBaseStruct {
44 virtual void f();
45
46private:
47 ~PrivateNonVirtualBaseStruct() {}
48};
49
50// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'PublicNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
51// CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it public and virtual
52struct PublicNonVirtualBaseStruct {
53 virtual void f();
54 ~PublicNonVirtualBaseStruct() {}
55 // CHECK-FIXES: virtual ~PublicNonVirtualBaseStruct() {}
56};
57
58struct PublicNonVirtualNonBaseStruct { // OK according to C.35, since this struct does not have any virtual methods.
59 void f();
60 ~PublicNonVirtualNonBaseStruct() {}
61};
62
63// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PublicImplicitNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
64// CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual
65// CHECK-FIXES: struct PublicImplicitNonVirtualBaseStruct {
66// CHECK-FIXES-NEXT: virtual ~PublicImplicitNonVirtualBaseStruct() = default;
67struct PublicImplicitNonVirtualBaseStruct {
68 virtual void f();
69};
70
71// CHECK-MESSAGES: :[[@LINE+5]]:8: warning: destructor of 'PublicASImplicitNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
72// CHECK-MESSAGES: :[[@LINE+4]]:8: note: make it public and virtual
73// CHECK-FIXES: struct PublicASImplicitNonVirtualBaseStruct {
74// CHECK-FIXES-NEXT: virtual ~PublicASImplicitNonVirtualBaseStruct() = default;
75// CHECK-FIXES-NEXT: private:
76struct PublicASImplicitNonVirtualBaseStruct {
77private:
78 virtual void f();
79};
80
81struct ProtectedNonVirtualBaseStruct { // OK
82 virtual void f();
83
84protected:
85 ~ProtectedNonVirtualBaseStruct() {}
86};
87
88// CHECK-MESSAGES: :[[@LINE+4]]:7: warning: destructor of 'PrivateVirtualBaseClass' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor]
89// CHECK-MESSAGES: :[[@LINE+3]]:7: note: make it public and virtual
90// CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected
91// As we have 2 conflicting fixes in notes, no fix is applied.
92class PrivateVirtualBaseClass {
93 virtual void f();
94 virtual ~PrivateVirtualBaseClass() {}
95};
96
97class PublicVirtualBaseClass { // OK
98 virtual void f();
99
100public:
101 virtual ~PublicVirtualBaseClass() {}
102};
103
104// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'ProtectedVirtualBaseClass' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
105// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
106class ProtectedVirtualBaseClass {
107 virtual void f();
108
109protected:
110 virtual ~ProtectedVirtualBaseClass() {}
111 // CHECK-FIXES: ~ProtectedVirtualBaseClass() {}
112};
113
114// CHECK-MESSAGES: :[[@LINE+5]]:7: warning: destructor of 'PublicImplicitNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
115// CHECK-MESSAGES: :[[@LINE+4]]:7: note: make it public and virtual
116// CHECK-FIXES: public:
117// CHECK-FIXES-NEXT: virtual ~PublicImplicitNonVirtualBaseClass() = default;
118// CHECK-FIXES-NEXT: };
119class PublicImplicitNonVirtualBaseClass {
120 virtual void f();
121};
122
123// CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'PublicASImplicitNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
124// CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it public and virtual
125// CHECK-FIXES: public:
126// CHECK-FIXES-NEXT: virtual ~PublicASImplicitNonVirtualBaseClass() = default;
127// CHECK-FIXES-NEXT: int foo = 42;
128// CHECK-FIXES-NEXT: };
129class PublicASImplicitNonVirtualBaseClass {
130 virtual void f();
131
132public:
133 int foo = 42;
134};
135
136// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'PublicNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
137// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it public and virtual
138class PublicNonVirtualBaseClass {
139 virtual void f();
140
141public:
142 ~PublicNonVirtualBaseClass() {}
143 // CHECK-FIXES: virtual ~PublicNonVirtualBaseClass() {}
144};
145
146class PublicNonVirtualNonBaseClass { // OK according to C.35, since this class does not have any virtual methods.
147 void f();
148
149public:
150 ~PublicNonVirtualNonBaseClass() {}
151};
152
153class ProtectedNonVirtualClass { // OK
154public:
155 virtual void f();
156
157protected:
158 ~ProtectedNonVirtualClass() {}
159};
160
161// CHECK-MESSAGES: :[[@LINE+7]]:7: warning: destructor of 'OverridingDerivedClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
162// CHECK-MESSAGES: :[[@LINE+6]]:7: note: make it public and virtual
163// CHECK-FIXES: class OverridingDerivedClass : ProtectedNonVirtualClass {
164// CHECK-FIXES-NEXT: public:
165// CHECK-FIXES-NEXT: virtual ~OverridingDerivedClass() = default;
166// CHECK-FIXES-NEXT: void f() override;
167// CHECK-FIXES-NEXT: };
168class OverridingDerivedClass : ProtectedNonVirtualClass {
169public:
170 void f() override; // is implicitly virtual
171};
172
173// CHECK-MESSAGES: :[[@LINE+7]]:7: warning: destructor of 'NonOverridingDerivedClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
174// CHECK-MESSAGES: :[[@LINE+6]]:7: note: make it public and virtual
175// CHECK-FIXES: class NonOverridingDerivedClass : ProtectedNonVirtualClass {
176// CHECK-FIXES-NEXT: void m();
177// CHECK-FIXES-NEXT: public:
178// CHECK-FIXES-NEXT: virtual ~NonOverridingDerivedClass() = default;
179// CHECK-FIXES-NEXT: };
180class NonOverridingDerivedClass : ProtectedNonVirtualClass {
181 void m();
182};
183// inherits virtual method
184
185// CHECK-MESSAGES: :[[@LINE+6]]:8: warning: destructor of 'OverridingDerivedStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
186// CHECK-MESSAGES: :[[@LINE+5]]:8: note: make it public and virtual
187// CHECK-FIXES: struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
188// CHECK-FIXES-NEXT: virtual ~OverridingDerivedStruct() = default;
189// CHECK-FIXES-NEXT: void f() override;
190// CHECK-FIXES-NEXT: };
191struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
192 void f() override; // is implicitly virtual
193};
194
195// CHECK-MESSAGES: :[[@LINE+6]]:8: warning: destructor of 'NonOverridingDerivedStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
196// CHECK-MESSAGES: :[[@LINE+5]]:8: note: make it public and virtual
197// CHECK-FIXES: struct NonOverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
198// CHECK-FIXES-NEXT: virtual ~NonOverridingDerivedStruct() = default;
199// CHECK-FIXES-NEXT: void m();
200// CHECK-FIXES-NEXT: };
201struct NonOverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
202 void m();
203};
204// inherits virtual method
205
206namespace Bugzilla_51912 {
207// Fixes https://bugs.llvm.org/show_bug.cgi?id=51912
208
209// Forward declarations
210// CHECK-MESSAGES-NOT: :[[@LINE+1]]:8: warning: destructor of 'ForwardDeclaredStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
211struct ForwardDeclaredStruct;
212
213struct ForwardDeclaredStruct : PublicVirtualBaseStruct {
214};
215
216// Normal Template
217// CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'TemplatedDerived' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
218template <typename T>
219struct TemplatedDerived : PublicVirtualBaseStruct {
220};
221
222TemplatedDerived<int> InstantiationWithInt;
223
224// Derived from template, base has virtual dtor
225// CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'DerivedFromTemplateVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
226template <typename T>
227struct DerivedFromTemplateVirtualBaseStruct : T {
228 virtual void foo();
229};
230
231DerivedFromTemplateVirtualBaseStruct<PublicVirtualBaseStruct> InstantiationWithPublicVirtualBaseStruct;
232
233// Derived from template, base has *not* virtual dtor
234// CHECK-MESSAGES: :[[@LINE+7]]:8: warning: destructor of 'DerivedFromTemplateNonVirtualBaseStruct<PublicNonVirtualBaseStruct>' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
235// CHECK-MESSAGES: :[[@LINE+6]]:8: note: make it public and virtual
236// CHECK-FIXES: struct DerivedFromTemplateNonVirtualBaseStruct : T {
237// CHECK-FIXES-NEXT: virtual ~DerivedFromTemplateNonVirtualBaseStruct() = default;
238// CHECK-FIXES-NEXT: virtual void foo();
239// CHECK-FIXES-NEXT: };
240template <typename T>
241struct DerivedFromTemplateNonVirtualBaseStruct : T {
242 virtual void foo();
243};
244
245DerivedFromTemplateNonVirtualBaseStruct<PublicNonVirtualBaseStruct> InstantiationWithPublicNonVirtualBaseStruct;
246
247// Derived from template, base has virtual dtor, to be used in a typedef
248// CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'DerivedFromTemplateVirtualBaseStruct2' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
249template <typename T>
250struct DerivedFromTemplateVirtualBaseStruct2 : T {
251 virtual void foo();
252};
253
254using DerivedFromTemplateVirtualBaseStruct2Typedef = DerivedFromTemplateVirtualBaseStruct2<PublicVirtualBaseStruct>;
255DerivedFromTemplateVirtualBaseStruct2Typedef InstantiationWithPublicVirtualBaseStruct2;
256
257// Derived from template, base has *not* virtual dtor, to be used in a typedef
258// CHECK-MESSAGES: :[[@LINE+7]]:8: warning: destructor of 'DerivedFromTemplateNonVirtualBaseStruct2<PublicNonVirtualBaseStruct>' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
259// CHECK-MESSAGES: :[[@LINE+6]]:8: note: make it public and virtual
260// CHECK-FIXES: struct DerivedFromTemplateNonVirtualBaseStruct2 : T {
261// CHECK-FIXES-NEXT: virtual ~DerivedFromTemplateNonVirtualBaseStruct2() = default;
262// CHECK-FIXES-NEXT: virtual void foo();
263// CHECK-FIXES-NEXT: };
264template <typename T>
265struct DerivedFromTemplateNonVirtualBaseStruct2 : T {
266 virtual void foo();
267};
268
269using DerivedFromTemplateNonVirtualBaseStruct2Typedef = DerivedFromTemplateNonVirtualBaseStruct2<PublicNonVirtualBaseStruct>;
270DerivedFromTemplateNonVirtualBaseStruct2Typedef InstantiationWithPublicNonVirtualBaseStruct2;
271
272} // namespace Bugzilla_51912
273
274namespace macro_tests {
275#define MY_VIRTUAL virtual
276#define CONCAT(x, y) x##y
277
278// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar1' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
279// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
280class FooBar1 {
281protected:
282 CONCAT(vir, tual) CONCAT(~Foo, Bar1()); // no-fixit
283};
284
285// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar2' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
286// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
287class FooBar2 {
288protected:
289 virtual CONCAT(~Foo, Bar2()); // FIXME: We should have a fixit for this.
290};
291
292// CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'FooBar3' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
293// CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it protected and non-virtual
294// CHECK-FIXES: class FooBar3 {
295// CHECK-FIXES-NEXT: protected:
296// CHECK-FIXES-NEXT: ~FooBar3();
297// CHECK-FIXES-NEXT: };
298class FooBar3 {
299protected:
300 CONCAT(vir, tual) ~FooBar3();
301};
302
303// CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'FooBar4' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
304// CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it protected and non-virtual
305// CHECK-FIXES: class FooBar4 {
306// CHECK-FIXES-NEXT: protected:
307// CHECK-FIXES-NEXT: ~CONCAT(Foo, Bar4());
308// CHECK-FIXES-NEXT: };
309class FooBar4 {
310protected:
311 CONCAT(vir, tual) ~CONCAT(Foo, Bar4());
312};
313
314// CHECK-MESSAGES: :[[@LINE+3]]:7: warning: destructor of 'FooBar5' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
315// CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected and non-virtual
316#define XMACRO(COLUMN1, COLUMN2) COLUMN1 COLUMN2
317class FooBar5 {
318protected:
319 XMACRO(CONCAT(vir, tual), ~CONCAT(Foo, Bar5());) // no-crash, no-fixit
320};
321
322// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar6' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
323// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
324class FooBar6 {
325protected:
326 MY_VIRTUAL ~FooBar6(); // FIXME: We should have a fixit for this.
327};
328
329#undef XMACRO
330#undef CONCAT
331#undef MY_VIRTUAL
332} // namespace macro_tests
333
334namespace FinalClassCannotBeBaseClass {
335class Base {
336public:
337 Base() = default;
338 virtual void func() = 0;
339
340protected:
341 ~Base() = default;
342};
343
344// no-warning: 'MostDerived' cannot be a base class, since it's marked 'final'.
345class MostDerived final : public Base {
346public:
347 MostDerived() = default;
348 ~MostDerived() = default;
349 void func() final;
350};
351} // namespace FinalClassCannotBeBaseClass
352

source code of clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/virtual-class-destructor.cpp