163ffaa8cSJordan Rose// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=((id)0)" -verify %s 263ffaa8cSJordan Rose// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=(id)0" -verify %s 363ffaa8cSJordan Rose// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=0" -verify %s 4ea70bf71SJordan Rose 5e2028139SJordan Rose// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare -fobjc-arc "-Dnil=((id)0)" -verify %s 6e2028139SJordan Rose// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare -fobjc-arc "-Dnil=(id)0" -verify %s 7e2028139SJordan Rose// RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare -fobjc-arc "-Dnil=0" -verify %s 8e2028139SJordan Rose 9ea70bf71SJordan Rose// (test the warning flag as well) 10d49a33e8SJordan Rose 1163ffaa8cSJordan Rosetypedef signed char BOOL; 12d49a33e8SJordan Rose 13d49a33e8SJordan Rose@interface BaseObject 14d49a33e8SJordan Rose+ (instancetype)new; 15d49a33e8SJordan Rose@end 16d49a33e8SJordan Rose 17d49a33e8SJordan Rose@interface NSObject : BaseObject 18d49a33e8SJordan Rose- (BOOL)isEqual:(id)other; 19d49a33e8SJordan Rose@end 20d49a33e8SJordan Rose 21d49a33e8SJordan Rose@interface NSNumber : NSObject 22d49a33e8SJordan Rose+ (NSNumber *)numberWithInt:(int)value; 23d49a33e8SJordan Rose+ (NSNumber *)numberWithDouble:(double)value; 24d49a33e8SJordan Rose+ (NSNumber *)numberWithBool:(BOOL)value; 25d49a33e8SJordan Rose@end 26d49a33e8SJordan Rose 27d49a33e8SJordan Rose@interface NSArray : NSObject 28d49a33e8SJordan Rose+ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt; 29d49a33e8SJordan Rose@end 30d49a33e8SJordan Rose 31d49a33e8SJordan Rose@interface NSDictionary : NSObject 32d49a33e8SJordan Rose+ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; 33d49a33e8SJordan Rose@end 34d49a33e8SJordan Rose 35d49a33e8SJordan Rose@interface NSString : NSObject 36d49a33e8SJordan Rose@end 37d49a33e8SJordan Rose 38d49a33e8SJordan Rosevoid testComparisonsWithFixits(id obj) { 397660f78fSJordan Rose if (obj == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 407660f78fSJordan Rose if (obj != @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 417660f78fSJordan Rose if (@"" == obj) return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 427660f78fSJordan Rose if (@"" == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 43d49a33e8SJordan Rose 447660f78fSJordan Rose if (@[] == obj) return; // expected-warning{{direct comparison of an array literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 457660f78fSJordan Rose if (@{} == obj) return; // expected-warning{{direct comparison of a dictionary literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 467660f78fSJordan Rose if (@12 == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 477660f78fSJordan Rose if (@1.0 == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 487660f78fSJordan Rose if (@__objc_yes == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 497660f78fSJordan Rose if (@(1+1) == obj) return; // expected-warning{{direct comparison of a boxed expression has undefined behavior}} expected-note{{use 'isEqual:' instead}} 50d49a33e8SJordan Rose} 51d49a33e8SJordan Rose 52d49a33e8SJordan Rose 53d49a33e8SJordan Rose@interface BadEqualReturnString : NSString 54d49a33e8SJordan Rose- (void)isEqual:(id)other; 55d49a33e8SJordan Rose@end 56d49a33e8SJordan Rose 57d49a33e8SJordan Rose@interface BadEqualArgString : NSString 58d49a33e8SJordan Rose- (BOOL)isEqual:(int)other; 59d49a33e8SJordan Rose@end 60d49a33e8SJordan Rose 61d49a33e8SJordan Rose 62d49a33e8SJordan Rosevoid testComparisonsWithoutFixits() { 637660f78fSJordan Rose if ([BaseObject new] == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} 64d49a33e8SJordan Rose 657660f78fSJordan Rose if ([BadEqualReturnString new] == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} 667660f78fSJordan Rose if ([BadEqualArgString new] == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} 67d49a33e8SJordan Rose 687660f78fSJordan Rose if (@"" < @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} 697660f78fSJordan Rose if (@"" > @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} 707660f78fSJordan Rose if (@"" <= @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} 717660f78fSJordan Rose if (@"" >= @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} 72d49a33e8SJordan Rose} 73d49a33e8SJordan Rose 74ea70bf71SJordan Rose 75ea70bf71SJordan Rose#pragma clang diagnostic push 76ea70bf71SJordan Rose#pragma clang diagnostic ignored "-Wobjc-string-compare" 77ea70bf71SJordan Rose 78ea70bf71SJordan Rosevoid testWarningFlags(id obj) { 79ea70bf71SJordan Rose if (obj == @"") return; // no-warning 80ea70bf71SJordan Rose if (@"" == obj) return; // no-warning 81ea70bf71SJordan Rose 82ea70bf71SJordan Rose if (obj == @1) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 83ea70bf71SJordan Rose if (@1 == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} 84ea70bf71SJordan Rose} 85ea70bf71SJordan Rose 86ea70bf71SJordan Rose#pragma clang diagnostic pop 87ea70bf71SJordan Rose 8863ffaa8cSJordan Rose 8963ffaa8cSJordan Rosevoid testNilComparison() { 9063ffaa8cSJordan Rose // Don't warn when comparing to nil in a macro. 9163ffaa8cSJordan Rose#define RETURN_IF_NIL(x) if (x == nil || nil == x) return 9263ffaa8cSJordan Rose RETURN_IF_NIL(@""); 9363ffaa8cSJordan Rose RETURN_IF_NIL(@1); 9463ffaa8cSJordan Rose RETURN_IF_NIL(@1.0); 9563ffaa8cSJordan Rose RETURN_IF_NIL(@[]); 9663ffaa8cSJordan Rose RETURN_IF_NIL(@{}); 9763ffaa8cSJordan Rose RETURN_IF_NIL(@__objc_yes); 9863ffaa8cSJordan Rose RETURN_IF_NIL(@(1+1)); 9963ffaa8cSJordan Rose} 10063ffaa8cSJordan Rose 101*25c05106SBenjamin Kramervoid PR15257(Class c) { 102*25c05106SBenjamin Kramer return c == @""; // expected-warning{{direct comparison of a string literal has undefined behavior}} 103*25c05106SBenjamin Kramer} 104