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 8void takes_boolean(BOOL); 9void takes_integer(int); 10 11void 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 39typedef NSNumber *SugaredNumber; 40void 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 57void 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 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) { 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 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 105} 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} 113