mirror of
https://github.com/apple/swift.git
synced 2026-03-04 18:24:35 +01:00
[Importer] Ensure that we can see macro-expanded declarations in C++ namespaces
Lookup into C++ namespaces uses a different path from C++ record declarations. Augment the C++ namespace lookup path to also account for the auxiliary declarations introduced by peer macro expansions.
This commit is contained in:
@@ -2750,8 +2750,24 @@ static void addNamespaceMembers(Decl *decl,
|
||||
auto clangMember = found.get<clang::NamedDecl *>();
|
||||
if (auto importedDecl =
|
||||
ctx.getClangModuleLoader()->importDeclDirectly(clangMember)) {
|
||||
if (addedMembers.insert(importedDecl).second)
|
||||
if (addedMembers.insert(importedDecl).second) {
|
||||
members.push_back(importedDecl);
|
||||
|
||||
// Handle macro-expanded declarations.
|
||||
importedDecl->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;
|
||||
|
||||
members.push_back(valueDecl);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5078,6 +5078,42 @@ ClangDirectLookupRequest::evaluate(Evaluator &evaluator,
|
||||
return filteredDecls;
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// Collects name lookup results into the given tiny vector, for use in the
|
||||
/// various Clang importer lookup routines.
|
||||
class CollectLookupResults {
|
||||
DeclName name;
|
||||
TinyPtrVector<ValueDecl *> &result;
|
||||
|
||||
public:
|
||||
CollectLookupResults(DeclName name, TinyPtrVector<ValueDecl *> &result)
|
||||
: name(name), result(result) { }
|
||||
|
||||
void add(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);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TinyPtrVector<ValueDecl *> CXXNamespaceMemberLookup::evaluate(
|
||||
Evaluator &evaluator, CXXNamespaceMemberLookupDescriptor desc) const {
|
||||
EnumDecl *namespaceDecl = desc.namespaceDecl;
|
||||
@@ -5087,6 +5123,8 @@ TinyPtrVector<ValueDecl *> CXXNamespaceMemberLookup::evaluate(
|
||||
auto &ctx = namespaceDecl->getASTContext();
|
||||
|
||||
TinyPtrVector<ValueDecl *> result;
|
||||
CollectLookupResults collector(name, result);
|
||||
|
||||
llvm::SmallPtrSet<clang::NamedDecl *, 8> importedDecls;
|
||||
for (auto redecl : clangNamespaceDecl->redecls()) {
|
||||
auto allResults = evaluateOrDefault(
|
||||
@@ -5102,7 +5140,7 @@ TinyPtrVector<ValueDecl *> CXXNamespaceMemberLookup::evaluate(
|
||||
continue;
|
||||
if (auto import =
|
||||
ctx.getClangModuleLoader()->importDeclDirectly(clangMember))
|
||||
result.push_back(cast<ValueDecl>(import));
|
||||
collector.add(cast<ValueDecl>(import));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6202,28 +6240,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
|
||||
|
||||
// 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);
|
||||
});
|
||||
};
|
||||
CollectLookupResults collector(name, result);
|
||||
|
||||
// Find the results that are actually a member of "recordDecl".
|
||||
ClangModuleLoader *clangModuleLoader = ctx.getClangModuleLoader();
|
||||
@@ -6261,7 +6278,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
|
||||
continue;
|
||||
}
|
||||
|
||||
addResult(cast<ValueDecl>(imported));
|
||||
collector.add(cast<ValueDecl>(imported));
|
||||
}
|
||||
|
||||
if (inheritance) {
|
||||
@@ -6280,7 +6297,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
|
||||
if (!imported)
|
||||
continue;
|
||||
|
||||
addResult(imported);
|
||||
collector.add(imported);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6329,7 +6346,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
|
||||
if (foundNameArities.count(getArity(foundInBase)))
|
||||
continue;
|
||||
|
||||
addResult(foundInBase);
|
||||
collector.add(foundInBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +329,11 @@ void swift::performImportResolutionForClangMacroBuffer(
|
||||
ImportResolver resolver(SF);
|
||||
resolver.addImplicitImport(clangModule);
|
||||
|
||||
// FIXME: This is a hack that we shouldn't need, but be sure that we can
|
||||
// see the Swift standard library.
|
||||
if (auto stdlib = SF.getASTContext().getStdlibModule())
|
||||
resolver.addImplicitImport(stdlib);
|
||||
|
||||
SF.setImports(resolver.getFinishedImports());
|
||||
SF.setImportedUnderlyingModule(resolver.getUnderlyingClangModule());
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// REQUIRES: swift_feature_SafeInteropWrappers
|
||||
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %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=Namespace -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/namespace.swift -dump-macro-expansions -typecheck -verify
|
||||
|
||||
// CHECK: enum foo {
|
||||
// CHECK: static func bar(_ p: UnsafeMutableBufferPointer<Float>)
|
||||
|
||||
//--- Inputs/module.modulemap
|
||||
module Namespace {
|
||||
header "namespace.h"
|
||||
requires cplusplus
|
||||
}
|
||||
|
||||
//--- Inputs/namespace.h
|
||||
|
||||
namespace foo {
|
||||
__attribute__((swift_attr("@_SwiftifyImport(.countedBy(pointer: .param(1), count: \"len\"))"))) void bar(float *p, int len);
|
||||
}
|
||||
|
||||
//--- namespace.swift
|
||||
import Namespace
|
||||
|
||||
func test(s: UnsafeMutableBufferPointer<Float>) {
|
||||
foo.bar(s)
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
// 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-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>)
|
||||
// CHECK-SAME: public mutating func bar(_ p: UnsafeMutableBufferPointer<Float>)
|
||||
|
||||
//--- Inputs/module.modulemap
|
||||
module Method {
|
||||
|
||||
Reference in New Issue
Block a user