Skip to content

Commit feaf651

Browse files
committed
Expose static inline function from GMF
They should be exposed even when two-phase name lookup and ADL are involved.
1 parent dac1829 commit feaf651

File tree

6 files changed

+168
-4
lines changed

6 files changed

+168
-4
lines changed

clang/lib/Sema/SemaOverload.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6926,11 +6926,26 @@ void Sema::AddOverloadCandidate(
69266926
/// have linkage. So that all entities of the same should share one
69276927
/// linkage. But in clang, different entities of the same could have
69286928
/// different linkage.
6929-
NamedDecl *ND = Function;
6930-
if (auto *SpecInfo = Function->getTemplateSpecializationInfo())
6929+
const NamedDecl *ND = Function;
6930+
bool IsImplicitlyInstantiated = false;
6931+
if (auto *SpecInfo = Function->getTemplateSpecializationInfo()) {
69316932
ND = SpecInfo->getTemplate();
6932-
6933-
if (ND->getFormalLinkage() == Linkage::Internal) {
6933+
IsImplicitlyInstantiated = SpecInfo->getTemplateSpecializationKind() ==
6934+
TSK_ImplicitInstantiation;
6935+
}
6936+
6937+
/// Don't remove inline functions with internal linkage from the overload
6938+
/// set if they are declared in a GMF.
6939+
/// The global module is meant to be a transition mechanism for C and C++
6940+
/// headers.
6941+
/// Inline functions with internal linkage are a common pattern in headers
6942+
/// to avoid ODR issues.
6943+
const bool IsInlineFunctionInGMF =
6944+
Function->getOwningModule() &&
6945+
Function->getOwningModule()->isGlobalModule() &&
6946+
(IsImplicitlyInstantiated || Function->isInlined());
6947+
6948+
if (ND->getFormalLinkage() == Linkage::Internal && !IsInlineFunctionInGMF) {
69346949
Candidate.Viable = false;
69356950
Candidate.FailureKind = ovl_fail_module_mismatched;
69366951
return;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm \
6+
// RUN: -DTEST_INLINE
7+
// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify \
8+
// RUN: -DTEST_INLINE
9+
//
10+
// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm
11+
// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify
12+
13+
//--- a.h
14+
#ifdef TEST_INLINE
15+
#define INLINE inline
16+
#else
17+
#define INLINE
18+
#endif
19+
static INLINE void func(long) {}
20+
template <typename T = long> void a() { func(T{}); }
21+
22+
//--- a.cppm
23+
module;
24+
#include "a.h"
25+
export module a;
26+
export using ::a;
27+
28+
//--- test.cc
29+
import a;
30+
auto m = (a(), 0);
31+
32+
#ifdef TEST_INLINE
33+
// expected-no-diagnostics
34+
#else
35+
// [email protected]:7 {{no matching function for call to 'func'}}
36+
// [email protected]:2 {{in instantiation of function template specialization 'a<long>' requested here}}
37+
#endif
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm
6+
// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify
7+
8+
//--- a.h
9+
template <typename G> static inline void func() {}
10+
template <typename T = long> void a() { func<T>(); }
11+
12+
//--- a.cppm
13+
module;
14+
#include "a.h"
15+
export module a;
16+
export using ::a;
17+
18+
//--- test.cc
19+
import a;
20+
auto m = (a(), 0);
21+
22+
// expected-no-diagnostics
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm
6+
// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify
7+
8+
//--- a.h
9+
namespace ns {
10+
template <typename G> static void func() {}
11+
template <typename T = long> void a() { func<T>(); }
12+
}
13+
14+
//--- a.cppm
15+
module;
16+
#include "a.h"
17+
export module a;
18+
export using ns::a;
19+
20+
//--- test.cc
21+
import a;
22+
auto m = (a(), 0);
23+
24+
// expected-no-diagnostics
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm \
6+
// RUN: -DTEST_INLINE
7+
// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify \
8+
// RUN: -DTEST_INLINE
9+
//
10+
// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm
11+
// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify
12+
13+
//--- a.h
14+
#ifdef TEST_INLINE
15+
#define INLINE inline
16+
#else
17+
#define INLINE
18+
#endif
19+
namespace ns {
20+
template <typename G> static void func() {}
21+
template <> INLINE void func<long>() {}
22+
template <typename T = long> void a() { func<T>(); }
23+
}
24+
25+
//--- a.cppm
26+
module;
27+
#include "a.h"
28+
export module a;
29+
export using ns::a;
30+
31+
//--- test.cc
32+
import a;
33+
auto m = (a(), 0);
34+
35+
#ifdef TEST_INLINE
36+
// expected-no-diagnostics
37+
#else
38+
// [email protected]:9 {{no matching function for call to 'func'}}
39+
// [email protected]:2 {{in instantiation of function template specialization 'ns::a<long>' requested here}}
40+
#endif
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang -std=c++20 %t/a.cppm --precompile -o %t/a.pcm
6+
// RUN: %clang -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -Xclang -verify
7+
8+
//--- a.h
9+
namespace ns {
10+
namespace {
11+
template <typename G> void func() {}
12+
}
13+
template <typename T = long> void a() { func<T>(); }
14+
}
15+
16+
//--- a.cppm
17+
module;
18+
#include "a.h"
19+
export module a;
20+
export using ns::a;
21+
22+
//--- test.cc
23+
import a;
24+
auto m = (a(), 0);
25+
26+
// expected-no-diagnostics

0 commit comments

Comments
 (0)