xref: /llvm-project/clang/test/SemaCXX/warn-self-assign-field-overloaded.cpp (revision 61061d69eacfb546283f33cba053c29bb1c1ef7e)
1*61061d69SRoman Lebedev // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DDUMMY -verify %s
2*61061d69SRoman Lebedev // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV0 -verify %s
3*61061d69SRoman Lebedev // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV1 -verify %s
4*61061d69SRoman Lebedev // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV2 -verify %s
5*61061d69SRoman Lebedev // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV3 -verify %s
6*61061d69SRoman Lebedev // RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -DV4 -verify %s
7*61061d69SRoman Lebedev 
8*61061d69SRoman Lebedev #ifdef DUMMY
9*61061d69SRoman Lebedev struct S {};
10*61061d69SRoman Lebedev #else
11*61061d69SRoman Lebedev struct S {
12*61061d69SRoman Lebedev #if defined(V0)
13*61061d69SRoman Lebedev   S() = default;
14*61061d69SRoman Lebedev #elif defined(V1)
15*61061d69SRoman Lebedev   S &operator=(const S &) = default;
16*61061d69SRoman Lebedev #elif defined(V2)
17*61061d69SRoman Lebedev   S &operator=(S &) = default;
18*61061d69SRoman Lebedev #elif defined(V3)
19*61061d69SRoman Lebedev   S &operator=(const S &);
20*61061d69SRoman Lebedev #elif defined(V4)
21*61061d69SRoman Lebedev   S &operator=(S &);
22*61061d69SRoman Lebedev #else
23*61061d69SRoman Lebedev #error Define something!
24*61061d69SRoman Lebedev #endif
25*61061d69SRoman Lebedev   S &operator*=(const S &);
26*61061d69SRoman Lebedev   S &operator/=(const S &);
27*61061d69SRoman Lebedev   S &operator%=(const S &);
28*61061d69SRoman Lebedev   S &operator+=(const S &);
29*61061d69SRoman Lebedev   S &operator-=(const S &);
30*61061d69SRoman Lebedev   S &operator<<=(const S &);
31*61061d69SRoman Lebedev   S &operator>>=(const S &);
32*61061d69SRoman Lebedev   S &operator&=(const S &);
33*61061d69SRoman Lebedev   S &operator|=(const S &);
34*61061d69SRoman Lebedev   S &operator^=(const S &);
35*61061d69SRoman Lebedev   S &operator=(const volatile S &) volatile;
36*61061d69SRoman Lebedev };
37*61061d69SRoman Lebedev #endif
38*61061d69SRoman Lebedev struct C {
39*61061d69SRoman Lebedev   S a;
40*61061d69SRoman Lebedev   S b;
41*61061d69SRoman Lebedev 
fC42*61061d69SRoman Lebedev   void f() {
43*61061d69SRoman Lebedev     a = a; // expected-warning {{assigning field to itself}}
44*61061d69SRoman Lebedev     b = b; // expected-warning {{assigning field to itself}}
45*61061d69SRoman Lebedev     a = b;
46*61061d69SRoman Lebedev 
47*61061d69SRoman Lebedev     this->a = a;       // expected-warning {{assigning field to itself}}
48*61061d69SRoman Lebedev     this->b = b;       // expected-warning {{assigning field to itself}}
49*61061d69SRoman Lebedev     a = this->a;       // expected-warning {{assigning field to itself}}
50*61061d69SRoman Lebedev     b = this->b;       // expected-warning {{assigning field to itself}}
51*61061d69SRoman Lebedev     this->a = this->a; // expected-warning {{assigning field to itself}}
52*61061d69SRoman Lebedev     this->b = this->b; // expected-warning {{assigning field to itself}}
53*61061d69SRoman Lebedev 
54*61061d69SRoman Lebedev     a = b;
55*61061d69SRoman Lebedev     a = this->b;
56*61061d69SRoman Lebedev     this->a = b;
57*61061d69SRoman Lebedev     this->a = this->b;
58*61061d69SRoman Lebedev 
59*61061d69SRoman Lebedev #ifndef DUMMY
60*61061d69SRoman Lebedev     a *= a;
61*61061d69SRoman Lebedev     a /= a; // expected-warning {{assigning field to itself}}
62*61061d69SRoman Lebedev     a %= a; // expected-warning {{assigning field to itself}}
63*61061d69SRoman Lebedev     a += a;
64*61061d69SRoman Lebedev     a -= a; // expected-warning {{assigning field to itself}}
65*61061d69SRoman Lebedev     a <<= a;
66*61061d69SRoman Lebedev     a >>= a;
67*61061d69SRoman Lebedev     a &= a; // expected-warning {{assigning field to itself}}
68*61061d69SRoman Lebedev     a |= a; // expected-warning {{assigning field to itself}}
69*61061d69SRoman Lebedev     a ^= a; // expected-warning {{assigning field to itself}}
70*61061d69SRoman Lebedev #endif
71*61061d69SRoman Lebedev   }
72*61061d69SRoman Lebedev 
false_positivesC73*61061d69SRoman Lebedev   void false_positives() {
74*61061d69SRoman Lebedev #define OP =
75*61061d69SRoman Lebedev #define LHS a
76*61061d69SRoman Lebedev #define RHS a
77*61061d69SRoman Lebedev     // These shouldn't warn due to the use of the preprocessor.
78*61061d69SRoman Lebedev     a OP a;
79*61061d69SRoman Lebedev     LHS = a;
80*61061d69SRoman Lebedev     a = RHS;
81*61061d69SRoman Lebedev     LHS OP RHS;
82*61061d69SRoman Lebedev #undef OP
83*61061d69SRoman Lebedev #undef LHS
84*61061d69SRoman Lebedev #undef RHS
85*61061d69SRoman Lebedev 
86*61061d69SRoman Lebedev     // Ways to silence the warning.
87*61061d69SRoman Lebedev     a = *&a;
88*61061d69SRoman Lebedev     a = (S &)a;
89*61061d69SRoman Lebedev     a = static_cast<decltype(a) &>(a);
90*61061d69SRoman Lebedev   }
91*61061d69SRoman Lebedev 
92*61061d69SRoman Lebedev #ifndef DUMMY
93*61061d69SRoman Lebedev   volatile S vol_a;
vol_testC94*61061d69SRoman Lebedev   void vol_test() {
95*61061d69SRoman Lebedev     // Volatile stores aren't side-effect free.
96*61061d69SRoman Lebedev     vol_a = vol_a;
97*61061d69SRoman Lebedev     volatile S &vol_a_ref = vol_a;
98*61061d69SRoman Lebedev     vol_a_ref = vol_a_ref;
99*61061d69SRoman Lebedev   }
100*61061d69SRoman Lebedev #endif
101*61061d69SRoman Lebedev };
102*61061d69SRoman Lebedev 
103*61061d69SRoman Lebedev // Do not diagnose self-assigment in an unevaluated context
104*61061d69SRoman Lebedev struct SNoExcept {
105*61061d69SRoman Lebedev   SNoExcept() = default;
106*61061d69SRoman Lebedev   SNoExcept &operator=(const SNoExcept &) noexcept;
107*61061d69SRoman Lebedev };
108*61061d69SRoman Lebedev struct false_positives_unevaluated_ctx_class {
109*61061d69SRoman Lebedev   SNoExcept a;
110*61061d69SRoman Lebedev 
false_positives_unevaluated_ctxfalse_positives_unevaluated_ctx_class111*61061d69SRoman Lebedev   void false_positives_unevaluated_ctx(SNoExcept a) noexcept(noexcept(a = a)) {
112*61061d69SRoman Lebedev     decltype(a = a) b = a;
113*61061d69SRoman Lebedev     static_assert(noexcept(a = a), "");
114*61061d69SRoman Lebedev     static_assert(sizeof(a = a), "");
115*61061d69SRoman Lebedev   }
116*61061d69SRoman Lebedev };
117*61061d69SRoman Lebedev 
118*61061d69SRoman Lebedev template <typename T>
119*61061d69SRoman Lebedev struct TemplateClass {
120*61061d69SRoman Lebedev   T var;
fTemplateClass121*61061d69SRoman Lebedev   void f() {
122*61061d69SRoman Lebedev     var = var; // expected-warning {{assigning field to itself}}
123*61061d69SRoman Lebedev   }
124*61061d69SRoman Lebedev };
instantiate()125*61061d69SRoman Lebedev void instantiate() {
126*61061d69SRoman Lebedev   {
127*61061d69SRoman Lebedev     TemplateClass<int> c;
128*61061d69SRoman Lebedev     c.f();
129*61061d69SRoman Lebedev   }
130*61061d69SRoman Lebedev   {
131*61061d69SRoman Lebedev     TemplateClass<S> c;
132*61061d69SRoman Lebedev     c.f();
133*61061d69SRoman Lebedev   }
134*61061d69SRoman Lebedev }
135*61061d69SRoman Lebedev 
136*61061d69SRoman Lebedev // It may make sense not to warn on the rest of the tests.
137*61061d69SRoman Lebedev // It may be a valid use-case to self-assign to tell the compiler that
138*61061d69SRoman Lebedev // it is ok to vectorize the store.
139*61061d69SRoman Lebedev 
f0(C * s,C * t)140*61061d69SRoman Lebedev void f0(C *s, C *t) {
141*61061d69SRoman Lebedev   s->a = s->a;
142*61061d69SRoman Lebedev   t->a = s->a;
143*61061d69SRoman Lebedev }
144*61061d69SRoman Lebedev 
f1(C & s,C & t)145*61061d69SRoman Lebedev void f1(C &s, C &t) {
146*61061d69SRoman Lebedev   s.a = s.a;
147*61061d69SRoman Lebedev   t.a = s.a;
148*61061d69SRoman Lebedev }
149*61061d69SRoman Lebedev 
150*61061d69SRoman Lebedev struct T {
151*61061d69SRoman Lebedev   C *s;
152*61061d69SRoman Lebedev };
153*61061d69SRoman Lebedev 
f2(T * t,T * t2)154*61061d69SRoman Lebedev void f2(T *t, T *t2) {
155*61061d69SRoman Lebedev   t->s->a = t->s->a;
156*61061d69SRoman Lebedev   t2->s->a = t->s->a;
157*61061d69SRoman Lebedev }
158*61061d69SRoman Lebedev 
f3(T & t,T & t2)159*61061d69SRoman Lebedev void f3(T &t, T &t2) {
160*61061d69SRoman Lebedev   t.s->a = t.s->a;
161*61061d69SRoman Lebedev   t2.s->a = t.s->a;
162*61061d69SRoman Lebedev }
163