brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.2 KiB · 9fdbb7a Raw
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