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