1// SPDX-License-Identifier: GPL-2.0-only 2/// 3/// Check for opencoded min(), max() implementations. 4/// Generated patches sometimes require adding a cast to fix compile warning. 5/// Warnings/patches scope intentionally limited to a function body. 6/// 7// Confidence: Medium 8// Copyright: (C) 2021 Denis Efremov ISPRAS 9// Options: --no-includes --include-headers 10// 11// Keywords: min, max 12// 13 14 15virtual report 16virtual org 17virtual context 18virtual patch 19 20@max_candidate disable not_int1, not_int2, neg_if_exp@ 21expression E1, E2, E3, E4; 22binary operator cmp = {>, >=}; 23@@ 24 25 E1 cmp E2 ? E3 : E4 26 27@min_candidate disable not_int1, not_int2, neg_if_exp@ 28expression E1, E2, E3, E4; 29binary operator cmp = {<, <=}; 30@@ 31 32 E1 cmp E2 ? E3 : E4 33 34@rmax depends on !patch && max_candidate disable not_int1, not_int2, neg_if_exp@ 35identifier func; 36expression x, y; 37binary operator cmp = {>, >=}; 38position p; 39@@ 40 41func(...) 42{ 43 <... 44* (x) cmp@p (y) ? (x) : (y) 45 ...> 46} 47 48@maxif_candidate disable not_int1, not_int2, neg_if@ 49expression x, y; 50expression max_val; 51binary operator cmp = {>, >=}; 52@@ 53 54if ((x) cmp (y)) { 55 max_val = (x); 56} else { 57 max_val = (y); 58} 59 60@rmaxif depends on !patch && maxif_candidate disable not_int1, not_int2, neg_if@ 61identifier func; 62expression x, y; 63expression max_val; 64binary operator cmp = {>, >=}; 65position p; 66@@ 67 68func(...) 69{ 70 <... 71* if ((x) cmp@p (y)) { 72* max_val = (x); 73* } else { 74* max_val = (y); 75* } 76 ...> 77} 78 79// Ignore errcode returns. 80@errcode depends on min_candidate disable not_int1, not_int2, neg_if_exp@ 81position p; 82identifier func; 83expression x; 84binary operator cmp = {<, <=}; 85@@ 86 87func(...) 88{ 89 <... 90 return ((x) cmp@p 0 ? (x) : 0); 91 ...> 92} 93 94@rmin depends on !patch && min_candidate disable not_int1, not_int2, neg_if_exp@ 95identifier func; 96expression x, y; 97binary operator cmp = {<, <=}; 98position p != errcode.p; 99@@ 100 101func(...) 102{ 103 <... 104* (x) cmp@p (y) ? (x) : (y) 105 ...> 106} 107 108@minif_candidate disable not_int1, not_int2, neg_if@ 109expression x, y; 110expression min_val; 111binary operator cmp = {<, <=}; 112@@ 113 114if ((x) cmp (y)) { 115 min_val = (x); 116} else { 117 min_val = (y); 118} 119 120@rminif depends on !patch && minif_candidate disable not_int1, not_int2, neg_if@ 121identifier func; 122expression x, y; 123expression min_val; 124binary operator cmp = {<, <=}; 125position p; 126@@ 127 128func(...) 129{ 130 <... 131* if ((x) cmp@p (y)) { 132* min_val = (x); 133* } else { 134* min_val = (y); 135* } 136 ...> 137} 138 139@pmax depends on patch && max_candidate disable not_int1, not_int2, neg_if_exp@ 140identifier func; 141expression x, y; 142binary operator cmp = {>=, >}; 143@@ 144 145func(...) 146{ 147 <... 148- ((x) cmp (y) ? (x) : (y)) 149+ max(x, y) 150 ...> 151} 152 153@pmaxif depends on patch && maxif_candidate disable not_int1, not_int2, neg_if@ 154identifier func; 155expression x, y; 156expression max_val; 157binary operator cmp = {>=, >}; 158@@ 159 160func(...) 161{ 162 <... 163- if ((x) cmp (y)) { 164- max_val = x; 165- } else { 166- max_val = y; 167- } 168+ max_val = max(x, y); 169 ...> 170} 171 172@pmin depends on patch && min_candidate disable not_int1, not_int2, neg_if_exp@ 173identifier func; 174expression x, y; 175binary operator cmp = {<=, <}; 176position p != errcode.p; 177@@ 178 179func(...) 180{ 181 <... 182- ((x) cmp@p (y) ? (x) : (y)) 183+ min(x, y) 184 ...> 185} 186 187@pminif depends on patch && minif_candidate disable not_int1, not_int2, neg_if@ 188identifier func; 189expression x, y; 190expression min_val; 191binary operator cmp = {<=, <}; 192@@ 193 194func(...) 195{ 196 <... 197- if ((x) cmp (y)) { 198- min_val = x; 199- } else { 200- min_val = y; 201- } 202+ min_val = min(x, y); 203 ...> 204} 205 206@script:python depends on report@ 207p << rmax.p; 208@@ 209 210for p0 in p: 211 coccilib.report.print_report(p0, "WARNING opportunity for max()") 212 213@script:python depends on org@ 214p << rmax.p; 215@@ 216 217for p0 in p: 218 coccilib.org.print_todo(p0, "WARNING opportunity for max()") 219 220@script:python depends on report@ 221p << rmaxif.p; 222@@ 223 224for p0 in p: 225 coccilib.report.print_report(p0, "WARNING opportunity for max()") 226 227@script:python depends on org@ 228p << rmaxif.p; 229@@ 230 231for p0 in p: 232 coccilib.org.print_todo(p0, "WARNING opportunity for max()") 233 234@script:python depends on report@ 235p << rmin.p; 236@@ 237 238for p0 in p: 239 coccilib.report.print_report(p0, "WARNING opportunity for min()") 240 241@script:python depends on org@ 242p << rmin.p; 243@@ 244 245for p0 in p: 246 coccilib.org.print_todo(p0, "WARNING opportunity for min()") 247 248@script:python depends on report@ 249p << rminif.p; 250@@ 251 252for p0 in p: 253 coccilib.report.print_report(p0, "WARNING opportunity for min()") 254 255@script:python depends on org@ 256p << rminif.p; 257@@ 258 259for p0 in p: 260 coccilib.org.print_todo(p0, "WARNING opportunity for min()") 261