1 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DDUMMY -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV0 -verify %s
3 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV1 -verify %s
4 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV2 -verify %s
5 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV3 -verify %s
6 // RUN: %clang_cc1 -fsyntax-only -Wself-assign -DV4 -verify %s
7 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DDUMMY -verify %s
8 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV0 -verify %s
9 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV1 -verify %s
10 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV2 -verify %s
11 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV3 -verify %s
12 // RUN: %clang_cc1 -fsyntax-only -Wno-self-assign -Wself-assign-overloaded -DV4 -verify %s
13
14 #ifdef DUMMY
15 struct S {};
16 #else
17 struct S {
18 #if defined(V0)
19 S() = default;
20 #elif defined(V1)
21 S &operator=(const S &) = default;
22 #elif defined(V2)
23 S &operator=(S &) = default;
24 #elif defined(V3)
25 S &operator=(const S &);
26 #elif defined(V4)
27 S &operator=(S &);
28 #else
29 #error Define something!
30 #endif
31 S &operator*=(const S &);
32 S &operator/=(const S &);
33 S &operator%=(const S &);
34 S &operator+=(const S &);
35 S &operator-=(const S &);
36 S &operator<<=(const S &);
37 S &operator>>=(const S &);
38 S &operator&=(const S &);
39 S &operator|=(const S &);
40 S &operator^=(const S &);
41 S &operator=(const volatile S &) volatile;
42 };
43 #endif
44
f()45 void f() {
46 S a, b;
47 a = a; // expected-warning{{explicitly assigning}}
48 b = b; // expected-warning{{explicitly assigning}}
49 a = b;
50 b = a = b;
51 a = a = a; // expected-warning{{explicitly assigning}}
52 a = b = b = a;
53
54 #ifndef DUMMY
55 a *= a;
56 a /= a; // expected-warning {{explicitly assigning}}
57 a %= a; // expected-warning {{explicitly assigning}}
58 a += a;
59 a -= a; // expected-warning {{explicitly assigning}}
60 a <<= a;
61 a >>= a;
62 a &= a; // expected-warning {{explicitly assigning}}
63 a |= a; // expected-warning {{explicitly assigning}}
64 a ^= a; // expected-warning {{explicitly assigning}}
65 #endif
66 }
67
false_positives()68 void false_positives() {
69 #define OP =
70 #define LHS a
71 #define RHS a
72 S a;
73 // These shouldn't warn due to the use of the preprocessor.
74 a OP a;
75 LHS = a;
76 a = RHS;
77 LHS OP RHS;
78 #undef OP
79 #undef LHS
80 #undef RHS
81
82 // Ways to silence the warning.
83 a = *&a;
84 a = (S &)a;
85 a = static_cast<decltype(a) &>(a);
86
87 #ifndef DUMMY
88 // Volatile stores aren't side-effect free.
89 volatile S vol_a;
90 vol_a = vol_a;
91 volatile S &vol_a_ref = vol_a;
92 vol_a_ref = vol_a_ref;
93 #endif
94 }
95
96 // Do not diagnose self-assigment in an unevaluated context
97 struct SNoExcept {
98 SNoExcept() = default;
99 SNoExcept &operator=(const SNoExcept &) noexcept;
100 };
false_positives_unevaluated_ctx(SNoExcept a)101 void false_positives_unevaluated_ctx(SNoExcept a) noexcept(noexcept(a = a)) {
102 decltype(a = a) b = a;
103 static_assert(noexcept(a = a), "");
104 static_assert(sizeof(a = a), "");
105 }
106
107 template <typename T>
g()108 void g() {
109 T a;
110 a = a; // expected-warning{{explicitly assigning}}
111 }
instantiate()112 void instantiate() {
113 g<int>();
114 g<S>();
115 }
116