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
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
fC42 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
false_positivesC73 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;
vol_testC94 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
false_positives_unevaluated_ctxfalse_positives_unevaluated_ctx_class111 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;
fTemplateClass121 void f() {
122 var = var; // expected-warning {{assigning field to itself}}
123 }
124 };
instantiate()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
f0(C * s,C * t)140 void f0(C *s, C *t) {
141 s->a = s->a;
142 t->a = s->a;
143 }
144
f1(C & s,C & t)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
f2(T * t,T * t2)154 void f2(T *t, T *t2) {
155 t->s->a = t->s->a;
156 t2->s->a = t->s->a;
157 }
158
f3(T & t,T & t2)159 void f3(T &t, T &t2) {
160 t.s->a = t.s->a;
161 t2.s->a = t.s->a;
162 }
163