mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[cxx-interop] Support nested classes in reverse interop
Turns out we already had most of the building blocks given we already support nested structs. rdar://143343490
This commit is contained in:
@@ -84,7 +84,6 @@ enum RepresentationError {
|
|||||||
UnrepresentableEnumCaseTuple,
|
UnrepresentableEnumCaseTuple,
|
||||||
UnrepresentableProtocol,
|
UnrepresentableProtocol,
|
||||||
UnrepresentableMoveOnly,
|
UnrepresentableMoveOnly,
|
||||||
UnrepresentableNested,
|
|
||||||
UnrepresentableMacro,
|
UnrepresentableMacro,
|
||||||
UnrepresentableZeroSizedValueType,
|
UnrepresentableZeroSizedValueType,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -249,11 +249,6 @@ swift::cxx_translation::getDeclRepresentation(
|
|||||||
return {Unsupported, UnrepresentableGeneric};
|
return {Unsupported, UnrepresentableGeneric};
|
||||||
genericSignature = typeDecl->getGenericSignature();
|
genericSignature = typeDecl->getGenericSignature();
|
||||||
}
|
}
|
||||||
// Nested classes are not yet supported.
|
|
||||||
if (isa<ClassDecl>(VD) && !typeDecl->hasClangNode() &&
|
|
||||||
isa_and_nonnull<NominalTypeDecl>(
|
|
||||||
typeDecl->getDeclContext()->getAsDecl()))
|
|
||||||
return {Unsupported, UnrepresentableNested};
|
|
||||||
if (!isa<ClassDecl>(typeDecl) && isZeroSized && (*isZeroSized)(typeDecl))
|
if (!isa<ClassDecl>(typeDecl) && isZeroSized && (*isZeroSized)(typeDecl))
|
||||||
return {Unsupported, UnrepresentableZeroSizedValueType};
|
return {Unsupported, UnrepresentableZeroSizedValueType};
|
||||||
}
|
}
|
||||||
@@ -392,8 +387,6 @@ swift::cxx_translation::diagnoseRepresenationError(RepresentationError error,
|
|||||||
return Diagnostic(diag::expose_protocol_to_cxx_unsupported, vd);
|
return Diagnostic(diag::expose_protocol_to_cxx_unsupported, vd);
|
||||||
case UnrepresentableMoveOnly:
|
case UnrepresentableMoveOnly:
|
||||||
return Diagnostic(diag::expose_move_only_to_cxx, vd);
|
return Diagnostic(diag::expose_move_only_to_cxx, vd);
|
||||||
case UnrepresentableNested:
|
|
||||||
return Diagnostic(diag::expose_nested_type_to_cxx, vd);
|
|
||||||
case UnrepresentableMacro:
|
case UnrepresentableMacro:
|
||||||
return Diagnostic(diag::expose_macro_to_cxx, vd);
|
return Diagnostic(diag::expose_macro_to_cxx, vd);
|
||||||
case UnrepresentableZeroSizedValueType:
|
case UnrepresentableZeroSizedValueType:
|
||||||
|
|||||||
@@ -260,9 +260,6 @@ private:
|
|||||||
auto VD = dyn_cast<ValueDecl>(member);
|
auto VD = dyn_cast<ValueDecl>(member);
|
||||||
if (!VD || !shouldInclude(VD))
|
if (!VD || !shouldInclude(VD))
|
||||||
continue;
|
continue;
|
||||||
// TODO: support nested classes.
|
|
||||||
if (isa<ClassDecl>(member))
|
|
||||||
continue;
|
|
||||||
if (const auto *TD = dyn_cast<NominalTypeDecl>(member))
|
if (const auto *TD = dyn_cast<NominalTypeDecl>(member))
|
||||||
printUsingForNestedType(TD, TD->getModuleContext());
|
printUsingForNestedType(TD, TD->getModuleContext());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,9 +116,12 @@ void ClangClassTypePrinter::printClassTypeDecl(
|
|||||||
void ClangClassTypePrinter::printClassTypeReturnScaffold(
|
void ClangClassTypePrinter::printClassTypeReturnScaffold(
|
||||||
raw_ostream &os, const ClassDecl *type, const ModuleDecl *moduleContext,
|
raw_ostream &os, const ClassDecl *type, const ModuleDecl *moduleContext,
|
||||||
llvm::function_ref<void(void)> bodyPrinter) {
|
llvm::function_ref<void(void)> bodyPrinter) {
|
||||||
|
ClangSyntaxPrinter printer(type->getASTContext(), os);
|
||||||
os << " return ";
|
os << " return ";
|
||||||
ClangSyntaxPrinter(type->getASTContext(), os).printModuleNamespaceQualifiersIfNeeded(
|
printer.printModuleNamespaceQualifiersIfNeeded(type->getModuleContext(),
|
||||||
type->getModuleContext(), moduleContext);
|
moduleContext);
|
||||||
|
if (!printer.printNestedTypeNamespaceQualifiers(type))
|
||||||
|
os << "::";
|
||||||
os << cxx_synthesis::getCxxImplNamespaceName() << "::";
|
os << cxx_synthesis::getCxxImplNamespaceName() << "::";
|
||||||
ClangValueTypePrinter::printCxxImplClassName(os, type);
|
ClangValueTypePrinter::printCxxImplClassName(os, type);
|
||||||
os << "::makeRetained(";
|
os << "::makeRetained(";
|
||||||
|
|||||||
@@ -348,7 +348,8 @@ public:
|
|||||||
if (typeUseKind == FunctionSignatureTypeUse::ParamType && !isInOutParam)
|
if (typeUseKind == FunctionSignatureTypeUse::ParamType && !isInOutParam)
|
||||||
os << "const ";
|
os << "const ";
|
||||||
printOptional(optionalKind, [&]() {
|
printOptional(optionalKind, [&]() {
|
||||||
ClangSyntaxPrinter(CT->getASTContext(), os).printBaseName(CT->getDecl());
|
ClangSyntaxPrinter(CT->getASTContext(), os)
|
||||||
|
.printPrimaryCxxTypeName(cd, moduleContext);
|
||||||
});
|
});
|
||||||
if (typeUseKind == FunctionSignatureTypeUse::ParamType)
|
if (typeUseKind == FunctionSignatureTypeUse::ParamType)
|
||||||
os << "&";
|
os << "&";
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// RUN: %empty-directory(%t)
|
||||||
|
|
||||||
|
// RUN: %target-swift-frontend %S/nested-classes-in-cxx.swift -enable-library-evolution -typecheck -module-name Classes -clang-header-expose-decls=all-public -emit-clang-header-path %t/classes.h
|
||||||
|
|
||||||
|
// RUN: %target-interop-build-clangxx -std=c++17 -c %s -I %t -o %t/swift-classes-execution.o
|
||||||
|
|
||||||
|
// RUN: %target-interop-build-swift %S/nested-classes-in-cxx.swift -enable-library-evolution -o %t/swift-classes-execution -Xlinker %t/swift-classes-execution.o -module-name Classes -Xfrontend -entry-point-function-name -Xfrontend swiftMain
|
||||||
|
|
||||||
|
// RUN: %target-codesign %t/swift-classes-execution
|
||||||
|
// RUN: %target-run %t/swift-classes-execution
|
||||||
|
|
||||||
|
// REQUIRES: executable_test
|
||||||
|
|
||||||
|
#include "classes.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
using namespace Classes;
|
||||||
|
auto x = makeRecordConfig();
|
||||||
|
RecordConfig::File::Gate y = x.getGate();
|
||||||
|
assert(y.getProp() == 80);
|
||||||
|
assert(y.computeValue() == 160);
|
||||||
|
RecordConfig::AudioFormat z = x.getFile().getFormat();
|
||||||
|
assert(z == RecordConfig::AudioFormat::ALAC);
|
||||||
|
RecordConfig::File::Gate g = RecordConfig::File::Gate::init();
|
||||||
|
}
|
||||||
35
test/Interop/SwiftToCxx/class/nested-classes-in-cxx.swift
Normal file
35
test/Interop/SwiftToCxx/class/nested-classes-in-cxx.swift
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: %target-swift-frontend %s -enable-library-evolution -typecheck -module-name Classes -clang-header-expose-decls=all-public -emit-clang-header-path %t/classes.h
|
||||||
|
|
||||||
|
// RUN: %check-interop-cxx-header-in-clang(%t/classes.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -std=c++17)
|
||||||
|
|
||||||
|
public class RecordConfig {
|
||||||
|
public enum AudioFormat {
|
||||||
|
case PCM, ALAC, AAC
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Directory {
|
||||||
|
public var path: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
public class File {
|
||||||
|
public var format: AudioFormat = .ALAC
|
||||||
|
|
||||||
|
public class Gate {
|
||||||
|
public init() {}
|
||||||
|
public var prop: Int32 = 80
|
||||||
|
|
||||||
|
public func computeValue() -> Int32 {
|
||||||
|
return prop * 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var directory = Directory()
|
||||||
|
public var file = File()
|
||||||
|
public var gate = File.Gate()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeRecordConfig() -> RecordConfig {
|
||||||
|
return RecordConfig()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user