1 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DDUMMY -verify %s 2 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV0 -verify %s 3 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV1 -verify %s 4 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV2 -verify %s 5 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV3 -verify %s 6 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV4 -verify %s 7 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DDUMMY -verify %s 8 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV0 -verify %s 9 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV1 -verify %s 10 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV2 -verify %s 11 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV3 -verify %s 12 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV4 -verify %s 13 14 #ifdef DUMMY 15 struct S {}; 16 #else 17 struct S { 18 #if defined(V0) 19 S() = default; 20 #elif defined(V1) 21 S &operator=(const S &) = default; 22 #elif defined(V2) 23 S &operator=(S &) = default; 24 #elif defined(V3) 25 S &operator=(const S &); 26 #elif defined(V4) 27 S &operator=(S &); 28 #else 29 #error Define something! 30 #endif 31 S &operator*=(const S &); 32 S &operator/=(const S &); 33 S &operator%=(const S &); 34 S &operator+=(const S &); 35 S &operator-=(const S &); 36 S &operator<<=(const S &); 37 S &operator>>=(const S &); 38 S &operator&=(const S &); 39 S &operator|=(const S &); 40 S &operator^=(const S &); 41 S &operator=(const volatile S &) volatile; 42 }; 43 #endif 44 f()45void f() { 46 S a, b; 47 a = a; // expected-warning{{explicitly assigning}} 48 b = b; // expected-warning{{explicitly assigning}} 49 a = b; 50 b = a = b; 51 a = a = a; // expected-warning{{explicitly assigning}} 52 a = b = b = a; 53 54 #ifndef DUMMY 55 a *= a; 56 a /= a; 57 a %= a; 58 a += a; 59 a -= a; 60 a <<= a; 61 a >>= a; 62 a &= a; 63 a |= a; 64 a ^= a; 65 #endif 66 } 67 false_positives()68void false_positives() { 69 #define OP = 70 #define LHS a 71 #define RHS a 72 S a; 73 // These shouldn't warn due to the use of the preprocessor. 74 a OP a; 75 LHS = a; 76 a = RHS; 77 LHS OP RHS; 78 #undef OP 79 #undef LHS 80 #undef RHS 81 82 // Ways to silence the warning. 83 a = *&a; 84 a = (S &)a; 85 a = static_cast<decltype(a) &>(a); 86 87 #ifndef DUMMY 88 // Volatile stores aren't side-effect free. 89 volatile S vol_a; 90 vol_a = vol_a; 91 volatile S &vol_a_ref = vol_a; 92 vol_a_ref = vol_a_ref; 93 #endif 94 } 95 96 // Do not diagnose self-assigment in an unevaluated context 97 struct SNoExcept { 98 SNoExcept() = default; 99 SNoExcept &operator=(const SNoExcept &) noexcept; 100 }; false_positives_unevaluated_ctx(SNoExcept a)101void false_positives_unevaluated_ctx(SNoExcept a) noexcept(noexcept(a = a)) { 102 decltype(a = a) b = a; 103 static_assert(noexcept(a = a), ""); 104 static_assert(sizeof(a = a), ""); 105 } 106 107 template <typename T> g()108void g() { 109 T a; 110 a = a; // expected-warning{{explicitly assigning}} 111 } instantiate()112void instantiate() { 113 g<int>(); 114 g<S>(); 115 } 116