File: suspicious-call-argument.cpp

package info (click to toggle)
llvm-toolchain-17 1%3A17.0.6-22
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,799,624 kB
  • sloc: cpp: 6,428,607; ansic: 1,383,196; asm: 793,408; python: 223,504; objc: 75,364; f90: 60,502; lisp: 33,869; pascal: 15,282; sh: 9,684; perl: 7,453; ml: 4,937; awk: 3,523; makefile: 2,889; javascript: 2,149; xml: 888; fortran: 619; cs: 573
file content (516 lines) | stat: -rw-r--r-- 18,963 bytes parent folder | download | duplicates (13)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
// RUN: %check_clang_tidy %s readability-suspicious-call-argument %t -- -- -std=c++11

void foo_1(int aaaaaa, int bbbbbb) {}

void foo_2(int source, int aaaaaa) {}

void foo_3(int valToRet, int aaaaaa) {}

void foo_4(int pointer, int aaaaaa) {}

void foo_5(int aaaaaa, int bbbbbb, int cccccc, ...) {}

void foo_6(const int dddddd, bool &eeeeee) {}

void foo_7(int aaaaaa, int bbbbbb, int cccccc, int ffffff = 7) {}

void foo_8(int frobble1, int frobble2) {}

// Test functions for convertible argument--parameter types.
void fun(const int &m);
void fun2() {
  int m = 3;
  fun(m);
}

// Test cases for parameters of const reference and value.
void value_const_reference(int llllll, const int &kkkkkk);

void const_ref_value_swapped() {
  const int &kkkkkk = 42;
  const int &llllll = 42;
  value_const_reference(kkkkkk, llllll);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'kkkkkk' (passed to 'llllll') looks like it might be swapped with the 2nd, 'llllll' (passed to 'kkkkkk') [readability-suspicious-call-argument]
  // CHECK-MESSAGES: :[[@LINE-7]]:6: note: in the call to 'value_const_reference', declared here
}

// Const, non const references.
void const_nonconst_parameters(const int &mmmmmm, int &nnnnnn);

void const_nonconst_swap1() {
  const int &nnnnnn = 42;
  int mmmmmm;
  // Do not check, because non-const reference parameter cannot bind to const reference argument.
  const_nonconst_parameters(nnnnnn, mmmmmm);
}

void const_nonconst_swap3() {
  const int nnnnnn = 42;
  int m = 42;
  int &mmmmmm = m;
  // Do not check, const int does not bind to non const reference.
  const_nonconst_parameters(nnnnnn, mmmmmm);
}

void const_nonconst_swap2() {
  int nnnnnn;
  int mmmmmm;
  // Check for swapped arguments. (Both arguments are non-const.)
  const_nonconst_parameters(nnnnnn, mmmmmm);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'nnnnnn' (passed to 'mmmmmm') looks like it might be swapped with the 2nd, 'mmmmmm' (passed to 'nnnnnn')
}

void const_nonconst_pointers(const int *mmmmmm, int *nnnnnn);
void const_nonconst_pointers2(const int *mmmmmm, const int *nnnnnn);

void const_nonconst_pointers_swapped() {
  int *mmmmmm;
  const int *nnnnnn;
  const_nonconst_pointers(nnnnnn, mmmmmm);
}

void const_nonconst_pointers_swapped2() {
  const int *mmmmmm;
  int *nnnnnn;
  const_nonconst_pointers2(nnnnnn, mmmmmm);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'nnnnnn' (passed to 'mmmmmm') looks like it might be swapped with the 2nd, 'mmmmmm' (passed to 'nnnnnn')
}

// Test cases for pointers and arrays.
void pointer_array_parameters(
    int *pppppp, int qqqqqq[4]);

void pointer_array_swap() {
  int qqqqqq[5];
  int *pppppp;
  // Check for swapped arguments. An array implicitly converts to a pointer.
  pointer_array_parameters(qqqqqq, pppppp);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'qqqqqq' (passed to 'pppppp') looks like it might be swapped with the 2nd, 'pppppp' (passed to 'qqqqqq')
}

