brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · ad84588 Raw
180 lines · cpp
1// RUN: %check_clang_tidy %s bugprone-parent-virtual-call %t2 3extern int foo();4 5class A {6public:7  A() = default;8  virtual ~A() = default;9 10  virtual int virt_1() { return foo() + 1; }11  virtual int virt_2() { return foo() + 2; }12 13  int non_virt() { return foo() + 3; }14  static int stat() { return foo() + 4; }15};16 17class B : public A {18public:19  B() = default;20 21  // Nothing to fix: calls to direct parent.22  int virt_1() override { return A::virt_1() + 3; }23  int virt_2() override { return A::virt_2() + 4; }24};25 26class C : public B {27public:28  int virt_1() override { return A::virt_1() + B::virt_1(); }29  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' refers to a member overridden in subclass; did you mean 'B'? [bugprone-parent-virtual-call]30  // CHECK-FIXES:  int virt_1() override { return B::virt_1() + B::virt_1(); }31  int virt_2() override { return A::virt_1() + B::virt_1(); }32  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'B'? {{.*}}33  // CHECK-FIXES:  int virt_2() override { return B::virt_1() + B::virt_1(); }34 35  // Test that non-virtual and static methods are not affected by this cherker.36  int method_c() { return A::stat() + A::non_virt(); }37};38 39// Check aliased type names40using A1 = A;41typedef A A2;42#define A3 A43 44class C2 : public B {45public:46  int virt_1() override { return A1::virt_1() + A2::virt_1() + A3::virt_1(); }47  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A1::virt_1' {{.*}}; did you mean 'B'? {{.*}}48  // CHECK-MESSAGES: :[[@LINE-2]]:49: warning: qualified name 'A2::virt_1' {{.*}}; did you mean 'B'? {{.*}}49  // CHECK-MESSAGES: :[[@LINE-3]]:64: warning: qualified name 'A3::virt_1' {{.*}}; did you mean 'B'? {{.*}}50  // CHECK-FIXES:  int virt_1() override { return B::virt_1() + B::virt_1() + B::virt_1(); }51};52 53// Test that the check affects grand-grand..-parent calls too.54class D : public C {55public:56  int virt_1() override { return A::virt_1() + B::virt_1() + D::virt_1(); }57  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'C'? {{.*}}58  // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: qualified name 'B::virt_1' {{.*}}; did you mean 'C'? {{.*}}59  // CHECK-FIXES:  int virt_1() override { return C::virt_1() + C::virt_1() + D::virt_1(); }60  int virt_2() override { return A::virt_1() + B::virt_1() + D::virt_1(); }61  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'C'? {{.*}}62  // CHECK-MESSAGES: :[[@LINE-2]]:48: warning: qualified name 'B::virt_1' {{.*}}; did you mean 'C'? {{.*}}63  // CHECK-FIXES:  int virt_2() override { return C::virt_1() + C::virt_1() + D::virt_1(); }64};65 66// Test classes in namespaces.67namespace {68class BN : public A {69public:70  int virt_1() override { return A::virt_1() + 3; }71  int virt_2() override { return A::virt_2() + 4; }72};73} // namespace74 75namespace N1 {76class A {77public:78  A() = default;79  virtual int virt_1() { return foo() + 1; }80  virtual int virt_2() { return foo() + 2; }81};82} // namespace N183 84namespace N2 {85class BN : public N1::A {86public:87  int virt_1() override { return A::virt_1() + 3; }88  int virt_2() override { return A::virt_2() + 4; }89};90} // namespace N291 92class CN : public BN {93public:94  int virt_1() override { return A::virt_1() + BN::virt_1(); }95  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BN'? {{.*}}96  // CHECK-FIXES:  int virt_1() override { return BN::virt_1() + BN::virt_1(); }97  int virt_2() override { return A::virt_1() + BN::virt_1(); }98  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BN'? {{.*}}99  // CHECK-FIXES:  int virt_2() override { return BN::virt_1() + BN::virt_1(); }100};101 102class CNN : public N2::BN {103public:104  int virt_1() override { return N1::A::virt_1() + N2::BN::virt_1(); }105  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'N1::A::virt_1' {{.*}}; did you mean 'N2::BN'? {{.*}}106  // CHECK-FIXES:  int virt_1() override { return N2::BN::virt_1() + N2::BN::virt_1(); }107  int virt_2() override { return N1::A::virt_1() + N2::BN::virt_1(); }108  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'N1::A::virt_1' {{.*}}; did you mean 'N2::BN'? {{.*}}109  // CHECK-FIXES:  int virt_2() override { return N2::BN::virt_1() + N2::BN::virt_1(); }110};111 112// Test multiple inheritance fixes113class AA {114public:115  AA() = default;116  virtual ~AA() = default;117 118  virtual int virt_1() { return foo() + 1; }119  virtual int virt_2() { return foo() + 2; }120 121  int non_virt() { return foo() + 3; }122  static int stat() { return foo() + 4; }123};124 125class BB_1 : virtual public AA {126public:127  BB_1() = default;128 129  // Nothing to fix: calls to parent.130  int virt_1() override { return AA::virt_1() + 3; }131  int virt_2() override { return AA::virt_2() + 4; }132};133 134class BB_2 : virtual public AA {135public:136  BB_2() = default;137  int virt_1() override { return AA::virt_1() + 3; }138};139 140class CC : public BB_1, public BB_2 {141public:142  int virt_1() override { return AA::virt_1() + 3; }143  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'AA::virt_1' refers to a member overridden in subclasses; did you mean 'BB_1' or 'BB_2'? {{.*}}144  // No fix available due to multiple choice of parent class.145};146 147// Test that virtual method is not diagnosed as not overridden in parent.148class BI : public A {149public:150  BI() = default;151};152 153class CI : BI {154  int virt_1() override { return A::virt_1(); }155};156 157// Test templated classes.158template <class F> class BF : public A {159public:160  int virt_1() override { return A::virt_1() + 3; }161};162 163// Test templated parent class.164class CF : public BF<int> {165public:166  int virt_1() override { return A::virt_1(); }167  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BF'? {{.*}}168};169 170// Test both templated class and its parent class.171template <class F> class DF : public BF<F> {172public:173  DF() = default;174  int virt_1() override { return A::virt_1(); }175  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: qualified name 'A::virt_1' {{.*}}; did you mean 'BF'? {{.*}}176};177 178// Just to instantiate DF<F>.179int bar() { return (new DF<int>())->virt_1(); }180