1 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -fblocks -w -analyzer-checker=osx.NumberObjectConversion %s -verify |
2 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -fblocks -w -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify |
3 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyzer-checker=osx.NumberObjectConversion %s -verify |
4 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify |
5 | |
6 | #include "Inputs/system-header-simulator-objc.h" |
7 | |
8 | void takes_boolean(BOOL); |
9 | void takes_integer(int); |
10 | |
11 | void bad(NSNumber *p) { |
12 | #ifdef PEDANTIC |
13 | if (p) {} // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive boolean value; instead, either compare the pointer to nil or call -boolValue}} |
14 | if (!p) {} // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive boolean value; instead, either compare the pointer to nil or call -boolValue}} |
15 | (!p) ? 1 : 2; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive boolean value; instead, either compare the pointer to nil or call -boolValue}} |
16 | if (p == 0) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; instead, either compare the pointer to nil or compare the result of calling a method on 'NSNumber *' to get the scalar value}} |
17 | #else |
18 | if (p) {} // no-warning |
19 | if (!p) {} // no-warning |
20 | (!p) ? 1 : 2; // no-warning |
21 | if (p == 0) {} // no-warning |
22 | #endif |
23 | (BOOL)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}} |
24 | if (p > 0) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to compare the result of calling a method on 'NSNumber *' to get the scalar value?}} |
25 | if (p == YES) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}} |
26 | if (p == NO) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}} |
27 | BOOL x = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}} |
28 | x = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}} |
29 | x = (p == YES); // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}} |
30 | if (p == 1) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to compare the result of calling a method on 'NSNumber *' to get the scalar value?}} |
31 | int y = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}} |
32 | y = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}} |
33 | takes_boolean(p); // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}} |
34 | takes_integer(p); // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}} |
35 | takes_boolean(x); // no-warning |
36 | takes_integer(y); // no-warning |
37 | } |
38 | |
39 | typedef NSNumber *SugaredNumber; |
40 | void bad_sugared(SugaredNumber p) { |
41 | p == YES; // expected-warning{{Comparing a pointer value of type 'SugaredNumber' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}} |
42 | } |
43 | |
44 | @interface I : NSObject { |
45 | @public |
46 | NSNumber *ivar; |
47 | NSNumber *prop; |
48 | } |
49 | - (NSNumber *)foo; |
50 | @property(copy) NSNumber *prop; |
51 | @end |
52 | |
53 | @implementation I |
54 | @synthesize prop; |
55 | @end |
56 | |
57 | void bad_ivar(I *i) { |
58 | i->ivar == YES; // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}} |
59 | i->prop == YES; // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}} |
60 | [i foo] == YES; // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}} |
61 | } |
62 | |
63 | void good(NSNumber *p) { |
64 | if ([p boolValue] == NO) {} // no-warning |
65 | if ([p boolValue] == YES) {} // no-warning |
66 | BOOL x = [p boolValue]; // no-warning |
67 | } |
68 | |
69 | void suppression(NSNumber *p) { |
70 | if (p == NULL) {} // no-warning |
71 | if (p == nil) {} // no-warning |
72 | } |
73 | |
74 | // Conversion of a pointer to an intptr_t is fine. |
75 | typedef long intptr_t; |
76 | typedef unsigned long uintptr_t; |
77 | typedef long fintptr_t; // Fake, for testing the regex. |
78 | void test_intptr_t(NSNumber *p) { |
79 | (long)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}} |
80 | (intptr_t)p; // no-warning |
81 | (unsigned long)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}} |
82 | (uintptr_t)p; // no-warning |
83 | (fintptr_t)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}} |
84 | } |
85 | |
86 | // Test macro suppressions. |
87 | #define FOO 0 |
88 | #define BAR 1 |
89 | void test_macro(NSNumber *p) { |
90 | if (p != BAR) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to compare the result of calling a method on 'NSNumber *' to get the scalar value?}} |
91 | #ifdef PEDANTIC |
92 | if (p != FOO) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; instead, either compare the pointer to nil or compare the result of calling a method on 'NSNumber *' to get the scalar value}} |
93 | #else |
94 | if (p != FOO) {} // no-warning |
95 | #endif |
96 | } |
97 | |
98 | #define NULL_INSIDE_MACRO NULL |
99 | void test_NULL_inside_macro(NSNumber *p) { |
100 | #ifdef PEDANTIC |
101 | if (p == NULL_INSIDE_MACRO) {} // no-warning |
102 | #else |
103 | if (p == NULL_INSIDE_MACRO) {} // no-warning |
104 | #endif |
105 | } |
106 | |
107 | // Test a different definition of NULL. |
108 | #undef NULL |
109 | #define NULL 0 |
110 | void test_non_pointer_NULL(NSNumber *p) { |
111 | if (p == NULL) {} // no-warning |
112 | } |
113 | |