// Test cases for multilevel pointers.
void multilevel_pointer_parameters(int *const **pppppp,
                                   const int *const *volatile const *qqqqqq);
void multilevel_pointer_parameters2(
    char *****nnnnnn, char *volatile *const *const *const *const &mmmmmm);

typedef float T;
typedef T *S;
typedef S *const volatile R;
typedef R *Q;
typedef Q *P;
typedef P *O;
void multilevel_pointer_parameters3(float **const volatile ***rrrrrr, O &ssssss);

void multilevel_pointer_swap() {
  int *const **qqqqqq;
  int *const **pppppp;
  multilevel_pointer_parameters(qqqqqq, pppppp);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'qqqqqq' (passed to 'pppppp') looks like it might be swapped with the 2nd, 'pppppp' (passed to 'qqqqqq')

  char *****mmmmmm;
  char *****nnnnnn;
  multilevel_pointer_parameters2(mmmmmm, nnnnnn);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'mmmmmm' (passed to 'nnnnnn') looks like it might be swapped with the 2nd, 'nnnnnn' (passed to 'mmmmmm')

  float **const volatile ***rrrrrr;
  float **const volatile ***ssssss;
  multilevel_pointer_parameters3(ssssss, rrrrrr);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'ssssss' (passed to 'rrrrrr') looks like it might be swapped with the 2nd, 'rrrrrr' (passed to 'ssssss')
}

void multilevel_pointer_parameters4(char ****pppppp,
                                    char *const volatile **const *qqqqqq);
void multilevel_pointer_parameters5(
    bool *****nnnnnn, bool *volatile *const *const *const *&mmmmmm);
void multilevel_pointer_parameters6(double **llllll, char **&kkkkkk);
void multilevel_pointer_parameters7(const volatile int ***iiiiii,
                                    const int *const *const *jjjjjj);

void multilevel_pointer_swap3() {
  char ****qqqqqq;
  char *const volatile **const *pppppp;
  // Do not check.
  multilevel_pointer_parameters4(qqqqqq, pppppp);

  bool *****mmmmmm;
  bool *volatile *const *const *const *nnnnnn;
  // Do not check.
  multilevel_pointer_parameters5(mmmmmm, nnnnnn);

  double **kkkkkk;
  char **llllll;
  multilevel_pointer_parameters6(kkkkkk, llllll);

  const volatile int ***jjjjjj;
  const int *const *const *iiiiii;
  multilevel_pointer_parameters7(jjjjjj, iiiiii);
}

// Test cases for multidimesional arrays.
void multilevel_array_parameters(int pppppp[2][2][2], const int qqqqqq[][2][2]);

void multilevel_array_parameters2(int (*mmmmmm)[2][2], int nnnnnn[9][2][23]);

void multilevel_array_parameters3(int (*eeeeee)[2][2], int (&ffffff)[1][2][2]);

void multilevel_array_parameters4(int (*llllll)[2][2], int kkkkkk[2][2]);

void multilevel_array_parameters5(int iiiiii[2][2], char jjjjjj[2][2]);

void multilevel_array_parameters6(int (*bbbbbb)[2][2], int cccccc[1][2][2]);

void multilevel_array_swap() {
  int qqqqqq[1][2][2];
  int pppppp[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}}; // int [2][2][2]
  multilevel_array_parameters(qqqqqq, pppppp);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'qqqqqq' (passed to 'pppppp') looks like it might be swapped with the 2nd, 'pppppp' (passed to 'qqqqqq')

  int(*nnnnnn)[2][2];
  int mmmmmm[9][2][23];
  // Do not check, array sizes has to match in every dimension, except the first.
  multilevel_array_parameters2(nnnnnn, mmmmmm);

  int ffffff[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}}; // int [2][2][2]
  int eeeeee[1][2][2] = {{{1, 2}, {1, 2}}};                  // int [1][2][2]
  // Do not check, for array references, size has to match in every dimension.
  multilevel_array_parameters3(ffffff, eeeeee);

  int kkkkkk[2][2][2];
  int(*llllll)[2];
  // Do not check, argument dimensions differ.
  multilevel_array_parameters4(kkkkkk, llllll);

  int jjjjjj[2][2];
  char iiiiii[2][2];
  // Do not check, array element types differ.
  multilevel_array_parameters5(jjjjjj, iiiiii);

  int t[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}}; // int [2][2][2]
  int(*cccccc)[2][2] = t;                               // int (*)[2][2]
  int bbbbbb[][2][2] = {{{1, 2}, {1, 2}}};              // int [1][2][2]
  multilevel_array_parameters6(cccccc, bbbbbb);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'bbbbbb') looks like it might be swapped with the 2nd, 'bbbbbb' (passed to 'cccccc')
}

