• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
9 struct S {};
10 #else
11 struct 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
38 struct C {
39   S a;
40   S b;
41 
fC42   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 
false_positivesC73   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;
vol_testC94   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
104 struct SNoExcept {
105   SNoExcept() = default;
106   SNoExcept &operator=(const SNoExcept &) noexcept;
107 };
108 struct false_positives_unevaluated_ctx_class {
109   SNoExcept a;
110 
false_positives_unevaluated_ctxfalse_positives_unevaluated_ctx_class111   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 
118 template <typename T>
119 struct TemplateClass {
120   T var;
fTemplateClass121   void f() {
122     var = var; // expected-warning {{assigning field to itself}}
123   }
124 };
instantiate()125 void 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 
f0(C * s,C * t)140 void f0(C *s, C *t) {
141   s->a = s->a;
142   t->a = s->a;
143 }
144 
f1(C & s,C & t)145 void f1(C &s, C &t) {
146   s.a = s.a;
147   t.a = s.a;
148 }
149 
150 struct T {
151   C *s;
152 };
153 
f2(T * t,T * t2)154 void f2(T *t, T *t2) {
155   t->s->a = t->s->a;
156   t2->s->a = t->s->a;
157 }
158 
f3(T & t,T & t2)159 void f3(T &t, T &t2) {
160   t.s->a = t.s->a;
161   t2.s->a = t.s->a;
162 }
163