[analyzer] Extend NoStoreFuncVisitor to insert a note on IVars

The note is added in the following situation:

 - We are throwing a nullability-related warning on an IVar
 - The path goes through a method which *could have* (syntactically
   determined) written into that IVar, but did not

rdar://42444460

Differential Revision: https://reviews.llvm.org/D49689

llvm-svn: 338149
diff --git a/clang/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/clang/test/Analysis/diagnostics/no-store-func-path-notes.cpp
index b96dc4c..17ec96a 100644
--- a/clang/test/Analysis/diagnostics/no-store-func-path-notes.cpp
+++ b/clang/test/Analysis/diagnostics/no-store-func-path-notes.cpp
@@ -97,6 +97,14 @@
   int x;
   int y;
   C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}}
+
+  C(int pX, int pY, bool Flag) {
+    x = pX;
+    if (Flag) // expected-note{{Assuming 'Flag' is not equal to 0}}
+              // expected-note@-1{{Taking true branch}}
+      return; // expected-note{{Returning without writing to 'this->y'}}
+    y = pY;
+  }
 };
 
 int use_constructor() {
@@ -106,6 +114,15 @@
               // expected-warning@-1{{Undefined or garbage value returned to caller}}
 }
 
+int coin();
+
+int use_other_constructor() {
+  C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}}
+                     // expected-note@-1{{Returning from constructor for 'C'}}
+  return c.y; // expected-note{{Undefined or garbage value returned to caller}}
+              // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
 struct D {
   void initialize(int *);
 };
@@ -122,8 +139,6 @@
                                 // expected-warning@-1{{Undefined or garbage value returned to caller}}
 }
 
-int coin();
-
 struct S2 {
   int x;
 };
diff --git a/clang/test/Analysis/diagnostics/no-store-func-path-notes.m b/clang/test/Analysis/diagnostics/no-store-func-path-notes.m
index 3ae97ef..51d1515 100644
--- a/clang/test/Analysis/diagnostics/no-store-func-path-notes.m
+++ b/clang/test/Analysis/diagnostics/no-store-func-path-notes.m
@@ -1,6 +1,10 @@
-// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core,nullability -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s
 
-@interface I
+#include "../Inputs/system-header-simulator-for-nullability.h"
+
+extern int coin();
+
+@interface I : NSObject
 - (int)initVar:(int *)var param:(int)param;
 @end
 
@@ -44,3 +48,30 @@
   }();
   return z;
 }
+
+extern void expectNonNull(NSString * _Nonnull a);
+
+@interface A : NSObject
+- (void) func;
+- (void) initAMaybe;
+@end
+
+@implementation A {
+  NSString * a;
+}
+
+- (void) initAMaybe {
+  if (coin()) // expected-note{{Assuming the condition is false}}
+              // expected-note@-1{{Taking false branch}}
+    a = @"string";
+} // expected-note{{Returning without writing to 'self->a'}}
+
+- (void) func {
+  a = nil; // expected-note{{nil object reference stored to 'a'}}
+  [self initAMaybe]; // expected-note{{Calling 'initAMaybe'}}
+                     // expected-note@-1{{Returning from 'initAMaybe'}}
+  expectNonNull(a); // expected-warning{{nil passed to a callee that requires a non-null 1st parameter}}
+                    // expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}}
+}
+
+@end