diff --git a/include/swift/AST/SwiftNameTranslation.h b/include/swift/AST/SwiftNameTranslation.h index ea1e5de4ac8..3e3c8806431 100644 --- a/include/swift/AST/SwiftNameTranslation.h +++ b/include/swift/AST/SwiftNameTranslation.h @@ -84,7 +84,6 @@ enum RepresentationError { UnrepresentableEnumCaseTuple, UnrepresentableProtocol, UnrepresentableMoveOnly, - UnrepresentableNested, UnrepresentableMacro, UnrepresentableZeroSizedValueType, }; diff --git a/lib/AST/SwiftNameTranslation.cpp b/lib/AST/SwiftNameTranslation.cpp index 351b468be39..934c4db467d 100644 --- a/lib/AST/SwiftNameTranslation.cpp +++ b/lib/AST/SwiftNameTranslation.cpp @@ -249,11 +249,6 @@ swift::cxx_translation::getDeclRepresentation( return {Unsupported, UnrepresentableGeneric}; genericSignature = typeDecl->getGenericSignature(); } - // Nested classes are not yet supported. - if (isa(VD) && !typeDecl->hasClangNode() && - isa_and_nonnull( - typeDecl->getDeclContext()->getAsDecl())) - return {Unsupported, UnrepresentableNested}; if (!isa(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: diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 18573bd2ecc..1731dbab0f8 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -260,9 +260,6 @@ private: auto VD = dyn_cast(member); if (!VD || !shouldInclude(VD)) continue; - // TODO: support nested classes. - if (isa(member)) - continue; if (const auto *TD = dyn_cast(member)) printUsingForNestedType(TD, TD->getModuleContext()); } diff --git a/lib/PrintAsClang/PrintClangClassType.cpp b/lib/PrintAsClang/PrintClangClassType.cpp index 48c74510339..464932e764a 100644 --- a/lib/PrintAsClang/PrintClangClassType.cpp +++ b/lib/PrintAsClang/PrintClangClassType.cpp @@ -116,9 +116,12 @@ void ClangClassTypePrinter::printClassTypeDecl( void ClangClassTypePrinter::printClassTypeReturnScaffold( raw_ostream &os, const ClassDecl *type, const ModuleDecl *moduleContext, llvm::function_ref 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("; diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index 99722251046..4ac7e7a4c29 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -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 << "&"; diff --git a/test/Interop/SwiftToCxx/class/nested-classes-in-cxx-execution.cpp b/test/Interop/SwiftToCxx/class/nested-classes-in-cxx-execution.cpp new file mode 100644 index 00000000000..2917c0a0155 --- /dev/null +++ b/test/Interop/SwiftToCxx/class/nested-classes-in-cxx-execution.cpp @@ -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 + +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(); +} diff --git a/test/Interop/SwiftToCxx/class/nested-classes-in-cxx.swift b/test/Interop/SwiftToCxx/class/nested-classes-in-cxx.swift new file mode 100644 index 00000000000..5eae53d9b1b --- /dev/null +++ b/test/Interop/SwiftToCxx/class/nested-classes-in-cxx.swift @@ -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() +}