CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
150 lines
3.2 KiB
C++
150 lines
3.2 KiB
C++
// RUN: %check_clang_tidy %s bugprone-copy-constructor-mutates-argument %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
|