r174257 - Don't forget to run destructors when we create an array temporary of class type.

Richard Smith richard-llvm at metafoo.co.uk
Fri Feb 1 17:13:06 PST 2013


Author: rsmith
Date: Fri Feb  1 19:13:06 2013
New Revision: 174257

URL: http://llvm.org/viewvc/llvm-project?rev=174257&view=rev
Log:
Don't forget to run destructors when we create an array temporary of class type.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp
    cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=174257&r1=174256&r2=174257&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Feb  1 19:13:06 2013
@@ -303,7 +303,8 @@ EmitExprForReferenceBinding(CodeGenFunct
     
     if (InitializedDecl) {
       // Get the destructor for the reference temporary.
-      if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
+      if (const RecordType *RT =
+            E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
         CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
         if (!ClassDecl->hasTrivialDestructor())
           ReferenceTemporaryDtor = ClassDecl->getDestructor();
@@ -406,10 +407,19 @@ CodeGenFunction::EmitReferenceBindingToE
   const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl);
   if (VD && VD->hasGlobalStorage()) {
     if (ReferenceTemporaryDtor) {
-      llvm::Constant *DtorFn = 
-        CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
-      CGM.getCXXABI().registerGlobalDtor(*this, DtorFn, 
-                                    cast<llvm::Constant>(ReferenceTemporary));
+      llvm::Constant *CleanupFn;
+      llvm::Constant *CleanupArg;
+      if (E->getType()->isArrayType()) {
+        CleanupFn = CodeGenFunction(CGM).generateDestroyHelper(
+            cast<llvm::Constant>(ReferenceTemporary), E->getType(),
+            destroyCXXObject, getLangOpts().Exceptions);
+        CleanupArg = llvm::Constant::getNullValue(Int8PtrTy);
+      } else {
+        CleanupFn =
+          CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
+        CleanupArg = cast<llvm::Constant>(ReferenceTemporary);
+      }
+      CGM.getCXXABI().registerGlobalDtor(*this, CleanupFn, CleanupArg);
     } else {
       assert(!ObjCARCReferenceLifetimeType.isNull());
       // Note: We intentionally do not register a global "destructor" to
@@ -419,9 +429,13 @@ CodeGenFunction::EmitReferenceBindingToE
     return RValue::get(Value);
   }
 
-  if (ReferenceTemporaryDtor)
-    PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
-  else {
+  if (ReferenceTemporaryDtor) {
+    if (E->getType()->isArrayType())
+      pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(),
+                  destroyCXXObject, getLangOpts().Exceptions);
+    else
+      PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
+  } else {
     switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) {
     case Qualifiers::OCL_None:
       llvm_unreachable(

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=174257&r1=174256&r2=174257&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Feb  1 19:13:06 2013
@@ -5240,7 +5240,8 @@ InitializationSequence::Perform(Sema &S,
       QualType Ty = ResultType ? ResultType->getNonReferenceType() : Step->Type;
       bool IsTemporary = Entity.getType()->isReferenceType();
       InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty);
-      InitListChecker PerformInitList(S, IsTemporary ? TempEntity : Entity,
+      InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity;
+      InitListChecker PerformInitList(S, InitEntity,
           InitList, Ty, /*VerifyOnly=*/false,
           Kind.getKind() != InitializationKind::IK_DirectList ||
             !S.getLangOpts().CPlusPlus11);
@@ -5259,7 +5260,9 @@ InitializationSequence::Perform(Sema &S,
       InitListExpr *StructuredInitList =
           PerformInitList.getFullyStructuredList();
       CurInit.release();
-      CurInit = S.Owned(StructuredInitList);
+      CurInit = shouldBindAsTemporary(InitEntity)
+          ? S.MaybeBindToTemporary(StructuredInitList)
+          : S.Owned(StructuredInitList);
       break;
     }
 

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp?rev=174257&r1=174256&r2=174257&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp Fri Feb  1 19:13:06 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -S -emit-llvm -o - %s -Wno-address-of-temporary | FileCheck %s
 
 // CHECK: @[[THREE_NULL_MEMPTRS:.*]] = private constant [3 x i32] [i32 -1, i32 -1, i32 -1]
 
@@ -48,3 +48,47 @@ namespace ValueInitArrayOfMemPtr {
     f(a{});
   }
 }
+
+namespace array_dtor {
+  struct S { S(); ~S(); };
+  using T = S[3];
+  void f(const T &);
+  // CHECK: define void @_ZN10array_dtor1gEv(
+  void g() {
+    // CHECK: %[[ARRAY:.*]] = alloca [3 x
+    // CHECK: br
+
+    // Construct loop.
+    // CHECK: call void @_ZN10array_dtor1SC1Ev(
+    // CHECK: br i1
+
+    // CHECK: call void @_ZN10array_dtor1fERA3_KNS_1SE(
+    // CHECK: br
+
+    // Destruct loop.
+    // CHECK: call void @_ZN10array_dtor1SD1Ev(
+    // CHECK: br i1
+
+    // CHECK: ret void
+
+    f(T{});
+  }
+  // CHECK: define void @_ZN10array_dtor1hEv(
+  void h() {
+    // CHECK: %[[ARRAY:.*]] = alloca [3 x
+    // CHECK: br
+
+    // CHECK: call void @_ZN10array_dtor1SC1Ev(
+    // CHECK: br i1
+    T &&t = T{};
+
+    // CHECK: call void @_ZN10array_dtor1fERA3_KNS_1SE(
+    // CHECK: br
+    f(t);
+
+    // CHECK: call void @_ZN10array_dtor1SD1Ev(
+    // CHECK: br i1
+
+    // CHECK: ret void
+  }
+}

Modified: cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp?rev=174257&r1=174256&r2=174257&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/global-array-destruction.cpp Fri Feb  1 19:13:06 2013
@@ -51,3 +51,12 @@ static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.
 // CHECK: call void @_ZN1TD1Ev
 // CHECK: icmp eq {{.*}} @_ZL2t
 // CHECK: br i1 {{.*}}
+
+using U = T[2][3];
+U &&u = U{ {{1.0, 2}, {3.0, 4}, {5.0, 6}}, {{7.0, 8}, {9.0, 10}, {11.0, 12}} };
+
+// CHECK: call {{.*}} @__cxa_atexit
+// CHECK: getelementptr inbounds ([2 x [3 x {{.*}}]]* @_ZGR1u, i64 1, i64 0, i64 0)
+// CHECK: call void @_ZN1TD1Ev
+// CHECK: icmp eq {{.*}} @_ZGR1u
+// CHECK: br i1 {{.*}}





More information about the cfe-commits mailing list