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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits