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 | int test_no_crash() { |
148 | auto foo = []() {}; |
149 | WithTemplBase<decltype(foo)>(); |
150 | } |
151 | |