344 lines · cpp
1// RUN: %check_clang_tidy %s cppcoreguidelines-virtual-class-destructor %t -- --fix-notes2 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 virtual5// CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected6// 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 { // OK15 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-virtual21struct 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-virtual31struct 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 virtual41// CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected42// 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 virtual52struct 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 virtual65// 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 virtual73// 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 { // OK82 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 virtual90// CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected91// 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 { // OK98 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-virtual106class 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 virtual116// 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 virtual125// 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 virtual138class 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 { // OK154public: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 virtual163// CHECK-FIXES: class OverridingDerivedClass : ProtectedNonVirtualClass {164// CHECK-FIXES-NEXT: public:165// CHECK-FIXES-NEXT: virtual ~OverridingDerivedClass() = default;166// CHECK-FIXES-NEXT: void f() override; // is implicitly virtual167// CHECK-FIXES-NEXT: };168class OverridingDerivedClass : ProtectedNonVirtualClass {169public:170 void f() override; // is implicitly virtual171};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 virtual175// 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 method184 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 virtual187// CHECK-FIXES: struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct {188// CHECK-FIXES-NEXT: virtual ~OverridingDerivedStruct() = default;189// CHECK-FIXES-NEXT: void f() override; // is implicitly virtual190// CHECK-FIXES-NEXT: };191struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct {192 void f() override; // is implicitly virtual193};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 virtual197// 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 method205 206namespace Bugzilla_51912 {207// Fixes https://bugs.llvm.org/show_bug.cgi?id=51912208 209// Forward declarations210// 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 Template217// 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 dtor225// 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 dtor234// 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 virtual236// 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 typedef248// 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 typedef258// 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 virtual260// 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_51912273 274namespace macro_tests {275#define MY_VIRTUAL virtual276#define CONCAT(x, y) x##y277 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-virtual280class FooBar1 {281protected:282 CONCAT(vir, tual) CONCAT(~Foo, Bar1()); // no-fixit283};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-virtual287class FooBar2 {288protected:289 virtual CONCAT(~Foo, Bar2()); // FIXME: We should have a fixit for this.290};291 292// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar3' is protected and virtual [cppcoreguidelines-virtual-class-destructor]293// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual294class FooBar3 {295protected:296 CONCAT(vir, tual) ~FooBar3(); // FIXME: We should have a fixit for this.297};298 299// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar4' is protected and virtual [cppcoreguidelines-virtual-class-destructor]300// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual301class FooBar4 {302protected:303 CONCAT(vir, tual) ~CONCAT(Foo, Bar4()); // FIXME: We should have a fixit for this.304};305 306// CHECK-MESSAGES: :[[@LINE+3]]:7: warning: destructor of 'FooBar5' is protected and virtual [cppcoreguidelines-virtual-class-destructor]307// CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected and non-virtual308#define XMACRO(COLUMN1, COLUMN2) COLUMN1 COLUMN2309class FooBar5 {310protected:311 XMACRO(CONCAT(vir, tual), ~CONCAT(Foo, Bar5());) // no-crash, no-fixit312};313 314// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar6' is protected and virtual [cppcoreguidelines-virtual-class-destructor]315// CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual316class FooBar6 {317protected:318 MY_VIRTUAL ~FooBar6(); // FIXME: We should have a fixit for this.319};320 321#undef XMACRO322#undef CONCAT323#undef MY_VIRTUAL324} // namespace macro_tests325 326namespace FinalClassCannotBeBaseClass {327class Base {328public:329 Base() = default;330 virtual void func() = 0;331 332protected:333 ~Base() = default;334};335 336// no-warning: 'MostDerived' cannot be a base class, since it's marked 'final'.337class MostDerived final : public Base {338public:339 MostDerived() = default;340 ~MostDerived() = default;341 void func() final;342};343} // namespace FinalClassCannotBeBaseClass344