1d3f92e30SSopy // RUN: %check_clang_tidy %s modernize-min-max-use-initializer-list %t 2d3f92e30SSopy 3d3f92e30SSopy // CHECK-FIXES: #include <algorithm> 4d3f92e30SSopy namespace utils { 5d3f92e30SSopy template <typename T> 6d3f92e30SSopy T max(T a, T b) { 7d3f92e30SSopy return (a < b) ? b : a; 8d3f92e30SSopy } 9d3f92e30SSopy } // namespace utils 10d3f92e30SSopy 11d3f92e30SSopy namespace std { 12d3f92e30SSopy template< class T > 13d3f92e30SSopy struct initializer_list { 14482c41e9SMital Ashok const T *a, *b; 15d3f92e30SSopy initializer_list()=default; 16d3f92e30SSopy initializer_list(T*,int){} 17d3f92e30SSopy const T* begin() const {return nullptr;} 18d3f92e30SSopy const T* end() const {return nullptr;} 19d3f92e30SSopy }; 20d3f92e30SSopy 21d3f92e30SSopy template<class ForwardIt> 22d3f92e30SSopy ForwardIt min_element(ForwardIt first, ForwardIt last) 23d3f92e30SSopy { 24d3f92e30SSopy if (first == last) 25d3f92e30SSopy return last; 26d3f92e30SSopy 27d3f92e30SSopy ForwardIt smallest = first; 28d3f92e30SSopy 29d3f92e30SSopy while (++first != last) 30d3f92e30SSopy if (*first < *smallest) 31d3f92e30SSopy smallest = first; 32d3f92e30SSopy 33d3f92e30SSopy return smallest; 34d3f92e30SSopy } 35d3f92e30SSopy 36d3f92e30SSopy template<class ForwardIt, class Compare> 37d3f92e30SSopy ForwardIt min_element(ForwardIt first, ForwardIt last, Compare comp) 38d3f92e30SSopy { 39d3f92e30SSopy if (first == last) 40d3f92e30SSopy return last; 41d3f92e30SSopy 42d3f92e30SSopy ForwardIt smallest = first; 43d3f92e30SSopy 44d3f92e30SSopy while (++first != last) 45d3f92e30SSopy if (comp(*first, *smallest)) 46d3f92e30SSopy smallest = first; 47d3f92e30SSopy 48d3f92e30SSopy return smallest; 49d3f92e30SSopy } 50d3f92e30SSopy 51d3f92e30SSopy template<class ForwardIt> 52d3f92e30SSopy ForwardIt max_element(ForwardIt first, ForwardIt last) 53d3f92e30SSopy { 54d3f92e30SSopy if (first == last) 55d3f92e30SSopy return last; 56d3f92e30SSopy 57d3f92e30SSopy ForwardIt largest = first; 58d3f92e30SSopy 59d3f92e30SSopy while (++first != last) 60d3f92e30SSopy if (*largest < *first) 61d3f92e30SSopy largest = first; 62d3f92e30SSopy 63d3f92e30SSopy return largest; 64d3f92e30SSopy } 65d3f92e30SSopy 66d3f92e30SSopy template<class ForwardIt, class Compare> 67d3f92e30SSopy ForwardIt max_element(ForwardIt first, ForwardIt last, Compare comp) 68d3f92e30SSopy { 69d3f92e30SSopy if (first == last) 70d3f92e30SSopy return last; 71d3f92e30SSopy 72d3f92e30SSopy ForwardIt largest = first; 73d3f92e30SSopy 74d3f92e30SSopy while(++first != last) 75d3f92e30SSopy if (comp(*largest, *first)) 76d3f92e30SSopy largest = first; 77d3f92e30SSopy 78d3f92e30SSopy return largest; 79d3f92e30SSopy } 80d3f92e30SSopy 81d3f92e30SSopy template< class T > 82d3f92e30SSopy const T& max( const T& a, const T& b ) { 83d3f92e30SSopy return (a < b) ? b : a; 84d3f92e30SSopy }; 85d3f92e30SSopy 86d3f92e30SSopy template< class T > 87d3f92e30SSopy T max(std::initializer_list<T> ilist) 88d3f92e30SSopy { 89d3f92e30SSopy return *std::max_element(ilist.begin(), ilist.end()); 90d3f92e30SSopy } 91d3f92e30SSopy 92d3f92e30SSopy template< class T, class Compare > 93d3f92e30SSopy const T& max( const T& a, const T& b, Compare comp ) { 94d3f92e30SSopy return (comp(a, b)) ? b : a; 95d3f92e30SSopy }; 96d3f92e30SSopy 97d3f92e30SSopy template< class T, class Compare > 98d3f92e30SSopy T max(std::initializer_list<T> ilist, Compare comp) { 99d3f92e30SSopy return *std::max_element(ilist.begin(), ilist.end(), comp); 100d3f92e30SSopy }; 101d3f92e30SSopy 102d3f92e30SSopy template< class T > 103d3f92e30SSopy const T& min( const T& a, const T& b ) { 104d3f92e30SSopy return (b < a) ? b : a; 105d3f92e30SSopy }; 106d3f92e30SSopy 107d3f92e30SSopy template< class T > 108d3f92e30SSopy T min(std::initializer_list<T> ilist) 109d3f92e30SSopy { 110d3f92e30SSopy return *std::min_element(ilist.begin(), ilist.end()); 111d3f92e30SSopy } 112d3f92e30SSopy 113d3f92e30SSopy 114d3f92e30SSopy template< class T, class Compare > 115d3f92e30SSopy const T& min( const T& a, const T& b, Compare comp ) { 116d3f92e30SSopy return (comp(b, a)) ? b : a; 117d3f92e30SSopy }; 118d3f92e30SSopy 119d3f92e30SSopy template< class T, class Compare > 120d3f92e30SSopy T min(std::initializer_list<T> ilist, Compare comp) { 121d3f92e30SSopy return *std::min_element(ilist.begin(), ilist.end(), comp); 122d3f92e30SSopy }; 123d3f92e30SSopy 124d3f92e30SSopy } // namespace std 125d3f92e30SSopy 126d3f92e30SSopy using namespace std; 127d3f92e30SSopy 128d3f92e30SSopy namespace { 129d3f92e30SSopy bool fless_than(int a, int b) { 130d3f92e30SSopy return a < b; 131d3f92e30SSopy } 132d3f92e30SSopy 133d3f92e30SSopy bool fgreater_than(int a, int b) { 134d3f92e30SSopy return a > b; 135d3f92e30SSopy } 136d3f92e30SSopy auto less_than = [](int a, int b) { return a < b; }; 137d3f92e30SSopy auto greater_than = [](int a, int b) { return a > b; }; 138d3f92e30SSopy 139d3f92e30SSopy int max1 = std::max(1, std::max(2, 3)); 140d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 141d3f92e30SSopy // CHECK-FIXES: int max1 = std::max({1, 2, 3}); 142d3f92e30SSopy 143d3f92e30SSopy int min1 = std::min(1, std::min(2, 3)); 144d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 145d3f92e30SSopy // CHECK-FIXES: int min1 = std::min({1, 2, 3}); 146d3f92e30SSopy 147d3f92e30SSopy int max2 = std::max(1, std::max(2, std::max(3, 4))); 148d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 149d3f92e30SSopy // CHECK-FIXES: int max2 = std::max({1, 2, 3, 4}); 150d3f92e30SSopy 151d3f92e30SSopy int max2b = std::max(std::max(std::max(1, 2), std::max(3, 4)), std::max(std::max(5, 6), std::max(7, 8))); 152d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 153d3f92e30SSopy // CHECK-FIXES: int max2b = std::max({1, 2, 3, 4, 5, 6, 7, 8}); 154d3f92e30SSopy 155d3f92e30SSopy int max2c = std::max(std::max(1, std::max(2, 3)), 4); 156d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 157d3f92e30SSopy // CHECK-FIXES: int max2c = std::max({1, 2, 3, 4}); 158d3f92e30SSopy 159d3f92e30SSopy int max2d = std::max(std::max({1, 2, 3}), 4); 160d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 161d3f92e30SSopy // CHECK-FIXES: int max2d = std::max({1, 2, 3, 4}); 162d3f92e30SSopy 163d3f92e30SSopy 164d3f92e30SSopy int max2e = std::max(1, max(2, max(3, 4))); 165d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 166d3f92e30SSopy // CHECK-FIXES: int max2e = std::max({1, 2, 3, 4}); 167d3f92e30SSopy 168d3f92e30SSopy int min2 = std::min(1, std::min(2, std::min(3, 4))); 169d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 170d3f92e30SSopy // CHECK-FIXES: int min2 = std::min({1, 2, 3, 4}); 171d3f92e30SSopy 172d3f92e30SSopy int max3 = std::max(std::max(4, 5), std::min(2, std::min(3, 1))); 173d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 174d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-2]]:37: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 175d3f92e30SSopy // CHECK-FIXES: int max3 = std::max({4, 5, std::min({2, 3, 1})}); 176d3f92e30SSopy 177d3f92e30SSopy int min3 = std::min(std::min(4, 5), std::max(2, std::max(3, 1))); 178d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 179d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-2]]:37: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 180d3f92e30SSopy // CHECK-FIXES: int min3 = std::min({4, 5, std::max({2, 3, 1})}); 181d3f92e30SSopy 182d3f92e30SSopy int max4 = std::max(1, std::max(2, 3, greater_than), less_than); 183d3f92e30SSopy // CHECK-FIXES: int max4 = std::max(1, std::max(2, 3, greater_than), less_than); 184d3f92e30SSopy 185d3f92e30SSopy int min4 = std::min(1, std::min(2, 3, greater_than), less_than); 186d3f92e30SSopy // CHECK-FIXES: int min4 = std::min(1, std::min(2, 3, greater_than), less_than); 187d3f92e30SSopy 188d3f92e30SSopy int max5 = std::max(1, std::max(2, 3), less_than); 189d3f92e30SSopy // CHECK-FIXES: int max5 = std::max(1, std::max(2, 3), less_than); 190d3f92e30SSopy 191d3f92e30SSopy int min5 = std::min(1, std::min(2, 3), less_than); 192d3f92e30SSopy // CHECK-FIXES: int min5 = std::min(1, std::min(2, 3), less_than); 193d3f92e30SSopy 194d3f92e30SSopy int max6 = std::max(1, std::max(2, 3, greater_than), greater_than); 195d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 196d3f92e30SSopy // CHECK-FIXES: int max6 = std::max({1, 2, 3 }, greater_than); 197d3f92e30SSopy 198d3f92e30SSopy int min6 = std::min(1, std::min(2, 3, greater_than), greater_than); 199d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 200d3f92e30SSopy // CHECK-FIXES: int min6 = std::min({1, 2, 3 }, greater_than); 201d3f92e30SSopy 202d3f92e30SSopy int max7 = std::max(1, std::max(2, 3, fless_than), fgreater_than); 203d3f92e30SSopy // CHECK-FIXES: int max7 = std::max(1, std::max(2, 3, fless_than), fgreater_than); 204d3f92e30SSopy 205d3f92e30SSopy int min7 = std::min(1, std::min(2, 3, fless_than), fgreater_than); 206d3f92e30SSopy // CHECK-FIXES: int min7 = std::min(1, std::min(2, 3, fless_than), fgreater_than); 207d3f92e30SSopy 208d3f92e30SSopy int max8 = std::max(1, std::max(2, 3, fless_than), less_than); 209d3f92e30SSopy // CHECK-FIXES: int max8 = std::max(1, std::max(2, 3, fless_than), less_than) 210d3f92e30SSopy 211d3f92e30SSopy int min8 = std::min(1, std::min(2, 3, fless_than), less_than); 212d3f92e30SSopy // CHECK-FIXES: int min8 = std::min(1, std::min(2, 3, fless_than), less_than); 213d3f92e30SSopy 214d3f92e30SSopy int max9 = std::max(1, std::max(2, 3, fless_than), fless_than); 215d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 216d3f92e30SSopy // CHECK-FIXES: int max9 = std::max({1, 2, 3 }, fless_than); 217d3f92e30SSopy 218d3f92e30SSopy int min9 = std::min(1, std::min(2, 3, fless_than), fless_than); 219d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 220d3f92e30SSopy // CHECK-FIXES: int min9 = std::min({1, 2, 3 }, fless_than); 221d3f92e30SSopy 222d3f92e30SSopy int min10 = std::min(std::min(4, 5), std::max(2, utils::max(3, 1))); 223d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 224d3f92e30SSopy // CHECK-FIXES: int min10 = std::min({4, 5, std::max(2, utils::max(3, 1))}); 225d3f92e30SSopy 226d3f92e30SSopy int max10 = std::max({std::max(1, 2), std::max({5, 6, 1}), 2, std::min({1, 2, 4})}); 227d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 228d3f92e30SSopy // CHECK-FIXES: int max10 = std::max({1, 2, 5, 6, 1, 2, std::min({1, 2, 4})}); 229d3f92e30SSopy 230d3f92e30SSopy int typecastTest = std::max(std::max<int>(0U, 0.0f), 0); 231d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 232d3f92e30SSopy // CHECK-FIXES: int typecastTest = std::max({static_cast<int>(0U), static_cast<int>(0.0f), 0}); 233d3f92e30SSopy 234d3f92e30SSopy int typecastTest1 = std::max(std::max<long>(0U, 0.0f), 0L); 235d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 236d3f92e30SSopy // CHECK-FIXES: int typecastTest1 = std::max({static_cast<long>(0U), static_cast<long>(0.0f), 0L}); 237d3f92e30SSopy 238d3f92e30SSopy int typecastTest2 = std::max(std::max<int>(10U, 20.0f), 30); 239d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 240d3f92e30SSopy // CHECK-FIXES: int typecastTest2 = std::max({static_cast<int>(10U), static_cast<int>(20.0f), 30}); 241d3f92e30SSopy 242d3f92e30SSopy int typecastTest3 = std::max(std::max<int>(0U, std::max<int>(0.0f, 1.0f)), 0); 243d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 244d3f92e30SSopy // CHECK-FIXES: int typecastTest3 = std::max({static_cast<int>(0U), static_cast<int>(0.0f), static_cast<int>(1.0f), 0}); 245d3f92e30SSopy 246d3f92e30SSopy #define max3f(a, b, c) std::max(a, std::max(b, c)) 247d3f92e30SSopy // CHECK-FIXES: #define max3f(a, b, c) std::max(a, std::max(b, c)) 248d3f92e30SSopy 249d3f92e30SSopy #define value 4545 250d3f92e30SSopy int macroVarMax = std::max(value, std::max(1, 2)); 251d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 252d3f92e30SSopy // CHECK-FIXES: int macroVarMax = std::max({value, 1, 2}); 253d3f92e30SSopy 254d3f92e30SSopy #define value2 45U 255d3f92e30SSopy int macroVarMax2 = std::max(1, std::max<int>(value2, 2.0f)); 256d3f92e30SSopy // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 257d3f92e30SSopy // CHECK-FIXES: int macroVarMax2 = std::max({1, static_cast<int>(value2), static_cast<int>(2.0f)}); 258d3f92e30SSopy 259d3f92e30SSopy // True-negative tests 260d3f92e30SSopy int maxTN1 = std::max(1, 2); 261d3f92e30SSopy // CHECK-FIXES: int maxTN1 = std::max(1, 2); 262d3f92e30SSopy 263d3f92e30SSopy int maxTN2 = std::max({1, 2, 3}); 264d3f92e30SSopy // CHECK-FIXES: int maxTN2 = std::max({1, 2, 3}); 265d3f92e30SSopy 266d3f92e30SSopy int maxTN3 = std::max({1, 2, 3}, less_than); 267d3f92e30SSopy // CHECK-FIXES: int maxTN3 = std::max({1, 2, 3}, less_than); 268d3f92e30SSopy 269d3f92e30SSopy // non-trivial types 270d3f92e30SSopy struct A { 271d3f92e30SSopy int a; 272d3f92e30SSopy A(int a) : a(a) {} 273d3f92e30SSopy bool operator<(const A &rhs) const { return a < rhs.a; } 274d3f92e30SSopy }; 275d3f92e30SSopy 276d3f92e30SSopy A maxNT1 = std::max(A(1), A(2)); 277d3f92e30SSopy // CHECK-FIXES: A maxNT1 = std::max(A(1), A(2)); 278d3f92e30SSopy 279d3f92e30SSopy A maxNT2 = std::max(A(1), std::max(A(2), A(3))); 280d3f92e30SSopy // CHECK-FIXES: A maxNT2 = std::max(A(1), std::max(A(2), A(3))); 281d3f92e30SSopy 282d3f92e30SSopy A maxNT3 = std::max(A(1), std::max(A(2), A(3)), [](const A &lhs, const A &rhs) { return lhs.a < rhs.a; }); 283d3f92e30SSopy // CHECK-FIXES: A maxNT3 = std::max(A(1), std::max(A(2), A(3)), [](const A &lhs, const A &rhs) { return lhs.a < rhs.a; }); 284d3f92e30SSopy 285d3f92e30SSopy // Trivial type with size greater than 32 286d3f92e30SSopy struct B { 287d3f92e30SSopy // 9*4 = 36 bytes > 32 bytes 288d3f92e30SSopy int a[9]; 289d3f92e30SSopy 290d3f92e30SSopy bool operator<(const B& rhs) const { 291d3f92e30SSopy return a[0] < rhs.a[0]; 292d3f92e30SSopy } 293d3f92e30SSopy }; 294d3f92e30SSopy 295d3f92e30SSopy B maxTT1 = std::max(B(), B()); 296d3f92e30SSopy // CHECK-FIXES: B maxTT1 = std::max(B(), B()); 297d3f92e30SSopy 298d3f92e30SSopy B maxTT2 = std::max(B(), std::max(B(), B())); 299d3f92e30SSopy // CHECK-FIXES: B maxTT2 = std::max(B(), std::max(B(), B())); 300d3f92e30SSopy 301d3f92e30SSopy B maxTT3 = std::max(B(), std::max(B(), B()), [](const B &lhs, const B &rhs) { return lhs.a[0] < rhs.a[0]; }); 302d3f92e30SSopy // CHECK-FIXES: B maxTT3 = std::max(B(), std::max(B(), B()), [](const B &lhs, const B &rhs) { return lhs.a[0] < rhs.a[0]; }); 303d3f92e30SSopy 304932f0de4SJulian Schmidt struct GH91982 { 305932f0de4SJulian Schmidt int fun0Args(); 306932f0de4SJulian Schmidt int fun1Arg(int a); 307932f0de4SJulian Schmidt int fun2Args(int a, int b); 308932f0de4SJulian Schmidt int fun3Args(int a, int b, int c); 309932f0de4SJulian Schmidt int fun4Args(int a, int b, int c, int d); 310932f0de4SJulian Schmidt 311932f0de4SJulian Schmidt int foo() { 312932f0de4SJulian Schmidt return std::max( 313932f0de4SJulian Schmidt fun0Args(), 314932f0de4SJulian Schmidt std::max(fun1Arg(0), 315932f0de4SJulian Schmidt std::max(fun2Args(0, 1), 316932f0de4SJulian Schmidt std::max(fun3Args(0, 1, 2), fun4Args(0, 1, 2, 3))))); 317932f0de4SJulian Schmidt // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list] 318932f0de4SJulian Schmidt // CHECK-FIXES: return std::max( 319932f0de4SJulian Schmidt // CHECK-FIXES-NEXT: {fun0Args(), 320932f0de4SJulian Schmidt // CHECK-FIXES-NEXT: fun1Arg(0), 321932f0de4SJulian Schmidt // CHECK-FIXES-NEXT: fun2Args(0, 1), 322932f0de4SJulian Schmidt // CHECK-FIXES-NEXT: fun3Args(0, 1, 2), fun4Args(0, 1, 2, 3)}); 323932f0de4SJulian Schmidt } 324932f0de4SJulian Schmidt }; 325d3f92e30SSopy 326*605a9adbSJulian Schmidt struct GH107594 { 327*605a9adbSJulian Schmidt int foo(int a, int b, char c) { 328*605a9adbSJulian Schmidt return std::max<int>({a, b, c}); 329*605a9adbSJulian Schmidt } 330*605a9adbSJulian Schmidt }; 331*605a9adbSJulian Schmidt 332d3f92e30SSopy } // namespace 333d3f92e30SSopy 334