163 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DDUMMY -verify %s2// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV0 -verify %s3// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV1 -verify %s4// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV2 -verify %s5// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV3 -verify %s6// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV4 -verify %s7 8#ifdef DUMMY9struct S {};10#else11struct 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#else23#error Define something!24#endif25 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#endif38struct 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 DUMMY60 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#endif71 }72 73 void false_positives() {74#define OP =75#define LHS a76#define RHS a77 // 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 OP83#undef LHS84#undef RHS85 86 // Ways to silence the warning.87 a = *&a;88 a = (S &)a;89 a = static_cast<decltype(a) &>(a);90 }91 92#ifndef DUMMY93 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#endif101};102 103// Do not diagnose self-assignment in an unevaluated context104struct SNoExcept {105 SNoExcept() = default;106 SNoExcept &operator=(const SNoExcept &) noexcept;107};108struct 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 118template <typename T>119struct TemplateClass {120 T var;121 void f() {122 var = var; // expected-warning {{assigning field to itself}}123 }124};125void 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 that138// it is ok to vectorize the store.139 140void f0(C *s, C *t) {141 s->a = s->a;142 t->a = s->a;143}144 145void f1(C &s, C &t) {146 s.a = s.a;147 t.a = s.a;148}149 150struct T {151 C *s;152};153 154void f2(T *t, T *t2) {155 t->s->a = t->s->a;156 t2->s->a = t->s->a;157}158 159void f3(T &t, T &t2) {160 t.s->a = t.s->a;161 t2.s->a = t.s->a;162}163