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,
|
||||
UnrepresentableProtocol,
|
||||
UnrepresentableMoveOnly,
|
||||
UnrepresentableNested,
|
||||
UnrepresentableMacro,
|
||||
UnrepresentableZeroSizedValueType,
|
||||
};
|
||||
|
||||
@@ -249,11 +249,6 @@ swift::cxx_translation::getDeclRepresentation(
|
||||
return {Unsupported, UnrepresentableGeneric};
|
||||
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))
|
||||
return {Unsupported, UnrepresentableZeroSizedValueType};
|
||||
}
|
||||
@@ -392,8 +387,6 @@ swift::cxx_translation::diagnoseRepresenationError(RepresentationError error,
|
||||
return Diagnostic(diag::expose_protocol_to_cxx_unsupported, vd);
|
||||
case UnrepresentableMoveOnly:
|
||||
return Diagnostic(diag::expose_move_only_to_cxx, vd);
|
||||
case UnrepresentableNested:
|
||||
return Diagnostic(diag::expose_nested_type_to_cxx, vd);
|
||||
case UnrepresentableMacro:
|
||||
return Diagnostic(diag::expose_macro_to_cxx, vd);
|
||||
case UnrepresentableZeroSizedValueType:
|
||||
|
||||
@@ -260,9 +260,6 @@ private:
|
||||
auto VD = dyn_cast<ValueDecl>(member);
|
||||
if (!VD || !shouldInclude(VD))
|
||||
continue;
|
||||
// TODO: support nested classes.
|
||||
if (isa<ClassDecl>(member))
|
||||
continue;
|
||||
if (const auto *TD = dyn_cast<NominalTypeDecl>(member))
|
||||
printUsingForNestedType(TD, TD->getModuleContext());
|
||||
}
|
||||
|
||||
@@ -116,9 +116,12 @@ void ClangClassTypePrinter::printClassTypeDecl(
|
||||
void ClangClassTypePrinter::printClassTypeReturnScaffold(
|
||||
raw_ostream &os, const ClassDecl *type, const ModuleDecl *moduleContext,
|
||||
llvm::function_ref<void(void)> bodyPrinter) {
|
||||
ClangSyntaxPrinter printer(type->getASTContext(), os);
|
||||
os << " return ";
|
||||
ClangSyntaxPrinter(type->getASTContext(), os).printModuleNamespaceQualifiersIfNeeded(
|
||||
type->getModuleContext(), moduleContext);
|
||||
printer.printModuleNamespaceQualifiersIfNeeded(type->getModuleContext(),
|
||||
moduleContext);
|
||||
if (!printer.printNestedTypeNamespaceQualifiers(type))
|
||||
os << "::";
|
||||
os << cxx_synthesis::getCxxImplNamespaceName() << "::";
|
||||
ClangValueTypePrinter::printCxxImplClassName(os, type);
|
||||
os << "::makeRetained(";
|
||||
|
||||
@@ -348,7 +348,8 @@ public:
|
||||
if (typeUseKind == FunctionSignatureTypeUse::ParamType && !isInOutParam)
|
||||
os << "const ";
|
||||
printOptional(optionalKind, [&]() {
|
||||
ClangSyntaxPrinter(CT->getASTContext(), os).printBaseName(CT->getDecl());
|
||||
ClangSyntaxPrinter(CT->getASTContext(), os)
|
||||
.printPrimaryCxxTypeName(cd, moduleContext);
|
||||
});
|
||||
if (typeUseKind == FunctionSignatureTypeUse::ParamType)
|
||||
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