1 // RUN: %clang_cc1 -triple i386-apple-darwin10 -w -std=c++11 -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
2 // RUN: %clang_cc1 -triple i386-apple-darwin10 -w -std=c++11 -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
3 
4 #define NULL ((void *)0)
5 #include "Inputs/system-header-simulator-cxx.h" // for nullptr
6 
7 class OSBoolean {
8 public:
9   virtual bool isTrue() const;
10   virtual bool isFalse() const;
11 };
12 
13 extern const OSBoolean *const &kOSBooleanFalse;
14 extern const OSBoolean *const &kOSBooleanTrue;
15 
16 void takes_bool(bool);
17 
18 void bad(const OSBoolean *p) {
19 #ifdef PEDANTIC
20   if (p) {} // expected-warning{{Converting 'const class OSBoolean *' to a plain boolean value for branching; please compare the pointer to NULL or nullptr instead to suppress this warning}}
21   if (!p) {} // expected-warning{{Converting 'const class OSBoolean *' to a plain boolean value for branching; please compare the pointer to NULL or nullptr instead to suppress this warning}}
22   p ? 1 : 2; // expected-warning{{Converting 'const class OSBoolean *' to a plain boolean value for branching; please compare the pointer to NULL or nullptr instead to suppress this warning}}
23   (bool)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; please compare the pointer to NULL or nullptr instead to suppress this warning}}
24 #endif
25   bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
26   x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
27   takes_bool(p); // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
28   takes_bool(x); // no-warning
29 }
30 
31 typedef bool sugared_bool;
32 typedef const OSBoolean *sugared_OSBoolean;
33 void bad_sugared(sugared_OSBoolean p) {
34   sugared_bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
35 }
36 
37 void good(const OSBoolean *p) {
38   bool x = p->isTrue(); // no-warning
39   (bool)p->isFalse(); // no-warning
40   if (p == kOSBooleanTrue) {} // no-warning
41 }
42 
43 void suppression(const OSBoolean *p) {
44   if (p == NULL) {} // no-warning
45   bool y = (p == nullptr); // no-warning
46 }
47 
48 // Conversion of a pointer to an intptr_t is fine.
49 typedef long intptr_t;
50 typedef unsigned long uintptr_t;
51 typedef long fintptr_t; // Fake, for testing the regex.
52 void test_intptr_t(const OSBoolean *p) {
53   (long)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain integer value; pointer value is being used instead}}
54   (intptr_t)p; // no-warning
55   (unsigned long)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain integer value; pointer value is being used instead}}
56   (uintptr_t)p; // no-warning
57   (fintptr_t)p; // expected-warning{{Converting 'const class OSBoolean *' to a plain integer value; pointer value is being used instead}}
58 }
59 
60 // Test a different definition of NULL.
61 #undef NULL
62 #define NULL 0
63 void test_non_pointer_NULL(const OSBoolean *p) {
64   if (p == NULL) {} // no-warning
65 }
66