Author: PiJoules Date: 2026-09-18T11:04:29-07:00 New Revision: 1e02641babceb803e3b568e8dfbe5036f0f15f0f
URL: https://github.com/llvm/llvm-project/commit/1e02641babceb803e3b568e8dfbe5036f0f15f0f DIFF: https://github.com/llvm/llvm-project/commit/1e02641babceb803e3b568e8dfbe5036f0f15f0f.diff LOG: [clang][CodeGen] Emit offsets to __cxa_pure/deleted_virtual under relative vtables (#224148) Previously, pure and deleted virtual functions were emitted as null (0) in relative vtables as a temporary workaround for PR43094 (#42439). Before dso_local_equivalent, taking relative offsets to external runtime functions required generating local symbols, which caused LLD COMDAT group merging conflicts for classes defined across multiple TUs. With dso_local_equivalent, we can now emit direct relative offsets to __cxa_pure_virtual and __cxa_deleted_virtual without generating local aliases or encountering COMDAT signature clashes. Added: clang/test/CodeGenCXX/RelativeVTablesABI/deleted-virtual-method.cpp Modified: clang/lib/CodeGen/CGVTables.cpp clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index ba4e90c0f95ba..f0c48eba1f5c3 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -819,16 +819,6 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, } auto getSpecialVirtualFn = [&](StringRef name) -> llvm::Constant * { - // FIXME(PR43094): When merging comdat groups, lld can select a local - // symbol as the signature symbol even though it cannot be accessed - // outside that symbol's TU. The relative vtables ABI would make - // __cxa_pure_virtual and __cxa_deleted_virtual local symbols, and - // depending on link order, the comdat groups could resolve to the one - // with the local symbol. As a temporary solution, fill these components - // with zero. We shouldn't be calling these in the first place anyway. - if (RelativeCXXABIVTables) - return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy); - llvm::FunctionType *fnTy = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); auto *F = cast<llvm::Function>( diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/deleted-virtual-method.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/deleted-virtual-method.cpp new file mode 100644 index 0000000000000..e683cce8a743b --- /dev/null +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/deleted-virtual-method.cpp @@ -0,0 +1,17 @@ +// Check the layout of the vtable for a class with a deleted virtual function. + +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -o - -emit-llvm -fhalf-no-semantic-interposition | FileCheck %s + +// CHECK: @_ZTV1A.local = internal constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @__cxa_deleted_virtual to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3barEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4 + +// CHECK: @_ZTV1A ={{.*}}alias { [4 x i32] }, ptr @_ZTV1A.local + +// CHECK: declare void @__cxa_deleted_virtual() unnamed_addr + +class A { +public: + virtual void foo() = delete; + virtual void bar(); +}; + +void A::bar() {} diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp index 58d11f2b49ebd..67fb8196d193c 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp @@ -1,17 +1,16 @@ // Override pure virtual function. -// We instead emit zero for the pure virtual function component. See PR43094 for -// details. +// Check that pure virtual functions emit a reference to __cxa_pure_virtual. // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -o - -emit-llvm -fhalf-no-semantic-interposition | FileCheck %s -// CHECK: @_ZTV1A.local = internal constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3barEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4 +// CHECK: @_ZTV1A.local = internal constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @__cxa_pure_virtual to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3barEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4 // CHECK: @_ZTV1B.local = internal constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B3barEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4 // CHECK: @_ZTV1A ={{.*}}alias { [4 x i32] }, ptr @_ZTV1A.local // CHECK: @_ZTV1B ={{.*}}alias { [4 x i32] }, ptr @_ZTV1B.local -// CHECK-NOT: declare void @__cxa_pure_virtual() unnamed_addr +// CHECK: declare void @__cxa_pure_virtual() unnamed_addr class A { public: _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
