150 lines · cpp
1// RUN: %check_clang_tidy %s bugprone-copy-constructor-mutates-argument %t2 3// Example test cases from CERT rule4// https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP58-CPP.+Copy+operations+must+not+mutate+the+source+object5namespace test_mutating_noncompliant_example {6class A {7 mutable int m;8 9public:10 A() : m(0) {}11 explicit A(int m) : m(m) {}12 13 A(const A &other) : m(other.m) {14 other.m = 0;15 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object16 }17 18 A &operator=(const A &other) {19 if (&other != this) {20 m = other.m;21 other.m = 0;22 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: mutating copied object23 }24 return *this;25 }26 27 int get_m() const { return m; }28};29} // namespace test_mutating_noncompliant_example30 31namespace test_mutating_compliant_example {32class B {33 int m;34 35public:36 B() : m(0) {}37 explicit B(int m) : m(m) {}38 39 B(const B &other) : m(other.m) {}40 B(B &&other) : m(other.m) {41 other.m = 0; //no-warning: mutation allowed in move constructor42 }43 44 B &operator=(const B &other) {45 if (&other != this) {46 m = other.m;47 }48 return *this;49 }50 51 B &operator=(B &&other) {52 m = other.m;53 other.m = 0; //no-warning: mutation allowed in move assignment operator54 return *this;55 }56 57 int get_m() const { return m; }58};59} // namespace test_mutating_compliant_example60 61namespace test_mutating_pointer {62class C {63 C *ptr;64 int value;65 66 C();67 C(C &other) {68 other = {};69 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object70 other.ptr = nullptr;71 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object72 other.value = 0;73 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object74 75 // no-warning: mutating a pointee is allowed76 other.ptr->value = 0;77 *other.ptr = {};78 }79};80} // namespace test_mutating_pointer81 82namespace test_mutating_indirect_member {83struct S {84 int x;85};86 87class D {88 S s;89 D(D &other) {90 other.s = {};91 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object92 other.s.x = 0;93 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object94 }95};96} // namespace test_mutating_indirect_member97 98namespace test_mutating_other_object {99class E {100 E();101 E(E &other) {102 E tmp;103 // no-warning: mutating an object that is not the source is allowed104 tmp = {};105 }106};107} // namespace test_mutating_other_object108 109namespace test_mutating_member_function {110class F {111 int a;112 113public:114 void bad_func() { a = 12; }115 void fine_func() const;116 void fine_func_2(int x) { x = 5; }117 void questionable_func();118 119 F(F &other) : a(other.a) {120 this->bad_func(); // no-warning: mutating this is allowed121 122 other.bad_func();123 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: call mutates copied object124 125 other.fine_func();126 other.fine_func_2(42);127 other.questionable_func();128 }129};130} // namespace test_mutating_member_function131 132namespace test_mutating_function_on_nested_object {133struct S {134 int x;135 void mutate(int y) {136 x = y;137 }138};139 140class G {141 S s;142 G(G &other) {143 s.mutate(0); // no-warning: mutating this is allowed144 145 other.s.mutate(0);146 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: call mutates copied object147 }148};149} // namespace test_mutating_function_on_nested_object150