[Clang importer] Report auxiliary decls from C++ member lookup

When performing name lookup into a C++ record type, make sure that we
also walk through auxiliary declarations (i.e., declarations that can
come from peer macro expansions) to find results.

Fixes rdar://146833294.
This commit is contained in:
Doug Gregor
2025-03-14 12:23:28 -07:00
parent 01b2789dc8
commit e3618dd797
2 changed files with 59 additions and 4 deletions

View File

@@ -6200,8 +6200,32 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
ClangDirectLookupRequest({recordDecl, recordDecl->getClangDecl(), name}),
{});
// Find the results that are actually a member of "recordDecl".
// The set of declarations we found.
TinyPtrVector<ValueDecl *> result;
auto addResult = [&result, name](ValueDecl *imported) {
result.push_back(imported);
// Expand any macros introduced by the Clang importer.
imported->visitAuxiliaryDecls([&](Decl *decl) {
auto valueDecl = dyn_cast<ValueDecl>(decl);
if (!valueDecl)
return;
// Bail out if the auxiliary decl was not produced by a macro.
auto module = decl->getDeclContext()->getParentModule();
auto *sf = module->getSourceFileContainingLocation(decl->getLoc());
if (!sf || sf->Kind != SourceFileKind::MacroExpansion)
return;
// Only produce results that match the requested name.
if (!valueDecl->getName().matchesRef(name))
return;
result.push_back(valueDecl);
});
};
// Find the results that are actually a member of "recordDecl".
ClangModuleLoader *clangModuleLoader = ctx.getClangModuleLoader();
for (auto foundEntry : directResults) {
auto found = foundEntry.get<clang::NamedDecl *>();
@@ -6236,7 +6260,8 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
if (!imported)
continue;
}
result.push_back(cast<ValueDecl>(imported));
addResult(cast<ValueDecl>(imported));
}
if (inheritance) {
@@ -6255,7 +6280,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
if (!imported)
continue;
result.push_back(cast<ValueDecl>(imported));
addResult(imported);
}
}
@@ -6304,7 +6329,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
if (foundNameArities.count(getArity(foundInBase)))
continue;
result.push_back(foundInBase);
addResult(foundInBase);
}
}
}

View File

@@ -0,0 +1,30 @@
// REQUIRES: swift_feature_SafeInteropWrappers
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUNx: %target-swift-ide-test -plugin-path %swift-plugin-dir -I %t/Inputs -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature SafeInteropWrappers -print-module -module-to-print=Method -source-filename=x | %FileCheck %s
// RUN: %target-swift-frontend -plugin-path %swift-plugin-dir -I %t/Inputs -cxx-interoperability-mode=default -enable-experimental-feature SafeInteropWrappers %t/method.swift -dump-macro-expansions -typecheck -verify
// CHECK: @_alwaysEmitIntoClient
// CHECK: public mutating func bar(_ p: UnsafeMutableBufferPointer<Int32>)
//--- Inputs/module.modulemap
module Method {
header "method.h"
requires cplusplus
}
//--- Inputs/method.h
class Foo {
public:
__attribute__((swift_attr("@_SwiftifyImport(.countedBy(pointer: .param(1), count: \"len\"))"))) void bar(float *p, int len);
};
//--- method.swift
import Method
func test(s: UnsafeMutableBufferPointer<Float>) {
var foo = Foo()
foo.bar(s)
}