189a1d03eSRichard // RUN: %check_clang_tidy %s cppcoreguidelines-virtual-class-destructor %t -- --fix-notes
289a1d03eSRichard 
389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PrivateVirtualBaseStruct' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor]
489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual
589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected
689a1d03eSRichard // As we have 2 conflicting fixes in notes, no fix is applied.
789a1d03eSRichard struct PrivateVirtualBaseStruct {
889a1d03eSRichard   virtual void f();
989a1d03eSRichard 
1089a1d03eSRichard private:
~PrivateVirtualBaseStructPrivateVirtualBaseStruct1189a1d03eSRichard   virtual ~PrivateVirtualBaseStruct() {}
1289a1d03eSRichard };
1389a1d03eSRichard 
1489a1d03eSRichard struct PublicVirtualBaseStruct { // OK
1589a1d03eSRichard   virtual void f();
~PublicVirtualBaseStructPublicVirtualBaseStruct1689a1d03eSRichard   virtual ~PublicVirtualBaseStruct() {}
1789a1d03eSRichard };
1889a1d03eSRichard 
1989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'ProtectedVirtualBaseStruct' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
2089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it protected and non-virtual
2189a1d03eSRichard struct ProtectedVirtualBaseStruct {
2289a1d03eSRichard   virtual void f();
2389a1d03eSRichard 
2489a1d03eSRichard protected:
~ProtectedVirtualBaseStructProtectedVirtualBaseStruct2589a1d03eSRichard   virtual ~ProtectedVirtualBaseStruct() {}
2689a1d03eSRichard   // CHECK-FIXES: ~ProtectedVirtualBaseStruct() {}
2789a1d03eSRichard };
2889a1d03eSRichard 
2989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'ProtectedVirtualDefaultBaseStruct' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
3089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it protected and non-virtual
3189a1d03eSRichard struct ProtectedVirtualDefaultBaseStruct {
3289a1d03eSRichard   virtual void f();
3389a1d03eSRichard 
3489a1d03eSRichard protected:
3589a1d03eSRichard   virtual ~ProtectedVirtualDefaultBaseStruct() = default;
3689a1d03eSRichard   // CHECK-FIXES: ~ProtectedVirtualDefaultBaseStruct() = default;
3789a1d03eSRichard };
3889a1d03eSRichard 
3989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PrivateNonVirtualBaseStruct' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor]
4089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual
4189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected
4289a1d03eSRichard // As we have 2 conflicting fixes in notes, no fix is applied.
4389a1d03eSRichard struct PrivateNonVirtualBaseStruct {
4489a1d03eSRichard   virtual void f();
4589a1d03eSRichard 
4689a1d03eSRichard private:
~PrivateNonVirtualBaseStructPrivateNonVirtualBaseStruct4789a1d03eSRichard   ~PrivateNonVirtualBaseStruct() {}
4889a1d03eSRichard };
4989a1d03eSRichard 
5089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'PublicNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
5189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it public and virtual
5289a1d03eSRichard struct PublicNonVirtualBaseStruct {
5389a1d03eSRichard   virtual void f();
~PublicNonVirtualBaseStructPublicNonVirtualBaseStruct5489a1d03eSRichard   ~PublicNonVirtualBaseStruct() {}
5589a1d03eSRichard   // CHECK-FIXES: virtual ~PublicNonVirtualBaseStruct() {}
5689a1d03eSRichard };
5789a1d03eSRichard 
5889a1d03eSRichard struct PublicNonVirtualNonBaseStruct { // OK according to C.35, since this struct does not have any virtual methods.
5989a1d03eSRichard   void f();
~PublicNonVirtualNonBaseStructPublicNonVirtualNonBaseStruct6089a1d03eSRichard   ~PublicNonVirtualNonBaseStruct() {}
6189a1d03eSRichard };
6289a1d03eSRichard 
6389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PublicImplicitNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
6489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual
6589a1d03eSRichard // CHECK-FIXES: struct PublicImplicitNonVirtualBaseStruct {
6689a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~PublicImplicitNonVirtualBaseStruct() = default;
6789a1d03eSRichard struct PublicImplicitNonVirtualBaseStruct {
6889a1d03eSRichard   virtual void f();
6989a1d03eSRichard };
7089a1d03eSRichard 
7189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+5]]:8: warning: destructor of 'PublicASImplicitNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
7289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+4]]:8: note: make it public and virtual
7389a1d03eSRichard // CHECK-FIXES: struct PublicASImplicitNonVirtualBaseStruct {
7489a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~PublicASImplicitNonVirtualBaseStruct() = default;
7589a1d03eSRichard // CHECK-FIXES-NEXT: private:
7689a1d03eSRichard struct PublicASImplicitNonVirtualBaseStruct {
7789a1d03eSRichard private:
7889a1d03eSRichard   virtual void f();
7989a1d03eSRichard };
8089a1d03eSRichard 
8189a1d03eSRichard struct ProtectedNonVirtualBaseStruct { // OK
8289a1d03eSRichard   virtual void f();
8389a1d03eSRichard 
8489a1d03eSRichard protected:
~ProtectedNonVirtualBaseStructProtectedNonVirtualBaseStruct8589a1d03eSRichard   ~ProtectedNonVirtualBaseStruct() {}
8689a1d03eSRichard };
8789a1d03eSRichard 
8889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+4]]:7: warning: destructor of 'PrivateVirtualBaseClass' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor]
8989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+3]]:7: note: make it public and virtual
9089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected
9189a1d03eSRichard // As we have 2 conflicting fixes in notes, no fix is applied.
9289a1d03eSRichard class PrivateVirtualBaseClass {
9389a1d03eSRichard   virtual void f();
~PrivateVirtualBaseClass()9489a1d03eSRichard   virtual ~PrivateVirtualBaseClass() {}
9589a1d03eSRichard };
9689a1d03eSRichard 
9789a1d03eSRichard class PublicVirtualBaseClass { // OK
9889a1d03eSRichard   virtual void f();
9989a1d03eSRichard 
10089a1d03eSRichard public:
~PublicVirtualBaseClass()10189a1d03eSRichard   virtual ~PublicVirtualBaseClass() {}
10289a1d03eSRichard };
10389a1d03eSRichard 
10489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'ProtectedVirtualBaseClass' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
10589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
10689a1d03eSRichard class ProtectedVirtualBaseClass {
10789a1d03eSRichard   virtual void f();
10889a1d03eSRichard 
10989a1d03eSRichard protected:
~ProtectedVirtualBaseClass()11089a1d03eSRichard   virtual ~ProtectedVirtualBaseClass() {}
11189a1d03eSRichard   // CHECK-FIXES: ~ProtectedVirtualBaseClass() {}
11289a1d03eSRichard };
11389a1d03eSRichard 
11489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+5]]:7: warning: destructor of 'PublicImplicitNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
11589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+4]]:7: note: make it public and virtual
11689a1d03eSRichard // CHECK-FIXES: public:
11789a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~PublicImplicitNonVirtualBaseClass() = default;
11889a1d03eSRichard // CHECK-FIXES-NEXT: };
11989a1d03eSRichard class PublicImplicitNonVirtualBaseClass {
12089a1d03eSRichard   virtual void f();
12189a1d03eSRichard };
12289a1d03eSRichard 
12389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'PublicASImplicitNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
12489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it public and virtual
12589a1d03eSRichard // CHECK-FIXES: public:
12689a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~PublicASImplicitNonVirtualBaseClass() = default;
12789a1d03eSRichard // CHECK-FIXES-NEXT: int foo = 42;
12889a1d03eSRichard // CHECK-FIXES-NEXT: };
12989a1d03eSRichard class PublicASImplicitNonVirtualBaseClass {
13089a1d03eSRichard   virtual void f();
13189a1d03eSRichard 
13289a1d03eSRichard public:
13389a1d03eSRichard   int foo = 42;
13489a1d03eSRichard };
13589a1d03eSRichard 
13689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'PublicNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
13789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it public and virtual
13889a1d03eSRichard class PublicNonVirtualBaseClass {
13989a1d03eSRichard   virtual void f();
14089a1d03eSRichard 
14189a1d03eSRichard public:
~PublicNonVirtualBaseClass()14289a1d03eSRichard   ~PublicNonVirtualBaseClass() {}
14389a1d03eSRichard   // CHECK-FIXES: virtual ~PublicNonVirtualBaseClass() {}
14489a1d03eSRichard };
14589a1d03eSRichard 
146*0ed2bd93SGabriel Ravier class PublicNonVirtualNonBaseClass { // OK according to C.35, since this class does not have any virtual methods.
14789a1d03eSRichard   void f();
14889a1d03eSRichard 
14989a1d03eSRichard public:
~PublicNonVirtualNonBaseClass()15089a1d03eSRichard   ~PublicNonVirtualNonBaseClass() {}
15189a1d03eSRichard };
15289a1d03eSRichard 
15389a1d03eSRichard class ProtectedNonVirtualClass { // OK
15489a1d03eSRichard public:
15589a1d03eSRichard   virtual void f();
15689a1d03eSRichard 
15789a1d03eSRichard protected:
~ProtectedNonVirtualClass()15889a1d03eSRichard   ~ProtectedNonVirtualClass() {}
15989a1d03eSRichard };
16089a1d03eSRichard 
16189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+7]]:7: warning: destructor of 'OverridingDerivedClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
16289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:7: note: make it public and virtual
16389a1d03eSRichard // CHECK-FIXES: class OverridingDerivedClass : ProtectedNonVirtualClass {
16489a1d03eSRichard // CHECK-FIXES-NEXT: public:
16589a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~OverridingDerivedClass() = default;
16689a1d03eSRichard // CHECK-FIXES-NEXT: void f() override;
16789a1d03eSRichard // CHECK-FIXES-NEXT: };
16889a1d03eSRichard class OverridingDerivedClass : ProtectedNonVirtualClass {
16989a1d03eSRichard public:
17089a1d03eSRichard   void f() override; // is implicitly virtual
17189a1d03eSRichard };
17289a1d03eSRichard 
17389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+7]]:7: warning: destructor of 'NonOverridingDerivedClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
17489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:7: note: make it public and virtual
17589a1d03eSRichard // CHECK-FIXES: class NonOverridingDerivedClass : ProtectedNonVirtualClass {
17689a1d03eSRichard // CHECK-FIXES-NEXT: void m();
17789a1d03eSRichard // CHECK-FIXES-NEXT: public:
17889a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~NonOverridingDerivedClass() = default;
17989a1d03eSRichard // CHECK-FIXES-NEXT: };
18089a1d03eSRichard class NonOverridingDerivedClass : ProtectedNonVirtualClass {
18189a1d03eSRichard   void m();
18289a1d03eSRichard };
18389a1d03eSRichard // inherits virtual method
18489a1d03eSRichard 
18589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:8: warning: destructor of 'OverridingDerivedStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
18689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+5]]:8: note: make it public and virtual
18789a1d03eSRichard // CHECK-FIXES: struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
18889a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~OverridingDerivedStruct() = default;
18989a1d03eSRichard // CHECK-FIXES-NEXT: void f() override;
19089a1d03eSRichard // CHECK-FIXES-NEXT: };
19189a1d03eSRichard struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
19289a1d03eSRichard   void f() override; // is implicitly virtual
19389a1d03eSRichard };
19489a1d03eSRichard 
19589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:8: warning: destructor of 'NonOverridingDerivedStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
19689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+5]]:8: note: make it public and virtual
19789a1d03eSRichard // CHECK-FIXES: struct NonOverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
19889a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~NonOverridingDerivedStruct() = default;
19989a1d03eSRichard // CHECK-FIXES-NEXT: void m();
20089a1d03eSRichard // CHECK-FIXES-NEXT: };
20189a1d03eSRichard struct NonOverridingDerivedStruct : ProtectedNonVirtualBaseStruct {
20289a1d03eSRichard   void m();
20389a1d03eSRichard };
20489a1d03eSRichard // inherits virtual method
20589a1d03eSRichard 
20689a1d03eSRichard namespace Bugzilla_51912 {
20789a1d03eSRichard // Fixes https://bugs.llvm.org/show_bug.cgi?id=51912
20889a1d03eSRichard 
20989a1d03eSRichard // Forward declarations
21089a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE+1]]:8: warning: destructor of 'ForwardDeclaredStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
21189a1d03eSRichard struct ForwardDeclaredStruct;
21289a1d03eSRichard 
21389a1d03eSRichard struct ForwardDeclaredStruct : PublicVirtualBaseStruct {
21489a1d03eSRichard };
21589a1d03eSRichard 
21689a1d03eSRichard // Normal Template
21789a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'TemplatedDerived' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
21889a1d03eSRichard template <typename T>
21989a1d03eSRichard struct TemplatedDerived : PublicVirtualBaseStruct {
22089a1d03eSRichard };
22189a1d03eSRichard 
22289a1d03eSRichard TemplatedDerived<int> InstantiationWithInt;
22389a1d03eSRichard 
22489a1d03eSRichard // Derived from template, base has virtual dtor
22589a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'DerivedFromTemplateVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
22689a1d03eSRichard template <typename T>
22789a1d03eSRichard struct DerivedFromTemplateVirtualBaseStruct : T {
22889a1d03eSRichard   virtual void foo();
22989a1d03eSRichard };
23089a1d03eSRichard 
23189a1d03eSRichard DerivedFromTemplateVirtualBaseStruct<PublicVirtualBaseStruct> InstantiationWithPublicVirtualBaseStruct;
23289a1d03eSRichard 
23389a1d03eSRichard // Derived from template, base has *not* virtual dtor
23489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+7]]:8: warning: destructor of 'DerivedFromTemplateNonVirtualBaseStruct<PublicNonVirtualBaseStruct>' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
23589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:8: note: make it public and virtual
23689a1d03eSRichard // CHECK-FIXES: struct DerivedFromTemplateNonVirtualBaseStruct : T {
23789a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~DerivedFromTemplateNonVirtualBaseStruct() = default;
23889a1d03eSRichard // CHECK-FIXES-NEXT: virtual void foo();
23989a1d03eSRichard // CHECK-FIXES-NEXT: };
24089a1d03eSRichard template <typename T>
24189a1d03eSRichard struct DerivedFromTemplateNonVirtualBaseStruct : T {
24289a1d03eSRichard   virtual void foo();
24389a1d03eSRichard };
24489a1d03eSRichard 
24589a1d03eSRichard DerivedFromTemplateNonVirtualBaseStruct<PublicNonVirtualBaseStruct> InstantiationWithPublicNonVirtualBaseStruct;
24689a1d03eSRichard 
24789a1d03eSRichard // Derived from template, base has virtual dtor, to be used in a typedef
24889a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'DerivedFromTemplateVirtualBaseStruct2' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
24989a1d03eSRichard template <typename T>
25089a1d03eSRichard struct DerivedFromTemplateVirtualBaseStruct2 : T {
25189a1d03eSRichard   virtual void foo();
25289a1d03eSRichard };
25389a1d03eSRichard 
25489a1d03eSRichard using DerivedFromTemplateVirtualBaseStruct2Typedef = DerivedFromTemplateVirtualBaseStruct2<PublicVirtualBaseStruct>;
25589a1d03eSRichard DerivedFromTemplateVirtualBaseStruct2Typedef InstantiationWithPublicVirtualBaseStruct2;
25689a1d03eSRichard 
25789a1d03eSRichard // Derived from template, base has *not* virtual dtor, to be used in a typedef
25889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+7]]:8: warning: destructor of 'DerivedFromTemplateNonVirtualBaseStruct2<PublicNonVirtualBaseStruct>' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]
25989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:8: note: make it public and virtual
26089a1d03eSRichard // CHECK-FIXES: struct DerivedFromTemplateNonVirtualBaseStruct2 : T {
26189a1d03eSRichard // CHECK-FIXES-NEXT: virtual ~DerivedFromTemplateNonVirtualBaseStruct2() = default;
26289a1d03eSRichard // CHECK-FIXES-NEXT: virtual void foo();
26389a1d03eSRichard // CHECK-FIXES-NEXT: };
26489a1d03eSRichard template <typename T>
26589a1d03eSRichard struct DerivedFromTemplateNonVirtualBaseStruct2 : T {
26689a1d03eSRichard   virtual void foo();
26789a1d03eSRichard };
26889a1d03eSRichard 
26989a1d03eSRichard using DerivedFromTemplateNonVirtualBaseStruct2Typedef = DerivedFromTemplateNonVirtualBaseStruct2<PublicNonVirtualBaseStruct>;
27089a1d03eSRichard DerivedFromTemplateNonVirtualBaseStruct2Typedef InstantiationWithPublicNonVirtualBaseStruct2;
27189a1d03eSRichard 
27289a1d03eSRichard } // namespace Bugzilla_51912
27389a1d03eSRichard 
27489a1d03eSRichard namespace macro_tests {
275b2cb7e81SJoachim Priesner #define MY_VIRTUAL virtual
27689a1d03eSRichard #define CONCAT(x, y) x##y
27789a1d03eSRichard 
27889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar1' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
27989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
28089a1d03eSRichard class FooBar1 {
28189a1d03eSRichard protected:
28289a1d03eSRichard   CONCAT(vir, tual) CONCAT(~Foo, Bar1()); // no-fixit
28389a1d03eSRichard };
28489a1d03eSRichard 
28589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar2' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
28689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
28789a1d03eSRichard class FooBar2 {
28889a1d03eSRichard protected:
28989a1d03eSRichard   virtual CONCAT(~Foo, Bar2()); // FIXME: We should have a fixit for this.
29089a1d03eSRichard };
29189a1d03eSRichard 
29289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'FooBar3' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
29389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it protected and non-virtual
29489a1d03eSRichard // CHECK-FIXES:      class FooBar3 {
29589a1d03eSRichard // CHECK-FIXES-NEXT: protected:
29689a1d03eSRichard // CHECK-FIXES-NEXT:   ~FooBar3();
29789a1d03eSRichard // CHECK-FIXES-NEXT: };
29889a1d03eSRichard class FooBar3 {
29989a1d03eSRichard protected:
30089a1d03eSRichard   CONCAT(vir, tual) ~FooBar3();
30189a1d03eSRichard };
30289a1d03eSRichard 
30389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'FooBar4' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
30489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it protected and non-virtual
30589a1d03eSRichard // CHECK-FIXES:      class FooBar4 {
30689a1d03eSRichard // CHECK-FIXES-NEXT: protected:
30789a1d03eSRichard // CHECK-FIXES-NEXT:   ~CONCAT(Foo, Bar4());
30889a1d03eSRichard // CHECK-FIXES-NEXT: };
30989a1d03eSRichard class FooBar4 {
31089a1d03eSRichard protected:
31189a1d03eSRichard   CONCAT(vir, tual) ~CONCAT(Foo, Bar4());
31289a1d03eSRichard };
31389a1d03eSRichard 
31489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+3]]:7: warning: destructor of 'FooBar5' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
31589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected and non-virtual
31689a1d03eSRichard #define XMACRO(COLUMN1, COLUMN2) COLUMN1 COLUMN2
31789a1d03eSRichard class FooBar5 {
31889a1d03eSRichard protected:
31989a1d03eSRichard   XMACRO(CONCAT(vir, tual), ~CONCAT(Foo, Bar5());) // no-crash, no-fixit
32089a1d03eSRichard };
321b2cb7e81SJoachim Priesner 
322b2cb7e81SJoachim Priesner // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar6' is protected and virtual [cppcoreguidelines-virtual-class-destructor]
323b2cb7e81SJoachim Priesner // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual
324b2cb7e81SJoachim Priesner class FooBar6 {
325b2cb7e81SJoachim Priesner protected:
326b2cb7e81SJoachim Priesner   MY_VIRTUAL ~FooBar6(); // FIXME: We should have a fixit for this.
327b2cb7e81SJoachim Priesner };
328b2cb7e81SJoachim Priesner 
32989a1d03eSRichard #undef XMACRO
33089a1d03eSRichard #undef CONCAT
331b2cb7e81SJoachim Priesner #undef MY_VIRTUAL
33289a1d03eSRichard } // namespace macro_tests
33389a1d03eSRichard 
33489a1d03eSRichard namespace FinalClassCannotBeBaseClass {
33589a1d03eSRichard class Base {
33689a1d03eSRichard public:
33789a1d03eSRichard   Base() = default;
33889a1d03eSRichard   virtual void func() = 0;
33989a1d03eSRichard 
34089a1d03eSRichard protected:
34189a1d03eSRichard   ~Base() = default;
34289a1d03eSRichard };
34389a1d03eSRichard 
34489a1d03eSRichard // no-warning: 'MostDerived' cannot be a base class, since it's marked 'final'.
34589a1d03eSRichard class MostDerived final : public Base {
34689a1d03eSRichard public:
34789a1d03eSRichard   MostDerived() = default;
34889a1d03eSRichard   ~MostDerived() = default;
34989a1d03eSRichard   void func() final;
35089a1d03eSRichard };
35189a1d03eSRichard } // namespace FinalClassCannotBeBaseClass
352