diff --git a/test/Interop/C/modules/print-qualified-clang-types/Inputs/HelperModule.swift b/test/Interop/C/modules/print-qualified-clang-types/Inputs/HelperModule.swift new file mode 100644 index 0000000000000..38cd0e7b41e91 --- /dev/null +++ b/test/Interop/C/modules/print-qualified-clang-types/Inputs/HelperModule.swift @@ -0,0 +1,2 @@ +import ForeignA +@_exported import ForeignB diff --git a/test/Interop/C/modules/print-qualified-clang-types/Inputs/MainModule.swift b/test/Interop/C/modules/print-qualified-clang-types/Inputs/MainModule.swift new file mode 100644 index 0000000000000..6f7a6a5629788 --- /dev/null +++ b/test/Interop/C/modules/print-qualified-clang-types/Inputs/MainModule.swift @@ -0,0 +1,3 @@ +import HelperModule + +public func funcTakingForeignStruct(_ param: ForeignStruct) {} diff --git a/test/Interop/C/modules/print-qualified-clang-types/Inputs/foreign-a.h b/test/Interop/C/modules/print-qualified-clang-types/Inputs/foreign-a.h new file mode 100644 index 0000000000000..ca297206959cc --- /dev/null +++ b/test/Interop/C/modules/print-qualified-clang-types/Inputs/foreign-a.h @@ -0,0 +1 @@ +#include "textual-header.h" diff --git a/test/Interop/C/modules/print-qualified-clang-types/Inputs/foreign-b.h b/test/Interop/C/modules/print-qualified-clang-types/Inputs/foreign-b.h new file mode 100644 index 0000000000000..ca297206959cc --- /dev/null +++ b/test/Interop/C/modules/print-qualified-clang-types/Inputs/foreign-b.h @@ -0,0 +1 @@ +#include "textual-header.h" diff --git a/test/Interop/C/modules/print-qualified-clang-types/Inputs/module.modulemap b/test/Interop/C/modules/print-qualified-clang-types/Inputs/module.modulemap new file mode 100644 index 0000000000000..bc5f5f4f50bab --- /dev/null +++ b/test/Interop/C/modules/print-qualified-clang-types/Inputs/module.modulemap @@ -0,0 +1,13 @@ +module ForeignA { + // Nest the header in a sub-module to make sure these are handled correctly. + module Sub { + header "foreign-a.h" + } +} + +module ForeignB { + // Nest the header in a sub-module to make sure these are handled correctly. + module Sub { + header "foreign-b.h" + } +} diff --git a/test/Interop/C/modules/print-qualified-clang-types/Inputs/textual-header.h b/test/Interop/C/modules/print-qualified-clang-types/Inputs/textual-header.h new file mode 100644 index 0000000000000..a53012248d706 --- /dev/null +++ b/test/Interop/C/modules/print-qualified-clang-types/Inputs/textual-header.h @@ -0,0 +1 @@ +typedef struct {} ForeignStruct; diff --git a/test/Interop/C/modules/print-qualified-clang-types/print-qualified-clang-types.swift b/test/Interop/C/modules/print-qualified-clang-types/print-qualified-clang-types.swift new file mode 100644 index 0000000000000..13a78745481e8 --- /dev/null +++ b/test/Interop/C/modules/print-qualified-clang-types/print-qualified-clang-types.swift @@ -0,0 +1,36 @@ +// Check that when qualifying Clang types with a module name, we choose a +// visible module. Clang types need special treatment because multiple Clang +// modules can contain the same type declarations from a textually included +// header, but not all of these modules may be visible. If we choose a module +// that isn't visible, we produce `.swiftinterface` files that don't compile. +// +// To test this, the test sets up the following structure: +// +// MainModule (Swift module) +// import HelperModule (Swift module) +// import ForeignA (Clang module) +// #include "textual-header.h" +// @_exported import ForeignB (Clang module) +// #include "textual-header.h" +// +// `ForeignA` and `ForeignB` both include the same textual header, which +// defines the struct `ForeignStruct`. +// +// Because `ForeignB` is re-exported by `HelperModule`, it is visible from +// `MainModule`, but `ForeignA` is not. This means that when `ForeignStruct` is +// used in `MainModule`, its qualified name should be printed as +// `ForeignB.ForeignStruct`, not `ForeignA.ForeignStruct`. +// +// In addition to checking for the presence of the expected string in the +// `.swiftinterface` file, we also verify that it compiles without error. +// +// This is a regression test for https://bugs.swift.org/browse/SR-13032. + +// RUN: %empty-directory(%t) +// RUN: mkdir %t/helper_module %t/main_module +// RUN: %target-swift-frontend -enable-library-evolution -swift-version 5 -emit-module -o %t/helper_module/HelperModule.swiftmodule %S/Inputs/HelperModule.swift -I %S/Inputs +// RUN: %target-swift-frontend -enable-library-evolution -swift-version 5 -emit-module -o %t/main_module/MainModule.swiftmodule -emit-module-interface-path %t/main_module/MainModule.swiftinterface -I %t/helper_module %S/Inputs/MainModule.swift -I %S/Inputs +// RUN: %FileCheck --input-file=%t/main_module/MainModule.swiftinterface %s +// RUN: %target-swift-frontend -typecheck -swift-version 5 %t/main_module/MainModule.swiftinterface -I %t/helper_module -I %S/Inputs + +// CHECK: public func funcTakingForeignStruct(_ param: ForeignB.ForeignStruct)