| 1 | // RUN: %check_clang_tidy %s bugprone-virtual-near-miss %t |
| 2 | |
| 3 | class NoDefinedClass1; |
| 4 | class NoDefinedClass2; |
| 5 | |
| 6 | struct Base { |
| 7 | virtual void func(); |
| 8 | virtual void gunk(); |
| 9 | virtual ~Base(); |
| 10 | virtual Base &operator=(const Base &); |
| 11 | virtual NoDefinedClass1 *f(); |
| 12 | }; |
| 13 | |
| 14 | struct Derived : Base { |
| 15 | // Should not warn "do you want to override 'gunk'?", because gunk is already |
| 16 | // overriden by this class. |
| 17 | virtual void funk(); |
| 18 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::funk' has a similar name and the same signature as virtual method 'Base::func'; did you mean to override it? [bugprone-virtual-near-miss] |
| 19 | // CHECK-FIXES: virtual void func(); |
| 20 | |
| 21 | void func2(); |
| 22 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::func2' has {{.*}} 'Base::func' |
| 23 | // CHECK-FIXES: void func(); |
| 24 | |
| 25 | void func22(); // Should not warn. |
| 26 | |
| 27 | void gunk(); // Should not warn: gunk is override. |
| 28 | |
| 29 | void fun(); |
| 30 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::fun' has {{.*}} 'Base::func' |
| 31 | // CHECK-FIXES: void func(); |
| 32 | |
| 33 | Derived &operator==(const Base &); // Should not warn: operators are ignored. |
| 34 | |
| 35 | virtual NoDefinedClass2 *f1(); // Should not crash: non-defined class return type is ignored. |
| 36 | }; |
| 37 | |
| 38 | template <typename T> |
| 39 | struct TBase { |
| 40 | virtual void tfunc(T t); |
| 41 | }; |
| 42 | |
| 43 | template <typename T> |
| 44 | struct TDerived : TBase<T> { |
| 45 | virtual void tfunk(T t); |
| 46 | // Should not apply fix for template. |
| 47 | // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: method 'TDerived<double>::tfunk' has {{.*}} 'TBase<double>::tfunc' |
| 48 | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: method 'TDerived<int>::tfunk' has {{.*}} 'TBase<int>::tfunc' |
| 49 | // CHECK-FIXES: virtual void tfunk(T t); |
| 50 | }; |
| 51 | |
| 52 | TDerived<int> T1; |
| 53 | TDerived<double> T2; |
| 54 | |
| 55 | // Should not fix macro definition |
| 56 | #define MACRO1 void funcM() |
| 57 | // CHECK-FIXES: #define MACRO1 void funcM() |
| 58 | #define MACRO2(m) void m() |
| 59 | // CHECK-FIXES: #define MACRO2(m) void m() |
| 60 | |
| 61 | struct DerivedMacro : Base { |
| 62 | MACRO1; |
| 63 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'DerivedMacro::funcM' has {{.*}} 'Base::func' |
| 64 | // CHECK-FIXES: MACRO1; |
| 65 | |
| 66 | MACRO2(func3); |
| 67 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'DerivedMacro::func3' has {{.*}} 'Base::func' |
| 68 | // CHECK-FIXES: MACRO2(func); |
| 69 | }; |
| 70 | |
| 71 | typedef Derived derived_type; |
| 72 | |
| 73 | class Father { |
| 74 | public: |
| 75 | Father(); |
| 76 | virtual void func(); |
| 77 | virtual Father *create(int i); |
| 78 | virtual Base &&generate(); |
| 79 | virtual Base *canonical(Derived D); |
| 80 | }; |
| 81 | |
| 82 | class Mother { |
| 83 | public: |
| 84 | Mother(); |
| 85 | static void method(); |
| 86 | virtual int method(int argc, const char **argv); |
| 87 | virtual int method(int argc) const; |
| 88 | virtual int decay(const char *str); |
| 89 | }; |
| 90 | |
| 91 | class Child : private Father, private Mother { |
| 92 | public: |
| 93 | Child(); |
| 94 | |
| 95 | virtual void func2(); |
| 96 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::func2' has {{.*}} 'Father::func' |
| 97 | // CHECK-FIXES: virtual void func(); |
| 98 | |
| 99 | int methoe(int x, char **strs); // Should not warn: parameter types don't match. |
| 100 | |
| 101 | int methoe(int x); |
| 102 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::methoe' has {{.*}} 'Mother::method' |
| 103 | // CHECK-FIXES: int method(int x); |
| 104 | |
| 105 | void methof(int x, const char **strs); // Should not warn: return types don't match. |
| 106 | |
| 107 | int methoh(int x, const char **strs); |
| 108 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::methoh' has {{.*}} 'Mother::method' |
| 109 | // CHECK-FIXES: int method(int x, const char **strs); |
| 110 | |
| 111 | virtual Child *creat(int i); |
| 112 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::creat' has {{.*}} 'Father::create' |
| 113 | // CHECK-FIXES: virtual Child *create(int i); |
| 114 | |
| 115 | virtual Derived &&generat(); |
| 116 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::generat' has {{.*}} 'Father::generate' |
| 117 | // CHECK-FIXES: virtual Derived &&generate(); |
| 118 | |
| 119 | int decaz(const char str[]); |
| 120 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::decaz' has {{.*}} 'Mother::decay' |
| 121 | // CHECK-FIXES: int decay(const char str[]); |
| 122 | |
| 123 | operator bool(); |
| 124 | |
| 125 | derived_type *canonica(derived_type D); |
| 126 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::canonica' has {{.*}} 'Father::canonical' |
| 127 | // CHECK-FIXES: derived_type *canonical(derived_type D); |
| 128 | |
| 129 | private: |
| 130 | void funk(); |
| 131 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::funk' has {{.*}} 'Father::func' |
| 132 | // CHECK-FIXES: void func(); |
| 133 | }; |
| 134 | |