diff --git a/.cirrus.yml b/.cirrus.yml index 4a43645e..d6985ef3 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,11 +1,11 @@ libcxxrt_freebsd_task: matrix: - freebsd_instance: - image_family: freebsd-13-3 + image_family: freebsd-13-5 - freebsd_instance: image_family: freebsd-15-0-snap - freebsd_instance: - image_family: freebsd-14-0 + image_family: freebsd-14-2 install_script: pkg install -y cmake ninja git @@ -31,7 +31,7 @@ libcxxrt_freebsd_task: libcxxrt_master_task: freebsd_instance: - image_family: freebsd-14-0 + image_family: freebsd-14-2 install_script: pkg install -y cmake ninja git clone_script: | diff --git a/Test/AssociatedObject.m b/Test/AssociatedObject.m index d22044bb..f0266e2a 100644 --- a/Test/AssociatedObject.m +++ b/Test/AssociatedObject.m @@ -41,9 +41,11 @@ int main(void) object = [Associated new]; holder = [Test new]; + size_t rc = object_getRetainCount_np(object); for (uintptr_t i = 1; i <= 20; ++i) { objc_setAssociatedObject(holder, (void*)i, object, OBJC_ASSOCIATION_RETAIN); + assert(rc + i == object_getRetainCount_np(object)); } int lost = 0; for (uintptr_t i = 1; i <= 20; ++i) @@ -53,6 +55,7 @@ int main(void) fprintf(stderr, "lost object %" PRIuPTR "\n", i); ++lost; } + assert(rc + 20 + i == object_getRetainCount_np(object)); } [holder release]; [object release]; diff --git a/associate.m b/associate.m index 79c9713a..2b987f99 100644 --- a/associate.m +++ b/associate.m @@ -341,6 +341,12 @@ id objc_getAssociatedObject(id object, const void *key) struct reference *r = findReference(list, key); if (NULL != r) { + // Check if the policy is OBJC_ASSOCIATION_{RETAIN, COPY} or OBJC_ASSOCIATION_{RETAIN, COPY}_NONATOMIC (LSB set) + // Apple's objc4 retains and autoreleases the object under these policies + if (r->policy & OBJC_ASSOCIATION_RETAIN_NONATOMIC) + { + objc_retainAutorelease(r->object); + } return r->object; } if (class_isMetaClass(object->isa)) @@ -364,6 +370,10 @@ id objc_getAssociatedObject(id object, const void *key) struct reference *r = findReference(list, key); if (NULL != r) { + if (r->policy & OBJC_ASSOCIATION_RETAIN_NONATOMIC) + { + objc_retainAutorelease(r->object); + } return r->object; } }