File: easily-swappable-parameters-len2.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 (429 lines) | stat: -rw-r--r-- 24,807 bytes parent folder | download | duplicates (11)
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
// RUN: %check_clang_tidy %s bugprone-easily-swappable-parameters %t \
// RUN:   -config='{CheckOptions: [ \
// RUN:     {key: bugprone-easily-swappable-parameters.MinimumLength, value: 2}, \
// RUN:     {key: bugprone-easily-swappable-parameters.IgnoredParameterNames, value: ""}, \
// RUN:     {key: bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes, value: ""}, \
// RUN:     {key: bugprone-easily-swappable-parameters.QualifiersMix, value: 0}, \
// RUN:     {key: bugprone-easily-swappable-parameters.ModelImplicitConversions, value: 0}, \
// RUN:     {key: bugprone-easily-swappable-parameters.SuppressParametersUsedTogether, value: 0}, \
// RUN:     {key: bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold, value: 0} \
// RUN:  ]}' --

namespace std {
using size_t = decltype(sizeof(int));
} // namespace std

#define assert(X) ((void)(X))

void declaration(int Param, int Other); // NO-WARN: No chance to change this function.

struct S {};

S *allocate() { return nullptr; }                           // NO-WARN: 0 parameters.
void allocate(S **Out) {}                                   // NO-WARN: 1 parameter.
bool operator<(const S &LHS, const S &RHS) { return true; } // NO-WARN: Binary operator.

struct MyComparator {
  bool operator()(const S &LHS, const S &RHS) { return true; } // NO-WARN: Binary operator.
};

struct MyFactory {
  S operator()() { return {}; }             // NO-WARN: 0 parameters, overloaded operator.
  S operator()(int I) { return {}; }        // NO-WARN: 1 parameter, overloaded operator.
  S operator()(int I, int J) { return {}; } // NO-WARN: Binary operator.

  S operator()(int I, int J, int K) { return {}; }
  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 3 adjacent parameters of 'operator()' of similar type ('int') are easily swapped by mistake [bugprone-easily-swappable-parameters]
  // CHECK-MESSAGES: :[[@LINE-2]]:20: note: the first parameter in the range is 'I'
  // CHECK-MESSAGES: :[[@LINE-3]]:34: note: the last parameter in the range is 'K'
};

// Variadic functions are not checked because the types are not seen from the
// *definition*. It would require analysing the call sites to do something
// for these.
int printf(const char *Format, ...) { return 0; } // NO-WARN: Variadic function not checked.
int sum(...) { return 0; }                        // NO-WARN: Variadic function not checked.

void *operator new(std::size_t Count, S &Manager, S &Janitor) noexcept { return nullptr; }
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: 2 adjacent parameters of 'operator new' of similar type ('S &')
// CHECK-MESSAGES: :[[@LINE-2]]:42: note: the first parameter in the range is 'Manager'
// CHECK-MESSAGES: :[[@LINE-3]]:54: note: the last parameter in the range is 'Janitor'

void redeclChain(int, int, int);
void redeclChain(int I, int, int);
void redeclChain(int, int J, int);
void redeclChain(int I, int J, int K) {}
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 3 adjacent parameters of 'redeclChain' of similar type ('int')
// CHECK-MESSAGES: :[[@LINE-2]]:22: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:36: note: the last parameter in the range is 'K'

void copyMany(S *Src, S *Dst, unsigned Num) {}
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: 2 adjacent parameters of 'copyMany' of similar type ('S *')
// CHECK-MESSAGES: :[[@LINE-2]]:18: note: the first parameter in the range is 'Src'
// CHECK-MESSAGES: :[[@LINE-3]]:26: note: the last parameter in the range is 'Dst'

template <typename T, typename U>
bool binaryPredicate(T L, U R) { return false; } // NO-WARN: Distinct types in template.

template <> // Explicit specialisation.
bool binaryPredicate(S *L, S *R) { return true; }
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 2 adjacent parameters of 'binaryPredicate<S *, S *>' of similar type ('S *')
// CHECK-MESSAGES: :[[@LINE-2]]:25: note: the first parameter in the range is 'L'
// CHECK-MESSAGES: :[[@LINE-3]]:31: note: the last parameter in the range is 'R'

