[PATCH] D22968: [analyzer] A checker for macOS-specific bool- and number-like objects.

2016-10-18 Thread Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL284473: [analyzer] Add NumberObjectConversion checker. 
(authored by dergachev).

Changed prior to commit:
  https://reviews.llvm.org/D22968?vs=74969=74979#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D22968

Files:
  cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
  cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
  cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
  cfe/trunk/test/Analysis/Inputs/system-header-simulator-objc.h
  cfe/trunk/test/Analysis/number-object-conversion.cpp
  cfe/trunk/test/Analysis/number-object-conversion.m

Index: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
===
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -474,6 +474,11 @@
 
 let ParentPackage = OSX in {
 
+def NumberObjectConversionChecker : Checker<"NumberObjectConversion">,
+  InPackage,
+  HelpText<"Check for erroneous conversions of objects representing numbers into numbers">,
+  DescFile<"NumberObjectConversionChecker.cpp">;
+
 def MacOSXAPIChecker : Checker<"API">,
   InPackage,
   HelpText<"Check for proper uses of various Apple APIs">,
Index: cfe/trunk/test/Analysis/Inputs/system-header-simulator-objc.h
===
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-objc.h
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-objc.h
@@ -10,10 +10,16 @@
 
 typedef signed long CFIndex;
 typedef signed char BOOL;
+#define YES ((BOOL)1)
+#define NO ((BOOL)0)
+
 typedef unsigned long NSUInteger;
 typedef unsigned short unichar;
 typedef UInt16 UniChar;
 
+#define NULL ((void *)0)
+#define nil ((id)0)
+
 enum {
 NSASCIIStringEncoding = 1,
 NSNEXTSTEPStringEncoding = 2,
@@ -72,6 +78,7 @@
 @end
 @interface NSNumber : NSValue  - (char)charValue;
 - (id)initWithInt:(int)value;
+- (BOOL)boolValue;
 @end   @class NSString;
 @interface NSArray : NSObject   - (NSUInteger)count;
 @end  @interface NSArray (NSArrayCreation)  + (id)array;
Index: cfe/trunk/test/Analysis/number-object-conversion.cpp
===
--- cfe/trunk/test/Analysis/number-object-conversion.cpp
+++ cfe/trunk/test/Analysis/number-object-conversion.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -w -std=c++11 -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// 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
+
+#define NULL ((void *)0)
+#include "Inputs/system-header-simulator-cxx.h" // for nullptr
+
+class OSBoolean {
+public:
+  virtual bool isTrue() const;
+  virtual bool isFalse() const;
+};
+
+extern const OSBoolean *const 
+extern const OSBoolean *const 
+
+void takes_bool(bool);
+
+void bad(const OSBoolean *p) {
+#ifdef PEDANTIC
+  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}}
+  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}}
+  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}}
+  (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}}
+#endif
+  bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
+  x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
+  takes_bool(p); // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
+  takes_bool(x); // no-warning
+}
+
+typedef bool sugared_bool;
+typedef const OSBoolean *sugared_OSBoolean;
+void bad_sugared(sugared_OSBoolean p) {
+  sugared_bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
+}
+
+void good(const OSBoolean *p) {
+  bool x = p->isTrue(); // no-warning
+  (bool)p->isFalse(); // no-warning
+  if (p == kOSBooleanTrue) {} // no-warning
+}
+
+void suppression(const OSBoolean *p) {
+  if (p == NULL) {} // no-warning
+  bool y = (p == nullptr); // no-warning
+}
+
+// Conversion of a pointer to an intptr_t is fine.
+typedef 

[PATCH] D22968: [analyzer] A checker for macOS-specific bool- and number-like objects.

2016-10-18 Thread Artem Dergachev via cfe-commits
NoQ updated this revision to Diff 74969.
NoQ added a comment.

- Support conversion though function calls.
- Move "if (x == 0)" to pedantic for now (too loud).


https://reviews.llvm.org/D22968

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
  test/Analysis/Inputs/system-header-simulator-objc.h
  test/Analysis/number-object-conversion.cpp
  test/Analysis/number-object-conversion.m

