Files
swift-mirror/stdlib/public/runtime/FoundationSupport.cpp
Karoy Lorentey f44cbe4697 [Foundation] Update & simplify class name stability check
Move the ObjC class name stability check logic to the Swift runtime, exposing it as a new SPI called _swift_isObjCTypeNameSerializable.

Update the reporting logic. The ObjC names of generic classes are considered stable now, but private classes and classes defined in function bodies or other anonymous contexts are unstable by design.

On the overlay side, rewrite the check’s implementation in Swift and considerably simplify it.

rdar://57809977
2020-07-02 19:32:22 -07:00

62 lines
2.0 KiB
C++

//===--- FoundationSupport.cpp - Support functions for Foundation ---------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Helper functions for the Foundation framework.
//
//===----------------------------------------------------------------------===//
#include "swift/Runtime/FoundationSupport.h"
#if SWIFT_OBJC_INTEROP
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/HeapObject.h"
using namespace swift;
/// Returns a boolean indicating whether the Objective-C name of a class type is
/// stable across executions, i.e., if the class name is safe to serialize. (The
/// names of private and local types are unstable.)
bool
swift::_swift_isObjCTypeNameSerializable(Class theClass) {
auto type = (AnyClassMetadata *)theClass;
switch (type->getKind()) {
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
return true;
case MetadataKind::Class: {
// Pure ObjC classes always have stable names.
if (type->isPureObjC())
return true;
auto cls = static_cast<const ClassMetadata *>(type);
// Peek through artificial subclasses.
if (cls->isArtificialSubclass()) {
cls = cls->Superclass;
}
// A custom ObjC name is always considered stable.
if (cls->getFlags() & ClassFlags::HasCustomObjCName)
return true;
// Otherwise the name is stable if the class has no anonymous ancestor context.
auto desc = static_cast<const ContextDescriptor *>(cls->getDescription());
while (desc) {
if (desc->getKind() == ContextDescriptorKind::Anonymous) {
return false;
}
desc = desc->Parent.get();
}
return true;
}
default:
return false;
}
}
#endif // SWIFT_OBJC_INTEROP