150
|
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 }
|