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