189a1d03eSRichard // RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t \
289a1d03eSRichard // RUN: -config='{CheckOptions: \
3e8a3ddafSNathan James // RUN:  {readability-implicit-bool-conversion.AllowIntegerConditions: true, \
4e8a3ddafSNathan James // RUN:   readability-implicit-bool-conversion.AllowPointerConditions: true}}'
589a1d03eSRichard 
689a1d03eSRichard template<typename T>
789a1d03eSRichard void functionTaking(T);
889a1d03eSRichard 
989a1d03eSRichard int functionReturningInt();
1089a1d03eSRichard int* functionReturningPointer();
1189a1d03eSRichard 
1289a1d03eSRichard struct Struct {
1389a1d03eSRichard   int member;
1489a1d03eSRichard   unsigned bitfield : 1;
15332be179SCongcong Cai   bool boolfield : 1;
1689a1d03eSRichard };
1789a1d03eSRichard 
1889a1d03eSRichard 
regularImplicitConversionIntegerToBoolIsNotIgnored()1989a1d03eSRichard void regularImplicitConversionIntegerToBoolIsNotIgnored() {
2089a1d03eSRichard   int integer = 0;
2189a1d03eSRichard   functionTaking<bool>(integer);
22*fd0e06d1SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> 'bool' [readability-implicit-bool-conversion]
2389a1d03eSRichard   // CHECK-FIXES: functionTaking<bool>(integer != 0);
2489a1d03eSRichard }
2589a1d03eSRichard 
implicitConversionIntegerToBoolInConditionalsIsAllowed()2689a1d03eSRichard void implicitConversionIntegerToBoolInConditionalsIsAllowed() {
2789a1d03eSRichard   Struct s = {};
2889a1d03eSRichard   if (s.member) {}
2989a1d03eSRichard   if (!s.member) {}
3089a1d03eSRichard   if (s.bitfield) {}
3189a1d03eSRichard   if (!s.bitfield) {}
32332be179SCongcong Cai   if (s.boolfield == true) {}
33332be179SCongcong Cai   if (s.boolfield != true) {}
3489a1d03eSRichard   if (functionReturningInt()) {}
3589a1d03eSRichard   if (!functionReturningInt()) {}
3689a1d03eSRichard   if (functionReturningInt() && functionReturningPointer()) {}
3789a1d03eSRichard   if (!functionReturningInt() && !functionReturningPointer()) {}
3889a1d03eSRichard   for (; functionReturningInt(); ) {}
3989a1d03eSRichard   for (; functionReturningPointer(); ) {}
4089a1d03eSRichard   for (; functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer()); ) {}
4189a1d03eSRichard   while (functionReturningInt()) {}
4289a1d03eSRichard   while (functionReturningPointer()) {}
4389a1d03eSRichard   while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer())) {}
44f263f45bSFabian Wolff   do {} while (functionReturningInt());
45f263f45bSFabian Wolff   do {} while (functionReturningPointer());
46f263f45bSFabian Wolff   do {} while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer()));
4789a1d03eSRichard   int value1 = functionReturningInt() ? 1 : 2;
4889a1d03eSRichard   int value2 = !functionReturningInt() ? 1 : 2;
4989a1d03eSRichard   int value3 = (functionReturningInt() && functionReturningPointer() || !functionReturningInt()) ? 1 : 2;
5089a1d03eSRichard   int value4 = functionReturningInt() ?: value3;
5189a1d03eSRichard   int *p1 = functionReturningPointer() ?: &value3;
5289a1d03eSRichard }
5389a1d03eSRichard 
regularImplicitConversionPointerToBoolIsNotIgnored()5489a1d03eSRichard void regularImplicitConversionPointerToBoolIsNotIgnored() {
5589a1d03eSRichard   int* pointer = nullptr;
5689a1d03eSRichard   functionTaking<bool>(pointer);
57*fd0e06d1SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int *' -> 'bool'
5889a1d03eSRichard   // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
5989a1d03eSRichard 
6089a1d03eSRichard   int Struct::* memberPointer = &Struct::member;
6189a1d03eSRichard   functionTaking<bool>(memberPointer);
62*fd0e06d1SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int Struct::*' -> 'bool'
6389a1d03eSRichard   // CHECK-FIXES: functionTaking<bool>(memberPointer != nullptr);
6489a1d03eSRichard }
6589a1d03eSRichard 
implicitConversionPointerToBoolInConditionalsIsAllowed()6689a1d03eSRichard void implicitConversionPointerToBoolInConditionalsIsAllowed() {
6789a1d03eSRichard   if (functionReturningPointer()) {}
6889a1d03eSRichard   if (not functionReturningPointer()) {}
6989a1d03eSRichard   int value1 = functionReturningPointer() ? 1 : 2;
7089a1d03eSRichard   int value2 = (not functionReturningPointer()) ? 1 : 2;
7189a1d03eSRichard 
7289a1d03eSRichard   int Struct::* memberPointer = &Struct::member;
7389a1d03eSRichard   if (memberPointer) {}
7489a1d03eSRichard   if (memberPointer) {}
7589a1d03eSRichard   int value3 = memberPointer ? 1 : 2;
7689a1d03eSRichard   int value4 = (not memberPointer) ? 1 : 2;
7789a1d03eSRichard }
78