Skip to content

Commit b02a3ab

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 704d51f + 0337f7e commit b02a3ab

11 files changed

+531
-12
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ GROUPED_WARNING(inconsistent_swift_name, ClangDeclarationImport, none,
7373
(bool, StringRef, StringRef, DeclName, StringRef, DeclName,
7474
StringRef))
7575

76+
WARNING(swift_name_attr_ignored, none,
77+
"ignoring swift_name attribute %0; swift_name attributes have no "
78+
"effect on method overrides",
79+
(DeclName))
80+
7681
GROUPED_WARNING(swift_name_circular_context_import, ClangDeclarationImport, none,
7782
"cycle detected while resolving '%0' in swift_name attribute for '%1'",
7883
(StringRef, StringRef))

lib/ClangImporter/ClangImporter.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6365,11 +6365,9 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
63656365
// Capture the arity of already found members in the
63666366
// current record, to avoid adding ambiguous members
63676367
// from base classes.
6368-
const auto getArity =
6369-
ClangImporter::Implementation::getImportedBaseMemberDeclArity;
6370-
llvm::SmallSet<size_t, 4> foundNameArities;
6368+
llvm::SmallSet<DeclName, 4> foundMethodNames;
63716369
for (const auto *valueDecl : result)
6372-
foundNameArities.insert(getArity(valueDecl));
6370+
foundMethodNames.insert(valueDecl->getName());
63736371

63746372
for (auto base : cxxRecord->bases()) {
63756373
if (skipIfNonPublic && base.getAccessSpecifier() != clang::AS_public)
@@ -6403,9 +6401,9 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
64036401
{});
64046402

