[6.2] use RespectOriginallyDefinedIn when mangling extension contexts (#82657)

- **Explanation**: USR mangling can include an extension context infix
(`AAE`) when an extended type uses `@_originallyDefinedIn` on platforms
other than the active one. This adds a check for the
`RespectOriginallyDefinedIn` flag when checking extension decls against
their extended type.
- **Scope**: Changes USR mangling in these situations so that USRs are
the same for the same code regardless of platform.
- **Issues**: rdar://152598492
- **Original PRs**: https://github.com/swiftlang/swift/pull/82348
- **Risk**: Low. The change is limited to situations where the name
mangler is already disrespecting the alternate module name, and only
additionally turns on that flag for any USR mangling.
- **Testing**: Automated tests
- **Reviewers**: @edymtt @augusto2112
This commit is contained in:
QuietMisdreavus
2025-07-01 01:30:15 -06:00
committed by GitHub
parent d9bc9a2238
commit a75f94eef4
7 changed files with 50 additions and 7 deletions

View File

@@ -2135,7 +2135,10 @@ public:
/// Determine whether this extension context is in the same defining module as
/// the original nominal type context.
bool isInSameDefiningModule() const;
///
/// \param RespectOriginallyDefinedIn Whether to respect
/// \c @_originallyDefinedIn attributes or the actual location of the decls.
bool isInSameDefiningModule(bool RespectOriginallyDefinedIn = true) const;
/// Determine whether this extension is equivalent to one that requires at
/// at least some constraints to be written in the source.

View File

@@ -946,6 +946,8 @@ std::string ASTMangler::mangleObjCRuntimeName(const NominalTypeDecl *Nominal) {
std::string ASTMangler::mangleTypeAsContextUSR(const NominalTypeDecl *type) {
beginManglingWithoutPrefix();
llvm::SaveAndRestore<bool> respectOriginallyDefinedInRAII(
RespectOriginallyDefinedIn, false);
llvm::SaveAndRestore<bool> allowUnnamedRAII(AllowNamelessEntities, true);
BaseEntitySignature base(type);
appendContext(type, base, type->getAlternateModuleName());
@@ -1014,6 +1016,8 @@ ASTMangler::mangleAnyDecl(const ValueDecl *Decl,
std::string ASTMangler::mangleDeclAsUSR(const ValueDecl *Decl,
StringRef USRPrefix) {
llvm::SaveAndRestore<bool> respectOriginallyDefinedInRAII(
RespectOriginallyDefinedIn, false);
return (llvm::Twine(USRPrefix) + mangleAnyDecl(Decl, false)).str();
}
@@ -1022,6 +1026,8 @@ std::string ASTMangler::mangleAccessorEntityAsUSR(AccessorKind kind,
StringRef USRPrefix,
bool isStatic) {
beginManglingWithoutPrefix();
llvm::SaveAndRestore<bool> respectOriginallyDefinedInRAII(
RespectOriginallyDefinedIn, false);
llvm::SaveAndRestore<bool> allowUnnamedRAII(AllowNamelessEntities, true);
Buffer << USRPrefix;
appendAccessorEntity(getCodeForAccessorKind(kind), decl, isStatic);
@@ -3052,9 +3058,9 @@ void ASTMangler::appendExtension(const ExtensionDecl* ext,
// "extension is to a protocol" would no longer be a reason to use the
// extension mangling, because an extension method implementation could be
// resiliently moved into the original protocol itself.
if (ext->isInSameDefiningModule() // case 1
&& !sigParts.hasRequirements() // case 2
&& !ext->getDeclaredInterfaceType()->isExistentialType()) { // case 3
if (ext->isInSameDefiningModule(RespectOriginallyDefinedIn) // case 1
&& !sigParts.hasRequirements() // case 2
&& !ext->getDeclaredInterfaceType()->isExistentialType()) { // case 3
// skip extension mangling
return appendAnyGenericType(decl);
}

View File

@@ -2165,10 +2165,13 @@ bool ExtensionDecl::isWrittenWithConstraints() const {
return false;
}
bool ExtensionDecl::isInSameDefiningModule() const {
bool ExtensionDecl::isInSameDefiningModule(
bool RespectOriginallyDefinedIn) const {
auto decl = getExtendedNominal();
auto extensionAlterName = getAlternateModuleName();
auto typeAlterName = decl->getAlternateModuleName();
auto extensionAlterName =
RespectOriginallyDefinedIn ? getAlternateModuleName() : "";
auto typeAlterName =
RespectOriginallyDefinedIn ? decl->getAlternateModuleName() : "";
if (!extensionAlterName.empty()) {
if (!typeAlterName.empty()) {

View File

@@ -0,0 +1,22 @@
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/macos)
// RUN: %empty-directory(%t/ios)
// RUN: %target-swift-frontend -target %target-cpu-apple-macos %s -module-name OriginallyDefinedInExtension -emit-module -emit-module-path %t/macos/OriginallyDefinedInExtension.swiftmodule -emit-symbol-graph -emit-symbol-graph-dir %t/macos/
// RUN: %FileCheck %s --input-file %t/macos/OriginallyDefinedInExtension.symbols.json
// RUN: %target-swift-frontend -target %target-cpu-apple-ios-simulator %s -module-name OriginallyDefinedInExtension -emit-module -emit-module-path %t/ios/OriginallyDefinedInExtension.swiftmodule -emit-symbol-graph -emit-symbol-graph-dir %t/ios/
// RUN: %FileCheck %s --input-file %t/ios/OriginallyDefinedInExtension.symbols.json
// CHECK: "precise":"s:28OriginallyDefinedInExtension12SimpleStructV05InnerF0V"
// REQUIRES: SWIFT_SDK=osx
// REQUIRES: SWIFT_SDK=ios_simulator
@available(macOS 10.8, *)
@_originallyDefinedIn(module: "another", macOS 11.0)
public struct SimpleStruct {}
@available(macOS 12.0, iOS 13.0, *)
public extension SimpleStruct {
struct InnerStruct {}
}

View File

@@ -852,6 +852,11 @@ config.available_features.add("SWIFT_VERSION=" + swift_version)
config.available_features.add("STDLIB_VARIANT={}".format(config.variant_suffix[1:]))
if "target-same-as-host" in config.available_features:
# Only add SWIFT_SDKS features if we're building host tools
for sdk in config.swift_sdks:
config.available_features.add("SWIFT_SDK=" + sdk.lower())
if "optimized_stdlib" in config.available_features:
config.available_features.add("optimized_stdlib_" + run_cpu)

View File

@@ -173,6 +173,8 @@ config.freestanding_sdk_name = "@SWIFT_SDK_FREESTANDING_LIB_SUBDIR@"
if '@SWIFT_BUILD_SWIFT_SYNTAX@' == 'TRUE':
config.available_features.add('swift_swift_parser')
config.swift_sdks = "@SWIFT_SDKS@".split(";")
# Let the main config do the real work.
if config.test_exec_root is None:
config.test_exec_root = os.path.dirname(lit.util.abs_path_preserve_drive(__file__))

View File

@@ -137,6 +137,8 @@ config.swift_stdlib_enable_objc_interop = "@SWIFT_STDLIB_ENABLE_OBJC_INTEROP@" =
# Configured in DarwinSDKs.cmake
config.freestanding_sdk_name = "@SWIFT_SDK_FREESTANDING_LIB_SUBDIR@"
config.swift_sdks = "@SWIFT_SDKS@".split(";")
# Let the main config do the real work.
config.test_exec_root = os.path.dirname(os.path.realpath(__file__))
lit_config.load_config(config, os.path.join(config.test_exec_root, "lit.swift-features.cfg"))