Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -44,6 +44,7 @@ def NullConversion : DiagGroup<"null-conversion">; def ImplicitConversionFloatingPointToBool : DiagGroup<"implicit-conversion-floating-point-to-bool">; +def ObjCLiteralConversion : DiagGroup<"objc-literal-conversion">; def BadArrayNewLength : DiagGroup<"bad-array-new-length">; def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">; def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; @@ -446,6 +447,7 @@ LiteralConversion, NonLiteralNullConversion, // (1-1)->pointer (etc) NullConversion, // NULL->non-pointer + ObjCLiteralConversion, SignConversion, StringConversion]>, DiagCategory<"Value Conversion Issue">; Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2296,6 +2296,9 @@ "prefix with the address-of operator to silence this warning">; def note_function_to_bool_call : Note< "suffix with parentheses to turn this into a function call">; +def warn_impcast_objective_c_literal_to_bool : Warning< + "implicit conversion turns Objective C literal into bool: %0 to %1">, + InGroup, DefaultIgnore; def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -5350,6 +5350,13 @@ // prevented by a check in AnalyzeImplicitConversions(). return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_string_literal_to_bool); + if (isa(E) || isa(E) || + isa(E) || isa(E)) { + // Warn on Objective C literal to bool conversions. This covers most of + // the Objective C types, except for ObjCBoolLiteral. + return DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_objective_c_literal_to_bool); + } if (Source->isFunctionType()) { // Warn on function to bool. Checks free functions and static member // functions. Weakly imported functions are excluded from the check, Index: test/SemaObjCXX/warn-objc-literal-conversion.mm =================================================================== --- test/SemaObjCXX/warn-objc-literal-conversion.mm +++ test/SemaObjCXX/warn-objc-literal-conversion.mm @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wobjc-literal-conversion %s + +@class NSString; + +@interface NSNumber ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(bool)value; +@end + +@interface NSArray ++ (id)arrayWithObjects:(const id [])objects count:(int)cnt; +@end + +@interface NSDictionary ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; +@end + +void char_test() { + if (@'a') {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} +} + +void int_test() { + if (@12) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} + if (@-12) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} + if (@12LL) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} + if (@-12LL) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} +} + +void float_test() { + if (@12.55) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} + if (@-12.55) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} + if (@12.55F) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} + if (@-12.55F) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} +} + +void bool_test() { + if (@true) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} + if (@false) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSNumber *' to 'bool'}} +} + +void string_test() { + if (@"asdf") {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSString *' to 'bool'}} +} + +void array_test() { + if (@[ @313, @331, @367, @379 ]) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSArray *' to 'bool'}} +} + +void dictionary_test() { + if (@{ @0: @0, @1: @1, @2: @1, @3: @3 }) {} + // expected-warning@-1{{implicit conversion turns Objective C literal into bool: 'NSDictionary *' to 'bool'}} +} + +void objc_bool_test () { + if (__objc_yes) {} + if (__objc_no) {} +}