xref: /llvm-project/clang/test/SemaObjC/objc-literal-comparison.m (revision 9ad94aa280619feaed083fd35f9a50c7e076a7b0)
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