Skip to content

Commit 91d40ef

Browse files
committed
Revert "[C++20] [Modules] [Itanium ABI] Generate the vtable in the module unit of dynamic classes (#75912)"
This reverts commit 18f3bcb, 15bb026 and 99873b3. See the post commit message in #75912 to see the reasons.
1 parent 9af1f8f commit 91d40ef

18 files changed

+64
-347
lines changed

clang/include/clang/AST/DeclBase.h

-10
Original file line numberDiff line numberDiff line change
@@ -670,16 +670,6 @@ class alignas(8) Decl {
670670
/// Whether this declaration comes from another module unit.
671671
bool isInAnotherModuleUnit() const;
672672

673-
/// Whether this declaration comes from the same module unit being compiled.
674-
bool isInCurrentModuleUnit() const;
675-
676-
/// Whether the definition of the declaration should be emitted in external
677-
/// sources.
678-
bool shouldEmitInExternalSource() const;
679-
680-
/// Whether this declaration comes from a named module;
681-
bool isInNamedModule() const;
682-
683673
/// Whether this declaration comes from explicit global module.
684674
bool isFromExplicitGlobalModule() const;
685675

clang/include/clang/Serialization/ASTBitCodes.h

-3
Original file line numberDiff line numberDiff line change
@@ -721,9 +721,6 @@ enum ASTRecordTypes {
721721

722722
/// Record code for \#pragma clang unsafe_buffer_usage begin/end
723723
PP_UNSAFE_BUFFER_USAGE = 69,
724-
725-
/// Record code for vtables to emit.
726-
VTABLES_TO_EMIT = 70,
727724
};
728725

729726
/// Record types used within a source manager block.

clang/include/clang/Serialization/ASTReader.h

-6
Original file line numberDiff line numberDiff line change
@@ -790,11 +790,6 @@ class ASTReader
790790
/// the consumer eagerly.
791791
SmallVector<GlobalDeclID, 16> EagerlyDeserializedDecls;
792792

793-
/// The IDs of all vtables to emit. The referenced declarations are passed
794-
/// to the consumers's HandleVTable eagerly after passing
795-
/// EagerlyDeserializedDecls.
796-
SmallVector<GlobalDeclID, 16> VTablesToEmit;
797-
798793
/// The IDs of all tentative definitions stored in the chain.
799794
///
800795
/// Sema keeps track of all tentative definitions in a TU because it has to
@@ -1505,7 +1500,6 @@ class ASTReader
15051500
bool isConsumerInterestedIn(Decl *D);
15061501
void PassInterestingDeclsToConsumer();
15071502
void PassInterestingDeclToConsumer(Decl *D);
1508-
void PassVTableToConsumer(CXXRecordDecl *RD);
15091503

15101504
void finishPendingActions();
15111505
void diagnoseOdrViolations();

clang/include/clang/Serialization/ASTWriter.h

-7
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,6 @@ class ASTWriter : public ASTDeserializationListener,
500500
std::vector<SourceRange> NonAffectingRanges;
501501
std::vector<SourceLocation::UIntTy> NonAffectingOffsetAdjustments;
502502

503-
/// A list of classes which need to emit the VTable in the corresponding
504-
/// object file.
505-
llvm::SmallVector<CXXRecordDecl *> PendingEmittingVTables;
506-
507503
/// Computes input files that didn't affect compilation of the current module,
508504
/// and initializes data structures necessary for leaving those files out
509505
/// during \c SourceManager serialization.
@@ -861,8 +857,6 @@ class ASTWriter : public ASTDeserializationListener,
861857
return PredefinedDecls.count(D);
862858
}
863859

