Clang Project

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