64056403
for (auto foundInBase : baseResults) {
6406-
// Do not add duplicate entry with the same arity,
6404+
// Do not add duplicate entry with the same DeclName,
64076405
// as that would cause an ambiguous lookup.
6408-
if (foundNameArities.count(getArity(foundInBase)))
6406+
if (foundMethodNames.count(foundInBase->getName()))
64096407
continue;
64106408

64116409
collector.add(foundInBase);
@@ -7709,6 +7707,7 @@ ValueDecl *ClangImporter::Implementation::importBaseMemberDecl(
77097707
auto known = clonedBaseMembers.find(key);
77107708
if (known == clonedBaseMembers.end()) {
77117709
ValueDecl *cloned = cloneBaseMemberDecl(decl, newContext, inheritance);
7710+
handleAmbiguousSwiftName(cloned);
77127711
known = clonedBaseMembers.insert({key, cloned}).first;
77137712
clonedMembers.insert(std::make_pair(cloned, decl));
77147713
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "swift/ClangImporter/ClangImporterRequests.h"
5656
#include "swift/ClangImporter/ClangModule.h"
5757
#include "swift/Parse/Lexer.h"
58+
#include "swift/Parse/ParseDeclName.h"
5859
#include "swift/Strings.h"
5960
#include "clang/AST/ASTContext.h"
6061
#include "clang/AST/Attr.h"
@@ -4427,7 +4428,43 @@ namespace {
44274428
// Create a thunk that will perform dynamic dispatch.
44284429
// TODO: we don't have to import the actual `method` in this case,
44294430
// we can just synthesize a thunk and import that instead.
4430-
auto result = synthesizer.makeVirtualMethod(decl);
4431+
4432+
FuncDecl *result;
4433+
if (decl->size_overridden_methods() > 0) {
4434+
if (auto swiftNameAttr = decl->getAttr<clang::SwiftNameAttr>()) {
4435+
auto parsedDeclName = parseDeclName(swiftNameAttr->getName());
4436+
auto swiftDeclName =
4437+
parsedDeclName.formDeclName(method->getASTContext());
4438+
ImportedName importedName;
4439+
std::tie(importedName, std::ignore) = importFullName(decl);
4440+
4441+
result = synthesizer.makeVirtualMethod(decl);
4442+
4443+
if (swiftDeclName != importedName.getDeclName()) {
4444+
Impl.diagnose(HeaderLoc(swiftNameAttr->getLoc()),
4445+
diag::swift_name_attr_ignored, swiftDeclName);
4446+
4447+
Impl.markUnavailable(
4448+
result, (llvm::Twine("ignoring swift_name '") +
4449+
swiftNameAttr->getName() + "' in '" +
4450+
decl->getParent()->getName() +
4451+
"'; swift_name attributes have no effect "
4452+
"on method overrides")
4453+
.str());
4454+
}
4455+
} else {
4456+
// If there's no swift_name attribute, we don't import this method.
4457+
// This is because if the overridden method was renamed and
4458+
// this one is not, we want to use the overridden method's name.
4459+
// This is reasonable because `makeVirtualMethod` returns
4460+
// a thunk that will perform dynamic dispatch, and consequently
4461+
// the correct instance of the method will get executed.
4462+
return nullptr;
4463+
}
4464+
} else {
4465+
result = synthesizer.makeVirtualMethod(decl);
4466+
}
4467+
44314468
if (result) {
44324469
return result;
44334470
} else {
@@ -10378,6 +10415,22 @@ ValueDecl *ClangImporter::Implementation::createUnavailableDecl(
1037810415
return var;
1037910416
}
1038010417

10418+
void ClangImporter::Implementation::handleAmbiguousSwiftName(ValueDecl *decl) {
10419+
if (!decl || decl->isUnavailable())
10420+
return;
10421+
10422+
auto *cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(
10423+
decl->getDeclContext()->getAsDecl()->getClangDecl());
10424+
10425+
if (!cxxRecordDecl)
10426+
return;
10427+
10428+
if (findUnavailableMethod(cxxRecordDecl, decl->getName())) {
10429+
markUnavailable(decl,
10430+
"overrides multiple C++ methods with different Swift names");
10431+
}
10432+
}
10433+
1038110434
// Force the members of the entire inheritance hierarchy to be loaded and
1038210435
// deserialized before loading the members of this class. This allows the
1038310436
// decl members table to be warmed up and enables the correct identification of

lib/ClangImporter/ImportName.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,12 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
17061706
}
17071707
}
17081708

1709+
// `swift_name` attribute is not supported in virtual methods overrides
1710+
if (auto method = dyn_cast<clang::CXXMethodDecl>(D)) {
1711+
if (method->isVirtual() && method->size_overridden_methods() > 0)
1712+
skipCustomName = true;
1713+
}
1714+
17091715
if (!skipCustomName) {
17101716
result.info.hasCustomName = true;
17111717
result.declName = parsedName.formDeclName(
@@ -2315,6 +2321,42 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
23152321
newName = baseName.substr(StringRef("__synthesizedVirtualCall_").size());
23162322
baseName = newName;
23172323
}
2324+
if (method->isVirtual()) {
2325+
// The name should be imported from the base method
2326+
if (method->size_overridden_methods() > 0) {
2327+
DeclName overriddenName;
2328+
bool foundDivergentMethod = false;
2329+
for (auto overriddenMethod : method->overridden_methods()) {
2330+
ImportedName importedName =
2331+
importName(overriddenMethod, version, givenName);
2332+
if (!overriddenName) {
2333+
overriddenName = importedName.getDeclName();
2334+
} else if (overriddenName.compare(importedName.getDeclName())) {
2335+
importerImpl->insertUnavailableMethod(method->getParent(),
2336+
importedName.getDeclName());
2337+
foundDivergentMethod = true;
2338+
}
2339+
}
2340+
2341+
if (foundDivergentMethod) {
2342+
// The method we want to mark as unavailable will be generated
2343+
// lazily, when we clone the methods from base classes to the derived
2344+
// class method->getParent().
2345+
// Since we don't have the actual method here, we store this
2346+
// information to be accessed when we generate the actual method.
2347+
importerImpl->insertUnavailableMethod(method->getParent(),
2348+
overriddenName);
2349+
return ImportedName();
2350+
}
2351+
2352+
baseName = overriddenName.getBaseIdentifier().str();
2353+
// Also inherit argument names from base method
2354+
argumentNames.clear();
2355+
llvm::for_each(overriddenName.getArgumentNames(), [&](Identifier arg) {
2356+
argumentNames.push_back(arg.str());
2357+
});
2358+
}
2359+
}
23182360
}
23192361

23202362
// swift_newtype-ed declarations may have common words with the type name

lib/ClangImporter/ImporterImpl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,14 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
699699
// Map all cloned methods back to the original member
700700
llvm::DenseMap<ValueDecl *, ValueDecl *> clonedMembers;
701701

702+
// Keep track of methods that are unavailale in each class.
703+
// We need this set because these methods will be imported lazily. We don't
704+
// have the corresponding Swift method when the availability check is
705+
// performed, so instead we store the information in this set and then, when
706+
// the method is finally generated, we check if it's present here
707+
llvm::DenseSet<std::pair<const clang::CXXRecordDecl *, DeclName>>
708+
unavailableMethods;
709+
702710
public:
703711
llvm::DenseMap<const clang::ParmVarDecl*, FuncDecl*> defaultArgGenerators;
704712

@@ -727,6 +735,18 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
727735
return getNameImporter().getEnumKind(decl);
728736
}
729737

738+
bool findUnavailableMethod(const clang::CXXRecordDecl *classDecl,
739+
DeclName name) {
740+
return unavailableMethods.contains({classDecl, name});
741+
}
742+
743+
void insertUnavailableMethod(const clang::CXXRecordDecl *classDecl,
744+
DeclName name) {
745+
unavailableMethods.insert({classDecl, name});
746+
}
747+
748+
void handleAmbiguousSwiftName(ValueDecl *decl);
749+
730750
private:
731751
/// A mapping from imported declarations to their "alternate" declarations,
732752
/// for cases where a single Clang declaration is imported to two

lib/ClangImporter/SwiftLookupTable.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/Basic/STLExtras.h"
2323
#include "swift/Basic/Version.h"
2424
#include "swift/ClangImporter/ClangImporter.h"
25+
#include "swift/Parse/ParseDeclName.h"
2526
#include "clang/AST/DeclCXX.h"
2627
#include "clang/AST/DeclObjC.h"
2728
#include "clang/Lex/MacroInfo.h"
@@ -1922,6 +1923,15 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
19221923
named, importedName.getEffectiveContext());
19231924
}
19241925

