brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.9 KiB · 7518e3f Raw
350 lines · cpp
1// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-easily-swappable-parameters %t \2// RUN:   -config='{CheckOptions: { \3// RUN:     bugprone-easily-swappable-parameters.MinimumLength: 2, \4// RUN:     bugprone-easily-swappable-parameters.IgnoredParameterNames: "", \5// RUN:     bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes: "", \6// RUN:     bugprone-easily-swappable-parameters.QualifiersMix: 0, \7// RUN:     bugprone-easily-swappable-parameters.ModelImplicitConversions: 1, \8// RUN:     bugprone-easily-swappable-parameters.SuppressParametersUsedTogether: 0, \9// RUN:     bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityThreshold: 0 \10// RUN:  }}' --11 12void implicitDoesntBreakOtherStuff(int A, int B) {}13// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: 2 adjacent parameters of 'implicitDoesntBreakOtherStuff' of similar type ('int') are easily swapped by mistake [bugprone-easily-swappable-parameters]14// CHECK-MESSAGES: :[[@LINE-2]]:40: note: the first parameter in the range is 'A'15// CHECK-MESSAGES: :[[@LINE-3]]:47: note: the last parameter in the range is 'B'16 17void arrayAndPtr1(int *IP, int IA[]) { arrayAndPtr1(IA, IP); }18// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 2 adjacent parameters of 'arrayAndPtr1' of similar type ('int *')19// CHECK-MESSAGES: :[[@LINE-2]]:24: note: the first parameter in the range is 'IP'20// CHECK-MESSAGES: :[[@LINE-3]]:32: note: the last parameter in the range is 'IA'21 22void arrayAndPtr2(int *IP, int IA[8]) { arrayAndPtr2(IA, IP); }23// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 2 adjacent parameters of 'arrayAndPtr2' of similar type ('int *')24// CHECK-MESSAGES: :[[@LINE-2]]:24: note: the first parameter in the range is 'IP'25// CHECK-MESSAGES: :[[@LINE-3]]:32: note: the last parameter in the range is 'IA'26 27void arrayAndElement(int I, int IA[]) {} // NO-WARN.28 29typedef int Point2D[2];30typedef int Point3D[3];31 32void 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 *') are34// 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 37void crefToArrayTypedef1(int I, const Point2D &P) {}38// NO-WARN.39 40void crefToArrayTypedef2(int *IA, const Point2D &P) {}41// NO-WARN.42 43void crefToArrayTypedef3(int P1[2], const Point2D &P) {}44// NO-WARN.45 46void crefToArrayTypedefBoth1(const Point2D &VecDescartes, const Point3D &VecThreeD) {}47// NO-WARN: Distinct types.48 49template <int N, int M>50void templatedArrayRef(int (&Array1)[N], int (&Array2)[M]) {}51// NO-WARN: Distinct template types in the primary template.52 53void 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 63template <>64void 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]') are66// 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 69template <>70void templatedArrayRef(int (&Array1)[16], int (&Array2)[24]) {}71// NO-WARN: Not the same type.72 73void numericConversion1(int I, double D) { numericConversion1(D, I); }74// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion1' of convertible types are easily swapped by mistake [bugprone-easily-swappable-parameters]75// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'76// CHECK-MESSAGES: :[[@LINE-3]]:39: note: the last parameter in the range is 'D'77// CHECK-MESSAGES: :[[@LINE-4]]:32: note: 'int' and 'double' may be implicitly converted{{$}}78 79void numericConversion2(int I, short S) { numericConversion2(S, I); }80// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion2' of convertible types81// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'82// CHECK-MESSAGES: :[[@LINE-3]]:38: note: the last parameter in the range is 'S'83// CHECK-MESSAGES: :[[@LINE-4]]:32: note: 'int' and 'short' may be implicitly converted{{$}}84 85void numericConversion3(float F, unsigned long long ULL) { numericConversion3(ULL, F); }86// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion3' of convertible types87// CHECK-MESSAGES: :[[@LINE-2]]:31: note: the first parameter in the range is 'F'88// CHECK-MESSAGES: :[[@LINE-3]]:53: note: the last parameter in the range is 'ULL'89// CHECK-MESSAGES: :[[@LINE-4]]:34: note: 'float' and 'unsigned long long' may be implicitly converted{{$}}90 91enum Unscoped { U_A,92                U_B };93enum UnscopedFixed : char { UF_A,94                            UF_B };95enum struct Scoped { A,96                     B };97 98void numericConversion4(int I, Unscoped U) {} // NO-WARN.99 100void numericConversion5(int I, UnscopedFixed UF) {} // NO-WARN.101 102void numericConversion6(int I, Scoped S) {} // NO-WARN.103 104void numericConversion7(double D, Unscoped U) {} // NO-WARN.105 106void numericConversion8(double D, UnscopedFixed UF) {} // NO-WARN.107 108void numericConversion9(double D, Scoped S) {} // NO-WARN.109 110void numericConversionMultiUnique(int I, double D1, double D2) {}111// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: 3 adjacent parameters of 'numericConversionMultiUnique' of convertible types112// CHECK-MESSAGES: :[[@LINE-2]]:39: note: the first parameter in the range is 'I'113// CHECK-MESSAGES: :[[@LINE-3]]:60: note: the last parameter in the range is 'D2'114// CHECK-MESSAGES: :[[@LINE-4]]:42: note: 'int' and 'double' may be implicitly converted{{$}}115// (Note: int<->double conversion for I<->D2 not diagnosed again.)116 117typedef int MyInt;118using MyDouble = double;119 120void numericConversion10(MyInt MI, MyDouble MD) { numericConversion10(MD, MI); }121// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 2 adjacent parameters of 'numericConversion10' of convertible types122// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'MI'123// CHECK-MESSAGES: :[[@LINE-3]]:45: note: the last parameter in the range is 'MD'124// CHECK-MESSAGES: :[[@LINE-4]]:36: note: 'MyInt' and 'MyDouble' may be implicitly converted: 'MyInt' (as 'int') -> 'MyDouble' (as 'double'), 'MyDouble' (as 'double') -> 'MyInt' (as 'int')125 126void numericAndQualifierConversion(int I, const double CD) { numericAndQualifierConversion(CD, I); }127// NO-WARN: Qualifier mixing is handled by a different check option.128 129struct FromInt {130  FromInt(int);131};132 133void oneWayConversion1(int I, FromInt FI) {} // NO-WARN: One-way.134 135struct AmbiguousConvCtor {136  AmbiguousConvCtor(int);137  AmbiguousConvCtor(double);138};139 140void ambiguous1(long L, AmbiguousConvCtor ACC) {} // NO-WARN: Ambiguous, one-way.141 142struct ToInt {143  operator int() const;144};145 146void oneWayConversion2(ToInt TI, int I) {} // NO-WARN: One-way.147 148struct AmbiguousConvOp {149  operator int() const;150  operator double() const;151};152 153void ambiguous2(AmbiguousConvOp ACO, long L) {} // NO-WARN: Ambiguous, one-way.154 155struct AmbiguousEverything1;156struct AmbiguousEverything2;157struct AmbiguousEverything1 {158  AmbiguousEverything1();159  AmbiguousEverything1(AmbiguousEverything2);160  operator AmbiguousEverything2() const;161};162struct AmbiguousEverything2 {163  AmbiguousEverything2();164  AmbiguousEverything2(AmbiguousEverything1);165  operator AmbiguousEverything1() const;166};167 168void ambiguous3(AmbiguousEverything1 AE1, AmbiguousEverything2 AE2) {} // NO-WARN: Ambiguous.169 170struct Integer {171  Integer(int);172  operator int() const;173};174 175void userDefinedConversion1(int I1, Integer I2) { userDefinedConversion1(I2, I1); }176// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: 2 adjacent parameters of 'userDefinedConversion1' of convertible types177// CHECK-MESSAGES: :[[@LINE-2]]:33: note: the first parameter in the range is 'I1'178// CHECK-MESSAGES: :[[@LINE-3]]:45: note: the last parameter in the range is 'I2'179// CHECK-MESSAGES: :[[@LINE-4]]:37: note: 'int' and 'Integer' may be implicitly converted{{$}}180// CHECK-MESSAGES: :[[@LINE-9]]:3: note: the implicit conversion involves the converting constructor declared here181// CHECK-MESSAGES: :[[@LINE-9]]:3: note: the implicit conversion involves the conversion operator declared here182 183struct Ambiguous {184  Ambiguous(int);185  Ambiguous(double);186  operator long() const;187  operator float() const;188};189 190void ambiguous3(char C, Ambiguous A) {} // NO-WARN: Ambiguous.191 192struct CDouble {193  CDouble(const double &);194  operator const double &() const;195};196 197void userDefinedConversion2(double D, CDouble CD) { userDefinedConversion2(CD, D); }198// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: 2 adjacent parameters of 'userDefinedConversion2' of convertible types199// CHECK-MESSAGES: :[[@LINE-2]]:36: note: the first parameter in the range is 'D'200// CHECK-MESSAGES: :[[@LINE-3]]:47: note: the last parameter in the range is 'CD'201// CHECK-MESSAGES: :[[@LINE-4]]:39: note: 'double' and 'CDouble' may be implicitly converted: 'double' -> 'const double &' -> 'CDouble', 'CDouble' -> 'const double &' -> 'double'202// CHECK-MESSAGES: :[[@LINE-9]]:3: note: the implicit conversion involves the converting constructor declared here203// CHECK-MESSAGES: :[[@LINE-9]]:3: note: the implicit conversion involves the conversion operator declared here204 205void userDefinedConversion3(int I, CDouble CD) { userDefinedConversion3(CD, I); }206// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: 2 adjacent parameters of 'userDefinedConversion3' of convertible types207// CHECK-MESSAGES: :[[@LINE-2]]:33: note: the first parameter in the range is 'I'208// CHECK-MESSAGES: :[[@LINE-3]]:44: note: the last parameter in the range is 'CD'209// CHECK-MESSAGES: :[[@LINE-4]]:36: note: 'int' and 'CDouble' may be implicitly converted: 'int' -> 'double' -> 'const double &' -> 'CDouble', 'CDouble' -> 'const double &' -> 'int'210// CHECK-MESSAGES: :[[@LINE-17]]:3: note: the implicit conversion involves the converting constructor declared here211// CHECK-MESSAGES: :[[@LINE-17]]:3: note: the implicit conversion involves the conversion operator declared here212 213struct TDInt {214  TDInt(const MyInt &);215  operator MyInt() const;216};217 218void userDefinedConversion4(int I, TDInt TDI) { userDefinedConversion4(TDI, I); }219// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: 2 adjacent parameters of 'userDefinedConversion4' of convertible types220// CHECK-MESSAGES: :[[@LINE-2]]:33: note: the first parameter in the range is 'I'221// CHECK-MESSAGES: :[[@LINE-3]]:42: note: the last parameter in the range is 'TDI'222// CHECK-MESSAGES: :[[@LINE-4]]:36: note: 'int' and 'TDInt' may be implicitly converted: 'int' -> 'const MyInt &' -> 'TDInt', 'TDInt' -> 'MyInt' -> 'int'223// CHECK-MESSAGES: :[[@LINE-9]]:3: note: the implicit conversion involves the converting constructor declared here224// CHECK-MESSAGES: :[[@LINE-9]]:3: note: the implicit conversion involves the conversion operator declared here225 226struct TDIntDouble {227  TDIntDouble(const MyInt &);228  TDIntDouble(const MyDouble &);229  operator MyInt() const;230  operator MyDouble() const;231};232 233void userDefinedConversion5(int I, TDIntDouble TDID) { userDefinedConversion5(TDID, I); }234// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: 2 adjacent parameters of 'userDefinedConversion5' of convertible types235// CHECK-MESSAGES: :[[@LINE-2]]:33: note: the first parameter in the range is 'I'236// CHECK-MESSAGES: :[[@LINE-3]]:48: note: the last parameter in the range is 'TDID'237// CHECK-MESSAGES: :[[@LINE-4]]:36: note: 'int' and 'TDIntDouble' may be implicitly converted: 'int' -> 'const MyInt &' -> 'TDIntDouble', 'TDIntDouble' -> 'MyInt' -> 'int'238// CHECK-MESSAGES: :[[@LINE-11]]:3: note: the implicit conversion involves the converting constructor declared here239// CHECK-MESSAGES: :[[@LINE-10]]:3: note: the implicit conversion involves the conversion operator declared here240 241void userDefinedConversion6(double D, TDIntDouble TDID) { userDefinedConversion6(TDID, D); }242// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: 2 adjacent parameters of 'userDefinedConversion6' of convertible types243// CHECK-MESSAGES: :[[@LINE-2]]:36: note: the first parameter in the range is 'D'244// CHECK-MESSAGES: :[[@LINE-3]]:51: note: the last parameter in the range is 'TDID'245// CHECK-MESSAGES: :[[@LINE-4]]:39: note: 'double' and 'TDIntDouble' may be implicitly converted: 'double' -> 'const MyDouble &' -> 'TDIntDouble', 'TDIntDouble' -> 'MyDouble' -> 'double'246// CHECK-MESSAGES: :[[@LINE-18]]:3: note: the implicit conversion involves the converting constructor declared here247// CHECK-MESSAGES: :[[@LINE-17]]:3: note: the implicit conversion involves the conversion operator declared here248 249void userDefinedConversion7(char C, TDIntDouble TDID) {} // NO-WARN: Ambiguous.250 251struct Forward1;252struct Forward2;253 254void incomplete(Forward1 *F1, Forward2 *F2) {} // NO-WARN: Do not compare incomplete types.255 256void pointeeConverison(int *IP, double *DP) {} // NO-WARN.257 258void pointerConversion1(void *VP, int *IP) {} // NO-WARN: One-way.259 260struct PointerBox {261  PointerBox(void *);262  operator int *() const;263};264 265void pointerConversion2(PointerBox PB, int *IP) { pointerConversion2(IP, PB); }266// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'pointerConversion2' of convertible types267// CHECK-MESSAGES: :[[@LINE-2]]:36: note: the first parameter in the range is 'PB'268// CHECK-MESSAGES: :[[@LINE-3]]:45: note: the last parameter in the range is 'IP'269// CHECK-MESSAGES: :[[@LINE-4]]:40: note: 'PointerBox' and 'int *' may be implicitly converted: 'PointerBox' -> 'int *', 'int *' -> 'void *' -> 'PointerBox'270// CHECK-MESSAGES: :[[@LINE-8]]:3: note: the implicit conversion involves the conversion operator declared here271// CHECK-MESSAGES: :[[@LINE-10]]:3: note: the implicit conversion involves the converting constructor declared here272 273void pointerConversion3(PointerBox PB, double *DP) {} // NO-WARN: Not convertible.274 275struct Base {};276struct Derived : Base {};277 278void pointerConversion4(Base *BP, Derived *DP) {} // NO-WARN: One-way.279 280struct BaseAndDerivedInverter {281  BaseAndDerivedInverter(Base); // Takes a Base282  operator Derived() const;     // and becomes a Derived.283};284 285void pointerConversion5(BaseAndDerivedInverter BADI, Derived D) { pointerConversion5(D, BADI); }286// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'pointerConversion5' of convertible types287// CHECK-MESSAGES: :[[@LINE-2]]:48: note: the first parameter in the range is 'BADI'288// CHECK-MESSAGES: :[[@LINE-3]]:62: note: the last parameter in the range is 'D'289// CHECK-MESSAGES: :[[@LINE-4]]:54: note: 'BaseAndDerivedInverter' and 'Derived' may be implicitly converted: 'BaseAndDerivedInverter' -> 'Derived', 'Derived' -> 'Base' -> 'BaseAndDerivedInverter'290// CHECK-MESSAGES: :[[@LINE-8]]:3: note: the implicit conversion involves the conversion operator declared here291// CHECK-MESSAGES: :[[@LINE-10]]:3: note: the implicit conversion involves the converting constructor declared here292 293void pointerConversion6(void (*NTF)() noexcept, void (*TF)()) {}294// NO-WARN: This call cannot be swapped, even if "getCanonicalType()" believes otherwise.295 296using NonThrowingFunction = void (*)() noexcept;297 298struct NoexceptMaker {299  NoexceptMaker(void (*ThrowingFunction)());300  // Need to use a typedef here because301  // "conversion function cannot convert to a function type".302  // operator (void (*)() noexcept) () const;303  operator NonThrowingFunction() const;304};305 306void pointerConversion7(void (*NTF)() noexcept, NoexceptMaker NM) { pointerConversion7(NM, NTF); }307// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'pointerConversion7' of convertible types308// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'NTF'309// CHECK-MESSAGES: :[[@LINE-3]]:63: note: the last parameter in the range is 'NM'310// CHECK-MESSAGES: :[[@LINE-4]]:49: note: 'void (*)() noexcept' and 'NoexceptMaker' may be implicitly converted: 'void (*)() noexcept' -> 'void (*)()' -> 'NoexceptMaker', 'NoexceptMaker' -> 'NonThrowingFunction' -> 'void (*)() noexcept'311// CHECK-MESSAGES: :[[@LINE-12]]:3: note: the implicit conversion involves the converting constructor declared here312// CHECK-MESSAGES: :[[@LINE-9]]:3: note: the implicit conversion involves the conversion operator declared here313 314struct ToType;315struct MiddleStep1 {316  operator ToType() const;317};318struct FromType {319  operator MiddleStep1() const;320};321struct MiddleStep2 {322  operator FromType() const;323};324struct ToType {325  operator MiddleStep2() const;326};327 328void f(FromType F, ToType T) { // NO-WARN: The path takes two steps.329  MiddleStep2 MS2 = T;330  FromType F2 = MS2;331 332  MiddleStep1 MS1 = F;333  ToType T2 = MS1;334 335  f(F2, T2);336}337 338// Synthesised example from OpenCV.339template <typename T>340struct TemplateConversion {341  template <typename T2>342  operator TemplateConversion<T2>() const;343};344using IntConverter = TemplateConversion<int>;345using FloatConverter = TemplateConversion<float>;346 347void templateConversion(IntConverter IC, FloatConverter FC) { templateConversion(FC, IC); }348// Note: even though this swap is possible, we do not model things when it comes to "template magic".349// But at least the check should not crash!350