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