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