Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -159,6 +159,166 @@
   return std::move(P);
 }
 
+namespace {
+
+/// Put a diagnostic on return statement of the inlined function \p F
+/// iff the region of interest \p R was passed to \p F,
+/// but not stored into inside \p F.
+class NoStoreFuncVisitor final
+    : public BugReporterVisitorImpl<NoStoreFuncVisitor> {
+
+  const SubRegion *RegionOfInterest;
+
+public:
+  NoStoreFuncVisitor(const SubRegion *R) : RegionOfInterest(R) {}
+
+  void Profile(llvm::FoldingSetNodeID &ID) const override {
+    static int Tag = 0;
+    ID.AddPointer(&Tag);
+  }
+
+  std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+                                                 const ExplodedNode *PrevN,
+                                                 BugReporterContext &BRC,
+                                                 BugReport &BR) override {
+    const LocationContext *Ctx = N->getLocationContext();
+    const StackFrameContext *SCtx = Ctx->getCurrentStackFrame();
+    ProgramStateRef State = N->getState();
+    auto CEB = N->getLocationAs<CallExitBegin>();
+
+    if (!CEB)
+      return nullptr;
+
+    CallEventRef<> Call =
+        BRC.getStateManager().getCallEventManager().getCaller(SCtx, State);
+
+    const LocationContext *ContextAtCallsite = SCtx->getParent();
+    for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
+      const ParmVarDecl *PVD = Call->parameters()[I];
+      const MemRegion *R = Call->getArgSVal(I).getAsRegion();
+      if (RegionOfInterest->isSubRegionOf(R) &&
+          !isPointerToConst(PVD->getType()) &&
+          !wasRegionModifiedInsideFunction(RegionOfInterest, N,
+                                           ContextAtCallsite))
+        return notModifiedDiagnostics(Ctx, BRC, *CEB, Call, PVD, R);
+    }
+
+    return nullptr;
+  }
+
+private:
+  /// \p ValueAtReturn Value of \p R at the time of return.
+  /// \return Whether \p R was modified inside the function
+  /// starting at \p N.
+  bool
+  wasRegionModifiedInsideFunction(const MemRegion *R,
+                                  const ExplodedNode *ReturnNode,
+                                  const LocationContext *ContextAtCallsite) {
+
+    ProgramStateRef ReturnState = ReturnNode->getState();
+    SVal ValueAtReturn = ReturnState->getSVal(R);
+    SValBuilder &Builder = ReturnState->getStateManager().getSValBuilder();
+    const ExplodedNode *N = ReturnNode;
+    while (N) {
+      if (N->getLocationAs<CallEnter>() &&
+          N->getLocationContext() == ContextAtCallsite)
+        return false;
+
+      // Writing into region of interest.
+      if (auto PS = N->getLocationAs<PostStmt>())
+        if (auto *BO = PS->getStmtAs<BinaryOperator>())
+          if (BO->isAssignmentOp() &&
+              N->getSVal(BO->getLHS()).getAsRegion() == RegionOfInterest)
+            return true;
+
+      // SVal after is different from a state before.
+      if (!Builder.areEqual(ReturnState, N->getState()->getSVal(R),
+                            ValueAtReturn))
+        return true;
+
+      N = N->getFirstPred();
+    }
+    return false;
+  }
+
+  /// \return whether \p Ty points to a const type, or is a const reference.
+  bool isPointerToConst(QualType Ty) {
+    return !Ty->getPointeeType().isNull() &&
+           Ty->getPointeeType().isConstQualified();
+  }
+
+  std::shared_ptr<PathDiagnosticPiece>
+  notModifiedDiagnostics(const LocationContext *Ctx, BugReporterContext &BRC,
+                         CallExitBegin CEB, CallEventRef<> Call,
+                         const ParmVarDecl *PVD, const MemRegion *ArgRegion) {
+
+    PathDiagnosticLocation L;
+    if (const ReturnStmt *RS = CEB.getReturnStmt()) {
+      L = PathDiagnosticLocation::createBegin(RS, BRC.getSourceManager(), Ctx);
+    } else {
+      L = PathDiagnosticLocation(
+          Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(),
+          BRC.getSourceManager());
+    }
+
+    SmallString<256> sbuf;
+    llvm::raw_svector_ostream os(sbuf);
+    os << "Returning without writing to '";
+
+    SmallString<128> RegionPrettyName;
+    const PrintingPolicy &PP = BRC.getASTContext().getPrintingPolicy();
+    bool out = prettyPrintRegionName(PVD, ArgRegion, RegionPrettyName, PP);
+    if (!out) {
+
+      // Fallback if we have failed to pretty-print.
+      PVD->printQualifiedName(os);
+    } else {
+      os << RegionPrettyName;
+    }
+    os << "'";
+    return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
+  }
+
+  /// Pretty-print region to \p RegionPrettyName
+  /// \return whether printing has succeeded
+  bool prettyPrintRegionName(const ParmVarDecl *PVD, const MemRegion *ArgRegion,
+                             SmallString<128> &RegionPrettyName,
+                             const PrintingPolicy &PP) {
+
+    llvm::raw_svector_ostream os(RegionPrettyName);
+    SmallVector<const MemRegion *, 5> Regions;
+    const MemRegion *R = RegionOfInterest;
+    Regions.push_back(R);
+    while (R != ArgRegion) {
+      R = dyn_cast<SubRegion>(R)->getSuperRegion();
+      Regions.push_back(R);
+    }
+
+    const char *Sep = PVD->getType()->isReferenceType() ? "." : "->";
+    for (auto I = Regions.rbegin(), E = Regions.rend(); I != E; ++I) {
+      R = *I;
+      if (R == ArgRegion) {
+        PVD->printQualifiedName(os);
+      } else if (auto *FR = dyn_cast<FieldRegion>(R)) {
+        os << Sep;
+        FR->getDecl()->getDeclName().print(os, PP);
+        Sep = ".";
+
+      } else if (auto *CXXR = dyn_cast<CXXBaseObjectRegion>(R)) {
+
+        // Just keep going up to the base region.
+        continue;
+      } else {
+
+        // Pattern matching failed, use dumber printing.
+        return false;
+      }
+    }
+    return true;
+  }
+};
+
+} // namespace
 
 namespace {
 /// Emits an extra note at the return statement of an interesting stack frame.
@@ -1128,6 +1288,9 @@
     if (R) {
       // Mark both the variable region and its contents as interesting.
       SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
+      assert(isa<SubRegion>(R));
+      report.addVisitor(
+          llvm::make_unique<NoStoreFuncVisitor>(R->getAs<SubRegion>()));
 
       report.markInteresting(R);
       report.markInteresting(V);
Index: test/Analysis/diagnostics/undef-value-param.c
===================================================================
--- test/Analysis/diagnostics/undef-value-param.c
+++ test/Analysis/diagnostics/undef-value-param.c
@@ -12,7 +12,7 @@
     if (c)
            //expected-note@-1{{Assuming 'c' is not equal to 0}}
            //expected-note@-2{{Taking true branch}}
-        return;
+           return; // expected-note{{Returning without writing to 'x'}}
     *x = 5;
 }
 
@@ -51,7 +51,7 @@
   if (x <= 0) //expected-note {{Taking true branch}}
               //expected-note@-1 {{Assuming 'x' is <= 0}}
 
-    return;
+    return; //expected-note{{Returning without writing to 'X->f1'}}
   X->f1 = getValidPtr();
 }
 double testPassingParentRegionStruct(int x) {
@@ -293,12 +293,12 @@
 // CHECK-NEXT:          <array>
 // CHECK-NEXT:           <dict>
 // CHECK-NEXT:            <key>line</key><integer>15</integer>
-// CHECK-NEXT:            <key>col</key><integer>9</integer>
+// CHECK-NEXT:            <key>col</key><integer>12</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:           <dict>
 // CHECK-NEXT:            <key>line</key><integer>15</integer>
-// CHECK-NEXT:            <key>col</key><integer>14</integer>
+// CHECK-NEXT:            <key>col</key><integer>17</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:          </array>
@@ -309,6 +309,20 @@
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
+// CHECK-NEXT:       <key>line</key><integer>15</integer>
+// CHECK-NEXT:       <key>col</key><integer>12</integer>
+// CHECK-NEXT:       <key>file</key><integer>0</integer>
+// CHECK-NEXT:      </dict>
+// CHECK-NEXT:      <key>depth</key><integer>1</integer>
+// CHECK-NEXT:      <key>extended_message</key>
+// CHECK-NEXT:      <string>Returning without writing to &apos;x&apos;</string>
+// CHECK-NEXT:      <key>message</key>
+// CHECK-NEXT:      <string>Returning without writing to &apos;x&apos;</string>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>event</string>
+// CHECK-NEXT:      <key>location</key>
+// CHECK-NEXT:      <dict>
 // CHECK-NEXT:       <key>line</key><integer>22</integer>
 // CHECK-NEXT:       <key>col</key><integer>5</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
@@ -1046,6 +1060,20 @@
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
+// CHECK-NEXT:       <key>line</key><integer>54</integer>
+// CHECK-NEXT:       <key>col</key><integer>5</integer>
+// CHECK-NEXT:       <key>file</key><integer>0</integer>
+// CHECK-NEXT:      </dict>
+// CHECK-NEXT:      <key>depth</key><integer>1</integer>
+// CHECK-NEXT:      <key>extended_message</key>
+// CHECK-NEXT:      <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
+// CHECK-NEXT:      <key>message</key>
+// CHECK-NEXT:      <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>event</string>
+// CHECK-NEXT:      <key>location</key>
+// CHECK-NEXT:      <dict>
 // CHECK-NEXT:       <key>line</key><integer>60</integer>
 // CHECK-NEXT:       <key>col</key><integer>3</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
Index: test/Analysis/diagnostics/undef-value-param.m
===================================================================
--- test/Analysis/diagnostics/undef-value-param.m
+++ test/Analysis/diagnostics/undef-value-param.m
@@ -69,7 +69,7 @@
              //expected-note@-1{{Assuming 'err' is not equal to 0}}
              //expected-note@-2{{Taking true branch}}
     CFRelease(ref);
-    return;
+    return; // expected-note{{Returning without writing to 'storeRef'}}
   }
   *storeRef = ref;
 }
