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