Skip to content

Commit 3d8e60d

Browse files
authored
Merge pull request swiftlang#63523 from hyp/eng/i-static-methods
[interop][SwiftToCxx] add C++ bindings for static methods
2 parents 2b13eca + 8305c7d commit 3d8e60d

File tree

5 files changed

+56
-17
lines changed

5 files changed

+56
-17
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,10 @@ class DeclAndTypePrinter::Implementation
977977
getForeignResultType(AFD, methodTy, asyncConvention, errorConvention);
978978

979979
if (outputLang == OutputLanguageMode::Cxx) {
980+
// FIXME: Support operators.
981+
if (AFD->isOperator() || (AFD->isStatic() && AFD->isImplicit()))
982+
return;
983+
980984
auto *typeDeclContext = dyn_cast<NominalTypeDecl>(AFD->getParent());
981985
if (!typeDeclContext) {
982986
typeDeclContext =
@@ -1013,6 +1017,7 @@ class DeclAndTypePrinter::Implementation
10131017
declPrinter.printCxxMethod(typeDeclContext, AFD,
10141018
funcABI->getSignature(),
10151019
funcABI->getSymbolName(), resultTy,
1020+
/*isStatic=*/isClassMethod,
10161021
/*isDefinition=*/false);
10171022
}
10181023

@@ -1035,6 +1040,7 @@ class DeclAndTypePrinter::Implementation
10351040
} else {
10361041
defPrinter.printCxxMethod(typeDeclContext, AFD, funcABI->getSignature(),
10371042
funcABI->getSymbolName(), resultTy,
1043+
/*isStatic=*/isClassMethod,
10381044
/*isDefinition=*/true);
10391045
}
10401046

@@ -1652,9 +1658,6 @@ class DeclAndTypePrinter::Implementation
16521658

16531659
void visitFuncDecl(FuncDecl *FD) {
16541660
if (outputLang == OutputLanguageMode::Cxx) {
1655-
// FIXME: Support static methods.
1656-
if (FD->getDeclContext()->isTypeContext() && FD->isStatic())
1657-
return;
16581661
if (FD->getDeclContext()->isTypeContext())
16591662
return printAbstractFunctionAsMethod(FD, FD->isStatic());
16601663

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,14 @@ class CFunctionSignatureTypePrinter
472472
return visitPart(ds->getSelfType(), optionalKind, isInOutParam);
473473
}
474474

475+
ClangRepresentation visitMetatypeType(MetatypeType *mt,
476+
Optional<OptionalTypeKind> optionalKind,
477+
bool isInOutParam) {
478+
if (typeUseKind == FunctionSignatureTypeUse::TypeReference)
479+
return visitPart(mt->getInstanceType(), optionalKind, isInOutParam);
480+
return ClangRepresentation::unsupported;
481+
}
482+
475483
ClangRepresentation visitPart(Type Ty,
476484
Optional<OptionalTypeKind> optionalKind,
477485
bool isInOutParam) {
@@ -1056,7 +1064,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
10561064
const AbstractFunctionDecl *FD, const LoweredFunctionSignature &signature,
10571065
StringRef swiftSymbolName, const NominalTypeDecl *typeDeclContext,
10581066
const ModuleDecl *moduleContext, Type resultTy, const ParameterList *params,
1059-
bool hasThrows, const AnyFunctionType *funcType) {
1067+
bool hasThrows, const AnyFunctionType *funcType, bool isStaticMethod) {
10601068
if (typeDeclContext)
10611069
ClangSyntaxPrinter(os).printNominalTypeOutsideMemberDeclInnerStaticAssert(
10621070
typeDeclContext);
@@ -1085,15 +1093,15 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
10851093
emitNewParam();
10861094
std::string paramName;
10871095
if (param.isSelfParameter()) {
1088-
bool needsStaticSelf = isa<ConstructorDecl>(FD);
1096+
bool needsStaticSelf = isa<ConstructorDecl>(FD) || isStaticMethod;
10891097
if (needsStaticSelf) {
10901098
os << "swift::TypeMetadataTrait<";
10911099
CFunctionSignatureTypePrinter typePrinter(
10921100
os, cPrologueOS, typeMapping, OutputLanguageMode::Cxx,
10931101
interopContext, CFunctionSignatureTypePrinterModifierDelegate(),
10941102
moduleContext, declPrinter,
10951103
FunctionSignatureTypeUse::TypeReference);
1096-
auto result = typePrinter.visit(param.getType(), OTK_None,
1104+
auto result = typePrinter.visit(param.getInterfaceType(), OTK_None,
10971105
/*isInOutParam=*/false);
10981106
assert(!result.isUnsupported());
10991107
os << ">::getTypeMetadata()";
@@ -1285,7 +1293,6 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
12851293
});
12861294
}
12871295
}
1288-
12891296
}
12901297

