Skip to content

Restore unnamed_addr on vtables in -fno-rtti builds#201846

Merged
zmodem merged 3 commits into
llvm:mainfrom
zmodem:vtables_fix
Jun 5, 2026
Merged

Restore unnamed_addr on vtables in -fno-rtti builds#201846
zmodem merged 3 commits into
llvm:mainfrom
zmodem:vtables_fix

Conversation

@zmodem
Copy link
Copy Markdown
Contributor

@zmodem zmodem commented Jun 5, 2026

This is a follow-up to #200108 which dropped unnamed_addr from vtables since it can break dynamic_cast under some circumstances. However, that caused significant binary size regressions due to preventing ICF of vtables.

This patch restores unnamed_addr on vtables in -fno-rtti builds, since those do not support dynamic_cast, recovering the binary size savings at least for those using that configuration.

@zmodem zmodem requested review from ChuanqiXu9, ojhunt and pcc June 5, 2026 14:03
@zmodem zmodem added the clang:codegen IR generation bugs: mangling, exceptions, etc. label Jun 5, 2026
@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category clang:openmp OpenMP related changes to Clang labels Jun 5, 2026
@llvmorg-github-actions
Copy link
Copy Markdown

llvmorg-github-actions Bot commented Jun 5, 2026

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: Hans Wennborg (zmodem)

Changes

This is a follow-up to #200108 which dropped unnamed_addr from vtables since it can break dynamic_cast under some circumstances. However, that caused significant binary size regressions due to preventing ICF of vtables.

This patch restores unnamed_addr on vtables in -fno-rtti builds, since those do not support dynamic_cast, recovering the binary size savings at least for those using that configuration.


Patch is 47.73 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201846.diff

17 Files Affected:

  • (modified) clang/lib/CodeGen/CGVTables.cpp (+6)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+2)
  • (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+4)
  • (modified) clang/test/CodeGenCUDA/increment-index-for-thunks.cu (+6-6)
  • (modified) clang/test/CodeGenCUDA/record-layout.cu (+2-2)
  • (modified) clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp (+3-3)
  • (modified) clang/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/dllimport.cpp (+6-6)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vftables.cpp (+5-5)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp (+8-8)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (+5-5)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp (+8-8)
  • (modified) clang/test/CodeGenCXX/ptrauth-apple-kext-indirect-call-2.cpp (+4-4)
  • (modified) clang/test/CodeGenCXX/ptrauth-apple-kext-indirect-virtual-dtor-call.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/ptrauth-global-constant-initializers.cpp (+10-10)
  • (modified) clang/test/OpenMP/nvptx_target_pure_deleted_codegen.cpp (+2-2)
  • (modified) clang/test/OpenMP/target_vtable_codegen_explicit.cpp (+1-1)
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 40abf4570f219..4b8514e4e2bc1 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -987,6 +987,11 @@ llvm::GlobalVariable *CodeGenVTables::GenerateConstructionVTable(
   llvm::GlobalVariable *VTable =
       CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage, Align);
 
+  // dynamic_cast assumes the vtable address is unique; see
+  // https://github.com/llvm/llvm-project/pull/200108
+  if (!CGM.shouldEmitRTTI())
+    VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
   llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
       CGM.getContext().getCanonicalTagType(Base.getBase()));
 
@@ -1070,6 +1075,7 @@ void CodeGenVTables::GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable,
     assert(VTableAlias->getLinkage() == Linkage);
   }
   VTableAlias->setVisibility(VTable->getVisibility());
+  VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr());
 
   // Both of these will now imply dso_local for the vtable.
   if (!VTable->hasComdat()) {
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 3c6b2b1227d6c..b4b3284f752ae 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2258,6 +2258,8 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
   VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
       Name, VTableType, llvm::GlobalValue::ExternalLinkage,
       getContext().toCharUnitsFromBits(PAlign).getAsAlign());
