aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-02-02 01:13:06 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-02-02 01:13:06 +0000
commit802e22682c17c4a9df3f747abd224db38e382e39 (patch)
tree4623c1c26979216f480a54a02eb8ae04ac823abf
parent975f253bb31f665171517d43de6686e56507abac (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.cpp30
-rw-r--r--lib/Sema/SemaInit.cpp7
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-array.cpp46
-rw-r--r--test/CodeGenCXX/global-array-destruction.cpp9
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 {{.*}}