https://github.com/glebov-andrey updated https://github.com/llvm/llvm-project/pull/114075
>From 4698bff9789ee73a2161f49ba509b0ce705ec49f Mon Sep 17 00:00:00 2001 From: Andrey Glebov <andrey458641...@gmail.com> Date: Mon, 28 Oct 2024 00:02:51 +0300 Subject: [PATCH] [clang] MicrosoftCXXABI: restore the RecordToCopyCtor table when loading AST (#53486) - Includes a regression test for the issue --- clang/include/clang/AST/ASTContext.h | 5 ++++ clang/include/clang/AST/ExternalASTSource.h | 4 +++ .../clang/Sema/MultiplexExternalSemaSource.h | 4 +++ .../include/clang/Serialization/ASTBitCodes.h | 2 ++ clang/include/clang/Serialization/ASTReader.h | 10 +++++++ clang/lib/AST/ASTContext.cpp | 17 +++++++++++ clang/lib/AST/CXXABI.h | 3 ++ clang/lib/AST/ExternalASTSource.cpp | 3 ++ clang/lib/AST/ItaniumCXXABI.cpp | 5 ++++ clang/lib/AST/MicrosoftCXXABI.cpp | 5 ++++ .../lib/Sema/MultiplexExternalSemaSource.cpp | 6 ++++ clang/lib/Serialization/ASTReader.cpp | 20 +++++++++++++ clang/lib/Serialization/ASTWriter.cpp | 14 +++++++++ .../CodeGenCXX/microsoft-abi-throw-pch.cpp | 13 ++++++++ .../test/CodeGenCXX/microsoft-abi-throw-pch.h | 30 +++++++++++++++++++ 15 files changed, 141 insertions(+) create mode 100644 clang/test/CodeGenCXX/microsoft-abi-throw-pch.cpp create mode 100644 clang/test/CodeGenCXX/microsoft-abi-throw-pch.h diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8d24d393eab09..84633d0d84e76 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -682,6 +682,8 @@ class ASTContext : public RefCountedBase<ASTContext> { /// For performance, track whether any function effects are in use. mutable bool AnyFunctionEffects = false; + bool ExternalCopyConstructorsForExceptionObjectsLoaded = false; + const TargetInfo *Target = nullptr; const TargetInfo *AuxTarget = nullptr; clang::PrintingPolicy PrintingPolicy; @@ -3362,6 +3364,9 @@ class ASTContext : public RefCountedBase<ASTContext> { const FunctionDecl *FD, llvm::function_ref<void(FunctionDecl *)> Pred) const; + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> * + getRecordToCopyCtor(); + const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD); diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index f45e3af7602c1..4eba9dac5ce07 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -40,6 +40,7 @@ class ASTConsumer; class ASTContext; class ASTSourceDescriptor; class CXXBaseSpecifier; +class CXXConstructorDecl; class CXXCtorInitializer; class CXXRecordDecl; class DeclarationName; @@ -175,6 +176,9 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> { LoadExternalSpecializations(const Decl *D, ArrayRef<TemplateArgument> TemplateArgs); + virtual void LoadExternalExceptionCopyingConstructors( + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> &RecordToCtor); + /// Ensures that the table of all visible declarations inside this /// context is up to date. /// diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 391c2177d75ec..17962c79a930e 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -106,6 +106,10 @@ class MultiplexExternalSemaSource : public ExternalSemaSource { LoadExternalSpecializations(const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) override; + void LoadExternalExceptionCopyingConstructors( + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> &RecordToCtor) + override; + /// Ensures that the table of all visible declarations inside this /// context is up to date. void completeVisibleDeclsMap(const DeclContext *DC) override; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 9d265f27b8e31..fc68f484741e5 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -742,6 +742,8 @@ enum ASTRecordTypes { UPDATE_MODULE_LOCAL_VISIBLE = 76, UPDATE_TU_LOCAL_VISIBLE = 77, + + MSCXXABI_EXCEPTION_COPYING_CONSTRUCTORS = 78, }; /// 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 6963611c6a815..212898a77dfe7 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1055,6 +1055,12 @@ class ASTReader /// The IDs of all decls with function effects to be checked. SmallVector<GlobalDeclID> DeclsWithEffectsToVerify; + struct RecordAndCopyingCtor { + GlobalDeclID RecordID; + GlobalDeclID CtorID; + }; + SmallVector<RecordAndCopyingCtor> RecordToCopyingCtor; + private: struct ImportedSubmodule { serialization::SubmoduleID ID; @@ -2177,6 +2183,10 @@ class ASTReader LoadExternalSpecializations(const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) override; + void LoadExternalExceptionCopyingConstructors( + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> &RecordToCtor) + override; + /// Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire /// lookup table as unmaterialized references. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5044d7c33ec3c..aee63455b538c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13333,8 +13333,25 @@ ASTContext::createMangleNumberingContext() const { return ABI->createMangleNumberingContext(); } +llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> * +ASTContext::getRecordToCopyCtor() { + if (ABI) { // TODO Why can this be null? + return ABI->getRecordToCopyCtor(); + } + return nullptr; +} + const CXXConstructorDecl * ASTContext::getCopyConstructorForExceptionObject(CXXRecordDecl *RD) { + if (!getTargetInfo().getCXXABI().isMicrosoft()) { + return nullptr; + } + if (ExternalSource && !ExternalCopyConstructorsForExceptionObjectsLoaded) { + auto *Map = ABI->getRecordToCopyCtor(); + assert(Map); + ExternalSource->LoadExternalExceptionCopyingConstructors(*Map); + ExternalCopyConstructorsForExceptionObjectsLoaded = true; + } return ABI->getCopyConstructorForExceptionObject( cast<CXXRecordDecl>(RD->getFirstDecl())); } diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h index 9258a53fefebc..612c9779346bd 100644 --- a/clang/lib/AST/CXXABI.h +++ b/clang/lib/AST/CXXABI.h @@ -56,6 +56,9 @@ class CXXABI { virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *, CXXConstructorDecl *) = 0; + virtual llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> * + getRecordToCopyCtor() = 0; + /// Retrieves the mapping from class to copy constructor for this C++ ABI. virtual const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0; diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index e8c1004089713..060aa5f7ac474 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -109,6 +109,9 @@ bool ExternalASTSource::LoadExternalSpecializations( return false; } +void ExternalASTSource::LoadExternalExceptionCopyingConstructors( + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> &) {} + void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {} void ExternalASTSource::FindExternalLexicalDecls( diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 6ceedd657fe7e..f85828148c763 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -256,6 +256,11 @@ class ItaniumCXXABI : public CXXABI { return Layout.getNonVirtualSize() == PointerSize; } + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> * + getRecordToCopyCtor() override { + return nullptr; + } + const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { return nullptr; diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index 1c020c3ad4ad5..472ca10054b4c 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -146,6 +146,11 @@ class MicrosoftCXXABI : public CXXABI { llvm_unreachable("unapplicable to the MS ABI"); } + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> * + getRecordToCopyCtor() override { + return &RecordToCopyCtor; + } + const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { return RecordToCopyCtor[RD]; diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index fbfb242598c24..46ba2f63a87b1 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -142,6 +142,12 @@ bool MultiplexExternalSemaSource::LoadExternalSpecializations( return AnyNewSpecsLoaded; } +void MultiplexExternalSemaSource::LoadExternalExceptionCopyingConstructors( + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> &RecordToCtor) { + for (size_t i = 0; i < Sources.size(); ++i) + Sources[i]->LoadExternalExceptionCopyingConstructors(RecordToCtor); +} + void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC){ for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->completeVisibleDeclsMap(DC); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 8d2f105b2dec3..df5efa3a9e28e 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -4358,6 +4358,16 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) DeclsToCheckForDeferredDiags.insert(ReadDeclID(F, Record, I)); break; + + case MSCXXABI_EXCEPTION_COPYING_CONSTRUCTORS: + if (Record.size() % 2 != 0) + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "Invalid MSCXXABI_EXCEPTION_COPYING_CONSTRUCTORS record"); + for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) + RecordToCopyingCtor.push_back( + {ReadDeclID(F, Record, I), ReadDeclID(F, Record, I)}); + break; } } } @@ -8418,6 +8428,16 @@ bool ASTReader::LoadExternalSpecializations( return NewDeclsFound; } +void ASTReader::LoadExternalExceptionCopyingConstructors( + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> &RecordToCtor) { + for (const auto &[RecordID, CtorID] : RecordToCopyingCtor) { + auto *RD = cast<CXXRecordDecl>(GetDecl(RecordID)); + auto *CD = cast<CXXConstructorDecl>(GetDecl(CtorID)); + RecordToCtor.insert({RD, CD}); + } + RecordToCopyingCtor.clear(); +} + void ASTReader::FindExternalLexicalDecls( const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl<Decl *> &Decls) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index cc9916a75d4b4..d493dc7453105 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5857,6 +5857,20 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) { if (!VTablesToEmit.empty()) Stream.EmitRecord(VTABLES_TO_EMIT, VTablesToEmit); + + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + const auto *RecordToCopyCtor = Context.getRecordToCopyCtor(); + if (RecordToCopyCtor) { + RecordData ExceptionCopyingConstructors; + for (const auto &[RD, CD] : *RecordToCopyCtor) { + AddDeclRef(RD, ExceptionCopyingConstructors); + AddDeclRef(CD, ExceptionCopyingConstructors); + } + if (!ExceptionCopyingConstructors.empty()) + Stream.EmitRecord(MSCXXABI_EXCEPTION_COPYING_CONSTRUCTORS, + ExceptionCopyingConstructors); + } + } } ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot, diff --git a/clang/test/CodeGenCXX/microsoft-abi-throw-pch.cpp b/clang/test/CodeGenCXX/microsoft-abi-throw-pch.cpp new file mode 100644 index 0000000000000..6b3570ba272bc --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-throw-pch.cpp @@ -0,0 +1,13 @@ +// Regression test for https://github.com/llvm/llvm-project/issues/53486 + +// RUN: %clang_cc1 -x c++ -std=c++11 -fcxx-exceptions -fexceptions -triple=x86_64-pc-windows-msvc -emit-pch -building-pch-with-obj -fmodules-codegen -o %t.pch %S/microsoft-abi-throw-pch.h +// RUN: %clang_cc1 -x c++ -std=c++11 -fcxx-exceptions -fexceptions -triple=x86_64-pc-windows-msvc -include-pch %t.pch -emit-llvm -building-pch-with-obj -fmodules-codegen -o - %s | FileCheck %s + +// CHECK-DAG: @"_CT??_R0?AUTrivial@@@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"??_R0?AUTrivial@@@8" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 1, i32 0 }, section ".xdata", comdat +// CHECK-DAG: @"_CTA1?AUTrivial@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"_CT??_R0?AUTrivial@@@81" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32)] }, section ".xdata", comdat + +// CHECK-DAG: @"_CT??_R0?AUNonTrivial@@@8??0NonTrivial@@QEAA@AEBU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"??_R0?AUNonTrivial@@@8" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"??0NonTrivial@@QEAA@AEBU0@@Z" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32) }, section ".xdata", comdat +// CHECK-DAG: @"_CTA1?AUNonTrivial@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"_CT??_R0?AUNonTrivial@@@8??0NonTrivial@@QEAA@AEBU0@@Z1" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32)] }, section ".xdata", comdat + +// CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QEAAXAEAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"??_R0?AUTemplateWithDefault@@@8" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"??$?_OH@TemplateWithDefault@@QEAAXAEAU0@@Z" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32) }, section ".xdata", comdat +// CHECK-DAG: @"_CTA1?AUTemplateWithDefault@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (ptr @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QEAAXAEAU0@@Z1" to i64), i64 ptrtoint (ptr @__ImageBase to i64)) to i32)] }, section ".xdata", comdat diff --git a/clang/test/CodeGenCXX/microsoft-abi-throw-pch.h b/clang/test/CodeGenCXX/microsoft-abi-throw-pch.h new file mode 100644 index 0000000000000..160f2f01370f0 --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-throw-pch.h @@ -0,0 +1,30 @@ +// Header for PCH test microsoft-abi-throw-pch.cpp + +struct Trivial {}; + +struct NonTrivial { + NonTrivial() = default; + NonTrivial(const NonTrivial &) noexcept {} + NonTrivial(NonTrivial &&) noexcept {} +}; + +struct TemplateWithDefault { + template <typename T> + static int f() { + return 0; + } + template <typename T = int> + TemplateWithDefault(TemplateWithDefault &, T = f<T>()); +}; + +inline void throw_trivial() { + throw Trivial(); +} + +inline void throw_non_trivial() { + throw NonTrivial(); +} + +inline void throw_template(TemplateWithDefault &e) { + throw e; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits