Skip to content

Commit 2183212

Browse files
committed
[clang-tidy] Fix crash on "reference-to-array" parameters in 'bugprone-easily-swappable-parameters'
An otherwise unexercised code path related to trying to model "array-to-pointer decay" resulted in a null pointer dereference crash when parameters of type "reference to array" were encountered. Fixes crash report http://bugs.llvm.org/show_bug.cgi?id=50995. Reviewed By: aaron.ballman Differential Revision: http://reviews.llvm.org/D106946
1 parent 9559bd1 commit 2183212

File tree

3 files changed

+90
-5
lines changed

3 files changed

+90
-5
lines changed

clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -962,11 +962,8 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
962962
// LValue->RValue is irrelevant for the check, because it is a thing to be
963963
// done at a call site, and will be performed if need be performed.
964964

965-
// Array->Ptr decay.
966-
if (const auto *ArrayT = dyn_cast<ArrayType>(From)) {
967-
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Array->Ptr decayed.\n");
968-
WorkType = ArrayT->getPointeeType();
969-
}
965+
// Array->Pointer decay is handled by the main method in desugaring
966+
// the parameter's DecayedType as "useless sugar".
970967

971968
// Function->Pointer conversions are also irrelevant, because a
972969
// "FunctionType" cannot be the type of a parameter variable, so this

clang-tools-extra/test/clang-tidy/checkers/bugprone-easily-swappable-parameters-implicits.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,50 @@ void arrayAndPtr2(int *IP, int IA[8]) { arrayAndPtr2(IA, IP); }
2626

2727
void arrayAndElement(int I, int IA[]) {} // NO-WARN.
2828

29+
typedef int Point2D[2];
30+
typedef int Point3D[3];
31+
32+
void arrays1(Point2D P2D, Point3D P3D) {} // In reality this is (int*, int*).
33+
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 2 adjacent parameters of 'arrays1' of similar type ('int *') are
34+
// CHECK-MESSAGES: :[[@LINE-2]]:22: note: the first parameter in the range is 'P2D'
35+
// CHECK-MESSAGES: :[[@LINE-3]]:35: note: the last parameter in the range is 'P3D'
36+
37+
void crefToArrayTypedef1(int I, const Point2D &P) {}
38+
// NO-WARN.
39+
40+
void crefToArrayTypedef2(int *IA, const Point2D &P) {}
41+
// NO-WARN.
42+
43+
void crefToArrayTypedef3(int P1[2], const Point2D &P) {}
44+
// NO-WARN.
45+
46+
void crefToArrayTypedefBoth1(const Point2D &VecDescartes, const Point3D &VecThreeD) {}
47+
// NO-WARN: Distinct types.
48+
49+
template <int N, int M>
50+
void templatedArrayRef(int (&Array1)[N], int (&Array2)[M]) {}
51+
// NO-WARN: Distinct template types in the primary template.
52+
53+
void templatedArrayRefTest() {
54+
int Foo[12], Bar[12];
55+
templatedArrayRef(Foo, Bar);
56+
57+
int Baz[12], Quux[42];
58+
templatedArrayRef(Baz, Quux);
59+
60+
// NO-WARN: Implicit instantiations are not checked.
61+
}
62+
63+
template <>
64+
void templatedArrayRef(int (&Array1)[8], int (&Array2)[8]) { templatedArrayRef(Array2, Array1); }
65+
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 2 adjacent parameters of 'templatedArrayRef<8, 8>' of similar type ('int (&)[8]') are
66+
// CHECK-MESSAGES: :[[@LINE-2]]:30: note: the first parameter in the range is 'Array1'
67+
// CHECK-MESSAGES: :[[@LINE-3]]:48: note: the last parameter in the range is 'Array2'
68+
69+
template <>
70+
void templatedArrayRef(int (&Array1)[16], int (&Array2)[24]) {}
71+
// NO-WARN: Not the same type.
72+
2973
void numericConversion1(int I, double D) { numericConversion1(D, I); }
3074
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion1' of convertible types are easily swapped by mistake [bugprone-easily-swappable-parameters]
3175
// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'

clang-tools-extra/test/clang-tidy/checkers/bugprone-easily-swappable-parameters-len2.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,26 @@ void referenceThroughTypedef(int I, ICRTy Builtin, MyIntCRTy MyInt) {}
244244
// CHECK-MESSAGES: :[[@LINE-6]]:52: note: 'int' and 'MyIntCRTy' parameters accept and bind the same kind of values
245245
// CHECK-MESSAGES: :[[@LINE-7]]:37: note: after resolving type aliases, the common type of 'ICRTy' and 'MyIntCRTy' is 'const int &'
246246

247+
typedef int Point2D[2];
248+
typedef int Point3D[3];
249+
250+
void arrays1(Point2D P2D, Point3D P3D) {} // In reality this is (int*, int*).
251+
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 2 adjacent parameters of 'arrays1' of similar type ('int *') are
252+
// CHECK-MESSAGES: :[[@LINE-2]]:22: note: the first parameter in the range is 'P2D'
253+
// CHECK-MESSAGES: :[[@LINE-3]]:35: note: the last parameter in the range is 'P3D'
254+
255+
void crefToArrayTypedef1(int I, const Point2D &P) {}
256+
// NO-WARN.
257+
258+
void crefToArrayTypedef2(int *IA, const Point2D &P) {}
259+
// NO-WARN.
260+
261+
void crefToArrayTypedef3(int P1[2], const Point2D &P) {}
262+
// NO-WARN.
263+
264+
void crefToArrayTypedefBoth1(const Point2D &VecDescartes, const Point3D &VecThreeD) {}
265+
// NO-WARN: Distinct types and no conversion because of &.
266+
247267
short const typedef int unsigned Eldritch;
248268
typedef const unsigned short Holy;
249269

@@ -300,6 +320,30 @@ void templateAndAliasTemplate(Pair<int, int> P, TwoOf<int> I) {}
300320
// CHECK-MESSAGES: :[[@LINE-2]]:46: note: the first parameter in the range is 'P'
301321
// CHECK-MESSAGES: :[[@LINE-3]]:60: note: the last parameter in the range is 'I'
302322

323+
template <int N, int M>
324+
void templatedArrayRef(int (&Array1)[N], int (&Array2)[M]) {}
325+
// NO-WARN: Distinct template types in the primary template.
326+
327+
void templatedArrayRefTest() {
328+
int Foo[12], Bar[12];
329+
templatedArrayRef(Foo, Bar);
330+
331+
int Baz[12], Quux[42];
332+
templatedArrayRef(Baz, Quux);
333+
334+
// NO-WARN: Implicit instantiations are not checked.
335+
}
336+
337+
template <>
338+
void templatedArrayRef(int (&Array1)[8], int (&Array2)[8]) { templatedArrayRef(Array2, Array1); }
339+
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 2 adjacent parameters of 'templatedArrayRef<8, 8>' of similar type ('int (&)[8]') are
340+
// CHECK-MESSAGES: :[[@LINE-2]]:30: note: the first parameter in the range is 'Array1'
341+
// CHECK-MESSAGES: :[[@LINE-3]]:48: note: the last parameter in the range is 'Array2'
342+
343+
template <>
344+
void templatedArrayRef(int (&Array1)[16], int (&Array2)[24]) {}
345+
// NO-WARN: Not the same type.
346+
303347
template <typename T>
304348
struct Vector {
305349
typedef T element_type;

0 commit comments

Comments
 (0)