]> granicus.if.org Git - clang/commitdiff
When applying the named return value optimization, we still need to
authorDouglas Gregor <dgregor@apple.com>
Sat, 15 May 2010 16:39:56 +0000 (16:39 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 15 May 2010 16:39:56 +0000 (16:39 +0000)
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

lib/CodeGen/CGDecl.cpp
test/CodeGenCXX/nrvo.cpp

index c93d9ba33df671212b15ef108e54fad3fff62e64..ae05fc5c8467c8652b63e97e91fec8849b8a92f0 100644 (file)
@@ -659,7 +659,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
     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 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
             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 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
             // Make sure to jump to the exit block.
             EmitBranch(Scope.getCleanupExitBlock());
           }
+          
           if (Exceptions) {
             EHCleanupBlock Cleanup(*this);
             EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false,
index 7b4f20398d80b26bc6804203b450bee5f8feb26e..92b41036027fc8ec14879e4fb617893cc665e2da 100644 (file)
@@ -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 @@ public:
 };
 
 // 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 @@ X test1(bool B) {
   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 @@ X test2(bool B) {
   // 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) {