diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 7 | ||||
-rw-r--r-- | clang/test/Analysis/objc-string.mm | 2 | ||||
-rw-r--r-- | clang/test/SemaObjCXX/warn-objc-literal-conversion.mm | 74 |
5 files changed, 88 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 110c53e2291..8e9ef688c6f 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -44,6 +44,7 @@ def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">; 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 @@ def Conversion : DiagGroup<"conversion", LiteralConversion, NonLiteralNullConversion, // (1-1)->pointer (etc) NullConversion, // NULL->non-pointer + ObjCLiteralConversion, SignConversion, StringConversion]>, DiagCategory<"Value Conversion Issue">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b682505299f..67f5837246f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2296,6 +2296,10 @@ def note_function_to_bool_silence : Note< "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 boolean conversion of Objective-C object literal always " + "evaluates to true">, + InGroup<ObjCLiteralConversion>; def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 0dffa53679e..ee0e6702e0f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5358,6 +5358,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // prevented by a check in AnalyzeImplicitConversions(). return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_string_literal_to_bool); + if (isa<ObjCStringLiteral>(E) || isa<ObjCArrayLiteral>(E) || + isa<ObjCDictionaryLiteral>(E) || isa<ObjCBoxedExpr>(E)) { + // This covers the literal expressions that evaluate to Objective-C + // objects. + 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, diff --git a/clang/test/Analysis/objc-string.mm b/clang/test/Analysis/objc-string.mm index c67ab5e8919..a32b740bba0 100644 --- a/clang/test/Analysis/objc-string.mm +++ b/clang/test/Analysis/objc-string.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -Wno-objc-literal-conversion %s void clang_analyzer_eval(bool); @class NSString; diff --git a/clang/test/SemaObjCXX/warn-objc-literal-conversion.mm b/clang/test/SemaObjCXX/warn-objc-literal-conversion.mm new file mode 100644 index 00000000000..44645613e31 --- /dev/null +++ b/clang/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 boolean conversion of Objective-C object literal always evaluates to true}} +} + +void int_test() { + if (@12) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} + if (@-12) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} + if (@12LL) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} + if (@-12LL) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} +} + +void float_test() { + if (@12.55) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} + if (@-12.55) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} + if (@12.55F) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} + if (@-12.55F) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} +} + +void bool_test() { + if (@true) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} + if (@false) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} +} + +void string_test() { + if (@"asdf") {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} +} + +void array_test() { + if (@[ @313, @331, @367, @379 ]) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} +} + +void dictionary_test() { + if (@{ @0: @0, @1: @1, @2: @1, @3: @3 }) {} + // expected-warning@-1{{implicit boolean conversion of Objective-C object literal always evaluates to true}} +} + +void objc_bool_test () { + if (__objc_yes) {} + if (__objc_no) {} +} |