[clang] [clang-repl] fix vtable symbol duplication error (closes #141039) (PR #185648)
Emery Conrad via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 31 03:14:46 PDT 2026
================
@@ -1300,11 +1301,18 @@ void CodeGenModule::EmitDeferredVTables() {
size_t savedSize = DeferredVTables.size();
#endif
- for (const CXXRecordDecl *RD : DeferredVTables)
+ for (const CXXRecordDecl *RD : DeferredVTables) {
+ // if a table has been emitted in an earlier PTU, but was also marked
+ // deferred, we should skip if the linkage is external
+ if (EmittedVTables.count(RD) &&
+ getVTableLinkage(RD) == llvm::GlobalValue::ExternalLinkage)
----------------
conrade-ctc wrote:
Hmmm, maybe I'm not quite understanding the whole setup, but the existing logic emits vtables without key function bodies defined (like in the test for `inline-virtual.cpp`), so it needs to be re-emitted once all the defs are there. We can change that logic to not emit until all the defs have bodies, but this is a bit heavier logic... like we'll need to track how many bodies are undefined, and only emit when that drops to 0 for example (I had a solution that had this previously, but canned it for the simpler linkage check... but maybe that is the correct thing to do, even if it's a bit more logic). The linkage check is basically a short-cut to the direct tracking and relies on resolving this in linkage.
Just to illustrate directly, not paying attention to the linkage right now causes this to fail with an undefined symbol (from `clang/test/Interpreter/inline-virtual.cpp`):
```struct A { int a; A(int a) : a(a) {} virtual ~A(); };
// Then define the virtual destructor as inline out-of-line, in a separate
// PartialTranslationUnit.
inline A::~A() { printf("~A(%d)\n", a); }```
In this case, we have weak linkage, and may have emitted without a definition, so it has to be re-emitted or we will be missing a def.
https://github.com/llvm/llvm-project/pull/185648
More information about the cfe-commits
mailing list