1 // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -verify %s
2
3 struct C {
4 int a;
5 int b;
6
fC7 void f() {
8 a = a; // expected-warning {{assigning field to itself}}
9 b = b; // expected-warning {{assigning field to itself}}
10 a = b;
11
12 this->a = a; // expected-warning {{assigning field to itself}}
13 this->b = b; // expected-warning {{assigning field to itself}}
14 a = this->a; // expected-warning {{assigning field to itself}}
15 b = this->b; // expected-warning {{assigning field to itself}}
16 this->a = this->a; // expected-warning {{assigning field to itself}}
17 this->b = this->b; // expected-warning {{assigning field to itself}}
18
19 a = b;
20 a = this->b;
21 this->a = b;
22 this->a = this->b;
23
24 a *= a;
25 a /= a;
26 a %= a;
27 a += a;
28 a -= a;
29 a <<= a;
30 a >>= a;
31 a &= a;
32 a |= a;
33 a ^= a;
34 }
35
false_positivesC36 void false_positives() {
37 #define OP =
38 #define LHS a
39 #define RHS a
40 // These shouldn't warn due to the use of the preprocessor.
41 a OP a;
42 LHS = a;
43 a = RHS;
44 LHS OP RHS;
45 #undef OP
46 #undef LHS
47 #undef RHS
48
49 // A way to silence the warning.
50 a = (int &)a;
51 }
52
53 // Do not diagnose self-assigment in an unevaluated context
false_positives_unevaluated_ctxC54 void false_positives_unevaluated_ctx() noexcept(noexcept(a = a)) // expected-warning {{expression with side effects has no effect in an unevaluated context}}
55 {
56 decltype(a = a) b = a; // expected-warning {{expression with side effects has no effect in an unevaluated context}}
57 static_assert(noexcept(a = a), ""); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
58 static_assert(sizeof(a = a), ""); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
59 }
60
61 volatile int vol_a;
vol_testC62 void vol_test() {
63 // Volatile stores aren't side-effect free.
64 vol_a = vol_a;
65 volatile int &vol_a_ref = vol_a;
66 vol_a_ref = vol_a_ref;
67 }
68 };
69
70 // Dummy type.
71 struct Dummy {};
72
73 template <typename T>
74 struct TemplateClass {
75 T var;
fTemplateClass76 void f() {
77 var = var; // expected-warning {{assigning field to itself}}
78 }
79 };
instantiate()80 void instantiate() {
81 {
82 TemplateClass<int> c;
83 c.f();
84 }
85 {
86 TemplateClass<Dummy> c;
87 c.f();
88 }
89 }
90
91 // It may make sense not to warn on the rest of the tests.
92 // It may be a valid use-case to self-assign to tell the compiler that
93 // it is ok to vectorize the store.
94
f0(C * s,C * t)95 void f0(C *s, C *t) {
96 s->a = s->a;
97 t->a = s->a;
98 }
99
f1(C & s,C & t)100 void f1(C &s, C &t) {
101 s.a = s.a;
102 t.a = s.a;
103 }
104
105 struct T {
106 C *s;
107 };
108
f2(T * t,T * t2)109 void f2(T *t, T *t2) {
110 t->s->a = t->s->a;
111 t2->s->a = t->s->a;
112 }
113
f3(T & t,T & t2)114 void f3(T &t, T &t2) {
115 t.s->a = t.s->a;
116 t2.s->a = t.s->a;
117 }
118