Author: Richard Smith Date: 2020-07-30T14:50:01-07:00 New Revision: 1e7f026c3b59bea22491819f86d8388d0c3e0c07
URL: https://github.com/llvm/llvm-project/commit/1e7f026c3b59bea22491819f86d8388d0c3e0c07 DIFF: https://github.com/llvm/llvm-project/commit/1e7f026c3b59bea22491819f86d8388d0c3e0c07.diff LOG: PR46908: Emit undef destroying_delete_t as an aggregate RValue. We previously used a non-aggregate RValue to represent the passed value, which violated the assumptions of call arg lowering in some cases, in particular on 32-bit Windows, where we'd end up producing an FCA store with TBAA metadata, that the IR verifier would reject. Added: Modified: clang/lib/CodeGen/CGExprCXX.cpp clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index d59aa6ce0fb9..d0e0c7d6c060 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1788,11 +1788,14 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, DeleteArgs.add(RValue::get(DeletePtr), ArgTy); // Pass the std::destroying_delete tag if present. + llvm::AllocaInst *DestroyingDeleteTag = nullptr; if (Params.DestroyingDelete) { QualType DDTag = *ParamTypeIt++; - // Just pass an 'undef'. We expect the tag type to be an empty struct. - auto *V = llvm::UndefValue::get(getTypes().ConvertType(DDTag)); - DeleteArgs.add(RValue::get(V), DDTag); + llvm::Type *Ty = getTypes().ConvertType(DDTag); + CharUnits Align = CGM.getNaturalTypeAlignment(DDTag); + DestroyingDeleteTag = CreateTempAlloca(Ty, "destroying.delete.tag"); + DestroyingDeleteTag->setAlignment(Align.getAsAlign()); + DeleteArgs.add(RValue::getAggregate(Address(DestroyingDeleteTag, Align)), DDTag); } // Pass the size if the delete function has a size_t parameter. @@ -1829,6 +1832,11 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, // Emit the call to delete. EmitNewDeleteCall(*this, DeleteFD, DeleteFTy, DeleteArgs); + + // If call argument lowering didn't use the destroying_delete_t alloca, + // remove it again. + if (DestroyingDeleteTag && DestroyingDeleteTag->use_empty()) + DestroyingDeleteTag->eraseFromParent(); } namespace { diff --git a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp index 60c5970cb94f..e689afa62092 100644 --- a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp +++ b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp @@ -1,5 +1,11 @@ -// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM -// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-windows -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-MSABI +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefixes=CHECK,CHECK-ITANIUM,CHECK-64BIT +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-windows -o - | FileCheck %s --check-prefixes=CHECK,CHECK-MSABI,CHECK-MSABI64,CHECK-64BIT +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple i386-windows -o - | FileCheck %s --check-prefixes=CHECK,CHECK-MSABI,CHECK-MSABI32,CHECK-32BIT + +// PR46908: ensure the IR passes the verifier with optimizations enabled. +// RUN: %clang_cc1 -std=c++2a -emit-llvm-only %s -triple x86_64-linux-gnu -O2 +// RUN: %clang_cc1 -std=c++2a -emit-llvm-only %s -triple x86_64-windows -O2 +// RUN: %clang_cc1 -std=c++2a -emit-llvm-only %s -triple i386-windows -O2 namespace std { using size_t = decltype(sizeof(0)); @@ -21,7 +27,8 @@ void delete_A(A *a) { delete a; } // Ensure that we call the destroying delete and not the destructor. // CHECK-NOT: call // CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) -// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-MSABI64: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-MSABI32: call void @"??3A@@SAXPAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], %{{.*}}* byval(%{{.*}}) align 4 %{{.*}}) // CHECK-NOT: call // CHECK: } @@ -39,7 +46,7 @@ void delete_B(B *b) { delete b; } // CHECK-NOT: call // CHECK: %[[VTABLE:.*]] = load // CHECK: %[[DTOR:.*]] = load -// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[b]] +// CHECK: call {{void|i8\*|x86_thiscallcc i8\*}} %[[DTOR]](%{{.*}}* %[[b]] // CHECK-MSABI-SAME: , i32 1) // CHECK-NOT: call // CHECK: } @@ -56,7 +63,8 @@ void delete_C(C *c) { delete c; } // CHECK: icmp eq %{{.*}} %[[c]], null // CHECK: br i1 // -// CHECK: %[[base:.*]] = getelementptr {{.*}}, i64 8 +// CHECK-64BIT: %[[base:.*]] = getelementptr {{.*}}, i64 8 +// CHECK-32BIT: %[[base:.*]] = getelementptr {{.*}}, i32 4 // CHECK: %[[castbase:.*]] = bitcast {{.*}} %[[base]] // // CHECK: %[[a:.*]] = phi {{.*}} %[[castbase]] @@ -65,7 +73,8 @@ void delete_C(C *c) { delete c; } // // CHECK-NOT: call // CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) -// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-MSABI64: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-MSABI32: call void @"??3A@@SAXPAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], %{{.*}}* byval(%{{.*}}) align 4 %{{.*}}) // CHECK-NOT: call // CHECK: } @@ -81,13 +90,14 @@ void delete_D(D *d) { delete d; } // For MS, we don't add a new vtable slot to the primary vtable for the virtual // destructor. Instead we cast to the VDel base class. // CHECK-MSABI: bitcast {{.*}} %[[d]] -// CHECK-MSABI-NEXT: getelementptr {{.*}}, i64 8 +// CHECK-MSABI64-NEXT: getelementptr {{.*}}, i64 8 +// CHECK-MSABI32-NEXT: getelementptr {{.*}}, i32 4 // CHECK-MSABI-NEXT: %[[d:.*]] = bitcast i8* // // CHECK: %[[VTABLE:.*]] = load // CHECK: %[[DTOR:.*]] = load // -// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[d]] +// CHECK: call {{void|i8\*|x86_thiscallcc i8\*}} %[[DTOR]](%{{.*}}* %[[d]] // CHECK-MSABI-SAME: , i32 1) // CHECK-NOT: call // CHECK: } @@ -100,7 +110,8 @@ void delete_G(G *g) { delete g; } // CHECK-LABEL: define {{.*}}delete_G // CHECK-NOT: call // CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t(%{{.*}}* %[[a]], i64 32, i64 16) -// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16) +// CHECK-MSABI64: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16) +// CHECK-MSABI32: call void @"??3F@@SAXPAU0@Udestroying_delete_t@std@@IW4align_val_t@2@@Z"(%{{.*}}* %[[a]], %{{.*}}* byval(%{{.*}}) align 4 %{{.*}}, i32 16, i32 16) // CHECK-NOT: call // CHECK: } @@ -116,19 +127,23 @@ H::~H() { call_in_dtor(); } // CHECK-ITANIUM-NOT: call // CHECK-ITANIUM: } -// CHECK-MSABI: define {{.*}} @"??_GH@@UEAAPEAXI@Z"( +// CHECK-MSABI64: define {{.*}} @"??_GH@@UEAAPEAXI@Z"( +// CHECK-MSABI32: define {{.*}} @"??_GH@@UAEPAXI@Z"( // CHECK-MSABI-NOT: call{{ }} // CHECK-MSABI: load i32 // CHECK-MSABI: icmp eq i32 {{.*}}, 0 // CHECK-MSABI: br i1 // // CHECK-MSABI-NOT: call{{ }} -// CHECK-MSABI: getelementptr {{.*}}, i64 24 +// CHECK-MSABI64: getelementptr {{.*}}, i64 24 +// CHECK-MSABI32: getelementptr {{.*}}, i32 20 // CHECK-MSABI-NOT: call{{ }} -// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16) +// CHECK-MSABI64: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16) +// CHECK-MSABI32: call void @"??3F@@SAXPAU0@Udestroying_delete_t@std@@IW4align_val_t@2@@Z"({{.*}}, i32 32, i32 16) // CHECK-MSABI: br label %[[RETURN:.*]] // -// CHECK-MSABI: call void @"??1H@@UEAA@XZ"( +// CHECK-MSABI64: call void @"??1H@@UEAA@XZ"( +// CHECK-MSABI32: call x86_thiscallcc void @"??1H@@UAE@XZ"( // CHECK-MSABI: br label %[[RETURN]] // // CHECK-MSABI: } @@ -143,19 +158,23 @@ I::~I() { call_in_dtor(); } // CHECK-ITANIUM-NOT: call // CHECK-ITANIUM: } -// CHECK-MSABI: define {{.*}} @"??_GI@@UEAAPEAXI@Z"( +// CHECK-MSABI64: define {{.*}} @"??_GI@@UEAAPEAXI@Z"( +// CHECK-MSABI32: define {{.*}} @"??_GI@@UAEPAXI@Z"( // CHECK-MSABI-NOT: call{{ }} // CHECK-MSABI: load i32 // CHECK-MSABI: icmp eq i32 {{.*}}, 0 // CHECK-MSABI: br i1 // // CHECK-MSABI-NOT: call{{ }} -// CHECK-MSABI: getelementptr {{.*}}, i64 24 +// CHECK-MSABI64: getelementptr {{.*}}, i64 24 +// CHECK-MSABI32: getelementptr {{.*}}, i32 20 // CHECK-MSABI-NOT: call{{ }} -// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32) +// CHECK-MSABI64: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32) +// CHECK-MSABI32: call void @"??3F@@SAXPAU0@Udestroying_delete_t@std@@IW4align_val_t@2@@Z"({{.*}}, i32 64, i32 32) // CHECK-MSABI: br label %[[RETURN:.*]] // -// CHECK-MSABI: call void @"??1I@@UEAA@XZ"( +// CHECK-MSABI64: call void @"??1I@@UEAA@XZ"( +// CHECK-MSABI32: call x86_thiscallcc void @"??1I@@UAE@XZ"( // CHECK-MSABI: br label %[[RETURN]] // // CHECK-MSABI: } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits