diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-02 01:13:06 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-02 01:13:06 +0000 |
commit | 802e22682c17c4a9df3f747abd224db38e382e39 (patch) | |
tree | 4623c1c26979216f480a54a02eb8ae04ac823abf | |
parent | 975f253bb31f665171517d43de6686e56507abac (diff) |
Don't forget to run destructors when we create an array temporary of class type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174257 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 7 | ||||
-rw-r--r-- | test/CodeGenCXX/cxx0x-initializer-array.cpp | 46 | ||||
-rw-r--r-- | test/CodeGenCXX/global-array-destruction.cpp | 9 |
4 files changed, 81 insertions, 11 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index ad62e10473..41518fb11b 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -303,7 +303,8 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, 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::EmitReferenceBindingToExpr(const Expr *E, 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::EmitReferenceBindingToExpr(const Expr *E, 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( diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index c3d612b732..95f6c76be7 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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; } diff --git a/test/CodeGenCXX/cxx0x-initializer-array.cpp b/test/CodeGenCXX/cxx0x-initializer-array.cpp index 5e81ba1ff9..73bbca13b1 100644 --- a/test/CodeGenCXX/cxx0x-initializer-array.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-array.cpp @@ -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 + } +} diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp index b86432228c..087d655f0a 100644 --- a/test/CodeGenCXX/global-array-destruction.cpp +++ b/test/CodeGenCXX/global-array-destruction.cpp @@ -51,3 +51,12 @@ static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; // 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 {{.*}} |