// RUN: %target-swift-frontend %s -emit-ir // RUN: %target-swift-frontend %s -emit-ir -O // REQUIRES: objc_interop // https://github.com/apple/swift/issues/45306 import Foundation /// This function returns true if inspectedClass is subclass of wantedSuperclass. /// This is achieved by climbing the class tree hierarchy using class_getSuperclass /// runtime function. This is useful when examining classes that do not have /// NSObject as root (e.g. NSProxy subclasses). private func XUClassKindOfClass(_ inspectedClass: AnyClass?, wantedSuperclass: AnyClass?) -> Bool { // We've hit the root, so no, it's not if inspectedClass == nil { return false } // It's the class, yay! if inspectedClass == wantedSuperclass { return true } // Recursively call the function on the superclass of inspectedClass return XUClassKindOfClass(class_getSuperclass(inspectedClass), wantedSuperclass: wantedSuperclass) } /// Works pretty much as +isKindOfClass: on NSObject, but will work fine even with /// NSProxy subclasses, which do not respond to +isKindOfClass: public func XUClassIsSubclassOfClass(_ superclass: AnyClass, subclass: AnyClass) -> Bool { return XUClassKindOfClass(subclass, wantedSuperclass: superclass) } /// Returns a list of subclasses of class T. Doesn't include the root T class. public func XUAllSubclassesOfClass(_ aClass: T.Type) -> [T.Type] { var result: [T.Type] = [] var numClasses: Int32 = 0 // Get the number of classes in the ObjC runtime numClasses = objc_getClassList(nil, 0) if numClasses > 0 { // Get them all let memory = malloc(MemoryLayout.size * Int(numClasses))! defer { free(memory) } let classesPtr = memory.assumingMemoryBound(to: AnyClass.self) let classes = AutoreleasingUnsafeMutablePointer(classesPtr) numClasses = objc_getClassList(classes, numClasses) for i in 0 ..< Int(numClasses) { // Go through the classes, find out if the class is kind of aClass // and then add it to the list let cl = classes[i] if XUClassKindOfClass(cl, wantedSuperclass: aClass) && cl != aClass { result.append(cl as! T.Type) } } } return result }