1// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
2
3class Base {
4 int i;
5 void f() {}
6 virtual void g() {}
7};
8
9class DerivedWithMemberVariables : public Base {
10 void f();
11 int j;
12};
13
14class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
15 void f();
16};
17
18class DerivedWithOverride : public Base {
19 void f();
20 void g() override {}
21};
22
23class TwiceDerivedWithNoOverride : public DerivedWithOverride {
24 void f();
25};
26
27void TakesBaseByValue(Base base);
28
29DerivedWithMemberVariables ReturnsDerived();
30
31void 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(base: 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
48void 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(base: 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
62void TakesBaseByReference(Base &base);
63
64class DerivedThatAddsVirtualH : public Base {
65 virtual void h();
66};
67
68class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
69 void h() override;
70};
71
72void negatives() {
73 // OK, simple copying from the same type.
74 Base a;
75 TakesBaseByValue(base: 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(base&: d);
92 TakesBaseByReference(base&: 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
102namespace PR31187 {
103// Don't warn when calling constructor of base virtual class, from
104// initialization list of derived class constructor.
105
106struct BaseA {
107virtual ~BaseA() {}
108virtual void foo() {}
109
110int i;
111};
112
113struct BaseB : virtual BaseA {
114virtual void foo() {}
115};
116
117struct ClassWithVirtualBases : BaseB {
118 ClassWithVirtualBases(const BaseB& other) : BaseA(other), BaseB(other) {}
119 ClassWithVirtualBases(const ClassWithVirtualBases& other) : BaseA(other), BaseB(other) {}
120};
121
122}
123

source code of clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/slicing.cpp