[clang] [Clang][Sema] Expose static inline functions from GMF (PR #104701)

2024-08-18 Thread Jan Kokemüller via cfe-commits

https://github.com/jiixyj created 
https://github.com/llvm/llvm-project/pull/104701

In C, it is a common pattern to have `static inline` functions in headers to 
avoid ODR issues. Currently, when those headers are included in a GMF, the 
names are not found when two-phase name lookup and ADL is involved. Those names 
are removed by `Sema::AddOverloadCandidate`.

Similarly, in C++, sometimes people use templates with internal linkage in 
headers.

As the GMF was designed to be a transitional mechanism for headers, special 
case those functions in `Sema::AddOverloadCandidate`.

This fixes .

From feaf6512fc6323ad0c3d5082c06e610504f0a527 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= 
Date: Sun, 18 Aug 2024 13:45:43 +0200
Subject: [PATCH] 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 00..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  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' 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 00..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

[clang] [Clang][Sema] Expose static inline functions from GMF (PR #104701)

2024-08-18 Thread Jan Kokemüller via cfe-commits

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?= 
Date: Sun, 18 Aug 2024 13:45:43 +0200
Subject: [PATCH 1/2] 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 00..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  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' 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 00..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  static inline void func() {}
+template  void a() { func(); }
+
+//--- 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 1006

[clang] [Clang][Sema] Expose static inline functions from GMF (PR #104701)

2024-08-20 Thread Jan Kokemüller via cfe-commits

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?= 
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 00..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  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' 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 00..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  static inline void func() {}
+template  void a() { func(); }
+
+//--- 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 1006

[clang] [Clang][Sema] Expose static inline functions from GMF (PR #104701)

2024-08-21 Thread Jan Kokemüller via cfe-commits


@@ -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.

jiixyj wrote:

Sounds like a good idea! One direction could be to create an additional 
exception to [basic.link#17]() for 
exposure of inline TU-local entities declared in a GMF, so that the program 
would be no longer ill-formed in that case, right? 
[depr.local]()'s note would have to be 
changed to reflect this.

I will add to the comment that the proposed behavior violates basic.link#17.

https://github.com/llvm/llvm-project/pull/104701
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Expose static inline functions from GMF (PR #104701)

2024-12-29 Thread Jan Kokemüller via cfe-commits

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?= 
Date: Sun, 18 Aug 2024 13:45:43 +0200
Subject: [PATCH 1/5] 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 00..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  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' 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 00..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  static inline void func() {}
+template  void a() { func(); }
+
+//--- 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 1006

[clang] [Clang][Sema] Expose static inline functions from GMF (PR #104701)

2024-12-29 Thread Jan Kokemüller via cfe-commits


@@ -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.

jiixyj wrote:

Sorry for the delay! I have now updated the comment to include the fact that 
this fix/workaround violates [basic.link]p17, strictly speaking. I've also 
merged the main branch. On my machine, the (new) tests in 
`./tools/clang/test/Modules` still pass. Does this work for you? Thanks again 
for the review!

https://github.com/llvm/llvm-project/pull/104701
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits