Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -467,13 +467,11 @@
     }
   };
 
-  struct DestroyNRVOVariable final : EHScopeStack::Cleanup {
-    DestroyNRVOVariable(Address addr,
-                        const CXXDestructorDecl *Dtor,
-                        llvm::Value *NRVOFlag)
-      : Dtor(Dtor), NRVOFlag(NRVOFlag), Loc(addr) {}
+  template <class Derived>
+  struct DestroyNRVOVariable : EHScopeStack::Cleanup {
+    DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag)
+        : NRVOFlag(NRVOFlag), Loc(addr) {}
 
-    const CXXDestructorDecl *Dtor;
     llvm::Value *NRVOFlag;
     Address Loc;
 
@@ -492,12 +490,39 @@
         CGF.EmitBlock(RunDtorBB);
       }
 
+      static_cast<Derived *>(this)->emitDestructorCall(CGF);
+
+      if (NRVO) CGF.EmitBlock(SkipDtorBB);
+    }
+
+    virtual ~DestroyNRVOVariable() = default;
+  };
+
+  struct DestroyNRVOVariableCXX final
+      : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
+    DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor,
+                           llvm::Value *NRVOFlag)
+      : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, NRVOFlag),
+        Dtor(Dtor) {}
+
+    const CXXDestructorDecl *Dtor;
+
+    void emitDestructorCall(CodeGenFunction &CGF) {
       CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
                                 /*ForVirtualBase=*/false,
-                                /*Delegating=*/false,
-                                Loc);
+                                /*Delegating=*/false, Loc);
+    }
+  };
 
-      if (NRVO) CGF.EmitBlock(SkipDtorBB);
+  struct DestroyNRVOVariableC final
+      : DestroyNRVOVariable<DestroyNRVOVariableC> {
+    DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty)
+        : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, NRVOFlag), Ty(Ty) {}
+
+    QualType Ty;
+
+    void emitDestructorCall(CodeGenFunction &CGF) {
+      CGF.destroyNonTrivialCStruct(CGF, Loc, Ty);
     }
   };
 
@@ -1088,7 +1113,10 @@
       address = ReturnValue;
 
       if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
-        if (!cast<CXXRecordDecl>(RecordTy->getDecl())->hasTrivialDestructor()) {
+        const auto *RD = cast<RecordDecl>(RecordTy->getDecl());
+        const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+        if ((CXXRD && !CXXRD->hasTrivialDestructor()) ||
+            RD->isNonTrivialToPrimitiveCopy()) {
           // Create a flag that is used to indicate when the NRVO was applied
           // to this variable. Set it to zero to indicate that NRVO was not
           // applied.
@@ -1461,8 +1489,8 @@
     if (emission.NRVOFlag) {
       assert(!type->isArrayType());
       CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
-      EHStack.pushCleanup<DestroyNRVOVariable>(cleanupKind, addr,
-                                               dtor, emission.NRVOFlag);
+      EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, dtor,
+                                                  emission.NRVOFlag);
       return;
     }
     break;
@@ -1484,6 +1512,12 @@
 
   case QualType::DK_nontrivial_c_struct:
     destroyer = CodeGenFunction::destroyNonTrivialCStruct;
+    if (emission.NRVOFlag) {
+      assert(!type->isArrayType());
+      EHStack.pushCleanup<DestroyNRVOVariableC>(cleanupKind, addr,
+                                                emission.NRVOFlag, type);
+      return;
+    }
     break;
   }
 
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -12712,8 +12712,10 @@
       // Try to apply the named return value optimization. We have to check
       // if we can do this here because lambdas keep return statements around
       // to deduce an implicit return type.
-      if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() &&
-          !FD->isDependentContext())
+      QualType RetTy = FD->getReturnType();
+      if (RetTy->isRecordType() &&
+          ((getLangOpts().CPlusPlus && !FD->isDependentContext()) ||
+           RetTy.isNonTrivialToPrimitiveCopy()))
         computeNRVO(Body, getCurFunction());
     }
 
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -2872,7 +2872,7 @@
 /// NRVO, or NULL if there is no such candidate.
 VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
                                        CopyElisionSemanticsKind CESK) {
-  if (!getLangOpts().CPlusPlus)
+  if (!getLangOpts().CPlusPlus && !ReturnType.isNonTrivialToPrimitiveCopy())
     return nullptr;
 
   // - in a return statement in a function [where] ...
Index: test/CodeGenObjC/objc-non-trivial-struct-nrvo.m
===================================================================
--- /dev/null
+++ test/CodeGenObjC/objc-non-trivial-struct-nrvo.m
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
+// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
+// CHECK: %[[STRUCT_WEAK:.*]] = type { i8* }
+
+typedef struct {
+  int x;
+} Trivial;
+
+typedef struct {
+  id x;
+} Strong;
+
+typedef struct {
+  __weak id x;
+} Weak;
+
+// CHECK: define i32 @testTrivial()
+// CHECK-NOT: br
+// CHECK: ret i32 %{{.*}}
+
+Trivial testTrivial() {
+  Trivial a;
+  return a;
+}
+
+// CHECK: define i8* @testStrong()
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8**
+// CHECK: call void @__default_constructor_8_s0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8**
+// CHECK: call void @__destructor_8_s0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
+// CHECK: %[[V2:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
+// CHECK: ret i8* %[[V2]]
+
+Strong testStrong() {
+  Strong a;
+  return a;
+}
+
+// CHECK: define void @testWeak(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]])
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__destructor_8_w0(i8** %[[V1]]) #3
+// CHECK: br
+
+// CHECK-NOT: call
+// CHECK: ret void
+
+Weak testWeak() {
+  Weak a;
+  return a;
+}
+
+// CHECK: define void @testWeak2(
+// CHECK: call void @__default_constructor_8_w0(
+// CHECK: call void @__default_constructor_8_w0(
+// CHECK: call void @__copy_constructor_8_8_w0(
+// CHECK: call void @__copy_constructor_8_8_w0(
+// CHECK: call void @__destructor_8_w0(
+// CHECK: call void @__destructor_8_w0(
+
+Weak testWeak2(int c) {
+  Weak a, b;
+  if (c)
+    return a;
+  else
+    return b;
+}
+
+// CHECK: define internal void @"\01-[C1 foo1]"(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]], %{{.*}}* %{{.*}}, i8* %{{.*}})
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__destructor_8_w0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK-NOT: call
+// CHECK: ret void
+
+__attribute__((objc_root_class))
+@interface C1
+- (Weak)foo1;
+@end
+
+@implementation C1
+- (Weak)foo1 {
+  Weak a;
+  return a;
+}
+@end