template <typename T>
T algebraicOperation(T L, T R) { return L; }
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 2 adjacent parameters of 'algebraicOperation' of similar type ('T')
// CHECK-MESSAGES: :[[@LINE-2]]:24: note: the first parameter in the range is 'L'
// CHECK-MESSAGES: :[[@LINE-3]]:29: note: the last parameter in the range is 'R'

void applyBinaryToS(S SInstance) { // NO-WARN: 1 parameter.
  assert(binaryPredicate(SInstance, SInstance) !=
         binaryPredicate(&SInstance, &SInstance));
  // NO-WARN: binaryPredicate(S, S) is instantiated, but it's not written
  // by the user.
}

void unnamedParameter(int I, int, int K, int) {}
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 4 adjacent parameters of 'unnamedParameter' of similar type ('int')
// CHECK-MESSAGES: :[[@LINE-2]]:27: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:45: note: the last parameter in the range is '<unnamed>'

void fullyUnnamed(int, int) {}
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 2 adjacent parameters of 'fullyUnnamed' of similar type ('int')
// CHECK-MESSAGES: :[[@LINE-2]]:22: note: the first parameter in the range is '<unnamed>'
// CHECK-MESSAGES: :[[@LINE-3]]:27: note: the last parameter in the range is '<unnamed>'

void multipleDistinctTypes(int I, int J, long L, long M) {}
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: 2 adjacent parameters of 'multipleDistinctTypes' of similar type ('int')
// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:39: note: the last parameter in the range is 'J'
// CHECK-MESSAGES: :[[@LINE-4]]:42: warning: 2 adjacent parameters of 'multipleDistinctTypes' of similar type ('long')
// CHECK-MESSAGES: :[[@LINE-5]]:47: note: the first parameter in the range is 'L'
// CHECK-MESSAGES: :[[@LINE-6]]:55: note: the last parameter in the range is 'M'

void variableAndPtr(int I, int *IP) {} // NO-WARN: Not the same type.

void differentPtrs(int *IP, long *LP) {} // NO-WARN: Not the same type.

typedef int MyInt1;
using MyInt2 = int;
typedef MyInt2 MyInt2b;

using CInt = const int;
using CMyInt1 = const MyInt1;
using CMyInt2 = const MyInt2;

typedef long MyLong1;
using MyLong2 = long;

void typedefAndTypedef1(MyInt1 I1, MyInt1 I2) {}
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'typedefAndTypedef1' of similar type ('MyInt1')
// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'I1'
// CHECK-MESSAGES: :[[@LINE-3]]:43: note: the last parameter in the range is 'I2'

void typedefAndTypedef2(MyInt2 I1, MyInt2 I2) {}
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'typedefAndTypedef2' of similar type ('MyInt2')
// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'I1'
// CHECK-MESSAGES: :[[@LINE-3]]:43: note: the last parameter in the range is 'I2'

void typedefMultiple(MyInt1 I1, MyInt2 I2x, MyInt2 I2y) {}
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 3 adjacent parameters of 'typedefMultiple' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I1'
// CHECK-MESSAGES: :[[@LINE-3]]:52: note: the last parameter in the range is 'I2y'
// CHECK-MESSAGES: :[[@LINE-4]]:22: note: after resolving type aliases, the common type of 'MyInt1' and 'MyInt2' is 'int'

void throughTypedef1(int I, MyInt1 J) {}
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 2 adjacent parameters of 'throughTypedef1' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:26: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:36: note: the last parameter in the range is 'J'
// CHECK-MESSAGES: :[[@LINE-4]]:22: note: after resolving type aliases, 'int' and 'MyInt1' are the same

void betweenTypedef2(MyInt1 I, MyInt2 J) {}
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 2 adjacent parameters of 'betweenTypedef2' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:39: note: the last parameter in the range is 'J'
// CHECK-MESSAGES: :[[@LINE-4]]:22: note: after resolving type aliases, the common type of 'MyInt1' and 'MyInt2' is 'int'

void typedefChain(int I, MyInt1 MI1, MyInt2 MI2, MyInt2b MI2b) {}
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 4 adjacent parameters of 'typedefChain' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:23: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:58: note: the last parameter in the range is 'MI2b'
// CHECK-MESSAGES: :[[@LINE-4]]:19: note: after resolving type aliases, 'int' and 'MyInt1' are the same
// CHECK-MESSAGES: :[[@LINE-5]]:19: note: after resolving type aliases, 'int' and 'MyInt2' are the same
// CHECK-MESSAGES: :[[@LINE-6]]:19: note: after resolving type aliases, 'int' and 'MyInt2b' are the same

