| // RUN: %check_clang_tidy %s cppcoreguidelines-virtual-class-destructor %t -- --fix-notes |
| |
| // CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PrivateVirtualBaseStruct' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual |
| // CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected |
| // As we have 2 conflicting fixes in notes, no fix is applied. |
| struct PrivateVirtualBaseStruct { |
| virtual void f(); |
| |
| private: |
| virtual ~PrivateVirtualBaseStruct() {} |
| }; |
| |
| struct PublicVirtualBaseStruct { // OK |
| virtual void f(); |
| virtual ~PublicVirtualBaseStruct() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'ProtectedVirtualBaseStruct' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it protected and non-virtual |
| struct ProtectedVirtualBaseStruct { |
| virtual void f(); |
| |
| protected: |
| virtual ~ProtectedVirtualBaseStruct() {} |
| // CHECK-FIXES: ~ProtectedVirtualBaseStruct() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'ProtectedVirtualDefaultBaseStruct' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it protected and non-virtual |
| struct ProtectedVirtualDefaultBaseStruct { |
| virtual void f(); |
| |
| protected: |
| virtual ~ProtectedVirtualDefaultBaseStruct() = default; |
| // CHECK-FIXES: ~ProtectedVirtualDefaultBaseStruct() = default; |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PrivateNonVirtualBaseStruct' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual |
| // CHECK-MESSAGES: :[[@LINE+2]]:8: note: make it protected |
| // As we have 2 conflicting fixes in notes, no fix is applied. |
| struct PrivateNonVirtualBaseStruct { |
| virtual void f(); |
| |
| private: |
| ~PrivateNonVirtualBaseStruct() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: destructor of 'PublicNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+1]]:8: note: make it public and virtual |
| struct PublicNonVirtualBaseStruct { |
| virtual void f(); |
| ~PublicNonVirtualBaseStruct() {} |
| // CHECK-FIXES: virtual ~PublicNonVirtualBaseStruct() {} |
| }; |
| |
| struct PublicNonVirtualNonBaseStruct { // OK according to C.35, since this struct does not have any virtual methods. |
| void f(); |
| ~PublicNonVirtualNonBaseStruct() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+4]]:8: warning: destructor of 'PublicImplicitNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+3]]:8: note: make it public and virtual |
| // CHECK-FIXES: struct PublicImplicitNonVirtualBaseStruct { |
| // CHECK-FIXES-NEXT: virtual ~PublicImplicitNonVirtualBaseStruct() = default; |
| struct PublicImplicitNonVirtualBaseStruct { |
| virtual void f(); |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+5]]:8: warning: destructor of 'PublicASImplicitNonVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+4]]:8: note: make it public and virtual |
| // CHECK-FIXES: struct PublicASImplicitNonVirtualBaseStruct { |
| // CHECK-FIXES-NEXT: virtual ~PublicASImplicitNonVirtualBaseStruct() = default; |
| // CHECK-FIXES-NEXT: private: |
| struct PublicASImplicitNonVirtualBaseStruct { |
| private: |
| virtual void f(); |
| }; |
| |
| struct ProtectedNonVirtualBaseStruct { // OK |
| virtual void f(); |
| |
| protected: |
| ~ProtectedNonVirtualBaseStruct() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+4]]:7: warning: destructor of 'PrivateVirtualBaseClass' is private and prevents using the type [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+3]]:7: note: make it public and virtual |
| // CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected |
| // As we have 2 conflicting fixes in notes, no fix is applied. |
| class PrivateVirtualBaseClass { |
| virtual void f(); |
| virtual ~PrivateVirtualBaseClass() {} |
| }; |
| |
| class PublicVirtualBaseClass { // OK |
| virtual void f(); |
| |
| public: |
| virtual ~PublicVirtualBaseClass() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'ProtectedVirtualBaseClass' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual |
| class ProtectedVirtualBaseClass { |
| virtual void f(); |
| |
| protected: |
| virtual ~ProtectedVirtualBaseClass() {} |
| // CHECK-FIXES: ~ProtectedVirtualBaseClass() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+5]]:7: warning: destructor of 'PublicImplicitNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+4]]:7: note: make it public and virtual |
| // CHECK-FIXES: public: |
| // CHECK-FIXES-NEXT: virtual ~PublicImplicitNonVirtualBaseClass() = default; |
| // CHECK-FIXES-NEXT: }; |
| class PublicImplicitNonVirtualBaseClass { |
| virtual void f(); |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'PublicASImplicitNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it public and virtual |
| // CHECK-FIXES: public: |
| // CHECK-FIXES-NEXT: virtual ~PublicASImplicitNonVirtualBaseClass() = default; |
| // CHECK-FIXES-NEXT: int foo = 42; |
| // CHECK-FIXES-NEXT: }; |
| class PublicASImplicitNonVirtualBaseClass { |
| virtual void f(); |
| |
| public: |
| int foo = 42; |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'PublicNonVirtualBaseClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it public and virtual |
| class PublicNonVirtualBaseClass { |
| virtual void f(); |
| |
| public: |
| ~PublicNonVirtualBaseClass() {} |
| // CHECK-FIXES: virtual ~PublicNonVirtualBaseClass() {} |
| }; |
| |
| class PublicNonVirtualNonBaseClass { // OK accoring to C.35, since this class does not have any virtual methods. |
| void f(); |
| |
| public: |
| ~PublicNonVirtualNonBaseClass() {} |
| }; |
| |
| class ProtectedNonVirtualClass { // OK |
| public: |
| virtual void f(); |
| |
| protected: |
| ~ProtectedNonVirtualClass() {} |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+7]]:7: warning: destructor of 'OverridingDerivedClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+6]]:7: note: make it public and virtual |
| // CHECK-FIXES: class OverridingDerivedClass : ProtectedNonVirtualClass { |
| // CHECK-FIXES-NEXT: public: |
| // CHECK-FIXES-NEXT: virtual ~OverridingDerivedClass() = default; |
| // CHECK-FIXES-NEXT: void f() override; |
| // CHECK-FIXES-NEXT: }; |
| class OverridingDerivedClass : ProtectedNonVirtualClass { |
| public: |
| void f() override; // is implicitly virtual |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+7]]:7: warning: destructor of 'NonOverridingDerivedClass' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+6]]:7: note: make it public and virtual |
| // CHECK-FIXES: class NonOverridingDerivedClass : ProtectedNonVirtualClass { |
| // CHECK-FIXES-NEXT: void m(); |
| // CHECK-FIXES-NEXT: public: |
| // CHECK-FIXES-NEXT: virtual ~NonOverridingDerivedClass() = default; |
| // CHECK-FIXES-NEXT: }; |
| class NonOverridingDerivedClass : ProtectedNonVirtualClass { |
| void m(); |
| }; |
| // inherits virtual method |
| |
| // CHECK-MESSAGES: :[[@LINE+6]]:8: warning: destructor of 'OverridingDerivedStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+5]]:8: note: make it public and virtual |
| // CHECK-FIXES: struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct { |
| // CHECK-FIXES-NEXT: virtual ~OverridingDerivedStruct() = default; |
| // CHECK-FIXES-NEXT: void f() override; |
| // CHECK-FIXES-NEXT: }; |
| struct OverridingDerivedStruct : ProtectedNonVirtualBaseStruct { |
| void f() override; // is implicitly virtual |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+6]]:8: warning: destructor of 'NonOverridingDerivedStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+5]]:8: note: make it public and virtual |
| // CHECK-FIXES: struct NonOverridingDerivedStruct : ProtectedNonVirtualBaseStruct { |
| // CHECK-FIXES-NEXT: virtual ~NonOverridingDerivedStruct() = default; |
| // CHECK-FIXES-NEXT: void m(); |
| // CHECK-FIXES-NEXT: }; |
| struct NonOverridingDerivedStruct : ProtectedNonVirtualBaseStruct { |
| void m(); |
| }; |
| // inherits virtual method |
| |
| namespace Bugzilla_51912 { |
| // Fixes https://bugs.llvm.org/show_bug.cgi?id=51912 |
| |
| // Forward declarations |
| // CHECK-MESSAGES-NOT: :[[@LINE+1]]:8: warning: destructor of 'ForwardDeclaredStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| struct ForwardDeclaredStruct; |
| |
| struct ForwardDeclaredStruct : PublicVirtualBaseStruct { |
| }; |
| |
| // Normal Template |
| // CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'TemplatedDerived' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| template <typename T> |
| struct TemplatedDerived : PublicVirtualBaseStruct { |
| }; |
| |
| TemplatedDerived<int> InstantiationWithInt; |
| |
| // Derived from template, base has virtual dtor |
| // CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'DerivedFromTemplateVirtualBaseStruct' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| template <typename T> |
| struct DerivedFromTemplateVirtualBaseStruct : T { |
| virtual void foo(); |
| }; |
| |
| DerivedFromTemplateVirtualBaseStruct<PublicVirtualBaseStruct> InstantiationWithPublicVirtualBaseStruct; |
| |
| // Derived from template, base has *not* virtual dtor |
| // CHECK-MESSAGES: :[[@LINE+7]]:8: warning: destructor of 'DerivedFromTemplateNonVirtualBaseStruct<PublicNonVirtualBaseStruct>' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+6]]:8: note: make it public and virtual |
| // CHECK-FIXES: struct DerivedFromTemplateNonVirtualBaseStruct : T { |
| // CHECK-FIXES-NEXT: virtual ~DerivedFromTemplateNonVirtualBaseStruct() = default; |
| // CHECK-FIXES-NEXT: virtual void foo(); |
| // CHECK-FIXES-NEXT: }; |
| template <typename T> |
| struct DerivedFromTemplateNonVirtualBaseStruct : T { |
| virtual void foo(); |
| }; |
| |
| DerivedFromTemplateNonVirtualBaseStruct<PublicNonVirtualBaseStruct> InstantiationWithPublicNonVirtualBaseStruct; |
| |
| // Derived from template, base has virtual dtor, to be used in a typedef |
| // CHECK-MESSAGES-NOT: :[[@LINE+2]]:8: warning: destructor of 'DerivedFromTemplateVirtualBaseStruct2' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| template <typename T> |
| struct DerivedFromTemplateVirtualBaseStruct2 : T { |
| virtual void foo(); |
| }; |
| |
| using DerivedFromTemplateVirtualBaseStruct2Typedef = DerivedFromTemplateVirtualBaseStruct2<PublicVirtualBaseStruct>; |
| DerivedFromTemplateVirtualBaseStruct2Typedef InstantiationWithPublicVirtualBaseStruct2; |
| |
| // Derived from template, base has *not* virtual dtor, to be used in a typedef |
| // CHECK-MESSAGES: :[[@LINE+7]]:8: warning: destructor of 'DerivedFromTemplateNonVirtualBaseStruct2<PublicNonVirtualBaseStruct>' is public and non-virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+6]]:8: note: make it public and virtual |
| // CHECK-FIXES: struct DerivedFromTemplateNonVirtualBaseStruct2 : T { |
| // CHECK-FIXES-NEXT: virtual ~DerivedFromTemplateNonVirtualBaseStruct2() = default; |
| // CHECK-FIXES-NEXT: virtual void foo(); |
| // CHECK-FIXES-NEXT: }; |
| template <typename T> |
| struct DerivedFromTemplateNonVirtualBaseStruct2 : T { |
| virtual void foo(); |
| }; |
| |
| using DerivedFromTemplateNonVirtualBaseStruct2Typedef = DerivedFromTemplateNonVirtualBaseStruct2<PublicNonVirtualBaseStruct>; |
| DerivedFromTemplateNonVirtualBaseStruct2Typedef InstantiationWithPublicNonVirtualBaseStruct2; |
| |
| } // namespace Bugzilla_51912 |
| |
| namespace macro_tests { |
| #define CONCAT(x, y) x##y |
| |
| // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar1' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual |
| class FooBar1 { |
| protected: |
| CONCAT(vir, tual) CONCAT(~Foo, Bar1()); // no-fixit |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: destructor of 'FooBar2' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: note: make it protected and non-virtual |
| class FooBar2 { |
| protected: |
| virtual CONCAT(~Foo, Bar2()); // FIXME: We should have a fixit for this. |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'FooBar3' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it protected and non-virtual |
| // CHECK-FIXES: class FooBar3 { |
| // CHECK-FIXES-NEXT: protected: |
| // CHECK-FIXES-NEXT: ~FooBar3(); |
| // CHECK-FIXES-NEXT: }; |
| class FooBar3 { |
| protected: |
| CONCAT(vir, tual) ~FooBar3(); |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+6]]:7: warning: destructor of 'FooBar4' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+5]]:7: note: make it protected and non-virtual |
| // CHECK-FIXES: class FooBar4 { |
| // CHECK-FIXES-NEXT: protected: |
| // CHECK-FIXES-NEXT: ~CONCAT(Foo, Bar4()); |
| // CHECK-FIXES-NEXT: }; |
| class FooBar4 { |
| protected: |
| CONCAT(vir, tual) ~CONCAT(Foo, Bar4()); |
| }; |
| |
| // CHECK-MESSAGES: :[[@LINE+3]]:7: warning: destructor of 'FooBar5' is protected and virtual [cppcoreguidelines-virtual-class-destructor] |
| // CHECK-MESSAGES: :[[@LINE+2]]:7: note: make it protected and non-virtual |
| #define XMACRO(COLUMN1, COLUMN2) COLUMN1 COLUMN2 |
| class FooBar5 { |
| protected: |
| XMACRO(CONCAT(vir, tual), ~CONCAT(Foo, Bar5());) // no-crash, no-fixit |
| }; |
| #undef XMACRO |
| #undef CONCAT |
| } // namespace macro_tests |