189a1d03eSRichard // RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
289a1d03eSRichard
389a1d03eSRichard class Base {
489a1d03eSRichard int i;
f()589a1d03eSRichard void f() {}
g()689a1d03eSRichard virtual void g() {}
789a1d03eSRichard };
889a1d03eSRichard
989a1d03eSRichard class DerivedWithMemberVariables : public Base {
1089a1d03eSRichard void f();
1189a1d03eSRichard int j;
1289a1d03eSRichard };
1389a1d03eSRichard
1489a1d03eSRichard class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
1589a1d03eSRichard void f();
1689a1d03eSRichard };
1789a1d03eSRichard
1889a1d03eSRichard class DerivedWithOverride : public Base {
1989a1d03eSRichard void f();
g()2089a1d03eSRichard void g() override {}
2189a1d03eSRichard };
2289a1d03eSRichard
2389a1d03eSRichard class TwiceDerivedWithNoOverride : public DerivedWithOverride {
2489a1d03eSRichard void f();
2589a1d03eSRichard };
2689a1d03eSRichard
2789a1d03eSRichard void TakesBaseByValue(Base base);
2889a1d03eSRichard
2989a1d03eSRichard DerivedWithMemberVariables ReturnsDerived();
3089a1d03eSRichard
positivesWithMemberVariables()3189a1d03eSRichard void positivesWithMemberVariables() {
3289a1d03eSRichard DerivedWithMemberVariables b;
3389a1d03eSRichard Base a{b};
3489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state [cppcoreguidelines-slicing]
3589a1d03eSRichard a = b;
3689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
3789a1d03eSRichard TakesBaseByValue(b);
3889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
3989a1d03eSRichard
4089a1d03eSRichard TwiceDerivedWithNoMemberVariables c;
4189a1d03eSRichard a = c;
4289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
4389a1d03eSRichard
4489a1d03eSRichard a = ReturnsDerived();
4589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state
4689a1d03eSRichard }
4789a1d03eSRichard
positivesWithOverride()4889a1d03eSRichard void positivesWithOverride() {
4989a1d03eSRichard DerivedWithOverride b;
5089a1d03eSRichard Base a{b};
5189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
5289a1d03eSRichard a = b;
5389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
5489a1d03eSRichard TakesBaseByValue(b);
5589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
5689a1d03eSRichard
5789a1d03eSRichard TwiceDerivedWithNoOverride c;
5889a1d03eSRichard a = c;
5989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
6089a1d03eSRichard }
6189a1d03eSRichard
6289a1d03eSRichard void TakesBaseByReference(Base &base);
6389a1d03eSRichard
6489a1d03eSRichard class DerivedThatAddsVirtualH : public Base {
6589a1d03eSRichard virtual void h();
6689a1d03eSRichard };
6789a1d03eSRichard
6889a1d03eSRichard class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
6989a1d03eSRichard void h() override;
7089a1d03eSRichard };
7189a1d03eSRichard
negatives()7289a1d03eSRichard void negatives() {
7389a1d03eSRichard // OK, simple copying from the same type.
7489a1d03eSRichard Base a;
7589a1d03eSRichard TakesBaseByValue(a);
7689a1d03eSRichard DerivedWithMemberVariables b;
7789a1d03eSRichard DerivedWithMemberVariables c{b};
7889a1d03eSRichard b = c;
7989a1d03eSRichard
8089a1d03eSRichard // OK, derived type does not have extra state.
8189a1d03eSRichard TwiceDerivedWithNoMemberVariables d;
8289a1d03eSRichard DerivedWithMemberVariables e{d};
8389a1d03eSRichard e = d;
8489a1d03eSRichard
8589a1d03eSRichard // OK, derived does not override any method.
8689a1d03eSRichard TwiceDerivedWithNoOverride f;
8789a1d03eSRichard DerivedWithOverride g{f};
8889a1d03eSRichard g = f;
8989a1d03eSRichard
9089a1d03eSRichard // OK, no copying.
9189a1d03eSRichard TakesBaseByReference(d);
9289a1d03eSRichard TakesBaseByReference(f);
9389a1d03eSRichard
9489a1d03eSRichard // Derived type overrides methods, but these methods are not in the base type,
9589a1d03eSRichard // so cannot be called accidentally. Right now this triggers, but we might
9689a1d03eSRichard // want to allow it.
9789a1d03eSRichard DerivedThatOverridesH h;
9889a1d03eSRichard a = h;
9989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
10089a1d03eSRichard }
101*f1e2469eSPiotr Zegar
102*f1e2469eSPiotr Zegar namespace PR31187 {
103*f1e2469eSPiotr Zegar // Don't warn when calling constructor of base virtual class, from
104*f1e2469eSPiotr Zegar // initialization list of derived class constructor.
105*f1e2469eSPiotr Zegar
106*f1e2469eSPiotr Zegar struct BaseA {
~BaseAPR31187::BaseA107*f1e2469eSPiotr Zegar virtual ~BaseA() {}
fooPR31187::BaseA108*f1e2469eSPiotr Zegar virtual void foo() {}
109*f1e2469eSPiotr Zegar
110*f1e2469eSPiotr Zegar int i;
111*f1e2469eSPiotr Zegar };
112*f1e2469eSPiotr Zegar
113*f1e2469eSPiotr Zegar struct BaseB : virtual BaseA {
fooPR31187::BaseB114*f1e2469eSPiotr Zegar virtual void foo() {}
115*f1e2469eSPiotr Zegar };
116*f1e2469eSPiotr Zegar
117*f1e2469eSPiotr Zegar struct ClassWithVirtualBases : BaseB {
ClassWithVirtualBasesPR31187::ClassWithVirtualBases118*f1e2469eSPiotr Zegar ClassWithVirtualBases(const BaseB& other) : BaseA(other), BaseB(other) {}
ClassWithVirtualBasesPR31187::ClassWithVirtualBases119*f1e2469eSPiotr Zegar ClassWithVirtualBases(const ClassWithVirtualBases& other) : BaseA(other), BaseB(other) {}
120*f1e2469eSPiotr Zegar };
121*f1e2469eSPiotr Zegar
122*f1e2469eSPiotr Zegar }
123