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