[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:36:58 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: None (conrade-ctc)

<details>
<summary>Changes</summary>

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.

closes issue #<!-- -->141039

---
Full diff: https://github.com/llvm/llvm-project/pull/185648.diff


2 Files Affected:

- (modified) clang/lib/CodeGen/CGVTables.cpp (+8) 
- (added) clang/test/Interpreter/virtualdef-outside.cpp (+19) 


``````````diff
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..fbb232ad68a8c
--- /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: XXX
+
+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

``````````

</details>


https://github.com/llvm/llvm-project/pull/185648


More information about the cfe-commits mailing list