| 1 | // RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t \ |
|---|---|
| 2 | // RUN: -config='{CheckOptions: \ |
| 3 | // RUN: {readability-implicit-bool-conversion.AllowIntegerConditions: true, \ |
| 4 | // RUN: readability-implicit-bool-conversion.AllowPointerConditions: true}}' |
| 5 | |
| 6 | template<typename T> |
| 7 | void functionTaking(T); |
| 8 | |
| 9 | int functionReturningInt(); |
| 10 | int* functionReturningPointer(); |
| 11 | |
| 12 | struct Struct { |
| 13 | int member; |
| 14 | unsigned bitfield : 1; |
| 15 | bool boolfield : 1; |
| 16 | }; |
| 17 | |
| 18 | |
| 19 | void regularImplicitConversionIntegerToBoolIsNotIgnored() { |
| 20 | int integer = 0; |
| 21 | functionTaking<bool>(integer); |
| 22 | // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> 'bool' [readability-implicit-bool-conversion] |
| 23 | // CHECK-FIXES: functionTaking<bool>(integer != 0); |
| 24 | } |
| 25 | |
| 26 | void implicitConversionIntegerToBoolInConditionalsIsAllowed() { |
| 27 | Struct s = {}; |
| 28 | if (s.member) {} |
| 29 | if (!s.member) {} |
| 30 | if (s.bitfield) {} |
| 31 | if (!s.bitfield) {} |
| 32 | if (s.boolfield == true) {} |
| 33 | if (s.boolfield != true) {} |
| 34 | if (functionReturningInt()) {} |
| 35 | if (!functionReturningInt()) {} |
| 36 | if (functionReturningInt() && functionReturningPointer()) {} |
| 37 | if (!functionReturningInt() && !functionReturningPointer()) {} |
| 38 | for (; functionReturningInt(); ) {} |
| 39 | for (; functionReturningPointer(); ) {} |
| 40 | for (; functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer()); ) {} |
| 41 | while (functionReturningInt()) {} |
| 42 | while (functionReturningPointer()) {} |
| 43 | while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer())) {} |
| 44 | do {} while (functionReturningInt()); |
| 45 | do {} while (functionReturningPointer()); |
| 46 | do {} while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer())); |
| 47 | int value1 = functionReturningInt() ? 1 : 2; |
| 48 | int value2 = !functionReturningInt() ? 1 : 2; |
| 49 | int value3 = (functionReturningInt() && functionReturningPointer() || !functionReturningInt()) ? 1 : 2; |
| 50 | int value4 = functionReturningInt() ?: value3; |
| 51 | int *p1 = functionReturningPointer() ?: &value3; |
| 52 | } |
| 53 | |
| 54 | void regularImplicitConversionPointerToBoolIsNotIgnored() { |
| 55 | int* pointer = nullptr; |
| 56 | functionTaking<bool>(pointer); |
| 57 | // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> 'bool' |
| 58 | // CHECK-FIXES: functionTaking<bool>(pointer != nullptr); |
| 59 | |
| 60 | int Struct::* memberPointer = &Struct::member; |
| 61 | functionTaking<bool>(memberPointer); |
| 62 | // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> 'bool' |
| 63 | // CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr); |
| 64 | } |
| 65 | |
| 66 | void implicitConversionPointerToBoolInConditionalsIsAllowed() { |
| 67 | if (functionReturningPointer()) {} |
| 68 | if (not functionReturningPointer()) {} |
| 69 | int value1 = functionReturningPointer() ? 1 : 2; |
| 70 | int value2 = (not functionReturningPointer()) ? 1 : 2; |
| 71 | |
| 72 | int Struct::* memberPointer = &Struct::member; |
| 73 | if (memberPointer) {} |
| 74 | if (memberPointer) {} |
| 75 | int value3 = memberPointer ? 1 : 2; |
| 76 | int value4 = (not memberPointer) ? 1 : 2; |
| 77 | } |
| 78 |
