mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
It is possible for a module interface (e.g., ModuleA) to be generated with C++ interop disabled, and then rebuilt with C++ interop enabled (e.g., because ModuleB, which imports ModuleA, has C++ interop enabled). This circumstance can lead to various issues when name lookup behaves differently depending on whether C++ interop is enabled, e.g., when a module name is shadowed by a namespace of the same name---this only happens in C++ because namespaces do not exist in C. Unfortunately, naming namespaces the same as a module is a common C++ convention, leading to many textual interfaces whose fully-qualified identifiers (e.g., c_module.c_member) cannot be correctly resolved when C++ interop is enabled (because c_module is shadowed by a namespace of the same name). This patch does two things. First, it introduces a new frontend flag, -formal-cxx-interoperability-mode, which records the C++ interop mode a module interface was originally compiled with. Doing so allows subsequent consumers of that interface to interpret it according to the formal C++ interop mode. Note that the actual "versioning" used by this flag is very crude: "off" means disabled, and "swift-6" means enabled. This is done to be compatible with C++ interop compat versioning scheme, which seems to produce some invalid (but unused) version numbers. The versioning scheme for both the formal and actual C++ interop modes should be clarified and fixed in a subsequent patch. The second thing this patch does is fix the module/namespace collision issue in module interface files. It uses the formal C++ interop mode to determine whether it should resolve C++-only decls during name lookup. For now, the fix is very minimal and conservative: it only filters out C++ namespaces during unqualified name lookup in an interface that was originally generated without C++ interop. Doing so should fix the issue while minimizing the chance for collateral breakge. More cases other than C++ namespaces should be added in subsequent patches, with sufficient testing and careful consideration. rdar://144566922
22 lines
1.4 KiB
Swift
22 lines
1.4 KiB
Swift
// RUN: %empty-directory(%t)
|
|
|
|
// Check if fragile Swift interface with struct extensions can be reparsed:
|
|
// RUN: %target-swift-frontend -swift-version 5 -typecheck -emit-module-interface-path %t/UsesCxxStruct.swiftinterface %s -I %S/Inputs -swift-version 5 -cxx-interoperability-mode=default %S/Inputs/namespace-extension-lib.swift
|
|
// RUN: %target-swift-frontend -swift-version 5 -typecheck-module-from-interface %t/UsesCxxStruct.swiftinterface -I %S/Inputs -cxx-interoperability-mode=default
|
|
// RUN: %FileCheck --input-file=%t/UsesCxxStruct.swiftinterface %s
|
|
|
|
// The textual module interface should not contain the C++ interop flag, but it
|
|
// should record the C++ interop version it was built with (the formal version):
|
|
// CHECK-NOT: -enable-experimental-cxx-interop
|
|
// CHECK-NOT: -cxx-interoperability-mode
|
|
// CHECK: -formal-cxx-interoperability-mode=
|
|
|
|
// Check if resilient Swift interface with builtin type extensions can be reparsed:
|
|
// RUN: %target-swift-emit-module-interface(%t/ResilientStruct.swiftinterface) %s -I %S/Inputs -enable-library-evolution -swift-version 5 -cxx-interoperability-mode=default %S/Inputs/namespace-extension-lib.swift -DRESILIENT
|
|
// RUN: %target-swift-typecheck-module-from-interface(%t/ResilientStruct.swiftinterface) -I %S/Inputs -DRESILIENT -cxx-interoperability-mode=default
|
|
// RUN: %FileCheck --input-file=%t/ResilientStruct.swiftinterface %s
|
|
|
|
import Namespaces
|
|
|
|
var x: Namespace.Parent? = nil
|