1 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -w -std=c++11 -analyzer-checker=osx.NumberObjectConversion %s -verify |
2 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -w -std=c++11 -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 | class OSNumber { |
14 | public: |
15 | virtual bool isEqualTo(const OSNumber *); |
16 | virtual unsigned char unsigned8BitValue() const; |
17 | virtual unsigned short unsigned16BitValue() const; |
18 | virtual unsigned int unsigned32BitValue() const; |
19 | virtual unsigned long long unsigned64BitValue() const; |
20 | }; |
21 | |
22 | extern const OSBoolean *const &kOSBooleanFalse; |
23 | extern const OSBoolean *const &kOSBooleanTrue; |
24 | |
25 | void takes_bool(bool); |
26 | |
27 | void bad_boolean(const OSBoolean *p) { |
28 | #ifdef PEDANTIC |
29 | if (p) {} // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive boolean value; instead, either compare the pointer to nullptr or call getValue()}} |
30 | if (!p) {} // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive boolean value; instead, either compare the pointer to nullptr or call getValue()}} |
31 | p ? 1 : 2; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive boolean value; instead, either compare the pointer to nullptr or call getValue()}} |
32 | #else |
33 | if (p) {} // no-warning |
34 | if (!p) {} // no-warning |
35 | p ? 1 : 2; // no-warning |
36 | #endif |
37 | (bool)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} |
38 | bool x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} |
39 | x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} |
40 | takes_bool(p); // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} |
41 | takes_bool(x); // no-warning |
42 | } |
43 | |
44 | void bad_number(const OSNumber *p) { |
45 | #ifdef PEDANTIC |
46 | if (p) {} // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar boolean value; instead, either compare the pointer to nullptr or call a method on 'class OSNumber *' to get the scalar value}} |
47 | if (!p) {} // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar boolean value; instead, either compare the pointer to nullptr or call a method on 'class OSNumber *' to get the scalar value}} |
48 | p ? 1 : 2; // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar boolean value; instead, either compare the pointer to nullptr or call a method on 'class OSNumber *' to get the scalar value}} |
49 | if (p == 0) {} // expected-warning{{Comparing a pointer value of type 'class OSNumber *' to a scalar integer value; instead, either compare the pointer to nullptr or compare the result of calling a method on 'class OSNumber *' to get the scalar value}} |
50 | #else |
51 | if (p) {} // no-warning |
52 | if (!p) {} // no-warning |
53 | p ? 1 : 2; // no-warning |
54 | if (p == 0) {} // no-warning |
55 | #endif |
56 | (int)p; // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar integer value; did you mean to call a method on 'class OSNumber *' to get the scalar value?}} |
57 | takes_bool(p); // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar bool value; did you mean to call a method on 'class OSNumber *' to get the scalar value?}} |
58 | } |
59 | |
60 | typedef bool sugared_bool; |
61 | typedef const OSBoolean *sugared_OSBoolean; |
62 | void bad_sugared(sugared_OSBoolean p) { |
63 | sugared_bool x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} |
64 | } |
65 | |
66 | void good(const OSBoolean *p) { |
67 | bool x = p->isTrue(); // no-warning |
68 | (bool)p->isFalse(); // no-warning |
69 | if (p == kOSBooleanTrue) {} // no-warning |
70 | } |
71 | |
72 | void suppression(const OSBoolean *p) { |
73 | if (p == NULL) {} // no-warning |
74 | bool y = (p == nullptr); // no-warning |
75 | } |
76 | |
77 | // Conversion of a pointer to an intptr_t is fine. |
78 | typedef long intptr_t; |
79 | typedef unsigned long uintptr_t; |
80 | typedef long fintptr_t; // Fake, for testing the regex. |
81 | void test_intptr_t(const OSBoolean *p) { |
82 | (long)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}} |
83 | (intptr_t)p; // no-warning |
84 | (unsigned long)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}} |
85 | (uintptr_t)p; // no-warning |
86 | (fintptr_t)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}} |
87 | } |
88 | |
89 | // Test a different definition of NULL. |
90 | #undef NULL |
91 | #define NULL 0 |
92 | void test_non_pointer_NULL(const OSBoolean *p) { |
93 | if (p == NULL) {} // no-warning |
94 | } |
95 | |