Index: test/Analysis/number-object-conversion.m
===
--- /dev/null
+++ test/Analysis/number-object-conversion.m
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// 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
+
+#include "Inputs/system-header-simulator-objc.h"
+
+void takes_boolean(BOOL);
+void takes_integer(int);
+
+void bad(NSNumber *p) {
+#ifdef PEDANTIC
+  if (p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
+  if (!p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
+  (!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}}
+  (BOOL)p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; please compare the pointer to nil instead to suppress this warning}}
+  if (p == 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; please compare the pointer to nil instead to suppress this warning}}
+  if (p > 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+#endif
+  if (p == YES) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  if (p == NO) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  BOOL x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  x = (p == YES); // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  if (p == 1) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+  int y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+  y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+  takes_boolean(p); // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  takes_integer(p); // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+  takes_boolean(x); // no-warning
+  takes_integer(y); // no-warning
+}
+
+typedef NSNumber *SugaredNumber;
+void bad_sugared(SugaredNumber p) {
+  p == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+}
+
+@interface I : NSObject {
+@public
+  NSNumber *ivar;
+  NSNumber *prop;
+}
+- (NSNumber *)foo;
+@property(copy) NSNumber *prop;
+@end
+
+@implementation I
+@synthesize prop;
+@end
+
+void bad_ivar(I *i) {
+  i->ivar == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  i->prop == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  [i foo] == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+}
+
+void good(NSNumber *p) {
+  if ([p boolValue] == NO) {} // no-warning
+  if ([p boolValue] == YES) {} // no-warning
+  BOOL x = [p boolValue]; // no-warning
+}
+
+void suppression(NSNumber *p) {
+  if (p == NULL) {} // no-warning
+  if (p == nil) {} // no-warning
+}
+
+// Conversion of a pointer to an intptr_t is fine.
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long fintptr_t; // Fake, for testing the regex.
+void 

[PATCH] D22968: [analyzer] A checker for macOS-specific bool- and number-like objects.

2016-10-12 Thread Anna Zaks via cfe-commits
zaks.anna accepted this revision.
zaks.anna added inline comments.
This revision is now accepted and ready to land.



Comment at: include/clang/StaticAnalyzer/Checkers/Checkers.td:479
+  InPackage,
+  HelpText<"Check for erroneous conversions of number pointers into numbers">,
+  DescFile<"NumberObjectConversionChecker">;

"number pointers" -> "objects representing numbers"


https://reviews.llvm.org/D22968



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D22968: [analyzer] A checker for macOS-specific bool- and number-like objects.

2016-10-07 Thread Artem Dergachev via cfe-commits
NoQ updated this revision to Diff 73889.
NoQ added a comment.

- Rename test files for consistency.
- Suppress false positives on `intptr_t`.
- Add a triple to the tests to in order to stop worrying about integer types.


https://reviews.llvm.org/D22968

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
  test/Analysis/Inputs/system-header-simulator-objc.h
  test/Analysis/number-object-conversion.cpp
  test/Analysis/number-object-conversion.m

Index: test/Analysis/number-object-conversion.m
===
--- /dev/null
+++ test/Analysis/number-object-conversion.m
@@ -0,0 +1,79 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// 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
+
+#include "Inputs/system-header-simulator-objc.h"
+
+void bad(NSNumber *p) {
+#ifdef PEDANTIC
+  if (p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
+  if (!p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
+  (!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}}
+  (BOOL)p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; please compare the pointer to nil instead to suppress this warning}}
+#endif
+  if (p == YES) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  if (p == NO) {} // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  BOOL x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  x = p; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  x = (p == YES); // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  if (p == 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; please compare the pointer to nil instead to suppress this warning}}
+  if (p == 1) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+  if (p > 0) {} // expected-warning{{Converting 'NSNumber *' to a plain integer value; please compare the pointer to nil instead to suppress this warning}}
+  int y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+  y = p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+}
+
+typedef NSNumber *SugaredNumber;
+void bad_sugared(SugaredNumber p) {
+  p == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+}
+
+@interface I : NSObject {
+@public
+  NSNumber *ivar;
+  NSNumber *prop;
+}
+- (NSNumber *)foo;
+@property(copy) NSNumber *prop;
+@end
+
+@implementation I
+@synthesize prop;
+@end
+
+void bad_ivar(I *i) {
+  i->ivar == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  i->prop == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+  [i foo] == YES; // expected-warning{{Converting 'NSNumber *' to a plain BOOL value; pointer value is being used instead}}
+}
+
+void good(NSNumber *p) {
+  if ([p boolValue] == NO) {} // no-warning
+  if ([p boolValue] == YES) {} // no-warning
+  BOOL x = [p boolValue]; // no-warning
+}
+
+void suppression(NSNumber *p) {
+  if (p == NULL) {} // no-warning
+  if (p == nil) {} // no-warning
+}
+
+// Conversion of a pointer to an intptr_t is fine.
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long fintptr_t; // Fake, for testing the regex.
+void test_intptr_t(NSNumber *p) {
+  (long)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being used instead}}
+  (intptr_t)p; // no-warning
+  (unsigned long)p; // expected-warning{{Converting 'NSNumber *' to a plain integer value; pointer value is being 

