forked from OSchip/llvm-project
323 lines
13 KiB
C++
323 lines
13 KiB
C++
// 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
|