https://github.com/jiixyj updated https://github.com/llvm/llvm-project/pull/104701
From feaf6512fc6323ad0c3d5082c06e610504f0a527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemuel...@gmail.com> Date: Sun, 18 Aug 2024 13:45:43 +0200 Subject: [PATCH 1/3] Expose static inline function from GMF They should be exposed even when two-phase name lookup and ADL are involved. --- clang/lib/Sema/SemaOverload.cpp | 23 +++++++++-- .../expose-static-inline-from-gmf-1.cppm | 37 +++++++++++++++++ .../expose-static-inline-from-gmf-2.cppm | 22 ++++++++++ .../expose-static-inline-from-gmf-3.cppm | 24 +++++++++++ .../expose-static-inline-from-gmf-4.cppm | 40 +++++++++++++++++++ .../expose-static-inline-from-gmf-5.cppm | 26 ++++++++++++ 6 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 clang/test/Modules/expose-static-inline-from-gmf-1.cppm create mode 100644 clang/test/Modules/expose-static-inline-from-gmf-2.cppm create mode 100644 clang/test/Modules/expose-static-inline-from-gmf-3.cppm create mode 100644 clang/test/Modules/expose-static-inline-from-gmf-4.cppm create mode 100644 clang/test/Modules/expose-static-inline-from-gmf-5.cppm diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 52f640eb96b73b..ca070d0e22d472 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6926,11 +6926,26 @@ void Sema::AddOverloadCandidate( /// have linkage. So that all entities of the same should share one /// linkage. But in clang, different entities of the same could have /// different linkage. - NamedDecl *ND = Function; - if (auto *SpecInfo = Function->getTemplateSpecializationInfo()) + const NamedDecl *ND = Function; + bool IsImplicitlyInstantiated = false; + if (auto *SpecInfo = Function->getTemplateSpecializationInfo()) { ND = SpecInfo->getTemplate(); - - if (ND->getFormalLinkage() == Linkage::Internal) { + IsImplicitlyInstantiated = SpecInfo->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation; + } + + /// Don't remove inline functions with internal linkage from the overload + /// set if they are declared in a GMF. + /// The global module is meant to be a transition mechanism for C and C++ + /// headers. + /// Inline functions with internal linkage are a common pattern in headers + /// to avoid ODR issues. + const bool IsInlineFunctionInGMF = + Function->getOwningModule() && + Function->getOwningModule()->isGlobalModule() && + (IsImplicitlyInstantiated || Function->isInlined()); + + if (ND->getFormalLinkage() == Linkage::Internal && !IsInlineFunctionInGMF) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_module_mismatched; return; diff --git a/clang/test/Modules/expose-static-inline-from-gmf-1.cppm b/clang/test/Modules/expose-static-inline-from-gmf-1.cppm new file mode 100644 index 00000000000000..4de9b583dac8da --- /dev/null +++ b/clang/test/Modules/expose-static-inline-from-gmf-1.cppm @@ -0,0 +1,37 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm \ +// RUN: -DTEST_INLINE +// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify \ +// RUN: -DTEST_INLINE +// +// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm +// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify + +//--- a.h +#ifdef TEST_INLINE +#define INLINE inline +#else +#define INLINE +#endif +static INLINE void func(long) {} +template <typename T = long> void a() { func(T{}); } + +//--- a.cppm +module; +#include "a.h" +export module a; +export using ::a; + +//--- test.cc +import a; +auto m = (a(), 0); + +#ifdef TEST_INLINE +// expected-no-diagnostics +#else +// expected-error@a.h:7 {{no matching function for call to 'func'}} +// expected-n...@test.cc:2 {{in instantiation of function template specialization 'a<long>' requested here}} +#endif diff --git a/clang/test/Modules/expose-static-inline-from-gmf-2.cppm b/clang/test/Modules/expose-static-inline-from-gmf-2.cppm new file mode 100644 index 00000000000000..c89b613f5074b1 --- /dev/null +++ b/clang/test/Modules/expose-static-inline-from-gmf-2.cppm @@ -0,0 +1,22 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm +// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify + +//--- a.h +template <typename G> static inline void func() {} +template <typename T = long> void a() { func<T>(); } + +//--- a.cppm +module; +#include "a.h" +export module a; +export using ::a; + +//--- test.cc +import a; +auto m = (a(), 0); + +// expected-no-diagnostics diff --git a/clang/test/Modules/expose-static-inline-from-gmf-3.cppm b/clang/test/Modules/expose-static-inline-from-gmf-3.cppm new file mode 100644 index 00000000000000..dee7cddafdf701 --- /dev/null +++ b/clang/test/Modules/expose-static-inline-from-gmf-3.cppm @@ -0,0 +1,24 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm +// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify + +//--- a.h +namespace ns { +template <typename G> static void func() {} +template <typename T = long> void a() { func<T>(); } +} + +//--- a.cppm +module; +#include "a.h" +export module a; +export using ns::a; + +//--- test.cc +import a; +auto m = (a(), 0); + +// expected-no-diagnostics diff --git a/clang/test/Modules/expose-static-inline-from-gmf-4.cppm b/clang/test/Modules/expose-static-inline-from-gmf-4.cppm new file mode 100644 index 00000000000000..09c6b1ffd9c797 --- /dev/null +++ b/clang/test/Modules/expose-static-inline-from-gmf-4.cppm @@ -0,0 +1,40 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm \ +// RUN: -DTEST_INLINE +// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify \ +// RUN: -DTEST_INLINE +// +// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm +// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify + +//--- a.h +#ifdef TEST_INLINE +#define INLINE inline +#else +#define INLINE +#endif +namespace ns { +template <typename G> static void func() {} +template <> INLINE void func<long>() {} +template <typename T = long> void a() { func<T>(); } +} + +//--- a.cppm +module; +#include "a.h" +export module a; +export using ns::a; + +//--- test.cc +import a; +auto m = (a(), 0); + +#ifdef TEST_INLINE +// expected-no-diagnostics +#else +// expected-error@a.h:9 {{no matching function for call to 'func'}} +// expected-n...@test.cc:2 {{in instantiation of function template specialization 'ns::a<long>' requested here}} +#endif diff --git a/clang/test/Modules/expose-static-inline-from-gmf-5.cppm b/clang/test/Modules/expose-static-inline-from-gmf-5.cppm new file mode 100644 index 00000000000000..334af845a693dd --- /dev/null +++ b/clang/test/Modules/expose-static-inline-from-gmf-5.cppm @@ -0,0 +1,26 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm +// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify + +//--- a.h +namespace ns { +namespace { +template <typename G> void func() {} +} +template <typename T = long> void a() { func<T>(); } +} + +//--- a.cppm +module; +#include "a.h" +export module a; +export using ns::a; + +//--- test.cc +import a; +auto m = (a(), 0); + +// expected-no-diagnostics From e847c47f7919b166f33bc4d048b5f96a2afd4815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemuel...@gmail.com> Date: Sun, 18 Aug 2024 14:08:29 +0200 Subject: [PATCH 2/3] autoformat --- clang/lib/Sema/SemaOverload.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index ca070d0e22d472..594b6071494be2 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6941,9 +6941,9 @@ void Sema::AddOverloadCandidate( /// Inline functions with internal linkage are a common pattern in headers /// to avoid ODR issues. const bool IsInlineFunctionInGMF = - Function->getOwningModule() && - Function->getOwningModule()->isGlobalModule() && - (IsImplicitlyInstantiated || Function->isInlined()); + Function->getOwningModule() && + Function->getOwningModule()->isGlobalModule() && + (IsImplicitlyInstantiated || Function->isInlined()); if (ND->getFormalLinkage() == Linkage::Internal && !IsInlineFunctionInGMF) { Candidate.Viable = false; From a17b9774759479e73430391fa8f33482f32a75a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemuel...@gmail.com> Date: Wed, 21 Aug 2024 06:51:41 +0200 Subject: [PATCH 3/3] Update clang/lib/Sema/SemaOverload.cpp Co-authored-by: Chuanqi Xu <yedeng...@linux.alibaba.com> --- clang/lib/Sema/SemaOverload.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 594b6071494be2..0ceec4d1d35fe1 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6941,8 +6941,7 @@ void Sema::AddOverloadCandidate( /// Inline functions with internal linkage are a common pattern in headers /// to avoid ODR issues. const bool IsInlineFunctionInGMF = - Function->getOwningModule() && - Function->getOwningModule()->isGlobalModule() && + Function->isFromGlobalModule() (IsImplicitlyInstantiated || Function->isInlined()); if (ND->getFormalLinkage() == Linkage::Internal && !IsInlineFunctionInGMF) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits