1 // RUN: %check_clang_tidy %s fuchsia-multiple-inheritance %t
2 
3 class Base_A {
4 public:
foo()5   virtual int foo() { return 0; }
6 };
7 
8 class Base_B {
9 public:
bar()10   virtual int bar() { return 0; }
11 };
12 
13 class Base_A_child : public Base_A {
14 public:
baz()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 {
foo()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 {
baz()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 {
foo()66   virtual int foo() override { return 0; }
67 };
68 
69 // Valid uses of multiple inheritance
70 class Good_Child1 : public Interface_A, Interface_B {
foo()71   virtual int foo() override { return 0; }
bar()72   virtual int bar() override { return 0; }
73 };
74 
75 class Good_Child2 : public Base_A, Interface_B {
bar()76   virtual int bar() override { return 0; }
77 };
78 
79 class Good_Child3 : public Base_A_child, Interface_C, Interface_B {
bar()80   virtual int bar() override { return 0; }
blat()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 
test_no_crash()147 int test_no_crash() {
148   auto foo = []() {};
149   WithTemplBase<decltype(foo)>();
150 }
151