|  | // RUN: %check_clang_tidy %s cert-oop58-cpp %t | 
|  |  | 
|  | // Example test cases from CERT rule | 
|  | // https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP58-CPP.+Copy+operations+must+not+mutate+the+source+object | 
|  | namespace test_mutating_noncompliant_example { | 
|  | class A { | 
|  | mutable int m; | 
|  |  | 
|  | public: | 
|  | A() : m(0) {} | 
|  | explicit A(int m) : m(m) {} | 
|  |  | 
|  | A(const A &other) : m(other.m) { | 
|  | other.m = 0; | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object | 
|  | } | 
|  |  | 
|  | A &operator=(const A &other) { | 
|  | if (&other != this) { | 
|  | m = other.m; | 
|  | other.m = 0; | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: mutating copied object | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | int get_m() const { return m; } | 
|  | }; | 
|  | } // namespace test_mutating_noncompliant_example | 
|  |  | 
|  | namespace test_mutating_compliant_example { | 
|  | class B { | 
|  | int m; | 
|  |  | 
|  | public: | 
|  | B() : m(0) {} | 
|  | explicit B(int m) : m(m) {} | 
|  |  | 
|  | B(const B &other) : m(other.m) {} | 
|  | B(B &&other) : m(other.m) { | 
|  | other.m = 0; //no-warning: mutation allowed in move constructor | 
|  | } | 
|  |  | 
|  | B &operator=(const B &other) { | 
|  | if (&other != this) { | 
|  | m = other.m; | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | B &operator=(B &&other) { | 
|  | m = other.m; | 
|  | other.m = 0; //no-warning: mutation allowed in move assignment operator | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | int get_m() const { return m; } | 
|  | }; | 
|  | } // namespace test_mutating_compliant_example | 
|  |  | 
|  | namespace test_mutating_pointer { | 
|  | class C { | 
|  | C *ptr; | 
|  | int value; | 
|  |  | 
|  | C(); | 
|  | C(C &other) { | 
|  | other = {}; | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object | 
|  | other.ptr = nullptr; | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object | 
|  | other.value = 0; | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object | 
|  |  | 
|  | // no-warning: mutating a pointee is allowed | 
|  | other.ptr->value = 0; | 
|  | *other.ptr = {}; | 
|  | } | 
|  | }; | 
|  | } // namespace test_mutating_pointer | 
|  |  | 
|  | namespace test_mutating_indirect_member { | 
|  | struct S { | 
|  | int x; | 
|  | }; | 
|  |  | 
|  | class D { | 
|  | S s; | 
|  | D(D &other) { | 
|  | other.s = {}; | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object | 
|  | other.s.x = 0; | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: mutating copied object | 
|  | } | 
|  | }; | 
|  | } // namespace test_mutating_indirect_member | 
|  |  | 
|  | namespace test_mutating_other_object { | 
|  | class E { | 
|  | E(); | 
|  | E(E &other) { | 
|  | E tmp; | 
|  | // no-warning: mutating an object that is not the source is allowed | 
|  | tmp = {}; | 
|  | } | 
|  | }; | 
|  | } // namespace test_mutating_other_object | 
|  |  | 
|  | namespace test_mutating_member_function { | 
|  | class F { | 
|  | int a; | 
|  |  | 
|  | public: | 
|  | void bad_func() { a = 12; } | 
|  | void fine_func() const; | 
|  | void fine_func_2(int x) { x = 5; } | 
|  | void questionable_func(); | 
|  |  | 
|  | F(F &other) : a(other.a) { | 
|  | this->bad_func(); // no-warning: mutating this is allowed | 
|  |  | 
|  | other.bad_func(); | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: call mutates copied object | 
|  |  | 
|  | other.fine_func(); | 
|  | other.fine_func_2(42); | 
|  | other.questionable_func(); | 
|  | } | 
|  | }; | 
|  | } // namespace test_mutating_member_function | 
|  |  | 
|  | namespace test_mutating_function_on_nested_object { | 
|  | struct S { | 
|  | int x; | 
|  | void mutate(int y) { | 
|  | x = y; | 
|  | } | 
|  | }; | 
|  |  | 
|  | class G { | 
|  | S s; | 
|  | G(G &other) { | 
|  | s.mutate(0); // no-warning: mutating this is allowed | 
|  |  | 
|  | other.s.mutate(0); | 
|  | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: call mutates copied object | 
|  | } | 
|  | }; | 
|  | } // namespace test_mutating_function_on_nested_object |