void throughTypedefToOtherType(MyInt1 I, MyLong1 J) {} // NO-WARN: int and long.

void qualified1(int I, const int CI) {} // NO-WARN: Different qualifiers.

void qualified2(int I, volatile int VI) {} // NO-WARN: Different qualifiers.

void qualified3(int *IP, const int *CIP) {} // NO-WARN: Different qualifiers.

void qualified4(const int CI, const long CL) {} // NO-WARN: Not the same type.

void qualifiedPtr1(int *IP, int *const IPC) {} // NO-WARN: Different qualifiers.

void qualifiedTypeAndQualifiedPtr1(const int *CIP, int *const volatile IPCV) {} // NO-WARN: Not the same type.

void qualifiedThroughTypedef1(int I, CInt CI) {} // NO-WARN: Different qualifiers.

void qualifiedThroughTypedef2(CInt CI1, const int CI2) {}
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 2 adjacent parameters of 'qualifiedThroughTypedef2' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:36: note: the first parameter in the range is 'CI1'
// CHECK-MESSAGES: :[[@LINE-3]]:51: note: the last parameter in the range is 'CI2'
// CHECK-MESSAGES: :[[@LINE-4]]:31: note: after resolving type aliases, 'CInt' and 'const int' are the same

void qualifiedThroughTypedef3(CInt CI1, const MyInt1 CI2, const int CI3) {}
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 3 adjacent parameters of 'qualifiedThroughTypedef3' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:36: note: the first parameter in the range is 'CI1'
// CHECK-MESSAGES: :[[@LINE-3]]:69: note: the last parameter in the range is 'CI3'
// CHECK-MESSAGES: :[[@LINE-4]]:31: note: after resolving type aliases, the common type of 'CInt' and 'const MyInt1' is 'const int'
// CHECK-MESSAGES: :[[@LINE-5]]:31: note: after resolving type aliases, 'CInt' and 'const int' are the same
// CHECK-MESSAGES: :[[@LINE-6]]:41: note: after resolving type aliases, 'const MyInt1' and 'const int' are the same

void qualifiedThroughTypedef4(CInt CI1, const MyInt1 CI2, const MyInt2 CI3) {}
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 3 adjacent parameters of 'qualifiedThroughTypedef4' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:36: note: the first parameter in the range is 'CI1'
// CHECK-MESSAGES: :[[@LINE-3]]:72: note: the last parameter in the range is 'CI3'
// CHECK-MESSAGES: :[[@LINE-4]]:31: note: after resolving type aliases, the common type of 'CInt' and 'const MyInt1' is 'const int'
// CHECK-MESSAGES: :[[@LINE-5]]:31: note: after resolving type aliases, the common type of 'CInt' and 'const MyInt2' is 'const int'
// CHECK-MESSAGES: :[[@LINE-6]]:41: note: after resolving type aliases, the common type of 'const MyInt1' and 'const MyInt2' is 'const int'

void qualifiedThroughTypedef5(CMyInt1 CMI1, CMyInt2 CMI2) {}
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 2 adjacent parameters of 'qualifiedThroughTypedef5' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:39: note: the first parameter in the range is 'CMI1'
// CHECK-MESSAGES: :[[@LINE-3]]:53: note: the last parameter in the range is 'CMI2'
// CHECK-MESSAGES: :[[@LINE-4]]:31: note: after resolving type aliases, the common type of 'CMyInt1' and 'CMyInt2' is 'const int'

void qualifiedThroughTypedef6(CMyInt1 CMI1, int I) {} // NO-WARN: Different qualifiers.

template <typename T>
void copy(const T *Dest, T *Source) {} // NO-WARN: Different qualifiers.

void reference1(int I, int &IR) {} // NO-WARN: Distinct semantics when called.

void reference2(int I, const int &CIR) {}
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: 2 adjacent parameters of 'reference2' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:21: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:35: note: the last parameter in the range is 'CIR'
// CHECK-MESSAGES: :[[@LINE-4]]:24: note: 'int' and 'const int &' parameters accept and bind the same kind of values

