diff options
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 23 |
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; |