From bd96959d145180298459809ed6588a33de10de1e Mon Sep 17 00:00:00 2001 From: zoecarver Date: Tue, 8 Dec 2020 09:56:06 -0800 Subject: [PATCH] [cxx-interop] Re-implement namespaces using enums + extensions. C++ namespaces are module-independent, but enums are owned by their module's in Swift. So, to prevent declaring two enums with the same name, this patch implements a new approach to namespaces: enums with extensions. Here's an example: ``` // Module A namespace N { void test1(); } // Module B namespace N { void test2(); } // __ObjC module enum N { } // Swift module A extension N { func test1() } // Swift module B extension N { func test1() } ``` Thanks to @gribozavr for the great idea. --- lib/ClangImporter/ImportDecl.cpp | 110 +++++++++++++++++- test/ClangImporter/cxx_interop_ir.swift | 8 +- .../linked-records-module-interface.swift | 2 +- .../namespace/Inputs/classes-second-header.h | 12 ++ test/Interop/Cxx/namespace/Inputs/classes.h | 43 +++++++ .../Inputs/free-functions-second-header.h | 10 ++ .../Cxx/namespace/Inputs/free-functions.h | 60 ++++++++++ .../Cxx/namespace/Inputs/module.modulemap | 28 +++++ .../Inputs/templates-second-header.h | 18 +++ test/Interop/Cxx/namespace/Inputs/templates.h | 90 ++++++++++++++ .../Interop/Cxx/namespace/classes-irgen.swift | 31 +++++ .../namespace/classes-module-interface.swift | 34 ++++++ ...asses-second-header-module-interface.swift | 9 ++ .../Cxx/namespace/classes-second-header.swift | 18 +++ test/Interop/Cxx/namespace/classes.swift | 37 ++++++ .../Cxx/namespace/free-functions-irgen.swift | 37 ++++++ .../free-functions-module-interface.swift | 28 +++++ ...tions-second-header-module-interface.swift | 7 ++ .../free-functions-second-header.swift | 16 +++ .../Cxx/namespace/free-functions.swift | 48 ++++++++ .../Cxx/namespace/templates-irgen.swift | 35 ++++++ .../templates-module-interface.swift | 42 +++++++ ...lates-second-header-module-interface.swift | 12 ++ .../namespace/templates-second-header.swift | 20 ++++ test/Interop/Cxx/namespace/templates.swift | 45 +++++++ ...mplate-in-namespace-module-interface.swift | 2 +- .../function-template-module-interface.swift | 2 +- ...iation-in-namespace-module-interface.swift | 3 + 28 files changed, 794 insertions(+), 13 deletions(-) create mode 100644 test/Interop/Cxx/namespace/Inputs/classes-second-header.h create mode 100644 test/Interop/Cxx/namespace/Inputs/classes.h create mode 100644 test/Interop/Cxx/namespace/Inputs/free-functions-second-header.h create mode 100644 test/Interop/Cxx/namespace/Inputs/free-functions.h create mode 100644 test/Interop/Cxx/namespace/Inputs/module.modulemap create mode 100644 test/Interop/Cxx/namespace/Inputs/templates-second-header.h create mode 100644 test/Interop/Cxx/namespace/Inputs/templates.h create mode 100644 test/Interop/Cxx/namespace/classes-irgen.swift create mode 100644 test/Interop/Cxx/namespace/classes-module-interface.swift create mode 100644 test/Interop/Cxx/namespace/classes-second-header-module-interface.swift create mode 100644 test/Interop/Cxx/namespace/classes-second-header.swift create mode 100644 test/Interop/Cxx/namespace/classes.swift create mode 100644 test/Interop/Cxx/namespace/free-functions-irgen.swift create mode 100644 test/Interop/Cxx/namespace/free-functions-module-interface.swift create mode 100644 test/Interop/Cxx/namespace/free-functions-second-header-module-interface.swift create mode 100644 test/Interop/Cxx/namespace/free-functions-second-header.swift create mode 100644 test/Interop/Cxx/namespace/free-functions.swift create mode 100644 test/Interop/Cxx/namespace/templates-irgen.swift create mode 100644 test/Interop/Cxx/namespace/templates-module-interface.swift create mode 100644 test/Interop/Cxx/namespace/templates-second-header-module-interface.swift create mode 100644 test/Interop/Cxx/namespace/templates-second-header.swift create mode 100644 test/Interop/Cxx/namespace/templates.swift diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index a1560847e5ebb..967c6f4836ad4 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -2445,19 +2445,116 @@ namespace { auto importedName = importFullName(decl, correctSwiftName); if (!importedName) return nullptr; - auto dc = + auto extensionDC = Impl.importDeclContextOf(decl, importedName.getEffectiveContext()); - if (!dc) + if (!extensionDC) return nullptr; SourceLoc loc = Impl.importSourceLoc(decl->getBeginLoc()); - - // FIXME: If Swift gets namespaces, import as a namespace. - auto enumDecl = Impl.createDeclWithClangNode( + DeclContext *dc = nullptr; + // If this is a top-level namespace, don't put it in the module we're + // importing, put it in the "__ObjC" module that is implicitly imported. + // This way, if we have multiple modules that all open the same namespace, + // we won't import multiple enums with the same name in swift. + if (extensionDC->getContextKind() == DeclContextKind::FileUnit) + dc = Impl.ImportedHeaderUnit; + else { + // This is a nested namespace, we need to find its extension decl + // context and then use that to find the parent enum. It's important + // that we add this to the parent enum (in the "__ObjC" module) and not + // to the extension. + auto parentNS = cast(decl->getParent()); + auto parent = Impl.importDecl(parentNS, getVersion()); + // Sometimes when the parent namespace is imported, this namespace + // also gets imported. If that's the case, then the parent namespace + // will be an enum (because it was able to be fully imported) in which + // case we need to bail here. + auto cachedResult = + Impl.ImportedDecls.find({decl->getCanonicalDecl(), getVersion()}); + if (cachedResult != Impl.ImportedDecls.end()) + return cachedResult->second; + dc = cast(parent) + ->getExtendedType() + ->getEnumOrBoundGenericEnum(); + } + auto *enumDecl = Impl.createDeclWithClangNode( decl, AccessLevel::Public, loc, importedName.getDeclName().getBaseIdentifier(), Impl.importSourceLoc(decl->getLocation()), None, nullptr, dc); - enumDecl->setMemberLoader(&Impl, 0); + if (isa(decl->getParent())) + cast(dc)->addMember(enumDecl); + + // We are creating an extension, so put it at the top level. This is done + // after creating the enum, though, because we may need the correctly + // nested decl context above when creating the enum. + while (extensionDC->getParent() && + extensionDC->getContextKind() != DeclContextKind::FileUnit) + extensionDC = extensionDC->getParent(); + + auto *extension = ExtensionDecl::create(Impl.SwiftContext, loc, nullptr, + {}, extensionDC, nullptr, decl); + Impl.SwiftContext.evaluator.cacheOutput(ExtendedTypeRequest{extension}, + enumDecl->getDeclaredType()); + Impl.SwiftContext.evaluator.cacheOutput(ExtendedNominalRequest{extension}, + std::move(enumDecl)); + // Keep track of what members we've already added so we don't add the same + // member twice. Note: we can't use "ImportedDecls" for this because we + // might import a decl that we don't add (for example, if it was a + // parameter to another decl). + SmallPtrSet addedMembers; + for (auto redecl : decl->redecls()) { + // This will be reset as the EnumDecl after we return from + // VisitNamespaceDecl. + Impl.ImportedDecls[{redecl->getCanonicalDecl(), getVersion()}] = + extension; + + // Insert these backwards into "namespaceDecls" so we can pop them off + // the end without loosing order. + SmallVector namespaceDecls; + auto addDeclsReversed = [&](auto decls) { + auto begin = decls.begin(); + auto end = decls.end(); + int currentSize = namespaceDecls.size(); + int declCount = currentSize + std::distance(begin, end); + namespaceDecls.resize(declCount); + for (int index = declCount - 1; index >= currentSize; --index) + namespaceDecls[index] = *(begin++); + }; + addDeclsReversed(redecl->decls()); + while (!namespaceDecls.empty()) { + auto nd = dyn_cast(namespaceDecls.pop_back_val()); + // Make sure we only import the defenition of a record. + if (auto tagDecl = dyn_cast_or_null(nd)) + // Some decls, for example ClassTemplateSpecializationDecls, won't + // have a definition here. That's OK. + nd = tagDecl->getDefinition() ? tagDecl->getDefinition() : tagDecl; + if (!nd) + continue; + + // Special case class templates: import all their specilizations here. + if (auto classTemplate = dyn_cast(nd)) { + addDeclsReversed(classTemplate->specializations()); + continue; + } + + auto member = Impl.importDecl(nd, getVersion()); + if (!member || addedMembers.count(member) || + isa(nd)) + continue; + // This happens (for example) when a struct is declared inside another + // struct inside a namespace but defined out of line. + assert(member->getDeclContext()->getAsDecl()); + if (dyn_cast(member->getDeclContext()->getAsDecl()) != + extension) + continue; + extension->addMember(member); + addedMembers.insert(member); + } + } + + if (!extension->getMembers().empty()) + enumDecl->addExtension(extension); + return enumDecl; } @@ -8583,6 +8680,7 @@ DeclContext *ClangImporter::Implementation::importDeclContextImpl( auto decl = dyn_cast(dc); if (!decl) return nullptr; + // Category decls with same name can be merged and using canonical decl always // leads to the first category of the given name. We'd like to keep these // categories separated. diff --git a/test/ClangImporter/cxx_interop_ir.swift b/test/ClangImporter/cxx_interop_ir.swift index 7383226ce5c9f..3a44a33c209d7 100644 --- a/test/ClangImporter/cxx_interop_ir.swift +++ b/test/ClangImporter/cxx_interop_ir.swift @@ -9,17 +9,17 @@ func indirectUsage() { useT(makeT()) } -// CHECK-LABEL: define hidden swiftcc %swift.type* @"$s6cxx_ir14reflectionInfo3argypXpSo2nsV1TV_tF" -// CHECK: %0 = call swiftcc %swift.metadata_response @"$sSo2nsV1TVMa"({{i64|i32}} 0) +// CHECK-LABEL: define hidden swiftcc %swift.type* @"$s6cxx_ir14reflectionInfo3argypXpSo2nsV10CXXInteropE1TV_tF" +// CHECK: %0 = call swiftcc %swift.metadata_response @"$sSo2nsV10CXXInteropE1TVMa"({{i64|i32}} 0) func reflectionInfo(arg: namespacedT) -> Any.Type { return type(of: arg) } -// CHECK: define hidden swiftcc void @"$s6cxx_ir24namespaceManglesIntoName3argySo2nsV1TV_tF" +// CHECK: define hidden swiftcc void @"$s6cxx_ir24namespaceManglesIntoName3argySo2nsV10CXXInteropE1TV_tF" func namespaceManglesIntoName(arg: namespacedT) { } -// CHECK: define hidden swiftcc void @"$s6cxx_ir42namespaceManglesIntoNameForUsingShadowDecl3argySo2nsV14NamespacedTypeV_tF" +// CHECK: define hidden swiftcc void @"$s6cxx_ir42namespaceManglesIntoNameForUsingShadowDecl3argySo2nsV10CXXInteropE14NamespacedTypeV_tF" func namespaceManglesIntoNameForUsingShadowDecl(arg: NamespacedType) { } diff --git a/test/Interop/Cxx/class/linked-records-module-interface.swift b/test/Interop/Cxx/class/linked-records-module-interface.swift index 9f8fb0f60aeeb..5fc94d3f5589d 100644 --- a/test/Interop/Cxx/class/linked-records-module-interface.swift +++ b/test/Interop/Cxx/class/linked-records-module-interface.swift @@ -1,6 +1,6 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=LinkedRecords -I %S/Inputs/ -source-filename=x -enable-cxx-interop | %FileCheck %s -// CHECK: enum Space { +// CHECK: extension Space { // CHECK: struct C { // CHECK: struct D { // CHECK: var B: Space.A.B diff --git a/test/Interop/Cxx/namespace/Inputs/classes-second-header.h b/test/Interop/Cxx/namespace/Inputs/classes-second-header.h new file mode 100644 index 0000000000000..7994b3fe3623b --- /dev/null +++ b/test/Interop/Cxx/namespace/Inputs/classes-second-header.h @@ -0,0 +1,12 @@ +#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_SECOND_HEADER_H +#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_SECOND_HEADER_H + +#include "classes.h" + +struct ClassesNS1::ClassesNS2::DefinedInDefs { + const char *basicMember() { + return "ClassesNS1::ClassesNS2::DefinedInDefs::basicMember"; + } +}; + +#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_SECOND_HEADER_H diff --git a/test/Interop/Cxx/namespace/Inputs/classes.h b/test/Interop/Cxx/namespace/Inputs/classes.h new file mode 100644 index 0000000000000..0fe119af460df --- /dev/null +++ b/test/Interop/Cxx/namespace/Inputs/classes.h @@ -0,0 +1,43 @@ +#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_H +#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_H + +namespace ClassesNS1 { +struct BasicStruct { + const char *basicMember() { return "ClassesNS1::BasicStruct::basicMember"; } +}; +struct ForwardDeclaredStruct; +} // namespace ClassesNS1 + +struct ClassesNS1::ForwardDeclaredStruct { + const char *basicMember() { + return "ClassesNS1::ForwardDeclaredStruct::basicMember"; + } +}; + +namespace ClassesNS1 { +namespace ClassesNS2 { +struct BasicStruct { + const char *basicMember() { + return "ClassesNS1::ClassesNS2::BasicStruct::basicMember"; + } +}; +struct ForwardDeclaredStruct; +struct DefinedInDefs; +} // namespace ClassesNS2 +} // namespace ClassesNS1 + +namespace ClassesNS1 { +struct ClassesNS2::ForwardDeclaredStruct { + const char *basicMember() { + return "ClassesNS1::ClassesNS2::ForwardDeclaredStruct::basicMember"; + } +}; +} // namespace ClassesNS1 + +namespace ClassesNS3 { +struct BasicStruct { + const char *basicMember() { return "ClassesNS3::BasicStruct::basicMember"; } +}; +} // namespace ClassesNS3 + +#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_H diff --git a/test/Interop/Cxx/namespace/Inputs/free-functions-second-header.h b/test/Interop/Cxx/namespace/Inputs/free-functions-second-header.h new file mode 100644 index 0000000000000..fe5e4fcb4f230 --- /dev/null +++ b/test/Interop/Cxx/namespace/Inputs/free-functions-second-header.h @@ -0,0 +1,10 @@ +#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTIONS_SECOND_HEADER_H +#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTIONS_SECOND_HEADER_H + +#include "free-functions.h" + +inline const char *FunctionsNS1::definedInDefs() { + return "FunctionsNS1::definedInDefs"; +} + +#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTIONS_SECOND_HEADER_H diff --git a/test/Interop/Cxx/namespace/Inputs/free-functions.h b/test/Interop/Cxx/namespace/Inputs/free-functions.h new file mode 100644 index 0000000000000..564d641808186 --- /dev/null +++ b/test/Interop/Cxx/namespace/Inputs/free-functions.h @@ -0,0 +1,60 @@ +#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTION_H +#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTION_H + +namespace FunctionsNS1 { +inline const char *basicFunctionTopLevel() { + return "FunctionsNS1::basicFunctionTopLevel"; +} +inline const char *forwardDeclared(); +inline const char *definedOutOfLine(); +} // namespace FunctionsNS1 + +namespace FunctionsNS1 { +inline const char *forwardDeclared() { return "FunctionsNS1::forwardDeclared"; } +} // namespace FunctionsNS1 + +inline const char *FunctionsNS1::definedOutOfLine() { + return "FunctionsNS1::definedOutOfLine"; +} + +namespace FunctionsNS1 { +namespace FunctionsNS2 { +inline const char *basicFunctionSecondLevel() { + return "FunctionsNS1::FunctionsNS2::basicFunctionSecondLevel"; +} +} // namespace FunctionsNS2 +} // namespace FunctionsNS1 + +namespace FunctionsNS1 { +namespace FunctionsNS2 { +namespace FunctionsNS3 { +inline const char *basicFunctionLowestLevel() { + return "FunctionsNS1::FunctionsNS2::FunctionsNS3::basicFunctionLowestLevel"; +} +} // namespace FunctionsNS3 +} // namespace FunctionsNS2 +} // namespace FunctionsNS1 + +namespace FunctionsNS1 { +inline const char *definedInDefs(); +} + +namespace FunctionsNS1 { +inline const char *sameNameInChild() { return "FunctionsNS1::sameNameInChild"; } +inline const char *sameNameInSibling() { + return "FunctionsNS1::sameNameInSibling"; +} +namespace FunctionsNS2 { +inline const char *sameNameInChild() { + return "FunctionsNS1::FunctionsNS2::sameNameInChild"; +} +} // namespace FunctionsNS2 +} // namespace FunctionsNS1 + +namespace FunctionsNS4 { +inline const char *sameNameInSibling() { + return "FunctionsNS4::sameNameInSibling"; +} +} // namespace FunctionsNS4 + +#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTION_H diff --git a/test/Interop/Cxx/namespace/Inputs/module.modulemap b/test/Interop/Cxx/namespace/Inputs/module.modulemap new file mode 100644 index 0000000000000..3fef2a43d5de6 --- /dev/null +++ b/test/Interop/Cxx/namespace/Inputs/module.modulemap @@ -0,0 +1,28 @@ +module Classes { + header "classes.h" +} + +module ClassesSecondHeader { + // TODO: we shouldn't have to include both of these, and the decls defined in + // these headers should be added to the correct module: SR-14214. + header "classes.h" + header "classes-second-header.h" +} + +module FreeFunctions { + header "free-functions.h" +} + +module FreeFunctionsSecondHeader { + header "free-functions.h" + header "free-functions-second-header.h" +} + +module Templates { + header "templates.h" +} + +module TemplatesSecondHeader { + header "templates.h" + header "templates-second-header.h" +} diff --git a/test/Interop/Cxx/namespace/Inputs/templates-second-header.h b/test/Interop/Cxx/namespace/Inputs/templates-second-header.h new file mode 100644 index 0000000000000..527ecbf3bfea4 --- /dev/null +++ b/test/Interop/Cxx/namespace/Inputs/templates-second-header.h @@ -0,0 +1,18 @@ +#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_SECOND_HEADER_H +#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_SECOND_HEADER_H + +template +const char *TemplatesNS1::basicFunctionTemplateDefinedInDefs(T) { + return "TemplatesNS1::basicFunctionTemplateDefinedInDefs"; +} + +template struct TemplatesNS1::BasicClassTemplateDefinedInDefs { + const char *basicMember() { + return "TemplatesNS1::BasicClassTemplateDefinedInDefs::basicMember"; + } +}; + +using BasicClassTemplateDefinedInDefsChar = + TemplatesNS1::BasicClassTemplateDefinedInDefs; + +#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_SECOND_HEADER_H diff --git a/test/Interop/Cxx/namespace/Inputs/templates.h b/test/Interop/Cxx/namespace/Inputs/templates.h new file mode 100644 index 0000000000000..ec66911cd3325 --- /dev/null +++ b/test/Interop/Cxx/namespace/Inputs/templates.h @@ -0,0 +1,90 @@ +#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_H +#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_H + +namespace TemplatesNS1 { +template const char *basicFunctionTemplate(T) { + return "TemplatesNS1::basicFunctionTemplate"; +} + +template struct BasicClassTemplate { + const char *basicMember() { return "TemplatesNS1::BasicClassTemplate::basicMember"; } +}; + +using BasicClassTemplateChar = BasicClassTemplate; +} // namespace TemplatesNS1 + +namespace TemplatesNS1 { +namespace TemplatesNS2 { +template const char *forwardDeclaredFunctionTemplate(T); +template struct ForwardDeclaredClassTemplate; + +template const char *forwardDeclaredFunctionTemplateOutOfLine(T); +template struct ForwardDeclaredClassTemplateOutOfLine; +} // namespace TemplatesNS2 +} // namespace TemplatesNS1 + +namespace TemplatesNS1 { +template +const char *TemplatesNS2::forwardDeclaredFunctionTemplate(T) { + return "TemplatesNS1::TemplatesNS2::forwardDeclaredFunctionTemplate"; +} + +template struct TemplatesNS2::ForwardDeclaredClassTemplate { + const char *basicMember() { + return "TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplate::basicMember"; + } +}; + +using ForwardDeclaredClassTemplateChar = + TemplatesNS2::ForwardDeclaredClassTemplate; +} // namespace TemplatesNS1 + +template +const char * +TemplatesNS1::TemplatesNS2::forwardDeclaredFunctionTemplateOutOfLine(T) { + return "TemplatesNS1::TemplatesNS2::forwardDeclaredFunctionTemplateOutOfLine"; +} + +template +struct TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplateOutOfLine { + const char *basicMember() { + return "TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplateOutOfLine::" + "basicMember"; + } +}; + +using ForwardDeclaredClassTemplateOutOfLineChar = + TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplateOutOfLine; + +namespace TemplatesNS1 { +namespace TemplatesNS3 { +template struct BasicClassTemplate {}; +} // namespace TemplatesNS3 +} // namespace TemplatesNS1 + +namespace TemplatesNS1 { +namespace TemplatesNS2 { +using BasicClassTemplateChar = TemplatesNS3::BasicClassTemplate; +inline const char *takesClassTemplateFromSibling(BasicClassTemplateChar) { + return "TemplatesNS1::TemplatesNS2::takesClassTemplateFromSibling"; +} +} // namespace TemplatesNS2 +} // namespace TemplatesNS1 + +namespace TemplatesNS4 { +template struct HasSpecialization {}; + +template <> struct HasSpecialization {}; +} // namespace TemplatesNS4 + +namespace TemplatesNS1 { +using UseTemplate = TemplatesNS4::HasSpecialization; +using UseSpecialized = TemplatesNS4::HasSpecialization; +} // namespace TemplatesNS1 + +namespace TemplatesNS1 { +template const char *basicFunctionTemplateDefinedInDefs(T); +template struct BasicClassTemplateDefinedInDefs; +} // namespace TemplatesNS1 + +#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_H diff --git a/test/Interop/Cxx/namespace/classes-irgen.swift b/test/Interop/Cxx/namespace/classes-irgen.swift new file mode 100644 index 0000000000000..a2ffeb1da20c9 --- /dev/null +++ b/test/Interop/Cxx/namespace/classes-irgen.swift @@ -0,0 +1,31 @@ +// RUN: %target-swift-emit-ir -I %S/Inputs -enable-cxx-interop %s | %FileCheck %s + +import Classes + +// CHECK-LABEL: define {{.*}}void @"$s4main10basicTestsyyF"() +// CHECK: call i8* @{{_ZN10ClassesNS111BasicStruct11basicMemberEv|"\?basicMember@BasicStruct@ClassesNS1@@QEAAPEBDXZ"}}(%"struct.ClassesNS1::BasicStruct"* +// CHECK: call i8* @{{_ZN10ClassesNS110ClassesNS211BasicStruct11basicMemberEv|"\?basicMember@BasicStruct@ClassesNS2@ClassesNS1@@QEAAPEBDXZ"}}(%"struct.ClassesNS1::ClassesNS2::BasicStruct"* +// CHECK: call i8* @{{_ZN10ClassesNS311BasicStruct11basicMemberEv|"\?basicMember@BasicStruct@ClassesNS3@@QEAAPEBDXZ"}}(%"struct.ClassesNS3::BasicStruct"* +// CHECK: ret void +public func basicTests() { + var basicStructInst = ClassesNS1.BasicStruct() + basicStructInst.basicMember() + + var nestedBasicStructInst = ClassesNS1.ClassesNS2.BasicStruct() + nestedBasicStructInst.basicMember() + + var siblingBasicStruct = ClassesNS3.BasicStruct() + siblingBasicStruct.basicMember() +} + +// CHECK-LABEL: define {{.*}}void @"$s4main15forwardDeclaredyyF"() +// CHECK: call i8* @{{_ZN10ClassesNS121ForwardDeclaredStruct11basicMemberEv|"\?basicMember@ForwardDeclaredStruct@ClassesNS1@@QEAAPEBDXZ"}}(%"struct.ClassesNS1::ForwardDeclaredStruct"* +// CHECK: call i8* @{{_ZN10ClassesNS110ClassesNS221ForwardDeclaredStruct11basicMemberEv|"\?basicMember@ForwardDeclaredStruct@ClassesNS2@ClassesNS1@@QEAAPEBDXZ"}}(%"struct.ClassesNS1::ClassesNS2::ForwardDeclaredStruct"* +// CHECK: ret void +public func forwardDeclared() { + var forwardDeclaredStruct = ClassesNS1.ForwardDeclaredStruct() + forwardDeclaredStruct.basicMember() + + var nestedForwardDeclaredStruct = ClassesNS1.ClassesNS2.ForwardDeclaredStruct() + nestedForwardDeclaredStruct.basicMember() +} diff --git a/test/Interop/Cxx/namespace/classes-module-interface.swift b/test/Interop/Cxx/namespace/classes-module-interface.swift new file mode 100644 index 0000000000000..ea1db04ab7706 --- /dev/null +++ b/test/Interop/Cxx/namespace/classes-module-interface.swift @@ -0,0 +1,34 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=Classes -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK-NOT: extension +// CHECK: extension ClassesNS1.ClassesNS2 { +// CHECK: struct BasicStruct { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: struct ForwardDeclaredStruct { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: } +// CHECK-NOT: extension + +// CHECK: extension ClassesNS1 { +// CHECK: struct BasicStruct { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: struct ForwardDeclaredStruct { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: } +// CHECK-NOT: extension + +// CHECK: extension ClassesNS3 { +// CHECK: struct BasicStruct { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: } +// CHECK-NOT: extension diff --git a/test/Interop/Cxx/namespace/classes-second-header-module-interface.swift b/test/Interop/Cxx/namespace/classes-second-header-module-interface.swift new file mode 100644 index 0000000000000..8da6d5de056ef --- /dev/null +++ b/test/Interop/Cxx/namespace/classes-second-header-module-interface.swift @@ -0,0 +1,9 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=ClassesSecondHeader -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK: extension ClassesNS1.ClassesNS2 { +// CHECK-NOT: extension +// CHECK: struct DefinedInDefs { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: } diff --git a/test/Interop/Cxx/namespace/classes-second-header.swift b/test/Interop/Cxx/namespace/classes-second-header.swift new file mode 100644 index 0000000000000..f0be989da4c9e --- /dev/null +++ b/test/Interop/Cxx/namespace/classes-second-header.swift @@ -0,0 +1,18 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import ClassesSecondHeader + +var NamespacesTestSuite = TestSuite("Classes second header in namespaces") + +NamespacesTestSuite.test("Declared and defined in different headers") { + var basicStructInst = ClassesNS1.ClassesNS2.DefinedInDefs() + let basicMemberCString = basicStructInst.basicMember() + expectEqual(String(cString: basicMemberCString!), + "ClassesNS1::ClassesNS2::DefinedInDefs::basicMember") +} + +runAllTests() + diff --git a/test/Interop/Cxx/namespace/classes.swift b/test/Interop/Cxx/namespace/classes.swift new file mode 100644 index 0000000000000..ce7838e4905db --- /dev/null +++ b/test/Interop/Cxx/namespace/classes.swift @@ -0,0 +1,37 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import Classes + +var NamespacesTestSuite = TestSuite("Classes in namespaces") + +NamespacesTestSuite.test("Basic classes") { + var basicStructInst = ClassesNS1.BasicStruct() + let basicMemberCString = basicStructInst.basicMember() + expectEqual(String(cString: basicMemberCString!), "ClassesNS1::BasicStruct::basicMember") + + var nestedBasicStructInst = ClassesNS1.ClassesNS2.BasicStruct() + let nestedBasicMemberCString = nestedBasicStructInst.basicMember() + expectEqual(String(cString: nestedBasicMemberCString!), + "ClassesNS1::ClassesNS2::BasicStruct::basicMember") + + var siblingBasicStruct = ClassesNS3.BasicStruct() + let siblingMemberCString = siblingBasicStruct.basicMember() + expectEqual(String(cString: siblingMemberCString!), "ClassesNS3::BasicStruct::basicMember") +} + +NamespacesTestSuite.test("Forward declared classes") { + var forwardDeclaredStruct = ClassesNS1.ForwardDeclaredStruct() + let basicMemberCString = forwardDeclaredStruct.basicMember() + expectEqual(String(cString: basicMemberCString!), "ClassesNS1::ForwardDeclaredStruct::basicMember") + + var nestedForwardDeclaredStruct = ClassesNS1.ClassesNS2.ForwardDeclaredStruct() + let nestedBasicMemberCString = nestedForwardDeclaredStruct.basicMember() + expectEqual(String(cString: nestedBasicMemberCString!), + "ClassesNS1::ClassesNS2::ForwardDeclaredStruct::basicMember") +} + +runAllTests() + diff --git a/test/Interop/Cxx/namespace/free-functions-irgen.swift b/test/Interop/Cxx/namespace/free-functions-irgen.swift new file mode 100644 index 0000000000000..1e2da09ed3265 --- /dev/null +++ b/test/Interop/Cxx/namespace/free-functions-irgen.swift @@ -0,0 +1,37 @@ +// RUN: %target-swift-emit-ir -I %S/Inputs -enable-cxx-interop %s | %FileCheck %s + +import FreeFunctions + +// CHECK-LABEL: define {{.*}}void @"$s4main10basicTestsyyF"() +// CHECK: call i8* @{{_ZN12FunctionsNS121basicFunctionTopLevelEv|"\?basicFunctionTopLevel@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: call i8* @{{_ZN12FunctionsNS112FunctionsNS224basicFunctionSecondLevelEv|"\?basicFunctionSecondLevel@FunctionsNS2@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: call i8* @{{_ZN12FunctionsNS112FunctionsNS212FunctionsNS324basicFunctionLowestLevelEv|"\?basicFunctionLowestLevel@FunctionsNS3@FunctionsNS2@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: ret void +public func basicTests() { + FunctionsNS1.basicFunctionTopLevel() + FunctionsNS1.FunctionsNS2.basicFunctionSecondLevel() + FunctionsNS1.FunctionsNS2.FunctionsNS3.basicFunctionLowestLevel() +} + +// CHECK-LABEL: define {{.*}}void @"$s4main20forwardDeclaredFuncsyyF"() +// CHECK: call i8* @{{_ZN12FunctionsNS115forwardDeclaredEv|"\?forwardDeclared@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: call i8* @{{_ZN12FunctionsNS116definedOutOfLineEv|"\?definedOutOfLine@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: ret void +public func forwardDeclaredFuncs() { + FunctionsNS1.forwardDeclared() + FunctionsNS1.definedOutOfLine() +} + +// CHECK-LABEL: define {{.*}}void @"$s4main9sameNamesyyF"() +// CHECK: call i8* @{{_ZN12FunctionsNS115sameNameInChildEv|"\?sameNameInChild@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: call i8* @{{_ZN12FunctionsNS117sameNameInSiblingEv|"\?sameNameInSibling@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: call i8* @{{_ZN12FunctionsNS112FunctionsNS215sameNameInChildEv|"\?sameNameInChild@FunctionsNS2@FunctionsNS1@@YAPEBDXZ"}}() +// CHECK: call i8* @{{_ZN12FunctionsNS417sameNameInSiblingEv|"\?sameNameInSibling@FunctionsNS4@@YAPEBDXZ"}}() +// CHECK: ret void +public func sameNames() { + FunctionsNS1.sameNameInChild() + FunctionsNS1.sameNameInSibling() + FunctionsNS1.FunctionsNS2.sameNameInChild() + FunctionsNS4.sameNameInSibling() +} + diff --git a/test/Interop/Cxx/namespace/free-functions-module-interface.swift b/test/Interop/Cxx/namespace/free-functions-module-interface.swift new file mode 100644 index 0000000000000..c9ddfa985e37c --- /dev/null +++ b/test/Interop/Cxx/namespace/free-functions-module-interface.swift @@ -0,0 +1,28 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=FreeFunctions -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK-NOT: extension +// CHECK: extension FunctionsNS1.FunctionsNS2.FunctionsNS3 { +// CHECK: static func basicFunctionLowestLevel() -> UnsafePointer! +// CHECK: } +// CHECK-NOT: extension + +// CHECK: extension FunctionsNS1 { +// CHECK: static func sameNameInChild() -> UnsafePointer! +// CHECK: static func sameNameInSibling() -> UnsafePointer! +// CHECK: static func definedInDefs() -> UnsafePointer! +// CHECK: static func forwardDeclared() -> UnsafePointer! +// CHECK: static func basicFunctionTopLevel() -> UnsafePointer! +// CHECK: static func definedOutOfLine() -> UnsafePointer! +// CHECK: } +// CHECK-NOT: extension + +// CHECK: extension FunctionsNS1.FunctionsNS2 { +// CHECK: static func sameNameInChild() -> UnsafePointer! +// CHECK: static func basicFunctionSecondLevel() -> UnsafePointer! +// CHECK: } +// CHECK-NOT: extension + +// CHECK: extension FunctionsNS4 { +// CHECK: static func sameNameInSibling() -> UnsafePointer! +// CHECK: } +// CHECK-NOT: extension diff --git a/test/Interop/Cxx/namespace/free-functions-second-header-module-interface.swift b/test/Interop/Cxx/namespace/free-functions-second-header-module-interface.swift new file mode 100644 index 0000000000000..2d396c914e375 --- /dev/null +++ b/test/Interop/Cxx/namespace/free-functions-second-header-module-interface.swift @@ -0,0 +1,7 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=FreeFunctionsSecondHeader -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// TODO: This file doesn't really test anything because functions need not be defined. +// CHECK: extension FunctionsNS1 { +// CHECK-NOT: extension +// CHECK: static func definedInDefs() -> UnsafePointer! +// CHECK: } diff --git a/test/Interop/Cxx/namespace/free-functions-second-header.swift b/test/Interop/Cxx/namespace/free-functions-second-header.swift new file mode 100644 index 0000000000000..ee62e7df01448 --- /dev/null +++ b/test/Interop/Cxx/namespace/free-functions-second-header.swift @@ -0,0 +1,16 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import FreeFunctionsSecondHeader + +var NamespacesTestSuite = TestSuite("Functions second header in namespaces") + +NamespacesTestSuite.test("Defined and declared in different headers") { + let definedInDefsCString = FunctionsNS1.definedInDefs() + expectEqual(String(cString: definedInDefsCString!), "FunctionsNS1::definedInDefs") +} + +runAllTests() + diff --git a/test/Interop/Cxx/namespace/free-functions.swift b/test/Interop/Cxx/namespace/free-functions.swift new file mode 100644 index 0000000000000..dacd6ba043156 --- /dev/null +++ b/test/Interop/Cxx/namespace/free-functions.swift @@ -0,0 +1,48 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import FreeFunctions + +var NamespacesTestSuite = TestSuite("Functions in namespaces") + +NamespacesTestSuite.test("Basic functions") { + let basicFunctionTopLevelCString = FunctionsNS1.basicFunctionTopLevel() + expectEqual(String(cString: basicFunctionTopLevelCString!), + "FunctionsNS1::basicFunctionTopLevel") + + let basicFunctionSecondLevelCString = FunctionsNS1.FunctionsNS2.basicFunctionSecondLevel() + expectEqual(String(cString: basicFunctionSecondLevelCString!), + "FunctionsNS1::FunctionsNS2::basicFunctionSecondLevel") + + let basicFunctionLowestLevelCString = FunctionsNS1.FunctionsNS2.FunctionsNS3.basicFunctionLowestLevel() + expectEqual(String(cString: basicFunctionLowestLevelCString!), + "FunctionsNS1::FunctionsNS2::FunctionsNS3::basicFunctionLowestLevel") +} + +NamespacesTestSuite.test("Forward declared functions") { + let forwardDeclaredCString = FunctionsNS1.forwardDeclared() + expectEqual(String(cString: forwardDeclaredCString!), "FunctionsNS1::forwardDeclared") + + let definedOutOfLineCString = FunctionsNS1.definedOutOfLine() + expectEqual(String(cString: definedOutOfLineCString!), "FunctionsNS1::definedOutOfLine") +} + +NamespacesTestSuite.test("Functions with the same name") { + let sameNameInChildCString = FunctionsNS1.sameNameInChild() + expectEqual(String(cString: sameNameInChildCString!), "FunctionsNS1::sameNameInChild") + + let sameNameInSiblingCString = FunctionsNS1.sameNameInSibling() + expectEqual(String(cString: sameNameInSiblingCString!), "FunctionsNS1::sameNameInSibling") + + let ns2SameNameInChildCString = FunctionsNS1.FunctionsNS2.sameNameInChild() + expectEqual(String(cString: ns2SameNameInChildCString!), + "FunctionsNS1::FunctionsNS2::sameNameInChild") + + let ns4SameNameInSiblingCString = FunctionsNS4.sameNameInSibling() + expectEqual(String(cString: ns4SameNameInSiblingCString!), "FunctionsNS4::sameNameInSibling") +} + +runAllTests() + diff --git a/test/Interop/Cxx/namespace/templates-irgen.swift b/test/Interop/Cxx/namespace/templates-irgen.swift new file mode 100644 index 0000000000000..9f373ccb0328a --- /dev/null +++ b/test/Interop/Cxx/namespace/templates-irgen.swift @@ -0,0 +1,35 @@ +// RUN: %target-swift-emit-ir -I %S/Inputs -enable-cxx-interop %s | %FileCheck %s + +import Templates + +// CHECK-LABEL: define {{.*}}void @"$s4main10basicTestsyyF"() +// CHECK: call i8* @{{_ZN12TemplatesNS121basicFunctionTemplateIiEEPKcT_|"\?\?\$basicFunctionTemplate@H@TemplatesNS1@@YAPEBDH@Z"}}(i32 0) +// CHECK: call i8* @{{_ZN12TemplatesNS118BasicClassTemplateIcE11basicMemberEv|"\?basicMember@\?\$BasicClassTemplate@D@TemplatesNS1@@QEAAPEBDXZ"}}(%"struct.TemplatesNS1::BasicClassTemplate"* +// CHECK: call i8* @{{_ZN12TemplatesNS112TemplatesNS229takesClassTemplateFromSiblingENS_12TemplatesNS318BasicClassTemplateIcEE|"\?takesClassTemplateFromSibling@TemplatesNS2@TemplatesNS1@@YAPEBDU\?\$BasicClassTemplate@D@TemplatesNS3@2@@Z"}}({{(i8 %[0-9]+)?}}) +// CHECK: ret void +public func basicTests() { + TemplatesNS1.basicFunctionTemplate(Int32(0)) + + var basicClassTemplateInst = TemplatesNS1.BasicClassTemplateChar() + basicClassTemplateInst.basicMember() + + TemplatesNS1.TemplatesNS2.takesClassTemplateFromSibling(TemplatesNS1.TemplatesNS2.BasicClassTemplateChar()) +} + +// CHECK-LABEL: define {{.*}}void @"$s4main22forwardDeclaredClassesyyF"() +// CHECK: call i8* @{{_ZN12TemplatesNS112TemplatesNS231forwardDeclaredFunctionTemplateIiEEPKcT_|"\?\?\$forwardDeclaredFunctionTemplate@H@TemplatesNS2@TemplatesNS1@@YAPEBDH@Z"}}(i32 0) +// CHECK: call i8* @{{_ZN12TemplatesNS112TemplatesNS228ForwardDeclaredClassTemplateIcE11basicMemberEv|"\?basicMember@\?\$ForwardDeclaredClassTemplate@D@TemplatesNS2@TemplatesNS1@@QEAAPEBDXZ"}}(%"struct.TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplate"* +// CHECK: call i8* @{{_ZN12TemplatesNS112TemplatesNS240forwardDeclaredFunctionTemplateOutOfLineIiEEPKcT_|"\?\?\$forwardDeclaredFunctionTemplateOutOfLine@H@TemplatesNS2@TemplatesNS1@@YAPEBDH@Z"}}(i32 0) +// CHECK: call i8* @{{_ZN12TemplatesNS112TemplatesNS237ForwardDeclaredClassTemplateOutOfLineIcE11basicMemberEv|"\?basicMember@\?\$ForwardDeclaredClassTemplateOutOfLine@D@TemplatesNS2@TemplatesNS1@@QEAAPEBDXZ"}}(%"struct.TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplateOutOfLine"* +// CHECK: ret void +public func forwardDeclaredClasses() { + TemplatesNS1.TemplatesNS2.forwardDeclaredFunctionTemplate(Int32(0)) + + var forwardDeclaredClassTemplateInst = TemplatesNS1.ForwardDeclaredClassTemplateChar() + forwardDeclaredClassTemplateInst.basicMember() + + TemplatesNS1.TemplatesNS2.forwardDeclaredFunctionTemplateOutOfLine(Int32(0)) + + var forwardDeclaredClassTemplateOutOfLineInst = ForwardDeclaredClassTemplateOutOfLineChar() + forwardDeclaredClassTemplateOutOfLineInst.basicMember() +} diff --git a/test/Interop/Cxx/namespace/templates-module-interface.swift b/test/Interop/Cxx/namespace/templates-module-interface.swift new file mode 100644 index 0000000000000..1474992840787 --- /dev/null +++ b/test/Interop/Cxx/namespace/templates-module-interface.swift @@ -0,0 +1,42 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=Templates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK-NOT: extension +// CHECK: extension TemplatesNS1 { +// CHECK: static func basicFunctionTemplate(_: T) -> UnsafePointer! +// CHECK: struct __CxxTemplateInstN12TemplatesNS118BasicClassTemplateIcEE { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: typealias BasicClassTemplateChar = TemplatesNS1.__CxxTemplateInstN12TemplatesNS118BasicClassTemplateIcEE +// CHECK: typealias UseTemplate = TemplatesNS4.__CxxTemplateInstN12TemplatesNS417HasSpecializationIcEE +// CHECK: typealias ForwardDeclaredClassTemplateChar = TemplatesNS1.TemplatesNS2.__CxxTemplateInstN12TemplatesNS112TemplatesNS228ForwardDeclaredClassTemplateIcEE +// CHECK: } +// CHECK: typealias ForwardDeclaredClassTemplateOutOfLineChar = TemplatesNS1.TemplatesNS2.__CxxTemplateInstN12TemplatesNS112TemplatesNS237ForwardDeclaredClassTemplateOutOfLineIcEE +// CHECK-NOT: extension + + +// CHECK: extension TemplatesNS1.TemplatesNS2 { +// CHECK: typealias BasicClassTemplateChar = TemplatesNS1.TemplatesNS3.__CxxTemplateInstN12TemplatesNS112TemplatesNS318BasicClassTemplateIcEE +// CHECK: static func takesClassTemplateFromSibling(_: TemplatesNS1.TemplatesNS2.BasicClassTemplateChar) -> UnsafePointer! +// CHECK: static func forwardDeclaredFunctionTemplate(_: T) -> UnsafePointer! +// CHECK: struct __CxxTemplateInstN12TemplatesNS112TemplatesNS228ForwardDeclaredClassTemplateIcEE { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: static func forwardDeclaredFunctionTemplateOutOfLine(_: T) -> UnsafePointer! +// CHECK: struct __CxxTemplateInstN12TemplatesNS112TemplatesNS237ForwardDeclaredClassTemplateOutOfLineIcEE { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: } +// CHECK-NOT: extension + +// CHECK: extension TemplatesNS4 { +// CHECK: struct __CxxTemplateInstN12TemplatesNS417HasSpecializationIcEE { +// CHECK: init() +// CHECK: } +// CHECK: struct __CxxTemplateInstN12TemplatesNS417HasSpecializationIiEE { +// CHECK: init() +// CHECK: } +// CHECK: } +// CHECK-NOT: extension diff --git a/test/Interop/Cxx/namespace/templates-second-header-module-interface.swift b/test/Interop/Cxx/namespace/templates-second-header-module-interface.swift new file mode 100644 index 0000000000000..bc16357ce4f39 --- /dev/null +++ b/test/Interop/Cxx/namespace/templates-second-header-module-interface.swift @@ -0,0 +1,12 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=TemplatesSecondHeader -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK: extension TemplatesNS1 { +// CHECK-NOT: extension +// CHECK: static func basicFunctionTemplateDefinedInDefs(_: T) -> UnsafePointer! +// CHECK: struct __CxxTemplateInstN12TemplatesNS131BasicClassTemplateDefinedInDefsIcEE { +// CHECK: init() +// CHECK: mutating func basicMember() -> UnsafePointer! +// CHECK: } +// CHECK: } + +// CHECK: typealias BasicClassTemplateDefinedInDefsChar = TemplatesNS1.__CxxTemplateInstN12TemplatesNS131BasicClassTemplateDefinedInDefsIcEE diff --git a/test/Interop/Cxx/namespace/templates-second-header.swift b/test/Interop/Cxx/namespace/templates-second-header.swift new file mode 100644 index 0000000000000..165632a87b77a --- /dev/null +++ b/test/Interop/Cxx/namespace/templates-second-header.swift @@ -0,0 +1,20 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import TemplatesSecondHeader + +var NamespacesTestSuite = TestSuite("Templates in namespaces") + +NamespacesTestSuite.test("Defined and declared in different headers") { + let basicFunctionTemplateCString = TemplatesNS1.basicFunctionTemplateDefinedInDefs(0) + expectEqual(String(cString: basicFunctionTemplateCString!), + "TemplatesNS1::basicFunctionTemplateDefinedInDefs") + + var basicClassTemplateInst = BasicClassTemplateDefinedInDefsChar() + let basicClassTemplateCString = basicClassTemplateInst.basicMember() + expectEqual(String(cString: basicClassTemplateCString!), "TemplatesNS1::BasicClassTemplateDefinedInDefs::basicMember") +} + +runAllTests() diff --git a/test/Interop/Cxx/namespace/templates.swift b/test/Interop/Cxx/namespace/templates.swift new file mode 100644 index 0000000000000..526b4df1efab9 --- /dev/null +++ b/test/Interop/Cxx/namespace/templates.swift @@ -0,0 +1,45 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import Templates + +var NamespacesTestSuite = TestSuite("Templates in namespaces") + +NamespacesTestSuite.test("Basic classes") { + let basicFunctionTemplateCString = TemplatesNS1.basicFunctionTemplate(0) + expectEqual(String(cString: basicFunctionTemplateCString!), + "TemplatesNS1::basicFunctionTemplate") + + var basicClassTemplateInst = TemplatesNS1.BasicClassTemplateChar() + let basicClassTemplateCString = basicClassTemplateInst.basicMember() + expectEqual(String(cString: basicClassTemplateCString!), + "TemplatesNS1::BasicClassTemplate::basicMember") + + let takesClassTemplateFromSiblingCString = TemplatesNS1.TemplatesNS2.takesClassTemplateFromSibling( + TemplatesNS1.TemplatesNS2.BasicClassTemplateChar()) + expectEqual(String(cString: takesClassTemplateFromSiblingCString!), "TemplatesNS1::TemplatesNS2::takesClassTemplateFromSibling") +} + +NamespacesTestSuite.test("Forward declared") { + let forwardDeclaredFunctionTemplateCString = TemplatesNS1.TemplatesNS2.forwardDeclaredFunctionTemplate(0) + expectEqual(String(cString: forwardDeclaredFunctionTemplateCString!), + "TemplatesNS1::TemplatesNS2::forwardDeclaredFunctionTemplate") + + var forwardDeclaredClassTemplateInst = TemplatesNS1.ForwardDeclaredClassTemplateChar() + let forwardDeclaredClassTemplateCString = forwardDeclaredClassTemplateInst.basicMember() + expectEqual(String(cString: forwardDeclaredClassTemplateCString!), + "TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplate::basicMember") + + let forwardDeclaredFunctionTemplateOutOfLineCString = TemplatesNS1.TemplatesNS2.forwardDeclaredFunctionTemplateOutOfLine(0) + expectEqual(String(cString: forwardDeclaredFunctionTemplateOutOfLineCString!), + "TemplatesNS1::TemplatesNS2::forwardDeclaredFunctionTemplateOutOfLine") + + var forwardDeclaredClassTemplateOutOfLineInst = ForwardDeclaredClassTemplateOutOfLineChar() + let forwardDeclaredClassTemplateOutOfLineCString = forwardDeclaredClassTemplateOutOfLineInst.basicMember() + expectEqual(String(cString: forwardDeclaredClassTemplateOutOfLineCString!), + "TemplatesNS1::TemplatesNS2::ForwardDeclaredClassTemplateOutOfLine::basicMember") +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift b/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift index afefbdb3c2f41..e63feac5590a1 100644 --- a/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift +++ b/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift @@ -1,6 +1,6 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=ClassTemplateInNamespace -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s -// CHECK: enum Space { +// CHECK: extension Space { // CHECK: struct __CxxTemplateInstN5Space4ShipIJFvbEEEE { // CHECK: init() // CHECK: } diff --git a/test/Interop/Cxx/templates/function-template-module-interface.swift b/test/Interop/Cxx/templates/function-template-module-interface.swift index 1bd5411206e30..46267b100ac46 100644 --- a/test/Interop/Cxx/templates/function-template-module-interface.swift +++ b/test/Interop/Cxx/templates/function-template-module-interface.swift @@ -18,7 +18,7 @@ // CHECK: func constLvalueReference(_: UnsafePointer) // CHECK: func forwardingReference(_: UnsafeMutablePointer) -// CHECK: enum Orbiters { +// CHECK: extension Orbiters { // CHECK: static func galileo(_: T) // CHECK: static func cassini(_: T, _: U) // CHECK: static func magellan(_: UnsafeMutablePointer) diff --git a/test/Interop/Cxx/templates/swift-class-instantiation-in-namespace-module-interface.swift b/test/Interop/Cxx/templates/swift-class-instantiation-in-namespace-module-interface.swift index dbd2a8236de06..0f9ebe75c3443 100644 --- a/test/Interop/Cxx/templates/swift-class-instantiation-in-namespace-module-interface.swift +++ b/test/Interop/Cxx/templates/swift-class-instantiation-in-namespace-module-interface.swift @@ -2,6 +2,9 @@ // RUN: %target-swiftxx-frontend -emit-module -o %t/SwiftClassTemplateInNamespaceModule.swiftmodule %S/Inputs/SwiftClassTemplateInNamespaceModule.swift -I %S/Inputs -enable-library-evolution -swift-version 5 // RUN: %target-swift-ide-test -print-module -module-to-print=SwiftClassTemplateInNamespaceModule -I %t/ -source-filename=x -enable-cxx-interop | %FileCheck %s +// The following bug needs to be resolved so decls in __ObjC don't dissapear. +// REQUIRES: SR-14211 + // CHECK: import ClassTemplateInNamespaceForSwiftModule // CHECK: func receiveShip(_ i: inout Space.__CxxTemplateInstN5Space4ShipIbEE) // CHECK: func receiveShipWithEngine(_ i: inout Space.__CxxTemplateInstN5Space4ShipIN6Engine8TurbojetEEE)