Skip to content

Commit e108828

Browse files
committed
[cxx-interop] Fix ambiguous methods in long chains of inheritance
1 parent 54f0bf2 commit e108828

File tree

5 files changed

+34
-1
lines changed

5 files changed

+34
-1
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ class ClangModuleLoader : public ModuleLoader {
216216
DeclContext *newContext,
217217
ClangInheritanceInfo inheritance) = 0;
218218

219+
/// Checks if \param decl is the original method or a clone from a base class
220+
virtual bool isClonedBaseMemberDecl(ValueDecl *decl) = 0;
221+
219222
/// Emits diagnostics for any declarations named name
220223
/// whose direct declaration context is a TU.
221224
virtual void diagnoseTopLevelValue(const DeclName &name) = 0;

include/swift/ClangImporter/ClangImporter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,8 @@ class ClangImporter final : public ClangModuleLoader {
657657
ValueDecl *importBaseMemberDecl(ValueDecl *decl, DeclContext *newContext,
658658
ClangInheritanceInfo inheritance) override;
659659

660+
bool isClonedBaseMemberDecl(ValueDecl *decl) override;
661+
660662
/// Emits diagnostics for any declarations named name
661663
/// whose direct declaration context is a TU.
662664
void diagnoseTopLevelValue(const DeclName &name) override;

lib/ClangImporter/ClangImporter.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6311,7 +6311,8 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
63116311
cast<NominalTypeDecl>(recordDecl)->getCurrentMembersWithoutLoading()) {
63126312
auto namedMember = dyn_cast<ValueDecl>(member);
63136313
if (!namedMember || !namedMember->hasName() ||
6314-
namedMember->getName().getBaseName() != name)
6314+
namedMember->getName().getBaseName() != name ||
6315+
clangModuleLoader->isClonedBaseMemberDecl(namedMember))
63156316
continue;
63166317

63176318
auto *imported = clangModuleLoader->importBaseMemberDecl(
@@ -7661,6 +7662,7 @@ ValueDecl *ClangImporter::Implementation::importBaseMemberDecl(
76617662
// result in multiple definitions of the same symbol.
76627663
std::pair<ValueDecl *, DeclContext *> key = {decl, newContext};
76637664
auto known = clonedBaseMembers.find(key);
7665+
76647666
if (known == clonedBaseMembers.end()) {
76657667
ValueDecl *cloned = cloneBaseMemberDecl(decl, newContext, inheritance);
76667668
known = clonedBaseMembers.insert({key, cloned}).first;
@@ -7669,6 +7671,19 @@ ValueDecl *ClangImporter::Implementation::importBaseMemberDecl(
76697671
return known->second;
76707672
}
76717673

7674+
bool ClangImporter::Implementation::isClonedBaseMemberDecl(ValueDecl *decl) {
7675+
7676+
// If this is a cloned decl, we don't want to reclone it
7677+
if (!decl->hasClangNode()) {
7678+
for (auto &CBM : clonedBaseMembers) {
7679+
if (decl == CBM.second)
7680+
return true;
7681+
}
7682+
}
7683+
7684+
return false;
7685+
}
7686+
76727687
size_t ClangImporter::Implementation::getImportedBaseMemberDeclArity(
76737688
const ValueDecl *valueDecl) {
76747689
if (auto *func = dyn_cast<FuncDecl>(valueDecl)) {
@@ -7685,6 +7700,10 @@ ClangImporter::importBaseMemberDecl(ValueDecl *decl, DeclContext *newContext,
76857700
return Impl.importBaseMemberDecl(decl, newContext, inheritance);
76867701
}
76877702

7703+
bool ClangImporter::isClonedBaseMemberDecl(ValueDecl *decl) {
7704+
return Impl.isClonedBaseMemberDecl(decl);
7705+
}
7706+
76887707
void ClangImporter::diagnoseTopLevelValue(const DeclName &name) {
76897708
Impl.diagnoseTopLevelValue(name);
76907709
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
700700
ValueDecl *importBaseMemberDecl(ValueDecl *decl, DeclContext *newContext,
701701
ClangInheritanceInfo inheritance);
702702

703+
bool isClonedBaseMemberDecl(ValueDecl *decl);
704+
703705
static size_t getImportedBaseMemberDeclArity(const ValueDecl *valueDecl);
704706

705707
// Cache for already-specialized function templates and any thunks they may

test/Interop/Cxx/class/inheritance/inherited-lookup-executable.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ import StdlibUnittest
66

77
var InheritedMemberTestSuite = TestSuite("Test if inherited lookup works")
88

9+
struct HasOne {
10+
let one: One
11+
let iOne: IOne
12+
let iiOne: IIOne
13+
let iiiOne: IIIOne
14+
}
15+
916
InheritedMemberTestSuite.test("Regular methods resolve to base classes") {
1017
// No inheritance (sanity check)
1118
let one = One()

0 commit comments

Comments
 (0)