[6.2][cxx-interop] Fix unqualified name lookup failure

Explanation: C++ interop synthesizes certain forwarding functions in an
_ObjC module. This confuses MemberImportVisibility. This patch adds
logic to work this around by keeping a mapping between the synthesized
and the original function and looks up where the synthesized functions
belong to based on the original functions' parent module.
Scope: C++ forward interop when MemberImportVisibility is enabled.
Issues: rdar://154887575
Original PRs: #82840
Risk: Low, a narrow change makes getModuleContextForNameLookupForCxxDecl more
precise, and it is only used with MemberImportVisibility.
Testing: Added a compiler test.
Reviewers: @egorzhdan, @tshortli, @hnrklssn
This commit is contained in:
Gábor Horváth
2025-07-08 17:53:35 +01:00
committed by Gabor Horvath
parent 7c12be865e
commit b51b58db30
8 changed files with 81 additions and 5 deletions

View File

@@ -906,6 +906,17 @@ static ModuleDecl *getModuleContextForNameLookupForCxxDecl(const Decl *decl) {
if (!ctx.LangOpts.EnableCXXInterop)
return nullptr;
// When we clone members for base classes the cloned members have no
// corresponding Clang nodes. Look up the original imported declaration to
// figure out what Clang module does the cloned member originate from.
bool isClonedMember = false;
if (auto VD = dyn_cast<ValueDecl>(decl))
if (auto loader = ctx.getClangModuleLoader())
if (auto original = loader->getOriginalForClonedMember(VD)) {
isClonedMember = true;
decl = original;
}
if (!decl->hasClangNode())
return nullptr;
@@ -913,8 +924,11 @@ static ModuleDecl *getModuleContextForNameLookupForCxxDecl(const Decl *decl) {
// We only need to look for the real parent module when the existing parent
// is the imported header module.
if (!parentModule->isClangHeaderImportModule())
if (!parentModule->isClangHeaderImportModule()) {
if (isClonedMember)
return parentModule;
return nullptr;
}
auto clangModule = decl->getClangDecl()->getOwningModule();
if (!clangModule)