void multilevel_array_swap2() {
  int qqqqqq[2][2][2];
  const int pppppp[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}};
  // Do not check, pppppp is const and cannot bind to an array with nonconst elements.
  multilevel_array_parameters(qqqqqq, pppppp);
}

// Complex test case.
void multilevel_pointer_array_parameters(const int(*const (*volatile const (*const (*const (*const &aaaaaa)[1])[32])[4])[3][2][2]), const int(*const (*volatile const (*const (*const (*&bbbbbb)[1])[32])[4])[3][2][2]));

void multilevel_pointer_array_swap() {
  const int(
          *const(*volatile const(*const(*const(*aaaaaa)[1])[32])[4])[3][2][2]);
  const int(
          *const(*volatile const(*const(*const(*bbbbbb)[1])[32])[4])[3][2][2]);
  multilevel_pointer_array_parameters(bbbbbb, aaaaaa);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'bbbbbb' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb')
}

enum class numbers_scoped { one,
                            two };

// Test cases for arithmetic types.
void arithmetic_type_parameters(float vvvvvv, int wwwwww);
void arithmetic_type_parameters2(numbers_scoped vvvvvv, int wwwwww);

void arithmetic_types_swap1() {
  bool wwwwww;
  float vvvvvv;
  arithmetic_type_parameters(wwwwww, vvvvvv);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww')
}

void arithmetic_types_swap3() {
  char wwwwww;
  unsigned long long int vvvvvv;
  arithmetic_type_parameters(wwwwww, vvvvvv);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww')
}

void arithmetic_types_swap4() {
  enum numbers { one,
                 two };
  numbers wwwwww = numbers::one;
  int vvvvvv;
  arithmetic_type_parameters(wwwwww, vvvvvv);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww')
}

void arithmetic_types_swap5() {
  wchar_t vvvvvv;
  float wwwwww;
  arithmetic_type_parameters(wwwwww, vvvvvv);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww')
}

void arithmetic_types_swap6() {
  wchar_t vvvvvv;
  numbers_scoped wwwwww = numbers_scoped::one;
  // Do not check, numers is a scoped enum type.
  arithmetic_type_parameters2(wwwwww, vvvvvv);
}

// Base, derived
class TestClass {
public:
  void thisFunction(int integerParam, int thisIsPARAM) {}
};

class DerivedTestClass : public TestClass {};

void base_derived_pointer_parameters(TestClass *aaaaaa,
                                     DerivedTestClass *bbbbbb);

void base_derived_swap1() {
  TestClass *bbbbbb;
  DerivedTestClass *aaaaaa;
  // Do not check, because TestClass does not convert implicitly to DerivedTestClass.
  base_derived_pointer_parameters(bbbbbb, aaaaaa);
}

void base_derived_swap2() {
  DerivedTestClass *bbbbbb, *aaaaaa;
  // Check for swapped arguments, DerivedTestClass converts to TestClass implicitly.
  base_derived_pointer_parameters(bbbbbb, aaaaaa);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'bbbbbb' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb')
}

class PrivateDerivedClass : private TestClass {};

void private_derived_pointer_parameters(TestClass *aaaaaa, PrivateDerivedClass *bbbbbb);

void private_base_swap1() {
  TestClass *bbbbbb;
  PrivateDerivedClass *aaaaaa;
  private_derived_pointer_parameters(bbbbbb, aaaaaa);
}