void reference3(int I, int &&IRR) {} // NO-WARN: Distinct semantics when called.

void reference4(int I, const int &&CIRR) {} // NO-WARN: Distinct semantics when called.

void reference5(const int CI, const int &CIR) {}
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: 2 adjacent parameters of 'reference5' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:27: note: the first parameter in the range is 'CI'
// CHECK-MESSAGES: :[[@LINE-3]]:42: note: the last parameter in the range is 'CIR'
// CHECK-MESSAGES: :[[@LINE-4]]:31: note: 'const int' and 'const int &' parameters accept and bind the same kind of values

void reference6(int I, const int &CIR, int J, const int &CJR) {}
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: 4 adjacent parameters of 'reference6' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:21: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:58: note: the last parameter in the range is 'CJR'
// CHECK-MESSAGES: :[[@LINE-4]]:24: note: 'int' and 'const int &' parameters accept and bind the same kind of values

using ICRTy = const int &;
using MyIntCRTy = const MyInt1 &;

void referenceToTypedef1(CInt &CIR, int I) {}
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 2 adjacent parameters of 'referenceToTypedef1' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'CIR'
// CHECK-MESSAGES: :[[@LINE-3]]:41: note: the last parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-4]]:37: note: 'CInt &' and 'int' parameters accept and bind the same kind of values

void referenceThroughTypedef(int I, ICRTy Builtin, MyIntCRTy MyInt) {}
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 3 adjacent parameters of 'referenceThroughTypedef' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:34: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:62: note: the last parameter in the range is 'MyInt'
// CHECK-MESSAGES: :[[@LINE-4]]:37: note: 'int' and 'ICRTy' parameters accept and bind the same kind of values
// CHECK-MESSAGES: :[[@LINE-5]]:30: note: after resolving type aliases, 'int' and 'MyIntCRTy' are the same
// CHECK-MESSAGES: :[[@LINE-6]]:52: note: 'int' and 'MyIntCRTy' parameters accept and bind the same kind of values
// CHECK-MESSAGES: :[[@LINE-7]]:37: note: after resolving type aliases, the common type of 'ICRTy' and 'MyIntCRTy' is 'const int &'

typedef int Point2D[2];
typedef int Point3D[3];

void arrays1(Point2D P2D, Point3D P3D) {} // In reality this is (int*, int*).
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 2 adjacent parameters of 'arrays1' of similar type ('int *') are
// CHECK-MESSAGES: :[[@LINE-2]]:22: note: the first parameter in the range is 'P2D'
// CHECK-MESSAGES: :[[@LINE-3]]:35: note: the last parameter in the range is 'P3D'

void crefToArrayTypedef1(int I, const Point2D &P) {}
// NO-WARN.

void crefToArrayTypedef2(int *IA, const Point2D &P) {}
// NO-WARN.

void crefToArrayTypedef3(int P1[2], const Point2D &P) {}
// NO-WARN.

void crefToArrayTypedefBoth1(const Point2D &VecDescartes, const Point3D &VecThreeD) {}
// NO-WARN: Distinct types and no conversion because of &.

short const typedef int unsigned Eldritch;
typedef const unsigned short Holy;

void collapse(Eldritch Cursed, Holy Blessed) {}
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: 2 adjacent parameters of 'collapse' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:24: note: the first parameter in the range is 'Cursed'
// CHECK-MESSAGES: :[[@LINE-3]]:37: note: the last parameter in the range is 'Blessed'
// CHECK-MESSAGES: :[[@LINE-4]]:15: note: after resolving type aliases, the common type of 'Eldritch' and 'Holy' is 'const unsigned short'

void collapseAndTypedef(Eldritch Cursed, const Holy &Blessed) {}
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'collapseAndTypedef' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:34: note: the first parameter in the range is 'Cursed'
// CHECK-MESSAGES: :[[@LINE-3]]:54: note: the last parameter in the range is 'Blessed'
// CHECK-MESSAGES: :[[@LINE-4]]:25: note: after resolving type aliases, the common type of 'Eldritch' and 'const Holy &' is 'const unsigned short'
// CHECK-MESSAGES: :[[@LINE-5]]:42: note: 'Eldritch' and 'const Holy &' parameters accept and bind the same kind of values

