diff --git a/src/ir/lower.test.zig b/src/ir/lower.test.zig index 6afaa59..ecad5d1 100644 --- a/src/ir/lower.test.zig +++ b/src/ir/lower.test.zig @@ -680,6 +680,22 @@ test "lower: isObjcClassPointer recognises pointer-to-foreign-Obj-C-class" { try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd); try std.testing.expect(lowering.isObjcClassPointer(ns_ptr)); + // *NSCopying where NSCopying is a registered Obj-C *protocol* → also true + // (the predicate accepts .objc_class OR .objc_protocol). + const proto_name = module.types.internString("NSCopying"); + const proto_struct = module.types.intern(.{ .@"struct" = .{ .name = proto_name, .fields = &.{} } }); + const proto_ptr = module.types.ptrTo(proto_struct); + var proto_fcd = ast.ForeignClassDecl{ + .name = "NSCopying", + .foreign_path = "NSCopying", + .runtime = .objc_protocol, + .members = &.{}, + .is_foreign = true, + .is_main = false, + }; + try lowering.program_index.foreign_class_map.put("NSCopying", &proto_fcd); + try std.testing.expect(lowering.isObjcClassPointer(proto_ptr)); + // *Plain where Plain is a non-foreign struct → false. const plain_name = module.types.internString("Plain"); const plain_struct = module.types.intern(.{ .@"struct" = .{ .name = plain_name, .fields = &.{} } }); @@ -720,6 +736,24 @@ test "lower: objcPropertyKind defaults + explicit ARC modifiers" { const obj_default = ast.ForeignFieldDecl{ .name = "title", .field_type = obj_ty, .is_property = true }; try std.testing.expect(lowering.objcPropertyKind(obj_default) == .strong); + // Protocol-pointer field → also strong by default (same object-pointer + // predicate accepts .objc_protocol). + const proto_name = module.types.internString("NSCoding"); + _ = module.types.intern(.{ .@"struct" = .{ .name = proto_name, .fields = &.{} } }); + var proto_fcd = ast.ForeignClassDecl{ + .name = "NSCoding", + .foreign_path = "NSCoding", + .runtime = .objc_protocol, + .members = &.{}, + .is_foreign = true, + .is_main = false, + }; + try lowering.program_index.foreign_class_map.put("NSCoding", &proto_fcd); + const proto_ty = typeKeyword(alloc, "*NSCoding"); + defer alloc.destroy(proto_ty); + const proto_default = ast.ForeignFieldDecl{ .name = "coder", .field_type = proto_ty, .is_property = true }; + try std.testing.expect(lowering.objcPropertyKind(proto_default) == .strong); + // Explicit modifiers on an object pointer win over the default. const weak_mods = [_][]const u8{"weak"}; try std.testing.expect(lowering.objcPropertyKind(.{ .name = "delegate", .field_type = obj_ty, .is_property = true, .property_modifiers = &weak_mods }) == .weak);