// Multilevel inheritance
class DerivedOfDerivedTestClass : public DerivedTestClass {};

void multi_level_inheritance_swap() {
  DerivedOfDerivedTestClass *aaaaaa, *bbbbbb;
  // Check for swapped arguments. Derived classes implicitly convert to their base.
  base_derived_pointer_parameters(
      bbbbbb, aaaaaa);
  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: 1st argument 'bbbbbb' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb')
}

// Tests for function pointer swaps
void funct_ptr_params(double (*ffffff)(int, int), double (*gggggg)(int, int));
void funct_ptr_params(double (*ffffff)(int, int), int (*gggggg)(int, int));

double ffffff(int a, int b) { return 0; }
double gggggg(int a, int b) { return 0; }

void funtionc_ptr_params_swap() {
  funct_ptr_params(gggggg, ffffff);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'gggggg' (passed to 'ffffff') looks like it might be swapped with the 2nd, 'ffffff' (passed to 'gggggg')
}

int fffff(int a, int b) { return 0; }

void function_ptr_swap2() {
  // Do not check, because the function `ffffff` cannot convert to a function
  // with prototype: double(int,int).
  funct_ptr_params(gggggg, fffff);
}

// Paraphrased example from Z3 (src/qe/qe_arrays.cpp) which originally produced
// a false positive. Operator() calls should ignore the called object
// "argument".
struct type1;
struct type2;
struct type3;

struct callable1 {
  void operator()(type1 &mdl, type2 &arr_vars, type3 &fml, type2 &aux_vars) const {}
};

struct callable2 {
  void operator()(type1 &mdl, type2 &arr_vars, type3 &fml, type2 &aux_vars,
                  bool reduce_all_selects) const {
    (void)reduce_all_selects;
    callable1 pe;
    pe(mdl, arr_vars, fml, aux_vars);
    // NO-WARN: Argument and parameter names match perfectly, "pe" should be
    // ignored!
  }
};

struct binop_t {};

binop_t operator+(const binop_t &lhs, const binop_t &rhs) { return lhs; }
bool operator<(const binop_t &lhs, const binop_t &rhs) { return true; }
bool operator>(const binop_t &aaaaaa, const binop_t &bbbbbb) { return false; }

void binop_test() {
  // NO-WARN: Binary operators are ignored.
  binop_t lhs, rhs;
  if (lhs + rhs < rhs)
    return;

  if (operator<(rhs, lhs))
    return;

  binop_t aaaaaa, cccccc;
  if (operator>(cccccc, aaaaaa))
    return;
}

int recursion(int aaaa, int bbbb) {
  if (aaaa)
    return 0;

  int cccc = 0;
  return recursion(bbbb, cccc);
  // NO-WARN: Recursive calls usually shuffle with arguments and we ignore those.
}

void pass_by_copy(binop_t xxxx, binop_t yyyy) {}

// Paraphrased example from LLVM's code (lib/Analysis/InstructionSimplify.cpp)
// that generated a false positive.
struct value;
enum opcode { Foo,
              Bar };
static value *SimplifyRightShift(
    opcode Opcode, value *Op0, value *Op1, bool isExact,
    const type1 &Q, unsigned MaxRecurse) {}
static value *SimplifyLShrInst(value *Op0, value *Op1, bool isExact,
                               const type1 &Q, unsigned MaxRecurse) {
  if (value *V = SimplifyRightShift(Foo, Op0, Op1, isExact, Q, MaxRecurse))
    return V;
  // NO-WARN: Argument names perfectly match parameter names, sans the enum.

  return nullptr;
}

void has_unnamed(int aaaaaa, int) {}

