[clang] 91d40ef - Revert "[C++20] [Modules] [Itanium ABI] Generate the vtable in the module unit of dynamic classes (#75912)"
Chuanqi Xu via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 9 20:00:11 PDT 2024
Author: Chuanqi Xu
Date: 2024-07-10T10:58:18+08:00
New Revision: 91d40ef6e369a73b0147d9153a95c3bc63e14102
URL: https://github.com/llvm/llvm-project/commit/91d40ef6e369a73b0147d9153a95c3bc63e14102
DIFF: https://github.com/llvm/llvm-project/commit/91d40ef6e369a73b0147d9153a95c3bc63e14102.diff
LOG: Revert "[C++20] [Modules] [Itanium ABI] Generate the vtable in the module unit of dynamic classes (#75912)"
This reverts commit 18f3bcbb13ca83d33223b00761d8cddf463e9ffb, 15bb02650e26875c48889053d6a9697444583721 and
99873b35da7ecb905143c8a6b8deca4d4416f1a9.
See the post commit message in
https://github.com/llvm/llvm-project/pull/75912 to see the reasons.
Added:
Modified:
clang/include/clang/AST/DeclBase.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/include/clang/Serialization/ASTReader.h
clang/include/clang/Serialization/ASTWriter.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/Decl.cpp
clang/lib/AST/DeclBase.cpp
clang/lib/CodeGen/CGVTables.cpp
clang/lib/CodeGen/ItaniumCXXABI.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/test/CodeGenCXX/modules-vtable.cppm
Removed:
clang/test/CodeGenCXX/pr70585.cppm
clang/test/Modules/pr97313.cppm
################################################################################
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 45dac82e54077..06ffc2ce09b89 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -670,16 +670,6 @@ class alignas(8) Decl {
/// Whether this declaration comes from another module unit.
bool isInAnotherModuleUnit() const;
- /// Whether this declaration comes from the same module unit being compiled.
- bool isInCurrentModuleUnit() const;
-
- /// Whether the definition of the declaration should be emitted in external
- /// sources.
- bool shouldEmitInExternalSource() const;
-
- /// Whether this declaration comes from a named module;
- bool isInNamedModule() const;
-
/// Whether this declaration comes from explicit global module.
bool isFromExplicitGlobalModule() const;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 38502a23f805e..488994c05dc12 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -721,9 +721,6 @@ enum ASTRecordTypes {
/// Record code for \#pragma clang unsafe_buffer_usage begin/end
PP_UNSAFE_BUFFER_USAGE = 69,
-
- /// Record code for vtables to emit.
- VTABLES_TO_EMIT = 70,
};
/// Record types used within a source manager block.
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index f41c473c97cd9..76e51ac7ab979 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -790,11 +790,6 @@ class ASTReader
/// the consumer eagerly.
SmallVector<GlobalDeclID, 16> EagerlyDeserializedDecls;
- /// The IDs of all vtables to emit. The referenced declarations are passed
- /// to the consumers's HandleVTable eagerly after passing
- /// EagerlyDeserializedDecls.
- SmallVector<GlobalDeclID, 16> VTablesToEmit;
-
/// The IDs of all tentative definitions stored in the chain.
///
/// Sema keeps track of all tentative definitions in a TU because it has to
@@ -1505,7 +1500,6 @@ class ASTReader
bool isConsumerInterestedIn(Decl *D);
void PassInterestingDeclsToConsumer();
void PassInterestingDeclToConsumer(Decl *D);
- void PassVTableToConsumer(CXXRecordDecl *RD);
void finishPendingActions();
void diagnoseOdrViolations();
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 71a7c28047e31..a0e475ec9f862 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -500,10 +500,6 @@ class ASTWriter : public ASTDeserializationListener,
std::vector<SourceRange> NonAffectingRanges;
std::vector<SourceLocation::UIntTy> NonAffectingOffsetAdjustments;
- /// A list of classes which need to emit the VTable in the corresponding
- /// object file.
- llvm::SmallVector<CXXRecordDecl *> PendingEmittingVTables;
-
/// Computes input files that didn't affect compilation of the current module,
/// and initializes data structures necessary for leaving those files out
/// during \c SourceManager serialization.
@@ -861,8 +857,6 @@ class ASTWriter : public ASTDeserializationListener,
return PredefinedDecls.count(D);
}
- void handleVTable(CXXRecordDecl *RD);
-
private:
// ASTDeserializationListener implementation
void ReaderInitialized(ASTReader *Reader) override;
@@ -957,7 +951,6 @@ class PCHGenerator : public SemaConsumer {
void InitializeSema(Sema &S) override { SemaPtr = &S; }
void HandleTranslationUnit(ASTContext &Ctx) override;
- void HandleVTable(CXXRecordDecl *RD) override { Writer.handleVTable(RD); }
ASTMutationListener *GetASTMutationListener() override;
ASTDeserializationListener *GetASTDeserializationListener() override;
bool hasEmittedPCH() const { return Buffer->IsComplete; }
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 84deaf5429df7..8e35e71d4a23e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -12116,7 +12116,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;
// Variables in other module units shouldn't be forced to be emitted.
- if (VD->shouldEmitInExternalSource())
+ if (VD->isInAnotherModuleUnit())
return false;
// Variables that can be needed in other TUs are required.
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 490c4a2fc525c..ecccab08cbaab 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1181,6 +1181,13 @@ Linkage NamedDecl::getLinkageInternal() const {
.getLinkage();
}
+/// Determine whether D is attached to a named module.
+static bool isInNamedModule(const NamedDecl *D) {
+ if (auto *M = D->getOwningModule())
+ return M->isNamedModule();
+ return false;
+}
+
static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
// FIXME: Handle isModulePrivate.
switch (D->getModuleOwnershipKind()) {
@@ -1190,7 +1197,7 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
return false;
case Decl::ModuleOwnershipKind::Visible:
case Decl::ModuleOwnershipKind::VisibleWhenImported:
- return D->isInNamedModule();
+ return isInNamedModule(D);
}
llvm_unreachable("unexpected module ownership kind");
}
@@ -1208,7 +1215,7 @@ Linkage NamedDecl::getFormalLinkage() const {
// [basic.namespace.general]/p2
// A namespace is never attached to a named module and never has a name with
// module linkage.
- if (isInNamedModule() && InternalLinkage == Linkage::External &&
+ if (isInNamedModule(this) && InternalLinkage == Linkage::External &&
!isExportedFromModuleInterfaceUnit(
cast<NamedDecl>(this->getCanonicalDecl())) &&
!isa<NamespaceDecl>(this))
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 98c55d6f4eba4..eef946e3aea2e 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1122,31 +1122,23 @@ bool Decl::isInExportDeclContext() const {
bool Decl::isInAnotherModuleUnit() const {
auto *M = getOwningModule();
- if (!M || !M->isNamedModule())
+ if (!M)
return false;
- return M != getASTContext().getCurrentNamedModule();
-}
-
-bool Decl::isInCurrentModuleUnit() const {
- auto *M = getOwningModule();
-
- if (!M || !M->isNamedModule())
+ M = M->getTopLevelModule();
+ // FIXME: It is problematic if the header module lives in another module
+ // unit. Consider to fix this by techniques like
+ // ExternalASTSource::hasExternalDefinitions.
+ if (M->isHeaderLikeModule())
return false;
- return M == getASTContext().getCurrentNamedModule();
-}
-
-bool Decl::shouldEmitInExternalSource() const {
- ExternalASTSource *Source = getASTContext().getExternalSource();
- if (!Source)
+ // A global module without parent implies that we're parsing the global
+ // module. So it can't be in another module unit.
+ if (M->isGlobalModule())
return false;
- return Source->hasExternalDefinitions(this) == ExternalASTSource::EK_Always;
-}
-
-bool Decl::isInNamedModule() const {
- return getOwningModule() && getOwningModule()->isNamedModule();
+ assert(M->isNamedModule() && "New module kind?");
+ return M != getASTContext().getCurrentNamedModule();
}
bool Decl::isFromExplicitGlobalModule() const {
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 10d972ec8a362..7f729d359b82b 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -1079,38 +1079,28 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;
- bool IsInNamedModule = RD->isInNamedModule();
- // If the CXXRecordDecl are not in a module unit, we need to get
- // its key function. We're at the end of the translation unit, so the current
- // key function is fully correct.
- const CXXMethodDecl *keyFunction =
- IsInNamedModule ? nullptr : Context.getCurrentKeyFunction(RD);
- if (IsInNamedModule || (keyFunction && !RD->hasAttr<DLLImportAttr>())) {
+ // We're at the end of the translation unit, so the current key
+ // function is fully correct.
+ const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD);
+ if (keyFunction && !RD->hasAttr<DLLImportAttr>()) {
// If this class has a key function, use that to determine the
// linkage of the vtable.
const FunctionDecl *def = nullptr;
- if (keyFunction && keyFunction->hasBody(def))
+ if (keyFunction->hasBody(def))
keyFunction = cast<CXXMethodDecl>(def);
- bool IsExternalDefinition =
- IsInNamedModule ? RD->shouldEmitInExternalSource() : !def;
-
- TemplateSpecializationKind Kind =
- IsInNamedModule ? RD->getTemplateSpecializationKind()
- : keyFunction->getTemplateSpecializationKind();
-
- switch (Kind) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
+ switch (keyFunction->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
assert(
- (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
+ (def || CodeGenOpts.OptimizationLevel > 0 ||
CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
- "Shouldn't query vtable linkage without the class in module units, "
- "key function, optimizations, or debug info");
- if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
+ "Shouldn't query vtable linkage without key function, "
+ "optimizations, or debug info");
+ if (!def && CodeGenOpts.OptimizationLevel > 0)
return llvm::GlobalVariable::AvailableExternallyLinkage;
- if (keyFunction && keyFunction->isInlined())
+ if (keyFunction->isInlined())
return !Context.getLangOpts().AppleKext
? llvm::GlobalVariable::LinkOnceODRLinkage
: llvm::Function::InternalLinkage;
@@ -1129,7 +1119,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
case TSK_ExplicitInstantiationDeclaration:
llvm_unreachable("Should not have been asked to emit this");
- }
+ }
}
// -fapple-kext mode does not support weak linkage, so we must use
@@ -1223,21 +1213,6 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
TSK == TSK_ExplicitInstantiationDefinition)
return false;
- // Itanium C++ ABI [5.2.3]:
- // Virtual tables for dynamic classes are emitted as follows:
- //
- // - If the class is templated, the tables are emitted in every object that
- // references any of them.
- // - Otherwise, if the class is attached to a module, the tables are uniquely
- // emitted in the object for the module unit in which it is defined.
- // - Otherwise, if the class has a key function (see below), the tables are
- // emitted in the object for the translation unit containing the definition of
- // the key function. This is unique if the key function is not inline.
- // - Otherwise, the tables are emitted in every object that references any of
- // them.
- if (RD->isInNamedModule())
- return RD->shouldEmitInExternalSource();
-
// Otherwise, if the class doesn't have a key function (possibly
// anymore), the vtable must be defined here.
const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
@@ -1247,7 +1222,13 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
const FunctionDecl *Def;
// Otherwise, if we don't have a definition of the key function, the
// vtable must be defined somewhere else.
- return !keyFunction->hasBody(Def);
+ if (!keyFunction->hasBody(Def))
+ return true;
+
+ assert(Def && "The body of the key function is not assigned to Def?");
+ // If the non-inline key function comes from another module unit, the vtable
+ // must be defined there.
+ return Def->isInAnotherModuleUnit() && !Def->isInlineSpecified();
}
/// Given that we're currently at the end of the translation unit, and
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 63e36e1b83893..e1d056765a866 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2161,9 +2161,6 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
if (!canSpeculativelyEmitVTableAsBaseClass(RD))
return false;
- if (RD->shouldEmitInExternalSource())
- return false;
-
// For a complete-object vtable (or more specifically, for the VTT), we need
// to be able to speculatively emit the vtables of all dynamic virtual bases.
for (const auto &B : RD->vbases()) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 97e1f7e05e44e..d1c7b9d5ae507 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10094,7 +10094,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// check at the end of the TU (or when the PMF starts) to see that we
// have a definition at that point.
if (isInline && !D.isFunctionDefinition() && getLangOpts().CPlusPlus20 &&
- NewFD->isInNamedModule()) {
+ NewFD->hasOwningModule() && NewFD->getOwningModule()->isNamedModule()) {
PendingInlineFuncDecls.insert(NewFD);
}
}
@@ -18031,15 +18031,6 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
if (NumInitMethods > 1 || !Def->hasInitMethod())
Diag(RD->getLocation(), diag::err_sycl_special_type_num_init_method);
}
-
- // If we're defining a dynamic class in a module interface unit, we always
- // need to produce the vtable for it even if the vtable is not used in the
- // current TU.
- //
- // The case that the current class is not dynamic is handled in
- // MarkVTableUsed.
- if (getCurrentModule() && getCurrentModule()->isInterfaceOrPartition())
- MarkVTableUsed(RD->getLocation(), RD, /*DefinitionRequired=*/true);
}
// Exit this scope of this tag's definition.
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 490cd6e864c43..a7da5285ad0e4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18455,15 +18455,11 @@ bool Sema::DefineUsedVTables() {
bool DefineVTable = true;
+ // If this class has a key function, but that key function is
+ // defined in another translation unit, we don't need to emit the
+ // vtable even though we're using it.
const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
- // V-tables for non-template classes with an owning module are always
- // uniquely emitted in that module.
- if (Class->isInCurrentModuleUnit())
- DefineVTable = true;
- else if (KeyFunction && !KeyFunction->hasBody()) {
- // If this class has a key function, but that key function is
- // defined in another translation unit, we don't need to emit the
- // vtable even though we're using it.
+ if (KeyFunction && !KeyFunction->hasBody()) {
// The key function is in another translation unit.
DefineVTable = false;
TemplateSpecializationKind TSK =
@@ -18508,7 +18504,7 @@ bool Sema::DefineUsedVTables() {
DefinedAnything = true;
MarkVirtualMembersReferenced(Loc, Class);
CXXRecordDecl *Canonical = Class->getCanonicalDecl();
- if (VTablesUsed[Canonical] && !Class->shouldEmitInExternalSource())
+ if (VTablesUsed[Canonical])
Consumer.HandleVTable(Class);
// Warn if we're emitting a weak vtable. The vtable will be weak if there is
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 079ac3f0e3545..afdeccaf93a9d 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -3921,13 +3921,6 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
}
break;
- case VTABLES_TO_EMIT:
- if (F.Kind == MK_MainFile ||
- getContext().getLangOpts().BuildingPCHWithObjectFile)
- for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/)
- VTablesToEmit.push_back(ReadDeclID(F, Record, I));
- break;
-
case IMPORTED_MODULES:
if (!F.isModule()) {
// If we aren't loading a module (which has its own exports), make
@@ -8117,10 +8110,6 @@ void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
Consumer->HandleInterestingDecl(DeclGroupRef(D));
}
-void ASTReader::PassVTableToConsumer(CXXRecordDecl *RD) {
- Consumer->HandleVTable(RD);
-}
-
void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
this->Consumer = Consumer;
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index cf3737c5a501d..cbaf1b0a98c61 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -4235,13 +4235,6 @@ void ASTReader::PassInterestingDeclsToConsumer() {
// If we add any new potential interesting decl in the last call, consume it.
ConsumingPotentialInterestingDecls();
-
- for (GlobalDeclID ID : VTablesToEmit) {
- auto *RD = cast<CXXRecordDecl>(GetDecl(ID));
- assert(!RD->shouldEmitInExternalSource());
- PassVTableToConsumer(RD);
- }
- VTablesToEmit.clear();
}
void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index c88fb002cb8ec..5b5b468532f32 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -927,7 +927,6 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS);
RECORD(PP_ASSUME_NONNULL_LOC);
RECORD(PP_UNSAFE_BUFFER_USAGE);
- RECORD(VTABLES_TO_EMIT);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -3962,10 +3961,6 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents);
}
-void ASTWriter::handleVTable(CXXRecordDecl *RD) {
- PendingEmittingVTables.push_back(RD);
-}
-
//===----------------------------------------------------------------------===//
// DeclContext's Name Lookup Table Serialization
//===----------------------------------------------------------------------===//
@@ -5168,13 +5163,6 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
// Write all of the DeclsToCheckForDeferredDiags.
for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)
GetDeclRef(D);
-
- // Write all classes need to emit the vtable definitions if required.
- if (isWritingStdCXXNamedModules())
- for (CXXRecordDecl *RD : PendingEmittingVTables)
- GetDeclRef(RD);
- else
- PendingEmittingVTables.clear();
}
void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
@@ -5329,17 +5317,6 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
}
if (!DeleteExprsToAnalyze.empty())
Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);
-
- RecordData VTablesToEmit;
- for (CXXRecordDecl *RD : PendingEmittingVTables) {
- if (!wasDeclEmitted(RD))
- continue;
-
- AddDeclRef(RD, VTablesToEmit);
- }
-
- if (!VTablesToEmit.empty())
- Stream.EmitRecord(VTABLES_TO_EMIT, VTablesToEmit);
}
ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
@@ -6587,12 +6564,10 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
// computed.
Record->push_back(D->getODRHash());
- bool ModulesCodegen =
- !D->isDependentType() &&
- (Writer->Context->getLangOpts().ModulesDebugInfo ||
- D->isInNamedModule());
- Record->push_back(ModulesCodegen);
- if (ModulesCodegen)
+ bool ModulesDebugInfo =
+ Writer->Context->getLangOpts().ModulesDebugInfo && !D->isDependentType();
+ Record->push_back(ModulesDebugInfo);
+ if (ModulesDebugInfo)
Writer->AddDeclRef(D, Writer->ModularCodegenDecls);
// IsLambda bit is already saved.
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 59d94c3d79824..b6583c54c9ba1 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1537,14 +1537,8 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (D->isThisDeclarationADefinition())
Record.AddCXXDefinitionData(D);
- if (D->isCompleteDefinition() && D->isInNamedModule())
- Writer.AddDeclRef(D, Writer.ModularCodegenDecls);
-
// Store (what we currently believe to be) the key function to avoid
// deserializing every method so we can compute it.
- //
- // FIXME: Avoid adding the key function if the class is defined in
- // module purview since the key function is meaningless in module purview.
if (D->isCompleteDefinition())
Record.AddDeclRef(Context.getCurrentKeyFunction(D));
diff --git a/clang/test/CodeGenCXX/modules-vtable.cppm b/clang/test/CodeGenCXX/modules-vtable.cppm
index 5cc3504d72628..fb179b1de4880 100644
--- a/clang/test/CodeGenCXX/modules-vtable.cppm
+++ b/clang/test/CodeGenCXX/modules-vtable.cppm
@@ -24,8 +24,6 @@
// RUN: %t/M-A.cppm -o %t/M-A.pcm
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -fmodule-file=M:A=%t/M-A.pcm \
// RUN: %t/M-B.cppm -emit-llvm -o - | FileCheck %t/M-B.cppm
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 \
-// RUN: %t/M-A.pcm -emit-llvm -o - | FileCheck %t/M-A.cppm
//--- Mod.cppm
export module Mod;
@@ -43,10 +41,9 @@ Base::~Base() {}
// CHECK: @_ZTSW3Mod4Base = constant
// CHECK: @_ZTIW3Mod4Base = constant
-// With the new Itanium C++ ABI, the linkage of vtables in modules don't need to be linkonce ODR.
-// CHECK-INLINE: @_ZTVW3Mod4Base = {{.*}}unnamed_addr constant
-// CHECK-INLINE: @_ZTSW3Mod4Base = {{.*}}constant
-// CHECK-INLINE: @_ZTIW3Mod4Base = {{.*}}constant
+// CHECK-INLINE: @_ZTVW3Mod4Base = linkonce_odr {{.*}}unnamed_addr constant
+// CHECK-INLINE: @_ZTSW3Mod4Base = linkonce_odr {{.*}}constant
+// CHECK-INLINE: @_ZTIW3Mod4Base = linkonce_odr {{.*}}constant
module :private;
int private_use() {
@@ -61,13 +58,13 @@ int use() {
return 43;
}
-// CHECK-NOT: @_ZTSW3Mod4Base
-// CHECK-NOT: @_ZTIW3Mod4Base
-// CHECK: @_ZTVW3Mod4Base = external
+// CHECK-NOT: @_ZTSW3Mod4Base = constant
+// CHECK-NOT: @_ZTIW3Mod4Base = constant
+// CHECK: @_ZTVW3Mod4Base = external unnamed_addr
-// CHECK-INLINE-NOT: @_ZTSW3Mod4Base
-// CHECK-INLINE-NOT: @_ZTIW3Mod4Base
-// CHECK-INLINE: @_ZTVW3Mod4Base = external
+// CHECK-INLINE: @_ZTVW3Mod4Base = linkonce_odr {{.*}}unnamed_addr constant
+// CHECK-INLINE: @_ZTSW3Mod4Base = linkonce_odr {{.*}}constant
+// CHECK-INLINE: @_ZTIW3Mod4Base = linkonce_odr {{.*}}constant
// Check the case that the declaration of the key function comes from another
// module unit but the definition of the key function comes from the current
@@ -85,10 +82,6 @@ int a_use() {
return 43;
}
-// CHECK: @_ZTVW1M1C = unnamed_addr constant
-// CHECK: @_ZTSW1M1C = constant
-// CHECK: @_ZTIW1M1C = constant
-
//--- M-B.cppm
export module M:B;
import :A;
@@ -100,6 +93,6 @@ int b_use() {
return 43;
}
-// CHECK: @_ZTVW1M1C = external
-// CHECK-NOT: @_ZTSW1M1C
-// CHECK-NOT: @_ZTIW1M1C
+// CHECK: @_ZTVW1M1C = unnamed_addr constant
+// CHECK: @_ZTSW1M1C = constant
+// CHECK: @_ZTIW1M1C = constant
diff --git a/clang/test/CodeGenCXX/pr70585.cppm b/clang/test/CodeGenCXX/pr70585.cppm
deleted file mode 100644
index ad4e13589d86e..0000000000000
--- a/clang/test/CodeGenCXX/pr70585.cppm
+++ /dev/null
@@ -1,47 +0,0 @@
-// REQUIRES: !system-windows
-
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: cd %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/layer1.cppm -triple %itanium_abi_triple \
-// RUN: -emit-module-interface -o %t/foo-layer1.pcm
-// RUN: %clang_cc1 -std=c++20 %t/layer2.cppm -triple %itanium_abi_triple \
-// RUN: -emit-module-interface -fmodule-file=foo:layer1=%t/foo-layer1.pcm \
-// RUN: -o %t/foo-layer2.pcm
-// RUN: %clang_cc1 -std=c++20 %t/foo-layer1.pcm -emit-llvm -o - | FileCheck %t/layer1.cppm
-// RUN: %clang_cc1 -std=c++20 %t/foo-layer2.pcm -emit-llvm -o - \
-// RUN: -fmodule-file=foo:layer1=%t/foo-layer1.pcm | FileCheck %t/layer2.cppm
-//
-// Check the case about emitting object files from sources directly.
-// RUN: %clang_cc1 -std=c++20 %t/layer1.cppm -triple %itanium_abi_triple \
-// RUN: -emit-llvm -o - | FileCheck %t/layer1.cppm
-// RUN: %clang_cc1 -std=c++20 %t/layer2.cppm -triple %itanium_abi_triple -emit-llvm \
-// RUN: -fmodule-file=foo:layer1=%t/foo-layer1.pcm -o - | FileCheck %t/layer2.cppm
-
-//--- layer1.cppm
-export module foo:layer1;
-struct Fruit {
- virtual ~Fruit() = default;
- virtual void eval();
-};
-
-// CHECK-DAG: @_ZTVW3foo5Fruit = unnamed_addr constant
-// CHECK-DAG: @_ZTSW3foo5Fruit = constant
-// CHECK-DAG: @_ZTIW3foo5Fruit = constant
-
-// Testing that:
-// (1) The use of virtual functions won't produce the vtable.
-// (2) The definition of key functions won't produce the vtable.
-//
-//--- layer2.cppm
-export module foo:layer2;
-import :layer1;
-export void layer2_fun() {
- Fruit *b = new Fruit();
- b->eval();
-}
-void Fruit::eval() {}
-// CHECK: @_ZTVW3foo5Fruit = external unnamed_addr constant
-// CHECK-NOT: @_ZTSW3foo5Fruit
-// CHECK-NOT: @_ZTIW3foo5Fruit
diff --git a/clang/test/Modules/pr97313.cppm b/clang/test/Modules/pr97313.cppm
deleted file mode 100644
index ebbd0ee4e2c65..0000000000000
--- a/clang/test/Modules/pr97313.cppm
+++ /dev/null
@@ -1,118 +0,0 @@
-// REQUIRES: !system-windows
-//
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Base.cppm \
-// RUN: -emit-module-interface -o %t/Base.pcm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Sub.cppm \
-// RUN: -emit-module-interface -o %t/Sub.pcm -fprebuilt-module-path=%t
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Sub.pcm \
-// RUN: -emit-llvm -o %t/Sub.pcm -o - -fprebuilt-module-path=%t | \
-// RUN: FileCheck %t/Sub.cppm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/main.cpp \
-// RUN: -emit-llvm -fprebuilt-module-path=%t -o - | FileCheck %t/main.cpp
-//
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Mod.cppm \
-// RUN: -emit-module-interface -o %t/Mod.pcm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Mod.pcm \
-// RUN: -emit-llvm -o - | FileCheck %t/Mod.cppm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Use.cpp \
-// RUN: -emit-llvm -fprebuilt-module-path=%t -o - | \
-// RUN: FileCheck %t/Use.cpp
-
-//--- Base.cppm
-export module Base;
-
-export template <class>
-class Base
-{
-public:
- constexpr Base();
- constexpr virtual ~Base();
-};
-
-template <class X>
-constexpr Base<X>::Base() = default;
-
-template <class X>
-constexpr Base<X>::~Base() = default;
-
-//--- Sub.cppm
-export module Sub;
-export import Base;
-
-export class Sub : public Base<int>
-{
-};
-
-// CHECK: @_ZTIW4Base4BaseIiE = {{.*}}linkonce_odr
-
-//--- main.cpp
-import Sub;
-
-int main()
-{
- Base<int> *b = new Sub();
- delete b;
-}
-
-// CHECK: @_ZTIW4Base4BaseIiE = {{.*}}linkonce_odr
-
-//--- Mod.cppm
-export module Mod;
-
-export class NonTemplate {
-public:
- virtual ~NonTemplate();
-};
-
-// CHECK: @_ZTIW3Mod11NonTemplate = {{.*}}constant
-
-export template <class C>
-class Template {
-public:
- virtual ~Template();
-};
-
-export template<>
-class Template<char> {
-public:
- virtual ~Template();
-};
-
-// CHECK: @_ZTIW3Mod8TemplateIcE = {{.*}}constant
-
-export template class Template<unsigned>;
-
-// CHECK: @_ZTIW3Mod8TemplateIjE = {{.*}}weak_odr
-
-export extern template class Template<double>;
-
-auto v = new Template<signed int>();
-
-// CHECK: @_ZTIW3Mod8TemplateIiE = {{.*}}linkonce_odr
-
-//--- Use.cpp
-import Mod;
-
-auto v1 = new NonTemplate();
-auto v2 = new Template<char>();
-auto v3 = new Template<unsigned>();
-auto v4 = new Template<double>();
-auto v5 = new Template<signed int>();
-auto v6 = new Template<NonTemplate>();
-
-// CHECK: @_ZTVW3Mod11NonTemplate = {{.*}}external
-// CHECK: @_ZTVW3Mod8TemplateIcE = {{.*}}external
-// CHECK: @_ZTVW3Mod8TemplateIjE = {{.*}}weak_odr
-// CHECK: @_ZTSW3Mod8TemplateIjE = {{.*}}weak_odr
-// CHECK: @_ZTIW3Mod8TemplateIjE = {{.*}}weak_odr
-// CHECK: @_ZTVW3Mod8TemplateIdE = {{.*}}external
-// CHECK: @_ZTVW3Mod8TemplateIiE = {{.*}}linkonce_odr
-// CHECK: @_ZTSW3Mod8TemplateIiE = {{.*}}linkonce_odr
-// CHECK: @_ZTIW3Mod8TemplateIiE = {{.*}}linkonce_odr
-// CHECK: @_ZTVW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr
-// CHECK: @_ZTSW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr
-// CHECK: @_ZTIW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr
More information about the cfe-commits
mailing list