1 // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DDUMMY -verify %s 2 // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV0 -verify %s 3 // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV1 -verify %s 4 // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV2 -verify %s 5 // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV3 -verify %s test()6// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV4 -verify %s 7 8 #ifdef DUMMY 9 struct S {}; 10 #else 11 struct S { 12 #if defined(V0) 13 S() = default; 14 #elif defined(V1) 15 S &operator=(const S &) = default; 16 #elif defined(V2) 17 S &operator=(S &) = default; 18 #elif defined(V3) 19 S &operator=(const S &); 20 #elif defined(V4) 21 S &operator=(S &); 22 #else 23 #error Define something! 24 #endif 25 S &operator*=(const S &); 26 S &operator/=(const S &); 27 S &operator%=(const S &); 28 S &operator+=(const S &); 29 S &operator-=(const S &); 30 S &operator<<=(const S &); 31 S &operator>>=(const S &); 32 S &operator&=(const S &); 33 S &operator|=(const S &); 34 S &operator^=(const S &); 35 S &operator=(const volatile S &) volatile; 36 }; 37 #endif 38 struct C { 39 S a; 40 S b; 41 42 void f() { 43 a = a; // expected-warning {{assigning field to itself}} 44 b = b; // expected-warning {{assigning field to itself}} 45 a = b; 46 47 this->a = a; // expected-warning {{assigning field to itself}} 48 this->b = b; // expected-warning {{assigning field to itself}} 49 a = this->a; // expected-warning {{assigning field to itself}} 50 b = this->b; // expected-warning {{assigning field to itself}} 51 this->a = this->a; // expected-warning {{assigning field to itself}} 52 this->b = this->b; // expected-warning {{assigning field to itself}} 53 54 a = b; 55 a = this->b; 56 this->a = b; 57 this->a = this->b; 58 59 #ifndef DUMMY 60 a *= a; 61 a /= a; // expected-warning {{assigning field to itself}} 62 a %= a; // expected-warning {{assigning field to itself}} 63 a += a; 64 a -= a; // expected-warning {{assigning field to itself}} 65 a <<= a; 66 a >>= a; 67 a &= a; // expected-warning {{assigning field to itself}} 68 a |= a; // expected-warning {{assigning field to itself}} 69 a ^= a; // expected-warning {{assigning field to itself}} 70 #endif 71 } 72 73 void false_positives() { 74 #define OP = 75 #define LHS a 76 #define RHS a 77 // These shouldn't warn due to the use of the preprocessor. 78 a OP a; 79 LHS = a; 80 a = RHS; 81 LHS OP RHS; 82 #undef OP 83 #undef LHS 84 #undef RHS 85 86 // Ways to silence the warning. 87 a = *&a; 88 a = (S &)a; 89 a = static_cast<decltype(a) &>(a); 90 } 91 92 #ifndef DUMMY 93 volatile S vol_a; 94 void vol_test() { 95 // Volatile stores aren't side-effect free. 96 vol_a = vol_a; 97 volatile S &vol_a_ref = vol_a; 98 vol_a_ref = vol_a_ref; 99 } 100 #endif 101 }; 102 103 // Do not diagnose self-assigment in an unevaluated context 104 struct SNoExcept { 105 SNoExcept() = default; 106 SNoExcept &operator=(const SNoExcept &) noexcept; 107 }; 108 struct false_positives_unevaluated_ctx_class { 109 SNoExcept a; 110 111 void false_positives_unevaluated_ctx(SNoExcept a) noexcept(noexcept(a = a)) { 112 decltype(a = a) b = a; 113 static_assert(noexcept(a = a), ""); 114 static_assert(sizeof(a = a), ""); 115 } 116 }; 117 118 template <typename T> 119 struct TemplateClass { 120 T var; 121 void f() { 122 var = var; // expected-warning {{assigning field to itself}} 123 } 124 }; 125 void instantiate() { 126 { 127 TemplateClass<int> c; 128 c.f(); 129 } 130 { 131 TemplateClass<S> c; 132 c.f(); 133 } 134 } 135 136 // It may make sense not to warn on the rest of the tests. 137 // It may be a valid use-case to self-assign to tell the compiler that 138 // it is ok to vectorize the store. 139 140 void f0(C *s, C *t) { 141 s->a = s->a; 142 t->a = s->a; 143 } 144 145 void f1(C &s, C &t) { 146 s.a = s.a; 147 t.a = s.a; 148 } 149 150 struct T { 151 C *s; 152 }; 153 154 void f2(T *t, T *t2) { 155 t->s->a = t->s->a; 156 t2->s->a = t->s->a; 157 } 158 159 void f3(T &t, T &t2) { 160 t.s->a = t.s->a; 161 t2.s->a = t.s->a; 162 } 163