| // RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t |
| |
| class Base { |
| int i; |
| void f() {} |
| virtual void g() {} |
| }; |
| |
| class DerivedWithMemberVariables : public Base { |
| void f(); |
| int j; |
| }; |
| |
| class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables { |
| void f(); |
| }; |
| |
| class DerivedWithOverride : public Base { |
| void f(); |
| void g() override {} |
| }; |
| |
| class TwiceDerivedWithNoOverride : public DerivedWithOverride { |
| void f(); |
| }; |
| |
| void TakesBaseByValue(Base base); |
| |
| DerivedWithMemberVariables ReturnsDerived(); |
| |
| void positivesWithMemberVariables() { |
| DerivedWithMemberVariables b; |
| Base a{b}; |
| // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state [cppcoreguidelines-slicing] |
| a = b; |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state |
| TakesBaseByValue(b); |
| // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state |
| |
| TwiceDerivedWithNoMemberVariables c; |
| a = c; |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state |
| |
| a = ReturnsDerived(); |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}} bytes of state |
| } |
| |
| void positivesWithOverride() { |
| DerivedWithOverride b; |
| Base a{b}; |
| // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g' |
| a = b; |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g' |
| TakesBaseByValue(b); |
| // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g' |
| |
| TwiceDerivedWithNoOverride c; |
| a = c; |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g' |
| } |
| |
| void TakesBaseByReference(Base &base); |
| |
| class DerivedThatAddsVirtualH : public Base { |
| virtual void h(); |
| }; |
| |
| class DerivedThatOverridesH : public DerivedThatAddsVirtualH { |
| void h() override; |
| }; |
| |
| void negatives() { |
| // OK, simple copying from the same type. |
| Base a; |
| TakesBaseByValue(a); |
| DerivedWithMemberVariables b; |
| DerivedWithMemberVariables c{b}; |
| b = c; |
| |
| // OK, derived type does not have extra state. |
| TwiceDerivedWithNoMemberVariables d; |
| DerivedWithMemberVariables e{d}; |
| e = d; |
| |
| // OK, derived does not override any method. |
| TwiceDerivedWithNoOverride f; |
| DerivedWithOverride g{f}; |
| g = f; |
| |
| // OK, no copying. |
| TakesBaseByReference(d); |
| TakesBaseByReference(f); |
| |
| // Derived type overrides methods, but these methods are not in the base type, |
| // so cannot be called accidentally. Right now this triggers, but we might |
| // want to allow it. |
| DerivedThatOverridesH h; |
| a = h; |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h' |
| } |