| 1 | // RUN: %check_clang_tidy %s fuchsia-multiple-inheritance %t |
| 2 | |
| 3 | class Base_A { |
| 4 | public: |
| 5 | virtual int foo() { return 0; } |
| 6 | }; |
| 7 | |
| 8 | class Base_B { |
| 9 | public: |
| 10 | virtual int bar() { return 0; } |
| 11 | }; |
| 12 | |
| 13 | class Base_A_child : public Base_A { |
| 14 | public: |
| 15 | virtual int baz() { return 0; } |
| 16 | }; |
| 17 | |
| 18 | class Interface_A { |
| 19 | public: |
| 20 | virtual int foo() = 0; |
| 21 | }; |
| 22 | |
| 23 | class Interface_B { |
| 24 | public: |
| 25 | virtual int bar() = 0; |
| 26 | }; |
| 27 | |
| 28 | class Interface_C { |
| 29 | public: |
| 30 | virtual int blat() = 0; |
| 31 | }; |
| 32 | |
| 33 | class Interface_A_with_member { |
| 34 | public: |
| 35 | virtual int foo() = 0; |
| 36 | int val = 0; |
| 37 | }; |
| 38 | |
| 39 | class Interface_with_A_Parent : public Base_A { |
| 40 | public: |
| 41 | virtual int baz() = 0; |
| 42 | }; |
| 43 | |
| 44 | // Shouldn't warn on forward declarations. |
| 45 | class Bad_Child1; |
| 46 | |
| 47 | // Inherits from multiple concrete classes. |
| 48 | // CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] |
| 49 | // CHECK-NEXT: class Bad_Child1 : public Base_A, Base_B {}; |
| 50 | class Bad_Child1 : public Base_A, Base_B {}; |
| 51 | |
| 52 | // CHECK-MESSAGES: [[@LINE+1]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] |
| 53 | class Bad_Child2 : public Base_A, Interface_A_with_member { |
| 54 | virtual int foo() override { return 0; } |
| 55 | }; |
| 56 | |
| 57 | // CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] |
| 58 | // CHECK-NEXT: class Bad_Child3 : public Interface_with_A_Parent, Base_B { |
| 59 | class Bad_Child3 : public Interface_with_A_Parent, Base_B { |
| 60 | virtual int baz() override { return 0; } |
| 61 | }; |
| 62 | |
| 63 | // Easy cases of single inheritance |
| 64 | class Simple_Child1 : public Base_A {}; |
| 65 | class Simple_Child2 : public Interface_A { |
| 66 | virtual int foo() override { return 0; } |
| 67 | }; |
| 68 | |
| 69 | // Valid uses of multiple inheritance |
| 70 | class Good_Child1 : public Interface_A, Interface_B { |
| 71 | virtual int foo() override { return 0; } |
| 72 | virtual int bar() override { return 0; } |
| 73 | }; |
| 74 | |
| 75 | class Good_Child2 : public Base_A, Interface_B { |
| 76 | virtual int bar() override { return 0; } |
| 77 | }; |
| 78 | |
| 79 | class Good_Child3 : public Base_A_child, Interface_C, Interface_B { |
| 80 | virtual int bar() override { return 0; } |
| 81 | virtual int blat() override { return 0; } |
| 82 | }; |
| 83 | |
| 84 | struct B1 { int x; }; |
| 85 | struct B2 { int x;}; |
| 86 | // CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] |
| 87 | // CHECK-NEXT: struct D : B1, B2 {}; |
| 88 | struct D1 : B1, B2 {}; |
| 89 | |
| 90 | struct Base1 { virtual void foo() = 0; }; |
| 91 | struct V1 : virtual Base1 {}; |
| 92 | struct V2 : virtual Base1 {}; |
| 93 | struct D2 : V1, V2 {}; |
| 94 | |
| 95 | struct Base2 { virtual void foo(); }; |
| 96 | struct V3 : virtual Base2 {}; |
| 97 | struct V4 : virtual Base2 {}; |
| 98 | struct D3 : V3, V4 {}; |
| 99 | |
| 100 | struct Base3 {}; |
| 101 | struct V5 : virtual Base3 { virtual void f(); }; |
| 102 | struct V6 : virtual Base3 { virtual void g(); }; |
| 103 | // CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] |
| 104 | // CHECK-NEXT: struct D4 : V5, V6 {}; |
| 105 | struct D4 : V5, V6 {}; |
| 106 | |
| 107 | struct Base4 {}; |
| 108 | struct V7 : virtual Base4 { virtual void f() = 0; }; |
| 109 | struct V8 : virtual Base4 { virtual void g() = 0; }; |
| 110 | struct D5 : V7, V8 {}; |
| 111 | |
| 112 | struct Base5 { virtual void f() = 0; }; |
| 113 | struct V9 : virtual Base5 { virtual void f(); }; |
| 114 | struct V10 : virtual Base5 { virtual void g() = 0; }; |
| 115 | struct D6 : V9, V10 {}; |
| 116 | |
| 117 | struct Base6 { virtual void f(); }; |
| 118 | struct Base7 { virtual void g(); }; |
| 119 | struct V15 : virtual Base6 { virtual void f() = 0; }; |
| 120 | struct V16 : virtual Base7 { virtual void g() = 0; }; |
| 121 | // CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] |
| 122 | // CHECK-NEXT: struct D9 : V15, V16 {}; |
| 123 | struct D9 : V15, V16 {}; |
| 124 | |
| 125 | struct Static_Base { static void foo(); }; |
| 126 | struct V11 : virtual Static_Base {}; |
| 127 | struct V12 : virtual Static_Base {}; |
| 128 | struct D7 : V11, V12 {}; |
| 129 | |
| 130 | struct Static_Base_2 {}; |
| 131 | struct V13 : virtual Static_Base_2 { static void f(); }; |
| 132 | struct V14 : virtual Static_Base_2 { static void g(); }; |
| 133 | struct D8 : V13, V14 {}; |
| 134 | |
| 135 | template<typename T> struct A : T {}; |
| 136 | template<typename T> struct B : virtual T {}; |
| 137 | |
| 138 | template<typename> struct C {}; |
| 139 | template<typename T> struct D : C<T> {}; |
| 140 | |
| 141 | // Check clang_tidy does not crash on this code. |
| 142 | template <class T> |
| 143 | struct WithTemplBase : T { |
| 144 | WithTemplBase(); |
| 145 | }; |
| 146 | |
| 147 | void test_no_crash() { |
| 148 | auto foo = []() {}; |
| 149 | WithTemplBase<decltype(foo)>(); |
| 150 | } |
| 151 | |