[clang] [CIR] Fix typeinfo linkage and comdat (PR #192721)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 17 12:36:47 PDT 2026
https://github.com/andykaylor created https://github.com/llvm/llvm-project/pull/192721
We weren't properly setting the linkage on typeinfo objects, leading to multiple definition linking error when typeinfo for a class was referenced in multiple source files. We had the correct linkage available in the buildTypeInfo function, but we weren't doing anything with it. This also prevented us from hitting the diagnostic saying that we should have set the comdat attribute for the typeinfo. This change fixes both of those problems.
>From deaebf9f3490a7f7ba93e14f62ebffea31ad615c Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Fri, 17 Apr 2026 12:31:16 -0700
Subject: [PATCH] [CIR] Fix typeinfo linkage and comdat
We weren't properly setting the linkage on typeinfo objects, leading to
multiple definition linking error when typeinfo for a class was
referenced in multiple source files. We had the correct linkage available
in the buildTypeInfo function, but we weren't doing anything with it.
This also prevented us from hitting the diagnostic saying that we
should have set the comdat attribute for the typeinfo. This change fixes
both of those problems.
---
clang/include/clang/CIR/MissingFeatures.h | 1 -
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 9 ++++-----
clang/test/CIR/CodeGen/rtti-member-pointer.cpp | 8 ++++----
clang/test/CIR/CodeGen/rtti-qualfn.cpp | 4 ++--
4 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 9fd9397e85e63..92d052de4e8db 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -39,7 +39,6 @@ struct MissingFeatures {
static bool opGlobalAnnotations() { return false; }
static bool opGlobalCtorPriority() { return false; }
static bool setDSOLocal() { return false; }
- static bool setComdat() { return false; }
static bool supportIFuncAttr() { return false; }
static bool supportVisibility() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 75658b23790bf..a1f2aabfe18bb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -1610,6 +1610,8 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
cir::GlobalOp gv =
CIRGenModule::createGlobalOp(cgm, loc, name, init.getType(),
/*isConstant=*/true);
+ gv.setLinkageAttr(
+ cir::GlobalLinkageKindAttr::get(&cgm.getMLIRContext(), linkage));
// Export the typeinfo in the same circumstances as the vtable is
// exported.
@@ -1629,11 +1631,8 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
oldGV->erase();
}
- if (cgm.supportsCOMDAT() && cir::isWeakForLinker(gv.getLinkage())) {
- assert(!cir::MissingFeatures::setComdat());
- cgm.errorNYI("buildTypeInfo: supportsCOMDAT & isWeakForLinker");
- return {};
- }
+ if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
+ gv.setComdat(true);
CharUnits align = cgm.getASTContext().toCharUnitsFromBits(
cgm.getTarget().getPointerAlign(LangAS::Default));
diff --git a/clang/test/CIR/CodeGen/rtti-member-pointer.cpp b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp
index f6c296e5c4dd4..b223857a9630c 100644
--- a/clang/test/CIR/CodeGen/rtti-member-pointer.cpp
+++ b/clang/test/CIR/CodeGen/rtti-member-pointer.cpp
@@ -25,8 +25,8 @@ void throw_data_member_ptr() {
// LLVM-DAG: @_ZTSM1Ai = linkonce_odr global [5 x i8] c"M1Ai\00", comdat
// LLVM-DAG: @_ZTS1A = linkonce_odr global [3 x i8] c"1A\00", comdat
-// LLVM-DAG: @_ZTI1A = constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 16), ptr @_ZTS1A }
-// LLVM-DAG: @_ZTIM1Ai = constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 16), ptr @_ZTSM1Ai, i32 0, ptr @_ZTIi, ptr @_ZTI1A }
+// LLVM-DAG: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 16), ptr @_ZTS1A }, comdat
+// LLVM-DAG: @_ZTIM1Ai = linkonce_odr constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 16), ptr @_ZTSM1Ai, i32 0, ptr @_ZTIi, ptr @_ZTI1A }, comdat
// LLVM-DAG: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIM1Ai, ptr null)
// OGCG-DAG: @_ZTSM1Ai = linkonce_odr constant [5 x i8] c"M1Ai\00", comdat
@@ -47,8 +47,8 @@ void throw_member_fn_ptr() {
// LLVM-DAG: @_ZTSM1AFvvE = linkonce_odr global [8 x i8] c"M1AFvvE\00", comdat
// LLVM-DAG: @_ZTSFvvE = linkonce_odr global [5 x i8] c"FvvE\00", comdat
-// LLVM-DAG: @_ZTIFvvE = constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 16), ptr @_ZTSFvvE }
-// LLVM-DAG: @_ZTIM1AFvvE = constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 16), ptr @_ZTSM1AFvvE, i32 0, ptr @_ZTIFvvE, ptr @_ZTI1A }
+// LLVM-DAG: @_ZTIFvvE = linkonce_odr constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 16), ptr @_ZTSFvvE }, comdat
+// LLVM-DAG: @_ZTIM1AFvvE = linkonce_odr constant { ptr, ptr, i32, ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 16), ptr @_ZTSM1AFvvE, i32 0, ptr @_ZTIFvvE, ptr @_ZTI1A }, comdat
// LLVM-DAG: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIM1AFvvE, ptr null)
// OGCG-DAG: @_ZTSM1AFvvE = linkonce_odr constant [8 x i8] c"M1AFvvE\00", comdat
diff --git a/clang/test/CIR/CodeGen/rtti-qualfn.cpp b/clang/test/CIR/CodeGen/rtti-qualfn.cpp
index ed9a06014480b..d57e7fce7915f 100644
--- a/clang/test/CIR/CodeGen/rtti-qualfn.cpp
+++ b/clang/test/CIR/CodeGen/rtti-qualfn.cpp
@@ -24,9 +24,9 @@ void f() noexcept {
// CIR: cir.throw %{{.*}} : !cir.ptr<!cir.ptr<!cir.func<()>>>, @_ZTIPDoFvvE
// LLVM-DAG: @_ZTSFvvE = linkonce_odr global [5 x i8] c"FvvE\00", comdat
-// LLVM-DAG: @_ZTIFvvE = constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 16), ptr @_ZTSFvvE }
+// LLVM-DAG: @_ZTIFvvE = linkonce_odr constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv120__function_type_infoE, i64 16), ptr @_ZTSFvvE }, comdat
// LLVM-DAG: @_ZTSPDoFvvE = linkonce_odr global [8 x i8] c"PDoFvvE\00", comdat
-// LLVM-DAG: @_ZTIPDoFvvE = constant { ptr, ptr, i32, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 16), ptr @_ZTSPDoFvvE, i32 64, ptr @_ZTIFvvE }
+// LLVM-DAG: @_ZTIPDoFvvE = linkonce_odr constant { ptr, ptr, i32, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 16), ptr @_ZTSPDoFvvE, i32 64, ptr @_ZTIFvvE }, comdat
// LLVM: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTIPDoFvvE, ptr null)
// OGCG-DAG: @_ZTSFvvE = linkonce_odr constant [5 x i8] c"FvvE\00", comdat
More information about the cfe-commits
mailing list