aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp23
1 files changed, 19 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index fff49b7..7589701 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6977,11 +6977,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, in violation of C++ [basic.link]p17.
+ /// However:
+ /// - Inline functions with internal linkage are a common pattern in
+ /// headers to avoid ODR issues.
+ /// - The global module is meant to be a transition mechanism for C and C++
+ /// headers, and the current rules as written work against that goal.
+ const bool IsInlineFunctionInGMF =
+ Function->isFromGlobalModule() &&
+ (IsImplicitlyInstantiated || Function->isInlined());
+
+ if (ND->getFormalLinkage() == Linkage::Internal && !IsInlineFunctionInGMF) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_module_mismatched;
return;