int main() {
  // Equality test.
  int aaaaaa, cccccc = 0;
  foo_1(cccccc, aaaaaa);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb')

  binop_t xxxx, yyyy;
  pass_by_copy(yyyy, xxxx);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'yyyy' (passed to 'xxxx') looks like it might be swapped with the 2nd, 'xxxx' (passed to 'yyyy')

  // Abbreviation test.
  int src = 0;
  foo_2(aaaaaa, src);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'aaaaaa' (passed to 'source') looks like it might be swapped with the 2nd, 'src' (passed to 'aaaaaa')

  // Levenshtein test.
  int aaaabb = 0;
  foo_1(cccccc, aaaabb);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaabb' (passed to 'bbbbbb')

  // Prefix test.
  int aaaa = 0;
  foo_1(cccccc, aaaa);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaa' (passed to 'bbbbbb')

  // Suffix test.
  int urce = 0;
  foo_2(cccccc, urce);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'source') looks like it might be swapped with the 2nd, 'urce' (passed to 'aaaaaa')

  // Substring test.
  int ourc = 0;
  foo_2(cccccc, ourc);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'source') looks like it might be swapped with the 2nd, 'ourc' (passed to 'aaaaaa')

  // Jaro-Winkler test.
  int iPonter = 0;
  foo_4(cccccc, iPonter);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'pointer') looks like it might be swapped with the 2nd, 'iPonter' (passed to 'aaaaaa')

  // Dice test.
  int aaabaa = 0;
  foo_1(cccccc, aaabaa);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaabaa' (passed to 'bbbbbb')

  // Variadic function test.
  int bbbbbb = 0;
  foo_5(src, bbbbbb, cccccc, aaaaaa); // Should pass.
  foo_5(cccccc, bbbbbb, aaaaaa, src);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 3rd, 'aaaaaa' (passed to 'cccccc')

  // Test function with default argument.
  foo_7(src, bbbbbb, cccccc, aaaaaa);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'src' (passed to 'aaaaaa') looks like it might be swapped with the 4th, 'aaaaaa' (passed to 'ffffff')

  foo_7(cccccc, bbbbbb, aaaaaa, src);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 3rd, 'aaaaaa' (passed to 'cccccc')

  int ffffff = 0;
  foo_7(ffffff, bbbbbb, cccccc); // NO-WARN: Even though 'ffffff' is passed to 'aaaaaa' and there is a 4th parameter 'ffffff', there isn't a **swap** here.

  int frobble1 = 1, frobble2 = 2;
  foo_8(frobble2, frobble1);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'frobble2' (passed to 'frobble1') looks like it might be swapped with the 2nd, 'frobble1' (passed to 'frobble2')

  int bar1 = 1, bar2 = 2;
  foo_8(bar2, bar1); // NO-WARN.

  // Type match
  bool dddddd = false;
  int eeeeee = 0;
  auto szam = 0;
  foo_6(eeeeee, dddddd);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'eeeeee' (passed to 'dddddd') looks like it might be swapped with the 2nd, 'dddddd' (passed to 'eeeeee')
  foo_1(szam, aaaaaa);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'szam' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb')

  // Test lambda.
  auto testMethod = [&](int method, int randomParam) { return 0; };
  int method = 0;
  testMethod(method, 0); // Should pass.

  // Member function test.
  TestClass test;
  int integ, thisIsAnArg = 0;
  test.thisFunction(integ, thisIsAnArg); // Should pass.

  has_unnamed(1, bbbbbb);

  return 0;
}

namespace Issue_54074 {

class T {};
using OperatorTy = int(const T &, const T &);
int operator-(const T &, const T &);

template <typename U>
struct Wrap {
  Wrap(U);
};

template <typename V>
void wrapTaker(V, Wrap<OperatorTy>);

template <typename V>
void wrapTaker(V aaaaa, V bbbbb, Wrap<OperatorTy>);

void test() {
  wrapTaker(0, operator-);
  // NO-WARN. No crash!

  int aaaaa = 4, bbbbb = 8;
  wrapTaker(bbbbb, aaaaa, operator-);
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'bbbbb' (passed to 'aaaaa') looks like it might be swapped with the 2nd, 'aaaaa' (passed to 'bbbbb')
  // CHECK-MESSAGES: :[[@LINE-9]]:6: note: in the call to 'wrapTaker<int>', declared here
}

} // namespace Issue_54074