Skip to content

Commit 2a2ed0f

Browse files
authored
[C++ Interop] Implement lookup within namespace. (#26439)
Known problems: - The same namespace in multiple c++ modules will be subtly confused when doing lookup.
1 parent 3dc53c0 commit 2a2ed0f

File tree

6 files changed

+55
-3
lines changed

6 files changed

+55
-3
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3657,7 +3657,7 @@ ClangImporter::Implementation::loadNamedMembers(
36573657

36583658
clang::ASTContext &clangCtx = getClangASTContext();
36593659

3660-
assert(isa<clang::ObjCContainerDecl>(CD));
3660+
assert(isa<clang::ObjCContainerDecl>(CD) || isa<clang::NamespaceDecl>(CD));
36613661

36623662
TinyPtrVector<ValueDecl *> Members;
36633663
for (auto entry : table->lookup(SerializedSwiftName(N),

lib/ClangImporter/ImportDecl.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2385,6 +2385,7 @@ namespace {
23852385
importedName.getDeclName().getBaseIdentifier(),
23862386
Impl.importSourceLoc(decl->getLocation()), None, nullptr, dc);
23872387
enumDecl->computeType();
2388+
enumDecl->setMemberLoader(&Impl, 0);
23882389
return enumDecl;
23892390
}
23902391

@@ -3649,7 +3650,8 @@ namespace {
36493650
return nullptr;
36503651

36513652
DeclName name = accessorInfo ? DeclName() : importedName.getDeclName();
3652-
if (importedName.importAsMember()) {
3653+
3654+
if (!dc->isModuleScopeContext() && !isa<clang::CXXMethodDecl>(decl)) {
36533655
// Handle initializers.
36543656
if (name.getBaseName() == DeclBaseName::createConstructor()) {
36553657
assert(!accessorInfo);
@@ -8461,6 +8463,28 @@ ClangImporter::Implementation::loadAllMembers(Decl *D, uint64_t extra) {
84618463
loadAllMembersOfObjcContainer(D, objcContainer);
84628464
return;
84638465
}
8466+
8467+
auto namespaceDecl =
8468+
dyn_cast_or_null<clang::NamespaceDecl>(D->getClangDecl());
8469+
if (namespaceDecl) {
8470+
auto *enumDecl = cast<EnumDecl>(D);
8471+
// TODO: This redecls should only match redecls that are in the same
8472+
// module as namespaceDecl after we import one namespace per clang module.
8473+
for (auto ns : namespaceDecl->redecls()) {
8474+
for (auto m : ns->decls()) {
8475+
auto nd = dyn_cast<clang::NamedDecl>(m);
8476+
if (!nd)
8477+
continue;
8478+
auto member = importDecl(nd, CurrentVersion);
8479+
if (!member)
8480+
continue;
8481+
8482+
enumDecl->addMember(member);
8483+
}
8484+
}
8485+
return;
8486+
}
8487+
84648488
loadAllMembersIntoExtension(D, extra);
84658489
}
84668490

lib/ClangImporter/SwiftLookupTable.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,14 @@ translateDeclToContext(clang::NamedDecl *decl) {
195195
return None;
196196
}
197197

198+
// Namespace declaration.
199+
if (auto namespaceDecl = dyn_cast<clang::NamespaceDecl>(decl)) {
200+
if (namespaceDecl->getIdentifier())
201+
return std::make_pair(SwiftLookupTable::ContextKind::Tag,
202+
namespaceDecl->getName());
203+
return None;
204+
}
205+
198206
// Objective-C class context.
199207
if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(decl))
200208
return std::make_pair(SwiftLookupTable::ContextKind::ObjCClass,
@@ -230,6 +238,11 @@ auto SwiftLookupTable::translateDeclContext(const clang::DeclContext *dc)
230238
if (auto tag = dyn_cast<clang::TagDecl>(dc))
231239
return translateDeclToContext(const_cast<clang::TagDecl *>(tag));
232240

241+
// Namespace declaration context.
242+
if (auto namespaceDecl = dyn_cast<clang::NamespaceDecl>(dc))
243+
return translateDeclToContext(
244+
const_cast<clang::NamespaceDecl *>(namespaceDecl));
245+
233246
// Objective-C class context.
234247
if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(dc))
235248
return std::make_pair(ContextKind::ObjCClass, objcClass->getName());
@@ -1672,7 +1685,7 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
16721685
// Walk the members of any context that can have nested members.
16731686
if (isa<clang::TagDecl>(named) || isa<clang::ObjCInterfaceDecl>(named) ||
16741687
isa<clang::ObjCProtocolDecl>(named) ||
1675-
isa<clang::ObjCCategoryDecl>(named)) {
1688+
isa<clang::ObjCCategoryDecl>(named) || isa<clang::NamespaceDecl>(named)) {
16761689
clang::DeclContext *dc = cast<clang::DeclContext>(named);
16771690
for (auto member : dc->decls()) {
16781691
if (auto namedMember = dyn_cast<clang::NamedDecl>(member))

test/ClangImporter/Inputs/custom-modules/cxx_interop.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// Ensure c++ features are used.
44
namespace ns {
55
class T {};
6+
7+
T *doMakeT();
68
} // namespace ns
79

810
struct Basic {

test/ClangImporter/cxx_interop.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ do {
99
tmp.a = 3
1010
tmp.b = nil
1111
}
12+
13+
// Namespace lookup
14+
func namespaceLookup() -> UnsafeMutablePointer<ns.T> {
15+
var tmp: UnsafeMutablePointer<ns.T> = ns.doMakeT()!
16+
return tmp
17+
}

test/ClangImporter/cxx_interop_ir.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ func reflectionInfo(arg: namespacedT) -> Any.Type {
1919
func namespaceManglesIntoName(arg: namespacedT) {
2020
}
2121

22+
// CHECK-LABEL: define hidden swiftcc void @"$s6cxx_ir14accessNSMemberyyF"()
23+
// CHECK: %0 = call %"class.ns::T"* @{{_ZN2ns7doMakeTEv|"\?doMakeT@ns@@YAPEAVT@1@XZ"}}()
24+
// CHECK: call void @{{_Z4useTPN2ns1TE|"\?useT@@YAXPE?AVT@ns@@@Z"}}(%"class.ns::T"* %2)
25+
func accessNSMember() {
26+
useT(ns.doMakeT())
27+
}
28+
2229
// CHECK-LABEL: define hidden swiftcc i32 @"$s6cxx_ir12basicMethods1as5Int32VSpySo0D0VG_tF"(i8*)
2330
// CHECK: [[THIS_PTR1:%.*]] = bitcast i8* %0 to %TSo7MethodsV*
2431
// CHECK: [[THIS_PTR2:%.*]] = bitcast %TSo7MethodsV* [[THIS_PTR1]] to %class.Methods*

0 commit comments

Comments
 (0)