@@ -831,6 +831,54 @@
 // CHECK-NEXT:       </array>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>control</string>
+// CHECK-NEXT:      <key>edges</key>
+// CHECK-NEXT:       <array>
+// CHECK-NEXT:        <dict>
+// CHECK-NEXT:         <key>start</key>
+// CHECK-NEXT:          <array>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>71</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>71</integer>
+// CHECK-NEXT:            <key>col</key><integer>13</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:          </array>
+// CHECK-NEXT:         <key>end</key>
+// CHECK-NEXT:          <array>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>72</integer>
+// CHECK-NEXT:            <key>col</key><integer>5</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:           <dict>
+// CHECK-NEXT:            <key>line</key><integer>72</integer>
+// CHECK-NEXT:            <key>col</key><integer>10</integer>
+// CHECK-NEXT:            <key>file</key><integer>0</integer>
+// CHECK-NEXT:           </dict>
+// CHECK-NEXT:          </array>
+// CHECK-NEXT:        </dict>
+// CHECK-NEXT:       </array>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>kind</key><string>event</string>
+// CHECK-NEXT:      <key>location</key>
+// CHECK-NEXT:      <dict>
+// CHECK-NEXT:       <key>line</key><integer>72</integer>
+// CHECK-NEXT:       <key>col</key><integer>5</integer>
+// CHECK-NEXT:       <key>file</key><integer>0</integer>
+// CHECK-NEXT:      </dict>
+// CHECK-NEXT:      <key>depth</key><integer>1</integer>
+// CHECK-NEXT:      <key>extended_message</key>
+// CHECK-NEXT:      <string>Returning without writing to &apos;storeRef&apos;</string>
+// CHECK-NEXT:      <key>message</key>
+// CHECK-NEXT:      <string>Returning without writing to &apos;storeRef&apos;</string>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>kind</key><string>event</string>
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
Index: test/Analysis/no-store-func-path-notes.mm
===================================================================
--- /dev/null
+++ test/Analysis/no-store-func-path-notes.mm
@@ -0,0 +1,310 @@
+// RUN: %clang_analyze_cc1 -x objective-c++ -analyzer-checker=core -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s
+
+namespace C_TEST {
+
+int initializer1(int *p, int x) {
+  if (x) { // expected-note{{Taking false branch}}
+    *p = 1;
+    return 0;
+  } else {
+    return 1; // expected-note {{Returning without writing to 'p'}}
+  }
+}
+
+int param_not_initialized_by_func() {
+  int p;                         // expected-note {{'p' declared without an initial value}}
+  int out = initializer1(&p, 0); // expected-note{{Calling 'initializer1'}}
+                                 // expected-note@-1{{Returning from 'initializer1'}}
+  return p;                      // expected-note{{Undefined or garbage value returned to caller}}
+                                 // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+int param_initialized_properly() {
+  int p;
+  int out = initializer1(&p, 1);
+  return p; //no-warning
+}
+
+static int global;
+
+int initializer2(int **p, int x) {
+  if (x) { // expected-note{{Taking false branch}}
+    *p = &global;
+    return 0;
+  } else {
+    return 1; // expected-note {{Returning without writing to 'p'}}
+  }
+}
+
+int param_not_written_into_by_func() {
+  int *p = 0;                    // expected-note{{'p' initialized to a null pointer value}}
+  int out = initializer2(&p, 0); // expected-note{{Calling 'initializer2'}}
+                                 // expected-note@-1{{Returning from 'initializer2'}}
+  return *p;                     // expected-warning{{Dereference of null pointer (loaded from variable 'p')}}
+                                 // expected-note@-1{{Dereference of null pointer (loaded from variable 'p')}}
+}
+
+void initializer3(int *p, int param) {
+  if (param) // expected-note{{Taking false branch}}
+    *p = 0;
+} // expected-note{{Returning without writing to 'p'}}
+
+int param_written_into_by_void_func() {
+  int p;               // expected-note{{'p' declared without an initial value}}
+  initializer3(&p, 0); // expected-note{{Calling 'initializer3'}}
+                       // expected-note@-1{{Returning from 'initializer3'}}
+  return p;            // expected-warning{{Undefined or garbage value returned to caller}}
+                       // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void initializer4(int *p, int param) {
+  if (param) // expected-note{{Taking false branch}}
+    *p = 0;
+} // expected-note{{Returning without writing to 'p'}}
+
+void initializer5(int *p, int param) {
+  if (!param) // expected-note{{Taking false branch}}
+    *p = 0;
+} // expected-note{{Returning without writing to 'p'}}
+
+int multi_init_tries_func() {
+  int p;               // expected-note{{'p' declared without an initial value}}
+  initializer4(&p, 0); // expected-note{{Calling 'initializer4'}}
+                       // expected-note@-1{{Returning from 'initializer4'}}
+  initializer5(&p, 1); // expected-note{{Calling 'initializer5'}}
+                       // expected-note@-1{{Returning from 'initializer5'}}
+  return p;            // expected-warning{{Undefined or garbage value returned to caller}}
+                       // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+int initializer6(const int *p) {
+  return 0;
+}
+
+int no_msg_on_const() {
+  int p; // expected-note{{'p' declared without an initial value}}
+  initializer6(&p);
+  return p; // expected-warning{{Undefined or garbage value returned to caller}}
+            // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct S {
+  int x;
+};
+
+int initializer7(S *s, int param) {
+  if (param) { // expected-note{{Taking false branch}}
+    s->x = 0;
+    return 0;
+  }
+  return 1; // expected-note{{Returning without writing to 's->x'}}
+}
+
+int initialize_struct_field() {
+  S local;
+  initializer7(&local, 0); // expected-note{{Calling 'initializer7'}}
+                           // expected-note@-1{{Returning from 'initializer7'}}
+  return local.x;          // expected-warning{{Undefined or garbage value returned to caller}}
+                           // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void nullwriter(int **p) {
+  *p = 0; // expected-note{{Null pointer value stored to 'p'}}
+} // no extra note
+
+int usage() {
+  int x = 0;
+  int *p = &x;
+  nullwriter(&p); // expected-note{{Calling 'nullwriter'}}
+                  // expected-note@-1{{Returning from 'nullwriter'}}
+  return *p;      // expected-warning{{Dereference of null pointer (loaded from variable 'p')}}
+                  // expected-note@-1{{Dereference of null pointer (loaded from variable 'p')}}
+}
+
+struct A {
+  int x;
+  int y;
+};
+
+void partial_initializer(A *a) {
+  a->x = 0;
+} // expected-note{{Returning without writing to 'a->y'}}
+
+int use_partial_initializer() {
+  A a;
+  partial_initializer(&a); // expected-note{{Calling 'partial_initializer'}}
+                           // expected-note@-1{{Returning from 'partial_initializer'}}
+  return a.y;              // expected-warning{{Undefined or garbage value returned to caller}}
+                           // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct B {
+  int x;
+  int y;
+};
+
+struct C {
+  B b;
+};
+
+void partial_nested_initializer(C *c) {
+  c->b.x = 0;
+} // expected-note{{Returning without writing to 'c->b.y'}}
+
+int use_partial_nested_initializer() {
+  B localB;
+  C localC;
+  localC.b = localB;
+  partial_nested_initializer(&localC); // expected-note{{Calling 'partial_nested_initializer'}}
+                                       // expected-note@-1{{Returning from 'partial_nested_initializer'}}
+  return localC.b.y;                   // expected-warning{{Undefined or garbage value returned to caller}}
+                                       // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+} // end namespace C_TEST
+
+namespace CPP_TEST {
+
+int initializer1(int &p, int x) {
+  if (x) { // expected-note{{Taking false branch}}
+    p = 1;
+    return 0;
+  } else {
+    return 1; // expected-note {{Returning without writing to 'p'}}
+  }
+}
+
+int param_not_initialized_by_func() {
+  int p;                        // expected-note {{'p' declared without an initial value}}
+  int out = initializer1(p, 0); // expected-note{{Calling 'initializer1'}}
+                                // expected-note@-1{{Returning from 'initializer1'}}
+  return p;                     // expected-note{{Undefined or garbage value returned to caller}}
+                                // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct S {
+  int initialize(int *p, int param) {
+    if (param) { //expected-note{{Taking false branch}}
+      *p = 1;
+      return 1;
+    }
+    return 0; // expected-note{{Returning without writing to 'p'}}
+  }
+};
+
+int use(S *s) {
+  int p;                //expected-note{{'p' declared without an initial value}}
+  s->initialize(&p, 0); //expected-note{{Calling 'S::initialize'}}
+                        //expected-note@-1{{Returning from 'S::initialize'}}
+  return p;             // expected-warning{{Undefined or garbage value returned to caller}}
+                        // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+int initializer2(const int &p) {
+  return 0;
+}
+
+int no_msg_const_ref() {
+  int p; //expected-note{{'p' declared without an initial value}}
+  initializer2(p);
+  return p; // expected-warning{{Undefined or garbage value returned to caller}}
+            // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+void nested() {}
+void init_in_nested_func(int **x) {
+  *x = 0; // expected-note{{Null pointer value stored to 'y'}}
+  nested();
+} // no-note
+
+int call_init_nested() {
+  int x = 0;
+  int *y = &x;
+  init_in_nested_func(&y); // expected-note{{Calling 'init_in_nested_func'}}
+                           // expected-note@-1{{Returning from 'init_in_nested_func'}}
+  return *y;               //expected-warning{{Dereference of null pointer (loaded from variable 'y')}}
+                           //expected-note@-1{{Dereference of null pointer (loaded from variable 'y')}}
+}
+
+struct A {
+  int x;
+  int y;
+};
+
+void partial_init_by_reference(A &a) {
+  a.x = 0;
+} // expected-note {{Returning without writing to 'a.y'}}
+
+int use_partial_init_by_reference() {
+  A a;
+  partial_init_by_reference(a); // expected-note{{Calling 'partial_init_by_reference'}}
+                                // expected-note@-1{{Returning from 'partial_init_by_reference'}}
+  return a.y;                   // expected-warning{{Undefined or garbage value returned to caller}}
+                                // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+struct B : A {
+};
+
+void partially_init_inherited_struct(B *b) {
+  b->x = 0;
+} // expected-note{{Returning without writing to 'b->y'}}
+
+int use_partially_init_inherited_struct() {
+  B b;
+  partially_init_inherited_struct(&b); // expected-note{{Calling 'partially_init_inherited_struct'}}
+                                       // expected-note@-1{{Returning from 'partially_init_inherited_struct'}}
+  return b.y;                          // expected-warning{{Undefined or garbage value returned to caller}}
+                                       // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+} // end namespace CPP_TEST
+
+@interface I
+- (int)initVar:(int *)var param:(int)param;
+@end
+
+@implementation I
+- (int)initVar:(int *)var param:(int)param {
+  if (param) { // expected-note{{Taking false branch}}
+    *var = 1;
+    return 0;
+  }
+  return 1; // expected-note{{Returning without writing to 'var'}}
+}
+@end
+
+namespace OBJCPP_TEST {
+
+int foo(I *i) {
+  int x;                            //expected-note{{'x' declared without an initial value}}
+  int out = [i initVar:&x param:0]; //expected-note{{Calling 'initVar:param:'}}
+                                    //expected-note@-1{{Returning from 'initVar:param:'}}
+  if (out)                          // expected-note{{Taking true branch}}
+    return x;                       //expected-warning{{Undefined or garbage value returned to caller}}
+                                    //expected-note@-1{{Undefined or garbage value returned to caller}}
+  return 0;
+}
+
+int initializer1(int *p, int x) {
+  if (x) { // expected-note{{Taking false branch}}
+    *p = 1;
+    return 0;
+  } else {
+    return 1; // expected-note {{Returning without writing to 'p'}}
+  }
+}
+
+int initFromBlock() {
+  __block int z;
+  ^{                     // expected-note {{Calling anonymous block}}
+    int p;               // expected-note{{'p' declared without an initial value}}
+    initializer1(&p, 0); // expected-note{{Calling 'initializer1'}}
+                         // expected-note@-1{{Returning from 'initializer1'}}
+    z = p;               // expected-warning{{Assigned value is garbage or undefined}}
+                         // expected-note@-1{{Assigned value is garbage or undefined}}
+  }();
+  return z;
+}
+
+} // end namespace OBJCPP_TEST