1926+
if (auto swiftNameAttr = named->getAttr<clang::SwiftNameAttr>()) {
1927+
auto parsedDeclName = parseDeclName(swiftNameAttr->getName());
1928+
auto swiftDeclName =
1929+
parsedDeclName.formDeclName(nameImporter.getContext());
1930+
if (importedName.getDeclName() != swiftDeclName)
1931+
table.addEntry(swiftDeclName, named,
1932+
importedName.getEffectiveContext());
1933+
}
1934+
19251935
return true;
19261936
});
19271937
if (failed) {

test/IDE/dump_swift_lookup_tables.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,19 @@ import ImportAsMember
4141
// CHECK-NEXT: TU: __swift
4242
// CHECK-NEXT: adding:
4343
// CHECK-NEXT: SNSomeStruct: SNAdding
44-
// CHECK-NEXT: blue:
44+
// CHECK: blue:
4545
// CHECK-NEXT: SNColorChoice: SNColorBlue
4646
// CHECK-NEXT: defaultValue:
4747
// CHECK-NEXT: SNSomeStruct: SNSomeStructGetDefault, SNSomeStructSetDefault
48-
// CHECK-NEXT: defaultX:
48+
// CHECK: defaultX:
4949
// CHECK-NEXT: SNSomeStruct: DefaultXValue
50-
// CHECK-NEXT: foo:
50+
// CHECK: foo:
5151
// CHECK-NEXT: SNSomeStruct: SNSomeStructGetFoo, SNSomeStructSetFoo
52-
// CHECK-NEXT: green:
52+
// CHECK: green:
5353
// CHECK-NEXT: SNColorChoice: SNColorGreen
5454
// CHECK-NEXT: init:
5555
// CHECK-NEXT: SNSomeStruct: SNCreate
56-
// CHECK-NEXT: makeSomeStruct:
56+
// CHECK: makeSomeStruct:
5757
// CHECK-NEXT: TU: SNMakeSomeStruct, SNMakeSomeStructForX
5858
// CHECK-NEXT: x:
5959
// CHECK-NEXT: SNSomeStruct: X

test/Interop/Cxx/foreign-reference/Inputs/member-inheritance.h

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,138 @@ inline const Immortal *_Nonnull castToImmortal(
139139
const DerivedFromImmortal *_Nonnull immortal) {
140140
return static_cast<const Immortal *>(immortal);
141141
}
142+
143+
// A1
144+
// / \
145+
// B1 B2
146+
// / \
147+
// C1 C2
148+
149+
struct IMMORTAL_FRT A1 {
150+
virtual int virtualMethod() const { return 111; }
151+
152+
__attribute__((swift_name("swiftFooRename()")))
153+
virtual int fooRename() const { return 112; }
154+
155+
__attribute__((swift_name("swiftBarRename()")))
156+
virtual int barRename() const { return 113; }
157+
158+
__attribute__((swift_name("swiftParamsRename(a1:)")))
159+
virtual int paramsRename(int i) const { return i; }
160+
161+
static A1 *_Nonnull create() { return new A1(); }
162+
};
163+
164+
struct B1 : A1 {
165+
__attribute__((swift_name("swiftVirtualMethod()")))
166+
virtual int virtualMethod() const override { return 211; }
167+
168+
virtual int fooRename() const override { return 212; }
169+
170+
__attribute__((swift_name("B1BarRename()")))
171+
virtual int barRename() const override { return 213; }
172+
173+
__attribute__((swift_name("swiftParamsRename(b1:)")))
174+
virtual int paramsRename(int i) const override { return i; }
175+
176+
static B1 *_Nonnull create() { return new B1(); }
177+
};
178+
179+
struct B2 : A1 {
180+
int virtualMethod() const { return 221; }
181+
182+
int fooRename() const { return 222; }
183+
184+
__attribute__((swift_name("B2BarRename()"))) int barRename() const {
185+
return 223;
186+
}
187+
188+
static B2 *_Nonnull create() { return new B2(); }
189+
};
190+
191+
struct C1 : B1 {
192+
__attribute__((swift_name("swiftFooRename()")))
193+
virtual int fooRename() const override { return 312; }
194+
195+
__attribute__((swift_name("swiftBarRename()")))
196+
virtual int barRename() const override { return 313; }
197+
198+
virtual int paramsRename(int i) const override { return i; }
199+
200+
static C1 *_Nonnull create() { return new C1(); }
201+
};
202+
203+
struct C2 : B1 {
204+
__attribute__((swift_name("swiftVirtualMethod()")))
205+
virtual int virtualMethod() const override { return 321; }
206+
207+
__attribute__((swift_name("C2FooRename()")))
208+
virtual int fooRename() const override { return 322; }
209+
210+
__attribute__((swift_name("B1BarRename()")))
211+
virtual int barRename() const override { return 323; }
212+
213+
__attribute__((swift_name("swiftParamsRename(b1:)")))
214+
virtual int paramsRename(int i) const override { return i; }
215+
216+
static C2 *_Nonnull create() { return new C2(); }
217+
};
218+
219+
struct IMMORTAL_FRT A2 {
220+
__attribute__((swift_name("swiftVirtualMethod()")))
221+
virtual int virtualMethod() const { return 121; }
222+
223+
__attribute__((swift_name("swiftFooRename()")))
224+
virtual int fooRename() const { return 122; }
225+
226+
__attribute__((swift_name("A2BarRename()")))
227+
virtual int barRename() const { return 123; }
228+
229+
__attribute__((swift_name("swiftParamsRename(a2:)"))) virtual int
230+
paramsRename(int i) const {
231+
return i + 1;
232+
}
233+
234+
static A2 *_Nonnull create() { return new A2(); }
235+
};
236+
237+
// A1 A2
238+
// \ /
239+
// D1
240+
241+
struct D1 : A1, A2 {
242+
static D1 *_Nonnull create() { return new D1(); }
243+
};
244+
245+
// A1 A2
246+
// \ /
247+
// B1 /
248+
// \ /
249+
// D2
250+
251+
struct D2 : B1, A2 {
252+
__attribute__((swift_name("swiftVirtualMethod()")))
253+
virtual int virtualMethod() const override { return 411; }
254+
255+
virtual int fooRename() const override { return 412; }
256+
257+
virtual int barRename() const override { return 413; }
258+
259+
virtual int paramsRename(int i) const override { return i; }
260+
};
261+
262+
// A1
263+
// / \
264+
// / \
265+
// B1 B2
266+
// |\ /|
267+
// | \ / |
268+
// | D3 |
269+
// C1 |
270+
// \ |
271+
// \ /
272+
// D4
273+
274+
struct D3 : B1, B2 {};
275+
276+
struct D4 : C1, B2 {};

0 commit comments

Comments
 (0)