1 | // RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=((id)0)" -verify %s |
2 | // RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=(id)0" -verify %s |
3 | // RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare "-Dnil=0" -verify %s |
4 | |
5 | // RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare -fobjc-arc "-Dnil=((id)0)" -verify %s |
6 | // RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare -fobjc-arc "-Dnil=(id)0" -verify %s |
7 | // RUN: %clang_cc1 -fsyntax-only -Wno-everything -Wobjc-literal-compare -fobjc-arc "-Dnil=0" -verify %s |
8 | |
9 | // (test the warning flag as well) |
10 | |
11 | typedef signed char BOOL; |
12 | |
13 | @interface BaseObject |
14 | + (instancetype)new; |
15 | @end |
16 | |
17 | @interface NSObject : BaseObject |
18 | - (BOOL)isEqual:(id)other; |
19 | @end |
20 | |
21 | @interface NSNumber : NSObject |
22 | + (NSNumber *)numberWithInt:(int)value; |
23 | + (NSNumber *)numberWithDouble:(double)value; |
24 | + (NSNumber *)numberWithBool:(BOOL)value; |
25 | @end |
26 | |
27 | @interface NSArray : NSObject |
28 | + (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt; |
29 | @end |
30 | |
31 | @interface NSDictionary : NSObject |
32 | + (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; |
33 | @end |
34 | |
35 | @interface NSString : NSObject |
36 | @end |
37 | |
38 | void testComparisonsWithFixits(id obj) { |
39 | if (obj == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
40 | if (obj != @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
41 | if (@"" == obj) return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
42 | if (@"" == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
43 | |
44 | if (@[] == obj) return; // expected-warning{{direct comparison of an array literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
45 | if (@{} == obj) return; // expected-warning{{direct comparison of a dictionary literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
46 | if (@12 == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
47 | if (@1.0 == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
48 | if (@__objc_yes == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
49 | if (@(1+1) == obj) return; // expected-warning{{direct comparison of a boxed expression has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
50 | } |
51 | |
52 | |
53 | @interface BadEqualReturnString : NSString |
54 | - (void)isEqual:(id)other; |
55 | @end |
56 | |
57 | @interface BadEqualArgString : NSString |
58 | - (BOOL)isEqual:(int)other; |
59 | @end |
60 | |
61 | |
62 | void testComparisonsWithoutFixits() { |
63 | if ([BaseObject new] == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
64 | |
65 | if ([BadEqualReturnString new] == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
66 | if ([BadEqualArgString new] == @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
67 | |
68 | if (@"" < @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
69 | if (@"" > @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
70 | if (@"" <= @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
71 | if (@"" >= @"") return; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
72 | } |
73 | |
74 | |
75 | #pragma clang diagnostic push |
76 | #pragma clang diagnostic ignored "-Wobjc-string-compare" |
77 | |
78 | void testWarningFlags(id obj) { |
79 | if (obj == @"") return; // no-warning |
80 | if (@"" == obj) return; // no-warning |
81 | |
82 | if (obj == @1) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
83 | if (@1 == obj) return; // expected-warning{{direct comparison of a numeric literal has undefined behavior}} expected-note{{use 'isEqual:' instead}} |
84 | } |
85 | |
86 | #pragma clang diagnostic pop |
87 | |
88 | |
89 | void testNilComparison() { |
90 | // Don't warn when comparing to nil in a macro. |
91 | #define RETURN_IF_NIL(x) if (x == nil || nil == x) return |
92 | RETURN_IF_NIL(@""); |
93 | RETURN_IF_NIL(@1); |
94 | RETURN_IF_NIL(@1.0); |
95 | RETURN_IF_NIL(@[]); |
96 | RETURN_IF_NIL(@{}); |
97 | RETURN_IF_NIL(@__objc_yes); |
98 | RETURN_IF_NIL(@(1+1)); |
99 | } |
100 | |
101 | void PR15257(Class c) { |
102 | return c == @""; // expected-warning{{direct comparison of a string literal has undefined behavior}} |
103 | } |
104 | |