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

Reply via email to