https://github.com/mpark updated https://github.com/llvm/llvm-project/pull/155948
>From 63519ed11294db85a9896e33a6a34bbc8b067dde Mon Sep 17 00:00:00 2001 From: Michael Park <[email protected]> Date: Thu, 28 Aug 2025 14:38:21 -0700 Subject: [PATCH 1/2] [C++20][Modules] Add tests related to anonymous members in class templates. --- .../test/Modules/merge-anon-in-template-2.cpp | 47 +++++++++++++++++++ .../test/Modules/merge-anon-in-template-3.cpp | 45 ++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 clang/test/Modules/merge-anon-in-template-2.cpp create mode 100644 clang/test/Modules/merge-anon-in-template-3.cpp diff --git a/clang/test/Modules/merge-anon-in-template-2.cpp b/clang/test/Modules/merge-anon-in-template-2.cpp new file mode 100644 index 0000000000000..15852f0120798 --- /dev/null +++ b/clang/test/Modules/merge-anon-in-template-2.cpp @@ -0,0 +1,47 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 -fmodule-name=hu-01 -emit-header-unit -xc++-user-header %t/hu-01.h \ +// RUN: -o %t/hu-01.pcm + +// RUN: %clang_cc1 -std=c++20 -fmodule-name=hu-02 -emit-header-unit -xc++-user-header %t/hu-02.h \ +// RUN: -Wno-experimental-header-units \ +// RUN: -fmodule-map-file=%t/hu-01.map -fmodule-file=hu-01=%t/hu-01.pcm \ +// RUN: -o %t/hu-02.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/main.cpp \ +// RUN: -Wno-experimental-header-units \ +// RUN: -fmodule-map-file=%t/hu-01.map -fmodule-file=hu-01=%t/hu-01.pcm \ +// RUN: -fmodule-map-file=%t/hu-02.map -fmodule-file=hu-02=%t/hu-02.pcm + +//--- hu-01.map +module "hu-01" { + header "hu-01.h" + export * +} + +//--- hu-02.map +module "hu-02" { + header "hu-02.h" + export * +} + +//--- hu-01.h +template <typename T> +struct S { union { T x; }; }; + +using SI = S<int>; + +//--- hu-02.h +template <typename T> +struct S { union { T x; }; }; + +inline void f(S<int> s = {}) { s.x; } + +//--- main.cpp +import "hu-01.h"; +void g(S<int>) {} + +import "hu-02.h"; +void h() { f(); } diff --git a/clang/test/Modules/merge-anon-in-template-3.cpp b/clang/test/Modules/merge-anon-in-template-3.cpp new file mode 100644 index 0000000000000..1ee447e3e524d --- /dev/null +++ b/clang/test/Modules/merge-anon-in-template-3.cpp @@ -0,0 +1,45 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 -fmodule-name=hu-01 -emit-header-unit -xc++-user-header %t/hu-01.h \ +// RUN: -o %t/hu-01.pcm + +// RUN: %clang_cc1 -std=c++20 -fmodule-name=hu-02 -emit-header-unit -xc++-user-header %t/hu-02.h \ +// RUN: -Wno-experimental-header-units \ +// RUN: -fmodule-map-file=%t/hu-01.map -fmodule-file=hu-01=%t/hu-01.pcm \ +// RUN: -o %t/hu-02.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/main.cpp \ +// RUN: -Wno-experimental-header-units \ +// RUN: -fmodule-map-file=%t/hu-01.map -fmodule-file=hu-01=%t/hu-01.pcm \ +// RUN: -fmodule-map-file=%t/hu-02.map -fmodule-file=hu-02=%t/hu-02.pcm + +//--- hu-01.map +module "hu-01" { + header "hu-01.h" + export * +} + +//--- hu-02.map +module "hu-02" { + header "hu-02.h" + export * +} + +//--- hu-01.h +template <typename T> +struct S { union { T x; }; }; + +using SI = S<int>; + +//--- hu-02.h +import "hu-01.h"; +inline void f(S<int> s = {}) { s.x; } + +//--- main.cpp +import "hu-01.h"; +void g(S<int>) {} + +import "hu-02.h"; +void h() { f(); } >From 302a2ea3cd891fb975cb2e5e20f4595552b7e2e9 Mon Sep 17 00:00:00 2001 From: Michael Park <[email protected]> Date: Fri, 12 Sep 2025 20:37:42 -0700 Subject: [PATCH 2/2] [C++20][Modules] Number the anonymous members if the decl was instantiated locally. --- clang/include/clang/AST/DeclTemplate.h | 9 +++++++++ clang/lib/AST/DeclTemplate.cpp | 5 +++-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 1 + clang/lib/Serialization/ASTReaderDecl.cpp | 11 ++++++++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index bba72365089f9..0a2cc18b00efa 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1874,6 +1874,11 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl, LLVM_PREFERRED_TYPE(bool) unsigned StrictPackMatch : 1; + /// Indicate whether this instantiation was performed locally (as opposed to + /// performed externally, during a module precompile). + LLVM_PREFERRED_TYPE(bool) + unsigned LocalInstantiation : 1; + protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation StartLoc, @@ -1968,6 +1973,10 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl, void setStrictPackMatch(bool Val) { StrictPackMatch = Val; } + bool isLocalInstantiation() { return LocalInstantiation; } + + void setLocalInstantiation() { LocalInstantiation = true; } + /// Get the point of instantiation (if any), or null if none. SourceLocation getPointOfInstantiation() const { return PointOfInstantiation; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 3162857aac5d0..cfb845a1728f8 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -974,7 +974,8 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl( SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)), - SpecializationKind(TSK_Undeclared), StrictPackMatch(StrictPackMatch) { + SpecializationKind(TSK_Undeclared), StrictPackMatch(StrictPackMatch), + LocalInstantiation(false) { assert(DK == Kind::ClassTemplateSpecialization || StrictPackMatch == false); } @@ -982,7 +983,7 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) : CXXRecordDecl(DK, TagTypeKind::Struct, C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr), - SpecializationKind(TSK_Undeclared) {} + SpecializationKind(TSK_Undeclared), LocalInstantiation(false) {} ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create( ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a72c95d6d77cf..cd3bcc1fc6537 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3699,6 +3699,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) { Spec->setTemplateSpecializationKind(TSK); Spec->setPointOfInstantiation(PointOfInstantiation); + Spec->setLocalInstantiation(); } InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 6b35b205079e5..a40d073f32ea0 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3425,7 +3425,16 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, // If this is the first time, but we have parsed a declaration of the context, // build the anonymous declaration list from the parsed declaration. auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC); - if (PrimaryDC && !cast<Decl>(PrimaryDC)->isFromASTFile()) { + auto needToNumberAnonymousDeclsWithin = [](Decl *D) { + if (!D->isFromASTFile()) + return true; + // If this is a class template specialization from an AST file + // but the instantiation occurred locally, we still need to number + // the anonymous decls. + auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D); + return CTSD && CTSD->isLocalInstantiation(); + }; + if (PrimaryDC && needToNumberAnonymousDeclsWithin(cast<Decl>(PrimaryDC))) { numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) { if (Previous.size() == Number) Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl())); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
