Index: clang/lib/CodeGen/CGVTables.cpp =================================================================== --- clang/lib/CodeGen/CGVTables.cpp +++ clang/lib/CodeGen/CGVTables.cpp @@ -1174,7 +1174,17 @@ // Otherwise, if we don't have a definition of the key function, the // vtable must be defined somewhere else. - return !keyFunction->hasBody(); + if (!keyFunction->hasBody()) + return true; + + // If the class comes from another translation unit, the vtable must be + // defined there. + if (auto *M = RD->getOwningModule(); + M && M->getTopLevelModule()->isModulePurview() && + M->getTopLevelModule() != CGM.getContext().getNamedModuleForCodeGen()) + return true; + + return false; } /// Given that we're currently at the end of the translation unit, and Index: clang/test/CodeGenCXX/modules-vtable.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/modules-vtable.cppm @@ -0,0 +1,58 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -emit-module-interface \ +// RUN: %t/Base.cppm -o %t/Base.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -emit-module-interface \ +// RUN: %t/Sub.cppm -o %t/Sub.pcm -fmodule-file=Mod:Base=%t/Base.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -emit-module-interface \ +// RUN: %t/Mod.cppm -o %t/Mod.pcm -fmodule-file=Mod:Base=%t/Base.pcm \ +// RUN: -fmodule-file=Mod:Sub=%t/Sub.pcm +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/Base.pcm \ +// RUN: -emit-llvm -o - | FileCheck %t/Base.cppm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -fmodule-file=Mod=%t/Mod.pcm \ +// RUN: %t/Use.cpp -emit-llvm -o - | FileCheck %t/Use.cpp + +//--- Base.cppm +export module Mod:Base; +export class Base { +public: + Base(); + virtual ~Base(); +}; +Base::Base() {} +Base::~Base() {} + +// CHECK: @_ZTVW3Mod4Base = unnamed_addr constant +// CHECK: @_ZTSW3Mod4Base = constant +// CHECK: @_ZTIW3Mod4Base = constant + +//--- Sub.cppm +export module Mod:Sub; +import :Base; +export class Sub : public Base { + +}; + +// CHECK + +//--- Mod.cppm +export module Mod; +export import :Base; +export import :Sub; + +//--- Use.cpp +import Mod; +int use() { + Base *b = new Sub(); +} + +// CHECK-NOT: @_ZTSW3Mod4Base = constant +// CHECK-NOT: @_ZTIW3Mod4Base = constant + +// CHECK-DAG: @_ZTVW3Mod3Sub = linkonce_odr unnamed_addr +// CHECK-DAG: @_ZTSW3Mod3Sub = linkonce_odr +// CHECK-DAG: @_ZTIW3Mod4Base = external constant ptr +// CHECK-DAG: @_ZTIW3Mod3Sub = linkonce_odr