[analyzer] Don't treat calls to system headers as escaping in CheckObjCDealloc.

This prevents false negatives when a -dealloc method, for example, removes itself as
as an observer with [[NSNotificationCenter defaultCenter] removeObserver:self]. It is
unlikely that passing 'self' to a system header method will release 'self''s instance
variables, so this is unlikely to produce false positives.

A challenge here is that while CheckObjCDealloc no longer treats these calls as
escaping, the rest of the analyzer still does. In particular, this means that loads
from the same instance variable before and after a call to a system header will
result in different symbols being loaded by the region store. To account for this,
the checker now treats different ivar symbols with the same instance and ivar decl as
the same for the purpose of release checking and more eagerly removes a release
requirement when an instance variable is assumed to be nil. This was not needed before
because when an ivar escaped its release requirement was always removed -- now the
requirement is not removed for calls to system headers.

llvm-svn: 262261
diff --git a/clang/test/Analysis/DeallocMissingRelease.m b/clang/test/Analysis/DeallocMissingRelease.m
index c7769db..bb67e436 100644
--- a/clang/test/Analysis/DeallocMissingRelease.m
+++ b/clang/test/Analysis/DeallocMissingRelease.m
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -verify %s
 // RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -triple x86_64-apple-darwin10 -fobjc-arc -fobjc-runtime-has-weak -verify %s
 
-#define nil ((id)0)
+#include "Inputs/system-header-simulator-for-objc-dealloc.h"
 
 #define NON_ARC !__has_feature(objc_arc)
 
@@ -16,22 +16,6 @@
   // expected-no-diagnostics
 #endif
 
-typedef signed char BOOL;
-@protocol NSObject
-- (BOOL)isEqual:(id)object;
-- (Class)class;
-@end
-
-@interface NSObject <NSObject> {}
-+ (instancetype)alloc;
-- (void)dealloc;
-- (id)init;
-- (id)retain;
-- (oneway void)release;
-@end
-
-typedef struct objc_selector *SEL;
-
 // Do not warn about missing release in -dealloc for ivars.
 
 @interface MyIvarClass1 : NSObject {
@@ -447,6 +431,50 @@
 }
 @end
 
+
+// Don't treat calls to system headers as escapes
+
+@interface ClassWhereSelfEscapesViaCallToSystem : NSObject
+@property (retain) NSObject *ivar1;
+@property (retain) NSObject *ivar2;
+@property (retain) NSObject *ivar3;
+@property (retain) NSObject *ivar4;
+@property (retain) NSObject *ivar5;
+@property (retain) NSObject *ivar6;
+@end
+
+@implementation ClassWhereSelfEscapesViaCallToSystem
+- (void)dealloc; {
+#if NON_ARC
+  [_ivar2 release];
+  if (_ivar3) {
+    [_ivar3 release];
+  }
+#endif
+
+  [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+#if NON_ARC
+  [_ivar4 release];
+
+  if (_ivar5) {
+    [_ivar5 release];
+  }
+#endif
+
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+#if NON_ARC
+  if (_ivar6) {
+    [_ivar6 release];
+  }
+
+  [super dealloc];  // expected-warning {{The '_ivar1' ivar in 'ClassWhereSelfEscapesViaCallToSystem' was retained by a synthesized property but not released before '[super dealloc]'}}
+#endif
+}
+@end
+
 // Don't warn when value escapes.
 
 @interface ClassWhereIvarValueEscapes : NSObject
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h b/clang/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h
new file mode 100644
index 0000000..0b9888a
--- /dev/null
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h
@@ -0,0 +1,29 @@
+#pragma clang system_header
+
+#define nil ((id)0)
+
+typedef signed char BOOL;
+@protocol NSObject
+- (BOOL)isEqual:(id)object;
+- (Class)class;
+@end
+
+@interface NSObject <NSObject> {}
++ (instancetype)alloc;
+- (void)dealloc;
+- (id)init;
+- (id)retain;
+- (oneway void)release;
+@end
+
+@interface NSRunLoop : NSObject
++ (NSRunLoop *)currentRunLoop;
+- (void)cancelPerformSelectorsWithTarget:(id)target;
+@end
+
+@interface NSNotificationCenter : NSObject
++ (NSNotificationCenter *)defaultCenter;
+- (void)removeObserver:(id)observer;
+@end
+
+typedef struct objc_selector *SEL;