864-
void handleVTable(CXXRecordDecl *RD);
865-
866860
private:
867861
// ASTDeserializationListener implementation
868862
void ReaderInitialized(ASTReader *Reader) override;
@@ -957,7 +951,6 @@ class PCHGenerator : public SemaConsumer {
957951

958952
void InitializeSema(Sema &S) override { SemaPtr = &S; }
959953
void HandleTranslationUnit(ASTContext &Ctx) override;
960-
void HandleVTable(CXXRecordDecl *RD) override { Writer.handleVTable(RD); }
961954
ASTMutationListener *GetASTMutationListener() override;
962955
ASTDeserializationListener *GetASTDeserializationListener() override;
963956
bool hasEmittedPCH() const { return Buffer->IsComplete; }

clang/lib/AST/ASTContext.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -12116,7 +12116,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
1211612116
return false;
1211712117

1211812118
// Variables in other module units shouldn't be forced to be emitted.
12119-
if (VD->shouldEmitInExternalSource())
12119+
if (VD->isInAnotherModuleUnit())
1212012120
return false;
1212112121

1212212122
// Variables that can be needed in other TUs are required.

clang/lib/AST/Decl.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,13 @@ Linkage NamedDecl::getLinkageInternal() const {
11811181
.getLinkage();
11821182
}
11831183

1184+
/// Determine whether D is attached to a named module.
1185+
static bool isInNamedModule(const NamedDecl *D) {
1186+
if (auto *M = D->getOwningModule())
1187+
return M->isNamedModule();
1188+
return false;
1189+
}
1190+
11841191
static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
11851192
// FIXME: Handle isModulePrivate.
11861193
switch (D->getModuleOwnershipKind()) {
@@ -1190,7 +1197,7 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
11901197
return false;
11911198
case Decl::ModuleOwnershipKind::Visible:
11921199
case Decl::ModuleOwnershipKind::VisibleWhenImported:
1193-
return D->isInNamedModule();
1200+
return isInNamedModule(D);
11941201
}
11951202
llvm_unreachable("unexpected module ownership kind");
11961203
}
@@ -1208,7 +1215,7 @@ Linkage NamedDecl::getFormalLinkage() const {
12081215
// [basic.namespace.general]/p2
12091216
// A namespace is never attached to a named module and never has a name with
12101217
// module linkage.
1211-
if (isInNamedModule() && InternalLinkage == Linkage::External &&
1218+
if (isInNamedModule(this) && InternalLinkage == Linkage::External &&
12121219
!isExportedFromModuleInterfaceUnit(
12131220
cast<NamedDecl>(this->getCanonicalDecl())) &&
12141221
!isa<NamespaceDecl>(this))

clang/lib/AST/DeclBase.cpp

+11-19
Original file line numberDiff line numberDiff line change
@@ -1122,31 +1122,23 @@ bool Decl::isInExportDeclContext() const {
11221122
bool Decl::isInAnotherModuleUnit() const {
11231123
auto *M = getOwningModule();
11241124

1125-
if (!M || !M->isNamedModule())
1125+
if (!M)
11261126
return false;
11271127

1128-
return M != getASTContext().getCurrentNamedModule();
1129-
}
1130-
1131-
bool Decl::isInCurrentModuleUnit() const {
1132-
auto *M = getOwningModule();
1133-
1134-
if (!M || !M->isNamedModule())
1128+
M = M->getTopLevelModule();
1129+
// FIXME: It is problematic if the header module lives in another module
1130+
// unit. Consider to fix this by techniques like
1131+
// ExternalASTSource::hasExternalDefinitions.
1132+
if (M->isHeaderLikeModule())
11351133
return false;
11361134

1137-
return M == getASTContext().getCurrentNamedModule();
1138-
}
1139-
1140-
bool Decl::shouldEmitInExternalSource() const {
1141-
ExternalASTSource *Source = getASTContext().getExternalSource();
1142-
if (!Source)
1135+
// A global module without parent implies that we're parsing the global
1136+
// module. So it can't be in another module unit.
1137+
if (M->isGlobalModule())
11431138
return false;
11441139

1145-
return Source->hasExternalDefinitions(this) == ExternalASTSource::EK_Always;
1146-
}
1147-
1148-
bool Decl::isInNamedModule() const {
1149-
return getOwningModule() && getOwningModule()->isNamedModule();
1140+
assert(M->isNamedModule() && "New module kind?");
1141+
return M != getASTContext().getCurrentNamedModule();
11501142
}
11511143

11521144
bool Decl::isFromExplicitGlobalModule() const {

clang/lib/CodeGen/CGVTables.cpp

+21-40
Original file line numberDiff line numberDiff line change
@@ -1079,38 +1079,28 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
10791079
if (!RD->isExternallyVisible())
10801080
return llvm::GlobalVariable::InternalLinkage;
10811081

1082-
bool IsInNamedModule = RD->isInNamedModule();
1083-
// If the CXXRecordDecl are not in a module unit, we need to get
1084-
// its key function. We're at the end of the translation unit, so the current
1085-
// key function is fully correct.
1086-
const CXXMethodDecl *keyFunction =
1087-
IsInNamedModule ? nullptr : Context.getCurrentKeyFunction(RD);
1088-
if (IsInNamedModule || (keyFunction && !RD->hasAttr<DLLImportAttr>())) {
1082+
// We're at the end of the translation unit, so the current key
1083+
// function is fully correct.
1084+
const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD);
1085+
if (keyFunction && !RD->hasAttr<DLLImportAttr>()) {
10891086
// If this class has a key function, use that to determine the
10901087
// linkage of the vtable.
10911088
const FunctionDecl *def = nullptr;
1092-
if (keyFunction && keyFunction->hasBody(def))
1089+
if (keyFunction->hasBody(def))
10931090
keyFunction = cast<CXXMethodDecl>(def);
10941091

1095-
bool IsExternalDefinition =
1096-
IsInNamedModule ? RD->shouldEmitInExternalSource() : !def;
1097-
1098-
TemplateSpecializationKind Kind =
1099-
IsInNamedModule ? RD->getTemplateSpecializationKind()
1100-
: keyFunction->getTemplateSpecializationKind();
1101-
1102-
switch (Kind) {
1103-
case TSK_Undeclared:
1104-
case TSK_ExplicitSpecialization:
1092+
switch (keyFunction->getTemplateSpecializationKind()) {
1093+
case TSK_Undeclared:
1094+
case TSK_ExplicitSpecialization:
11051095
assert(
1106-
(IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
1096+
(def || CodeGenOpts.OptimizationLevel > 0 ||
11071097
CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
1108-
"Shouldn't query vtable linkage without the class in module units, "
1109-
"key function, optimizations, or debug info");
1110-
if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
1098+
"Shouldn't query vtable linkage without key function, "
1099+
"optimizations, or debug info");
1100+
if (!def && CodeGenOpts.OptimizationLevel > 0)
11111101
return llvm::GlobalVariable::AvailableExternallyLinkage;
11121102

1113-
if (keyFunction && keyFunction->isInlined())
1103+
if (keyFunction->isInlined())
11141104
return !Context.getLangOpts().AppleKext
11151105
? llvm::GlobalVariable::LinkOnceODRLinkage
11161106
: llvm::Function::InternalLinkage;
@@ -1129,7 +1119,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
11291119

11301120
case TSK_ExplicitInstantiationDeclaration:
11311121
llvm_unreachable("Should not have been asked to emit this");
1132-
}
1122+
}
11331123
}
11341124

11351125
// -fapple-kext mode does not support weak linkage, so we must use
@@ -1223,21 +1213,6 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
12231213
TSK == TSK_ExplicitInstantiationDefinition)
12241214
return false;
12251215

1226-
// Itanium C++ ABI [5.2.3]:
1227-
// Virtual tables for dynamic classes are emitted as follows:
1228-
//
1229-
// - If the class is templated, the tables are emitted in every object that
1230-
// references any of them.
1231-
// - Otherwise, if the class is attached to a module, the tables are uniquely
1232-
// emitted in the object for the module unit in which it is defined.
1233-
// - Otherwise, if the class has a key function (see below), the tables are
1234-
// emitted in the object for the translation unit containing the definition of
1235-
// the key function. This is unique if the key function is not inline.
1236-
// - Otherwise, the tables are emitted in every object that references any of
1237-
// them.
1238-
if (RD->isInNamedModule())
1239-
return RD->shouldEmitInExternalSource();
1240-
12411216
// Otherwise, if the class doesn't have a key function (possibly
12421217
// anymore), the vtable must be defined here.
12431218
const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
@@ -1247,7 +1222,13 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
12471222
const FunctionDecl *Def;
12481223
// Otherwise, if we don't have a definition of the key function, the
12491224
// vtable must be defined somewhere else.
1250-
return !keyFunction->hasBody(Def);
1225+
if (!keyFunction->hasBody(Def))
1226+
return true;
1227+
1228+
assert(Def && "The body of the key function is not assigned to Def?");
1229+
// If the non-inline key function comes from another module unit, the vtable
1230+
// must be defined there.
1231+
return Def->isInAnotherModuleUnit() && !Def->isInlineSpecified();
12511232
}
12521233

12531234
/// Given that we're currently at the end of the translation unit, and

clang/lib/CodeGen/ItaniumCXXABI.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -2161,9 +2161,6 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
21612161
if (!canSpeculativelyEmitVTableAsBaseClass(RD))
21622162
return false;
21632163

2164-
if (RD->shouldEmitInExternalSource())
2165-
return false;
2166-
21672164
// For a complete-object vtable (or more specifically, for the VTT), we need
21682165
// to be able to speculatively emit the vtables of all dynamic virtual bases.
21692166
for (const auto &B : RD->vbases()) {

clang/lib/Sema/SemaDecl.cpp

+1-10
Original file line numberDiff line numberDiff line change
@@ -10094,7 +10094,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1009410094
// check at the end of the TU (or when the PMF starts) to see that we
1009510095
// have a definition at that point.
1009610096
if (isInline && !D.isFunctionDefinition() && getLangOpts().CPlusPlus20 &&
10097-
NewFD->isInNamedModule()) {
10097+
NewFD->hasOwningModule() && NewFD->getOwningModule()->isNamedModule()) {
1009810098
PendingInlineFuncDecls.insert(NewFD);
1009910099
}
1010010100
}
@@ -18031,15 +18031,6 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
1803118031
if (NumInitMethods > 1 || !Def->hasInitMethod())
1803218032
Diag(RD->getLocation(), diag::err_sycl_special_type_num_init_method);
1803318033
}
18034-
18035-
// If we're defining a dynamic class in a module interface unit, we always
18036-
// need to produce the vtable for it even if the vtable is not used in the
18037-
// current TU.
18038-
//
18039-
// The case that the current class is not dynamic is handled in
18040-
// MarkVTableUsed.
18041-
if (getCurrentModule() && getCurrentModule()->isInterfaceOrPartition())
18042-
MarkVTableUsed(RD->getLocation(), RD, /*DefinitionRequired=*/true);
1804318034
}
1804418035

1804518036
// Exit this scope of this tag's definition.

clang/lib/Sema/SemaDeclCXX.cpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -18455,15 +18455,11 @@ bool Sema::DefineUsedVTables() {
1845518455

1845618456
bool DefineVTable = true;
1845718457

18458+
// If this class has a key function, but that key function is
18459+
// defined in another translation unit, we don't need to emit the
18460+
// vtable even though we're using it.
1845818461
const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
18459-
// V-tables for non-template classes with an owning module are always
18460-
// uniquely emitted in that module.
18461-
if (Class->isInCurrentModuleUnit())
18462-
DefineVTable = true;
18463-
else if (KeyFunction && !KeyFunction->hasBody()) {
18464-
// If this class has a key function, but that key function is
18465-
// defined in another translation unit, we don't need to emit the
18466-
// vtable even though we're using it.
18462+
if (KeyFunction && !KeyFunction->hasBody()) {
1846718463
// The key function is in another translation unit.
1846818464
DefineVTable = false;
1846918465
TemplateSpecializationKind TSK =
@@ -18508,7 +18504,7 @@ bool Sema::DefineUsedVTables() {
1850818504
DefinedAnything = true;
1850918505
MarkVirtualMembersReferenced(Loc, Class);
1851018506
CXXRecordDecl *Canonical = Class->getCanonicalDecl();
18511-
if (VTablesUsed[Canonical] && !Class->shouldEmitInExternalSource())
18507+
if (VTablesUsed[Canonical])
1851218508
Consumer.HandleVTable(Class);
1851318509

1851418510
// Warn if we're emitting a weak vtable. The vtable will be weak if there is

clang/lib/Serialization/ASTReader.cpp

-11
Original file line numberDiff line numberDiff line change
@@ -3921,13 +3921,6 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
39213921
}
39223922
break;
39233923

3924-
case VTABLES_TO_EMIT:
3925-
if (F.Kind == MK_MainFile ||
3926-
getContext().getLangOpts().BuildingPCHWithObjectFile)
3927-
for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/)
3928-
VTablesToEmit.push_back(ReadDeclID(F, Record, I));
3929-
break;
3930-
39313924
case IMPORTED_MODULES:
39323925
if (!F.isModule()) {
39333926
// If we aren't loading a module (which has its own exports), make
@@ -8117,10 +8110,6 @@ void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
81178110
Consumer->HandleInterestingDecl(DeclGroupRef(D));
81188111
}
81198112

8120-
void ASTReader::PassVTableToConsumer(CXXRecordDecl *RD) {
8121-
Consumer->HandleVTable(RD);
8122-
}
8123-
81248113
void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
81258114
this->Consumer = Consumer;
81268115

clang/lib/Serialization/ASTReaderDecl.cpp

-7
Original file line numberDiff line numberDiff line change
@@ -4235,13 +4235,6 @@ void ASTReader::PassInterestingDeclsToConsumer() {
42354235

42364236
// If we add any new potential interesting decl in the last call, consume it.
42374237
ConsumingPotentialInterestingDecls();
4238-
4239-
for (GlobalDeclID ID : VTablesToEmit) {
4240-
auto *RD = cast<CXXRecordDecl>(GetDecl(ID));
4241-
assert(!RD->shouldEmitInExternalSource());
4242-
PassVTableToConsumer(RD);
4243-
}
4244-
VTablesToEmit.clear();
42454238
}
42464239

42474240
void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {

0 commit comments

Comments
 (0)