forked from OSchip/llvm-project
101 lines
3.1 KiB
C++
101 lines
3.1 KiB
C++
|
// 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'
|
||
|
}
|