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()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(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()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(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()72void 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