12911298
static StringRef getConstructorName(const AbstractFunctionDecl *FD) {
@@ -1301,19 +1308,19 @@ static StringRef getConstructorName(const AbstractFunctionDecl *FD) {
13011308
void DeclAndTypeClangFunctionPrinter::printCxxMethod(
13021309
const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD,
13031310
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
1304-
Type resultTy, bool isDefinition) {
1311+
Type resultTy, bool isStatic, bool isDefinition) {
13051312
bool isConstructor = isa<ConstructorDecl>(FD);
13061313
os << " ";
13071314

13081315
FunctionSignatureModifiers modifiers;
13091316
if (isDefinition)
13101317
modifiers.qualifierContext = typeDeclContext;
1311-
modifiers.isStatic = isConstructor && !isDefinition;
1318+
modifiers.isStatic = (isStatic || isConstructor) && !isDefinition;
13121319
modifiers.isInline = true;
13131320
bool isMutating =
13141321
isa<FuncDecl>(FD) ? cast<FuncDecl>(FD)->isMutating() : false;
1315-
modifiers.isConst =
1316-
!isa<ClassDecl>(typeDeclContext) && !isMutating && !isConstructor;
1322+
modifiers.isConst = !isa<ClassDecl>(typeDeclContext) && !isMutating &&
1323+
!isConstructor && !isStatic;
13171324
modifiers.hasSymbolUSR = !isDefinition;
13181325
auto result = printFunctionSignature(
13191326
FD, signature,
@@ -1329,10 +1336,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
13291336

13301337
os << " {\n";
13311338
// FIXME: should it be objTy for resultTy?
1332-
printCxxThunkBody(FD, signature, swiftSymbolName, typeDeclContext,
1333-
FD->getModuleContext(), resultTy, FD->getParameters(),
1334-
FD->hasThrows(),
1335-
FD->getInterfaceType()->castTo<AnyFunctionType>());
1339+
printCxxThunkBody(
1340+
FD, signature, swiftSymbolName, typeDeclContext, FD->getModuleContext(),
1341+
resultTy, FD->getParameters(), FD->hasThrows(),
1342+
FD->getInterfaceType()->castTo<AnyFunctionType>(), isStatic);
13361343
os << " }\n";
13371344
}
13381345

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,15 @@ class DeclAndTypeClangFunctionPrinter {
113113
const NominalTypeDecl *typeDeclContext,
114114
const ModuleDecl *moduleContext, Type resultTy,
115115
const ParameterList *params, bool hasThrows = false,
116-
const AnyFunctionType *funcType = nullptr);
116+
const AnyFunctionType *funcType = nullptr,
117+
bool isStaticMethod = false);
117118

118119
/// Print the Swift method as C++ method declaration/definition, including
119120
/// constructors.
120121
void printCxxMethod(const NominalTypeDecl *typeDeclContext,
121122
const AbstractFunctionDecl *FD,
122123
const LoweredFunctionSignature &signature,
123-
StringRef swiftSymbolName, Type resultTy,
124+
StringRef swiftSymbolName, Type resultTy, bool isStatic,
124125
bool isDefinition);
125126

126127
/// Print the C++ getter/setter method signature.

test/Interop/SwiftToCxx/methods/method-in-cxx-execution.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,14 @@ int main() {
6363
// CHECK-NEXT: PassStructInClassMethod.retStruct 2;
6464
// CHECK-NEXT: -578, 2, -100, 42, 67, -10101
6565
}
66+
67+
{
68+
LargeStruct::staticMethod();
69+
// CHECK-NEXT: LargeStruct.staticMethod;
70+
auto largeStruct = ClassWithMethods::staticFinalClassMethod(9075);
71+
// CHECK-NEXT: ClassWithMethods.staticFinalClassMethod;
72+
largeStruct.dump();
73+
// CHECK-NEXT: 1, -1, -9075, -2, 9075, -456
74+
}
6675
return 0;
6776
}

test/Interop/SwiftToCxx/methods/method-in-cxx.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public struct LargeStruct {
2222
public func added(_ x: LargeStruct) -> LargeStruct {
2323
return LargeStruct(x1: x1 + x.x1, x2: x2 + x.x2, x3: x3 + x.x3, x4: x4 + x.x4, x5: x5 + x.x5, x6: x6 + x.x6)
2424
}
25+
26+
static public func staticMethod() {
27+
print("LargeStruct.staticMethod;")
28+
}
2529
}
2630

2731
public final class ClassWithMethods {
@@ -50,6 +54,11 @@ public final class ClassWithMethods {
5054
public func deepCopy(_ x: Int) -> ClassWithMethods {
5155
return ClassWithMethods(field + x)
5256
}
57+
58+
static public func staticFinalClassMethod(x: Int) -> LargeStruct {
59+
print("ClassWithMethods.staticFinalClassMethod;")
60+
return LargeStruct(x1: 1, x2: -1, x3: -x, x4: -2, x5: x, x6: -456)
61+
}
5362
}
5463

5564
public final class PassStructInClassMethod {
@@ -83,13 +92,15 @@ public final class PassStructInClassMethod {
8392
// CHECK-NEXT: inline ClassWithMethods sameRet() SWIFT_SYMBOL("s:7Methods09ClassWithA0C7sameRetACyF");
8493
// CHECK-NEXT: inline void mutate() SWIFT_SYMBOL("s:7Methods09ClassWithA0C6mutateyyF");
8594
// CHECK-NEXT: inline ClassWithMethods deepCopy(swift::Int x) SWIFT_SYMBOL("s:7Methods09ClassWithA0C8deepCopyyACSiF");
95+
// CHECK-NEXT: static inline LargeStruct staticFinalClassMethod(swift::Int x) SWIFT_SYMBOL("s:7Methods09ClassWithA0C011staticFinalB6Method1xAA11LargeStructVSi_tFZ");
8696

8797
// CHECK: class SWIFT_SYMBOL("s:7Methods11LargeStructV") LargeStruct final {
8898
// CHECK: inline LargeStruct(LargeStruct &&)
8999
// CHECK-NEXT: inline LargeStruct doubled() const SWIFT_SYMBOL("s:7Methods11LargeStructV7doubledACyF");
90100
// CHECK-NEXT: inline void dump() const SWIFT_SYMBOL("s:7Methods11LargeStructV4dumpyyF");
91101
// CHECK-NEXT: inline LargeStruct scaled(swift::Int x, swift::Int y) const SWIFT_SYMBOL("s:7Methods11LargeStructV6scaledyACSi_SitF");
92102
// CHECK-NEXT: inline LargeStruct added(const LargeStruct& x) const SWIFT_SYMBOL("s:7Methods11LargeStructV5addedyA2CF");
103+
// CHECK-NEXT: static inline void staticMethod() SWIFT_SYMBOL("s:7Methods11LargeStructV12staticMethodyyFZ");
93104
// CHECK-NEXT: private
94105

95106
public func createClassWithMethods(_ x: Int) -> ClassWithMethods {
@@ -117,6 +128,11 @@ public func createPassStructInClassMethod() -> PassStructInClassMethod {
117128
// CHECK-NEXT: inline ClassWithMethods ClassWithMethods::deepCopy(swift::Int x) {
118129
// CHECK-NEXT: return _impl::_impl_ClassWithMethods::makeRetained(_impl::$s7Methods09ClassWithA0C8deepCopyyACSiF(x, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)));
119130
// CHECK-NEXT: }
131+
// CHECK-NEXT: inline LargeStruct ClassWithMethods::staticFinalClassMethod(swift::Int x) {
132+
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](char * _Nonnull result) {
133+
// CHECK-NEXT: _impl::$s7Methods09ClassWithA0C011staticFinalB6Method1xAA11LargeStructVSi_tFZ(result, x, swift::TypeMetadataTrait<ClassWithMethods>::getTypeMetadata());
134+
// CHECK-NEXT: });
135+
// CHECK-NEXT: }
120136

121137
// CHECK: inline LargeStruct LargeStruct::doubled() const {
122138
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](char * _Nonnull result) {
@@ -136,6 +152,9 @@ public func createPassStructInClassMethod() -> PassStructInClassMethod {
136152
// CHECK-NEXT: _impl::$s7Methods11LargeStructV5addedyA2CF(result, _impl::_impl_LargeStruct::getOpaquePointer(x), _getOpaquePointer());
137153
// CHECK-NEXT: });
138154
// CHECK-NEXT: }
155+
// CHECK-NEXT: inline void LargeStruct::staticMethod() {
156+
// CHECK-NEXT: return _impl::$s7Methods11LargeStructV12staticMethodyyFZ();
157+
// CHECK-NEXT: }
139158

140159
// CHECK: inline LargeStruct PassStructInClassMethod::retStruct(swift::Int x) {
141160
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](char * _Nonnull result) {

0 commit comments

Comments
 (0)