Re: [PATCH] D22968: [analyzer] A checker for macOS-specific bool- and number-like objects.

2016-09-25 Thread Artem Dergachev via cfe-commits
NoQ marked an inline comment as done.
NoQ added a comment.

Ouch, seems inline answers don't automatically post themselves when you update 
the diff :o



Comment at: lib/StaticAnalyzer/Checkers/BoolConversionChecker.cpp:62
@@ +61,3 @@
+   << "' to a plain boolean value: probably a forgotten "
+   << (IsObjC ? "'[boolValue]'" : "'->isTrue()'");
+BR.EmitBasicReport(

dcoughlin wrote:
> - The '[boolValue]' thing here is weird. Maybe use '-boolValue' instead?
> - How about "Comparison between 'NSNumber *' and 'BOOL'; use -boolValue 
> instead."
> - You probably want to remove lifetime qualifiers from the type with 
> `.getUnqualifiedType()`. before printing (i.e., don't mention '__strong') in 
> the diagnostic.
> 
Yeah, noticed the lifetime qualifiers. Changed messages significantly.


Comment at: lib/StaticAnalyzer/Checkers/BoolConversionChecker.cpp:117
@@ +116,3 @@
+auto ConversionThroughComparisonM =
+binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+   hasEitherOperand(NSNumberExprM),

zaks.anna wrote:
> Can we use any binary operator here without any restrictions?
Comparisons are handled here. Assignments are handled in a different matcher. 
Arithmetic operators are either a valid pointer arithmetic (such as `+` or `-`) 
or cause compile errors (such as `*` or `/`). Bitwise ops (`&`, `>>`, etc.) - 
perhaps somebody is computing shadow memory. Logical ops - also too commonly 
intentional (typically: `if (p && [p boolValue])`). Comma operator - ouch, we 
should probably warn about the very fact that somebody uses comma operators.


Comment at: test/Analysis/bool-conversion.cpp:18
@@ +17,3 @@
+#ifdef PEDANTIC
+  if (p) {} // expected-warning{{}}
+  if (!p) {} // expected-warning{{}}

zaks.anna wrote:
> dcoughlin wrote:
> > It is generally good to include the diagnostic text in the test for the 
> > warning. This way we make sure we get the warning we expected.
> +1
> 
> Are these pedantic because we assume these are comparing the pointer and not 
> the value? Have you checked that this is a common idiom?
> 
> Same comment applies to NSNumber. If it is common practice to compare against 
> nil..
> 
> Are these pedantic because we assume these are comparing the pointer and not 
> the value? Have you checked that this is a common idiom?

I haven't checked if this is more popular or less popular than `if (p == nil)`, 
but it's clearly too popular and too often correct for a warning enabled by 
default.


Comment at: test/Analysis/bool-conversion.cpp:21
@@ +20,3 @@
+  p ? 1 : 2; // expected-warning{{}}
+  (bool)p; // expected-warning{{}}
+#endif

zaks.anna wrote:
> Why is this OK?
Will test more closely; i think this gives a lot of intentionals, but a cast to 
a non-boolean integer is clearly an error that must be reported.


Comment at: test/Analysis/bool-conversion.m:10
@@ +9,3 @@
+  if (!p) {} // expected-warning{{}}
+  if (p == YES) {} // expected-warning{{}}
+  if (p == NO) {} // expected-warning{{}}

zaks.anna wrote:
> dcoughlin wrote:
> > There is a Sema warning for `p == YES` already, right? ("comparison between 
> > pointer and integer ('NSNumber *' and 'int')")
> These tests seem to be even more relevant to OSBoolean.
> There is a Sema warning

Yep, but it is disabled with `-w`. I think it's a good idea to add `-w` to the 
run line in all analyzer tests - it often makes tests easier to read, and in 
particular we're sure that all warnings in the test are coming from the enabled 
checkers, not from other sources.


Comment at: test/Analysis/bool-conversion.m:11
@@ +10,3 @@
+  if (p == YES) {} // expected-warning{{}}
+  if (p == NO) {} // expected-warning{{}}
+  (!p) ? 1 : 2; // expected-warning{{}}

dcoughlin wrote:
> Should `p == NO` be on in non-pedantic mode, as well? It also seems to me 
> that you could warn on comparison of *any* ObjCObjectPointerType type to 
> `NO`. At a minimum it would probably be good to check for comparisons of `id` 
> to NO.
Whoops, accidental.


https://reviews.llvm.org/D22968



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D22968: [analyzer] A checker for macOS-specific bool- and number-like objects.

2016-09-24 Thread Artem Dergachev via cfe-commits
NoQ retitled this revision from "[analyzer] A checker for macOS-specific 
bool-like objects." to "[analyzer] A checker for macOS-specific bool- and 
number-like objects.".
NoQ updated the summary for this revision.
NoQ updated this revision to Diff 72392.
NoQ marked 10 inline comments as done.
NoQ added a comment.
Herald added subscribers: mgorny, beanz.

The checker now checks conversions of `NSNumber` to integer types, not just 
boolean.

To do now - a bit more time needed to test various tweaks. The current version 
of the non-pedantic checker has found a couple of good new true positives, 
being relatively silent in general. I'm keeping positives of form `x == 0` 
(where `x` is a number pointer) in non-pedantic checker, even though they have 
been reporting non-bugs, because bugs of this form have been found, and it 
seems very desirable to make the code more specific in this particular case.

To do later - consider conversions by passing NSNumber to a function that 
expects an integer, consider OSNumber and maybe CFNumber(?).


https://reviews.llvm.org/D22968

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
  test/Analysis/Inputs/system-header-simulator-objc.h
  test/Analysis/NSNumber-conversion.m
  test/Analysis/OSBoolean-conversion.cpp

Index: test/Analysis/OSBoolean-conversion.cpp
===
--- /dev/null
+++ test/Analysis/OSBoolean-conversion.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -w -std=c++11 -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -w -std=c++11 -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+
+#define NULL ((void *)0)
+#include "Inputs/system-header-simulator-cxx.h" // for nullptr
+
+class OSBoolean {
+public:
+  virtual bool isTrue() const;
+  virtual bool isFalse() const;
+};
+
+extern const OSBoolean *const 
+extern const OSBoolean *const 
+
+void bad(const OSBoolean *p) {
+#ifdef PEDANTIC
+  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}}
+  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}}
+  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}}
+  (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}}
+#endif
+  bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
+  x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
+}
+
+typedef bool sugared_bool;
+typedef const OSBoolean *sugared_OSBoolean;
+void bad_sugared(sugared_OSBoolean p) {
+  sugared_bool x = p; // expected-warning{{Converting 'const class OSBoolean *' to a plain bool value; pointer value is being used instead}}
+}
+
+void good(const OSBoolean *p) {
+  bool x = p->isTrue(); // no-warning
+  (bool)p->isFalse(); // no-warning
+  if (p == kOSBooleanTrue) {} // no-warning
+}
+
+void suppression(const OSBoolean *p) {
+  if (p == NULL) {} // no-warning
+  bool y = (p == nullptr); // no-warning
+}
+
+// Test a different definition of NULL.
+#undef NULL
+#define NULL 0
+void test_non_pointer_NULL(const OSBoolean *p) {
+  if (p == NULL) {} // no-warning
+}
Index: test/Analysis/NSNumber-conversion.m
===
--- /dev/null
+++ test/Analysis/NSNumber-conversion.m
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+// RUN: %clang_cc1 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+
+#include "Inputs/system-header-simulator-objc.h"
+
+void bad(NSNumber *p) {
+#ifdef PEDANTIC
+  if (p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to nil instead to suppress this warning}}
+  if (!p) {} // expected-warning{{Converting 'NSNumber *' to a plain boolean value for branching; please compare the pointer to