template <typename T1, typename T2>
struct Pair {};

void templateParam1(Pair<int, int> P1, Pair<int, int> P2) {}
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 2 adjacent parameters of 'templateParam1' of similar type ('Pair<int, int>')
// CHECK-MESSAGES: :[[@LINE-2]]:36: note: the first parameter in the range is 'P1'
// CHECK-MESSAGES: :[[@LINE-3]]:55: note: the last parameter in the range is 'P2'

void templateParam2(Pair<int, long> P1, Pair<int, long> P2) {}
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 2 adjacent parameters of 'templateParam2' of similar type ('Pair<int, long>')
// CHECK-MESSAGES: :[[@LINE-2]]:37: note: the first parameter in the range is 'P1'
// CHECK-MESSAGES: :[[@LINE-3]]:57: note: the last parameter in the range is 'P2'

void templateParam3(Pair<int, int> P1, Pair<int, long> P2) {} // NO-WARN: Not the same type.

template <typename X, typename Y>
struct Coord {};

void templateAndOtherTemplate1(Pair<int, int> P, Coord<int, int> C) {} // NO-WARN: Not the same type.

template <typename Ts>
void templateVariadic1(Ts TVars...) {} // NO-WARN: Requires instantiation to check.

template <typename T, typename... Us>
void templateVariadic2(T TVar, Us... UVars) {} // NO-WARN: Distinct types in primary template.

template <>
void templateVariadic2(int TVar, int UVars1, int UVars2) {}
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 3 adjacent parameters of 'templateVariadic2<int, int, int>' of similar type ('int')
// CHECK-MESSAGES: :[[@LINE-2]]:28: note: the first parameter in the range is 'TVar'
// CHECK-MESSAGES: :[[@LINE-3]]:50: note: the last parameter in the range is 'UVars2'

template <typename T>
using TwoOf = Pair<T, T>;

void templateAndAliasTemplate(Pair<int, int> P, TwoOf<int> I) {}
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: 2 adjacent parameters of 'templateAndAliasTemplate' of similar type ('Pair<int, int>')
// CHECK-MESSAGES: :[[@LINE-2]]:46: note: the first parameter in the range is 'P'
// CHECK-MESSAGES: :[[@LINE-3]]:60: note: the last parameter in the range is 'I'

template <int N, int M>
void templatedArrayRef(int (&Array1)[N], int (&Array2)[M]) {}
// NO-WARN: Distinct template types in the primary template.

void templatedArrayRefTest() {
  int Foo[12], Bar[12];
  templatedArrayRef(Foo, Bar);

  int Baz[12], Quux[42];
  templatedArrayRef(Baz, Quux);

  // NO-WARN: Implicit instantiations are not checked.
}

template <>
void templatedArrayRef(int (&Array1)[8], int (&Array2)[8]) { templatedArrayRef(Array2, Array1); }
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 2 adjacent parameters of 'templatedArrayRef<8, 8>' of similar type ('int (&)[8]') are
// CHECK-MESSAGES: :[[@LINE-2]]:30: note: the first parameter in the range is 'Array1'
// CHECK-MESSAGES: :[[@LINE-3]]:48: note: the last parameter in the range is 'Array2'

template <>
void templatedArrayRef(int (&Array1)[16], int (&Array2)[24]) {}
// NO-WARN: Not the same type.

template <typename T>
struct Vector {
  typedef T element_type;
  typedef T &reference_type;
  typedef const T const_element_type;
  typedef const T &const_reference_type;
};

void memberTypedef(int I, Vector<int>::element_type E) {}
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 2 adjacent parameters of 'memberTypedef' of similar type are
// CHECK-MESSAGES: :[[@LINE-2]]:24: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:53: note: the last parameter in the range is 'E'
// CHECK-MESSAGES: :[[@LINE-4]]:20: note: after resolving type aliases, 'int' and 'Vector<int>::element_type' are the same

template <typename T>
void memberTypedefDependent1(T T1, typename Vector<T>::element_type T2) {} // NO-WARN: Dependent name is not instantiated and resolved against other type.

template <typename T>
void memberTypedefDependent2(typename Vector<T>::element_type E1,
                             typename Vector<T>::element_type E2) {}
