1 | // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -verify %s |
2 | |
3 | struct C { |
4 | int a; |
5 | int b; |
6 | |
7 | 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 | |
36 | 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 |
54 | 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; |
62 | 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; |
76 | void f() { |
77 | var = var; // expected-warning {{assigning field to itself}} |
78 | } |
79 | }; |
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 | |
95 | void f0(C *s, C *t) { |
96 | s->a = s->a; |
97 | t->a = s->a; |
98 | } |
99 | |
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 | |
109 | void f2(T *t, T *t2) { |
110 | t->s->a = t->s->a; |
111 | t2->s->a = t->s->a; |
112 | } |
113 | |
114 | void f3(T &t, T &t2) { |
115 | t.s->a = t.s->a; |
116 | t2.s->a = t.s->a; |
117 | } |
118 | |