From 2d1b55ebea88547d153fcd980b88c946cffc5ca5 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 4 Jan 2022 15:24:14 +0100 Subject: [PATCH] [CodeGen] Make element type in emitArrayDestroy() predictable When calling emitArrayDestroy(), the pointer will usually have ConvertTypeForMem(EltType) as the element type, as one would expect. However, globals with initializers sometimes don't use the same types as values normally would, e.g. here the global uses { double, i32 } rather than %struct.T as element type. Add an early cast to the global destruction path to avoid this special case. The cast would happen lateron anyway, it only gets moved to an earlier point. Differential Revision: https://reviews.llvm.org/D116219 --- clang/lib/CodeGen/CGDecl.cpp | 7 ++++--- clang/lib/CodeGen/CGDeclCXX.cpp | 1 + clang/test/CodeGenCXX/global-array-destruction.cpp | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 36185faf942f..18d658436086 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2252,16 +2252,17 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, // Shift the address back by one element. llvm::Value *negativeOne = llvm::ConstantInt::get(SizeTy, -1, true); + llvm::Type *llvmElementType = ConvertTypeForMem(elementType); llvm::Value *element = Builder.CreateInBoundsGEP( - elementPast->getType()->getPointerElementType(), elementPast, negativeOne, - "arraydestroy.element"); + llvmElementType, elementPast, negativeOne, "arraydestroy.element"); if (useEHCleanup) pushRegularPartialArrayCleanup(begin, element, elementType, elementAlign, destroyer); // Perform the actual destruction there. - destroyer(*this, Address(element, elementAlign), elementType); + destroyer(*this, Address(element, llvmElementType, elementAlign), + elementType); if (useEHCleanup) PopCleanupBlock(); diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 3579761f1429..7b880c1354e1 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -136,6 +136,7 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, } // Otherwise, the standard logic requires a helper function. } else { + Addr = Addr.getElementBitCast(CGF.ConvertTypeForMem(Type)); Func = CodeGenFunction(CGM) .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind), CGF.needsEHCleanup(DtorKind), &D); diff --git a/clang/test/CodeGenCXX/global-array-destruction.cpp b/clang/test/CodeGenCXX/global-array-destruction.cpp index 0f280e000112..686c8a6c580a 100644 --- a/clang/test/CodeGenCXX/global-array-destruction.cpp +++ b/clang/test/CodeGenCXX/global-array-destruction.cpp @@ -39,7 +39,7 @@ struct T { T t[2][3] = { 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 {{.*}}]], [2 x [3 x {{.*}}]]* @t, i64 1, i64 0, i64 0) +// CHECK: getelementptr inbounds ([2 x [3 x %struct.T]], [2 x [3 x %struct.T]]* bitcast ([2 x [3 x { double, i32 }]]* @t to [2 x [3 x %struct.T]]*), i64 1, i64 0, i64 0) // CHECK: call void @_ZN1TD1Ev // CHECK: icmp eq {{.*}} @t // CHECK: br i1 {{.*}} @@ -47,7 +47,7 @@ T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 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 {{.*}} @__cxa_atexit -// CHECK: getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @_ZL2t2, i64 1, i64 0, i64 0) +// CHECK: getelementptr inbounds ([2 x [3 x %struct.T]], [2 x [3 x %struct.T]]* bitcast ([2 x [3 x { double, i32 }]]* @_ZL2t2 to [2 x [3 x %struct.T]]*), i64 1, i64 0, i64 0) // CHECK: call void @_ZN1TD1Ev // CHECK: icmp eq {{.*}} @_ZL2t2 // CHECK: br i1 {{.*}} @@ -56,7 +56,7 @@ 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 {{.*}}]], [2 x [3 x {{.*}}]]* @_ZGR1u_, i64 1, i64 0, i64 0) +// CHECK: getelementptr inbounds ([2 x [3 x %struct.T]], [2 x [3 x %struct.T]]* @_ZGR1u_, i64 1, i64 0, i64 0) // CHECK: call void @_ZN1TD1Ev // CHECK: icmp eq {{.*}} @_ZGR1u_ // CHECK: br i1 {{.*}}