diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 8b99508..dcbb7f5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -8589,10 +8589,30 @@ static bool IsReadonlyMessage(Expr *E, Sema &S) {
   return Base->getMethodDecl() != nullptr;
 }
 
+enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda };
+
+/// \brief Returns whether the first byval capture for \p Var was a block or
+/// lambda.
+static NonConstCaptureKind getOutermostByvalCaptureKind(Sema &S, VarDecl *Var) {
+  for (FunctionScopeInfo *FSI : S.FunctionScopes) {
+    if (!isa<CapturingScopeInfo>(FSI) ||   // Skip non-capturing scopes
+        isa<CapturedRegionScopeInfo>(FSI)) // CapturedDecl always captures byref
+      continue;
+
+    auto *CSI = cast<CapturingScopeInfo>(FSI);
+    if (!CSI->isCaptured(Var))
+      continue; // Decl for Var is enclosed, not captured. Skip.
+
+    CapturingScopeInfo::Capture &Capture = CSI->getCapture(Var);
+    if (Capture.isCopyCapture())
+      return isa<BlockScopeInfo>(CSI) ? NCCK_Block : NCCK_Lambda;
+  }
+  llvm_unreachable("missing copy capture for Var");
+}
+
 /// Is the given expression (which must be 'const') a reference to a
 /// variable which was originally non-const, but which has become
 /// 'const' due to being captured within a block?
-enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda };
 static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
   assert(E->isLValue() && E->getType().isConstQualified());
   E = E->IgnoreParens();
@@ -8608,16 +8628,11 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
   if (var->getType().isConstQualified()) return NCCK_None;
   assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
 
-  // Decide whether the first capture was for a block or a lambda.
-  DeclContext *DC = S.CurContext, *Prev = nullptr;
-  while (DC != var->getDeclContext()) {
-    Prev = DC;
-    DC = DC->getParent();
-  }
-  // Unless we have an init-capture, we've gone one step too far.
-  if (!var->isInitCapture())
-    DC = Prev;
-  return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
+  if (var->isInitCapture())
+    return NCCK_Lambda;
+
+  // Decide whether the first byval capture was for a block or a lambda.
+  return getOutermostByvalCaptureKind(S, var);
 }
 
 /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue.  If not,
@@ -11911,7 +11926,8 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
     return false;
   }
   const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
-  if (HasBlocksAttr || CaptureType->isReferenceType()) {
+  if (HasBlocksAttr || Var->getType()->isReferenceType() ||
+      !Var->hasLocalStorage()) {
     // Block capture by reference does not change the capture or
     // declaration reference types.
     ByRef = true;
diff --git a/test/CodeGenCXX/blocks-cxx11.cpp b/test/CodeGenCXX/blocks-cxx11.cpp
index 10d1c65..6b7e7a9 100644
--- a/test/CodeGenCXX/blocks-cxx11.cpp
+++ b/test/CodeGenCXX/blocks-cxx11.cpp
@@ -90,25 +90,32 @@ namespace test_block_in_lambda {
   struct A {
     void *p;
     A(const A &);
+    A &operator=(const A &);
     ~A();
     void use() const;
   };
 
-  void test(A a) {
-    auto lambda = [a]() {
-      takeBlock(^{ a.use(); });
+  void test(A a, A b) {
+    auto lambda = [a, &b]() {
+      takeBlock(^{ a.use(); b.use(); });
     };
     lambda(); // make sure we emit the invocation function
   }
-  // CHECK-LABEL:    define internal void @"_ZZN20test_block_in_lambda4testENS_1AEENK3$_0clEv"(
+  // CHECK-LABEL:    define internal void @"_ZZN20test_block_in_lambda4testENS_1AES0_ENK3$_0clEv"(
   // CHECK:      [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
   // CHECK:      [[THIS:%.*]] = load [[LAMBDA_T:%.*]]**
-  // CHECK:      [[TO_DESTROY:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+  // CHECK:      [[TO_DESTROYa:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+  // CHECK:      [[TO_DESTROYb:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 6
   // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
   // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[LAMBDA_T]]* [[THIS]], i32 0, i32 0
   // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* dereferenceable({{[0-9]+}}) [[T1]])
+  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 6
+  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[LAMBDA_T]]* [[THIS]], i32 0, i32 1
+  // CHECK-NEXT: [[T2:%.*]] = load {{.*}}** [[T1]]
+  // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* dereferenceable({{[0-9]+}}) [[T2]])
   // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
   // CHECK-NEXT: call void @_ZN20test_block_in_lambda9takeBlockEU13block_pointerFvvE(void ()* [[T0]])
-  // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROY]])
+  // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROYb]])
+  // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROYa]])
   // CHECK-NEXT: ret void
 }
diff --git a/test/Sema/captured-statements.c b/test/Sema/captured-statements.c
index 86e9273..0d166b4 100644
--- a/test/Sema/captured-statements.c
+++ b/test/Sema/captured-statements.c
@@ -69,7 +69,7 @@ void test_nest_block() {
     int d;
     ^{
       a = b; // expected-error{{__block variable 'a' cannot be captured in a captured statement}}
-      b = d; // OK - Consistent with block inside a lambda
+      b = d; // expected-error{{variable is not assignable (missing __block type specifier)}}
       c = a; // expected-error{{__block variable 'a' cannot be captured in a captured statement}}
       c = d; // OK
       d = b; // expected-error{{variable is not assignable (missing __block type specifier)}}
diff --git a/test/SemaCXX/blocks.cpp b/test/SemaCXX/blocks.cpp
index 0521802..c35a6ca 100644
--- a/test/SemaCXX/blocks.cpp
+++ b/test/SemaCXX/blocks.cpp
@@ -145,3 +145,34 @@ namespace test6c {
             A::foo(); });
   }
 }
+
+// When diagnosing modification of a bycopy capture, indicate the outermost
+// context that has a copy capture.
+void test7() {
+  int a = 0;
+  int b = 0;
+  int &c = a;
+  int &d = a;
+  [&, b]() {
+    ^{
+      a = 1; // expected-error{{missing __block}}
+      b = 1; // expected-error{{captured by copy in a non-mutable lambda}}
+      c = 1; // OK
+    }();
+  }();
+
+  ^{
+    [&, b, c]() {
+      a = 1; // expected-error{{missing __block}}
+      b = 2; // expected-error{{missing __block}}
+      c = 3; // expected-error{{captured by copy in a non-mutable lambda}}
+      d = 4; // OK, c has reference type
+      [&, d]() {
+        ^{
+          c = 3; // expected-error{{captured by copy in a non-mutable lambda}}
+          d = 4; // expected-error{{captured by copy in a non-mutable lambda}}
+        }();
+      }();
+    }();
+  }();
+}