+  if (!CGM.shouldEmitRTTI())
+    VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
 
   if (CGM.getTarget().hasPS4DLLImportExport())
     setVTableSelectiveDLLImportExport(CGM, VTable, RD);
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index ad2c201bc2518..40c7c00d85395 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1941,6 +1941,8 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
   VTable = new llvm::GlobalVariable(CGM.getModule(), VTableType,
                                     /*isConstant=*/true, VTableLinkage,
                                     /*Initializer=*/nullptr, VTableName);
+  if (!CGM.shouldEmitRTTI())
+    VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
 
   llvm::Comdat *C = nullptr;
   if (!VFTableComesFromAnotherTU &&
@@ -1967,6 +1969,8 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
                                         /*AddressSpace=*/0, VFTableLinkage,
                                         VFTableName.str(), VTableGEP,
                                         &CGM.getModule());
+    if (!CGM.shouldEmitRTTI())
+      VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
   } else {
     // We don't need a GlobalAlias to be a symbol for the VTable if we won't
     // be referencing any RTTI data.
diff --git a/clang/test/CodeGenCUDA/increment-index-for-thunks.cu b/clang/test/CodeGenCUDA/increment-index-for-thunks.cu
index 2d8cc3c29009b..48dbf6ef82b7d 100644
--- a/clang/test/CodeGenCUDA/increment-index-for-thunks.cu
+++ b/clang/test/CodeGenCUDA/increment-index-for-thunks.cu
@@ -3,12 +3,12 @@
 // RUN: %clang_cc1 -fcuda-is-device -triple spirv64-amd-amdhsa \
 // RUN:   -emit-llvm -xhip %s -o - | FileCheck %s --check-prefix=SPIRV
 
-// GCN: @_ZTV1C = linkonce_odr addrspace(1) constant { [5 x ptr addrspace(1)], [4 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1B2f2Ev to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1C2f1Ev to ptr addrspace(1))], [4 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 -8 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZThn8_N1C2f1Ev to ptr addrspace(1))] }, comdat, align 8
-// GCN: @_ZTV1B = linkonce_odr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1B2f2Ev to ptr addrspace(1))] }, comdat, align 8
-// GCN: @_ZTV1A = linkonce_odr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8
-// SPIRV: @_ZTV1C = linkonce_odr addrspace(1) constant { [5 x ptr addrspace(1)], [4 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZN1B2f2Ev to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZN1C2f1Ev to ptr addrspace(1))], [4 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 -8 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZThn8_N1C2f1Ev to ptr addrspace(1))] }, comdat, align 8
-// SPIRV: @_ZTV1B = linkonce_odr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZN1B2f2Ev to ptr addrspace(1))] }, comdat, align 8
-// SPIRV: @_ZTV1A = linkonce_odr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8
+// GCN: @_ZTV1C = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)], [4 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1B2f2Ev to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1C2f1Ev to ptr addrspace(1))], [4 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 -8 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZThn8_N1C2f1Ev to ptr addrspace(1))] }, comdat, align 8
+// GCN: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1B2f2Ev to ptr addrspace(1))] }, comdat, align 8
+// GCN: @_ZTV1A = linkonce_odr unnamed_addr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8
+// SPIRV: @_ZTV1C = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)], [4 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZN1B2f2Ev to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZN1C2f1Ev to ptr addrspace(1))], [4 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 -8 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZThn8_N1C2f1Ev to ptr addrspace(1))] }, comdat, align 8
+// SPIRV: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @_ZN1B2f2Ev to ptr addrspace(1))] }, comdat, align 8
+// SPIRV: @_ZTV1A = linkonce_odr unnamed_addr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr addrspace(4) @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8
 
 struct A {
   __attribute__((device)) A() { }
diff --git a/clang/test/CodeGenCUDA/record-layout.cu b/clang/test/CodeGenCUDA/record-layout.cu
index 9a1950509b8c8..4e27321452ee7 100644
--- a/clang/test/CodeGenCUDA/record-layout.cu
+++ b/clang/test/CodeGenCUDA/record-layout.cu
@@ -48,8 +48,8 @@ struct C : A, B {
 // HOST: @"??_7J@@6B@" = alias ptr, getelementptr inbounds ({ [4 x ptr] }, ptr @0, i32 0, i32 0, i32 1)
 // HOST: @"??_7I@@6B@" = alias ptr, getelementptr inbounds ({ [4 x ptr] }, ptr @1, i32 0, i32 0, i32 1)
 
-// DEV: @_ZTV1J = linkonce_odr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1J1gEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1J1hEv to ptr addrspace(1))] }, comdat, align 8
-// DEV: @_ZTV1I = linkonce_odr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8
+// DEV: @_ZTV1J = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1J1gEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1J1hEv to ptr addrspace(1))] }, comdat, align 8
+// DEV: @_ZTV1I = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8
 struct I {
     virtual void f() = 0;
     __device__ virtual void g() = 0;
diff --git a/clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp b/clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp
index aa6357c59ced4..75fd72af11d72 100644
--- a/clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp
+++ b/clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp
@@ -10,9 +10,9 @@
 /// - A virtual function
 ///
 /// Now vtables should have just two components.
-// POINTER: @_ZTV1A = constant { [2 x ptr] } { [2 x ptr] [ptr null, ptr @_ZN1A3fooEv] }, align 8
-// RELATIVE: @_ZTV1A.local = internal constant { [2 x i32] } { [2 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [2 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 1) to i64)) to i32)] }, align 4
-// RELATIVE: @_ZTV1A = alias { [2 x i32] }, ptr @_ZTV1A.local
+// POINTER: @_ZTV1A = unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr null, ptr @_ZN1A3fooEv] }, align 8
+// RELATIVE: @_ZTV1A.local = internal unnamed_addr constant { [2 x i32] } { [2 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [2 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 1) to i64)) to i32)] }, align 4
+// RELATIVE: @_ZTV1A = unnamed_addr alias { [2 x i32] }, ptr @_ZTV1A.local
 
 /// None of these supplementary symbols should be emitted with -fno-rtti, but
 /// as a sanity check lets make sure they're not emitted also.
diff --git a/clang/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp b/clang/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
index fb9d87f03370f..d615b5516b752 100644
--- a/clang/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
+++ b/clang/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -disable-O0-optnone -emit-llvm -o - %s | FileCheck %s
 
-// CHECK: @_ZTV5TemplIiE = internal constant { [7 x ptr] } { [7 x ptr] [ptr null, ptr null, ptr @_ZN5TemplIiED1Ev, ptr @_ZN5TemplIiED0Ev, ptr @_ZN5TemplIiE1fEv, ptr @_ZN5TemplIiE1gEv, ptr null] }
+// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant { [7 x ptr] } { [7 x ptr] [ptr null, ptr null, ptr @_ZN5TemplIiED1Ev, ptr @_ZN5TemplIiED0Ev, ptr @_ZN5TemplIiE1fEv, ptr @_ZN5TemplIiE1gEv, ptr null] }
 
 struct B1 { 
   virtual ~B1(); 
diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp
index 86fe7561f4c4e..ed1c72c5185d3 100644
--- a/clang/test/CodeGenCXX/dllimport.cpp
+++ b/clang/test/CodeGenCXX/dllimport.cpp
@@ -673,16 +673,16 @@ USEMEMFUNC(V, foo)
 struct __declspec(dllimport) W { virtual void foo() {} };
 USECLASS(W)
 // vftable:
-// MO1-DAG: @"??_SW@@6B@" = linkonce_odr constant { [1 x ptr] } { [1 x ptr] [ptr @"?foo@W@@UAEXXZ"] }
-// GO1-DAG: @_ZTV1W = available_externally dllimport constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN1W3fooEv] }
+// MO1-DAG: @"??_SW@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"?foo@W@@UAEXXZ"] }
+// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN1W3fooEv] }
 
 struct __declspec(dllimport) KeyFuncClass {
   constexpr KeyFuncClass() {}
   virtual void foo();
 };
 extern constexpr KeyFuncClass keyFuncClassVar = {};
-// G32-DAG: @_ZTV12KeyFuncClass = external dllimport constant { [3 x ptr] }
-// C32-DAG: @_ZTV12KeyFuncClass = external dllimport constant { [3 x ptr] }
+// G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant { [3 x ptr] }
+// C32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant { [3 x ptr] }
 
 struct __declspec(dllimport) X : public virtual W {};
 USECLASS(X)
@@ -788,7 +788,7 @@ namespace PR21355 {
   // S::~S is a key function, so we would ordinarily emit a strong definition for
   // the vtable. However, S is imported, so the vtable should be too.
 
-  // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport constant { [4 x ptr] }
+  // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant { [4 x ptr] }
 }
 
 namespace PR21366 {
@@ -810,7 +810,7 @@ namespace PR27319 {
   };
   extern template struct __declspec(dllimport) A<int>;
   void f() { new A<int>(); }
-  // MO1-DAG: @"??_S?$A@H@PR27319@@6B@" = linkonce_odr constant { [1 x ptr] }
+  // MO1-DAG: @"??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] }
 }
 
 // MS ignores DLL attributes on partial specializations.
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp
index d00019aaa04d4..c707a286b5129 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp
@@ -11,7 +11,7 @@ struct S {
 // RTTI-DAG: [[VTABLE_S:@.*]] = private constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4S@@6B@", ptr @"??_ES@@UAEPAXI@Z"] }, comdat($"??_7S@@6B@")
 // RTTI-DAG: @"??_7S@@6B@" = alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_S]], i32 0, i32 0, i32 1)
 
-// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_ES@@UAEPAXI@Z"] }
+// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_ES@@UAEPAXI@Z"] }
 
 struct __declspec(dllimport) U {
   virtual ~U();
@@ -20,7 +20,7 @@ struct __declspec(dllimport) U {
 // RTTI-DAG: [[VTABLE_U:@.*]] = private constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4U@@6B@", ptr @"??_EU@@UAEPAXI@Z"] }
 // RTTI-DAG: @"??_SU@@6B@" = alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_U]], i32 0, i32 0, i32 1)
 
-// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EU@@UAEPAXI@Z"] }
+// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EU@@UAEPAXI@Z"] }
 
 struct __declspec(dllexport) V {
   virtual ~V();
@@ -29,7 +29,7 @@ struct __declspec(dllexport) V {
 // RTTI-DAG: [[VTABLE_V:@.*]] = private constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4V@@6B@", ptr @"??_EV@@UAEPAXI@Z"] }, comdat($"??_7V@@6B@")
 // RTTI-DAG: @"??_7V@@6B@" = dllexport alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_V]], i32 0, i32 0, i32 1)
 
-// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EV@@UAEPAXI@Z"] }
+// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EV@@UAEPAXI@Z"] }
 
 namespace {
 struct W {
@@ -39,7 +39,7 @@ struct W {
 // RTTI-DAG: [[VTABLE_W:@.*]] = private constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4W@?A0x{{[^@]*}}@@6B@", ptr @"??_EW@?A0x{{[^@]*}}@@UAEPAXI@Z"] }
 // RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_W]], i32 0, i32 0, i32 1)
 
-// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EW@?A0x{{[^@]*}}@@UAEPAXI@Z"] }
+// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EW@?A0x{{[^@]*}}@@UAEPAXI@Z"] }
 
 struct X {};
 template <class> struct Y : virtual X {
@@ -52,4 +52,4 @@ template Y<int>::Y();
 // RTTI-DAG: [[VTABLE_Y:@.*]] = private constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4?$Y@H@@6B@", ptr @"??_E?$Y@H@@UAEPAXI@Z"] }, comdat($"??_7?$Y@H@@6B@")
 // RTTI-DAG: @"??_7?$Y@H@@6B@" = alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_Y]], i32 0, i32 0, i32 1)
 
-// NO-RTTI-DAG: @"??_7?$Y@H@@6B@" = linkonce_odr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_E?$Y@H@@UAEPAXI@Z"] }, comdat
+// NO-RTTI-DAG: @"??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_E?$Y@H@@UAEPAXI@Z"] }, comdat
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
index ffd4d20fb758a..1a589370d3a74 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
@@ -26,7 +26,7 @@ J::J() {}
 // VFTABLES-NEXT:       [return adjustment (to type 'struct test1::C *'): 0 non-virtual]
 // VFTABLES-NEXT:   2 | D *test1::J::foo()
 
-// GLOBALS-LABEL: @"??_7J@test1@@6B@" = linkonce_odr constant { [3 x ptr] }
+// GLOBALS-LABEL: @"??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant { [3 x ptr] }
 // GLOBALS: @"?foo@J@test1@@QAEPAUB@2@XZ"
 // GLOBALS: @"?foo@J@test1@@QAEPAUC@2@XZ"
 // GLOBALS: @"?foo@J@test1@@UAEPAUD@2@XZ"
@@ -44,7 +44,7 @@ K::K() {}
 
 // Only B to C requires adjustment, but we get 3 thunks in K's vftable, two of
 // which are trivial.
-// GLOBALS-LABEL: @"??_7K@test1@@6B@" = linkonce_odr constant { [4 x ptr] }
+// GLOBALS-LABEL: @"??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant { [4 x ptr] }
 // GLOBALS: @"?foo@K@test1@@QAEPAUB@2@XZ"
 // GLOBALS: @"?foo@K@test1@@QAEPAUC@2@XZ"
 // GLOBALS: @"?foo@K@test1@@QAEPAUD@2@XZ"
@@ -90,7 +90,7 @@ J::J() {}
 // VFTABLES-NEXT:         [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
 // VFTABLES-NEXT:    1 | D *test2::J::foo()
 
-// GLOBALS-LABEL: @"??_7J@test2@@6B@" = linkonce_odr constant { [2 x ptr] }
+// GLOBALS-LABEL: @"??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant { [2 x ptr] }
 
 K::K() {}
 
@@ -101,7 +101,7 @@ K::K() {}
 // VFTABLES-NEXT:         [return adjustment (to type 'struct test2::D *'): 0 non-virtual]
 // VFTABLES-NEXT:    2 | E *test2::K::foo()
 
-// GLOBALS-LABEL: @"??_7K@test2@@6B@" = linkonce_odr constant { [3 x ptr] }
+// GLOBALS-LABEL: @"??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant { [3 x ptr] }
 
 }
 
@@ -124,7 +124,7 @@ struct C : virtual A, B {
 
 C::C() {}
 
-// GLOBALS-LABEL: @"??_7C@pr20479@@6B@" = linkonce_odr constant { [2 x ptr] }
+// GLOBALS-LABEL: @"??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant { [2 x ptr] }
 // GLOBALS: @"?f@B@pr20479@@QAEPAUA@2@XZ"
 // GLOBALS: @"?f@B@pr20479@@UAEPAU12@XZ"
 }
@@ -151,7 +151,7 @@ struct C : virtual A, virtual B {
 
 C::C() {}
 
-// GLOBALS-LABEL: @"??_7C@pr21073@@6B@" = linkonce_odr constant { [2 x ptr] }
+// GLOBALS-LABEL: @"??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant { [2 x ptr] }
 // GLOBALS: @"?f@B@pr21073@@WPPPPPPPI@AEPAUA@2@XZ"
 // GLOBALS: @"?f@B@pr21073@@WPPPPPPPI@AEPAU12@XZ"
 }
@@ -168,7 +168,7 @@ D...
[truncated]

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

🐧 Linux x64 Test Results

  • 118239 tests passed
  • 4814 tests skipped

✅ The build succeeded and all tests passed.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

🪟 Windows x64 Test Results

  • 55750 tests passed
  • 2632 tests skipped

✅ The build succeeded and all tests passed.

Copy link
Copy Markdown
Contributor

@alanzhao1 alanzhao1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but someone else should also approve.

@zmodem zmodem merged commit 75db4ce into llvm:main Jun 5, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:codegen IR generation bugs: mangling, exceptions, etc. clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants