[clang] [clang-repl] fix vtable symbol duplication error (closes #141039) (PR #185648)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 10 06:42:21 PDT 2026
https://github.com/conrade-ctc updated https://github.com/llvm/llvm-project/pull/185648
>From 05c2c79948547d0629f727111fe98502280f612f Mon Sep 17 00:00:00 2001
From: Emery Conrad <emery.conrad at chicagotrading.com>
Date: Tue, 10 Mar 2026 07:22:18 -0500
Subject: [PATCH] [clang-repl] fix vtable symbol duplication error
In incremental mode, emit by ExternalLinkage causes duplicate
symbol error. A single targeted change in getVTableLinkage()
fixes the issue by returning LinkOnceODRLinkage when
IncrementalExtensions is active. The JIT linker then keeps the first
definition a silently discards subsequent ones.
(Claude Sonnet 4.6 helped find this minimal delta)
---
clang/lib/CodeGen/CGVTables.cpp | 8 ++++++++
clang/test/Interpreter/virtualdef-outside.cpp | 19 +++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 clang/test/Interpreter/virtualdef-outside.cpp
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 3891697a986e4..cadc98169226a 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -1151,6 +1151,14 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
? llvm::GlobalVariable::LinkOnceODRLinkage
: llvm::Function::InternalLinkage;
+ // In incremental compilation, each partial translation unit is a separate
+ // LLVM module. Multiple PTUs may independently emit the vtable (once the
+ // key function's body is visible), causing duplicate symbol errors in the
+ // JIT. Use linkonce_odr so the JIT linker keeps the first definition and
+ // silently discards the rest, matching how template vtables work.
+ if (Context.getLangOpts().IncrementalExtensions)
+ return llvm::GlobalVariable::LinkOnceODRLinkage;
+
return llvm::GlobalVariable::ExternalLinkage;
case TSK_ImplicitInstantiation:
diff --git a/clang/test/Interpreter/virtualdef-outside.cpp b/clang/test/Interpreter/virtualdef-outside.cpp
new file mode 100644
index 0000000000000..a9198b3a22da5
--- /dev/null
+++ b/clang/test/Interpreter/virtualdef-outside.cpp
@@ -0,0 +1,19 @@
+// REQUIRES: host-supports-jit
+// RUN: cat %s | clang-repl | FileCheck %s
+// virtual functions defined outside of class had duplicate symbols:
+// duplicate definition of symbol '__ZTV3Two' (i.e., vtable for Two)
+// see https://github.com/llvm/llvm-project/issues/141039.
+// fixed in PR #185648
+
+extern "C" int printf(const char *, ...);
+
+struct One { virtual void print() { printf("ONE\n"); } };
+One().print();
+// CHECK: ONE
+
+struct Two { virtual void print(); };
+void Two::print() { printf("TWO\n"); }
+Two().print();
+// CHECK: TWO
+
+%quit
More information about the cfe-commits
mailing list