1*184c6242SDominic Chen // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -w -std=c++11 -analyzer-checker=osx.NumberObjectConversion %s -verify 2*184c6242SDominic Chen // 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 3940c770dSArtem Dergachev 4940c770dSArtem Dergachev #define NULL ((void *)0) 5940c770dSArtem Dergachev #include "Inputs/system-header-simulator-cxx.h" // for nullptr 6940c770dSArtem Dergachev 7940c770dSArtem Dergachev class OSBoolean { 8940c770dSArtem Dergachev public: 9940c770dSArtem Dergachev virtual bool isTrue() const; 10940c770dSArtem Dergachev virtual bool isFalse() const; 11940c770dSArtem Dergachev }; 12940c770dSArtem Dergachev 13e14d8818SArtem Dergachev class OSNumber { 14e14d8818SArtem Dergachev public: 15e14d8818SArtem Dergachev virtual bool isEqualTo(const OSNumber *); 16e14d8818SArtem Dergachev virtual unsigned char unsigned8BitValue() const; 17e14d8818SArtem Dergachev virtual unsigned short unsigned16BitValue() const; 18e14d8818SArtem Dergachev virtual unsigned int unsigned32BitValue() const; 19e14d8818SArtem Dergachev virtual unsigned long long unsigned64BitValue() const; 20e14d8818SArtem Dergachev }; 21e14d8818SArtem Dergachev 22940c770dSArtem Dergachev extern const OSBoolean *const &kOSBooleanFalse; 23940c770dSArtem Dergachev extern const OSBoolean *const &kOSBooleanTrue; 24940c770dSArtem Dergachev 25940c770dSArtem Dergachev void takes_bool(bool); 26940c770dSArtem Dergachev bad_boolean(const OSBoolean * p)27e14d8818SArtem Dergachevvoid bad_boolean(const OSBoolean *p) { 28940c770dSArtem Dergachev #ifdef PEDANTIC 29e14d8818SArtem Dergachev 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()}} 30e14d8818SArtem Dergachev 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()}} 31e14d8818SArtem Dergachev 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()}} 32e14d8818SArtem Dergachev #else 33e14d8818SArtem Dergachev if (p) {} // no-warning 34e14d8818SArtem Dergachev if (!p) {} // no-warning 35e14d8818SArtem Dergachev p ? 1 : 2; // no-warning 36940c770dSArtem Dergachev #endif 37e14d8818SArtem Dergachev (bool)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} 38e14d8818SArtem Dergachev bool x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} 39e14d8818SArtem Dergachev x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} 40e14d8818SArtem Dergachev takes_bool(p); // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}} 41940c770dSArtem Dergachev takes_bool(x); // no-warning 42940c770dSArtem Dergachev } 43940c770dSArtem Dergachev bad_number(const OSNumber * p)44e14d8818SArtem Dergachevvoid bad_number(const OSNumber *p) { 45e14d8818SArtem Dergachev #ifdef PEDANTIC 46e14d8818SArtem Dergachev 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}} 47e14d8818SArtem Dergachev 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}} 48e14d8818SArtem Dergachev 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}} 49e14d8818SArtem Dergachev 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}} 50e14d8818SArtem Dergachev #else 51e14d8818SArtem Dergachev if (p) {} // no-warning 52e14d8818SArtem Dergachev if (!p) {} // no-warning 53e14d8818SArtem Dergachev p ? 1 : 2; // no-warning 54e14d8818SArtem Dergachev if (p == 0) {} // no-warning 55e14d8818SArtem Dergachev #endif 56e14d8818SArtem Dergachev (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?}} 57e14d8818SArtem Dergachev 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?}} 58e14d8818SArtem Dergachev } 59e14d8818SArtem Dergachev 60940c770dSArtem Dergachev typedef bool sugared_bool; 61940c770dSArtem Dergachev typedef const OSBoolean *sugared_OSBoolean; bad_sugared(sugared_OSBoolean p)62940c770dSArtem Dergachevvoid bad_sugared(sugared_OSBoolean p) { 63e14d8818SArtem Dergachev 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()?}} 64940c770dSArtem Dergachev } 65940c770dSArtem Dergachev good(const OSBoolean * p)66940c770dSArtem Dergachevvoid good(const OSBoolean *p) { 67940c770dSArtem Dergachev bool x = p->isTrue(); // no-warning 68940c770dSArtem Dergachev (bool)p->isFalse(); // no-warning 69940c770dSArtem Dergachev if (p == kOSBooleanTrue) {} // no-warning 70940c770dSArtem Dergachev } 71940c770dSArtem Dergachev suppression(const OSBoolean * p)72940c770dSArtem Dergachevvoid suppression(const OSBoolean *p) { 73940c770dSArtem Dergachev if (p == NULL) {} // no-warning 74940c770dSArtem Dergachev bool y = (p == nullptr); // no-warning 75940c770dSArtem Dergachev } 76940c770dSArtem Dergachev 77940c770dSArtem Dergachev // Conversion of a pointer to an intptr_t is fine. 78940c770dSArtem Dergachev typedef long intptr_t; 79940c770dSArtem Dergachev typedef unsigned long uintptr_t; 80940c770dSArtem Dergachev typedef long fintptr_t; // Fake, for testing the regex. test_intptr_t(const OSBoolean * p)81940c770dSArtem Dergachevvoid test_intptr_t(const OSBoolean *p) { 82e14d8818SArtem Dergachev (long)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}} 83940c770dSArtem Dergachev (intptr_t)p; // no-warning 84e14d8818SArtem Dergachev (unsigned long)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}} 85940c770dSArtem Dergachev (uintptr_t)p; // no-warning 86e14d8818SArtem Dergachev (fintptr_t)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}} 87940c770dSArtem Dergachev } 88940c770dSArtem Dergachev 89940c770dSArtem Dergachev // Test a different definition of NULL. 90940c770dSArtem Dergachev #undef NULL 91940c770dSArtem Dergachev #define NULL 0 test_non_pointer_NULL(const OSBoolean * p)92940c770dSArtem Dergachevvoid test_non_pointer_NULL(const OSBoolean *p) { 93940c770dSArtem Dergachev if (p == NULL) {} // no-warning 94940c770dSArtem Dergachev } 95