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