// CHECK-MESSAGES: :[[@LINE-2]]:30: warning: 2 adjacent parameters of 'memberTypedefDependent2' of similar type ('typename Vector<T>::element_type')
// CHECK-MESSAGES: :[[@LINE-3]]:63: note: the first parameter in the range is 'E1'
// CHECK-MESSAGES: :[[@LINE-3]]:63: note: the last parameter in the range is 'E2'

template <typename T>
void memberTypedefDependentReference1(
    typename Vector<T>::element_type E,
    typename Vector<T>::const_element_type &R) {} // NO-WARN: Not instantiated.

template <typename T>
void memberTypedefDependentReference2(
    typename Vector<T>::element_type E,
    typename Vector<T>::const_reference_type R) {} // NO-WARN: Not instantiated.

template <typename T>
void memberTypedefDependentReference3(
    typename Vector<T>::element_type E,
    const typename Vector<T>::element_type &R) {}
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: 2 adjacent parameters of 'memberTypedefDependentReference3' of similar type are
// CHECK-MESSAGES: :[[@LINE-3]]:38: note: the first parameter in the range is 'E'
// CHECK-MESSAGES: :[[@LINE-3]]:45: note: the last parameter in the range is 'R'
// CHECK-MESSAGES: :[[@LINE-4]]:5: note: 'typename Vector<T>::element_type' and 'const typename Vector<T>::element_type &' parameters accept and bind the same kind of values

void functionPrototypeLosesNoexcept(void (*NonThrowing)() noexcept, void (*Throwing)()) {}
// NO-WARN: This call cannot be swapped, even if "getCanonicalType()" believes otherwise.

void attributedParam1(const __attribute__((address_space(256))) int *One,
                      const __attribute__((address_space(256))) int *Two) {}
// CHECK-MESSAGES: :[[@LINE-2]]:23: warning: 2 adjacent parameters of 'attributedParam1' of similar type ('const __attribute__((address_space(256))) int *') are
// CHECK-MESSAGES: :[[@LINE-3]]:70: note: the first parameter in the range is 'One'
// CHECK-MESSAGES: :[[@LINE-3]]:70: note: the last parameter in the range is 'Two'

void attributedParam1Typedef(const __attribute__((address_space(256))) int *One,
                             const __attribute__((address_space(256))) MyInt1 *Two) {}
// CHECK-MESSAGES: :[[@LINE-2]]:30: warning: 2 adjacent parameters of 'attributedParam1Typedef' of similar type are
// CHECK-MESSAGES: :[[@LINE-3]]:77: note: the first parameter in the range is 'One'
// CHECK-MESSAGES: :[[@LINE-3]]:80: note: the last parameter in the range is 'Two'
// CHECK-MESSAGES: :[[@LINE-5]]:30: note: after resolving type aliases, 'const __attribute__((address_space(256))) int *' and 'const __attribute__((address_space(256))) MyInt1 *' are the same

void attributedParam1TypedefRef(
    const __attribute__((address_space(256))) int &OneR,
    __attribute__((address_space(256))) MyInt1 &TwoR) {}
// NO-WARN: One is CVR-qualified, the other is not.

void attributedParam1TypedefCRef(
    const __attribute__((address_space(256))) int &OneR,
    const __attribute__((address_space(256))) MyInt1 &TwoR) {}
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: 2 adjacent parameters of 'attributedParam1TypedefCRef' of similar type are
// CHECK-MESSAGES: :[[@LINE-3]]:52: note: the first parameter in the range is 'OneR'
// CHECK-MESSAGES: :[[@LINE-3]]:55: note: the last parameter in the range is 'TwoR'
// CHECK-MESSAGES: :[[@LINE-5]]:5: note: after resolving type aliases, 'const __attribute__((address_space(256))) int &' and 'const __attribute__((address_space(256))) MyInt1 &' are the same

void attributedParam2(__attribute__((address_space(256))) int *One,
                      const __attribute__((address_space(256))) MyInt1 *Two) {}
// NO-WARN: One is CVR-qualified, the other is not.

void attributedParam3(const int *One,
                      const __attribute__((address_space(256))) MyInt1 *Two) {}
// NO-WARN: One is attributed, the other is not.

void attributedParam4(const __attribute__((address_space(512))) int *One,
                      const __attribute__((address_space(256))) MyInt1 *Two) {}
// NO-WARN: Different value of the attribute.