Skip to content

Commit 9a3fd10

Browse files
committed
[cxx-interop] Allow virtual methods to be renamed with SWIFT_NAME
1 parent b41a21a commit 9a3fd10

File tree

5 files changed

+37
-8
lines changed

5 files changed

+37
-8
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4393,7 +4393,16 @@ namespace {
43934393
// Create a thunk that will perform dynamic dispatch.
43944394
// TODO: we don't have to import the actual `method` in this case,
43954395
// we can just synthesize a thunk and import that instead.
4396-
auto result = synthesizer.makeVirtualMethod(decl);
4396+
ImportedName importedName;
4397+
std::optional<ImportedName> correctSwiftName;
4398+
std::tie(importedName, correctSwiftName) = importFullName(decl);
4399+
if (!importedName)
4400+
return nullptr;
4401+
auto result = synthesizer.makeVirtualMethod(decl, importedName);
4402+
4403+
if (correctSwiftName)
4404+
markAsVariant(result, *correctSwiftName);
4405+
43974406
if (result) {
43984407
return result;
43994408
} else {

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,7 +2013,8 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
20132013
ForwardingMethodKind forwardingMethodKind,
20142014
ReferenceReturnTypeBehaviorForBaseMethodSynthesis
20152015
referenceReturnTypeBehavior,
2016-
bool forceConstQualifier) {
2016+
bool forceConstQualifier,
2017+
std::optional<importer::ImportedName> importedName) {
20172018

20182019
auto &clangCtx = ImporterImpl.getClangASTContext();
20192020
auto &clangSema = ImporterImpl.getClangSema();
@@ -2029,7 +2030,9 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
20292030
os << (forwardingMethodKind == ForwardingMethodKind::Virtual
20302031
? "__synthesizedVirtualCall_"
20312032
: "__synthesizedBaseCall_")
2032-
<< name.getAsIdentifierInfo()->getName();
2033+
<< (importedName
2034+
? importedName->getDeclName().getBaseName().userFacingName()
2035+
: name.getAsIdentifierInfo()->getName());
20332036
name = clang::DeclarationName(
20342037
&ImporterImpl.getClangPreprocessor().getIdentifierTable().get(
20352038
os.str()));
@@ -2259,9 +2262,9 @@ SwiftDeclSynthesizer::makeOperator(FuncDecl *operatorMethod,
22592262
}
22602263

22612264
// MARK: C++ virtual methods
2262-
22632265
FuncDecl *SwiftDeclSynthesizer::makeVirtualMethod(
2264-
const clang::CXXMethodDecl *clangMethodDecl) {
2266+
const clang::CXXMethodDecl *clangMethodDecl,
2267+
importer::ImportedName importedName) {
22652268
auto clangDC = clangMethodDecl->getParent();
22662269
auto &ctx = ImporterImpl.SwiftContext;
22672270

@@ -2271,7 +2274,7 @@ FuncDecl *SwiftDeclSynthesizer::makeVirtualMethod(
22712274
auto newMethod = synthesizeCXXForwardingMethod(
22722275
clangDC, clangDC, clangMethodDecl, ForwardingMethodKind::Virtual,
22732276
ReferenceReturnTypeBehaviorForBaseMethodSynthesis::KeepReference,
2274-
/*forceConstQualifier*/ false);
2277+
/*forceConstQualifier*/ false, importedName);
22752278

22762279
auto result = dyn_cast_or_null<FuncDecl>(
22772280
ctx.getClangModuleLoader()->importDeclDirectly(newMethod));

lib/ClangImporter/SwiftDeclSynthesizer.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,13 @@ class SwiftDeclSynthesizer {
318318
ReferenceReturnTypeBehaviorForBaseMethodSynthesis
319319
referenceReturnTypeBehavior =
320320
ReferenceReturnTypeBehaviorForBaseMethodSynthesis::KeepReference,
321-
bool forceConstQualifier = false);
321+
bool forceConstQualifier = false,
322+
std::optional<importer::ImportedName> importedName = std::nullopt);
322323

323324
/// Given an overload of a C++ virtual method on a reference type, create a
324325
/// method that dispatches the call dynamically.
325-
FuncDecl *makeVirtualMethod(const clang::CXXMethodDecl *clangMethodDecl);
326+
FuncDecl *makeVirtualMethod(const clang::CXXMethodDecl *clangMethodDecl,
327+
importer::ImportedName importedName);
326328

327329
FuncDecl *makeInstanceToStaticOperatorCallMethod(
328330
const clang::CXXMethodDecl *clangMethodDecl);

test/Interop/Cxx/class/inheritance/Inputs/virtual-methods.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ inline void testFunctionCollected() {
66

77
struct Base {
88
virtual void foo() = 0;
9+
virtual void virtualRename() const
10+
__attribute__((swift_name("swiftVirtualRename()")));
911
};
1012

1113
struct Base2 { virtual int f() = 0; };
@@ -83,6 +85,8 @@ struct IMMORTAL_FRT DerivedFromImmortal : public Immortal {
8385
struct IMMORTAL_FRT Immortal2 {
8486
public:
8587
virtual void virtualMethod(HasDestructor) = 0;
88+
virtual void virtualRename() const
89+
__attribute__((swift_name("swiftVirtualRename()")));
8690
};
8791

8892
inline const ImmortalBase *_Nonnull castToImmortalBase(

test/Interop/Cxx/class/inheritance/virtual-methods-typechecker.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,14 @@ func takesDerivedFromImmortal(_ i: DerivedFromImmortal) {
3737
let _ = i.getIntValue()
3838
i.setIntValue(1)
3939
}
40+
41+
func callVirtualRenamedMethod(_ b: Base) {
42+
b.virtualRename() // expected-error {{value of type 'Base' has no member 'virtualRename'}}
43+
b.swiftVirtualRename()
44+
}
45+
46+
@available(SwiftStdlib 5.8, *)
47+
func callsRenamedVirtualMethodsInFRT(_ i: Immortal2) {
48+
i.virtualRename() // expected-error {{value of type 'Immortal2' has no member 'virtualRename'}}
49+
i.swiftVirtualRename()
50+
}

0 commit comments

Comments
 (0)