├── APPLE_LICENSE
├── ReleaseNotes.rtf
├── libobjc.order
├── markgc.cpp
├── objc.sln
├── objc.suo
├── objc.vcproj
├── objc.xcodeproj
└── project.pbxproj
├── objcrt
└── objcrt.vcproj
├── prebuild.bat
├── runtime
├── Messengers.subproj
│ ├── objc-msg-arm.s
│ ├── objc-msg-arm64.s
│ ├── objc-msg-i386.s
│ ├── objc-msg-simulator-i386.s
│ ├── objc-msg-simulator-x86_64.s
│ ├── objc-msg-win32.m
│ └── objc-msg-x86_64.s
├── NSObjCRuntime.h
├── NSObject.h
├── NSObject.mm
├── Object.h
├── Object.mm
├── OldClasses.subproj
│ ├── List.h
│ └── List.m
├── Protocol.h
├── Protocol.mm
├── a1a2-blocktramps-arm.s
├── a1a2-blocktramps-arm64.s
├── a1a2-blocktramps-i386.s
├── a1a2-blocktramps-x86_64.s
├── a2a3-blocktramps-arm.s
├── a2a3-blocktramps-i386.s
├── a2a3-blocktramps-x86_64.s
├── hashtable.h
├── hashtable2.h
├── hashtable2.mm
├── llvm-AlignOf.h
├── llvm-DenseMap.h
├── llvm-DenseMapInfo.h
├── llvm-MathExtras.h
├── llvm-type_traits.h
├── maptable.h
├── maptable.mm
├── message.h
├── objc-abi.h
├── objc-accessors.h
├── objc-accessors.mm
├── objc-api.h
├── objc-auto-dump.h
├── objc-auto-dump.mm
├── objc-auto.h
├── objc-auto.mm
├── objc-block-trampolines.mm
├── objc-cache-old.h
├── objc-cache-old.mm
├── objc-cache.h
├── objc-cache.mm
├── objc-class-old.mm
├── objc-class.h
├── objc-class.mm
├── objc-config.h
├── objc-env.h
├── objc-errors.mm
├── objc-exception.h
├── objc-exception.mm
├── objc-externalref.mm
├── objc-file-old.h
├── objc-file-old.mm
├── objc-file.h
├── objc-file.mm
├── objc-gdb.h
├── objc-initialize.h
├── objc-initialize.mm
├── objc-internal.h
├── objc-layout.mm
├── objc-load.h
├── objc-load.mm
├── objc-loadmethod.h
├── objc-loadmethod.mm
├── objc-lockdebug.h
├── objc-lockdebug.mm
├── objc-object.h
├── objc-opt.mm
├── objc-os.h
├── objc-os.mm
├── objc-private.h
├── objc-probes.d
├── objc-references.h
├── objc-references.mm
├── objc-runtime-new.h
├── objc-runtime-new.mm
├── objc-runtime-old.h
├── objc-runtime-old.mm
├── objc-runtime.h
├── objc-runtime.mm
├── objc-sel-old.mm
├── objc-sel-set.h
├── objc-sel-set.mm
├── objc-sel-table.s
├── objc-sel.mm
├── objc-sync.h
├── objc-sync.mm
├── objc-typeencoding.mm
├── objc-weak.h
├── objc-weak.mm
├── objc.h
├── objcrt.c
├── objcrt.h
└── runtime.h
├── test
├── ARRBase.h
├── ARRBase.m
├── ARRLayouts.m
├── ARRMRR.h
├── ARRMRR.m
├── MRRARR.h
├── MRRARR.m
├── MRRBase.h
├── MRRBase.m
├── Makefile
├── accessors.m
├── accessors2.m
├── addMethod.m
├── addProtocol.m
├── applescriptobjc.m
├── applescriptobjc2.m
├── arr-cast.m
├── arr-weak.m
├── association-cf.m
├── association.m
├── atomicProperty.mm
├── badAltHandler.m
├── badCache.m
├── badTagClass.m
├── badTagIndex.m
├── bigrc.m
├── blocksAsImps.m
├── cacheflush.h
├── cacheflush.m
├── cacheflush0.m
├── cacheflush2.m
├── cacheflush3.m
├── category.m
├── cdtors.mm
├── classgetclass.m
├── classname.m
├── classpair.m
├── classversion.m
├── concurrentcat.m
├── concurrentcat_category.m
├── copyIvarList.m
├── copyMethodList.m
├── copyPropertyList.m
├── createInstance.m
├── customrr-cat1.m
├── customrr-cat2.m
├── customrr-nsobject-awz.m
├── customrr-nsobject-none.m
├── customrr-nsobject-rr.m
├── customrr-nsobject-rrawz.m
├── customrr-nsobject.m
├── customrr.m
├── customrr2.m
├── definitions.c
├── designatedinit.m
├── duplicateClass.m
├── duplicatedClasses.m
├── evil-category-0.m
├── evil-category-00.m
├── evil-category-000.m
├── evil-category-1.m
├── evil-category-2.m
├── evil-category-3.m
├── evil-category-4.m
├── evil-category-def.m
├── evil-class-0.m
├── evil-class-00.m
├── evil-class-000.m
├── evil-class-1.m
├── evil-class-2.m
├── evil-class-3.m
├── evil-class-4.m
├── evil-class-5.m
├── evil-class-def.m
├── evil-main.m
├── exc.m
├── exchangeImp.m
├── foreach.m
├── forward.m
├── forwardDefault.m
├── forwardDefaultStret.m
├── future.h
├── future.m
├── future0.m
├── future2.m
├── gc-main.m
├── gc.c
├── gc.m
├── gcenforcer-nogc-1.m
├── gcenforcer-nogc-2.m
├── gcenforcer-noobjc.m
├── gcenforcer-requiresgc-1.m
├── gcenforcer-requiresgc-2.m
├── gcenforcer-supportsgc.m
├── gcenforcer.m
├── gdb.m
├── getMethod.m
├── ignoredSelector.m
├── ignoredSelector2.m
├── imageorder.h
├── imageorder.m
├── imageorder1.m
├── imageorder2.m
├── imageorder3.m
├── includes.c
├── initialize.m
├── initializeVersusWeak.m
├── instanceSize.m
├── ismeta.m
├── ivar.m
├── ivarSlide.h
├── ivarSlide.m
├── ivarSlide1.m
├── layout.m
├── literals.m
├── load-noobjc.m
├── load-noobjc2.m
├── load-noobjc3.m
├── load-order.m
├── load-order1.m
├── load-order2.m
├── load-order3.m
├── load-parallel.m
├── load-parallel0.m
├── load-parallel00.m
├── load-reentrant.m
├── load-reentrant2.m
├── load.m
├── methodArgs.m
├── methodListSize.m
├── method_getName.m
├── msgSend.m
├── nilAPIArgs.m
├── nonpointerisa.m
├── nopool.m
├── nscdtors.mm
├── nsexc.m
├── nsobject.m
├── nsprotocol.m
├── objectCopy.m
├── property.m
├── propertyDesc.m
├── protocol.m
├── protocol_copyMethodList.m
├── protocol_copyPropertyList.m
├── protocol_cw.m
├── rawisa.m
├── readClassPair.m
├── resolve.m
├── rr-autorelease-fast.m
├── rr-autorelease-fastarc.m
├── rr-autorelease-stacklogging.m
├── rr-autorelease.m
├── rr-autorelease2.m
├── rr-nsautorelease.m
├── rr-sidetable.m
├── runtime.m
├── sel.m
├── setSuper.m
├── subscripting.m
├── super.m
├── synchronized-counter.m
├── synchronized-grid.m
├── synchronized.m
├── taggedNSPointers.m
├── taggedPointers.m
├── taggedPointersDisabled.m
├── tbi.c
├── test.h
├── test.pl
├── testroot.i
├── unload.h
├── unload.m
├── unload2.m
├── unload3.c
├── unload4.m
├── unwind.m
├── verify-exports.pl
├── weak.h
├── weak.m
├── weak2.m
├── weakcopy.m
├── weakframework-missing.m
├── weakframework-not-missing.m
├── weakimport-missing.m
├── weakimport-not-missing.m
├── weakrace.m
├── xref.m
└── zone.m
├── unexported_symbols
├── version.bat
└── version.rc
/objc.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 9.00
3 | # Visual C++ Express 2005
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "objc", "objc.vcproj", "{B3408263-0CF1-47BE-83CC-56070EFC9BC1}"
5 | EndProject
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "objcrt", "objcrt\objcrt.vcproj", "{E38C1996-8B3D-4050-A4B2-DC85957B047D}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1} = {B3408263-0CF1-47BE-83CC-56070EFC9BC1}
9 | EndProjectSection
10 | EndProject
11 | Global
12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
13 | Debug|Win32 = Debug|Win32
14 | DebugDLL|Win32 = DebugDLL|Win32
15 | Release|Win32 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Debug|Win32.ActiveCfg = Debug|Win32
19 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Debug|Win32.Build.0 = Debug|Win32
20 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
21 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
22 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Release|Win32.ActiveCfg = Release|Win32
23 | {B3408263-0CF1-47BE-83CC-56070EFC9BC1}.Release|Win32.Build.0 = Release|Win32
24 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Debug|Win32.ActiveCfg = Debug|Win32
25 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Debug|Win32.Build.0 = Debug|Win32
26 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.DebugDLL|Win32.ActiveCfg = Debug|Win32
27 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.DebugDLL|Win32.Build.0 = Debug|Win32
28 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Release|Win32.ActiveCfg = Release|Win32
29 | {E38C1996-8B3D-4050-A4B2-DC85957B047D}.Release|Win32.Build.0 = Release|Win32
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/objc.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/opensource-apple/objc4/cd5e62a5597ea7a31dccef089317abb3a661c154/objc.suo
--------------------------------------------------------------------------------
/objcrt/objcrt.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
24 |
28 |
31 |
34 |
38 |
39 |
47 |
51 |
54 |
57 |
61 |
62 |
63 |
64 |
65 |
66 |
71 |
74 |
75 |
76 |
81 |
84 |
85 |
86 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/prebuild.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | echo prebuild: installing headers
4 | xcopy /Y "%ProjectDir%runtime\objc.h" "%DSTROOT%\AppleInternal\include\objc\"
5 | xcopy /Y "%ProjectDir%runtime\objc-api.h" "%DSTROOT%\AppleInternal\include\objc\"
6 | xcopy /Y "%ProjectDir%runtime\objc-auto.h" "%DSTROOT%\AppleInternal\include\objc\"
7 | xcopy /Y "%ProjectDir%runtime\objc-exception.h" "%DSTROOT%\AppleInternal\include\objc\"
8 | xcopy /Y "%ProjectDir%runtime\message.h" "%DSTROOT%\AppleInternal\include\objc\"
9 | xcopy /Y "%ProjectDir%runtime\runtime.h" "%DSTROOT%\AppleInternal\include\objc\"
10 | xcopy /Y "%ProjectDir%runtime\hashtable.h" "%DSTROOT%\AppleInternal\include\objc\"
11 | xcopy /Y "%ProjectDir%runtime\hashtable2.h" "%DSTROOT%\AppleInternal\include\objc\"
12 | xcopy /Y "%ProjectDir%runtime\maptable.h" "%DSTROOT%\AppleInternal\include\objc\"
13 |
14 | echo prebuild: setting version
15 | version
16 |
--------------------------------------------------------------------------------
/runtime/NSObjCRuntime.h:
--------------------------------------------------------------------------------
1 | /* NSObjCRuntime.h
2 | Copyright (c) 1994-2012, Apple Inc. All rights reserved.
3 | */
4 |
5 | #ifndef _OBJC_NSOBJCRUNTIME_H_
6 | #define _OBJC_NSOBJCRUNTIME_H_
7 |
8 | #include
9 | #include
10 |
11 | #if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
12 | typedef long NSInteger;
13 | typedef unsigned long NSUInteger;
14 | #else
15 | typedef int NSInteger;
16 | typedef unsigned int NSUInteger;
17 | #endif
18 |
19 | #define NSIntegerMax LONG_MAX
20 | #define NSIntegerMin LONG_MIN
21 | #define NSUIntegerMax ULONG_MAX
22 |
23 | #define NSINTEGER_DEFINED 1
24 |
25 | #ifndef NS_DESIGNATED_INITIALIZER
26 | #if __has_attribute(objc_designated_initializer)
27 | #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
28 | #else
29 | #define NS_DESIGNATED_INITIALIZER
30 | #endif
31 | #endif
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/runtime/NSObject.h:
--------------------------------------------------------------------------------
1 | /* NSObject.h
2 | Copyright (c) 1994-2012, Apple Inc. All rights reserved.
3 | */
4 |
5 | #ifndef _OBJC_NSOBJECT_H_
6 | #define _OBJC_NSOBJECT_H_
7 |
8 | #if __OBJC__
9 |
10 | #include
11 | #include
12 |
13 | @class NSString, NSMethodSignature, NSInvocation;
14 |
15 | @protocol NSObject
16 |
17 | - (BOOL)isEqual:(id)object;
18 | @property (readonly) NSUInteger hash;
19 |
20 | @property (readonly) Class superclass;
21 | - (Class)class OBJC_SWIFT_UNAVAILABLE("use 'anObject.dynamicType' instead");
22 | - (instancetype)self;
23 |
24 | - (id)performSelector:(SEL)aSelector;
25 | - (id)performSelector:(SEL)aSelector withObject:(id)object;
26 | - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
27 |
28 | - (BOOL)isProxy;
29 |
30 | - (BOOL)isKindOfClass:(Class)aClass;
31 | - (BOOL)isMemberOfClass:(Class)aClass;
32 | - (BOOL)conformsToProtocol:(Protocol *)aProtocol;
33 |
34 | - (BOOL)respondsToSelector:(SEL)aSelector;
35 |
36 | - (instancetype)retain OBJC_ARC_UNAVAILABLE;
37 | - (oneway void)release OBJC_ARC_UNAVAILABLE;
38 | - (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
39 | - (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
40 |
41 | - (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
42 |
43 | @property (readonly, copy) NSString *description;
44 | @optional
45 | @property (readonly, copy) NSString *debugDescription;
46 |
47 | @end
48 |
49 |
50 | __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0)
51 | OBJC_ROOT_CLASS
52 | OBJC_EXPORT
53 | @interface NSObject {
54 | Class isa OBJC_ISA_AVAILABILITY;
55 | }
56 |
57 | + (void)load;
58 |
59 | + (void)initialize;
60 | - (instancetype)init
61 | #if NS_ENFORCE_NSOBJECT_DESIGNATED_INITIALIZER
62 | NS_DESIGNATED_INITIALIZER
63 | #endif
64 | ;
65 |
66 | + (instancetype)new OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
67 | + (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
68 | + (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
69 | - (void)dealloc OBJC_SWIFT_UNAVAILABLE("use 'deinit' to define a de-initializer");
70 |
71 | - (void)finalize;
72 |
73 | - (id)copy;
74 | - (id)mutableCopy;
75 |
76 | + (id)copyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
77 | + (id)mutableCopyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
78 |
79 | + (BOOL)instancesRespondToSelector:(SEL)aSelector;
80 | + (BOOL)conformsToProtocol:(Protocol *)protocol;
81 | - (IMP)methodForSelector:(SEL)aSelector;
82 | + (IMP)instanceMethodForSelector:(SEL)aSelector;
83 | - (void)doesNotRecognizeSelector:(SEL)aSelector;
84 |
85 | - (id)forwardingTargetForSelector:(SEL)aSelector __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
86 | - (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");
87 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");
88 |
89 | + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");
90 |
91 | - (BOOL)allowsWeakReference UNAVAILABLE_ATTRIBUTE;
92 | - (BOOL)retainWeakReference UNAVAILABLE_ATTRIBUTE;
93 |
94 | + (BOOL)isSubclassOfClass:(Class)aClass;
95 |
96 | + (BOOL)resolveClassMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
97 | + (BOOL)resolveInstanceMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
98 |
99 | + (NSUInteger)hash;
100 | + (Class)superclass;
101 | + (Class)class OBJC_SWIFT_UNAVAILABLE("use 'aClass.self' instead");
102 | + (NSString *)description;
103 | + (NSString *)debugDescription;
104 |
105 | @end
106 |
107 | #endif
108 |
109 | #endif
110 |
--------------------------------------------------------------------------------
/runtime/Protocol.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2003, 2006-2007 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 | /*
24 | Protocol.h
25 | Copyright 1991-1996 NeXT Software, Inc.
26 | */
27 |
28 | #ifndef _OBJC_PROTOCOL_H_
29 | #define _OBJC_PROTOCOL_H_
30 |
31 | #if !__OBJC__
32 |
33 | // typedef Protocol is here:
34 | #include
35 |
36 |
37 | #elif __OBJC2__
38 |
39 | #include
40 |
41 | // All methods of class Protocol are unavailable.
42 | // Use the functions in objc/runtime.h instead.
43 |
44 | __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0)
45 | @interface Protocol : NSObject
46 | @end
47 |
48 |
49 | #else
50 |
51 | #include
52 |
53 | __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0)
54 | @interface Protocol : Object
55 | {
56 | @private
57 | char *protocol_name OBJC2_UNAVAILABLE;
58 | struct objc_protocol_list *protocol_list OBJC2_UNAVAILABLE;
59 | struct objc_method_description_list *instance_methods OBJC2_UNAVAILABLE;
60 | struct objc_method_description_list *class_methods OBJC2_UNAVAILABLE;
61 | }
62 |
63 | /* Obtaining attributes intrinsic to the protocol */
64 |
65 | - (const char *)name OBJC2_UNAVAILABLE;
66 |
67 | /* Testing protocol conformance */
68 |
69 | - (BOOL) conformsTo: (Protocol *)aProtocolObject OBJC2_UNAVAILABLE;
70 |
71 | /* Looking up information specific to a protocol */
72 |
73 | - (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel
74 | __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_2_0,__IPHONE_2_0);
75 | - (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel
76 | __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_2_0,__IPHONE_2_0);
77 |
78 | @end
79 |
80 | #endif
81 |
82 | #endif /* _OBJC_PROTOCOL_H_ */
83 |
--------------------------------------------------------------------------------
/runtime/a1a2-blocktramps-arm.s:
--------------------------------------------------------------------------------
1 | #if __arm__
2 |
3 | #include
4 | #include
5 |
6 | .syntax unified
7 |
8 | .text
9 |
10 | .private_extern __a1a2_tramphead
11 | .private_extern __a1a2_firsttramp
12 | .private_extern __a1a2_trampend
13 |
14 | // Trampoline machinery assumes the trampolines are Thumb function pointers
15 | #if !__thumb2__
16 | # error sorry
17 | #endif
18 |
19 | .thumb
20 | .thumb_func __a1a2_tramphead
21 | .thumb_func __a1a2_firsttramp
22 | .thumb_func __a1a2_trampend
23 |
24 | .align PAGE_MAX_SHIFT
25 | __a1a2_tramphead:
26 | /*
27 | r0 == self
28 | r12 == pc of trampoline's first instruction + PC bias
29 | lr == original return address
30 | */
31 |
32 | mov r1, r0 // _cmd = self
33 |
34 | // Trampoline's data is one page before the trampoline text.
35 | // Also correct PC bias of 4 bytes.
36 | sub r12, #PAGE_MAX_SIZE
37 | ldr r0, [r12, #-4] // self = block object
38 | ldr pc, [r0, #12] // tail call block->invoke
39 | // not reached
40 |
41 | // Align trampolines to 8 bytes
42 | .align 3
43 |
44 | .macro TrampolineEntry
45 | mov r12, pc
46 | b __a1a2_tramphead
47 | .align 3
48 | .endmacro
49 |
50 | .macro TrampolineEntryX16
51 | TrampolineEntry
52 | TrampolineEntry
53 | TrampolineEntry
54 | TrampolineEntry
55 |
56 | TrampolineEntry
57 | TrampolineEntry
58 | TrampolineEntry
59 | TrampolineEntry
60 |
61 | TrampolineEntry
62 | TrampolineEntry
63 | TrampolineEntry
64 | TrampolineEntry
65 |
66 | TrampolineEntry
67 | TrampolineEntry
68 | TrampolineEntry
69 | TrampolineEntry
70 | .endmacro
71 |
72 | .macro TrampolineEntryX256
73 | TrampolineEntryX16
74 | TrampolineEntryX16
75 | TrampolineEntryX16
76 | TrampolineEntryX16
77 |
78 | TrampolineEntryX16
79 | TrampolineEntryX16
80 | TrampolineEntryX16
81 | TrampolineEntryX16
82 |
83 | TrampolineEntryX16
84 | TrampolineEntryX16
85 | TrampolineEntryX16
86 | TrampolineEntryX16
87 |
88 | TrampolineEntryX16
89 | TrampolineEntryX16
90 | TrampolineEntryX16
91 | TrampolineEntryX16
92 | .endmacro
93 |
94 | .private_extern __a1a2_firsttramp
95 | __a1a2_firsttramp:
96 | // 2048-2 trampolines to fill 16K page
97 | TrampolineEntryX256
98 | TrampolineEntryX256
99 | TrampolineEntryX256
100 | TrampolineEntryX256
101 |
102 | TrampolineEntryX256
103 | TrampolineEntryX256
104 | TrampolineEntryX256
105 |
106 | TrampolineEntryX16
107 | TrampolineEntryX16
108 | TrampolineEntryX16
109 | TrampolineEntryX16
110 |
111 | TrampolineEntryX16
112 | TrampolineEntryX16
113 | TrampolineEntryX16
114 | TrampolineEntryX16
115 |
116 | TrampolineEntryX16
117 | TrampolineEntryX16
118 | TrampolineEntryX16
119 | TrampolineEntryX16
120 |
121 | TrampolineEntryX16
122 | TrampolineEntryX16
123 | TrampolineEntryX16
124 |
125 | TrampolineEntry
126 | TrampolineEntry
127 | TrampolineEntry
128 | TrampolineEntry
129 |
130 | TrampolineEntry
131 | TrampolineEntry
132 | TrampolineEntry
133 | TrampolineEntry
134 |
135 | TrampolineEntry
136 | TrampolineEntry
137 | TrampolineEntry
138 | TrampolineEntry
139 |
140 | TrampolineEntry
141 | TrampolineEntry
142 | // TrampolineEntry
143 | // TrampolineEntry
144 |
145 | .private_extern __a1a2_trampend
146 | __a1a2_trampend:
147 |
148 | #endif
149 |
--------------------------------------------------------------------------------
/runtime/a1a2-blocktramps-arm64.s:
--------------------------------------------------------------------------------
1 | #if __arm64__
2 |
3 | #include
4 |
5 | .text
6 |
7 | .private_extern __a1a2_tramphead
8 | .private_extern __a1a2_firsttramp
9 | .private_extern __a1a2_trampend
10 |
11 | .align PAGE_MAX_SHIFT
12 | __a1a2_tramphead:
13 | L_a1a2_tramphead:
14 | /*
15 | x0 == self
16 | x17 == address of called trampoline's data (1 page before its code)
17 | lr == original return address
18 | */
19 |
20 | mov x1, x0 // _cmd = self
21 | ldr x0, [x17] // self = block object
22 | ldr x16, [x0, #16] // tail call block->invoke
23 | br x16
24 |
25 | // pad up to TrampolineBlockPagePair header size
26 | nop
27 | nop
28 |
29 | .macro TrampolineEntry
30 | // load address of trampoline data (one page before this instruction)
31 | adr x17, -PAGE_MAX_SIZE
32 | b L_a1a2_tramphead
33 | .endmacro
34 |
35 | .macro TrampolineEntryX16
36 | TrampolineEntry
37 | TrampolineEntry
38 | TrampolineEntry
39 | TrampolineEntry
40 |
41 | TrampolineEntry
42 | TrampolineEntry
43 | TrampolineEntry
44 | TrampolineEntry
45 |
46 | TrampolineEntry
47 | TrampolineEntry
48 | TrampolineEntry
49 | TrampolineEntry
50 |
51 | TrampolineEntry
52 | TrampolineEntry
53 | TrampolineEntry
54 | TrampolineEntry
55 | .endmacro
56 |
57 | .macro TrampolineEntryX256
58 | TrampolineEntryX16
59 | TrampolineEntryX16
60 | TrampolineEntryX16
61 | TrampolineEntryX16
62 |
63 | TrampolineEntryX16
64 | TrampolineEntryX16
65 | TrampolineEntryX16
66 | TrampolineEntryX16
67 |
68 | TrampolineEntryX16
69 | TrampolineEntryX16
70 | TrampolineEntryX16
71 | TrampolineEntryX16
72 |
73 | TrampolineEntryX16
74 | TrampolineEntryX16
75 | TrampolineEntryX16
76 | TrampolineEntryX16
77 | .endmacro
78 |
79 | .align 3
80 | .private_extern __a1a2_firsttramp
81 | __a1a2_firsttramp:
82 | // 2048-3 trampolines to fill 16K page
83 | TrampolineEntryX256
84 | TrampolineEntryX256
85 | TrampolineEntryX256
86 | TrampolineEntryX256
87 |
88 | TrampolineEntryX256
89 | TrampolineEntryX256
90 | TrampolineEntryX256
91 |
92 | TrampolineEntryX16
93 | TrampolineEntryX16
94 | TrampolineEntryX16
95 | TrampolineEntryX16
96 |
97 | TrampolineEntryX16
98 | TrampolineEntryX16
99 | TrampolineEntryX16
100 | TrampolineEntryX16
101 |
102 | TrampolineEntryX16
103 | TrampolineEntryX16
104 | TrampolineEntryX16
105 | TrampolineEntryX16
106 |
107 | TrampolineEntryX16
108 | TrampolineEntryX16
109 | TrampolineEntryX16
110 |
111 | TrampolineEntry
112 | TrampolineEntry
113 | TrampolineEntry
114 | TrampolineEntry
115 |
116 | TrampolineEntry
117 | TrampolineEntry
118 | TrampolineEntry
119 | TrampolineEntry
120 |
121 | TrampolineEntry
122 | TrampolineEntry
123 | TrampolineEntry
124 | TrampolineEntry
125 |
126 | TrampolineEntry
127 | // TrampolineEntry
128 | // TrampolineEntry
129 | // TrampolineEntry
130 |
131 | .private_extern __a1a2_trampend
132 | __a1a2_trampend:
133 |
134 | #endif
135 |
--------------------------------------------------------------------------------
/runtime/a2a3-blocktramps-arm.s:
--------------------------------------------------------------------------------
1 | #if __arm__
2 |
3 | #include
4 | #include
5 |
6 | .syntax unified
7 |
8 | .text
9 |
10 | .private_extern __a2a3_tramphead
11 | .private_extern __a2a3_firsttramp
12 | .private_extern __a2a3_trampend
13 |
14 | // Trampoline machinery assumes the trampolines are Thumb function pointers
15 | #if !__thumb2__
16 | # error sorry
17 | #endif
18 |
19 | .thumb
20 | .thumb_func __a2a3_tramphead
21 | .thumb_func __a2a3_firsttramp
22 | .thumb_func __a2a3_trampend
23 |
24 | .align PAGE_MAX_SHIFT
25 | __a2a3_tramphead:
26 | /*
27 | r1 == self
28 | r12 == pc of trampoline's first instruction + PC bias
29 | lr == original return address
30 | */
31 |
32 | mov r2, r1 // _cmd = self
33 |
34 | // Trampoline's data is one page before the trampoline text.
35 | // Also correct PC bias of 4 bytes.
36 | sub r12, #PAGE_MAX_SIZE
37 | ldr r1, [r12, #-4] // self = block object
38 | ldr pc, [r1, #12] // tail call block->invoke
39 | // not reached
40 |
41 | // Align trampolines to 8 bytes
42 | .align 3
43 |
44 | .macro TrampolineEntry
45 | mov r12, pc
46 | b __a2a3_tramphead
47 | .align 3
48 | .endmacro
49 |
50 | .macro TrampolineEntryX16
51 | TrampolineEntry
52 | TrampolineEntry
53 | TrampolineEntry
54 | TrampolineEntry
55 |
56 | TrampolineEntry
57 | TrampolineEntry
58 | TrampolineEntry
59 | TrampolineEntry
60 |
61 | TrampolineEntry
62 | TrampolineEntry
63 | TrampolineEntry
64 | TrampolineEntry
65 |
66 | TrampolineEntry
67 | TrampolineEntry
68 | TrampolineEntry
69 | TrampolineEntry
70 | .endmacro
71 |
72 | .macro TrampolineEntryX256
73 | TrampolineEntryX16
74 | TrampolineEntryX16
75 | TrampolineEntryX16
76 | TrampolineEntryX16
77 |
78 | TrampolineEntryX16
79 | TrampolineEntryX16
80 | TrampolineEntryX16
81 | TrampolineEntryX16
82 |
83 | TrampolineEntryX16
84 | TrampolineEntryX16
85 | TrampolineEntryX16
86 | TrampolineEntryX16
87 |
88 | TrampolineEntryX16
89 | TrampolineEntryX16
90 | TrampolineEntryX16
91 | TrampolineEntryX16
92 | .endmacro
93 |
94 | .private_extern __a2a3_firsttramp
95 | __a2a3_firsttramp:
96 | // 2048-2 trampolines to fill 16K page
97 | TrampolineEntryX256
98 | TrampolineEntryX256
99 | TrampolineEntryX256
100 | TrampolineEntryX256
101 |
102 | TrampolineEntryX256
103 | TrampolineEntryX256
104 | TrampolineEntryX256
105 |
106 | TrampolineEntryX16
107 | TrampolineEntryX16
108 | TrampolineEntryX16
109 | TrampolineEntryX16
110 |
111 | TrampolineEntryX16
112 | TrampolineEntryX16
113 | TrampolineEntryX16
114 | TrampolineEntryX16
115 |
116 | TrampolineEntryX16
117 | TrampolineEntryX16
118 | TrampolineEntryX16
119 | TrampolineEntryX16
120 |
121 | TrampolineEntryX16
122 | TrampolineEntryX16
123 | TrampolineEntryX16
124 |
125 | TrampolineEntry
126 | TrampolineEntry
127 | TrampolineEntry
128 | TrampolineEntry
129 |
130 | TrampolineEntry
131 | TrampolineEntry
132 | TrampolineEntry
133 | TrampolineEntry
134 |
135 | TrampolineEntry
136 | TrampolineEntry
137 | TrampolineEntry
138 | TrampolineEntry
139 |
140 | TrampolineEntry
141 | TrampolineEntry
142 | // TrampolineEntry
143 | // TrampolineEntry
144 |
145 | .private_extern __a2a3_trampend
146 | __a2a3_trampend:
147 |
148 | #endif
149 |
--------------------------------------------------------------------------------
/runtime/hashtable.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
--------------------------------------------------------------------------------
/runtime/objc-accessors.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_ACCESSORS_H_
25 | #define _OBJC_ACCESSORS_H_
26 |
27 | #include
28 | #include
29 |
30 | __BEGIN_DECLS
31 |
32 | #if SUPPORT_GC
33 |
34 | extern void objc_setProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy);
35 | extern id objc_getProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic);
36 |
37 | extern void objc_setProperty_gc(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy);
38 | extern id objc_getProperty_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic);
39 |
40 | #endif
41 |
42 | __END_DECLS
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/runtime/objc-auto-dump.h:
--------------------------------------------------------------------------------
1 | //
2 | // objc-auto-dump.h
3 | // objc
4 | // The raw dump file format
5 | // See objc-gdb.h for the primitive.
6 | //
7 | // Created by Blaine Garst on 12/8/08.
8 | // Copyright 2008 Apple, Inc. All rights reserved.
9 | //
10 | #ifndef _OBJC_AUTO_DUMP_H_
11 | #define _OBJC_AUTO_DUMP_H_
12 |
13 | /*
14 | * Raw file format definitions
15 | */
16 |
17 | // must be unique in first letter...
18 | // RAW FORMAT
19 | #define HEADER "dumpster"
20 | #define THREAD 't'
21 | #define LOCAL 'l'
22 | #define NODE 'n'
23 | #define REGISTER 'r'
24 | #define ROOT 'g'
25 | #define WEAK 'w'
26 | #define CLASS 'c'
27 | #define END 'e'
28 |
29 | #define SixtyFour 1
30 | #define Little 2
31 |
32 | /*
33 |
34 | Raw format, not that anyone should really care. Most programs should use the cooked file reader.
35 |
36 | *
37 | := 'd' 'u' 'm' 'p' 's' 't' 'e' 'r' ; the HEADER string
38 | := SixtyFour? + Little? ; architecture
39 | := | | | |
40 | := * ; the triple
41 | := 'r' longLength [bytes] ; the register bank
42 | := 't' longLength [bytes] ; the stack
43 | := 'l' [long] ; a thread local node
44 | := 'g' longAddress longValue
45 | := 'n' longAddress longSize intLayout longRefcount longIsa?
46 | := 'w' longAddress longValue
47 | := 'c' longAddress
48 | := intLength [bytes] ; no null byte
49 | := intLength [bytes] ; including 0 byte at end
50 | := intLength [bytes] ; including 0 byte at end
51 | := 'e'
52 |
53 | */
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/runtime/objc-cache-old.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_CACHE_OLD_H
25 | #define _OBJC_CACHE_OLD_H
26 |
27 | #include "objc-private.h"
28 |
29 | __BEGIN_DECLS
30 |
31 | extern IMP _cache_getImp(Class cls, SEL sel);
32 | extern Method _cache_getMethod(Class cls, SEL sel, IMP objc_msgForward_internal_imp);
33 |
34 | extern void flush_cache(Class cls);
35 | extern bool _cache_fill(Class cls, Method meth, SEL sel);
36 | extern void _cache_addForwardEntry(Class cls, SEL sel);
37 | extern IMP _cache_addIgnoredEntry(Class cls, SEL sel);
38 | extern void _cache_free(Cache cache);
39 | extern void _cache_collect(bool collectALot);
40 |
41 | __END_DECLS
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/runtime/objc-cache.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _OBJC_CACHE_H
3 | #define _OBJC_CACHE_H
4 |
5 | #include "objc-private.h"
6 |
7 | __BEGIN_DECLS
8 |
9 | extern IMP cache_getImp(Class cls, SEL sel);
10 |
11 | extern void cache_fill(Class cls, SEL sel, IMP imp, id receiver);
12 |
13 | extern void cache_erase_nolock(Class cls);
14 |
15 | extern void cache_delete(Class cls);
16 |
17 | extern void cache_collect(bool collectALot);
18 |
19 | __END_DECLS
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/runtime/objc-class.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
--------------------------------------------------------------------------------
/runtime/objc-file-old.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_FILE_OLD_H
25 | #define _OBJC_FILE_OLD_H
26 |
27 | #if !__OBJC2__
28 |
29 | #include "objc-os.h"
30 |
31 | struct objc_module;
32 | struct old_protocol;
33 | struct old_class;
34 |
35 | __BEGIN_DECLS
36 |
37 | extern struct objc_module *_getObjcModules(const header_info *hi, size_t *nmodules);
38 | extern SEL *_getObjcSelectorRefs(const header_info *hi, size_t *nmess);
39 | extern struct old_protocol **_getObjcProtocols(const header_info *hi, size_t *nprotos);
40 | extern Class *_getObjcClassRefs(const header_info *hi, size_t *nclasses);
41 | extern const char *_getObjcClassNames(const header_info *hi, size_t *size);
42 |
43 | __END_DECLS
44 |
45 | #endif
46 |
47 | #endif
48 |
--------------------------------------------------------------------------------
/runtime/objc-file.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_FILE_NEW_H
25 | #define _OBJC_FILE_NEW_H
26 |
27 | #if __OBJC2__
28 |
29 | #include "objc-runtime-new.h"
30 |
31 | // classref_t is not fixed up at launch; use remapClass() to convert
32 |
33 | extern SEL *_getObjc2SelectorRefs(const header_info *hi, size_t *count);
34 | extern message_ref_t *_getObjc2MessageRefs(const header_info *hi, size_t *count);
35 | extern Class*_getObjc2ClassRefs(const header_info *hi, size_t *count);
36 | extern Class*_getObjc2SuperRefs(const header_info *hi, size_t *count);
37 | extern classref_t *_getObjc2ClassList(const header_info *hi, size_t *count);
38 | extern classref_t *_getObjc2NonlazyClassList(const header_info *hi, size_t *count);
39 | extern category_t **_getObjc2CategoryList(const header_info *hi, size_t *count);
40 | extern category_t **_getObjc2NonlazyCategoryList(const header_info *hi, size_t *count);
41 | extern protocol_t **_getObjc2ProtocolList(const header_info *hi, size_t *count);
42 | extern protocol_t **_getObjc2ProtocolRefs(const header_info *hi, size_t *count);
43 | using Initializer = void(*)(void);
44 | extern Initializer* getLibobjcInitializers(const header_info *hi, size_t *count);
45 |
46 | extern classref_t *_getObjc2NonlazyClassList(const headerType *mhdr, size_t *count);
47 | extern category_t **_getObjc2NonlazyCategoryList(const headerType *mhdr, size_t *count);
48 | extern Initializer* getLibobjcInitializers(const headerType *mhdr, size_t *count);
49 |
50 | #endif
51 |
52 | #endif
53 |
--------------------------------------------------------------------------------
/runtime/objc-initialize.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2005-2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef _OBJC_INITIALIZE_H
25 | #define _OBJC_INITIALIZE_H
26 |
27 | #include "objc-private.h"
28 |
29 | __BEGIN_DECLS
30 |
31 | struct _objc_initializing_classes;
32 |
33 | extern void _class_initialize(Class cls);
34 |
35 | extern void _destroyInitializingClassList(struct _objc_initializing_classes *list);
36 |
37 | __END_DECLS
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/runtime/objc-load.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1999-2001, 2005-2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 | /*
24 | * objc-load.h
25 | * Copyright 1988-1996, NeXT Software, Inc.
26 | */
27 |
28 | #ifndef _OBJC_LOAD_H_
29 | #define _OBJC_LOAD_H_
30 |
31 | #include
32 |
33 | #include
34 |
35 | /* dynamically loading Mach-O object files that contain Objective-C code */
36 |
37 | OBJC_EXPORT long objc_loadModules (
38 | char *modlist[],
39 | void *errStream,
40 | void (*class_callback) (Class, Category),
41 | /*headerType*/ struct mach_header **hdr_addr,
42 | char *debug_file
43 | ) OBJC2_UNAVAILABLE;
44 | OBJC_EXPORT int objc_loadModule (
45 | char * moduleName,
46 | void (*class_callback) (Class, Category),
47 | int * errorCode
48 | ) OBJC2_UNAVAILABLE;
49 | OBJC_EXPORT long objc_unloadModules(
50 | void *errorStream, /* input (optional) */
51 | void (*unloadCallback)(Class, Category) /* input (optional) */
52 | ) OBJC2_UNAVAILABLE;
53 |
54 | #endif /* _OBJC_LOAD_H_ */
55 |
--------------------------------------------------------------------------------
/runtime/objc-loadmethod.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /***********************************************************************
25 | * objc-loadmethod.h
26 | * Support for +load methods.
27 | **********************************************************************/
28 |
29 | #ifndef _OBJC_LOADMETHOD_H
30 | #define _OBJC_LOADMETHOD_H
31 |
32 | #include "objc-private.h"
33 |
34 | __BEGIN_DECLS
35 |
36 | extern void add_class_to_loadable_list(Class cls);
37 | extern void add_category_to_loadable_list(Category cat);
38 | extern void remove_class_from_loadable_list(Class cls);
39 | extern void remove_category_from_loadable_list(Category cat);
40 |
41 | extern void call_load_methods(void);
42 |
43 | __END_DECLS
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/runtime/objc-probes.d:
--------------------------------------------------------------------------------
1 | provider objc_runtime
2 | {
3 | probe objc_exception_throw(void *id);
4 | probe objc_exception_rethrow();
5 | };
6 |
--------------------------------------------------------------------------------
/runtime/objc-references.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2008 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 | /*
24 | * objc-references.h
25 | */
26 |
27 | #ifndef _OBJC_REFERENCES_H_
28 | #define _OBJC_REFERENCES_H_
29 |
30 | #include "objc-api.h"
31 | #include "objc-config.h"
32 |
33 | __BEGIN_DECLS
34 |
35 | extern void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy);
36 | extern id _object_get_associative_reference(id object, void *key);
37 | extern void _object_remove_assocations(id object);
38 |
39 | __END_DECLS
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/runtime/objc-runtime.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
--------------------------------------------------------------------------------
/runtime/objc-sel-set.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004 Apple Inc. All rights reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | /*
25 | * objc-sel-set.h
26 | * A set of SELs used for SEL uniquing.
27 | */
28 |
29 | #ifndef _OBJC_SEL_SET_H_
30 | #define _OBJC_SEL_SET_H_
31 |
32 | #if !__OBJC2__
33 |
34 | #include
35 | #include "objc-os.h"
36 |
37 | __BEGIN_DECLS
38 |
39 | struct __objc_sel_set;
40 |
41 | extern struct __objc_sel_set *__objc_sel_set_create(size_t selrefCount);
42 | extern SEL __objc_sel_set_get(struct __objc_sel_set *sset, SEL candidate);
43 | extern void __objc_sel_set_add(struct __objc_sel_set *sset, SEL value);
44 |
45 | __END_DECLS
46 |
47 | #endif
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/runtime/objc-sel-table.s:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #if __LP64__
5 | # define PTR(x) .quad x
6 | #else
7 | # define PTR(x) .long x
8 | #endif
9 |
10 | .section __TEXT,__objc_opt_ro
11 | .align 3
12 | .private_extern __objc_opt_data
13 | __objc_opt_data:
14 | .long 13 /* table.version */
15 | .long 0 /* table.selopt_offset */
16 | .long 0 /* table.headeropt_offset */
17 | .long 0 /* table.clsopt_offset */
18 | .space PAGE_MAX_SIZE-16
19 |
20 | /* space for selopt, smax/capacity=262144, blen/mask=262143+1 */
21 | .space 262144 /* mask tab */
22 | .space 524288 /* checkbytes */
23 | .space 524288*4 /* offsets */
24 |
25 | /* space for clsopt, smax/capacity=32768, blen/mask=16383+1 */
26 | .space 16384 /* mask tab */
27 | .space 32768 /* checkbytes */
28 | .space 32768*12 /* offsets to name and class and header_info */
29 | .space PAGE_MAX_SIZE /* some duplicate classes */
30 |
31 | /* space for protocolopt, smax/capacity=8192, blen/mask=4095+1 */
32 | .space 4096 /* mask tab */
33 | .space 8192 /* checkbytes */
34 | .space 8192*4 /* offsets */
35 |
36 |
37 | .section __DATA,__objc_opt_rw
38 | .align 3
39 | .private_extern __objc_opt_rw_data
40 | __objc_opt_rw_data:
41 | /* space for header_info structures */
42 | .space 32768
43 |
44 | /* space for 8192 protocols */
45 | #if __LP64__
46 | .space 8192 * 11 * 8
47 | #else
48 | .space 8192 * 11 * 4
49 | #endif
50 |
51 |
52 | /* section of pointers that the shared cache optimizer wants to know about */
53 | .section __DATA,__objc_opt_ptrs
54 | .align 3
55 |
56 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE && __i386__
57 | // old ABI
58 | .globl .objc_class_name_Protocol
59 | PTR(.objc_class_name_Protocol)
60 | #else
61 | // new ABI
62 | .globl _OBJC_CLASS_$_Protocol
63 | PTR(_OBJC_CLASS_$_Protocol)
64 | #endif
65 |
--------------------------------------------------------------------------------
/runtime/objc-sync.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002, 2006 Apple Inc. All Rights Reserved.
3 | *
4 | * @APPLE_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apple Public Source License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://www.opensource.apple.com/apsl/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPLE_LICENSE_HEADER_END@
22 | */
23 |
24 | #ifndef __OBJC_SNYC_H_
25 | #define __OBJC_SNYC_H_
26 |
27 | #include
28 |
29 |
30 | /**
31 | * Begin synchronizing on 'obj'.
32 | * Allocates recursive pthread_mutex associated with 'obj' if needed.
33 | *
34 | * @param obj The object to begin synchronizing on.
35 | *
36 | * @return OBJC_SYNC_SUCCESS once lock is acquired.
37 | */
38 | OBJC_EXPORT int objc_sync_enter(id obj)
39 | __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0);
40 |
41 | /**
42 | * End synchronizing on 'obj'.
43 | *
44 | * @param obj The objet to end synchronizing on.
45 | *
46 | * @return OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
47 | */
48 | OBJC_EXPORT int objc_sync_exit(id obj)
49 | __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0);
50 |
51 | // The wait/notify functions have never worked correctly and no longer exist.
52 | OBJC_EXPORT int objc_sync_wait(id obj, long long milliSecondsMaxWait)
53 | UNAVAILABLE_ATTRIBUTE;
54 | OBJC_EXPORT int objc_sync_notify(id obj)
55 | UNAVAILABLE_ATTRIBUTE;
56 | OBJC_EXPORT int objc_sync_notifyAll(id obj)
57 | UNAVAILABLE_ATTRIBUTE;
58 |
59 | enum {
60 | OBJC_SYNC_SUCCESS = 0,
61 | OBJC_SYNC_NOT_OWNING_THREAD_ERROR = -1,
62 | OBJC_SYNC_TIMED_OUT = -2,
63 | OBJC_SYNC_NOT_INITIALIZED = -3
64 | };
65 |
66 |
67 | #endif // __OBJC_SNYC_H_
68 |
--------------------------------------------------------------------------------
/runtime/objcrt.c:
--------------------------------------------------------------------------------
1 | #define WIN32_LEAN_AND_MEAN
2 | #include
3 | #include
4 | #include
5 | #include "objcrt.h"
6 |
7 | // Boundary symbols for metadata sections
8 |
9 | #pragma section(".objc_module_info$A",long,read,write)
10 | #pragma data_seg(".objc_module_info$A")
11 | static uintptr_t __objc_modStart = 0;
12 | #pragma section(".objc_module_info$C",long,read,write)
13 | #pragma data_seg(".objc_module_info$C")
14 | static uintptr_t __objc_modEnd = 0;
15 |
16 | #pragma section(".objc_protocol$A",long,read,write)
17 | #pragma data_seg(".objc_protocol$A")
18 | static uintptr_t __objc_protoStart = 0;
19 | #pragma section(".objc_protocol$C",long,read,write)
20 | #pragma data_seg(".objc_protocol$C")
21 | static uintptr_t __objc_protoEnd = 0;
22 |
23 | #pragma section(".objc_image_info$A",long,read,write)
24 | #pragma data_seg(".objc_image_info$A")
25 | static uintptr_t __objc_iiStart = 0;
26 | #pragma section(".objc_image_info$C",long,read,write)
27 | #pragma data_seg(".objc_image_info$C")
28 | static uintptr_t __objc_iiEnd = 0;
29 |
30 | #pragma section(".objc_message_refs$A",long,read,write)
31 | #pragma data_seg(".objc_message_refs$A")
32 | static uintptr_t __objc_selrefsStart = 0;
33 | #pragma section(".objc_message_refs$C",long,read,write)
34 | #pragma data_seg(".objc_message_refs$C")
35 | static uintptr_t __objc_selrefsEnd = 0;
36 |
37 | #pragma section(".objc_class_refs$A",long,read,write)
38 | #pragma data_seg(".objc_class_refs$A")
39 | static uintptr_t __objc_clsrefsStart = 0;
40 | #pragma section(".objc_class_refs$C",long,read,write)
41 | #pragma data_seg(".objc_class_refs$C")
42 | static uintptr_t __objc_clsrefsEnd = 0;
43 |
44 | #pragma data_seg()
45 |
46 | // Merge all metadata into .data
47 | // fixme order these by usage?
48 | #pragma comment(linker, "/MERGE:.objc_module_info=.data")
49 | #pragma comment(linker, "/MERGE:.objc_protocol=.data")
50 | #pragma comment(linker, "/MERGE:.objc_image_info=.data")
51 | #pragma comment(linker, "/MERGE:.objc_message_refs=.data")
52 | #pragma comment(linker, "/MERGE:.objc_class_refs=.data")
53 |
54 |
55 | // Image initializers
56 |
57 | static void *__hinfo = NULL; // cookie from runtime
58 | extern IMAGE_DOS_HEADER __ImageBase; // this image's header
59 |
60 | static int __objc_init(void)
61 | {
62 | objc_sections sections = {
63 | 5,
64 | &__objc_modStart, &__objc_modEnd,
65 | &__objc_protoStart, &__objc_protoEnd,
66 | &__objc_iiStart, &__objc_iiEnd,
67 | &__objc_selrefsStart, &__objc_selrefsEnd,
68 | &__objc_clsrefsStart, &__objc_clsrefsEnd,
69 | };
70 | __hinfo = _objc_init_image((HMODULE)&__ImageBase, §ions);
71 | return 0;
72 | }
73 |
74 | static void __objc_unload(void)
75 | {
76 | _objc_unload_image((HMODULE)&__ImageBase, __hinfo);
77 | }
78 |
79 | static int __objc_load(void)
80 | {
81 | _objc_load_image((HMODULE)&__ImageBase, __hinfo);
82 | return 0;
83 | }
84 |
85 | // run _objc_init_image ASAP
86 | #pragma section(".CRT$XIAA",long,read,write)
87 | #pragma data_seg(".CRT$XIAA")
88 | static void *__objc_init_fn = &__objc_init;
89 |
90 | // run _objc_load_image (+load methods) after all other initializers;
91 | // otherwise constant NSStrings are not initialized yet
92 | #pragma section(".CRT$XCUO",long,read,write)
93 | #pragma data_seg(".CRT$XCUO")
94 | static void *__objc_load_fn = &__objc_load;
95 |
96 | // _objc_unload_image is called by atexit(), not by an image terminator
97 |
98 | #pragma data_seg()
99 |
--------------------------------------------------------------------------------
/runtime/objcrt.h:
--------------------------------------------------------------------------------
1 | #ifndef _OBJC_RT_H_
2 | #define _OBJC_RT_H_
3 |
4 | #include
5 |
6 |
7 | typedef struct {
8 | int count; // number of pointer pairs that follow
9 | void *modStart;
10 | void *modEnd;
11 | void *protoStart;
12 | void *protoEnd;
13 | void *iiStart;
14 | void *iiEnd;
15 | void *selrefsStart;
16 | void *selrefsEnd;
17 | void *clsrefsStart;
18 | void *clsrefsEnd;
19 | } objc_sections;
20 |
21 | OBJC_EXPORT void *_objc_init_image(HMODULE image, const objc_sections *sects);
22 | OBJC_EXPORT void _objc_load_image(HMODULE image, void *hinfo);
23 | OBJC_EXPORT void _objc_unload_image(HMODULE image, void *hinfo);
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/test/ARRBase.h:
--------------------------------------------------------------------------------
1 | //
2 | // ARRBase.h
3 | // TestARRLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ARRBase : NSObject
12 | @property long number;
13 | @property(retain) id object;
14 | @property void *pointer;
15 | @property(weak) __weak id delegate;
16 | @end
17 |
--------------------------------------------------------------------------------
/test/ARRBase.m:
--------------------------------------------------------------------------------
1 | //
2 | // ARRBase.m
3 | // TestARRLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "ARRBase.h"
10 |
11 | #if 1
12 | @interface ARRBase () {
13 | @private
14 | long number;
15 | id object;
16 | void *pointer;
17 | __weak id delegate;
18 | }
19 | @end
20 | #endif
21 |
22 | @implementation ARRBase
23 | @synthesize number, object, pointer, delegate;
24 | @end
25 |
--------------------------------------------------------------------------------
/test/ARRLayouts.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG MEM=arc CC=clang
3 | TEST_BUILD
4 | $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRRBase.m
5 | $C{COMPILE_NOLINK_NOMEM} -c $DIR/MRRARR.m
6 | $C{COMPILE_NOLINK} -c $DIR/ARRBase.m
7 | $C{COMPILE_NOLINK} -c $DIR/ARRMRR.m
8 | $C{COMPILE} -fobjc-arc $DIR/ARRLayouts.m -x none MRRBase.o MRRARR.o ARRBase.o ARRMRR.o -framework Foundation -o ARRLayouts.out
9 | END
10 | */
11 |
12 | #include "test.h"
13 | #import
14 | #import
15 | #import
16 |
17 | #import "ARRMRR.h"
18 | #import "MRRARR.h"
19 |
20 | @interface NSObject (Layouts)
21 | + (const char *)strongLayout;
22 | + (const char *)weakLayout;
23 | @end
24 |
25 | void printlayout(const char *name, const uint8_t *layout)
26 | {
27 | if (! getenv("VERBOSE")) return;
28 |
29 | testprintf("%s: ", name);
30 |
31 | if (!layout) {
32 | fprintf(stderr, "NULL\n");
33 | return;
34 | }
35 |
36 | const uint8_t *c;
37 | for (c = layout; *c; c++) {
38 | fprintf(stderr, "%02x ", *c);
39 | }
40 |
41 | fprintf(stderr, "00\n");
42 | }
43 |
44 | @implementation NSObject (Layouts)
45 |
46 | + (const char *)strongLayout {
47 | const uint8_t *layout = class_getIvarLayout(self);
48 | printlayout("strong", layout);
49 | return (const char *)layout;
50 | }
51 |
52 | + (const char *)weakLayout {
53 | const uint8_t *weakLayout = class_getWeakIvarLayout(self);
54 | printlayout("weak", weakLayout);
55 | return (const char *)weakLayout;
56 | }
57 |
58 | + (Ivar)instanceVariable:(const char *)name {
59 | return class_getInstanceVariable(self, name);
60 | }
61 |
62 | @end
63 |
64 | int main (int argc __unused, const char * argv[] __unused) {
65 | // Under ARR, layout strings are relative to the class' own ivars.
66 | testassert(strcmp([ARRBase strongLayout], "\x11\x20") == 0);
67 | testassert(strcmp([ARRBase weakLayout], "\x31") == 0);
68 | testassert([MRRBase strongLayout] == NULL);
69 | testassert([MRRBase weakLayout] == NULL);
70 | testassert(strcmp([ARRMRR strongLayout], "\x01") == 0);
71 | testassert([ARRMRR weakLayout] == NULL);
72 | testassert([MRRARR strongLayout] == NULL);
73 | testassert([MRRARR weakLayout] == NULL);
74 |
75 | // now check consistency between dynamic accessors and KVC, etc.
76 | ARRMRR *am = [ARRMRR new];
77 | MRRARR *ma = [MRRARR new];
78 |
79 | NSString *am_description = [[NSString alloc] initWithFormat:@"%s %p", "ARRMRR", am];
80 | NSString *ma_description = [[NSString alloc] initWithFormat:@"%s %p", "MRRARR", ma];
81 |
82 | am.number = M_PI;
83 | object_setIvar(am, [ARRMRR instanceVariable:"object"], am_description);
84 | testassert(CFGetRetainCount(objc_unretainedPointer(am_description)) == 1);
85 | am.pointer = @selector(ARRMRR);
86 | object_setIvar(am, [ARRMRR instanceVariable:"delegate"], ma);
87 | testassert(CFGetRetainCount(objc_unretainedPointer(ma)) == 1);
88 |
89 | ma.number = M_E;
90 | object_setIvar(ma, [MRRARR instanceVariable:"object"], ma_description);
91 | testassert(CFGetRetainCount(objc_unretainedPointer(ma_description)) == 2);
92 | ma.pointer = @selector(MRRARR);
93 | ma.delegate = am;
94 | object_setIvar(ma, [MRRARR instanceVariable:"delegate"], am);
95 | testassert(CFGetRetainCount(objc_unretainedPointer(am)) == 1);
96 |
97 | succeed(__FILE__);
98 | return 0;
99 | }
100 |
--------------------------------------------------------------------------------
/test/ARRMRR.h:
--------------------------------------------------------------------------------
1 | //
2 | // ARRMRR.h
3 | // TestARRLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "MRRBase.h"
10 |
11 | @interface ARRMRR : MRRBase
12 | @property(retain) id dataSource;
13 | @end
14 |
--------------------------------------------------------------------------------
/test/ARRMRR.m:
--------------------------------------------------------------------------------
1 | //
2 | // ARRMRR.m
3 | //
4 |
5 | #import "ARRMRR.h"
6 |
7 | @implementation ARRMRR
8 |
9 | @synthesize dataSource;
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/test/MRRARR.h:
--------------------------------------------------------------------------------
1 | //
2 | // MRRARR.h
3 | // TestARRLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "ARRBase.h"
10 |
11 | @interface MRRARR : ARRBase
12 | @property(retain) id dataSource;
13 | @end
14 |
--------------------------------------------------------------------------------
/test/MRRARR.m:
--------------------------------------------------------------------------------
1 | //
2 | // MRRARR.m
3 | //
4 |
5 | #import "MRRARR.h"
6 |
7 | @implementation MRRARR
8 |
9 | @synthesize dataSource;
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/test/MRRBase.h:
--------------------------------------------------------------------------------
1 | //
2 | // MRRBase.h
3 | // TestARRLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MRRBase : NSObject
12 | @property double number;
13 | @property(retain) id object;
14 | @property void *pointer;
15 | @property(weak) __weak id delegate;
16 | @end
17 |
--------------------------------------------------------------------------------
/test/MRRBase.m:
--------------------------------------------------------------------------------
1 | //
2 | // MRRBase.m
3 | // TestARRLayouts
4 | //
5 | // Created by Patrick Beard on 3/8/11.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "MRRBase.h"
10 |
11 | #if 1
12 | @interface MRRBase () {
13 | @private
14 | double number;
15 | id object;
16 | void *pointer;
17 | __weak id delegate;
18 | }
19 | @end
20 | #endif
21 |
22 | @implementation MRRBase
23 | @synthesize number, object, pointer, delegate;
24 | @end
25 |
--------------------------------------------------------------------------------
/test/Makefile:
--------------------------------------------------------------------------------
1 | # quick test
2 | all:
3 | perl test.pl $(MAKEFLAGS)
4 |
5 | # default-arch but otherwise comprehensive test for buildbot
6 | buildbot:
7 | perl test.pl $(MAKEFLAGS) MEM=mrc,arc,gc CC=clang LANGUAGE=objc,objc++
8 |
9 | # comprehensive tests
10 | mac macos macosx:
11 | perl test.pl $(MAKEFLAGS) ARCH=x86_64,i386 MEM=mrc,arc,gc CC=clang LANGUAGE=objc,objc++
12 |
13 | iphonesimulator:
14 | perl test.pl $(MAKEFLAGS) ARCH=i386 SDK=iphonesimulator MEM=mrc,arc CC=clang LANGUAGE=objc,objc++
15 |
16 | iphoneos:
17 | perl test.pl $(MAKEFLAGS) ARCH=armv6,armv7 SDK=iphoneos MEM=mrc,arc CC=clang LANGUAGE=objc,objc++
18 |
19 | clean:
20 | @ perl test.pl clean
21 |
--------------------------------------------------------------------------------
/test/accessors.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 |
3 | #import
4 | #import
5 | #import
6 | #include "test.h"
7 |
8 | @interface Test : NSObject {
9 | NSString *_value;
10 | // _object is at the last optimized property offset
11 | id _object __attribute__((aligned(64)));
12 | }
13 | @property(readonly) Class cls;
14 | @property(copy) NSString *value;
15 | @property(assign) id object;
16 | @end
17 |
18 | typedef struct {
19 | void *isa;
20 | void *_value;
21 | // _object is at the last optimized property offset
22 | void *_object __attribute__((aligned(64)));
23 | } TestDefs;
24 |
25 | @implementation Test
26 |
27 | // Question: why can't this code be automatically generated?
28 |
29 | #if !__has_feature(objc_arc)
30 | - (void)dealloc {
31 | self.value = nil;
32 | self.object = nil;
33 | [super dealloc];
34 | }
35 | #endif
36 |
37 | - (Class)cls { return objc_getProperty(self, _cmd, 0, YES); }
38 |
39 | - (NSString*)value { return (NSString*) objc_getProperty(self, _cmd, offsetof(TestDefs, _value), YES); }
40 | - (void)setValue:(NSString*)inValue { objc_setProperty(self, _cmd, offsetof(TestDefs, _value), inValue, YES, YES); }
41 |
42 | - (id)object { return objc_getProperty(self, _cmd, offsetof(TestDefs, _object), YES); }
43 | - (void)setObject:(id)inObject { objc_setProperty(self, _cmd, offsetof(TestDefs, _object), inObject, YES, NO); }
44 |
45 | - (NSString *)description {
46 | return [NSString stringWithFormat:@"value = %@, object = %@", self.value, self.object];
47 | }
48 |
49 | @end
50 |
51 | int main() {
52 | PUSH_POOL {
53 |
54 | NSMutableString *value = [NSMutableString stringWithUTF8String:"test"];
55 | id object = [NSNumber numberWithInt:11];
56 | Test *t = AUTORELEASE([Test new]);
57 | t.value = value;
58 | [value setString:@"yuck"]; // mutate the string.
59 | testassert(t.value != value); // must copy, since it was mutable.
60 | testassert([t.value isEqualToString:@"test"]);
61 |
62 | Class testClass = [Test class];
63 | Class cls = t.cls;
64 | testassert(testClass == cls);
65 | cls = t.cls;
66 | testassert(testClass == cls);
67 |
68 | t.object = object;
69 | t.object = object;
70 |
71 | // NSLog(@"t.object = %@, t.value = %@", t.object, t.value);
72 | // NSLog(@"t.object = %@, t.value = %@", t.object, t.value); // second call will optimized getters.
73 |
74 | } POP_POOL;
75 |
76 | succeed(__FILE__);
77 |
78 | return 0;
79 | }
80 |
--------------------------------------------------------------------------------
/test/applescriptobjc.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=macosx
2 | // TEST_CFLAGS -framework AppleScriptObjC -framework Foundation
3 |
4 | // Verify that trivial AppleScriptObjC apps run with GC off.
5 |
6 | #include
7 | #include "test.h"
8 |
9 | int main()
10 | {
11 | [NSBundle class];
12 | testassert(!objc_collectingEnabled());
13 | succeed(__FILE__);
14 | }
15 |
--------------------------------------------------------------------------------
/test/applescriptobjc2.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework AppleScriptObjC -framework Foundation
2 | // TEST_CONFIG MEM=gc
3 |
4 | // Verify that non-trivial AppleScriptObjC apps run with GC ON.
5 |
6 | #include
7 | #include "test.h"
8 |
9 | @interface NonTrivial : NSObject @end
10 | @implementation NonTrivial @end
11 |
12 | int main()
13 | {
14 | [NSBundle class];
15 | testassert(objc_collectingEnabled());
16 | succeed(__FILE__);
17 | }
18 |
--------------------------------------------------------------------------------
/test/arr-cast.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | // objc.h redefines these calls into bridge casts.
6 | // This test verifies that the function implementations are exported.
7 | __BEGIN_DECLS
8 | extern void *retainedObject(void *arg) __asm__("_objc_retainedObject");
9 | extern void *unretainedObject(void *arg) __asm__("_objc_unretainedObject");
10 | extern void *unretainedPointer(void *arg) __asm__("_objc_unretainedPointer");
11 | __END_DECLS
12 |
13 | int main()
14 | {
15 | void *p = (void*)&main;
16 | testassert(p == retainedObject(p));
17 | testassert(p == unretainedObject(p));
18 | testassert(p == unretainedPointer(p));
19 | succeed(__FILE__);
20 | }
21 |
--------------------------------------------------------------------------------
/test/association-cf.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework CoreFoundation
2 |
3 | #include
4 | #include
5 |
6 | #include "test.h"
7 |
8 | #if __has_feature(objc_arc)
9 |
10 | int main()
11 | {
12 | testwarn("rdar://11368528 confused by Foundation");
13 | succeed(__FILE__);
14 | }
15 |
16 | #else
17 |
18 | int main()
19 | {
20 | // rdar://6164781 setAssociatedObject on pure-CF object crashes LP64
21 |
22 | id obj;
23 | id array = objc_retainedObject(CFArrayCreate(0, 0, 0, 0));
24 | testassert(array);
25 |
26 | testassert(! objc_getClass("NSCFArray"));
27 |
28 | objc_setAssociatedObject(array, (void*)1, array, OBJC_ASSOCIATION_ASSIGN);
29 |
30 | obj = objc_getAssociatedObject(array, (void*)1);
31 | testassert(obj == array);
32 |
33 | RELEASE_VAR(array);
34 |
35 | succeed(__FILE__);
36 | }
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/test/association.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | static int values;
8 | static int supers;
9 | static int subs;
10 |
11 | static const char *key = "key";
12 |
13 |
14 | @interface Value : NSObject @end
15 | @interface Super : NSObject @end
16 | @interface Sub : NSObject @end
17 |
18 | @interface Super2 : NSObject @end
19 | @interface Sub2 : NSObject @end
20 |
21 | @implementation Super
22 | -(id) init
23 | {
24 | // rdar://8270243 don't lose associations after isa swizzling
25 |
26 | id value = [Value new];
27 | objc_setAssociatedObject(self, &key, value, OBJC_ASSOCIATION_RETAIN);
28 | RELEASE_VAR(value);
29 |
30 | object_setClass(self, [Sub class]);
31 |
32 | return self;
33 | }
34 |
35 | -(void) dealloc
36 | {
37 | supers++;
38 | SUPER_DEALLOC();
39 | }
40 | -(void) finalize
41 | {
42 | supers++;
43 | [super finalize];
44 | }
45 |
46 | @end
47 |
48 | @implementation Sub
49 | -(void) dealloc
50 | {
51 | subs++;
52 | SUPER_DEALLOC();
53 | }
54 | -(void) finalize
55 | {
56 | subs++;
57 | [super finalize];
58 | }
59 | @end
60 |
61 | @implementation Super2
62 | -(id) init
63 | {
64 | // rdar://9617109 don't lose associations after isa swizzling
65 |
66 | id value = [Value new];
67 | object_setClass(self, [Sub2 class]);
68 | objc_setAssociatedObject(self, &key, value, OBJC_ASSOCIATION_RETAIN);
69 | RELEASE_VAR(value);
70 | object_setClass(self, [Super2 class]);
71 |
72 | return self;
73 | }
74 |
75 | -(void) dealloc
76 | {
77 | supers++;
78 | SUPER_DEALLOC();
79 | }
80 | -(void) finalize
81 | {
82 | supers++;
83 | [super finalize];
84 | }
85 |
86 | @end
87 |
88 | @implementation Sub2
89 | -(void) dealloc
90 | {
91 | subs++;
92 | SUPER_DEALLOC();
93 | }
94 | -(void) finalize
95 | {
96 | subs++;
97 | [super finalize];
98 | }
99 | @end
100 |
101 | @implementation Value
102 | -(void) dealloc {
103 | values++;
104 | SUPER_DEALLOC();
105 | }
106 | -(void) finalize {
107 | values++;
108 | [super finalize];
109 | }
110 | @end
111 |
112 |
113 | int main()
114 | {
115 | testonthread(^{
116 | int i;
117 | for (i = 0; i < 100; i++) {
118 | RELEASE_VALUE([[Super alloc] init]);
119 | }
120 | });
121 | testcollect();
122 |
123 | testassert(supers == 0);
124 | testassert(subs > 0);
125 | testassert(subs == values);
126 |
127 |
128 | supers = 0;
129 | subs = 0;
130 | values = 0;
131 |
132 | testonthread(^{
133 | int i;
134 | for (i = 0; i < 100; i++) {
135 | RELEASE_VALUE([[Super2 alloc] init]);
136 | }
137 | });
138 | testcollect();
139 |
140 | testassert(supers > 0);
141 | testassert(subs == 0);
142 | testassert(supers == values);
143 |
144 | succeed(__FILE__);
145 | }
146 |
--------------------------------------------------------------------------------
/test/atomicProperty.mm:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG CC=clang
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #import
7 |
8 | class SerialNumber {
9 | size_t _number;
10 | public:
11 | SerialNumber() : _number(42) {}
12 | SerialNumber(const SerialNumber &number) : _number(number._number + 1) {}
13 | SerialNumber &operator=(const SerialNumber &number) { _number = number._number + 1; return *this; }
14 |
15 | int operator==(const SerialNumber &number) { return _number == number._number; }
16 | int operator!=(const SerialNumber &number) { return _number != number._number; }
17 | };
18 |
19 | @interface TestAtomicProperty : NSObject {
20 | SerialNumber number;
21 | }
22 | @property(atomic) SerialNumber number;
23 | @end
24 |
25 | @implementation TestAtomicProperty
26 |
27 | @synthesize number;
28 |
29 | @end
30 |
31 | int main()
32 | {
33 | PUSH_POOL {
34 | SerialNumber number;
35 | TestAtomicProperty *test = [TestAtomicProperty new];
36 | test.number = number;
37 | testassert(test.number != number);
38 | } POP_POOL;
39 |
40 | succeed(__FILE__);
41 | }
42 |
--------------------------------------------------------------------------------
/test/badAltHandler.m:
--------------------------------------------------------------------------------
1 | // for OBJC2 mac only
2 | /* TEST_CONFIG OS=macosx ARCH=x86_64
3 | TEST_CRASHES
4 |
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: objc_removeExceptionHandler\(\) called with unknown alt handler; this is probably a bug in multithreaded AppKit use. Set environment variable OBJC_DEBUG_ALT_HANDLERS=YES or break in objc_alt_handler_error\(\) to debug.
7 | CRASHED: SIGILL
8 | END
9 | */
10 |
11 | #include "test.h"
12 |
13 | #include
14 |
15 | /*
16 | rdar://6888838
17 | Mail installs an alt handler on one thread and deletes it on another.
18 | This confuses the alt handler machinery, which halts the process.
19 | */
20 |
21 | uintptr_t Token;
22 |
23 | void handler(id unused __unused, void *context __unused)
24 | {
25 | }
26 |
27 | int main()
28 | {
29 | #if __clang__ && __cplusplus
30 | // alt handlers need the objc personality
31 | // catch (id) workaround forces the objc personality
32 | @try {
33 | testwarn("rdar://9183014 clang uses wrong exception personality");
34 | } @catch (id e __unused) {
35 | }
36 | #endif
37 |
38 | @try {
39 | // Install 4 alt handlers
40 | uintptr_t t1, t2, t3, t4;
41 | t1 = objc_addExceptionHandler(&handler, NULL);
42 | t2 = objc_addExceptionHandler(&handler, NULL);
43 | t3 = objc_addExceptionHandler(&handler, NULL);
44 | t4 = objc_addExceptionHandler(&handler, NULL);
45 |
46 | // Remove 3 of them.
47 | objc_removeExceptionHandler(t1);
48 | objc_removeExceptionHandler(t2);
49 | objc_removeExceptionHandler(t3);
50 |
51 | // Create an alt handler on another thread
52 | // that collides with one of the removed handlers
53 | testonthread(^{
54 | @try {
55 | Token = objc_addExceptionHandler(&handler, NULL);
56 | } @catch (...) {
57 | }
58 | });
59 |
60 | // Incorrectly remove the other thread's handler
61 | objc_removeExceptionHandler(Token);
62 | // Remove the 4th handler
63 | objc_removeExceptionHandler(t4);
64 |
65 | // Install 8 more handlers.
66 | // If the other thread's handler was not ignored,
67 | // this will fail.
68 | objc_addExceptionHandler(&handler, NULL);
69 | objc_addExceptionHandler(&handler, NULL);
70 | objc_addExceptionHandler(&handler, NULL);
71 | objc_addExceptionHandler(&handler, NULL);
72 | objc_addExceptionHandler(&handler, NULL);
73 | objc_addExceptionHandler(&handler, NULL);
74 | objc_addExceptionHandler(&handler, NULL);
75 | objc_addExceptionHandler(&handler, NULL);
76 | } @catch (...) {
77 | }
78 |
79 | // This should have crashed earlier.
80 | fail(__FILE__);
81 | }
82 |
--------------------------------------------------------------------------------
/test/badCache.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CRASHES
3 | TEST_RUN_OUTPUT
4 | objc1
5 | OK: badCache.m
6 | OR
7 | crash now
8 | objc\[\d+\]: Method cache corrupted.*
9 | objc\[\d+\]: .*
10 | objc\[\d+\]: .*
11 | objc\[\d+\]: .*
12 | objc\[\d+\]: .*
13 | objc\[\d+\]: Method cache corrupted\.
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 |
19 | #include "test.h"
20 |
21 | #if !__OBJC2__ || __arm__
22 |
23 | int main()
24 | {
25 | fprintf(stderr, "objc1\n");
26 | succeed(__FILE__);
27 | }
28 |
29 | #else
30 |
31 | #include "testroot.i"
32 |
33 | #if __LP64__
34 | typedef uint32_t mask_t;
35 | #else
36 | typedef uint16_t mask_t;
37 | #endif
38 |
39 | struct bucket_t {
40 | uintptr_t sel;
41 | uintptr_t imp;
42 | };
43 |
44 | struct cache_t {
45 | struct bucket_t *buckets;
46 | mask_t mask;
47 | mask_t occupied;
48 | };
49 |
50 | struct class_t {
51 | void *isa;
52 | void *supercls;
53 | struct cache_t cache;
54 | };
55 |
56 | @interface Subclass : TestRoot @end
57 | @implementation Subclass @end
58 |
59 | int main()
60 | {
61 | Class cls = [TestRoot class];
62 | id obj = [cls new];
63 | [obj self];
64 |
65 | struct cache_t *cache = &((__bridge struct class_t *)cls)->cache;
66 |
67 | # define COUNT 4
68 | struct bucket_t *buckets = calloc(sizeof(struct bucket_t), COUNT+1);
69 | for (int i = 0; i < COUNT; i++) {
70 | buckets[i].sel = ~0;
71 | buckets[i].imp = ~0;
72 | }
73 | buckets[COUNT].sel = 1;
74 | buckets[COUNT].imp = (uintptr_t)buckets;
75 |
76 | cache->mask = COUNT-1;
77 | cache->occupied = 0;
78 | cache->buckets = buckets;
79 |
80 | fprintf(stderr, "crash now\n");
81 | [obj self];
82 |
83 | fail("should have crashed");
84 | }
85 |
86 | #endif
87 |
--------------------------------------------------------------------------------
/test/badTagClass.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CRASHES
3 | TEST_RUN_OUTPUT
4 | objc\[\d+\]: tag index 7 used for two different classes \(was 0x[0-9a-fA-F]+ NSObject, now 0x[0-9a-fA-F]+ TestRoot\)
5 | CRASHED: SIG(ILL|TRAP)
6 | OR
7 | no tagged pointers
8 | OK: badTagClass.m
9 | END
10 | */
11 |
12 | #include "test.h"
13 | #include "testroot.i"
14 |
15 | #include
16 | #include
17 |
18 | #if OBJC_HAVE_TAGGED_POINTERS
19 |
20 | int main()
21 | {
22 | // re-registration and nil registration allowed
23 | _objc_registerTaggedPointerClass(OBJC_TAG_7, [NSObject class]);
24 | _objc_registerTaggedPointerClass(OBJC_TAG_7, [NSObject class]);
25 | _objc_registerTaggedPointerClass(OBJC_TAG_7, nil);
26 | _objc_registerTaggedPointerClass(OBJC_TAG_7, [NSObject class]);
27 |
28 | // colliding registration disallowed
29 | _objc_registerTaggedPointerClass(OBJC_TAG_7, [TestRoot class]);
30 |
31 | fail(__FILE__);
32 | }
33 |
34 | #else
35 |
36 | int main()
37 | {
38 | fprintf(stderr, "no tagged pointers\n");
39 | succeed(__FILE__);
40 | }
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/test/badTagIndex.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CRASHES
3 | TEST_RUN_OUTPUT
4 | objc\[\d+\]: tag index 8 is too large.
5 | CRASHED: SIG(ILL|TRAP)
6 | OR
7 | no tagged pointers
8 | OK: badTagIndex.m
9 | END
10 | */
11 |
12 | #include "test.h"
13 |
14 | #include
15 | #include
16 |
17 | #if OBJC_HAVE_TAGGED_POINTERS
18 |
19 | int main()
20 | {
21 | _objc_registerTaggedPointerClass((objc_tag_index_t)8, [NSObject class]);
22 | fail(__FILE__);
23 | }
24 |
25 | #else
26 |
27 | int main()
28 | {
29 | fprintf(stderr, "no tagged pointers\n");
30 | succeed(__FILE__);
31 | }
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/test/bigrc.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 | /*
3 | TEST_RUN_OUTPUT
4 | objc\[\d+\]: Deallocator object 0x[0-9a-fA-F]+ overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug
5 | OK: bigrc.m
6 | OR
7 | no overrelease enforcement
8 | OK: bigrc.m
9 | END
10 | */
11 |
12 | #include "test.h"
13 | #include "testroot.i"
14 |
15 | static size_t LOTS;
16 |
17 | @interface Deallocator : TestRoot @end
18 | @implementation Deallocator
19 |
20 | -(void)dealloc
21 | {
22 | id o = self;
23 | size_t rc = 1;
24 |
25 |
26 | testprintf("Retain a lot during dealloc\n");
27 |
28 | testassert(rc == 1);
29 | testassert([o retainCount] == rc);
30 | do {
31 | [o retain];
32 | if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
33 | } while (++rc < LOTS);
34 |
35 | testassert([o retainCount] == rc);
36 |
37 | do {
38 | [o release];
39 | if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
40 | } while (--rc > 1);
41 |
42 | testassert(rc == 1);
43 | testassert([o retainCount] == rc);
44 |
45 |
46 | testprintf("Overrelease during dealloc\n");
47 |
48 | // Not all architectures enforce this.
49 | #if !SUPPORT_NONPOINTER_ISA
50 | testwarn("no overrelease enforcement");
51 | fprintf(stderr, "no overrelease enforcement\n");
52 | #endif
53 | [o release];
54 |
55 | [super dealloc];
56 | }
57 |
58 | @end
59 |
60 |
61 | int main()
62 | {
63 | Deallocator *o = [Deallocator new];
64 | size_t rc = 1;
65 |
66 | [o retain];
67 |
68 | uintptr_t isa = *(uintptr_t *)o;
69 | if (isa & 1) {
70 | // Assume refcount in high bits.
71 | LOTS = 1 << (4 + __builtin_clzll(isa));
72 | testprintf("LOTS %zu via cntlzw\n", LOTS);
73 | } else {
74 | LOTS = 0x1000000;
75 | testprintf("LOTS %zu via guess\n", LOTS);
76 | }
77 |
78 | [o release];
79 |
80 |
81 | testprintf("Retain a lot\n");
82 |
83 | testassert(rc == 1);
84 | testassert([o retainCount] == rc);
85 | do {
86 | [o retain];
87 | if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
88 | } while (++rc < LOTS);
89 |
90 | testassert([o retainCount] == rc);
91 |
92 | do {
93 | [o release];
94 | if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
95 | } while (--rc > 1);
96 |
97 | testassert(rc == 1);
98 | testassert([o retainCount] == rc);
99 |
100 |
101 | testprintf("tryRetain a lot\n");
102 |
103 | id w;
104 | objc_storeWeak(&w, o);
105 | testassert(w == o);
106 |
107 | testassert(rc == 1);
108 | testassert([o retainCount] == rc);
109 | do {
110 | objc_loadWeakRetained(&w);
111 | if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
112 | } while (++rc < LOTS);
113 |
114 | testassert([o retainCount] == rc);
115 |
116 | do {
117 | [o release];
118 | if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
119 | } while (--rc > 1);
120 |
121 | testassert(rc == 1);
122 | testassert([o retainCount] == rc);
123 |
124 | testprintf("dealloc\n");
125 |
126 | testassert(TestRootDealloc == 0);
127 | testassert(w != nil);
128 | [o release];
129 | testassert(TestRootDealloc == 1);
130 | testassert(w == nil);
131 |
132 | succeed(__FILE__);
133 | }
134 |
--------------------------------------------------------------------------------
/test/cacheflush.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include "test.h"
3 |
4 | @interface TestRoot(cat)
5 | +(int)classMethod;
6 | -(int)instanceMethod;
7 | @end
8 |
--------------------------------------------------------------------------------
/test/cacheflush.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/cacheflush0.m -o cacheflush0.dylib -dynamiclib
4 | $C{COMPILE} $DIR/cacheflush2.m -x none cacheflush0.dylib -o cacheflush2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/cacheflush3.m -x none cacheflush0.dylib -o cacheflush3.dylib -dynamiclib
6 | $C{COMPILE} $DIR/cacheflush.m -x none cacheflush0.dylib -o cacheflush.out
7 | END
8 | */
9 |
10 | #include "test.h"
11 | #include
12 | #include
13 |
14 | #include "cacheflush.h"
15 |
16 | @interface Sub : TestRoot @end
17 | @implementation Sub @end
18 |
19 |
20 | int main()
21 | {
22 | TestRoot *sup = [TestRoot new];
23 | Sub *sub = [Sub new];
24 |
25 | // Fill method cache
26 | testassert(1 == [TestRoot classMethod]);
27 | testassert(1 == [sup instanceMethod]);
28 | testassert(1 == [TestRoot classMethod]);
29 | testassert(1 == [sup instanceMethod]);
30 |
31 | testassert(1 == [Sub classMethod]);
32 | testassert(1 == [sub instanceMethod]);
33 | testassert(1 == [Sub classMethod]);
34 | testassert(1 == [sub instanceMethod]);
35 |
36 | // Dynamically load a category
37 | dlopen("cacheflush2.dylib", 0);
38 |
39 | // Make sure old cache results are gone
40 | testassert(2 == [TestRoot classMethod]);
41 | testassert(2 == [sup instanceMethod]);
42 |
43 | testassert(2 == [Sub classMethod]);
44 | testassert(2 == [sub instanceMethod]);
45 |
46 | // Dynamically load another category
47 | dlopen("cacheflush3.dylib", 0);
48 |
49 | // Make sure old cache results are gone
50 | testassert(3 == [TestRoot classMethod]);
51 | testassert(3 == [sup instanceMethod]);
52 |
53 | testassert(3 == [Sub classMethod]);
54 | testassert(3 == [sub instanceMethod]);
55 |
56 | // fixme test subclasses
57 |
58 | // fixme test objc_flush_caches(), class_addMethod(), class_addMethods()
59 |
60 | succeed(__FILE__);
61 | }
62 |
--------------------------------------------------------------------------------
/test/cacheflush0.m:
--------------------------------------------------------------------------------
1 | #include "cacheflush.h"
2 | #include "testroot.i"
3 |
4 | @implementation TestRoot(cat)
5 | +(int)classMethod { return 1; }
6 | -(int)instanceMethod { return 1; }
7 | @end
8 |
--------------------------------------------------------------------------------
/test/cacheflush2.m:
--------------------------------------------------------------------------------
1 | #include "cacheflush.h"
2 |
3 | @implementation TestRoot (Category2)
4 | +(int)classMethod { return 2; }
5 | -(int)instanceMethod { return 2; }
6 | @end
7 |
--------------------------------------------------------------------------------
/test/cacheflush3.m:
--------------------------------------------------------------------------------
1 | #include "cacheflush.h"
2 |
3 | @implementation TestRoot (Category3)
4 | +(int)classMethod { return 3; }
5 | -(int)instanceMethod { return 3; }
6 | @end
7 |
--------------------------------------------------------------------------------
/test/category.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -Wl,-no_objc_category_merging
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 | #include
7 |
8 | static int state = 0;
9 |
10 | @interface Super : TestRoot @end
11 | @implementation Super
12 | -(void)instancemethod { fail("-instancemethod not overridden by category"); }
13 | +(void)method { fail("+method not overridden by category"); }
14 | @end
15 |
16 | @interface Super (Category) @end
17 | @implementation Super (Category)
18 | +(void)method {
19 | testprintf("in [Super(Category) method]\n");
20 | testassert(self == [Super class]);
21 | testassert(state == 0);
22 | state = 1;
23 | }
24 | -(void)instancemethod {
25 | testprintf("in [Super(Category) instancemethod]\n");
26 | testassert(object_getClass(self) == [Super class]);
27 | testassert(state == 1);
28 | state = 2;
29 | }
30 | @end
31 |
32 | @interface Super (PropertyCategory)
33 | @property int i;
34 | @end
35 | @implementation Super (PropertyCategory)
36 | - (int)i { return 0; }
37 | - (void)setI:(int)value { (void)value; }
38 | @end
39 |
40 | // rdar://5086110 memory smasher in category with class method and property
41 | @interface Super (r5086110)
42 | @property int property5086110;
43 | @end
44 | @implementation Super (r5086110)
45 | +(void)method5086110 {
46 | fail("method method5086110 called!");
47 | }
48 | - (int)property5086110 { fail("property5086110 called!"); return 0; }
49 | - (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; }
50 | @end
51 |
52 |
53 | @interface PropertyClass : Super {
54 | int q;
55 | }
56 | @property(readonly) int q;
57 | @end
58 | @implementation PropertyClass
59 | @synthesize q;
60 | @end
61 |
62 | @interface PropertyClass (PropertyCategory)
63 | @property int q;
64 | @end
65 | @implementation PropertyClass (PropertyCategory)
66 | @dynamic q;
67 | @end
68 |
69 |
70 | int main()
71 | {
72 | // methods introduced by category
73 | state = 0;
74 | [Super method];
75 | [[Super new] instancemethod];
76 | testassert(state == 2);
77 |
78 | // property introduced by category
79 | objc_property_t p = class_getProperty([Super class], "i");
80 | testassert(p);
81 | testassert(0 == strcmp(property_getName(p), "i"));
82 | testassert(property_getAttributes(p));
83 |
84 | // methods introduced by category's property
85 | Method m;
86 | m = class_getInstanceMethod([Super class], @selector(i));
87 | testassert(m);
88 | m = class_getInstanceMethod([Super class], @selector(setI:));
89 | testassert(m);
90 |
91 | // class's property shadowed by category's property
92 | objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL);
93 | testassert(plist);
94 | testassert(plist[0]);
95 | testassert(0 == strcmp(property_getName(plist[0]), "q"));
96 | testassert(0 == strcmp(property_getAttributes(plist[0]), "Ti,D"));
97 | testassert(plist[1]);
98 | testassert(0 == strcmp(property_getName(plist[1]), "q"));
99 | testassert(0 == strcmp(property_getAttributes(plist[1]), "Ti,R,Vq"));
100 | testassert(!plist[2]);
101 | free(plist);
102 |
103 | succeed(__FILE__);
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/test/classgetclass.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #import
7 |
8 | @interface Foo:NSObject
9 | @end
10 | @implementation Foo
11 | @end
12 |
13 | int main()
14 | {
15 | #if __OBJC2__
16 | testassert(gdb_class_getClass([Foo class]) == [Foo class]);
17 | #endif
18 |
19 | succeed(__FILE__);
20 | }
21 |
--------------------------------------------------------------------------------
/test/classname.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 | #include
7 |
8 | @interface Fake : TestRoot @end
9 | @implementation Fake @end
10 |
11 | int main()
12 | {
13 | TestRoot *obj = [TestRoot new];
14 | Class __unsafe_unretained * buf = (Class *)objc_unretainedPointer(obj);
15 | *buf = [Fake class];
16 |
17 | testassert(object_getClass(obj) == [Fake class]);
18 | testassert(object_setClass(obj, [TestRoot class]) == [Fake class]);
19 | testassert(object_getClass(obj) == [TestRoot class]);
20 | testassert(object_setClass(nil, [TestRoot class]) == nil);
21 |
22 | testassert(malloc_size(buf) >= sizeof(id));
23 | bzero(buf, malloc_size(buf));
24 | testassert(object_setClass(obj, [TestRoot class]) == nil);
25 |
26 | testassert(object_getClass(obj) == [TestRoot class]);
27 | testassert(object_getClass([TestRoot class]) == object_getClass([TestRoot class]));
28 | testassert(object_getClass(nil) == Nil);
29 |
30 | testassert(0 == strcmp(object_getClassName(obj), "TestRoot"));
31 | testassert(0 == strcmp(object_getClassName([TestRoot class]), "TestRoot"));
32 | testassert(0 == strcmp(object_getClassName(nil), "nil"));
33 |
34 | testassert(0 == strcmp(class_getName([TestRoot class]), "TestRoot"));
35 | testassert(0 == strcmp(class_getName(object_getClass([TestRoot class])), "TestRoot"));
36 | testassert(0 == strcmp(class_getName(nil), "nil"));
37 |
38 | succeed(__FILE__);
39 | }
40 |
--------------------------------------------------------------------------------
/test/classversion.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | int main()
8 | {
9 | Class cls = [TestRoot class];
10 | testassert(class_getVersion(cls) == 0);
11 | testassert(class_getVersion(object_getClass(cls)) > 5);
12 | class_setVersion(cls, 100);
13 | testassert(class_getVersion(cls) == 100);
14 |
15 | testassert(class_getVersion(Nil) == 0);
16 | class_setVersion(Nil, 100);
17 |
18 | succeed(__FILE__);
19 | }
20 |
--------------------------------------------------------------------------------
/test/concurrentcat_category.m:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #import
4 |
5 | @interface TargetClass : NSObject
6 | @end
7 |
8 | @interface TargetClass(LoadedMethods)
9 | - (void) m0;
10 | - (void) m1;
11 | - (void) m2;
12 | - (void) m3;
13 | - (void) m4;
14 | - (void) m5;
15 | - (void) m6;
16 | - (void) m7;
17 | - (void) m8;
18 | - (void) m9;
19 | - (void) m10;
20 | - (void) m11;
21 | - (void) m12;
22 | - (void) m13;
23 | - (void) m14;
24 | - (void) m15;
25 | @end
26 |
27 | @interface TN:TargetClass
28 | @end
29 |
30 | @implementation TN
31 | - (void) m1 { [super m1]; }
32 | - (void) m3 { [self m1]; }
33 |
34 | - (void) m2
35 | {
36 | [self willChangeValueForKey: @"m4"];
37 | [self didChangeValueForKey: @"m4"];
38 | }
39 |
40 | - (void)observeValueForKeyPath:(NSString *) keyPath
41 | ofObject:(id)object
42 | change:(NSDictionary *)change
43 | context:(void *)context
44 | {
45 | // suppress warning
46 | keyPath = nil;
47 | object = nil;
48 | change = nil;
49 | context = NULL;
50 | }
51 | @end
52 |
53 | @implementation TargetClass(LoadedMethods)
54 | - (void) m0 { ; }
55 | - (void) m1 { ; }
56 | - (void) m2 { ; }
57 | - (void) m3 { ; }
58 | - (void) m4 { ; }
59 | - (void) m5 { ; }
60 | - (void) m6 { ; }
61 | - (void) m7 { ; }
62 | - (void) m8 { ; }
63 | - (void) m9 { ; }
64 | - (void) m10 { ; }
65 | - (void) m11 { ; }
66 | - (void) m12 { ; }
67 | - (void) m13 { ; }
68 | - (void) m14 { ; }
69 | - (void) m15 { ; }
70 | @end
71 |
--------------------------------------------------------------------------------
/test/copyIvarList.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #include
7 |
8 | OBJC_ROOT_CLASS
9 | @interface SuperIvars {
10 | id isa;
11 | int ivar1;
12 | int ivar2;
13 | } @end
14 | @implementation SuperIvars @end
15 |
16 | @interface SubIvars : SuperIvars {
17 | int ivar3;
18 | int ivar4;
19 | } @end
20 | @implementation SubIvars @end
21 |
22 | OBJC_ROOT_CLASS
23 | @interface FourIvars {
24 | int ivar1;
25 | int ivar2;
26 | int ivar3;
27 | int ivar4;
28 | } @end
29 | @implementation FourIvars @end
30 |
31 | OBJC_ROOT_CLASS
32 | @interface NoIvars { } @end
33 | @implementation NoIvars @end
34 |
35 | static int isNamed(Ivar iv, const char *name)
36 | {
37 | return (0 == strcmp(name, ivar_getName(iv)));
38 | }
39 |
40 | int main()
41 | {
42 | Ivar *ivars;
43 | unsigned int count;
44 | Class cls;
45 |
46 | cls = objc_getClass("SubIvars");
47 | testassert(cls);
48 |
49 | count = 100;
50 | ivars = class_copyIvarList(cls, &count);
51 | testassert(ivars);
52 | testassert(count == 2);
53 | testassert(isNamed(ivars[0], "ivar3"));
54 | testassert(isNamed(ivars[1], "ivar4"));
55 | // ivars[] should be null-terminated
56 | testassert(ivars[2] == NULL);
57 | free(ivars);
58 |
59 | cls = objc_getClass("SuperIvars");
60 | testassert(cls);
61 |
62 | count = 100;
63 | ivars = class_copyIvarList(cls, &count);
64 | testassert(ivars);
65 | testassert(count == 3);
66 | testassert(isNamed(ivars[0], "isa"));
67 | testassert(isNamed(ivars[1], "ivar1"));
68 | testassert(isNamed(ivars[2], "ivar2"));
69 | // ivars[] should be null-terminated
70 | testassert(ivars[3] == NULL);
71 | free(ivars);
72 |
73 | // Check null-termination - this ivar list block would be 16 bytes
74 | // if it weren't for the terminator
75 | cls = objc_getClass("FourIvars");
76 | testassert(cls);
77 |
78 | count = 100;
79 | ivars = class_copyIvarList(cls, &count);
80 | testassert(ivars);
81 | testassert(count == 4);
82 | testassert(malloc_size(ivars) >= 5 * sizeof(Ivar));
83 | testassert(ivars[3] != NULL);
84 | testassert(ivars[4] == NULL);
85 | free(ivars);
86 |
87 | // Check NULL count parameter
88 | ivars = class_copyIvarList(cls, NULL);
89 | testassert(ivars);
90 | testassert(ivars[4] == NULL);
91 | testassert(ivars[3] != NULL);
92 | free(ivars);
93 |
94 | // Check NULL class parameter
95 | count = 100;
96 | ivars = class_copyIvarList(NULL, &count);
97 | testassert(!ivars);
98 | testassert(count == 0);
99 |
100 | // Check NULL class and count
101 | ivars = class_copyIvarList(NULL, NULL);
102 | testassert(!ivars);
103 |
104 | // Check class with no ivars
105 | cls = objc_getClass("NoIvars");
106 | testassert(cls);
107 |
108 | count = 100;
109 | ivars = class_copyIvarList(cls, &count);
110 | testassert(!ivars);
111 | testassert(count == 0);
112 |
113 | succeed(__FILE__);
114 | return 0;
115 | }
116 |
--------------------------------------------------------------------------------
/test/copyPropertyList.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #include
7 |
8 | OBJC_ROOT_CLASS
9 | @interface SuperProps { id isa; int prop1; int prop2; }
10 | @property int prop1;
11 | @property int prop2;
12 | @end
13 | @implementation SuperProps
14 | @synthesize prop1;
15 | @synthesize prop2;
16 | @end
17 |
18 | @interface SubProps : SuperProps { int prop3; int prop4; }
19 | @property int prop3;
20 | @property int prop4;
21 | @end
22 | @implementation SubProps
23 | @synthesize prop3;
24 | @synthesize prop4;
25 | @end
26 |
27 | OBJC_ROOT_CLASS
28 | @interface FourProps { int prop1; int prop2; int prop3; int prop4; }
29 | @property int prop1;
30 | @property int prop2;
31 | @property int prop3;
32 | @property int prop4;
33 | @end
34 | @implementation FourProps
35 | @synthesize prop1;
36 | @synthesize prop2;
37 | @synthesize prop3;
38 | @synthesize prop4;
39 | @end
40 |
41 | OBJC_ROOT_CLASS
42 | @interface NoProps @end
43 | @implementation NoProps @end
44 |
45 | static int isNamed(objc_property_t p, const char *name)
46 | {
47 | return (0 == strcmp(name, property_getName(p)));
48 | }
49 |
50 | int main()
51 | {
52 | objc_property_t *props;
53 | unsigned int count;
54 | Class cls;
55 |
56 | cls = objc_getClass("SubProps");
57 | testassert(cls);
58 |
59 | count = 100;
60 | props = class_copyPropertyList(cls, &count);
61 | testassert(props);
62 | testassert(count == 2);
63 | testassert((isNamed(props[0], "prop3") && isNamed(props[1], "prop4")) ||
64 | (isNamed(props[1], "prop3") && isNamed(props[0], "prop4")));
65 | // props[] should be null-terminated
66 | testassert(props[2] == NULL);
67 | free(props);
68 |
69 | cls = objc_getClass("SuperProps");
70 | testassert(cls);
71 |
72 | count = 100;
73 | props = class_copyPropertyList(cls, &count);
74 | testassert(props);
75 | testassert(count == 2);
76 | testassert((isNamed(props[0], "prop1") && isNamed(props[1], "prop2")) ||
77 | (isNamed(props[1], "prop1") && isNamed(props[0], "prop2")));
78 | // props[] should be null-terminated
79 | testassert(props[2] == NULL);
80 | free(props);
81 |
82 | // Check null-termination - this property list block would be 16 bytes
83 | // if it weren't for the terminator
84 | cls = objc_getClass("FourProps");
85 | testassert(cls);
86 |
87 | count = 100;
88 | props = class_copyPropertyList(cls, &count);
89 | testassert(props);
90 | testassert(count == 4);
91 | testassert(malloc_size(props) >= 5 * sizeof(objc_property_t));
92 | testassert(props[3] != NULL);
93 | testassert(props[4] == NULL);
94 | free(props);
95 |
96 | // Check NULL count parameter
97 | props = class_copyPropertyList(cls, NULL);
98 | testassert(props);
99 | testassert(props[4] == NULL);
100 | testassert(props[3] != NULL);
101 | free(props);
102 |
103 | // Check NULL class parameter
104 | count = 100;
105 | props = class_copyPropertyList(NULL, &count);
106 | testassert(!props);
107 | testassert(count == 0);
108 |
109 | // Check NULL class and count
110 | props = class_copyPropertyList(NULL, NULL);
111 | testassert(!props);
112 |
113 | // Check class with no properties
114 | cls = objc_getClass("NoProps");
115 | testassert(cls);
116 |
117 | count = 100;
118 | props = class_copyPropertyList(cls, &count);
119 | testassert(!props);
120 | testassert(count == 0);
121 |
122 | succeed(__FILE__);
123 | return 0;
124 | }
125 |
--------------------------------------------------------------------------------
/test/createInstance.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc,gc
2 | // TEST_CFLAGS -Wno-deprecated-declarations
3 |
4 | #import
5 | #import
6 | #ifndef OBJC_NO_GC
7 | #include
8 | #else
9 | static BOOL auto_zone_is_valid_pointer(void *a, void *b) { return a||b; }
10 | #endif
11 | #include "test.h"
12 |
13 | OBJC_ROOT_CLASS
14 | @interface Super { @public id isa; } @end
15 | @implementation Super
16 | +(void) initialize { }
17 | +(Class) class { return self; }
18 | @end
19 |
20 | @interface Sub : Super { int array[128]; } @end
21 | @implementation Sub @end
22 |
23 | int main()
24 | {
25 | Super *s;
26 |
27 | s = class_createInstance([Super class], 0);
28 | testassert(s);
29 | testassert(object_getClass(s) == [Super class]);
30 | testassert(malloc_size(s) >= class_getInstanceSize([Super class]));
31 | if (objc_collectingEnabled()) testassert(auto_zone_is_valid_pointer(objc_collectableZone(), s));
32 |
33 | object_dispose(s);
34 |
35 | s = class_createInstance([Sub class], 0);
36 | testassert(s);
37 | testassert(object_getClass(s) == [Sub class]);
38 | testassert(malloc_size(s) >= class_getInstanceSize([Sub class]));
39 | if (objc_collectingEnabled()) testassert(auto_zone_is_valid_pointer(objc_collectableZone(), s));
40 |
41 | object_dispose(s);
42 |
43 | s = class_createInstance([Super class], 100);
44 | testassert(s);
45 | testassert(object_getClass(s) == [Super class]);
46 | testassert(malloc_size(s) >= class_getInstanceSize([Super class]) + 100);
47 | if (objc_collectingEnabled()) testassert(auto_zone_is_valid_pointer(objc_collectableZone(), s));
48 |
49 | object_dispose(s);
50 |
51 | s = class_createInstance([Sub class], 100);
52 | testassert(s);
53 | testassert(object_getClass(s) == [Sub class]);
54 | testassert(malloc_size(s) >= class_getInstanceSize([Sub class]) + 100);
55 | if (objc_collectingEnabled()) testassert(auto_zone_is_valid_pointer(objc_collectableZone(), s));
56 |
57 | object_dispose(s);
58 |
59 | s = class_createInstance(Nil, 0);
60 | testassert(!s);
61 |
62 | succeed(__FILE__);
63 | }
64 |
--------------------------------------------------------------------------------
/test/customrr-cat1.m:
--------------------------------------------------------------------------------
1 | @interface InheritingSubCat @end
2 |
3 | @interface InheritingSubCat (NonClobberingCategory) @end
4 |
5 | @implementation InheritingSubCat (NonClobberingCategory)
6 | -(id) unrelatedMethod { return self; }
7 | @end
8 |
--------------------------------------------------------------------------------
/test/customrr-cat2.m:
--------------------------------------------------------------------------------
1 | @interface InheritingSubCat @end
2 |
3 | @interface InheritingSubCat (ClobberingCategory) @end
4 |
5 | @implementation InheritingSubCat (ClobberingCategory)
6 | -(int) retainCount { return 1; }
7 | @end
8 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-awz.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-awz.out -DSWIZZLE_AWZ=1
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | objc\[\d+\]: CUSTOM AWZ: NSObject \(meta\)
12 | OK: customrr-nsobject-awz.out
13 | END
14 |
15 | */
16 |
17 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-none.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-none.out
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | OK: customrr-nsobject-none.out
12 | END
13 |
14 | */
15 |
16 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-rr.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-rr.out -DSWIZZLE_RELEASE=1
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | objc\[\d+\]: CUSTOM RR: NSObject
12 | OK: customrr-nsobject-rr.out
13 | END
14 |
15 | */
16 |
17 |
--------------------------------------------------------------------------------
/test/customrr-nsobject-rrawz.m:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | TEST_CONFIG MEM=mrc
4 | TEST_ENV OBJC_PRINT_CUSTOM_RR=YES OBJC_PRINT_CUSTOM_AWZ=YES
5 |
6 | TEST_BUILD
7 | $C{COMPILE} $DIR/customrr-nsobject.m -o customrr-nsobject-rrawz.out -DSWIZZLE_RELEASE=1 -DSWIZZLE_AWZ=1
8 | END
9 |
10 | TEST_RUN_OUTPUT
11 | objc\[\d+\]: CUSTOM AWZ: NSObject \(meta\)
12 | objc\[\d+\]: CUSTOM RR: NSObject
13 | OK: customrr-nsobject-rrawz.out
14 | END
15 |
16 | */
17 |
18 |
--------------------------------------------------------------------------------
/test/customrr2.m:
--------------------------------------------------------------------------------
1 | // These options must match customrr.m
2 | // TEST_CONFIG MEM=mrc
3 | /*
4 | TEST_BUILD
5 | $C{COMPILE} $DIR/customrr.m -fvisibility=default -o customrr2.out -DTEST_EXCHANGEIMPLEMENTATIONS=1
6 | $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/customrr-cat1.m -o customrr-cat1.dylib
7 | $C{COMPILE} -undefined dynamic_lookup -dynamiclib $DIR/customrr-cat2.m -o customrr-cat2.dylib
8 | END
9 | */
10 |
--------------------------------------------------------------------------------
/test/definitions.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | // DO NOT include anything else here
4 | #include
5 | // DO NOT include anything else here
6 | Class c = Nil;
7 | SEL s;
8 | IMP i;
9 | id o = nil;
10 | BOOL b = YES;
11 | BOOL b2 = NO;
12 | #if !__has_feature(objc_arc)
13 | __strong void *p;
14 | #endif
15 | id __unsafe_unretained u;
16 | id __weak w;
17 |
18 | void fn(void) __unused;
19 | void fn(void) {
20 | id __autoreleasing a __unused;
21 | }
22 |
23 | #if __llvm__ && !__clang__
24 | // llvm-gcc defines _NSConcreteGlobalBlock wrong
25 | #else
26 | // rdar://10118972 wrong type inference for blocks returning YES and NO
27 | BOOL (^block1)(void) = ^{ return YES; };
28 | BOOL (^block2)(void) = ^{ return NO; };
29 | #endif
30 |
31 | #include "test.h"
32 |
33 | int main()
34 | {
35 | testassert(YES);
36 | testassert(!NO);
37 | #if __cplusplus
38 | testwarn("rdar://12371870 -Wnull-conversion");
39 | testassert(!(bool)nil);
40 | testassert(!(bool)Nil);
41 | #else
42 | testassert(!nil);
43 | testassert(!Nil);
44 | #endif
45 |
46 | #if __has_feature(objc_bool)
47 | // YES[array] is disallowed for objc just as true[array] is for C++
48 | #else
49 | // this will fail if YES and NO do not have enough parentheses
50 | int array[2] = { 888, 999 };
51 | testassert(NO[array] == 888);
52 | testassert(YES[array] == 999);
53 | #endif
54 |
55 | succeed(__FILE__);
56 | }
57 |
--------------------------------------------------------------------------------
/test/designatedinit.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | /* TEST_BUILD_OUTPUT
3 | .*designatedinit.m:\d+:\d+: warning: designated initializer should only invoke a designated initializer on 'super'.*
4 | .*designatedinit.m:\d+:\d+: note: .*
5 | .*designatedinit.m:\d+:\d+: warning: method override for the designated initializer of the superclass '-init' not found.*
6 | .*NSObject.h:\d+:\d+: note: .*
7 | END */
8 |
9 | #define NS_ENFORCE_NSOBJECT_DESIGNATED_INITIALIZER 1
10 | #include "test.h"
11 | #include
12 |
13 | @interface C : NSObject
14 | -(id) initWithInt:(int)i NS_DESIGNATED_INITIALIZER;
15 | @end
16 |
17 | @implementation C
18 | -(id) initWithInt:(int)__unused i {
19 | return [self init];
20 | }
21 | @end
22 |
23 | int main()
24 | {
25 | succeed(__FILE__);
26 | }
27 |
--------------------------------------------------------------------------------
/test/duplicatedClasses.m:
--------------------------------------------------------------------------------
1 | // TEST_ENV OBJC_DEBUG_DUPLICATE_CLASSES=YES
2 | // TEST_CRASHES
3 | /*
4 | TEST_RUN_OUTPUT
5 | objc\[\d+\]: Class GKScore is implemented in both [^\s]+ and [^\s]+ One of the two will be used. Which one is undefined.
6 | CRASHED: SIG(ILL|TRAP)
7 | OR
8 | OK: duplicatedClasses.m
9 | END
10 | */
11 |
12 | #include "test.h"
13 | #include "testroot.i"
14 |
15 | @interface GKScore : TestRoot @end
16 | @implementation GKScore @end
17 |
18 | int main()
19 | {
20 | if (objc_collectingEnabled()) {
21 | testwarn("rdar://19042235 test disabled because GameKit is not GC");
22 | succeed(__FILE__);
23 | }
24 | void *dl = dlopen("/System/Library/Frameworks/GameKit.framework/GameKit", RTLD_LAZY);
25 | if (!dl) fail("couldn't open GameKit");
26 | fail("should have crashed already");
27 | }
28 |
--------------------------------------------------------------------------------
/test/evil-category-0.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_BUILD
5 | $C{COMPILE} $DIR/evil-category-0.m -dynamiclib -o libevil.dylib
6 | $C{COMPILE} $DIR/evil-main.m -x none -DNOT_EVIL libevil.dylib -o evil-category-0.out
7 | END
8 | */
9 |
10 | // NOT EVIL version
11 |
12 | #define EVIL_INSTANCE_METHOD 0
13 | #define EVIL_CLASS_METHOD 0
14 |
15 | #define OMIT_CAT 0
16 | #define OMIT_NL_CAT 0
17 |
18 | #include "evil-category-def.m"
19 |
--------------------------------------------------------------------------------
/test/evil-category-00.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-category-00.m $DIR/evil-main.m -o evil-category-00.out
9 | END
10 |
11 | TEST_RUN_OUTPUT
12 | CRASHED: SIGSEGV
13 | END
14 | */
15 |
16 | // NOT EVIL version: apps are allowed through (then crash in +load)
17 |
18 | #define EVIL_INSTANCE_METHOD 1
19 | #define EVIL_CLASS_METHOD 1
20 |
21 | #define OMIT_CAT 0
22 | #define OMIT_NL_CAT 0
23 |
24 | #include "evil-category-def.m"
25 |
--------------------------------------------------------------------------------
/test/evil-category-000.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_BUILD
5 | $C{COMPILE} $DIR/evil-category-000.m -dynamiclib -o libevil.dylib
6 | $C{COMPILE} $DIR/evil-main.m -x none -DNOT_EVIL libevil.dylib -o evil-category-000.out
7 | END
8 | */
9 |
10 | // NOT EVIL version: category omitted from all lists
11 |
12 | #define EVIL_INSTANCE_METHOD 1
13 | #define EVIL_CLASS_METHOD 1
14 |
15 | #define OMIT_CAT 1
16 | #define OMIT_NL_CAT 1
17 |
18 | #include "evil-category-def.m"
19 |
--------------------------------------------------------------------------------
/test/evil-category-1.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-category-1.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-category-1.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_INSTANCE_METHOD 1
19 | #define EVIL_CLASS_METHOD 0
20 |
21 | #define OMIT_CAT 0
22 | #define OMIT_NL_CAT 0
23 |
24 | #include "evil-category-def.m"
25 |
--------------------------------------------------------------------------------
/test/evil-category-2.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-category-2.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-category-2.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_INSTANCE_METHOD 0
19 | #define EVIL_CLASS_METHOD 1
20 |
21 | #define OMIT_CAT 0
22 | #define OMIT_NL_CAT 0
23 |
24 | #include "evil-category-def.m"
25 |
--------------------------------------------------------------------------------
/test/evil-category-3.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-category-3.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-category-3.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_INSTANCE_METHOD 0
19 | #define EVIL_CLASS_METHOD 1
20 |
21 | #define OMIT_CAT 1
22 | #define OMIT_NL_CAT 0
23 |
24 | #include "evil-category-def.m"
25 |
--------------------------------------------------------------------------------
/test/evil-category-4.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-category-4.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-category-4.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_INSTANCE_METHOD 0
19 | #define EVIL_CLASS_METHOD 1
20 |
21 | #define OMIT_CAT 0
22 | #define OMIT_NL_CAT 1
23 |
24 | #include "evil-category-def.m"
25 |
--------------------------------------------------------------------------------
/test/evil-category-def.m:
--------------------------------------------------------------------------------
1 |
2 | #if __OBJC2__
3 |
4 | #include
5 |
6 | #if __LP64__
7 | # define PTR " .quad "
8 | #else
9 | # define PTR " .long "
10 | #endif
11 |
12 | #define str(x) #x
13 | #define str2(x) str(x)
14 |
15 | __BEGIN_DECLS
16 | void nop(void) { }
17 | __END_DECLS
18 |
19 | asm(
20 | ".section __DATA,__objc_data \n"
21 | ".align 3 \n"
22 | "L_category: \n"
23 | PTR "L_cat_name \n"
24 | PTR "_OBJC_CLASS_$_NSObject \n"
25 | #if EVIL_INSTANCE_METHOD
26 | PTR "L_evil_methods \n"
27 | #else
28 | PTR "L_good_methods \n"
29 | #endif
30 | #if EVIL_CLASS_METHOD
31 | PTR "L_evil_methods \n"
32 | #else
33 | PTR "L_good_methods \n"
34 | #endif
35 | PTR "0 \n"
36 | PTR "0 \n"
37 |
38 | "L_evil_methods: \n"
39 | ".long 24 \n"
40 | ".long 1 \n"
41 | PTR "L_load \n"
42 | PTR "L_load \n"
43 | PTR str2(SHARED_REGION_BASE+SHARED_REGION_SIZE-PAGE_MAX_SIZE) " \n"
44 |
45 | "L_good_methods: \n"
46 | ".long 24 \n"
47 | ".long 1 \n"
48 | PTR "L_load \n"
49 | PTR "L_load \n"
50 | PTR "_nop \n"
51 |
52 | ".cstring \n"
53 | "L_cat_name: .ascii \"Evil\\0\" \n"
54 | "L_load: .ascii \"load\\0\" \n"
55 |
56 | ".section __DATA,__objc_catlist \n"
57 | #if !OMIT_CAT
58 | PTR "L_category \n"
59 | #endif
60 |
61 | ".section __DATA,__objc_nlcatlist \n"
62 | #if !OMIT_NL_CAT
63 | PTR "L_category \n"
64 | #endif
65 |
66 | ".text \n"
67 | );
68 |
69 | // __OBJC2__
70 | #endif
71 |
72 | void fn(void) { }
73 |
--------------------------------------------------------------------------------
/test/evil-class-0.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_BUILD
5 | $C{COMPILE} $DIR/evil-class-0.m -dynamiclib -o libevil.dylib
6 | $C{COMPILE} $DIR/evil-main.m -x none -DNOT_EVIL libevil.dylib -o evil-class-0.out
7 | END
8 | */
9 |
10 | // NOT EVIL version
11 |
12 | #define EVIL_SUPER 0
13 | #define EVIL_SUPER_META 0
14 | #define EVIL_SUB 0
15 | #define EVIL_SUB_META 0
16 |
17 | #define OMIT_SUPER 0
18 | #define OMIT_NL_SUPER 0
19 | #define OMIT_SUB 0
20 | #define OMIT_NL_SUB 0
21 |
22 | #include "evil-class-def.m"
23 |
--------------------------------------------------------------------------------
/test/evil-class-00.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-class-00.m $DIR/evil-main.m -o evil-class-00.out
9 | END
10 |
11 | TEST_RUN_OUTPUT
12 | CRASHED: SIGSEGV
13 | END
14 | */
15 |
16 | // NOT EVIL version: apps are allowed through (then crash in +load)
17 |
18 | #define EVIL_SUPER 0
19 | #define EVIL_SUPER_META 1
20 | #define EVIL_SUB 0
21 | #define EVIL_SUB_META 0
22 |
23 | #define OMIT_SUPER 1
24 | #define OMIT_NL_SUPER 1
25 | #define OMIT_SUB 1
26 | #define OMIT_NL_SUB 0
27 |
28 | #include "evil-class-def.m"
29 |
--------------------------------------------------------------------------------
/test/evil-class-000.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_BUILD
5 | $C{COMPILE} $DIR/evil-class-000.m -dynamiclib -o libevil.dylib
6 | $C{COMPILE} $DIR/evil-main.m -x none -DNOT_EVIL libevil.dylib -o evil-class-000.out
7 | END
8 | */
9 |
10 | // NOT EVIL version: all classes omitted from all lists
11 |
12 | #define EVIL_SUPER 1
13 | #define EVIL_SUPER_META 1
14 | #define EVIL_SUB 1
15 | #define EVIL_SUB_META 1
16 |
17 | #define OMIT_SUPER 1
18 | #define OMIT_NL_SUPER 1
19 | #define OMIT_SUB 1
20 | #define OMIT_NL_SUB 1
21 |
22 | #include "evil-class-def.m"
23 |
--------------------------------------------------------------------------------
/test/evil-class-1.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-class-1.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-class-1.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_SUPER 1
19 | #define EVIL_SUPER_META 0
20 | #define EVIL_SUB 0
21 | #define EVIL_SUB_META 0
22 |
23 | #define OMIT_SUPER 0
24 | #define OMIT_NL_SUPER 0
25 | #define OMIT_SUB 0
26 | #define OMIT_NL_SUB 0
27 |
28 | #include "evil-class-def.m"
29 |
--------------------------------------------------------------------------------
/test/evil-class-2.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-class-2.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-class-2.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_SUPER 0
19 | #define EVIL_SUPER_META 1
20 | #define EVIL_SUB 0
21 | #define EVIL_SUB_META 0
22 |
23 | #define OMIT_SUPER 0
24 | #define OMIT_NL_SUPER 0
25 | #define OMIT_SUB 0
26 | #define OMIT_NL_SUB 0
27 |
28 | #include "evil-class-def.m"
29 |
--------------------------------------------------------------------------------
/test/evil-class-3.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-class-3.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-class-3.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_SUPER 0
19 | #define EVIL_SUPER_META 0
20 | #define EVIL_SUB 1
21 | #define EVIL_SUB_META 0
22 |
23 | #define OMIT_SUPER 0
24 | #define OMIT_NL_SUPER 0
25 | #define OMIT_SUB 0
26 | #define OMIT_NL_SUB 0
27 |
28 | #include "evil-class-def.m"
29 |
--------------------------------------------------------------------------------
/test/evil-class-4.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_CONFIG OS=iphoneos
5 | TEST_CRASHES
6 |
7 | TEST_BUILD
8 | $C{COMPILE} $DIR/evil-class-4.m -dynamiclib -o libevil.dylib
9 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-class-4.out
10 | END
11 |
12 | TEST_RUN_OUTPUT
13 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
14 | CRASHED: SIG(ILL|TRAP)
15 | END
16 | */
17 |
18 | #define EVIL_SUPER 0
19 | #define EVIL_SUPER_META 0
20 | #define EVIL_SUB 0
21 | #define EVIL_SUB_META 1
22 |
23 | #define OMIT_SUPER 0
24 | #define OMIT_NL_SUPER 0
25 | #define OMIT_SUB 0
26 | #define OMIT_NL_SUB 0
27 |
28 | #include "evil-class-def.m"
29 |
--------------------------------------------------------------------------------
/test/evil-class-5.m:
--------------------------------------------------------------------------------
1 | /*
2 | rdar://8553305
3 |
4 | TEST_DISABLED rdar://19200100
5 |
6 | TEST_CONFIG OS=iphoneos
7 | TEST_CRASHES
8 |
9 | TEST_BUILD
10 | $C{COMPILE} $DIR/evil-class-5.m -dynamiclib -o libevil.dylib
11 | $C{COMPILE} $DIR/evil-main.m -x none libevil.dylib -o evil-class-5.out
12 | END
13 |
14 | TEST_RUN_OUTPUT
15 | objc\[\d+\]: bad method implementation \(0x[0-9a-f]+ at 0x[0-9a-f]+\)
16 | CRASHED: SIG(ILL|TRAP)
17 | END
18 | */
19 |
20 | #define EVIL_SUPER 0
21 | #define EVIL_SUPER_META 1
22 | #define EVIL_SUB 0
23 | #define EVIL_SUB_META 0
24 |
25 | #define OMIT_SUPER 1
26 | #define OMIT_NL_SUPER 1
27 | #define OMIT_SUB 1
28 | #define OMIT_NL_SUB 0
29 |
30 | #include "evil-class-def.m"
31 |
--------------------------------------------------------------------------------
/test/evil-main.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | extern void fn(void);
4 |
5 | int main(int argc __unused, char **argv)
6 | {
7 | fn();
8 |
9 | #if TARGET_OS_EMBEDDED && !defined(NOT_EVIL)
10 | #pragma unused (argv)
11 | fail("All that is necessary for the triumph of evil is that good men do nothing.");
12 | #else
13 | succeed(basename(argv[0]));
14 | #endif
15 | }
16 |
--------------------------------------------------------------------------------
/test/forwardDefault.m:
--------------------------------------------------------------------------------
1 | /*
2 | no arc, rdar://11368528 confused by Foundation
3 | TEST_CONFIG MEM=mrc,gc
4 | TEST_CRASHES
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: \+\[NSObject fakeorama\]: unrecognized selector sent to instance 0x[0-9a-fA-F]+ \(no message forward handler is installed\)
7 | CRASHED: SIG(ILL|TRAP)
8 | OR
9 | not OBJC2
10 | objc\[\d+\]: NSObject: Does not recognize selector forward:: \(while forwarding fakeorama\)
11 | CRASHED: SIG(ILL|TRAP)
12 | END
13 | */
14 |
15 | #include "test.h"
16 |
17 | #include
18 |
19 | @interface NSObject (Fake)
20 | -(void)fakeorama;
21 | @end
22 |
23 | int main()
24 | {
25 | #if !__OBJC2__
26 | fprintf(stderr, "not OBJC2\n");
27 | #endif
28 | [NSObject fakeorama];
29 | fail("should have crashed");
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/test/forwardDefaultStret.m:
--------------------------------------------------------------------------------
1 | /*
2 | no arc, rdar://11368528 confused by Foundation
3 | TEST_CONFIG MEM=mrc,gc
4 | TEST_CRASHES
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: \+\[NSObject fakeorama\]: unrecognized selector sent to instance 0x[0-9a-fA-F]+ \(no message forward handler is installed\)
7 | CRASHED: SIG(ILL|TRAP)
8 | OR
9 | not OBJC2
10 | objc\[\d+\]: NSObject: Does not recognize selector forward:: \(while forwarding fakeorama\)
11 | CRASHED: SIG(ILL|TRAP)
12 | END
13 | */
14 |
15 | #include "test.h"
16 |
17 | #include
18 |
19 | @interface NSObject (Fake)
20 | -(struct stret)fakeorama;
21 | @end
22 |
23 | int main()
24 | {
25 | #if !__OBJC2__
26 | fprintf(stderr, "not OBJC2\n");
27 | #endif
28 | [NSObject fakeorama];
29 | fail("should have crashed");
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/test/future.h:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | @interface Sub1 : TestRoot
4 | +(int)method;
5 | +(Class)classref;
6 | @end
7 |
8 | @interface Sub2 : TestRoot
9 | +(int)method;
10 | +(Class)classref;
11 | @end
12 |
13 | @interface SubSub1 : Sub1 @end
14 |
15 | @interface SubSub2 : Sub2 @end
16 |
--------------------------------------------------------------------------------
/test/future.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/future0.m -o future0.dylib -dynamiclib
4 | $C{COMPILE} $DIR/future2.m -x none future0.dylib -o future2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/future.m -x none future0.dylib -o future.out
6 | END
7 | */
8 |
9 | #include "test.h"
10 |
11 | #if __has_feature(objc_arc)
12 |
13 | int main()
14 | {
15 | testwarn("rdar://10041403 future class API is not ARC-compatible");
16 | succeed(__FILE__);
17 | }
18 |
19 |
20 | #else
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include "future.h"
27 |
28 | @implementation Sub2
29 | +(int)method {
30 | return 2;
31 | }
32 | +(Class)classref {
33 | return [Sub2 class];
34 | }
35 | @end
36 |
37 | @implementation SubSub2
38 | +(int)method {
39 | return 1 + [super method];
40 | }
41 | @end
42 |
43 | int main()
44 | {
45 | Class oldTestRoot;
46 | Class oldSub1;
47 | Class newSub1;
48 |
49 | // objc_getFutureClass with existing class
50 | oldTestRoot = objc_getFutureClass("TestRoot");
51 | testassert(oldTestRoot == [TestRoot class]);
52 | testassert(! _class_isFutureClass(oldTestRoot));
53 |
54 | // objc_getFutureClass with missing class
55 | oldSub1 = objc_getFutureClass("Sub1");
56 | testassert(oldSub1);
57 | testassert(malloc_size(objc_unretainedPointer(oldSub1)) > 0);
58 | testassert(objc_getClass("Sub1") == Nil);
59 | testassert(_class_isFutureClass(oldSub1));
60 | testassert(0 == strcmp(class_getName(oldSub1), "Sub1"));
61 | testassert(object_getClass(oldSub1) == Nil); // CF expects this
62 |
63 | // objc_getFutureClass a second time
64 | testassert(oldSub1 == objc_getFutureClass("Sub1"));
65 |
66 | // Load class Sub1
67 | dlopen("future2.dylib", 0);
68 |
69 | // Verify use of future class
70 | newSub1 = objc_getClass("Sub1");
71 | testassert(oldSub1 == newSub1);
72 | testassert(newSub1 == [newSub1 classref]);
73 | testassert(newSub1 == class_getSuperclass(objc_getClass("SubSub1")));
74 | testassert(! _class_isFutureClass(newSub1));
75 |
76 | testassert(1 == [oldSub1 method]);
77 | testassert(1 == [newSub1 method]);
78 |
79 | succeed(__FILE__);
80 | }
81 |
82 | #endif
83 |
--------------------------------------------------------------------------------
/test/future0.m:
--------------------------------------------------------------------------------
1 | #include "future.h"
2 | #include "testroot.i"
3 |
--------------------------------------------------------------------------------
/test/future2.m:
--------------------------------------------------------------------------------
1 | #include "future.h"
2 |
3 |
4 | @implementation Sub1
5 | +(Class)classref {
6 | return [Sub1 class];
7 | }
8 | +(int)method {
9 | return 1;
10 | }
11 | @end
12 |
13 | @implementation SubSub1
14 | +(int)method {
15 | return 1 + [super method];
16 | }
17 | @end
18 |
--------------------------------------------------------------------------------
/test/gc-main.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | OBJC_ROOT_CLASS
4 | @interface Main @end
5 | @implementation Main @end
6 |
7 | int main(int argc __attribute__((unused)), char **argv)
8 | {
9 | succeed(basename(argv[0]));
10 | }
11 |
--------------------------------------------------------------------------------
/test/gc.c:
--------------------------------------------------------------------------------
1 | int GC(void) { return 42; }
2 |
--------------------------------------------------------------------------------
/test/gc.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | OBJC_ROOT_CLASS
4 | @interface GC @end
5 | @implementation GC @end
6 |
7 | // silence "no debug symbols in executable" warning
8 | void foo(void) { }
9 |
--------------------------------------------------------------------------------
/test/gcenforcer-nogc-1.m:
--------------------------------------------------------------------------------
1 | // gc-off app loading gc-off dylib: should work
2 |
3 | /*
4 | TEST_CONFIG MEM=mrc,arc OS=macosx
5 |
6 | TEST_BUILD
7 | $C{COMPILE_C} $DIR/gc.c -dynamiclib -o libnoobjc.dylib
8 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libnogc.dylib
9 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libsupportsgc.dylib -fobjc-gc
10 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.dylib -fobjc-gc-only
11 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.fake.dylib -fobjc-gc -install_name librequiresgc.dylib
12 |
13 | $C{COMPILE} $DIR/gc-main.m -x none libnogc.dylib -o gcenforcer-nogc-1.out
14 | END
15 | */
16 |
--------------------------------------------------------------------------------
/test/gcenforcer-nogc-2.m:
--------------------------------------------------------------------------------
1 | // gc-on app loading gc-off dylib: should crash
2 |
3 | /*
4 | TEST_CONFIG MEM=gc OS=macosx
5 | TEST_CRASHES
6 |
7 | TEST_RUN_OUTPUT
8 | objc\[\d+\]: '.*libnogc.dylib' was not compiled with -fobjc-gc or -fobjc-gc-only, but the application requires GC
9 | objc\[\d+\]: \*\*\* GC capability of application and some libraries did not match
10 | CRASHED: SIGILL
11 | END
12 |
13 | TEST_BUILD
14 | $C{COMPILE_C} $DIR/gc.c -dynamiclib -o libnoobjc.dylib
15 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libnogc.dylib
16 | $C{COMPILE} $DIR/gc.m -dynamiclib -o libsupportsgc.dylib -fobjc-gc
17 | $C{COMPILE} $DIR/gc.m -dynamiclib -o librequiresgc.dylib -fobjc-gc-only
18 | $C{COMPILE} $DIR/gc.m -dynamiclib -o librequiresgc.fake.dylib -fobjc-gc -install_name librequiresgc.dylib
19 |
20 | $C{COMPILE} $DIR/gc-main.m -x none libnogc.dylib -o gcenforcer-nogc-2.out
21 | END
22 | */
23 |
--------------------------------------------------------------------------------
/test/gcenforcer-noobjc.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG OS=macosx
3 |
4 | TEST_BUILD
5 | $C{COMPILE_C} $DIR/gc.c -dynamiclib -o libnoobjc.dylib
6 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libnogc.dylib
7 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libsupportsgc.dylib -fobjc-gc
8 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.dylib -fobjc-gc-only
9 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.fake.dylib -fobjc-gc -install_name librequiresgc.dylib
10 |
11 | $C{COMPILE} $DIR/gc-main.m -x none libnoobjc.dylib -o gcenforcer-noobjc.out
12 | END
13 | */
14 |
--------------------------------------------------------------------------------
/test/gcenforcer-requiresgc-1.m:
--------------------------------------------------------------------------------
1 | // gc-off app loading gc-required dylib: should crash
2 | // linker sees librequiresgc.fake.dylib, runtime uses librequiresgc.dylib
3 |
4 | /*
5 | TEST_CONFIG MEM=mrc,arc OS=macosx
6 | TEST_CRASHES
7 |
8 | TEST_RUN_OUTPUT
9 | objc\[\d+\]: '.*librequiresgc.dylib' was compiled with -fobjc-gc-only, but the application does not support GC
10 | objc\[\d+\]: \*\*\* GC capability of application and some libraries did not match
11 | CRASHED: SIGILL
12 | END
13 |
14 | TEST_BUILD
15 | $C{COMPILE_C} $DIR/gc.c -dynamiclib -o libnoobjc.dylib
16 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libnogc.dylib
17 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libsupportsgc.dylib -fobjc-gc
18 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.dylib -fobjc-gc-only
19 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.fake.dylib -fobjc-gc -install_name librequiresgc.dylib
20 |
21 | $C{COMPILE} $DIR/gc-main.m -x none librequiresgc.fake.dylib -o gcenforcer-requiresgc-1.out
22 | END
23 | */
24 |
--------------------------------------------------------------------------------
/test/gcenforcer-requiresgc-2.m:
--------------------------------------------------------------------------------
1 | // gc-off app loading gc-required dylib: should crash
2 | // linker sees librequiresgc.fake.dylib, runtime uses librequiresgc.dylib
3 |
4 | /*
5 | TEST_CONFIG MEM=gc OS=macosx
6 |
7 | TEST_BUILD
8 | $C{COMPILE_C} $DIR/gc.c -dynamiclib -o libnoobjc.dylib
9 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libnogc.dylib
10 | $C{COMPILE} $DIR/gc.m -dynamiclib -o libsupportsgc.dylib -fobjc-gc
11 | $C{COMPILE} $DIR/gc.m -dynamiclib -o librequiresgc.dylib -fobjc-gc-only
12 | $C{COMPILE} $DIR/gc.m -dynamiclib -o librequiresgc.fake.dylib -fobjc-gc -install_name librequiresgc.dylib
13 |
14 | $C{COMPILE} $DIR/gc-main.m -x none librequiresgc.fake.dylib -o gcenforcer-requiresgc-2.out
15 | END
16 | */
17 |
--------------------------------------------------------------------------------
/test/gcenforcer-supportsgc.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG OS=macosx
3 |
4 | TEST_BUILD
5 | $C{COMPILE_C} $DIR/gc.c -dynamiclib -o libnoobjc.dylib
6 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libnogc.dylib
7 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libsupportsgc.dylib -fobjc-gc
8 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.dylib -fobjc-gc-only
9 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.fake.dylib -fobjc-gc -install_name librequiresgc.dylib
10 |
11 | $C{COMPILE} $DIR/gc-main.m -x none libsupportsgc.dylib -o gcenforcer-supportsgc.out
12 | END
13 | */
14 |
--------------------------------------------------------------------------------
/test/gcenforcer.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CONFIG OS=macosx
3 |
4 | TEST_BUILD
5 | $C{COMPILE_C} $DIR/gc.c -dynamiclib -o libnoobjc.dylib
6 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libnogc.dylib
7 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o libsupportsgc.dylib -fobjc-gc
8 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.dylib -fobjc-gc-only
9 | $C{COMPILE_NOMEM} $DIR/gc.m -dynamiclib -o librequiresgc.fake.dylib -fobjc-gc -install_name librequiresgc.dylib
10 |
11 | $C{COMPILE} $DIR/gcenforcer.m -o gcenforcer.out
12 | END
13 | */
14 |
15 | #include "test.h"
16 | #include
17 | #include
18 |
19 | int main()
20 | {
21 | int i;
22 | for (i = 0; i < 1000; i++) {
23 | testassert(dlopen_preflight("libsupportsgc.dylib"));
24 | testassert(dlopen_preflight("libnoobjc.dylib"));
25 |
26 | if (objc_collectingEnabled()) {
27 | testassert(dlopen_preflight("librequiresgc.dylib"));
28 | testassert(! dlopen_preflight("libnogc.dylib"));
29 | } else {
30 | testassert(! dlopen_preflight("librequiresgc.dylib"));
31 | testassert(dlopen_preflight("libnogc.dylib"));
32 | }
33 | }
34 |
35 | succeed(__FILE__);
36 | }
37 |
--------------------------------------------------------------------------------
/test/gdb.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -Wno-deprecated-declarations
2 |
3 | #include "test.h"
4 |
5 | #if TARGET_OS_IPHONE
6 |
7 | int main()
8 | {
9 | succeed(__FILE__);
10 | }
11 |
12 | #else
13 |
14 | #include "testroot.i"
15 | #include
16 | #include
17 |
18 | int main()
19 | {
20 | // Class hashes
21 | #if __OBJC2__
22 |
23 | Class result;
24 |
25 | // Class should not be realized yet
26 | // fixme not true during class hash rearrangement
27 | // result = NXMapGet(gdb_objc_realized_classes, "TestRoot");
28 | // testassert(!result);
29 |
30 | [TestRoot class];
31 | // Now class should be realized
32 |
33 | result = (Class)objc_unretainedObject(NXMapGet(gdb_objc_realized_classes, "TestRoot"));
34 | testassert(result);
35 | testassert(result == [TestRoot class]);
36 |
37 | result = (Class)objc_unretainedObject(NXMapGet(gdb_objc_realized_classes, "DoesNotExist"));
38 | testassert(!result);
39 |
40 | #else
41 |
42 | struct objc_class query;
43 | Class result;
44 |
45 | query.name = "TestRoot";
46 | result = (Class)NXHashGet(_objc_debug_class_hash, &query);
47 | testassert(result);
48 | testassert((id)result == [TestRoot class]);
49 |
50 | query.name = "DoesNotExist";
51 | result = (Class)NXHashGet(_objc_debug_class_hash, &query);
52 | testassert(!result);
53 |
54 | #endif
55 |
56 | succeed(__FILE__);
57 | }
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/test/ignoredSelector2.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=gc
2 | // TEST_CFLAGS -framework Foundation
3 |
4 | // This test must use CF and test ignoredSelector must not use CF.
5 |
6 | #include "test.h"
7 | #include
8 |
9 | int main()
10 | {
11 | if (objc_collectingEnabled()) {
12 | // ARC RR functions don't retain and don't hit the side table.
13 | __block int count;
14 | testblock_t testblock = ^{
15 | for (int i = 0; i < count; i++) {
16 | id obj = [NSObject new];
17 | objc_retain(obj);
18 | objc_retain(obj);
19 | objc_release(obj);
20 | }
21 | };
22 | count = 100;
23 | testonthread(testblock);
24 | testonthread(testblock);
25 | leak_mark();
26 | count = 10000000;
27 | testonthread(testblock);
28 | #if __OBJC_GC__
29 | testwarn("rdar://19042235 possible leaks suppressed under GC");
30 | leak_check(2000);
31 | #else
32 | leak_check(0);
33 | #endif
34 | }
35 |
36 | succeed(__FILE__);
37 | }
38 |
--------------------------------------------------------------------------------
/test/imageorder.h:
--------------------------------------------------------------------------------
1 | extern int state;
2 | extern int cstate;
3 |
4 | OBJC_ROOT_CLASS
5 | @interface Super { id isa; }
6 | +(void) method;
7 | +(void) method0;
8 | @end
9 |
10 | @interface Super (cat1)
11 | +(void) method1;
12 | @end
13 |
14 | @interface Super (cat2)
15 | +(void) method2;
16 | @end
17 |
18 | @interface Super (cat3)
19 | +(void) method3;
20 | @end
21 |
--------------------------------------------------------------------------------
/test/imageorder.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/imageorder1.m -o imageorder1.dylib -dynamiclib
4 | $C{COMPILE} $DIR/imageorder2.m -x none imageorder1.dylib -o imageorder2.dylib -dynamiclib
5 | $C{COMPILE} $DIR/imageorder3.m -x none imageorder2.dylib imageorder1.dylib -o imageorder3.dylib -dynamiclib
6 | $C{COMPILE} $DIR/imageorder.m -x none imageorder3.dylib imageorder2.dylib imageorder1.dylib -o imageorder.out
7 | END
8 | */
9 |
10 | #include "test.h"
11 | #include "imageorder.h"
12 | #include
13 | #include
14 |
15 | int main()
16 | {
17 | // +load methods and C static initializers
18 | testassert(state == 3);
19 | testassert(cstate == 3);
20 |
21 | Class cls = objc_getClass("Super");
22 | testassert(cls);
23 |
24 | // make sure all categories arrived
25 | state = -1;
26 | [Super method0];
27 | testassert(state == 0);
28 | [Super method1];
29 | testassert(state == 1);
30 | [Super method2];
31 | testassert(state == 2);
32 | [Super method3];
33 | testassert(state == 3);
34 |
35 | // make sure imageorder3.dylib is the last category to attach
36 | state = 0;
37 | [Super method];
38 | testassert(state == 3);
39 |
40 | succeed(__FILE__);
41 | }
42 |
--------------------------------------------------------------------------------
/test/imageorder1.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "imageorder.h"
3 |
4 | int state = -1;
5 | int cstate = 0;
6 |
7 | static void c1(void) __attribute__((constructor));
8 | static void c1(void)
9 | {
10 | testassert(state == 1); // +load before C/C++
11 | testassert(cstate == 0);
12 | cstate = 1;
13 | }
14 |
15 |
16 | #if __clang__
17 | #pragma clang diagnostic push
18 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
19 | #endif
20 |
21 | @implementation Super (cat1)
22 | +(void) method {
23 | fail("+[Super(cat1) method] not replaced!");
24 | }
25 | +(void) method1 {
26 | state = 1;
27 | }
28 | +(void) load {
29 | testassert(state == 0);
30 | state = 1;
31 | }
32 | @end
33 |
34 | #if __clang__
35 | #pragma clang diagnostic pop
36 | #endif
37 |
38 |
39 | @implementation Super
40 | +(void) initialize { }
41 | +(void) method {
42 | fail("+[Super method] not replaced!");
43 | }
44 | +(void) method0 {
45 | state = 0;
46 | }
47 | +(void) load {
48 | testassert(state == -1);
49 | state = 0;
50 | }
51 | @end
52 |
53 |
--------------------------------------------------------------------------------
/test/imageorder2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "imageorder.h"
3 |
4 | static void c2(void) __attribute__((constructor));
5 | static void c2(void)
6 | {
7 | testassert(state == 2); // +load before C/C++
8 | testassert(cstate == 1);
9 | cstate = 2;
10 | }
11 |
12 |
13 | #if __clang__
14 | #pragma clang diagnostic push
15 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
16 | #endif
17 |
18 | @implementation Super (cat2)
19 | +(void) method {
20 | fail("+[Super(cat2) method] not replaced!");
21 | }
22 | +(void) method2 {
23 | state = 2;
24 | }
25 | +(void) load {
26 | testassert(state == 1);
27 | state = 2;
28 | }
29 | @end
30 |
31 | #if __clang__
32 | #pragma clang diagnostic pop
33 | #endif
34 |
--------------------------------------------------------------------------------
/test/imageorder3.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include "imageorder.h"
3 |
4 | static void c3(void) __attribute__((constructor));
5 | static void c3(void)
6 | {
7 | testassert(state == 3); // +load before C/C++
8 | testassert(cstate == 2);
9 | cstate = 3;
10 | }
11 |
12 |
13 | #if __clang__
14 | #pragma clang diagnostic push
15 | #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
16 | #endif
17 |
18 | @implementation Super (cat3)
19 | +(void) method {
20 | state = 3;
21 | }
22 | +(void) method3 {
23 | state = 3;
24 | }
25 | +(void) load {
26 | testassert(state == 2);
27 | state = 3;
28 | }
29 | @end
30 |
31 | #if __clang__
32 | #pragma clang diagnostic pop
33 | #endif
34 |
--------------------------------------------------------------------------------
/test/includes.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | // Verify that all headers can be included in any language.
4 |
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #if !TARGET_OS_IPHONE
28 | #include
29 | #include
30 | #include
31 | #endif
32 |
33 | #include "test.h"
34 |
35 | int main()
36 | {
37 | succeed(__FILE__);
38 | }
39 |
--------------------------------------------------------------------------------
/test/initializeVersusWeak.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=arc
2 | // TEST_CFLAGS -framework Foundation
3 |
4 | // Problem: If weak reference operations provoke +initialize, the runtime
5 | // can deadlock (recursive weak lock, or lock inversion between weak lock
6 | // and +initialize lock).
7 | // Solution: object_setClass() and objc_storeWeak() perform +initialize
8 | // if needed so that no weakly-referenced object can ever have an
9 | // un-+initialized isa.
10 |
11 | #include
12 | #include
13 | #include "test.h"
14 |
15 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
16 | #pragma clang diagnostic ignored "-Warc-unsafe-retained-assign"
17 |
18 | // This is StripedMap's pointer hash
19 | uintptr_t hash(id obj) {
20 | uintptr_t addr = (uintptr_t)obj;
21 | return ((addr >> 4) ^ (addr >> 9)) % 64;
22 | }
23 |
24 | bool sameAlignment(id o1, id o2)
25 | {
26 | return hash(o1) == hash(o2);
27 | }
28 |
29 | // Return a new string object that uses the same striped weak locks as `obj`.
30 | NSMutableString *newAlignedString(id obj)
31 | {
32 | NSMutableArray *strings = [NSMutableArray new];
33 | NSMutableString *result;
34 | do {
35 | result = [NSMutableString new];
36 | [strings addObject:result];
37 | } while (!sameAlignment(obj, result));
38 | return result;
39 | }
40 |
41 |
42 | __weak NSObject *weak1;
43 | __weak NSMutableString *weak2;
44 | NSMutableString *strong2;
45 |
46 | @interface A : NSObject @end
47 | @implementation A
48 | +(void)initialize {
49 | weak2 = strong2; // weak store #2
50 | strong2 = nil;
51 | }
52 | @end
53 |
54 | void testA()
55 | {
56 | // Weak store #1 provokes +initialize which performs weak store #2.
57 | // Solution: weak store #1 runs +initialize if needed
58 | // without holding locks.
59 | @autoreleasepool {
60 | A *obj = [A new];
61 | strong2 = newAlignedString(obj);
62 | [obj addObserver:obj forKeyPath:@"foo" options:0 context:0];
63 | weak1 = obj; // weak store #1
64 | [obj removeObserver:obj forKeyPath:@"foo"];
65 | obj = nil;
66 | }
67 | }
68 |
69 |
70 | __weak NSObject *weak3;
71 | __weak NSMutableString *weak4;
72 | NSMutableString *strong4;
73 |
74 | @interface B : NSObject @end
75 | @implementation B
76 | +(void)initialize {
77 | weak4 = strong4; // weak store #4
78 | strong4 = nil;
79 | }
80 | @end
81 |
82 |
83 | void testB()
84 | {
85 | // Weak load #3 provokes +initialize which performs weak store #4.
86 | // Solution: object_setClass() runs +initialize if needed
87 | // without holding locks.
88 | @autoreleasepool {
89 | B *obj = [B new];
90 | strong4 = newAlignedString(obj);
91 | weak3 = obj;
92 | [obj addObserver:obj forKeyPath:@"foo" options:0 context:0];
93 | [weak3 self]; // weak load #3
94 | [obj removeObserver:obj forKeyPath:@"foo"];
95 | obj = nil;
96 | }
97 | }
98 |
99 |
100 | __weak id weak5;
101 |
102 | @interface C : NSObject @end
103 | @implementation C
104 | +(void)initialize {
105 | weak5 = [self new];
106 | }
107 | @end
108 |
109 | void testC()
110 | {
111 | // +initialize performs a weak store of itself.
112 | // Make sure the retry in objc_storeWeak() doesn't spin.
113 | @autoreleasepool {
114 | [C self];
115 | }
116 | }
117 |
118 |
119 | int main()
120 | {
121 | alarm(10); // replace hangs with crashes
122 |
123 | testA();
124 | testB();
125 | testC();
126 |
127 | succeed(__FILE__);
128 | }
129 |
130 |
--------------------------------------------------------------------------------
/test/instanceSize.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 |
8 | @interface Sub1 : TestRoot {
9 | // id isa; // 0..4
10 | BOOL b; // 4..5
11 | }
12 | @end
13 |
14 | @implementation Sub1 @end
15 |
16 | @interface Sub2 : Sub1 {
17 | // id isa // 0..4 0..8
18 | // BOOL b // 4..5 8..9
19 | BOOL b2; // 5..6 9..10
20 | id o; // 8..12 16..24
21 | }
22 | @end
23 | @implementation Sub2 @end
24 |
25 | @interface Sub3 : Sub1 {
26 | // id isa; // 0..4 0..8
27 | // BOOL b; // 4..5 8..9
28 | id o; // 8..12 16..24
29 | BOOL b2; // 12..13 24..25
30 | }
31 | @end
32 | @implementation Sub3 @end
33 |
34 | int main()
35 | {
36 | testassert(sizeof(id) == class_getInstanceSize([TestRoot class]));
37 | testassert(2*sizeof(id) == class_getInstanceSize([Sub1 class]));
38 | testassert(3*sizeof(id) == class_getInstanceSize([Sub2 class]));
39 | testassert(4*sizeof(id) == class_getInstanceSize([Sub3 class]));
40 |
41 | #if !__has_feature(objc_arc)
42 | id o;
43 |
44 | o = [TestRoot new];
45 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
46 | RELEASE_VAR(o);
47 | o = [Sub1 new];
48 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
49 | RELEASE_VAR(o);
50 | o = [Sub2 new];
51 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
52 | RELEASE_VAR(o);
53 | o = [Sub3 new];
54 | testassert(object_getIndexedIvars(o) == (char *)o + class_getInstanceSize(object_getClass(o)));
55 | RELEASE_VAR(o);
56 | #endif
57 |
58 | succeed(__FILE__);
59 | }
60 |
--------------------------------------------------------------------------------
/test/ismeta.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | int main()
8 | {
9 | testassert(!class_isMetaClass([TestRoot class]));
10 | testassert(class_isMetaClass(object_getClass([TestRoot class])));
11 | testassert(!class_isMetaClass(nil));
12 | succeed(__FILE__);
13 | }
14 |
--------------------------------------------------------------------------------
/test/ivarSlide.h:
--------------------------------------------------------------------------------
1 | @interface Super : TestRoot {
2 | @public
3 | #if OLD
4 | // nothing
5 | #else
6 | char superIvar;
7 | #endif
8 | }
9 | @end
10 |
11 |
12 | @interface ShrinkingSuper : TestRoot {
13 | @public
14 | #if OLD
15 | id superIvar[5];
16 | __weak id superIvar2[5];
17 | #else
18 | // nothing
19 | #endif
20 | }
21 | @end;
22 |
23 |
24 | @interface MoreStrongSuper : TestRoot {
25 | @public
26 | #if OLD
27 | void *superIvar;
28 | #else
29 | id superIvar;
30 | #endif
31 | }
32 | @end;
33 |
34 |
35 | @interface MoreWeakSuper : TestRoot {
36 | @public
37 | #if OLD
38 | id superIvar;
39 | #else
40 | __weak id superIvar;
41 | #endif
42 | }
43 | @end;
44 |
45 | @interface MoreWeak2Super : TestRoot {
46 | @public
47 | #if OLD
48 | void *superIvar;
49 | #else
50 | __weak id superIvar;
51 | #endif
52 | }
53 | @end;
54 |
55 | @interface LessStrongSuper : TestRoot {
56 | @public
57 | #if OLD
58 | id superIvar;
59 | #else
60 | void *superIvar;
61 | #endif
62 | }
63 | @end;
64 |
65 | @interface LessWeakSuper : TestRoot {
66 | @public
67 | #if OLD
68 | __weak id superIvar;
69 | #else
70 | id superIvar;
71 | #endif
72 | }
73 | @end;
74 |
75 | @interface LessWeak2Super : TestRoot {
76 | @public
77 | #if OLD
78 | __weak id superIvar;
79 | #else
80 | void *superIvar;
81 | #endif
82 | }
83 | @end;
84 |
85 | @interface NoGCChangeSuper : TestRoot {
86 | @public
87 | intptr_t d;
88 | char superc1;
89 | #if OLD
90 | // nothing
91 | #else
92 | char superc2;
93 | #endif
94 | }
95 | @end
96 |
97 | @interface RunsOf15 : TestRoot {
98 | @public
99 | id scan1;
100 | intptr_t skip15[15];
101 | id scan15[15];
102 | intptr_t skip15_2[15];
103 | id scan15_2[15];
104 | #if OLD
105 | // nothing
106 | #else
107 | intptr_t skip1;
108 | #endif
109 | }
110 | @end
111 |
--------------------------------------------------------------------------------
/test/ivarSlide1.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #include
3 | #include
4 |
5 | #define OLD 0
6 | #include "ivarSlide.h"
7 |
8 | #include "testroot.i"
9 |
10 | @implementation Super @end
11 |
12 | @implementation ShrinkingSuper @end
13 |
14 | @implementation MoreStrongSuper @end
15 | @implementation LessStrongSuper @end
16 | @implementation MoreWeakSuper @end
17 | @implementation MoreWeak2Super @end
18 | @implementation LessWeakSuper @end
19 | @implementation LessWeak2Super @end
20 | @implementation NoGCChangeSuper @end
21 | @implementation RunsOf15 @end
22 |
--------------------------------------------------------------------------------
/test/layout.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=gc OS=macosx
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | @class NSObject;
8 |
9 | void printlayout(const char *name, const uint8_t *layout)
10 | {
11 | testprintf("%s: ", name);
12 |
13 | if (!layout) {
14 | testprintf("NULL\n");
15 | return;
16 | }
17 |
18 | const uint8_t *c;
19 | for (c = layout; *c; c++) {
20 | testprintf("%02x ", *c);
21 | }
22 |
23 | testprintf("00\n");
24 | }
25 |
26 | OBJC_ROOT_CLASS
27 | @interface Super { id isa; } @end
28 | @implementation Super @end
29 |
30 |
31 | // strong: 0c 00 (0a00 without structs)
32 | // weak: NULL
33 | @interface AllScanned : Super {
34 | id id1;
35 | NSObject *o1;
36 | __strong void *v1;
37 | __strong intptr_t *i1;
38 | __strong long *l1;
39 | /* fixme
40 | struct {
41 | id id1;
42 | id id2;
43 | } str;
44 | */
45 | id arr1[4];
46 | }
47 | @end
48 | @implementation AllScanned @end
49 |
50 | // strong: 00
51 | // weak: 1b 00 (18 00 without structs)
52 | @interface AllWeak : Super {
53 | __weak id id1;
54 | __weak NSObject *o1;
55 | __weak void *v1;
56 | __weak intptr_t *i1;
57 | __weak long *l1;
58 | /* fixme
59 | struct {
60 | __weak id id1;
61 | __weak id id2;
62 | } str;
63 | */
64 | __weak id arr1[4];
65 | }
66 | @end
67 | @implementation AllWeak @end
68 |
69 | // strong: ""
70 | // weak: NULL
71 | OBJC_ROOT_CLASS
72 | @interface NoScanned { long i; } @end
73 | @implementation NoScanned @end
74 |
75 | int main()
76 | {
77 | const uint8_t *layout;
78 |
79 | layout = class_getIvarLayout(objc_getClass("AllScanned"));
80 | printlayout("AllScanned", layout);
81 | layout = class_getWeakIvarLayout(objc_getClass("AllScanned"));
82 | printlayout("AllScanned weak", layout);
83 | // testassert(0 == strcmp(layout, "\x0a"));
84 |
85 | layout = class_getIvarLayout(objc_getClass("AllWeak"));
86 | printlayout("AllWeak", layout);
87 | layout = class_getWeakIvarLayout(objc_getClass("AllWeak"));
88 | printlayout("AllWeak weak", layout);
89 | // testassert(0 == strcmp(layout, ""));
90 |
91 | layout = class_getIvarLayout(objc_getClass("NoScanned"));
92 | printlayout("NoScanned", layout);
93 | // testassert(0 == strcmp(layout, ""));
94 |
95 | succeed(__FILE__);
96 | return 0;
97 | }
98 |
--------------------------------------------------------------------------------
/test/literals.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=arc,mrc CC=clang LANGUAGE=objc,objc++
2 | // TEST_CFLAGS -framework Foundation
3 |
4 | #import
5 | #import
6 | #import
7 | #import
8 | #import
9 | #include "test.h"
10 |
11 | int main() {
12 | PUSH_POOL {
13 |
14 | #if __has_feature(objc_bool) // placeholder until we get a more precise macro.
15 | NSArray *array = @[ @1, @2, @YES, @NO, @"Hello", @"World" ];
16 | testassert([array count] == 6);
17 | NSDictionary *dict = @{ @"Name" : @"John Q. Public", @"Age" : @42 };
18 | testassert([dict count] == 2);
19 | NSDictionary *numbers = @{ @"π" : @M_PI, @"e" : @M_E };
20 | testassert([[numbers objectForKey:@"π"] doubleValue] == M_PI);
21 | testassert([[numbers objectForKey:@"e"] doubleValue] == M_E);
22 |
23 | BOOL yesBool = YES;
24 | BOOL noBool = NO;
25 | array = @[
26 | @(true),
27 | @(YES),
28 | [NSNumber numberWithBool:YES],
29 | @YES,
30 | @(yesBool),
31 | @((BOOL)YES),
32 |
33 | @(false),
34 | @(NO),
35 | [NSNumber numberWithBool:NO],
36 | @NO,
37 | @(noBool),
38 | @((BOOL)NO),
39 | ];
40 | NSData * jsonData = [NSJSONSerialization dataWithJSONObject:array options:0 error:nil];
41 | NSString * string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
42 | #if __cplusplus
43 | testassert([string isEqualToString:@"[true,true,true,true,true,true,false,false,false,false,false,false]"]);
44 | #else
45 | // C99 @(true) and @(false) evaluate to @(1) and @(0).
46 | testassert([string isEqualToString:@"[1,true,true,true,true,true,0,false,false,false,false,false]"]);
47 | #endif
48 |
49 | #endif
50 |
51 | } POP_POOL;
52 |
53 | succeed(__FILE__);
54 |
55 | return 0;
56 | }
57 |
--------------------------------------------------------------------------------
/test/load-noobjc.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/load-noobjc.m -o load-noobjc.out
4 | $C{COMPILE} $DIR/load-noobjc2.m -o libload-noobjc2.dylib -bundle -bundle_loader load-noobjc.out
5 | $C{COMPILE} $DIR/load-noobjc3.m -o libload-noobjc3.dylib -bundle -bundle_loader load-noobjc.out
6 | END
7 | */
8 |
9 | #include "test.h"
10 |
11 | #if !__OBJC2__
12 | // old runtime can't fix this deadlock
13 |
14 | int main()
15 | {
16 | succeed(__FILE__);
17 | }
18 |
19 | #else
20 |
21 | #include
22 |
23 | int state = 0;
24 | semaphore_t go;
25 |
26 | void *thread(void *arg __unused)
27 | {
28 | objc_registerThreadWithCollector();
29 | dlopen("libload-noobjc2.dylib", RTLD_LAZY);
30 | fail("dlopen should not have returned");
31 | }
32 |
33 | int main()
34 | {
35 | semaphore_create(mach_task_self(), &go, SYNC_POLICY_FIFO, 0);
36 |
37 | pthread_t th;
38 | pthread_create(&th, nil, &thread, nil);
39 |
40 | // Wait for thread to stop in libload-noobjc2's +load method.
41 | semaphore_wait(go);
42 |
43 | // run nooobjc3's constructor function.
44 | // There's no objc code here so it shouldn't require the +load lock.
45 | void *dlh = dlopen("libload-noobjc3.dylib", RTLD_LAZY);
46 | testassert(dlh);
47 | testassert(state == 1);
48 |
49 | succeed(__FILE__);
50 | }
51 |
52 | #endif
53 |
--------------------------------------------------------------------------------
/test/load-noobjc2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 | #if __OBJC2__
3 |
4 | extern semaphore_t go;
5 |
6 | OBJC_ROOT_CLASS
7 | @interface noobjc @end
8 | @implementation noobjc
9 | +(void)load
10 | {
11 | semaphore_signal(go);
12 | while (1) sleep(1);
13 | }
14 | @end
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/test/load-noobjc3.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | #if __OBJC2__
4 |
5 | extern int state;
6 |
7 | __attribute__((constructor))
8 | static void ctor(void)
9 | {
10 | state = 1;
11 | }
12 |
13 | #endif
14 |
--------------------------------------------------------------------------------
/test/load-order.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/load-order3.m -o load-order3.dylib -dynamiclib
4 | $C{COMPILE} $DIR/load-order2.m -o load-order2.dylib -x none load-order3.dylib -dynamiclib
5 | $C{COMPILE} $DIR/load-order1.m -o load-order1.dylib -x none load-order3.dylib load-order2.dylib -dynamiclib
6 | $C{COMPILE} $DIR/load-order.m -o load-order.out -x none load-order3.dylib load-order2.dylib load-order1.dylib
7 | END
8 | */
9 |
10 | #include "test.h"
11 |
12 | extern int state1, state2, state3;
13 |
14 | int main()
15 | {
16 | testassert(state1 == 1 && state2 == 2 && state3 == 3);
17 | succeed(__FILE__);
18 | }
19 |
--------------------------------------------------------------------------------
/test/load-order1.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | extern int state2, state3;
4 |
5 | int state1 = 0;
6 |
7 | OBJC_ROOT_CLASS
8 | @interface One @end
9 | @implementation One
10 | +(void)load
11 | {
12 | testassert(state2 == 2 && state3 == 3);
13 | state1 = 1;
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/test/load-order2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | extern int state3;
4 |
5 | int state2 = 0;
6 |
7 | OBJC_ROOT_CLASS
8 | @interface Two @end
9 | @implementation Two
10 | +(void)load
11 | {
12 | testassert(state3 == 3);
13 | state2 = 2;
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/test/load-order3.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | int state3 = 0;
4 |
5 | OBJC_ROOT_CLASS
6 | @interface Three @end
7 | @implementation Three
8 | +(void)load
9 | {
10 | state3 = 3;
11 | }
12 | @end
13 |
--------------------------------------------------------------------------------
/test/load-parallel.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/load-parallel00.m -o load-parallel00.dylib -dynamiclib
4 | $C{COMPILE} $DIR/load-parallel.m -x none load-parallel00.dylib -o load-parallel.out -DCOUNT=10
5 |
6 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel0.dylib -dynamiclib -DN=0
7 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel1.dylib -dynamiclib -DN=1
8 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel2.dylib -dynamiclib -DN=2
9 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel3.dylib -dynamiclib -DN=3
10 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel4.dylib -dynamiclib -DN=4
11 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel5.dylib -dynamiclib -DN=5
12 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel6.dylib -dynamiclib -DN=6
13 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel7.dylib -dynamiclib -DN=7
14 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel8.dylib -dynamiclib -DN=8
15 | $C{COMPILE} $DIR/load-parallel0.m -x none load-parallel00.dylib -o load-parallel9.dylib -dynamiclib -DN=9
16 | END
17 | */
18 |
19 | #include "test.h"
20 |
21 | #include
22 | #include
23 |
24 | #ifndef COUNT
25 | #error -DCOUNT=c missing
26 | #endif
27 |
28 | extern int state;
29 |
30 | void *thread(void *arg)
31 | {
32 | uintptr_t num = (uintptr_t)arg;
33 | char *buf;
34 |
35 | objc_registerThreadWithCollector();
36 |
37 | asprintf(&buf, "load-parallel%lu.dylib", (unsigned long)num);
38 | testprintf("%s\n", buf);
39 | void *dlh = dlopen(buf, RTLD_LAZY);
40 | if (!dlh) {
41 | fail("dlopen failed: %s", dlerror());
42 | }
43 | free(buf);
44 |
45 | return NULL;
46 | }
47 |
48 | int main()
49 | {
50 | pthread_t t[COUNT];
51 | uintptr_t i;
52 |
53 | for (i = 0; i < COUNT; i++) {
54 | pthread_create(&t[i], NULL, thread, (void *)i);
55 | }
56 |
57 | for (i = 0; i < COUNT; i++) {
58 | pthread_join(t[i], NULL);
59 | }
60 |
61 | testprintf("loaded %d/%d\n", state, COUNT*26);
62 | testassert(state == COUNT*26);
63 |
64 | succeed(__FILE__);
65 | }
66 |
--------------------------------------------------------------------------------
/test/load-parallel0.m:
--------------------------------------------------------------------------------
1 | #ifndef N
2 | #error -DN=n missing
3 | #endif
4 |
5 | #import
6 | #include
7 | #include
8 | #include
9 | #include
10 | extern int state;
11 |
12 | #define CLASS0(n,nn) \
13 | OBJC_ROOT_CLASS \
14 | @interface C_##n##_##nn @end \
15 | @implementation C_##n##_##nn \
16 | +(void)load { OSAtomicIncrement32(&state); usleep(10); } \
17 | @end
18 |
19 | #define CLASS(n,nn) CLASS0(n,nn)
20 |
21 | CLASS(a,N)
22 | CLASS(b,N)
23 | CLASS(c,N)
24 | CLASS(d,N)
25 | CLASS(e,N)
26 | CLASS(f,N)
27 | CLASS(g,N)
28 | CLASS(h,N)
29 | CLASS(i,N)
30 | CLASS(j,N)
31 | CLASS(k,N)
32 | CLASS(l,N)
33 | CLASS(m,N)
34 | CLASS(n,N)
35 | CLASS(o,N)
36 | CLASS(p,N)
37 | CLASS(q,N)
38 | CLASS(r,N)
39 | CLASS(s,N)
40 | CLASS(t,N)
41 | CLASS(u,N)
42 | CLASS(v,N)
43 | CLASS(w,N)
44 | CLASS(x,N)
45 | CLASS(y,N)
46 | CLASS(z,N)
47 |
--------------------------------------------------------------------------------
/test/load-parallel00.m:
--------------------------------------------------------------------------------
1 | int state = 0;
2 |
--------------------------------------------------------------------------------
/test/load-reentrant.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/load-reentrant.m -o load-reentrant.out
4 | $C{COMPILE} $DIR/load-reentrant2.m -o libload-reentrant2.dylib -bundle -bundle_loader load-reentrant.out
5 | END
6 | */
7 |
8 | #include "test.h"
9 | #include
10 |
11 | int state1 = 0;
12 | int *state2_p;
13 |
14 | OBJC_ROOT_CLASS
15 | @interface One @end
16 | @implementation One
17 | +(void)load
18 | {
19 | state1 = 111;
20 |
21 | // Re-entrant +load doesn't get to complete until we do
22 | void *dlh = dlopen("libload-reentrant2.dylib", RTLD_LAZY);
23 | testassert(dlh);
24 | state2_p = (int *)dlsym(dlh, "state2");
25 | testassert(state2_p);
26 | testassert(*state2_p == 0);
27 |
28 | state1 = 1;
29 | }
30 | @end
31 |
32 | int main()
33 | {
34 | testassert(state1 == 1 && state2_p && *state2_p == 2);
35 | succeed(__FILE__);
36 | }
37 |
--------------------------------------------------------------------------------
/test/load-reentrant2.m:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | int state2 = 0;
4 | extern int state1;
5 |
6 | static void ctor(void) __attribute__((constructor));
7 | static void ctor(void)
8 | {
9 | // should be called during One's dlopen(), before Two's +load
10 | testassert(state1 == 111);
11 | testassert(state2 == 0);
12 | }
13 |
14 | OBJC_ROOT_CLASS
15 | @interface Two @end
16 | @implementation Two
17 | +(void) load
18 | {
19 | // Does not run until One's +load completes
20 | testassert(state1 == 1);
21 | state2 = 2;
22 | }
23 | @end
24 |
--------------------------------------------------------------------------------
/test/load.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 |
6 | int state = 0;
7 | int catstate = 0;
8 | int deallocstate = 0;
9 |
10 | @interface Deallocator : TestRoot @end
11 | @implementation Deallocator
12 | -(id)init {
13 | self = [super init];
14 | if (objc_collectingEnabled()) {
15 | deallocstate = 1;
16 | }
17 | return self;
18 | }
19 | -(void)dealloc {
20 | deallocstate = 1;
21 | SUPER_DEALLOC();
22 | }
23 | @end
24 |
25 |
26 | @interface Super : TestRoot @end
27 | @implementation Super
28 | +(void)initialize {
29 | if (self == [Super class]) {
30 | testprintf("in +[Super initialize]\n");
31 | testassert(state == 2);
32 | state = 3;
33 | } else {
34 | testprintf("in +[Super initialize] on behalf of Sub\n");
35 | testassert(state == 3);
36 | state = 4;
37 | }
38 | }
39 | -(void)load { fail("-[Super load] called!"); }
40 | +(void)load {
41 | testprintf("in +[Super load]\n");
42 | testassert(state == 0);
43 | state = 1;
44 | }
45 | @end
46 |
47 | @interface Sub : Super { } @end
48 | @implementation Sub
49 | +(void)load {
50 | testprintf("in +[Sub load]\n");
51 | testassert(state == 1);
52 | state = 2;
53 | }
54 | -(void)load { fail("-[Sub load] called!"); }
55 | @end
56 |
57 | @interface SubNoLoad : Super { } @end
58 | @implementation SubNoLoad @end
59 |
60 | @interface Super (Category) @end
61 | @implementation Super (Category)
62 | -(void)load { fail("-[Super(Category) load called!"); }
63 | +(void)load {
64 | testprintf("in +[Super(Category) load]\n");
65 | testassert(state >= 1);
66 | catstate++;
67 | }
68 | @end
69 |
70 |
71 | @interface Sub (Category) @end
72 | @implementation Sub (Category)
73 | -(void)load { fail("-[Sub(Category) load called!"); }
74 | +(void)load {
75 | testprintf("in +[Sub(Category) load]\n");
76 | testassert(state >= 2);
77 | catstate++;
78 |
79 | // test autorelease pool
80 | __autoreleasing id x;
81 | x = AUTORELEASE([Deallocator new]);
82 | }
83 | @end
84 |
85 |
86 | @interface SubNoLoad (Category) @end
87 | @implementation SubNoLoad (Category)
88 | -(void)load { fail("-[SubNoLoad(Category) load called!"); }
89 | +(void)load {
90 | testprintf("in +[SubNoLoad(Category) load]\n");
91 | testassert(state >= 1);
92 | catstate++;
93 | }
94 | @end
95 |
96 | int main()
97 | {
98 | testassert(state == 2);
99 | testassert(catstate == 3);
100 | testassert(deallocstate == 1);
101 | [Sub class];
102 | testassert(state == 4);
103 | testassert(catstate == 3);
104 |
105 | succeed(__FILE__);
106 | }
107 |
--------------------------------------------------------------------------------
/test/methodListSize.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | // rdar://8052003 rdar://8077031
3 |
4 | #include "test.h"
5 |
6 | #include
7 | #include
8 |
9 | // add SELCOUNT methods to each of CLASSCOUNT classes
10 | #define CLASSCOUNT 100
11 | #define SELCOUNT 200
12 |
13 | int main()
14 | {
15 | int i, j;
16 | malloc_statistics_t start, end;
17 |
18 | Class root;
19 | root = objc_allocateClassPair(NULL, "Root", 0);
20 | objc_registerClassPair(root);
21 |
22 | Class classes[CLASSCOUNT];
23 | for (i = 0; i < CLASSCOUNT; i++) {
24 | char *classname;
25 | asprintf(&classname, "GrP_class_%d", i);
26 | classes[i] = objc_allocateClassPair(root, classname, 0);
27 | objc_registerClassPair(classes[i]);
28 | free(classname);
29 | }
30 |
31 | SEL selectors[SELCOUNT];
32 | for (i = 0; i < SELCOUNT; i++) {
33 | char *selname;
34 | asprintf(&selname, "GrP_sel_%d", i);
35 | selectors[i] = sel_registerName(selname);
36 | free(selname);
37 | }
38 |
39 | malloc_zone_statistics(NULL, &start);
40 |
41 | for (i = 0; i < CLASSCOUNT; i++) {
42 | for (j = 0; j < SELCOUNT; j++) {
43 | class_addMethod(classes[i], selectors[j], (IMP)main, "");
44 | }
45 | }
46 |
47 | malloc_zone_statistics(NULL, &end);
48 |
49 | // expected: 3-word method struct plus two other words
50 | ssize_t expected = (sizeof(void*) * (3+2)) * SELCOUNT * CLASSCOUNT;
51 | ssize_t actual = end.size_in_use - start.size_in_use;
52 | testassert(actual < expected * 3); // allow generous fudge factor
53 |
54 | succeed(__FILE__);
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/test/method_getName.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | #undef SUPPORT_NONPOINTER_ISA // remove test.h's definition
8 | #include "../runtime/objc-config.h"
9 |
10 | int main() {
11 | unsigned i;
12 | Class c = [NSObject class];
13 | unsigned numMethods;
14 | Method *methods = class_copyMethodList(c, &numMethods);
15 |
16 | for (i=0; i method_getName crash on NSObject method when GC is enabled
18 | SEL aMethod;
19 | aMethod = method_getName(methods[i]);
20 | #if defined(kIgnore)
21 | if (aMethod == (SEL)kIgnore)
22 | fail(__FILE__);
23 | #endif
24 | }
25 |
26 | succeed(__FILE__);
27 | }
28 |
--------------------------------------------------------------------------------
/test/nilAPIArgs.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #import
6 |
7 | int main() {
8 | // ensure various bits of API don't crash when tossed nil parameters
9 | class_conformsToProtocol(nil, nil);
10 | method_setImplementation(nil, NULL);
11 |
12 | succeed(__FILE__);
13 | }
14 |
--------------------------------------------------------------------------------
/test/nopool.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 |
6 | @implementation TestRoot (Loader)
7 | +(void)load
8 | {
9 | [[TestRoot new] autorelease];
10 | testassert(TestRootAutorelease == 1);
11 | testassert(TestRootDealloc == 0);
12 | }
13 | @end
14 |
15 | int main()
16 | {
17 | // +load's autoreleased object should have deallocated
18 | testassert(TestRootDealloc == 1);
19 |
20 | [[TestRoot new] autorelease];
21 | testassert(TestRootAutorelease == 2);
22 |
23 | objc_autoreleasePoolPop(objc_autoreleasePoolPush());
24 |
25 | [[TestRoot new] autorelease];
26 | testassert(TestRootAutorelease == 3);
27 |
28 | testonthread(^{
29 | [[TestRoot new] autorelease];
30 | testassert(TestRootAutorelease == 4);
31 | testassert(TestRootDealloc == 1);
32 | });
33 |
34 | // thread's autoreleased object should have deallocated
35 | testassert(TestRootDealloc == 2);
36 |
37 | succeed(__FILE__);
38 | }
39 |
--------------------------------------------------------------------------------
/test/nscdtors.mm:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 | // test cdtors, with NSObject instead of TestRoot as the root class
3 |
4 | #define USE_FOUNDATION 1
5 | #include "cdtors.mm"
6 |
7 |
--------------------------------------------------------------------------------
/test/nsexc.m:
--------------------------------------------------------------------------------
1 | /*
2 | need exception-safe ARC for exception deallocation tests
3 | TEST_CFLAGS -fobjc-arc-exceptions -framework Foundation
4 |
5 | llvm-gcc unavoidably warns about our deliberately out-of-order handlers
6 |
7 | TEST_BUILD_OUTPUT
8 | In file included from .*
9 | .*exc.m: In function .*
10 | .*exc.m:\d+: warning: exception of type .* will be caught
11 | .*exc.m:\d+: warning: by earlier handler for .*
12 | .*exc.m:\d+: warning: exception of type .* will be caught
13 | .*exc.m:\d+: warning: by earlier handler for .*
14 | .*exc.m:\d+: warning: exception of type .* will be caught
15 | .*exc.m:\d+: warning: by earlier handler for .*
16 | OR
17 | END
18 | */
19 |
20 | #define USE_FOUNDATION 1
21 | #include "exc.m"
22 |
--------------------------------------------------------------------------------
/test/nsobject.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc,gc
2 |
3 | #include "test.h"
4 |
5 | #import
6 |
7 | @interface Sub : NSObject @end
8 | @implementation Sub
9 | +(id)allocWithZone:(NSZone *)zone {
10 | testprintf("in +[Sub alloc]\n");
11 | return [super allocWithZone:zone];
12 | }
13 | -(void)dealloc {
14 | testprintf("in -[Sub dealloc]\n");
15 | [super dealloc];
16 | }
17 | @end
18 |
19 |
20 | // These declarations and definitions can be used
21 | // to check the compile-time type of an object.
22 | @interface NSObject (Checker)
23 | // fixme this isn't actually enforced
24 | +(void)NSObjectInstance __attribute__((unavailable));
25 | @end
26 | @implementation NSObject (Checker)
27 | -(void)NSObjectInstance { }
28 | +(void)NSObjectClass { }
29 | @end
30 | @interface Sub (Checker)
31 | -(void)NSObjectInstance __attribute__((unavailable));
32 | +(void)NSObjectClass __attribute__((unavailable));
33 | @end
34 | @implementation Sub (Checker)
35 | -(void)SubInstance { }
36 | +(void)SubClass { }
37 | @end
38 |
39 | int main()
40 | {
41 | PUSH_POOL {
42 | [[Sub new] autorelease];
43 | } POP_POOL;
44 |
45 | // Verify that dot syntax on class objects works with some instance methods
46 | // (void)NSObject.self; fixme
47 | (void)NSObject.class;
48 | (void)NSObject.superclass;
49 | (void)NSObject.hash;
50 | (void)NSObject.description;
51 | (void)NSObject.debugDescription;
52 |
53 | // Verify that some methods return the correct type.
54 | Class cls;
55 | NSObject *nsobject = nil;
56 | Sub *subobject = nil;
57 |
58 | cls = [NSObject self];
59 | cls = [Sub self];
60 | nsobject = [nsobject self];
61 | subobject = [subobject self];
62 | [[NSObject self] NSObjectClass];
63 | [[nsobject self] NSObjectInstance];
64 | [[Sub self] SubClass];
65 | [[subobject self] SubInstance];
66 |
67 | // fixme
68 | // cls = NSObject.self;
69 | // cls = Sub.self;
70 | // [NSObject.self NSObjectClass];
71 | // [nsobject.self NSObjectInstance];
72 | // [Sub.self SubClass];
73 | // [subobject.self SubInstance];
74 |
75 | cls = [NSObject class];
76 | cls = [nsobject class];
77 | cls = [Sub class];
78 | cls = [subobject class];
79 | [[NSObject class] NSObjectClass];
80 | [[nsobject class] NSObjectClass];
81 | [[Sub class] SubClass];
82 | [[subobject class] SubClass];
83 |
84 | cls = NSObject.class;
85 | cls = nsobject.class;
86 | cls = Sub.class;
87 | cls = subobject.class;
88 | [NSObject.class NSObjectClass];
89 | [nsobject.class NSObjectClass];
90 | [Sub.class SubClass];
91 | [subobject.class SubClass];
92 |
93 |
94 | cls = [NSObject superclass];
95 | cls = [nsobject superclass];
96 | cls = [Sub superclass];
97 | cls = [subobject superclass];
98 | [[NSObject superclass] NSObjectClass];
99 | [[nsobject superclass] NSObjectClass];
100 | [[Sub superclass] NSObjectClass];
101 | [[subobject superclass] NSObjectClass];
102 |
103 | cls = NSObject.superclass;
104 | cls = nsobject.superclass;
105 | cls = Sub.superclass;
106 | cls = subobject.superclass;
107 | [NSObject.superclass NSObjectClass];
108 | [nsobject.superclass NSObjectClass];
109 | [Sub.superclass NSObjectClass];
110 | [subobject.superclass NSObjectClass];
111 |
112 |
113 | succeed(__FILE__);
114 | }
115 |
--------------------------------------------------------------------------------
/test/nsprotocol.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #if __OBJC2__
6 |
7 | #include
8 |
9 | int main()
10 | {
11 | // Class Protocol is always a subclass of NSObject
12 |
13 | testassert(objc_getClass("NSObject"));
14 |
15 | Class cls = objc_getClass("Protocol");
16 | testassert(class_getInstanceMethod(cls, sel_registerName("isProxy")));
17 | testassert(class_getSuperclass(cls) == objc_getClass("NSObject"));
18 |
19 | succeed(__FILE__);
20 | }
21 |
22 | #else
23 |
24 | #include
25 | #include
26 |
27 | int main()
28 | {
29 | // Class Protocol is never a subclass of NSObject
30 | // CoreFoundation adds NSObject methods to Protocol when it loads
31 |
32 | testassert(objc_getClass("NSObject"));
33 |
34 | Class cls = objc_getClass("Protocol");
35 | testassert(!class_getInstanceMethod(cls, sel_registerName("isProxy")));
36 | testassert(class_getSuperclass(cls) != objc_getClass("NSObject"));
37 |
38 | void *dl = dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY);
39 | testassert(dl);
40 |
41 | testassert(class_getInstanceMethod(cls, sel_registerName("isProxy")));
42 | testassert(class_getSuperclass(cls) != objc_getClass("NSObject"));
43 |
44 | succeed(__FILE__);
45 | }
46 |
47 | #endif
48 |
--------------------------------------------------------------------------------
/test/objectCopy.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc,gc
2 |
3 | #include "test.h"
4 | #include
5 |
6 | @interface Test : NSObject {
7 | @public
8 | char bytes[32-sizeof(void*)];
9 | }
10 | @end
11 | @implementation Test
12 | @end
13 |
14 |
15 | int main()
16 | {
17 | Test *o0 = [Test new];
18 | [o0 retain];
19 | Test *o1 = class_createInstance([Test class], 32);
20 | [o1 retain];
21 | id o2 = object_copy(o0, 0);
22 | id o3 = object_copy(o1, 0);
23 | id o4 = object_copy(o1, 32);
24 | testassert(malloc_size(o0) == 32);
25 | testassert(malloc_size(o1) == 64);
26 | testassert(malloc_size(o2) == 32);
27 | testassert(malloc_size(o3) == 32);
28 | testassert(malloc_size(o4) == 64);
29 | if (!objc_collecting_enabled()) {
30 | testassert([o0 retainCount] == 2);
31 | testassert([o1 retainCount] == 2);
32 | testassert([o2 retainCount] == 1);
33 | testassert([o3 retainCount] == 1);
34 | testassert([o4 retainCount] == 1);
35 | }
36 | succeed(__FILE__);
37 | }
38 |
--------------------------------------------------------------------------------
/test/property.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 | #include
7 | #include
8 |
9 | @interface Super : TestRoot {
10 | @public
11 | char superIvar;
12 | }
13 |
14 | @property(readonly) char superProp;
15 | @end
16 |
17 | @implementation Super
18 | @synthesize superProp = superIvar;
19 | @end
20 |
21 |
22 | @interface Sub : Super {
23 | @public
24 | uintptr_t subIvar;
25 | }
26 | @property(readonly) uintptr_t subProp;
27 | @end
28 |
29 | @implementation Sub
30 | @synthesize subProp = subIvar;
31 | @end
32 |
33 |
34 | int main()
35 | {
36 | /*
37 | Runtime layout of Sub:
38 | [0] isa
39 | [1] superIvar
40 | [2] subIvar
41 | */
42 |
43 | objc_property_t prop;
44 |
45 | prop = class_getProperty([Sub class], "subProp");
46 | testassert(prop);
47 |
48 | prop = class_getProperty([Super class], "superProp");
49 | testassert(prop);
50 | testassert(prop == class_getProperty([Sub class], "superProp"));
51 |
52 | prop = class_getProperty([Super class], "subProp");
53 | testassert(!prop);
54 |
55 | prop = class_getProperty(object_getClass([Sub class]), "subProp");
56 | testassert(!prop);
57 |
58 |
59 | testassert(NULL == class_getProperty(NULL, "foo"));
60 | testassert(NULL == class_getProperty([Sub class], NULL));
61 | testassert(NULL == class_getProperty(NULL, NULL));
62 |
63 | succeed(__FILE__);
64 | return 0;
65 | }
66 |
--------------------------------------------------------------------------------
/test/protocol_copyPropertyList.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | // need Foundation to get NSObject compatibility additions for class Protocol
3 | // because ARC calls [protocol retain]
4 |
5 | #include "test.h"
6 | #include
7 | #include
8 | #include
9 |
10 | @protocol SuperProps
11 | @property int prop1;
12 | @property int prop2;
13 | @end
14 |
15 | @protocol SubProps
16 | @property int prop3;
17 | @property int prop4;
18 | @end
19 |
20 |
21 | @protocol FourProps
22 | @property int prop1;
23 | @property int prop2;
24 | @property int prop3;
25 | @property int prop4;
26 | @end
27 |
28 | @protocol NoProps @end
29 |
30 | static int isNamed(objc_property_t p, const char *name)
31 | {
32 | return (0 == strcmp(name, property_getName(p)));
33 | }
34 |
35 | int main()
36 | {
37 | objc_property_t *props;
38 | unsigned int count;
39 | Protocol *proto;
40 |
41 | proto = @protocol(SubProps);
42 | testassert(proto);
43 |
44 | count = 100;
45 | props = protocol_copyPropertyList(proto, &count);
46 | testassert(props);
47 | testassert(count == 2);
48 | testassert((isNamed(props[0], "prop4") && isNamed(props[1], "prop3")) ||
49 | (isNamed(props[0], "prop3") && isNamed(props[1], "prop4")));
50 | // props[] should be null-terminated
51 | testassert(props[2] == NULL);
52 | free(props);
53 |
54 | proto = @protocol(SuperProps);
55 | testassert(proto);
56 |
57 | count = 100;
58 | props = protocol_copyPropertyList(proto, &count);
59 | testassert(props);
60 | testassert(count == 2);
61 | testassert((isNamed(props[0], "prop1") && isNamed(props[1], "prop2")) ||
62 | (isNamed(props[0], "prop2") && isNamed(props[1], "prop1")));
63 | // props[] should be null-terminated
64 | testassert(props[2] == NULL);
65 | free(props);
66 |
67 | // Check null-termination - this property list block would be 16 bytes
68 | // if it weren't for the terminator
69 | proto = @protocol(FourProps);
70 | testassert(proto);
71 |
72 | count = 100;
73 | props = protocol_copyPropertyList(proto, &count);
74 | testassert(props);
75 | testassert(count == 4);
76 | testassert(malloc_size(props) >= 5 * sizeof(objc_property_t));
77 | testassert(props[3] != NULL);
78 | testassert(props[4] == NULL);
79 | free(props);
80 |
81 | // Check NULL count parameter
82 | props = protocol_copyPropertyList(proto, NULL);
83 | testassert(props);
84 | testassert(props[4] == NULL);
85 | testassert(props[3] != NULL);
86 | free(props);
87 |
88 | // Check NULL protocol parameter
89 | count = 100;
90 | props = protocol_copyPropertyList(NULL, &count);
91 | testassert(!props);
92 | testassert(count == 0);
93 |
94 | // Check NULL protocol and count
95 | props = protocol_copyPropertyList(NULL, NULL);
96 | testassert(!props);
97 |
98 | // Check protocol with no properties
99 | proto = @protocol(NoProps);
100 | testassert(proto);
101 |
102 | count = 100;
103 | props = protocol_copyPropertyList(proto, &count);
104 | testassert(!props);
105 | testassert(count == 0);
106 |
107 | succeed(__FILE__);
108 | return 0;
109 | }
110 |
--------------------------------------------------------------------------------
/test/protocol_cw.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -Wno-deprecated-declarations
2 |
3 | #include "test.h"
4 |
5 | #if __OBJC2__
6 |
7 | int main()
8 | {
9 | succeed(__FILE__);
10 | }
11 |
12 | #else
13 |
14 | // rdar://4951638
15 |
16 | #include
17 | #include
18 |
19 | char Protocol_name[] __attribute__((section("__OBJC,__class_names"))) = "Protocol";
20 |
21 | struct st {
22 | void *isa;
23 | const char *protocol_name;
24 | void *protocol_list;
25 | void *instance_methods;
26 | void *class_methods;
27 | };
28 |
29 | struct st Foo_protocol __attribute__((section("__OBJC,__protocol"))) = { Protocol_name, "Foo", 0, 0, 0 };
30 |
31 | int main()
32 | {
33 | Protocol *foo = objc_getProtocol("Foo");
34 |
35 | testassert(foo == (Protocol *)&Foo_protocol);
36 | testassert(0 == strcmp("Foo", [foo name]));
37 | succeed(__FILE__);
38 | }
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/test/rawisa.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_CFLAGS -Xlinker -sectcreate -Xlinker __DATA -Xlinker __objc_rawisa -Xlinker /dev/null
3 | TEST_ENV OBJC_PRINT_RAW_ISA=YES
4 |
5 | TEST_RUN_OUTPUT
6 | objc\[\d+\]: RAW ISA: disabling non-pointer isa because the app has a __DATA,__objc_rawisa section
7 | (.* RAW ISA: .*\n)*
8 | OK: rawisa.m
9 | OR
10 | (.* RAW ISA: .*\n)*
11 | no __DATA,__rawisa support
12 | OK: rawisa.m
13 | END
14 | */
15 |
16 | #include "test.h"
17 |
18 | int main()
19 | {
20 | fprintf(stderr, "\n");
21 | #if ! (SUPPORT_NONPOINTER_ISA && TARGET_OS_MAC && !TARGET_OS_IPHONE)
22 | // only 64-bit Mac supports this
23 | fprintf(stderr, "no __DATA,__rawisa support\n");
24 | #endif
25 | succeed(__FILE__);
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/test/readClassPair.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #if !__OBJC2__
6 |
7 | int main()
8 | {
9 | succeed(__FILE__);
10 | }
11 |
12 | #else
13 |
14 | #include
15 |
16 | // Reuse evil-class-def.m as a non-evil class definition.
17 |
18 | #define EVIL_SUPER 0
19 | #define EVIL_SUPER_META 0
20 | #define EVIL_SUB 0
21 | #define EVIL_SUB_META 0
22 |
23 | #define OMIT_SUPER 1
24 | #define OMIT_NL_SUPER 1
25 | #define OMIT_SUB 1
26 | #define OMIT_NL_SUB 1
27 |
28 | #include "evil-class-def.m"
29 |
30 | int main()
31 | {
32 | // This definition is ABI and is never allowed to change.
33 | testassert(OBJC_MAX_CLASS_SIZE == 32*sizeof(void*));
34 |
35 | struct objc_image_info ii = { 0, 0 };
36 |
37 | // Read a root class.
38 | testassert(!objc_getClass("Super"));
39 |
40 | extern intptr_t OBJC_CLASS_$_Super[OBJC_MAX_CLASS_SIZE/sizeof(void*)];
41 | Class Super = objc_readClassPair((__bridge Class)(void*)&OBJC_CLASS_$_Super, &ii);
42 | testassert(Super);
43 |
44 | testassert(objc_getClass("Super") == Super);
45 | testassert(0 == strcmp(class_getName(Super), "Super"));
46 | testassert(class_getSuperclass(Super) == nil);
47 | testassert(class_getClassMethod(Super, @selector(load)));
48 | testassert(class_getInstanceMethod(Super, @selector(load)));
49 | testassert(class_getInstanceVariable(Super, "super_ivar"));
50 | testassert(class_getInstanceSize(Super) == sizeof(void*));
51 | [Super load];
52 |
53 | // Read a non-root class.
54 | testassert(!objc_getClass("Sub"));
55 |
56 | extern intptr_t OBJC_CLASS_$_Sub[OBJC_MAX_CLASS_SIZE/sizeof(void*)];
57 | intptr_t Sub2_buf[OBJC_MAX_CLASS_SIZE/sizeof(void*)];
58 | memcpy(Sub2_buf, &OBJC_CLASS_$_Sub, sizeof(Sub2_buf));
59 | Class Sub = objc_readClassPair((__bridge Class)(void*)&OBJC_CLASS_$_Sub, &ii);
60 | testassert(Sub);
61 |
62 | testassert(0 == strcmp(class_getName(Sub), "Sub"));
63 | testassert(objc_getClass("Sub") == Sub);
64 | testassert(class_getSuperclass(Sub) == Super);
65 | testassert(class_getClassMethod(Sub, @selector(load)));
66 | testassert(class_getInstanceMethod(Sub, @selector(load)));
67 | testassert(class_getInstanceVariable(Sub, "sub_ivar"));
68 | testassert(class_getInstanceSize(Sub) == 2*sizeof(void*));
69 | [Sub load];
70 |
71 | // Reading a class whose name already exists fails.
72 | testassert(! objc_readClassPair((__bridge Class)(void*)Sub2_buf, &ii));
73 |
74 | succeed(__FILE__);
75 | }
76 |
77 | #endif
78 |
--------------------------------------------------------------------------------
/test/rr-autorelease-stacklogging.m:
--------------------------------------------------------------------------------
1 | // Test OBJC_DEBUG_POOL_ALLOCATION (which is also enabled by MallocStackLogging)
2 |
3 | // TEST_ENV OBJC_DEBUG_POOL_ALLOCATION=YES
4 | // TEST_CFLAGS -framework Foundation
5 | // TEST_CONFIG MEM=mrc
6 |
7 | #include "test.h"
8 |
9 | #define FOUNDATION 0
10 | #define NAME "rr-autorelease-stacklogging"
11 |
12 | #include "rr-autorelease2.m"
13 |
--------------------------------------------------------------------------------
/test/rr-autorelease.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | // TEST_CONFIG MEM=mrc
3 |
4 | #include "test.h"
5 |
6 | #define FOUNDATION 0
7 | #define NAME "rr-autorelease"
8 |
9 | #include "rr-autorelease2.m"
10 |
--------------------------------------------------------------------------------
/test/rr-nsautorelease.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | // TEST_CONFIG MEM=mrc
3 |
4 | #define FOUNDATION 1
5 | #define NAME "rr-nsautorelease"
6 |
7 | #include "rr-autorelease2.m"
8 |
--------------------------------------------------------------------------------
/test/rr-sidetable.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 | // TEST_CONFIG MEM=mrc ARCH=x86_64
3 |
4 | // Stress-test nonpointer isa's side table retain count transfers.
5 |
6 | // x86_64 only. arm64's side table limit is high enough that bugs
7 | // are harder to reproduce.
8 |
9 | #include "test.h"
10 | #import
11 |
12 | #define OBJECTS 1
13 | #define LOOPS 256
14 | #define THREADS 16
15 | #if __x86_64__
16 | # define RC_HALF (1ULL<<7)
17 | #else
18 | # error sorry
19 | #endif
20 | #define RC_DELTA RC_HALF
21 |
22 | static bool Deallocated = false;
23 | @interface Deallocator : NSObject @end
24 | @implementation Deallocator
25 | -(void)dealloc {
26 | Deallocated = true;
27 | [super dealloc];
28 | }
29 | @end
30 |
31 | // This is global to avoid extra retains by the dispatch block objects.
32 | static Deallocator *obj;
33 |
34 | int main() {
35 | dispatch_queue_t queue =
36 | dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
37 |
38 | for (size_t i = 0; i < OBJECTS; i++) {
39 | obj = [Deallocator new];
40 |
41 | dispatch_apply(THREADS, queue, ^(size_t i __unused) {
42 | for (size_t a = 0; a < LOOPS; a++) {
43 | for (size_t b = 0; b < RC_DELTA; b++) {
44 | [obj retain];
45 | }
46 | for (size_t b = 0; b < RC_DELTA; b++) {
47 | [obj release];
48 | }
49 | }
50 | });
51 |
52 | testassert(!Deallocated);
53 | [obj release];
54 | testassert(Deallocated);
55 | Deallocated = false;
56 | }
57 |
58 | succeed(__FILE__);
59 | }
60 |
--------------------------------------------------------------------------------
/test/sel.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 | #include
7 |
8 | int main()
9 | {
10 | // Make sure @selector values are correctly fixed up
11 | testassert(@selector(foo) == sel_registerName("foo"));
12 |
13 | // sel_getName recognizes the zero SEL
14 | testassert(0 == strcmp("", sel_getName(0)));
15 |
16 | // GC-ignored selectors.
17 | #if __has_feature(objc_arc)
18 |
19 | // ARC dislikes `@selector(retain)`
20 |
21 | #else
22 |
23 | # if defined(__i386__)
24 | // sel_getName recognizes GC-ignored SELs
25 | if (objc_collectingEnabled()) {
26 | testassert(0 == strcmp("",
27 | sel_getName(@selector(retain))));
28 | } else {
29 | testassert(0 == strcmp("retain",
30 | sel_getName(@selector(retain))));
31 | }
32 |
33 | // _objc_search_builtins() shouldn't crash on GC-ignored SELs
34 | union {
35 | SEL sel;
36 | const char *ptr;
37 | } u;
38 | u.sel = @selector(retain);
39 | testassert(@selector(retain) == sel_registerName(u.ptr));
40 | # endif
41 |
42 | #endif
43 |
44 | succeed(__FILE__);
45 | }
46 |
--------------------------------------------------------------------------------
/test/setSuper.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -Wno-deprecated-declarations
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | @interface Super1 : TestRoot @end
8 | @implementation Super1
9 | +(int)classMethod { return 1; }
10 | -(int)instanceMethod { return 10000; }
11 | @end
12 |
13 | @interface Super2 : TestRoot @end
14 | @implementation Super2
15 | +(int)classMethod { return 2; }
16 | -(int)instanceMethod { return 20000; }
17 | @end
18 |
19 | @interface Sub : Super1 @end
20 | @implementation Sub
21 | +(int)classMethod { return [super classMethod] + 100; }
22 | -(int)instanceMethod {
23 | return [super instanceMethod] + 1000000;
24 | }
25 | @end
26 |
27 | int main()
28 | {
29 | Class cls;
30 | Sub *obj = [Sub new];
31 |
32 | testassert(101 == [[Sub class] classMethod]);
33 | testassert(1010000 == [obj instanceMethod]);
34 |
35 | cls = class_setSuperclass([Sub class], [Super2 class]);
36 |
37 | testassert(cls == [Super1 class]);
38 | testassert(object_getClass(cls) == object_getClass([Super1 class]));
39 |
40 | testassert(102 == [[Sub class] classMethod]);
41 | testassert(1020000 == [obj instanceMethod]);
42 |
43 | succeed(__FILE__);
44 | }
45 |
--------------------------------------------------------------------------------
/test/super.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include "testroot.i"
5 | #include
6 |
7 | @interface Sub : TestRoot @end
8 | @implementation Sub @end
9 |
10 | int main()
11 | {
12 | // [super ...] messages are tested in msgSend.m
13 |
14 | testassert(class_getSuperclass([Sub class]) == [TestRoot class]);
15 | testassert(class_getSuperclass(object_getClass([Sub class])) == object_getClass([TestRoot class]));
16 | testassert(class_getSuperclass([TestRoot class]) == Nil);
17 | testassert(class_getSuperclass(object_getClass([TestRoot class])) == [TestRoot class]);
18 | testassert(class_getSuperclass(Nil) == Nil);
19 |
20 | succeed(__FILE__);
21 | }
22 |
--------------------------------------------------------------------------------
/test/synchronized-counter.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | // synchronized stress test
13 | // Single locked counter incremented by many threads.
14 |
15 | #if defined(__arm__)
16 | #define THREADS 16
17 | #define COUNT 1024*24
18 | #else
19 | // 64 / 1024*24 test takes about 20s on 4x2.6GHz Mac Pro
20 | #define THREADS 64
21 | #define COUNT 1024*24
22 | #endif
23 |
24 | static id lock;
25 | static int count;
26 |
27 | static void *threadfn(void *arg)
28 | {
29 | int n, d;
30 | int depth = 1 + (int)(intptr_t)arg % 4;
31 |
32 | objc_registerThreadWithCollector();
33 |
34 | for (n = 0; n < COUNT; n++) {
35 | // Lock
36 | for (d = 0; d < depth; d++) {
37 | int err = objc_sync_enter(lock);
38 | testassert(err == OBJC_SYNC_SUCCESS);
39 | }
40 |
41 | // Increment
42 | count++;
43 |
44 | // Unlock
45 | for (d = 0; d < depth; d++) {
46 | int err = objc_sync_exit(lock);
47 | testassert(err == OBJC_SYNC_SUCCESS);
48 | }
49 | }
50 |
51 | // Verify lack of objc pthread data (should have used sync fast cache)
52 | #ifdef __PTK_FRAMEWORK_OBJC_KEY0
53 | testassert(! pthread_getspecific(__PTK_FRAMEWORK_OBJC_KEY0));
54 | #endif
55 |
56 | return NULL;
57 | }
58 |
59 | int main()
60 | {
61 | pthread_t threads[THREADS];
62 | int t;
63 | int err;
64 |
65 | lock = [[NSObject alloc] init];
66 |
67 | // Verify objc pthread data on this thread (from +initialize)
68 | // Worker threads shouldn't have any because of sync fast cache.
69 | #ifdef __PTK_FRAMEWORK_OBJC_KEY0
70 | testassert(pthread_getspecific(__PTK_FRAMEWORK_OBJC_KEY0));
71 | #endif
72 |
73 | // Start the threads
74 | for (t = 0; t < THREADS; t++) {
75 | pthread_create(&threads[t], NULL, &threadfn, (void*)(intptr_t)t);
76 | }
77 |
78 | // Wait for threads to finish
79 | for (t = 0; t < THREADS; t++) {
80 | pthread_join(threads[t], NULL);
81 | }
82 |
83 | // Verify lock: should be available
84 | // Verify count: should be THREADS*COUNT
85 | err = objc_sync_enter(lock);
86 | testassert(err == OBJC_SYNC_SUCCESS);
87 | testassert(count == THREADS*COUNT);
88 |
89 | succeed(__FILE__);
90 | }
91 |
--------------------------------------------------------------------------------
/test/synchronized-grid.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | // synchronized stress test
12 | // 2-D grid of counters and locks.
13 | // Each thread increments all counters some number of times.
14 | // To increment:
15 | // * thread picks a target [row][col]
16 | // * thread locks all locks [row][0] to [row][col], possibly recursively
17 | // * thread increments counter [row][col]
18 | // * thread unlocks all of the locks
19 |
20 | #if defined(__arm__)
21 | // 16 / 4 / 3 / 1024*8 test takes about 30s on 2nd gen iPod touch
22 | #define THREADS 16
23 | #define ROWS 4
24 | #define COLS 3
25 | #define COUNT 1024*8
26 | #else
27 | // 64 / 4 / 3 / 1024*8 test takes about 20s on 4x2.6GHz Mac Pro
28 | #define THREADS 64
29 | #define ROWS 4
30 | #define COLS 3
31 | #define COUNT 1024*8
32 | #endif
33 |
34 | static id locks[ROWS][COLS];
35 | static int counts[ROWS][COLS];
36 |
37 |
38 | static void *threadfn(void *arg)
39 | {
40 | int n, d;
41 | int depth = 1 + (int)(intptr_t)arg % 4;
42 |
43 | objc_registerThreadWithCollector();
44 |
45 | for (n = 0; n < COUNT; n++) {
46 | int rrr = rand() % ROWS;
47 | int ccc = rand() % COLS;
48 | int rr, cc;
49 | for (rr = 0; rr < ROWS; rr++) {
50 | int r = (rrr+rr) % ROWS;
51 | for (cc = 0; cc < COLS; cc++) {
52 | int c = (ccc+cc) % COLS;
53 | int l;
54 |
55 | // Lock [r][0..c]
56 | // ... in that order to prevent deadlock
57 | for (l = 0; l <= c; l++) {
58 | for (d = 0; d < depth; d++) {
59 | int err = objc_sync_enter(locks[r][l]);
60 | testassert(err == OBJC_SYNC_SUCCESS);
61 | }
62 | }
63 |
64 | // Increment count [r][c]
65 | counts[r][c]++;
66 |
67 | // Unlock [r][0..c]
68 | // ... in that order to increase contention
69 | for (l = 0; l <= c; l++) {
70 | for (d = 0; d < depth; d++) {
71 | int err = objc_sync_exit(locks[r][l]);
72 | testassert(err == OBJC_SYNC_SUCCESS);
73 | }
74 | }
75 | }
76 | }
77 | }
78 |
79 | return NULL;
80 | }
81 |
82 | int main()
83 | {
84 | pthread_t threads[THREADS];
85 | int r, c, t;
86 |
87 | for (r = 0; r < ROWS; r++) {
88 | for (c = 0; c < COLS; c++) {
89 | locks[r][c] = [[NSObject alloc] init];
90 | }
91 | }
92 |
93 | // Start the threads
94 | for (t = 0; t < THREADS; t++) {
95 | pthread_create(&threads[t], NULL, &threadfn, (void*)(intptr_t)t);
96 | }
97 |
98 | // Wait for threads to finish
99 | for (t = 0; t < THREADS; t++) {
100 | pthread_join(threads[t], NULL);
101 | }
102 |
103 | // Verify locks: all should be available
104 | // Verify counts: all should be THREADS*COUNT
105 | for (r = 0; r < ROWS; r++) {
106 | for (c = 0; c < COLS; c++) {
107 | int err = objc_sync_enter(locks[r][c]);
108 | testassert(err == OBJC_SYNC_SUCCESS);
109 | testassert(counts[r][c] == THREADS*COUNT);
110 | }
111 | }
112 |
113 | succeed(__FILE__);
114 | }
115 |
--------------------------------------------------------------------------------
/test/synchronized.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | // Basic @synchronized tests.
13 |
14 |
15 | #define WAIT_SEC 3
16 |
17 | static id obj;
18 | static semaphore_t go;
19 | static semaphore_t stop;
20 |
21 | void *thread(void *arg __unused)
22 | {
23 | int err;
24 |
25 | objc_registerThreadWithCollector();
26 |
27 | // non-blocking sync_enter
28 | err = objc_sync_enter(obj);
29 | testassert(err == OBJC_SYNC_SUCCESS);
30 |
31 | semaphore_signal(go);
32 | // main thread: sync_exit of object locked on some other thread
33 | semaphore_wait(stop);
34 |
35 | err = objc_sync_exit(obj);
36 | testassert(err == OBJC_SYNC_SUCCESS);
37 | err = objc_sync_enter(obj);
38 | testassert(err == OBJC_SYNC_SUCCESS);
39 |
40 | semaphore_signal(go);
41 | // main thread: blocking sync_enter
42 | testassert(WAIT_SEC/3*3 == WAIT_SEC);
43 | sleep(WAIT_SEC/3);
44 | // recursive enter while someone waits
45 | err = objc_sync_enter(obj);
46 | testassert(err == OBJC_SYNC_SUCCESS);
47 | sleep(WAIT_SEC/3);
48 | // recursive exit while someone waits
49 | err = objc_sync_exit(obj);
50 | testassert(err == OBJC_SYNC_SUCCESS);
51 | sleep(WAIT_SEC/3);
52 | // sync_exit while someone waits
53 | err = objc_sync_exit(obj);
54 | testassert(err == OBJC_SYNC_SUCCESS);
55 |
56 | return NULL;
57 | }
58 |
59 | int main()
60 | {
61 | pthread_t th;
62 | int err;
63 | struct timeval start, end;
64 |
65 | obj = [[NSObject alloc] init];
66 |
67 | // sync_exit of never-locked object
68 | err = objc_sync_exit(obj);
69 | testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR);
70 |
71 | semaphore_create(mach_task_self(), &go, 0, 0);
72 | semaphore_create(mach_task_self(), &stop, 0, 0);
73 | pthread_create(&th, NULL, &thread, NULL);
74 | semaphore_wait(go);
75 |
76 | // sync_exit of object locked on some other thread
77 | err = objc_sync_exit(obj);
78 | testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR);
79 |
80 | semaphore_signal(stop);
81 | semaphore_wait(go);
82 |
83 | // blocking sync_enter
84 | gettimeofday(&start, NULL);
85 | err = objc_sync_enter(obj);
86 | gettimeofday(&end, NULL);
87 | testassert(err == OBJC_SYNC_SUCCESS);
88 | // should have waited more than WAIT_SEC but less than WAIT_SEC+1
89 | // fixme hack: sleep(1) is ending 500 usec too early on x86_64 buildbot
90 | // (rdar://6456975)
91 | testassert(end.tv_sec*1000000LL+end.tv_usec >=
92 | start.tv_sec*1000000LL+start.tv_usec + WAIT_SEC*1000000LL
93 | - 3*500 /*hack*/);
94 | testassert(end.tv_sec*1000000LL+end.tv_usec <
95 | start.tv_sec*1000000LL+start.tv_usec + (1+WAIT_SEC)*1000000LL);
96 |
97 | err = objc_sync_exit(obj);
98 | testassert(err == OBJC_SYNC_SUCCESS);
99 |
100 | err = objc_sync_exit(obj);
101 | testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR);
102 |
103 | succeed(__FILE__);
104 | }
105 |
--------------------------------------------------------------------------------
/test/taggedNSPointers.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS -framework Foundation
2 |
3 | #include "test.h"
4 | #include
5 | #import
6 |
7 | #if OBJC_HAVE_TAGGED_POINTERS
8 |
9 | void testTaggedNumber()
10 | {
11 | NSNumber *taggedNS = [NSNumber numberWithInt: 1234];
12 | CFNumberRef taggedCF = (CFNumberRef)objc_unretainedPointer(taggedNS);
13 | int result;
14 |
15 | testassert( CFGetTypeID(taggedCF) == CFNumberGetTypeID() );
16 | testassert(_objc_getClassForTag(OBJC_TAG_NSNumber) == [taggedNS class]);
17 |
18 | CFNumberGetValue(taggedCF, kCFNumberIntType, &result);
19 | testassert(result == 1234);
20 |
21 | testassert(_objc_isTaggedPointer(taggedCF));
22 | testassert(_objc_getTaggedPointerTag(taggedCF) == OBJC_TAG_NSNumber);
23 | testassert(_objc_makeTaggedPointer(_objc_getTaggedPointerTag(taggedCF), _objc_getTaggedPointerValue(taggedCF)) == taggedCF);
24 |
25 | // do some generic object-y things to the taggedPointer instance
26 | CFRetain(taggedCF);
27 | CFRelease(taggedCF);
28 |
29 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
30 | [dict setObject: taggedNS forKey: @"fred"];
31 | testassert(taggedNS == [dict objectForKey: @"fred"]);
32 | [dict setObject: @"bob" forKey: taggedNS];
33 | testassert([@"bob" isEqualToString: [dict objectForKey: taggedNS]]);
34 |
35 | NSNumber *iM88 = [NSNumber numberWithInt:-88];
36 | NSNumber *i12346 = [NSNumber numberWithInt: 12346];
37 | NSNumber *i12347 = [NSNumber numberWithInt: 12347];
38 |
39 | NSArray *anArray = [NSArray arrayWithObjects: iM88, i12346, i12347, nil];
40 | testassert([anArray count] == 3);
41 | testassert([anArray indexOfObject: i12346] == 1);
42 |
43 | NSSet *aSet = [NSSet setWithObjects: iM88, i12346, i12347, nil];
44 | testassert([aSet count] == 3);
45 | testassert([aSet containsObject: i12346]);
46 |
47 | [taggedNS performSelector: @selector(intValue)];
48 | testassert(![taggedNS isProxy]);
49 | testassert([taggedNS isKindOfClass: [NSNumber class]]);
50 | testassert([taggedNS respondsToSelector: @selector(intValue)]);
51 |
52 | (void)[taggedNS description];
53 | }
54 |
55 | int main()
56 | {
57 | PUSH_POOL {
58 | testTaggedNumber(); // should be tested by CF... our tests are wrong, wrong, wrong.
59 | } POP_POOL;
60 |
61 | succeed(__FILE__);
62 | }
63 |
64 | // OBJC_HAVE_TAGGED_POINTERS
65 | #else
66 | // not OBJC_HAVE_TAGGED_POINTERS
67 |
68 | // Tagged pointers not supported. Crash if an NSNumber actually
69 | // is a tagged pointer (which means this test is out of date).
70 |
71 | int main()
72 | {
73 | PUSH_POOL {
74 | testassert(*(void **)objc_unretainedPointer([NSNumber numberWithInt:1234]));
75 | } POP_POOL;
76 |
77 | succeed(__FILE__);
78 | }
79 |
80 | #endif
81 |
--------------------------------------------------------------------------------
/test/taggedPointersDisabled.m:
--------------------------------------------------------------------------------
1 | // TEST_ENV OBJC_DISABLE_TAGGED_POINTERS=YES
2 | // TEST_CRASHES
3 | /*
4 | TEST_RUN_OUTPUT
5 | objc\[\d+\]: tagged pointers are disabled
6 | CRASHED: SIG(ILL|TRAP)
7 | OR
8 | OK: taggedPointersDisabled.m
9 | END
10 | */
11 |
12 | #include "test.h"
13 | #include
14 |
15 | #if !OBJC_HAVE_TAGGED_POINTERS
16 |
17 | int main()
18 | {
19 | succeed(__FILE__);
20 | }
21 |
22 | #else
23 |
24 | int main()
25 | {
26 | testassert(!_objc_taggedPointersEnabled());
27 | _objc_registerTaggedPointerClass((objc_tag_index_t)0, nil);
28 | fail("should have crashed in _objc_registerTaggedPointerClass()");
29 | }
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/test/tbi.c:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG OS=iphoneos ARCH=arm64
2 |
3 | #include "test.h"
4 |
5 | #ifndef __arm64__
6 | #error wrong architecture for TBI hardware feature
7 | #endif
8 |
9 | volatile int x = 123456;
10 |
11 | int main(void) {
12 | testassert(*(int *)((unsigned long)&x | 0xFF00000000000000ul) == 123456);
13 | succeed(__FILE__);
14 | }
15 |
--------------------------------------------------------------------------------
/test/unload.h:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | @interface SmallClass : TestRoot @end
4 |
5 | @interface BigClass : TestRoot @end
6 |
7 |
--------------------------------------------------------------------------------
/test/unload2.m:
--------------------------------------------------------------------------------
1 | #include "unload.h"
2 | #include "testroot.i"
3 | #import
4 |
5 | @implementation SmallClass : TestRoot
6 | -(void)unload2_instance_method { }
7 | @end
8 |
9 |
10 | @implementation BigClass : TestRoot
11 | @end
12 |
13 | OBJC_ROOT_CLASS
14 | @interface UnusedClass { id isa; } @end
15 | @implementation UnusedClass @end
16 |
17 |
18 | @protocol SmallProtocol
19 | -(void)unload2_category_method;
20 | @end
21 |
22 | @interface SmallClass (Category) @end
23 |
24 | @implementation SmallClass (Category)
25 | -(void)unload2_category_method { }
26 | @end
27 |
--------------------------------------------------------------------------------
/test/unload3.c:
--------------------------------------------------------------------------------
1 | // unload3: contains imageinfo but no other objc metadata
2 | // libobjc must not keep it open
3 | // DO NOT USE __OBJC2__; this is a C file.
4 |
5 | #include
6 |
7 | #if TARGET_OS_WIN32 || (TARGET_OS_MAC && TARGET_CPU_X86 && !TARGET_IPHONE_SIMULATOR)
8 | // old ABI
9 | int fake[2] __attribute__((section("__OBJC,__image_info")))
10 | #else
11 | // new ABI
12 | int fake[2] __attribute__((section("__DATA,__objc_imageinfo")))
13 | #endif
14 | = { 0, TARGET_IPHONE_SIMULATOR ? (1<<5) : 0 };
15 |
16 | // silence "no debug symbols in executable" warning
17 | void fn(void) { }
18 |
--------------------------------------------------------------------------------
/test/unload4.m:
--------------------------------------------------------------------------------
1 | // unload4: contains some objc metadata other than imageinfo
2 | // libobjc must keep it open
3 |
4 | #if __OBJC2__
5 | int fake2 __attribute__((section("__DATA,__objc_foo"))) = 0;
6 | #else
7 | int fake2 __attribute__((section("__OBJC,__foo"))) = 0;
8 | #endif
9 |
10 | // getsectiondata() falls over if __TEXT has no contents
11 | const char *unload4 = "unload4";
12 |
--------------------------------------------------------------------------------
/test/unwind.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | #if !defined(__OBJC2__)
8 |
9 | int main()
10 | {
11 | succeed(__FILE__);
12 | }
13 |
14 | #else
15 |
16 | static int state;
17 |
18 | @interface Foo : NSObject @end
19 | @interface Bar : NSObject @end
20 |
21 | @interface Foo (Unimplemented)
22 | +(void)method;
23 | @end
24 |
25 | @implementation Bar @end
26 |
27 | @implementation Foo
28 |
29 | -(void)check { state++; }
30 | +(void)check { testassert(!"caught class object, not instance"); }
31 |
32 | static id exc;
33 |
34 | static void handler(id unused, void *ctx) __attribute__((used));
35 | static void handler(id unused __unused, void *ctx __unused)
36 | {
37 | testassert(state == 3); state++;
38 | }
39 |
40 | +(BOOL) resolveClassMethod:(SEL)__unused name
41 | {
42 | testassert(state == 1); state++;
43 | #if !TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
44 | objc_addExceptionHandler(&handler, 0);
45 | testassert(state == 2);
46 | #else
47 | state++; // handler would have done this
48 | #endif
49 | state++;
50 | exc = [Foo new];
51 | @throw exc;
52 | }
53 |
54 |
55 | @end
56 |
57 | int main()
58 | {
59 | int i;
60 |
61 | // unwind exception and alt handler through objc_msgSend()
62 |
63 | PUSH_POOL {
64 |
65 | state = 0;
66 | for (i = 0; i < 100000; i++) {
67 | @try {
68 | testassert(state == 0); state++;
69 | [Foo method];
70 | testassert(0);
71 | } @catch (Bar *e) {
72 | testassert(0);
73 | } @catch (Foo *e) {
74 | testassert(e == exc);
75 | testassert(state == 4); state++;
76 | testassert(state == 5); [e check]; // state++
77 | RELEASE_VAR(exc);
78 | } @catch (id e) {
79 | testassert(0);
80 | } @catch (...) {
81 | testassert(0);
82 | } @finally {
83 | testassert(state == 6); state++;
84 | }
85 | testassert(state == 7); state = 0;
86 | }
87 |
88 | } POP_POOL;
89 |
90 | succeed(__FILE__);
91 | }
92 |
93 | #endif
94 |
--------------------------------------------------------------------------------
/test/weak.h:
--------------------------------------------------------------------------------
1 | /*
2 | To test -weak-l or -weak-framework:
3 | * -DWEAK_IMPORT=
4 | * -DWEAK_FRAMEWORK=1
5 | * -UEMPTY when building the weak-not-missing library
6 | * -DEMPTY= when building the weak-missing library
7 |
8 | To test attribute((weak_import)):
9 | * -DWEAK_IMPORT=__attribute__((weak_import))
10 | * -UWEAK_FRAMEWORK
11 | * -UEMPTY when building the weak-not-missing library
12 | * -DEMPTY= when building the weak-missing library
13 |
14 | */
15 |
16 | #include "test.h"
17 | #include
18 |
19 | extern int state;
20 |
21 | WEAK_IMPORT OBJC_ROOT_CLASS
22 | @interface MissingRoot {
23 | id isa;
24 | }
25 | +(void) initialize;
26 | +(Class) class;
27 | +(id) alloc;
28 | -(id) init;
29 | -(void) dealloc;
30 | +(int) method;
31 | @end
32 |
33 | @interface MissingRoot (RR)
34 | -(id) retain;
35 | -(void) release;
36 | @end
37 |
38 | WEAK_IMPORT
39 | @interface MissingSuper : MissingRoot {
40 | @public
41 | int ivar;
42 | }
43 | @end
44 |
45 | OBJC_ROOT_CLASS
46 | @interface NotMissingRoot {
47 | id isa;
48 | }
49 | +(void) initialize;
50 | +(Class) class;
51 | +(id) alloc;
52 | -(id) init;
53 | -(void) dealloc;
54 | +(int) method;
55 | @end
56 |
57 | @interface NotMissingRoot (RR)
58 | -(id) retain;
59 | -(void) release;
60 | @end
61 |
62 | @interface NotMissingSuper : NotMissingRoot {
63 | @public
64 | int unused[100];
65 | int ivar;
66 | }
67 | @end
68 |
--------------------------------------------------------------------------------
/test/weak2.m:
--------------------------------------------------------------------------------
1 | // See instructions in weak.h
2 |
3 | #include "test.h"
4 | #include "weak.h"
5 | #include
6 |
7 | int state = 0;
8 |
9 | static void *noop_fn(void *self, SEL _cmd __unused) {
10 | return self;
11 | }
12 | static void *retain_fn(void *self, SEL _cmd __unused) {
13 | void * (*fn)(void *) = (typeof(fn))_objc_rootRetain;
14 | return fn(self);
15 | }
16 | static void release_fn(void *self, SEL _cmd __unused) {
17 | void (*fn)(void *) = (typeof(fn))_objc_rootRelease;
18 | fn(self);
19 | }
20 | static void *autorelease_fn(void *self, SEL _cmd __unused) {
21 | void * (*fn)(void *) = (typeof(fn))_objc_rootAutorelease;
22 | return fn(self);
23 | }
24 |
25 | #if !defined(EMPTY)
26 |
27 | @implementation MissingRoot
28 | +(void) initialize { }
29 | +(Class) class { return self; }
30 | +(id) alloc { return _objc_rootAlloc(self); }
31 | +(id) allocWithZone:(void*)zone { return _objc_rootAllocWithZone(self, (malloc_zone_t *)zone); }
32 | -(id) init { return self; }
33 | -(void) dealloc { _objc_rootDealloc(self); }
34 | +(int) method { return 10; }
35 | +(void) load {
36 | class_addMethod(self, sel_registerName("retain"), (IMP)retain_fn, "");
37 | class_addMethod(self, sel_registerName("release"), (IMP)release_fn, "");
38 | class_addMethod(self, sel_registerName("autorelease"), (IMP)autorelease_fn, "");
39 |
40 | class_addMethod(object_getClass(self), sel_registerName("retain"), (IMP)noop_fn, "");
41 | class_addMethod(object_getClass(self), sel_registerName("release"), (IMP)noop_fn, "");
42 | class_addMethod(object_getClass(self), sel_registerName("autorelease"), (IMP)noop_fn, "");
43 |
44 | state++;
45 | }
46 | @end
47 |
48 | @implementation MissingSuper
49 | +(int) method { return 1+[super method]; }
50 | -(id) init { self = [super init]; ivar = 100; return self; }
51 | +(void) load { state++; }
52 | @end
53 |
54 | #endif
55 |
56 | @implementation NotMissingRoot
57 | +(void) initialize { }
58 | +(Class) class { return self; }
59 | +(id) alloc { return _objc_rootAlloc(self); }
60 | +(id) allocWithZone:(void*)zone { return _objc_rootAllocWithZone(self, (malloc_zone_t *)zone); }
61 | -(id) init { return self; }
62 | -(void) dealloc { _objc_rootDealloc(self); }
63 | +(int) method { return 20; }
64 | +(void) load {
65 | class_addMethod(self, sel_registerName("retain"), (IMP)retain_fn, "");
66 | class_addMethod(self, sel_registerName("release"), (IMP)release_fn, "");
67 | class_addMethod(self, sel_registerName("autorelease"), (IMP)autorelease_fn, "");
68 |
69 | class_addMethod(object_getClass(self), sel_registerName("retain"), (IMP)noop_fn, "");
70 | class_addMethod(object_getClass(self), sel_registerName("release"), (IMP)noop_fn, "");
71 | class_addMethod(object_getClass(self), sel_registerName("autorelease"), (IMP)noop_fn, "");
72 |
73 | state++;
74 | }
75 | @end
76 |
77 | @implementation NotMissingSuper
78 | +(int) method { return 1+[super method]; }
79 | -(id) init { self = [super init]; ivar = 200; return self; }
80 | +(void) load { state++; }
81 | @end
82 |
83 |
--------------------------------------------------------------------------------
/test/weakcopy.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 |
5 | #if __OBJC_GC__ && __cplusplus && __i386__
6 |
7 | int main()
8 | {
9 | testwarn("rdar://19042235 test disabled for 32-bit objc++ GC because of unknown bit rot");
10 | succeed(__FILE__);
11 | }
12 |
13 | #else
14 |
15 | #include "testroot.i"
16 | #include
17 | #include
18 | #include
19 |
20 | @interface Weak : TestRoot {
21 | @public
22 | __weak id value;
23 | }
24 | @end
25 | @implementation Weak
26 | @end
27 |
28 | Weak *oldObject;
29 | Weak *newObject;
30 |
31 | void *fn(void *arg __unused)
32 | {
33 | objc_registerThreadWithCollector();
34 |
35 | return NULL;
36 | }
37 |
38 | int main()
39 | {
40 | testonthread(^{
41 | TestRoot *value;
42 |
43 | PUSH_POOL {
44 | value = [TestRoot new];
45 | testassert(value);
46 | oldObject = [Weak new];
47 | testassert(oldObject);
48 |
49 | oldObject->value = value;
50 | testassert(oldObject->value == value);
51 |
52 | newObject = [oldObject copy];
53 | testassert(newObject);
54 | testassert(newObject->value == oldObject->value);
55 |
56 | newObject->value = nil;
57 | testassert(newObject->value == nil);
58 | testassert(oldObject->value == value);
59 | } POP_POOL;
60 |
61 | testcollect();
62 | TestRootDealloc = 0;
63 | TestRootFinalize = 0;
64 | RELEASE_VAR(value);
65 | });
66 |
67 | testcollect();
68 | testassert(TestRootDealloc || TestRootFinalize);
69 |
70 | #if defined(__OBJC_GC__) || __has_feature(objc_arc)
71 | testassert(oldObject->value == nil);
72 | #else
73 | testassert(oldObject->value != nil);
74 | #endif
75 | testassert(newObject->value == nil);
76 |
77 | RELEASE_VAR(newObject);
78 | RELEASE_VAR(oldObject);
79 |
80 | succeed(__FILE__);
81 | return 0;
82 | }
83 |
84 | #endif
85 |
--------------------------------------------------------------------------------
/test/weakframework-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -DWEAK_FRAMEWORK=1 -DWEAK_IMPORT= -UEMPTY -dynamiclib -o libweakframework.dylib
4 |
5 | $C{COMPILE} $DIR/weakframework-missing.m -L. -weak-lweakframework -o weakframework-missing.out
6 |
7 | $C{COMPILE} $DIR/weak2.m -DWEAK_FRAMEWORK=1 -DWEAK_IMPORT= -DEMPTY= -dynamiclib -o libweakframework.dylib
8 |
9 | END
10 | */
11 |
12 | #define WEAK_FRAMEWORK 1
13 | #define WEAK_IMPORT
14 | #include "weak.m"
15 |
--------------------------------------------------------------------------------
/test/weakframework-not-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -DWEAK_FRAMEWORK=1 -DWEAK_IMPORT= -UEMPTY -dynamiclib -o libweakframework.dylib
4 |
5 | $C{COMPILE} $DIR/weakframework-not-missing.m -L. -weak-lweakframework -o weakframework-not-missing.out
6 | END
7 | */
8 |
9 | #define WEAK_FRAMEWORK 1
10 | #define WEAK_IMPORT
11 | #include "weak.m"
12 |
--------------------------------------------------------------------------------
/test/weakimport-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -UWEAK_FRAMEWORK -DWEAK_IMPORT=__attribute__\\(\\(weak_import\\)\\) -UEMPTY -dynamiclib -o libweakimport.dylib
4 |
5 | $C{COMPILE} $DIR/weakimport-missing.m -L. -weak-lweakimport -o weakimport-missing.out
6 |
7 | $C{COMPILE} $DIR/weak2.m -UWEAK_FRAMEWORK -DWEAK_IMPORT=__attribute__\\(\\(weak_import\\)\\) -DEMPTY= -dynamiclib -o libweakimport.dylib
8 | END
9 | */
10 |
11 | // #define WEAK_FRAMEWORK
12 | #define WEAK_IMPORT __attribute__((weak_import))
13 | #include "weak.m"
14 |
--------------------------------------------------------------------------------
/test/weakimport-not-missing.m:
--------------------------------------------------------------------------------
1 | /*
2 | TEST_BUILD
3 | $C{COMPILE} $DIR/weak2.m -UWEAK_FRAMEWORK -DWEAK_IMPORT=__attribute__\\(\\(weak_import\\)\\) -UEMPTY -dynamiclib -o libweakimport.dylib
4 |
5 | $C{COMPILE} $DIR/weakimport-not-missing.m -L. -weak-lweakimport -o weakimport-not-missing.out
6 | END
7 | */
8 |
9 | // #define WEAK_FRAMEWORK
10 | #define WEAK_IMPORT __attribute__((weak_import))
11 | #include "weak.m"
12 |
--------------------------------------------------------------------------------
/test/weakrace.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG MEM=mrc
2 |
3 | #include "test.h"
4 | #include
5 |
6 | static semaphore_t go1;
7 | static semaphore_t go2;
8 | static semaphore_t done;
9 |
10 | #define VARCOUNT 100000
11 | static id obj;
12 | static id vars[VARCOUNT];
13 |
14 |
15 | void *destroyer(void *arg __unused)
16 | {
17 | while (1) {
18 | semaphore_wait(go1);
19 | for (int i = 0; i < VARCOUNT; i++) {
20 | objc_destroyWeak(&vars[i]);
21 | }
22 | semaphore_signal(done);
23 | }
24 | }
25 |
26 |
27 | void *deallocator(void *arg __unused)
28 | {
29 | while (1) {
30 | semaphore_wait(go2);
31 | [obj release];
32 | semaphore_signal(done);
33 | }
34 | }
35 |
36 |
37 | void cycle(void)
38 | {
39 | // rdar://12896779 objc_destroyWeak() versus weak clear in dealloc
40 |
41 | // Clean up from previous cycle - objc_destroyWeak() doesn't set var to nil
42 | for (int i = 0; i < VARCOUNT; i++) {
43 | vars[i] = nil;
44 | }
45 |
46 | obj = [NSObject new];
47 | for (int i = 0; i < VARCOUNT; i++) {
48 | objc_storeWeak(&vars[i], obj);
49 | }
50 |
51 | // let destroyer start before deallocator runs
52 | semaphore_signal(go1);
53 | sched_yield();
54 | semaphore_signal(go2);
55 |
56 | semaphore_wait(done);
57 | semaphore_wait(done);
58 | }
59 |
60 |
61 | int main()
62 | {
63 | semaphore_create(mach_task_self(), &go1, 0, 0);
64 | semaphore_create(mach_task_self(), &go2, 0, 0);
65 | semaphore_create(mach_task_self(), &done, 0, 0);
66 |
67 | pthread_t th[2];
68 | pthread_create(&th[1], NULL, deallocator, NULL);
69 | pthread_create(&th[1], NULL, destroyer, NULL);
70 |
71 | for (int i = 0; i < 100; i++) {
72 | cycle();
73 | }
74 |
75 | succeed(__FILE__);
76 | }
77 |
--------------------------------------------------------------------------------
/test/xref.m:
--------------------------------------------------------------------------------
1 | // TEST_CFLAGS
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "test.h"
8 |
9 | int main()
10 | {
11 | // rdar://8350188 External references (handles)
12 |
13 | id object = [NSObject new];
14 | testassert(object);
15 |
16 | // STRONG
17 | objc_xref_t xref = _object_addExternalReference(object, OBJC_XREF_STRONG);
18 | testassert(xref);
19 | testassert(_object_readExternalReference(xref) == object);
20 | _object_removeExternalReference(xref);
21 | // TODO: expect a crash if a stale xref is used.
22 |
23 | // WEAK
24 | xref = _object_addExternalReference(object, OBJC_XREF_WEAK);
25 | testassert(xref);
26 | testassert(_object_readExternalReference(xref) == object);
27 | _object_removeExternalReference(xref);
28 |
29 | RELEASE_VAR(object);
30 |
31 | succeed(__FILE__);
32 | }
33 |
--------------------------------------------------------------------------------
/test/zone.m:
--------------------------------------------------------------------------------
1 | // TEST_CONFIG
2 |
3 | #include "test.h"
4 | #include
5 | #include
6 |
7 | // Look for malloc zone "ObjC" iff OBJC_USE_INTERNAL_ZONE is set.
8 | // This fails if objc tries to allocate before checking its own
9 | // environment variables (rdar://6688423)
10 |
11 | int main()
12 | {
13 | if (is_guardmalloc()) {
14 | // guard malloc confuses this test
15 | succeed(__FILE__);
16 | }
17 |
18 | kern_return_t kr;
19 | vm_address_t *zones;
20 | unsigned int count, i;
21 | BOOL has_objc = NO, want_objc = NO;
22 |
23 | want_objc = (getenv("OBJC_USE_INTERNAL_ZONE") != NULL) ? YES : NO;
24 | testprintf("want objc %s\n", want_objc ? "YES" : "NO");
25 |
26 | kr = malloc_get_all_zones(mach_task_self(), NULL, &zones, &count);
27 | testassert(!kr);
28 | for (i = 0; i < count; i++) {
29 | const char *name = malloc_get_zone_name((malloc_zone_t *)zones[i]);
30 | if (name) {
31 | BOOL is_objc = (0 == strcmp(name, "ObjC_Internal")) ? YES : NO;
32 | if (is_objc) has_objc = YES;
33 | testprintf("zone %s\n", name);
34 | }
35 | }
36 |
37 | testassert(want_objc == has_objc);
38 |
39 | succeed(__FILE__);
40 | }
41 |
--------------------------------------------------------------------------------
/unexported_symbols:
--------------------------------------------------------------------------------
1 | .objc_class_name___IncompleteProtocol
2 | __Znam
3 | __ZnamRKSt9nothrow_t
4 | __Znwm
5 | __ZnwmRKSt9nothrow_t
6 | __ZdaPv
7 | __ZdaPvRKSt9nothrow_t
8 | __ZdlPv
9 | __ZdlPvRKSt9nothrow_t
10 | __ZTISt9bad_alloc
11 | __ZTISt9exception
12 | __ZTISt11logic_error
13 | __ZTISt12length_error
14 | __ZTSSt9bad_alloc
15 | __ZTSSt9exception
16 | __ZTSSt11logic_error
17 | __ZTSSt12length_error
18 |
--------------------------------------------------------------------------------
/version.bat:
--------------------------------------------------------------------------------
1 | :: version.bat
2 | :: Writes version numbers from B&I into version.h for use by version.rc.
3 |
4 | @ECHO OFF
5 |
6 | :: Set default values for environment variables if not set by B&I
7 | IF "%OBJROOT%"=="" SET OBJROOT=.
8 | IF "%RC_PROJECTSOURCEVERSION%"=="" SET RC_PROJECTSOURCEVERSION=0.0
9 | IF "%RC_PROJECTBUILDVERSION%"=="" SET RC_PROJECTBUILDVERSION=0
10 |
11 | :: Get version numbers from environment variables
12 | SET major=1
13 | SET patch=0
14 | FOR /F "tokens=1* eol= delims=." %%i IN ("%RC_PROJECTSOURCEVERSION%") DO (
15 | SET minor=%%i
16 | IF NOT "%%j"=="" SET patch=%%j
17 | )
18 | SET build=%RC_PROJECTBUILDVERSION%
19 |
20 | ECHO version %major% . %minor% . %patch% . %build%
21 |
22 | :: Write version.h
23 | ECHO // This file is automatically generated by version.bat. > "%OBJROOT%\version.h"
24 | ECHO // DO NOT EDIT >> "%OBJROOT%\version.h"
25 | ECHO #define major %major% >> "%OBJROOT%\version.h"
26 | ECHO #define minor %minor% >> "%OBJROOT%\version.h"
27 | ECHO #define patch %patch% >> "%OBJROOT%\version.h"
28 | ECHO #define build %build% >> "%OBJROOT%\version.h"
29 | ECHO #define string "%major%,%minor%,%patch%,%build%" >> "%OBJROOT%\version.h"
30 |
--------------------------------------------------------------------------------
/version.rc:
--------------------------------------------------------------------------------
1 | #include "Winver.h"
2 |
3 | // built by version.bat; sets variables major, minor, patch, build, string
4 | #include "version.h"
5 |
6 | VS_VERSION_INFO VERSIONINFO
7 | FILEVERSION major,minor,patch,build
8 | PRODUCTVERSION major,minor,patch,build
9 | FILEFLAGSMASK 0x17L
10 | #ifdef _DEBUG
11 | FILEFLAGS VS_FF_DEBUG
12 | #else
13 | FILEFLAGS 0x0L
14 | #endif
15 | FILEOS VOS_NT_WINDOWS32
16 | FILETYPE VFT_DLL
17 | FILESUBTYPE VFT2_UNKNOWN
18 | BEGIN
19 | BLOCK "StringFileInfo"
20 | BEGIN
21 | BLOCK "040904b0"
22 | BEGIN
23 | VALUE "CompanyName", "Apple Inc."
24 | VALUE "FileDescription", "Objective-C Runtime Library"
25 | VALUE "FileVersion", string
26 | VALUE "ProductVersion", string
27 | VALUE "ProductName", "objc4"
28 | VALUE "InternalName", "objc4"
29 | VALUE "LegalCopyright", "Copyright (C) 2007-2009, Apple Inc."
30 | VALUE "OriginalFilename", "objc.dll"
31 | END
32 | END
33 | BLOCK "VarFileInfo"
34 | BEGIN
35 | VALUE "Translation", 0x409, 1200
36 | END
37 | END
38 |
39 |
--------------------------------------------------------------------------------