https://github.com/mpark updated https://github.com/llvm/llvm-project/pull/129982
>From 39b845fd64c2ce173b95ddcafbbab2d5116aa68e Mon Sep 17 00:00:00 2001 From: Michael Park <mcyp...@gmail.com> Date: Wed, 5 Mar 2025 18:46:10 -0800 Subject: [PATCH 1/3] [clang][modules] Add a unit test for the assertion failure in bootstrap build on OS X with XCode. --- clang/test/Modules/pr129982.cpp | 107 ++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 clang/test/Modules/pr129982.cpp diff --git a/clang/test/Modules/pr129982.cpp b/clang/test/Modules/pr129982.cpp new file mode 100644 index 0000000000000..b19cccfd07687 --- /dev/null +++ b/clang/test/Modules/pr129982.cpp @@ -0,0 +1,107 @@ +// If this test fails, it should be investigated under Debug builds. +// Before the PR, this test was violating an assertion. + +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 -emit-obj -fmodules \ +// RUN: -fmodule-map-file=%t/module.modulemap \ +// RUN: -fmodules-cache-path=%t %t/a.cpp + +//--- module.modulemap +module ebo { + header "ebo.h" +} + +module fwd { + header "fwd.h" +} + +module s { + header "s.h" + export * +} + +module mod { + header "a.h" + header "b.h" +} + +//--- ebo.h +#pragma once + +namespace N { inline namespace __1 { + +template <typename T> +struct EBO : T { + EBO() = default; +}; + +}} + +//--- fwd.h +#pragma once + +namespace N { inline namespace __1 { + +template <typename T> +struct Empty; + +template <typename T> +struct BS; + +using S = BS<Empty<char>>; + +}} + +//--- s.h +#pragma once + +#include "fwd.h" +#include "ebo.h" + +namespace N { inline namespace __1 { + +template <typename T> +struct Empty {}; + +template <typename T> +struct BS { + EBO<T> _; + void f(); +}; + +extern template void BS<Empty<char>>::f(); + +}} + +//--- b.h +#pragma once + +#include "s.h" + +struct B { + void f() { + N::S{}.f(); + } +}; + +//--- a.h +#pragma once + +#include "s.h" + +struct A { + void f(int) {} + void f(const N::S &) {} + + void g(); +}; + +//--- a.cpp +#include "a.h" + +void A::g() { f(0); } + +// expected-no-diagnostics >From e3aebf17e0ea72492564a3652518e6ad20f37330 Mon Sep 17 00:00:00 2001 From: Michael Park <mcyp...@gmail.com> Date: Thu, 6 Mar 2025 11:49:54 -0800 Subject: [PATCH 2/3] [clang][modules] Re-add the unit test from #121245. --- clang/test/Modules/pr121245.cpp | 93 +++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 clang/test/Modules/pr121245.cpp diff --git a/clang/test/Modules/pr121245.cpp b/clang/test/Modules/pr121245.cpp new file mode 100644 index 0000000000000..0e276ad0e435d --- /dev/null +++ b/clang/test/Modules/pr121245.cpp @@ -0,0 +1,93 @@ +// If this test fails, it should be investigated under Debug builds. +// Before the PR, this test was encountering an `llvm_unreachable()`. + +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// RUN: cd %t + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-01.h \ +// RUN: -fcxx-exceptions -o %t/hu-01.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-02.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-02.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-03.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-03.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-04.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-04.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-05.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-03.pcm -fmodule-file=%t/hu-04.pcm \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-05.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/main.cpp \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-02.pcm -fmodule-file=%t/hu-05.pcm \ +// RUN: -fmodule-file=%t/hu-04.pcm -fmodule-file=%t/hu-03.pcm \ +// RUN: -fmodule-file=%t/hu-01.pcm + +//--- hu-01.h +template <typename T> +struct A { + A() {} + ~A() {} +}; + +template <typename T> +struct EBO : T { + EBO() = default; +}; + +template <typename T> +struct HT : EBO<A<T>> {}; + +//--- hu-02.h +import "hu-01.h"; + +inline void f() { + HT<int>(); +} + +//--- hu-03.h +import "hu-01.h"; + +struct C { + C(); + + HT<long> _; +}; + +//--- hu-04.h +import "hu-01.h"; + +void g(HT<long> = {}); + +//--- hu-05.h +import "hu-03.h"; +import "hu-04.h"; +import "hu-01.h"; + +struct B { + virtual ~B() = default; + + virtual void f() { + HT<long>(); + } +}; + +//--- main.cpp +import "hu-02.h"; +import "hu-05.h"; +import "hu-03.h"; + +int main() { + f(); + C(); + B(); +} >From 3134ad3f6fccfa3216ddcb7333350cdfa93f05ec Mon Sep 17 00:00:00 2001 From: Michael Park <mcyp...@gmail.com> Date: Thu, 6 Mar 2025 11:47:09 -0800 Subject: [PATCH 3/3] [clang][modules] Only update the generation number if the update was not delayed. --- clang/include/clang/AST/ASTContext.h | 2 +- clang/include/clang/AST/ExternalASTSource.h | 13 +++++++------ .../clang/Sema/MultiplexExternalSemaSource.h | 2 +- clang/include/clang/Serialization/ASTReader.h | 4 ++-- clang/lib/AST/ExternalASTSource.cpp | 2 +- clang/lib/Sema/MultiplexExternalSemaSource.cpp | 8 +++++--- clang/lib/Serialization/ASTReader.cpp | 14 ++++++++------ .../Plugins/ExpressionParser/Clang/ASTUtils.h | 12 +++++++----- 8 files changed, 32 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 4c6966c922cc7..7c2eb79dc3dc9 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3730,7 +3730,7 @@ inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) { /// Create the representation of a LazyGenerationalUpdatePtr. template <typename Owner, typename T, - void (clang::ExternalASTSource::*Update)(Owner)> + bool (clang::ExternalASTSource::*Update)(Owner)> typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType clang::LazyGenerationalUpdatePtr<Owner, T, Update>::makeValue( const clang::ASTContext &Ctx, T Value) { diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 42aed56d42e07..1d28deed8d7b1 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -220,8 +220,9 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> { /// Gives the external AST source an opportunity to complete /// the redeclaration chain for a declaration. Called each time we /// need the most recent declaration of a declaration after the - /// generation count is incremented. - virtual void CompleteRedeclChain(const Decl *D); + /// generation count is incremented. Returns true if the redeclaration + /// chain completion was completed. + virtual bool CompleteRedeclChain(const Decl *D); /// Gives the external AST source an opportunity to complete /// an incomplete type. @@ -437,7 +438,7 @@ struct LazyOffsetPtr { /// A lazy value (of type T) that is within an AST node of type Owner, /// where the value might change in later generations of the external AST /// source. -template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)> +template<typename Owner, typename T, bool (ExternalASTSource::*Update)(Owner)> struct LazyGenerationalUpdatePtr { /// A cache of the value of this pointer, in the most recent generation in /// which we queried it. @@ -487,9 +488,9 @@ struct LazyGenerationalUpdatePtr { /// Get the value of this pointer, updating its owner if necessary. T get(Owner O) { if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) { - if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) { + if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration() && + (LazyVal->ExternalSource->*Update)(O)) { LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration(); - (LazyVal->ExternalSource->*Update)(O); } return LazyVal->LastValue; } @@ -516,7 +517,7 @@ namespace llvm { /// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be /// placed into a PointerUnion. template<typename Owner, typename T, - void (clang::ExternalASTSource::*Update)(Owner)> + bool (clang::ExternalASTSource::*Update)(Owner)> struct PointerLikeTypeTraits< clang::LazyGenerationalUpdatePtr<Owner, T, Update>> { using Ptr = clang::LazyGenerationalUpdatePtr<Owner, T, Update>; diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 921bebe3a44af..ce7a74fa39291 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -69,7 +69,7 @@ class MultiplexExternalSemaSource : public ExternalSemaSource { /// Complete the redeclaration chain if it's been extended since the /// previous generation of the AST source. - void CompleteRedeclChain(const Decl *D) override; + bool CompleteRedeclChain(const Decl *D) override; /// Resolve a selector ID into a selector. Selector GetExternalSelector(uint32_t ID) override; diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 47301419c76c6..3ca3d44039b3c 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1226,7 +1226,7 @@ class ASTReader /// The list of canonical declarations whose redeclaration chains /// need to be marked as incomplete once we're done deserializing things. - SmallVector<Decl *, 16> PendingIncompleteDeclChains; + llvm::SmallPtrSet<Decl *, 16> PendingIncompleteDeclChains; /// The Decl IDs for the Sema/Lexical DeclContext of a Decl that has /// been loaded but its DeclContext was not set yet. @@ -2135,7 +2135,7 @@ class ASTReader /// If any redeclarations of \p D have been imported since it was /// last checked, this digs out those redeclarations and adds them to the /// redeclaration chain for \p D. - void CompleteRedeclChain(const Decl *D) override; + bool CompleteRedeclChain(const Decl *D) override; CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index e2451f294741d..edf485d93b17c 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -42,7 +42,7 @@ void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset, unsigned Length, SmallVectorImpl<Decl *> &Decls) {} -void ExternalASTSource::CompleteRedeclChain(const Decl *D) {} +bool ExternalASTSource::CompleteRedeclChain(const Decl *D) { return true; } void ExternalASTSource::CompleteType(TagDecl *Tag) {} diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 6d945300c386c..ae6a6e0f31bfe 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -53,9 +53,11 @@ Decl *MultiplexExternalSemaSource::GetExternalDecl(GlobalDeclID ID) { return nullptr; } -void MultiplexExternalSemaSource::CompleteRedeclChain(const Decl *D) { - for (size_t i = 0; i < Sources.size(); ++i) - Sources[i]->CompleteRedeclChain(D); +bool MultiplexExternalSemaSource::CompleteRedeclChain(const Decl *D) { + bool Result = true; + for (ExternalSemaSource *Source : Sources) + Result &= Source->CompleteRedeclChain(D); + return Result; } Selector MultiplexExternalSemaSource::GetExternalSelector(uint32_t ID) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index ca09c3d79d941..279c1b7a4d192 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7825,19 +7825,19 @@ ASTRecordReader::readASTTemplateArgumentListInfo() { Decl *ASTReader::GetExternalDecl(GlobalDeclID ID) { return GetDecl(ID); } -void ASTReader::CompleteRedeclChain(const Decl *D) { +bool ASTReader::CompleteRedeclChain(const Decl *D) { if (NumCurrentElementsDeserializing) { // We arrange to not care about the complete redeclaration chain while we're // deserializing. Just remember that the AST has marked this one as complete // but that it's not actually complete yet, so we know we still need to // complete it later. - PendingIncompleteDeclChains.push_back(const_cast<Decl*>(D)); - return; + PendingIncompleteDeclChains.insert(const_cast<Decl*>(D)); + return false; } if (!D->getDeclContext()) { assert(isa<TranslationUnitDecl>(D) && "Not a TU?"); - return; + return true; } const DeclContext *DC = D->getDeclContext()->getRedeclContext(); @@ -7894,6 +7894,8 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { else Template->loadLazySpecializationsImpl(Args); } + + return true; } CXXCtorInitializer ** @@ -10233,8 +10235,8 @@ void ASTReader::finishPendingActions() { // For each decl chain that we wanted to complete while deserializing, mark // it as "still needs to be completed". - for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) { - markIncompleteDeclChain(PendingIncompleteDeclChains[I]); + for (Decl* D : PendingIncompleteDeclChains) { + markIncompleteDeclChain(D); } PendingIncompleteDeclChains.clear(); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h index a1f02dc3d1b09..497d0dedf80a6 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h @@ -117,8 +117,8 @@ class ExternalASTSourceWrapper : public clang::ExternalSemaSource { m_Source->FindFileRegionDecls(File, Offset, Length, Decls); } - void CompleteRedeclChain(const clang::Decl *D) override { - m_Source->CompleteRedeclChain(D); + bool CompleteRedeclChain(const clang::Decl *D) override { + return m_Source->CompleteRedeclChain(D); } void CompleteType(clang::TagDecl *Tag) override { @@ -334,9 +334,11 @@ class SemaSourceWithPriorities : public clang::ExternalSemaSource { return newDeclFound; } - void CompleteRedeclChain(const clang::Decl *D) override { - for (size_t i = 0; i < Sources.size(); ++i) - Sources[i]->CompleteRedeclChain(D); + bool CompleteRedeclChain(const clang::Decl *D) override { + bool Result = true; + for (clang::ExternalSemaSource *Source : Sources) + Result &= Source->CompleteRedeclChain(D); + return Result; } clang::Selector GetExternalSelector(uint32_t ID) override { _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits