1 // RUN: %check_clang_tidy %s misc-unconventional-assign-operator %t -- -- -isystem %S/Inputs/Headers -fno-delayed-template-parsing
2 
3 namespace std {
4 template <typename T>
5 struct remove_reference { typedef T type; };
6 template <typename T>
7 struct remove_reference<T &> { typedef T type; };
8 template <typename T>
9 struct remove_reference<T &&> { typedef T type; };
10 template <typename T>
11 typename remove_reference<T>::type &&move(T &&t);
12 }
13 
14 
15 struct Good {
16   Good& operator=(const Good&);
17   Good& operator=(Good&&);
18 
19   // Assign from other types is fine too.
20   Good& operator=(int);
21 };
22 
23 struct AlsoGood {
24   // By value is also fine.
25   AlsoGood& operator=(AlsoGood);
26 };
27 
28 struct BadReturnType {
29   void operator=(const BadReturnType&);
30   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'BadReturnType&' [misc-unconventional-assign-operator]
31   const BadReturnType& operator=(BadReturnType&&);
32   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
33   void operator=(int);
34   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
35 };
36 
37 struct BadReturnType2 {
38   BadReturnType2&& operator=(const BadReturnType2&);
39   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
40   int operator=(BadReturnType2&&);
41   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
42 };
43 
44 struct BadArgument {
45   BadArgument& operator=(BadArgument&);
46   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should take 'BadArgument const&', 'BadArgument&&' or 'BadArgument'
47   BadArgument& operator=(const BadArgument&&);
48   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should take 'BadAr
49 };
50 
51 struct BadModifier {
52   BadModifier& operator=(const BadModifier&) const;
53   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'const'
54 };
55 
56 struct Deleted {
57   // We don't check the return value of deleted operators.
58   void operator=(const Deleted&) = delete;
59   void operator=(Deleted&&) = delete;
60 };
61 
62 class Private {
63   // We don't check the return value of private operators.
64   // Pre-C++11 way of disabling assignment.
65   void operator=(const Private &);
66 };
67 
68 struct Virtual {
69   virtual Virtual& operator=(const Virtual &);
70   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should not be marked 'virtual'
71 };
72 
73 class BadReturnStatement {
74   int n;
75 
76 public:
operator =(BadReturnStatement && rhs)77   BadReturnStatement& operator=(BadReturnStatement&& rhs) {
78     n = std::move(rhs.n);
79     return rhs;
80 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator=() should always return '*this'
81   }
82 
83   // Do not check if return type is different from '&BadReturnStatement'
operator =(int i)84   int operator=(int i) {
85   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'Bad
86     n = i;
87     return n;
88   }
89 };
90 
91 namespace pr31531 {
92 enum E { e };
93 // This declaration makes the 'return *this' below have an unresolved operator
94 // in the class template, but not in an instantiation.
95 E operator*(E, E);
96 
97 template <typename>
98 struct UnresolvedOperator {
operator =pr31531::UnresolvedOperator99   UnresolvedOperator &operator=(const UnresolvedOperator &) { return *this; }
100 };
101 
102 UnresolvedOperator<int> UnresolvedOperatorInt;
103 
104 template <typename>
105 struct Template {
operator =pr31531::Template106   Template &operator=(const Template &) { return this; }
107   // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: operator=() should always return '*this'
108 };
109 
110 Template<int> TemplateInt;
111 }
112 
113 struct AssignmentCallAtReturn {
returnThisAssignmentCallAtReturn114   AssignmentCallAtReturn &returnThis() {
115     return *this;
116   }
operator =AssignmentCallAtReturn117   AssignmentCallAtReturn &operator=(int rhs) {
118     return *this;
119   }
operator =AssignmentCallAtReturn120   AssignmentCallAtReturn &operator=(char rhs) {
121     // Allow call to assignment from other type.
122     return (*this = static_cast<int>(rhs));
123   }
operator =AssignmentCallAtReturn124   AssignmentCallAtReturn &operator=(float rhs) {
125     // Do not allow calls to other functions.
126     return returnThis();
127     // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator=() should always return '*this'
128   }
129 };
130