When applying the named return value optimization, we still need to
destroy the variable along the exceptional edge; it's only during
normal execution that we avoid destroying this variable.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103872 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index c93d9ba..ae05fc5 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -659,7 +659,7 @@
     DtorTy = getContext().getBaseElementType(Array);
   if (const RecordType *RT = DtorTy->getAs<RecordType>())
     if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {      
-      if (!ClassDecl->hasTrivialDestructor() && !NRVO) {
+      if (!ClassDecl->hasTrivialDestructor()) {
         // Note: We suppress the destructor call when this is an NRVO variable.
         llvm::Value *Loc = DeclPtr;
         if (isByRef)
@@ -693,7 +693,9 @@
             EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
           }
         } else {
-          {
+          if (!NRVO) {
+            // We don't call the destructor along the normal edge if we're
+            // applying the NRVO.
             DelayedCleanupBlock Scope(*this);
             EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false,
                                   Loc);
@@ -701,6 +703,7 @@
             // Make sure to jump to the exit block.
             EmitBranch(Scope.getCleanupExitBlock());
           }
+          
           if (Exceptions) {
             EHCleanupBlock Cleanup(*this);
             EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false,
diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp
index 7b4f203..92b4103 100644
--- a/test/CodeGenCXX/nrvo.cpp
+++ b/test/CodeGenCXX/nrvo.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
 
 // Test code generation for the named return value optimization.
 class X {
@@ -9,11 +10,15 @@
 };
 
 // CHECK: define void @_Z5test0v
+// CHECK-EH: define void @_Z5test0v
 X test0() {
   X x;
   // CHECK-NOT: call void @_ZN1XD1Ev
   // CHECK: ret void
+  // CHECK-EH: ret void
   return x;
+  // CHECK-EH: ehcleanup:
+  // CHECK-EH: invoke void @_ZN1XD1Ev
 }
 
 // CHECK: define void @_Z5test1b(
@@ -25,9 +30,12 @@
   if (B)
     return (x);
   return x;
+  // CHECK-EH: ehcleanup:
+  // CHECK-EH: invoke void @_ZN1XD1Ev
 }
 
 // CHECK: define void @_Z5test2b
+// CHECK-EH: define void @_Z5test2b
 X test2(bool B) {
   // No NRVO
   // CHECK: call void @_ZN1XC1Ev
@@ -35,13 +43,18 @@
   // CHECK: call void @_ZN1XC1Ev
   X y;
   // CHECK: call void @_ZN1XC1ERKS_
+  // CHECK-EH: invoke void @_ZN1XC1ERKS_
   if (B)
     return y;
   // CHECK: call void @_ZN1XC1ERKS_
+  // CHECK-EH: invoke void @_ZN1XC1ERKS_
   return x;
   // CHECK: call void @_ZN1XD1Ev
   // CHECK: call void @_ZN1XD1Ev
   // CHECK: ret void
+  // CHECK-EH: ehcleanup:
+  // CHECK-EH: invoke void @_ZN1XD1Ev
+  // CHECK-EH: invoke void @_ZN1XD1Ev
 }
 
 X test3(bool B) {