1 // RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
2 
3 class Base {
4   int i;
f()5   void f() {}
g()6   virtual void g() {}
7 };
8 
9 class DerivedWithMemberVariables : public Base {
10   void f();
11   int j;
12 };
13 
14 class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
15   void f();
16 };
17 
18 class DerivedWithOverride : public Base {
19   void f();
g()20   void g() override {}
21 };
22 
23 class TwiceDerivedWithNoOverride : public DerivedWithOverride {
24   void f();
25 };
26 
27 void TakesBaseByValue(Base base);
28 
29 DerivedWithMemberVariables ReturnsDerived();
30 
positivesWithMemberVariables()31 void positivesWithMemberVariables() {
32   DerivedWithMemberVariables b;
33   Base a{b};
34   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state [cppcoreguidelines-slicing]
35   a = b;
36   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
37   TakesBaseByValue(b);
38   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
39 
40   TwiceDerivedWithNoMemberVariables c;
41   a = c;
42   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
43 
44   a = ReturnsDerived();
45   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
46 }
47 
positivesWithOverride()48 void positivesWithOverride() {
49   DerivedWithOverride b;
50   Base a{b};
51   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
52   a = b;
53   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
54   TakesBaseByValue(b);
55   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
56 
57   TwiceDerivedWithNoOverride c;
58   a = c;
59   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
60 }
61 
62 void TakesBaseByReference(Base &base);
63 
64 class DerivedThatAddsVirtualH : public Base {
65   virtual void h();
66 };
67 
68 class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
69   void h() override;
70 };
71 
negatives()72 void negatives() {
73   // OK, simple copying from the same type.
74   Base a;
75   TakesBaseByValue(a);
76   DerivedWithMemberVariables b;
77   DerivedWithMemberVariables c{b};
78   b = c;
79 
80   // OK, derived type does not have extra state.
81   TwiceDerivedWithNoMemberVariables d;
82   DerivedWithMemberVariables e{d};
83   e = d;
84 
85   // OK, derived does not override any method.
86   TwiceDerivedWithNoOverride f;
87   DerivedWithOverride g{f};
88   g = f;
89 
90   // OK, no copying.
91   TakesBaseByReference(d);
92   TakesBaseByReference(f);
93 
94   // Derived type overrides methods, but these methods are not in the base type,
95   // so cannot be called accidentally. Right now this triggers, but we might
96   // want to allow it.
97   DerivedThatOverridesH h;
98   a = h;
99   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
100 }
101