blob: 8bc03320e6d6bb5ef93b2ec1b2f5e91ba0a00b8f [file] [log] [blame]
Dominic Chen184c6242017-03-03 18:02:02 +00001// 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
Artem Dergachev940c7702016-10-18 11:06:28 +00005
6#include "Inputs/system-header-simulator-objc.h"
7
8void takes_boolean(BOOL);
9void takes_integer(int);
10
11void bad(NSNumber *p) {
12#ifdef PEDANTIC
Artem Dergacheve14d8812016-10-31 03:08:48 +000013 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
Artem Dergachev940c7702016-10-18 11:06:28 +000022#endif
Artem Dergacheve14d8812016-10-31 03:08:48 +000023 (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?}}
Artem Dergachev940c7702016-10-18 11:06:28 +000035 takes_boolean(x); // no-warning
36 takes_integer(y); // no-warning
37}
38
39typedef NSNumber *SugaredNumber;
40void bad_sugared(SugaredNumber p) {
Artem Dergacheve14d8812016-10-31 03:08:48 +000041 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?}}
Artem Dergachev940c7702016-10-18 11:06:28 +000042}
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
57void bad_ivar(I *i) {
Artem Dergacheve14d8812016-10-31 03:08:48 +000058 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?}}
Artem Dergachev940c7702016-10-18 11:06:28 +000061}
62
63void 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
69void 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.
75typedef long intptr_t;
76typedef unsigned long uintptr_t;
77typedef long fintptr_t; // Fake, for testing the regex.
78void test_intptr_t(NSNumber *p) {
Artem Dergacheve14d8812016-10-31 03:08:48 +000079 (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?}}
Artem Dergachev940c7702016-10-18 11:06:28 +000080 (intptr_t)p; // no-warning
Artem Dergacheve14d8812016-10-31 03:08:48 +000081 (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?}}
Artem Dergachev940c7702016-10-18 11:06:28 +000082 (uintptr_t)p; // no-warning
Artem Dergacheve14d8812016-10-31 03:08:48 +000083 (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
89void 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
99void 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
Artem Dergachev940c7702016-10-18 11:06:28 +0000105}
106
107// Test a different definition of NULL.
108#undef NULL
109#define NULL 0
110void test_non_pointer_NULL(NSNumber *p) {
111 if (p == NULL) {} // no-warning
112}