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