blob: 3d20ab747194c99e0f653a436f8a374672ee36de [file] [log] [blame]
Artem Dergachev940c7702016-10-18 11:06:28 +00001// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
2// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
3// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
4// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
5
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
13 if (p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
14 if (!p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
15 (!p) ? 1 : 2; // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
16 (BOOL)p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; please compare the pointer to nil instead to suppress this warning}}
17 if (p == 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; please compare the pointer to nil instead to suppress this warning}}
18 if (p > 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
19#endif
20 if (p == YES) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
21 if (p == NO) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
22 BOOL x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
23 x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
24 x = (p == YES); // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
25 if (p == 1) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
26 int y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
27 y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
28 takes_boolean(p); // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
29 takes_integer(p); // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
30 takes_boolean(x); // no-warning
31 takes_integer(y); // no-warning
32}
33
34typedef NSNumber *SugaredNumber;
35void bad_sugared(SugaredNumber p) {
36 p == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
37}
38
39@interface I : NSObject {
40@public
41 NSNumber *ivar;
42 NSNumber *prop;
43}
44- (NSNumber *)foo;
45@property(copy) NSNumber *prop;
46@end
47
48@implementation I
49@synthesize prop;
50@end
51
52void bad_ivar(I *i) {
53 i->ivar == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
54 i->prop == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
55 [i foo] == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
56}
57
58void good(NSNumber *p) {
59 if ([p boolValue] == NO) {} // no-warning
60 if ([p boolValue] == YES) {} // no-warning
61 BOOL x = [p boolValue]; // no-warning
62}
63
64void suppression(NSNumber *p) {
65 if (p == NULL) {} // no-warning
66 if (p == nil) {} // no-warning
67}
68
69// Conversion of a pointer to an intptr_t is fine.
70typedef long intptr_t;
71typedef unsigned long uintptr_t;
72typedef long fintptr_t; // Fake, for testing the regex.
73void test_intptr_t(NSNumber *p) {
74 (long)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
75 (intptr_t)p; // no-warning
76 (unsigned long)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
77 (uintptr_t)p; // no-warning
78 (fintptr_t)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
79}
80
81// Test a different definition of NULL.
82#undef NULL
83#define NULL 0
84void test_non_pointer_NULL(NSNumber *p) {
85 if (p == NULL) {} // no-warning
86}