From 15021003e58634d63c173680b6c2d2b53fe1adf7 Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Fri, 3 Apr 2026 13:17:36 -0500
Subject: [PATCH 01/12] Add phase 4B collections nullability annotations
---
Headers/Foundation/NSArray.h | 50 ++++++++++++++++------------
Headers/Foundation/NSDictionary.h | 54 +++++++++++++++++++------------
Headers/Foundation/NSSet.h | 22 +++++++++----
3 files changed, 77 insertions(+), 49 deletions(-)
diff --git a/Headers/Foundation/NSArray.h b/Headers/Foundation/NSArray.h
index 9f32070779..c34213181b 100644
--- a/Headers/Foundation/NSArray.h
+++ b/Headers/Foundation/NSArray.h
@@ -56,19 +56,22 @@ enum
typedef NSUInteger NSBinarySearchingOptions;
#endif
+NS_ASSUME_NONNULL_BEGIN
+
GS_EXPORT_CLASS
@interface GS_GENERIC_CLASS(NSArray, __covariant ElementT) : NSObject
+ (instancetype) array;
+ (instancetype) arrayWithArray: (GS_GENERIC_CLASS(NSArray, ElementT) *)array;
-+ (instancetype) arrayWithContentsOfFile: (NSString*)file;
++ (instancetype _Nullable) arrayWithContentsOfFile: (NSString*)file;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-+ (instancetype) arrayWithContentsOfURL: (NSURL*)aURL;
++ (instancetype _Nullable) arrayWithContentsOfURL: (NSURL*)aURL;
#endif
+ (instancetype) arrayWithObject: (id)anObject;
+ (instancetype) arrayWithObjects: (id)firstObject, ...;
-+ (instancetype) arrayWithObjects: (const id[])objects count: (NSUInteger)count;
++ (instancetype) arrayWithObjects: (const id _Nonnull [])objects
+ count: (NSUInteger)count;
- (GS_GENERIC_CLASS(NSArray, ElementT) *) arrayByAddingObject:
(GS_GENERIC_TYPE(ElementT))anObject;
@@ -80,8 +83,10 @@ GS_EXPORT_CLASS
* Returns the number of elements contained in the receiver.
*/
- (NSUInteger) count;
-- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer;
-- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer
+- (void) getObjects:
+ (__unsafe_unretained GS_GENERIC_TYPE(ElementT) _Nonnull [])aBuffer;
+- (void) getObjects:
+ (__unsafe_unretained GS_GENERIC_TYPE(ElementT) _Nonnull [])aBuffer
range: (NSRange)aRange;
- (NSUInteger) indexOfObject: (GS_GENERIC_TYPE(ElementT))anObject;
- (NSUInteger) indexOfObject: (GS_GENERIC_TYPE(ElementT))anObject
@@ -95,9 +100,9 @@ GS_EXPORT_CLASS
- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array
copyItems: (BOOL)shouldCopy;
#endif
-- (instancetype) initWithContentsOfFile: (NSString*)file;
+- (instancetype _Nullable) initWithContentsOfFile: (NSString*)file;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-- (instancetype) initWithContentsOfURL: (NSURL*)aURL;
+- (instancetype _Nullable) initWithContentsOfURL: (NSURL*)aURL;
#endif
- (instancetype) initWithObjects: (GS_GENERIC_TYPE(ElementT)) firstObject, ...;
@@ -108,11 +113,12 @@ GS_EXPORT_CLASS
* and needs to be re-implemented in subclasses in order to have all
* other initialisers work.
*/
-- (instancetype) initWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects
+- (instancetype) initWithObjects:
+ (const GS_GENERIC_TYPE(ElementT) _Nonnull [])objects
count: (NSUInteger)count;
-- (GS_GENERIC_TYPE(ElementT)) lastObject;
+- (GS_GENERIC_TYPE(ElementT) _Nullable) lastObject;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
-- (GS_GENERIC_TYPE(ElementT)) firstObject;
+- (GS_GENERIC_TYPE(ElementT) _Nullable) firstObject;
#endif
/**
@@ -129,27 +135,27 @@ GS_EXPORT_CLASS
(NSIndexSet *)indexes;
#endif
-- (GS_GENERIC_TYPE(ElementT)) firstObjectCommonWithArray:
+- (GS_GENERIC_TYPE(ElementT) _Nullable) firstObjectCommonWithArray:
(GS_GENERIC_CLASS(NSArray, ElementT) *)otherArray;
- (BOOL) isEqualToArray: (NSArray*)otherArray;
#if OS_API_VERSION(GS_API_OPENSTEP, GS_API_MACOSX)
- (void) makeObjectsPerform: (SEL)aSelector;
-- (void) makeObjectsPerform: (SEL)aSelector withObject: (id)argument;
+- (void) makeObjectsPerform: (SEL)aSelector withObject: (id _Nullable)argument;
#endif
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (void) makeObjectsPerformSelector: (SEL)aSelector;
-- (void) makeObjectsPerformSelector: (SEL)aSelector withObject: (id)arg;
+- (void) makeObjectsPerformSelector: (SEL)aSelector withObject: (id _Nullable)arg;
#endif
-- (NSData*) sortedArrayHint;
+- (NSData *_Nullable) sortedArrayHint;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingFunction:
(NSComparisonResult (*)(id, id, void*))comparator
- context: (void*)context;
+ context: (void *_Nullable)context;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingFunction:
(NSComparisonResult (*)(id, id, void*))comparator
- context: (void*)context
- hint: (NSData*)hint;
+ context: (void *_Nullable)context
+ hint: (NSData *_Nullable)hint;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingSelector:
(SEL)comparator;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) subarrayWithRange: (NSRange)aRange;
@@ -162,15 +168,15 @@ GS_EXPORT_CLASS
- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) reverseObjectEnumerator;
- (NSString*) description;
-- (NSString*) descriptionWithLocale: (id)locale;
-- (NSString*) descriptionWithLocale: (id)locale
+- (NSString*) descriptionWithLocale: (id _Nullable)locale;
+- (NSString*) descriptionWithLocale: (id _Nullable)locale
indent: (NSUInteger)level;
- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (BOOL) writeToURL: (NSURL*)url atomically: (BOOL)useAuxiliaryFile;
- (id) valueForKey: (NSString*)key;
-- (void) setValue: (id)value forKey: (NSString*)key;
+- (void) setValue: (id _Nullable)value forKey: (NSString*)key;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
@@ -389,7 +395,7 @@ GS_EXPORT_CLASS
- (void) sortUsingFunction:
(NSComparisonResult (*)(GS_GENERIC_TYPE(ElementT),
GS_GENERIC_TYPE(ElementT),void*))compare
- context: (void*)context;
+ context: (void *_Nullable)context;
- (void) sortUsingSelector: (SEL)comparator;
@@ -415,6 +421,8 @@ atIndexedSubscript: (NSUInteger)anIndex;
#endif
@end
+NS_ASSUME_NONNULL_END
+
#if defined(__cplusplus)
}
#endif
diff --git a/Headers/Foundation/NSDictionary.h b/Headers/Foundation/NSDictionary.h
index 9cdbbf9fe8..18f816818f 100644
--- a/Headers/Foundation/NSDictionary.h
+++ b/Headers/Foundation/NSDictionary.h
@@ -36,34 +36,38 @@ extern "C" {
@class GS_GENERIC_CLASS(NSSet, ElementT);
@class NSString, NSURL;
+NS_ASSUME_NONNULL_BEGIN
+
GS_EXPORT_CLASS
@interface GS_GENERIC_CLASS(NSDictionary,
__covariant KeyT:id, __covariant ValT)
: NSObject
+ (instancetype) dictionary;
-+ (instancetype) dictionaryWithContentsOfFile: (NSString*)path;
++ (instancetype _Nullable) dictionaryWithContentsOfFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-+ (instancetype) dictionaryWithContentsOfURL: (NSURL*)aURL;
++ (instancetype _Nullable) dictionaryWithContentsOfURL: (NSURL*)aURL;
#endif
+ (instancetype) dictionaryWithDictionary: (NSDictionary*)otherDictionary;
+ (instancetype) dictionaryWithObject: (GS_GENERIC_TYPE(ValT))object
forKey: (GS_GENERIC_TYPE(KeyT))key;
+ (instancetype) dictionaryWithObjects: (GS_GENERIC_CLASS(NSArray,ValT)*)objects
forKeys: (GS_GENERIC_CLASS(NSArray,KeyT)*)keys;
-+ (instancetype) dictionaryWithObjects: (const GS_GENERIC_TYPE(ValT)[])objects
- forKeys: (const GS_GENERIC_TYPE_F(KeyT,id)[])keys
++ (instancetype) dictionaryWithObjects:
+ (const GS_GENERIC_TYPE(ValT) _Nonnull [])objects
+ forKeys:
+ (const GS_GENERIC_TYPE_F(KeyT,id) _Nonnull [])keys
count: (NSUInteger)count;
+ (instancetype) dictionaryWithObjectsAndKeys: (id)firstObject, ...;
- (GS_GENERIC_CLASS(NSArray,KeyT)*) allKeys;
-- (GS_GENERIC_CLASS(NSArray,KeyT)*) allKeysForObject:
- (GS_GENERIC_TYPE(ValT))anObject;
+- (GS_GENERIC_CLASS(NSArray,KeyT)* _Nullable) allKeysForObject:
+ (GS_GENERIC_TYPE(ValT) _Nullable)anObject;
- (GS_GENERIC_CLASS(NSArray,ValT)*) allValues;
- (NSUInteger) count; // Primitive
- (NSString*) description;
- (NSString*) descriptionInStringsFileFormat;
-- (NSString*) descriptionWithLocale: (id)locale;
-- (NSString*) descriptionWithLocale: (id)locale
+- (NSString*) descriptionWithLocale: (id _Nullable)locale;
+- (NSString*) descriptionWithLocale: (id _Nullable)locale
indent: (NSUInteger)level;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
@@ -74,13 +78,15 @@ DEFINE_BLOCK_TYPE(GSKeysAndObjectsEnumeratorBlock, void, GS_GENERIC_TYPE_F(KeyT,
usingBlock: (GSKeysAndObjectsEnumeratorBlock)aBlock;
#endif
-- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ValT)[])objects
- andKeys: (__unsafe_unretained GS_GENERIC_TYPE_F(KeyT,id)[])keys;
+- (void) getObjects:
+ (__unsafe_unretained GS_GENERIC_TYPE(ValT) _Nullable [])objects
+ andKeys:
+ (__unsafe_unretained GS_GENERIC_TYPE_F(KeyT,id) _Nullable [])keys;
- (instancetype) init;
-- (instancetype) initWithContentsOfFile: (NSString*)path;
+- (instancetype _Nullable) initWithContentsOfFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-- (instancetype) initWithContentsOfURL: (NSURL*)aURL;
+- (instancetype _Nullable) initWithContentsOfURL: (NSURL*)aURL;
#endif
- (instancetype) initWithDictionary:
@@ -90,8 +96,9 @@ DEFINE_BLOCK_TYPE(GSKeysAndObjectsEnumeratorBlock, void, GS_GENERIC_TYPE_F(KeyT,
- (id) initWithObjects: (GS_GENERIC_CLASS(NSArray,KeyT)*)objects
forKeys: (GS_GENERIC_CLASS(NSArray,ValT)*)keys;
- (id) initWithObjectsAndKeys: (GS_GENERIC_TYPE(ValT))firstObject, ...;
-- (id) initWithObjects: (const GS_GENERIC_TYPE(ValT)[])objects
- forKeys: (const GS_GENERIC_TYPE_F(KeyT,id)[])keys
+- (id) initWithObjects: (const GS_GENERIC_TYPE(ValT) _Nonnull [])objects
+ forKeys:
+ (const GS_GENERIC_TYPE_F(KeyT,id) _Nonnull [])keys
count: (NSUInteger)count; // Primitive
- (BOOL) isEqualToDictionary: (GS_GENERIC_CLASS(NSDictionary,KeyT, ValT)*)other;
@@ -110,14 +117,14 @@ DEFINE_BLOCK_TYPE(GSKeysAndObjectsPredicateBlock, BOOL, GS_GENERIC_TYPE_F(KeyT,i
- (GS_GENERIC_CLASS(NSArray,ValT)*) keysSortedByValueUsingComparator:(NSComparator)cmptr;
- (GS_GENERIC_CLASS(NSArray,ValT)*) keysSortedByValueWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr;
- (GS_GENERIC_CLASS(NSEnumerator,ValT)*) objectEnumerator; // Primitive
-- (GS_GENERIC_TYPE(ValT)) objectForKey:
+- (GS_GENERIC_TYPE(ValT) _Nullable) objectForKey:
(GS_GENERIC_TYPE(KeyT))aKey; // Primitive
- (GS_GENERIC_CLASS(NSArray,ValT)*) objectsForKeys:
(GS_GENERIC_CLASS(NSArray,KeyT)*)keys
notFoundMarker: (GS_GENERIC_TYPE(ValT))marker;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-- (GS_GENERIC_TYPE(ValT)) valueForKey: (NSString*)key;
+- (GS_GENERIC_TYPE(ValT) _Nullable) valueForKey: (NSString*)key;
#endif
- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile;
@@ -128,7 +135,7 @@ DEFINE_BLOCK_TYPE(GSKeysAndObjectsPredicateBlock, BOOL, GS_GENERIC_TYPE_F(KeyT,i
/**
* Method called by array subscripting.
*/
-- (GS_GENERIC_TYPE(ValT)) objectForKeyedSubscript:
+- (GS_GENERIC_TYPE(ValT) _Nullable) objectForKeyedSubscript:
(GS_GENERIC_TYPE(KeyT))aKey;
@end
@@ -153,18 +160,23 @@ GS_EXPORT_CLASS
- (void) setDictionary:
(GS_GENERIC_CLASS(NSDictionary, KeyT, ValT)*)otherDictionary;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-- (void) setValue: (GS_GENERIC_TYPE(ValT))value forKey: (NSString*)key;
-- (void) takeStoredValue: (GS_GENERIC_TYPE(ValT))value forKey: (NSString*)key;
-- (void) takeValue: (GS_GENERIC_TYPE(ValT))value forKey: (NSString*)key;
+- (void) setValue: (GS_GENERIC_TYPE(ValT) _Nullable)value
+ forKey: (NSString*)key;
+- (void) takeStoredValue: (GS_GENERIC_TYPE(ValT) _Nullable)value
+ forKey: (NSString*)key;
+- (void) takeValue: (GS_GENERIC_TYPE(ValT) _Nullable)value
+ forKey: (NSString*)key;
#endif
/**
* Method called by array subscripting.
*/
-- (void) setObject: (GS_GENERIC_TYPE(ValT))anObject
+- (void) setObject: (GS_GENERIC_TYPE(ValT) _Nullable)anObject
forKeyedSubscript: (GS_GENERIC_TYPE(KeyT))aKey;
@end
+NS_ASSUME_NONNULL_END
+
#if defined(__cplusplus)
}
#endif
diff --git a/Headers/Foundation/NSSet.h b/Headers/Foundation/NSSet.h
index 674d407a43..5325c1388a 100644
--- a/Headers/Foundation/NSSet.h
+++ b/Headers/Foundation/NSSet.h
@@ -42,6 +42,8 @@ extern "C" {
@class GS_GENERIC_CLASS(NSDictionary, KeyT:id, ValT);
@class NSString;
+NS_ASSUME_NONNULL_BEGIN
+
GS_EXPORT_CLASS
@interface GS_GENERIC_CLASS(NSSet, __covariant ElementT) : NSObject
Date: Fri, 3 Apr 2026 13:11:40 -0500
Subject: [PATCH 02/12] Add phase 4B core Foundation nullability annotations
Add narrow nullability annotations for the first Phase 4B core Foundation tranche without touching collection headers, module maps, or non-core surfaces.
Keep the remaining judgment-call annotations conservative:
- NSString legacy C-string decoding entry points stay nullable where decoding can return nil even though NULL C string inputs still raise.
- NSURL initWithScheme:host:path: stays nullable because it funnels through initWithString:relativeToURL:, which can still fail for constructed non-ASCII URL text.
- NSData bytes and mutableBytes stay nullable because zero-length concrete storage may legitimately expose a NULL backing pointer.
---
Headers/Foundation/NSData.h | 66 +++++------
Headers/Foundation/NSError.h | 20 ++--
Headers/Foundation/NSJSONSerialization.h | 22 ++--
Headers/Foundation/NSObjCRuntime.h | 26 ++++-
Headers/Foundation/NSObject.h | 50 +++++----
Headers/Foundation/NSString.h | 134 ++++++++++++-----------
Headers/Foundation/NSURL.h | 76 ++++++-------
7 files changed, 217 insertions(+), 177 deletions(-)
diff --git a/Headers/Foundation/NSData.h b/Headers/Foundation/NSData.h
index 4c1210cc7e..d881bba486 100644
--- a/Headers/Foundation/NSData.h
+++ b/Headers/Foundation/NSData.h
@@ -98,37 +98,39 @@ enum {
DEFINE_BLOCK_TYPE(GSDataDeallocatorBlock, void, void*, NSUInteger);
#endif
+NS_ASSUME_NONNULL_BEGIN
+
GS_EXPORT_CLASS
@interface NSData : NSObject
// Allocating and Initializing a Data Object
+ (instancetype) data;
-+ (instancetype) dataWithBytes: (const void*)bytes
++ (instancetype) dataWithBytes: (const void *_Nullable)bytes
length: (NSUInteger)length;
-+ (instancetype) dataWithBytesNoCopy: (void*)bytes
++ (instancetype) dataWithBytesNoCopy: (void *_Nullable)bytes
length: (NSUInteger)length;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-+ (instancetype) dataWithBytesNoCopy: (void*)aBuffer
++ (instancetype) dataWithBytesNoCopy: (void *_Nullable)aBuffer
length: (NSUInteger)bufferSize
freeWhenDone: (BOOL)shouldFree;
#endif
-+ (instancetype) dataWithContentsOfFile: (NSString *)path
- options: (NSDataReadingOptions)readOptionsMask
- error: (NSError **)errorPtr;
-+ (instancetype) dataWithContentsOfFile: (NSString*)path;
-+ (instancetype) dataWithContentsOfMappedFile: (NSString*)path;
++ (instancetype _Nullable) dataWithContentsOfFile: (NSString *)path
+ options: (NSDataReadingOptions)readOptionsMask
+ error: (NSError **)errorPtr;
++ (instancetype _Nullable) dataWithContentsOfFile: (NSString*)path;
++ (instancetype _Nullable) dataWithContentsOfMappedFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-+ (instancetype) dataWithContentsOfURL: (NSURL *)url
- options: (NSDataReadingOptions)readOptionsMask
- error: (NSError **)errorPtr;
-+ (instancetype) dataWithContentsOfURL: (NSURL*)url;
++ (instancetype _Nullable) dataWithContentsOfURL: (NSURL *)url
+ options: (NSDataReadingOptions)readOptionsMask
+ error: (NSError **)errorPtr;
++ (instancetype _Nullable) dataWithContentsOfURL: (NSURL*)url;
#endif
+ (instancetype) dataWithData: (NSData*)data;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_9,GS_API_LATEST)
-- (instancetype) initWithBase64EncodedData: (NSData*)base64Data
+- (instancetype _Nullable) initWithBase64EncodedData: (NSData*)base64Data
options: (NSDataBase64DecodingOptions)options;
-- (instancetype) initWithBase64EncodedString: (NSString*)base64String
+- (instancetype _Nullable) initWithBase64EncodedString: (NSString*)base64String
options: (NSDataBase64DecodingOptions)options;
/**
*
@@ -141,31 +143,31 @@ GS_EXPORT_CLASS
length: (NSUInteger)length
deallocator: (GSDataDeallocatorBlock)deallocBlock;
#endif
-- (instancetype) initWithBytes: (const void*)aBuffer
+- (instancetype) initWithBytes: (const void *_Nullable)aBuffer
length: (NSUInteger)bufferSize;
-- (instancetype) initWithBytesNoCopy: (void*)aBuffer
+- (instancetype) initWithBytesNoCopy: (void *_Nullable)aBuffer
length: (NSUInteger)bufferSize;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-- (instancetype) initWithBytesNoCopy: (void*)aBuffer
+- (instancetype) initWithBytesNoCopy: (void *_Nullable)aBuffer
length: (NSUInteger)bufferSize
freeWhenDone: (BOOL)shouldFree;
#endif
-- (instancetype) initWithContentsOfFile: (NSString*)path;
-- (instancetype) initWithContentsOfFile: (NSString *) path
- options: (NSDataReadingOptions) readOptionsMask
- error: (NSError **) errorPtr;
-- (instancetype) initWithContentsOfMappedFile: (NSString*)path;
+- (instancetype _Nullable) initWithContentsOfFile: (NSString*)path;
+- (instancetype _Nullable) initWithContentsOfFile: (NSString *) path
+ options: (NSDataReadingOptions) readOptionsMask
+ error: (NSError **) errorPtr;
+- (instancetype _Nullable) initWithContentsOfMappedFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
-- (instancetype) initWithContentsOfURL: (NSURL*)url;
-- (instancetype) initWithContentsOfURL: (NSURL *)url
- options: (NSDataReadingOptions)readOptionsMask
- error: (NSError **)errorPtr;
+- (instancetype _Nullable) initWithContentsOfURL: (NSURL*)url;
+- (instancetype _Nullable) initWithContentsOfURL: (NSURL *)url
+ options: (NSDataReadingOptions)readOptionsMask
+ error: (NSError **)errorPtr;
#endif
- (instancetype) initWithData: (NSData*)data;
// Accessing Data
-- (const void*) bytes;
+- (const void *_Nullable) bytes;
- (NSString*) description;
- (void) getBytes: (void*)buffer;
- (void) getBytes: (void*)buffer
@@ -355,21 +357,21 @@ GS_EXPORT_CLASS
- (void) increaseLengthBy: (NSUInteger)extraLength;
- (void) setLength: (NSUInteger)size;
-- (void*) mutableBytes;
+- (void *_Nullable) mutableBytes;
// Appending Data
-- (void) appendBytes: (const void*)aBuffer
+- (void) appendBytes: (const void *_Nullable)aBuffer
length: (NSUInteger)bufferSize;
- (void) appendData: (NSData*)other;
// Modifying Data
- (void) replaceBytesInRange: (NSRange)aRange
- withBytes: (const void*)bytes;
+ withBytes: (const void *_Nullable)bytes;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (void) replaceBytesInRange: (NSRange)aRange
- withBytes: (const void*)bytes
+ withBytes: (const void *_Nullable)bytes
length: (NSUInteger)length;
#endif
- (void) resetBytesInRange: (NSRange)aRange;
@@ -392,6 +394,8 @@ GS_EXPORT_CLASS
@end
+NS_ASSUME_NONNULL_END
+
#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
@interface NSMutableData (GNUstepExtensions)
diff --git a/Headers/Foundation/NSError.h b/Headers/Foundation/NSError.h
index df3ce5a31a..21459d68d0 100644
--- a/Headers/Foundation/NSError.h
+++ b/Headers/Foundation/NSError.h
@@ -37,6 +37,8 @@ extern "C" {
@class NSArray, NSDictionary, NSString;
+NS_ASSUME_NONNULL_BEGIN
+
typedef NSString* NSErrorDomain;
/**
@@ -135,7 +137,7 @@ GS_EXPORT_CLASS
@private
int _code;
NSString *_domain;
- NSDictionary *_userInfo;
+ NSDictionary *_Nullable _userInfo;
#endif
#if GS_NONFRAGILE
#else
@@ -154,7 +156,7 @@ GS_EXPORT_CLASS
*/
+ (instancetype) errorWithDomain: (NSErrorDomain)aDomain
code: (NSInteger)aCode
- userInfo: (NSDictionary*)aDictionary;
+ userInfo: (NSDictionary *_Nullable)aDictionary;
/**
* Return the error code ... which is not globally unique, just unique for
@@ -173,7 +175,7 @@ GS_EXPORT_CLASS
*/
- (instancetype) initWithDomain: (NSErrorDomain)aDomain
code: (NSInteger)aCode
- userInfo: (NSDictionary*)aDictionary;
+ userInfo: (NSDictionary *_Nullable)aDictionary;
/**
* Return a human readable description for the error.
@@ -191,7 +193,7 @@ GS_EXPORT_CLASS
* The default implementation uses the value from the user info dictionary
* if it is available, otherwise it returns nil.
*/
-- (NSString *) localizedFailureReason;
+- (NSString *_Nullable) localizedFailureReason;
/**
* Returns an array of strings to be used as titles of buttons in an
@@ -200,7 +202,7 @@ GS_EXPORT_CLASS
* The default implementation uses the value from the user info dictionary
* if it is available, otherwise it returns nil.
*/
-- (NSArray *) localizedRecoveryOptions;
+- (NSArray *_Nullable) localizedRecoveryOptions;
/**
* Returns a string used as the secondary text in an alert panel,
@@ -209,14 +211,14 @@ GS_EXPORT_CLASS
* The default implementation uses the value from the user info dictionary
* if it is available, otherwise it returns nil.
*/
-- (NSString *) localizedRecoverySuggestion;
+- (NSString *_Nullable) localizedRecoverySuggestion;
/**
* Not yet useful in GNUstep.
* The default implementation uses the value from the user info dictionary
* if it is available, otherwise it returns nil.
*/
-- (id) recoveryAttempter;
+- (id _Nullable) recoveryAttempter;
#endif
/**
@@ -227,9 +229,11 @@ GS_EXPORT_CLASS
* NSError instance if an error is available describing any
* underlying problem.
*/
-- (NSDictionary*) userInfo;
+- (NSDictionary *_Nullable) userInfo;
@end
+NS_ASSUME_NONNULL_END
+
#if defined(__cplusplus)
}
#endif
diff --git a/Headers/Foundation/NSJSONSerialization.h b/Headers/Foundation/NSJSONSerialization.h
index 354ed6d623..d86debeae0 100644
--- a/Headers/Foundation/NSJSONSerialization.h
+++ b/Headers/Foundation/NSJSONSerialization.h
@@ -28,6 +28,8 @@
@class NSInputStream;
@class NSOutputStream;
+NS_ASSUME_NONNULL_BEGIN
+
enum
{
/**
@@ -87,18 +89,20 @@ typedef NSUInteger NSJSONReadingOptions;
*/
GS_EXPORT_CLASS
@interface NSJSONSerialization : NSObject
-+ (NSData*) dataWithJSONObject: (id)obj
- options: (NSJSONWritingOptions)opt
- error: (NSError **)error;
++ (NSData *_Nullable) dataWithJSONObject: (id)obj
+ options: (NSJSONWritingOptions)opt
+ error: (NSError **)error;
+ (BOOL) isValidJSONObject: (id)obj;
-+ (id) JSONObjectWithData: (NSData *)data
- options: (NSJSONReadingOptions)opt
- error: (NSError **)error;
-+ (id) JSONObjectWithStream: (NSInputStream *)stream
- options: (NSJSONReadingOptions)opt
- error: (NSError **)error;
++ (id _Nullable) JSONObjectWithData: (NSData *)data
+ options: (NSJSONReadingOptions)opt
+ error: (NSError **)error;
++ (id _Nullable) JSONObjectWithStream: (NSInputStream *)stream
+ options: (NSJSONReadingOptions)opt
+ error: (NSError **)error;
+ (NSInteger) writeJSONObject: (id)obj
toStream: (NSOutputStream *)stream
options: (NSJSONWritingOptions)opt
error: (NSError **)error;
@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Headers/Foundation/NSObjCRuntime.h b/Headers/Foundation/NSObjCRuntime.h
index b350baef3b..2ac67ce601 100644
--- a/Headers/Foundation/NSObjCRuntime.h
+++ b/Headers/Foundation/NSObjCRuntime.h
@@ -184,6 +184,16 @@ extern "C" {
# define NS_SWIFT_NOTHROW
#endif
+/*
+ * Import a declaration with a specific Swift name when the compiler
+ * supports the attribute.
+ */
+#if __has_attribute(swift_name)
+# define NS_SWIFT_NAME(_name) __attribute__((swift_name(#_name)))
+#else
+# define NS_SWIFT_NAME(_name)
+#endif
+
/*
* Backwards compatibility macro for instance type.
*/
@@ -243,17 +253,21 @@ typedef NS_OPTIONS(NSUInteger, NSSortOptions)
#import
+NS_ASSUME_NONNULL_BEGIN
+
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
-GS_EXPORT NSString *NSStringFromProtocol(Protocol *aProtocol);
-GS_EXPORT Protocol *NSProtocolFromString(NSString *aProtocolName);
+GS_EXPORT NSString *_Nullable NSStringFromProtocol(Protocol *_Nullable aProtocol);
+GS_EXPORT Protocol *_Nullable NSProtocolFromString(NSString *aProtocolName);
#endif
GS_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);
-GS_EXPORT NSString *NSStringFromSelector(SEL aSelector);
+GS_EXPORT NSString *_Nullable NSStringFromSelector(SEL aSelector);
GS_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);
-GS_EXPORT Class NSClassFromString(NSString *aClassName);
-GS_EXPORT NSString *NSStringFromClass(Class aClass);
+GS_EXPORT Class _Nullable NSClassFromString(NSString *aClassName);
+GS_EXPORT NSString *_Nullable NSStringFromClass(Class _Nullable aClass);
GS_EXPORT const char *NSGetSizeAndAlignment(const char *typePtr,
- NSUInteger *sizep, NSUInteger *alignp);
+ NSUInteger *_Nullable sizep, NSUInteger *_Nullable alignp);
+
+NS_ASSUME_NONNULL_END
#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
/* Logging */
diff --git a/Headers/Foundation/NSObject.h b/Headers/Foundation/NSObject.h
index 9361669bb5..e017b0654a 100644
--- a/Headers/Foundation/NSObject.h
+++ b/Headers/Foundation/NSObject.h
@@ -48,6 +48,8 @@ extern "C" {
@class NSInvocation;
@class Protocol;
+NS_ASSUME_NONNULL_BEGIN
+
/**
* The NSObject protocol describes a minimal set of methods that all
* objects are expected to support. You should be able to send any
@@ -71,7 +73,7 @@ extern "C" {
* superclass of the receiver's class, ignoring proxies, then use
* "class_getSuperclass(object_getClass())".
*/
-- (Class) superclass;
+- (Class _Nullable) superclass;
/**
* Returns whether the receiver is equal to the argument. Defining equality is
@@ -90,7 +92,7 @@ extern "C" {
* If two objects are equal, then they must have the same hash value, however
* equal hash values do not imply equality.
*/
-- (BOOL) isEqual: (id)anObject;
+- (BOOL) isEqual: (id _Nullable)anObject;
/**
* Returns YES if the receiver is an instance of the class, an instance of the
@@ -141,24 +143,24 @@ extern "C" {
* Performs the specified selector. The selector must correspond to a method
* that takes no arguments.
*/
-- (id) performSelector: (SEL)aSelector;
+- (id _Nullable) performSelector: (SEL)aSelector;
/**
* Performs the specified selector, with the object as the argument. This
* method does not perform any automatic unboxing, so the selector must
* correspond to a method that takes one object argument.
*/
-- (id) performSelector: (SEL)aSelector
- withObject: (id)anObject;
+- (id _Nullable) performSelector: (SEL)aSelector
+ withObject: (id _Nullable)anObject;
/**
* Performs the specified selector, with the objects as the arguments. This
* method does not perform any automatic unboxing, so the selector must
* correspond to a method that takes two object arguments.
*/
-- (id) performSelector: (SEL)aSelector
- withObject: (id)object1
- withObject: (id)object2;
+- (id _Nullable) performSelector: (SEL)aSelector
+ withObject: (id _Nullable)object1
+ withObject: (id _Nullable)object2;
/**
* Returns YES if the object can respond to messages with the specified
@@ -223,7 +225,7 @@ extern "C" {
/**
* Returns the zone of the object.
*/
-- (NSZone*) zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+- (NSZone *_Nullable) zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
@end
/**
@@ -246,7 +248,7 @@ extern "C" {
* new copy, or are themselves copied, or whether some other mechanism
* entirely is used.
*/
-- (id) copyWithZone: (NSZone*)zone;
+- (id) copyWithZone: (NSZone *_Nullable)zone;
@end
/**
@@ -268,7 +270,7 @@ extern "C" {
* new copy, or are themselves copied, or whether some other mechanism
* entirely is used.
*/
-- (id) mutableCopyWithZone: (NSZone*)zone;
+- (id) mutableCopyWithZone: (NSZone *_Nullable)zone;
@end
/**
@@ -325,7 +327,7 @@ GS_EXPORT_CLASS GS_ROOT_CLASS
- (NSString*) className;
#endif
-+ (id) allocWithZone: (NSZone*)z;
++ (id) allocWithZone: (NSZone *_Nullable)z;
+ (id) alloc;
+ (Class) class;
@@ -375,8 +377,8 @@ GS_EXPORT_CLASS GS_ROOT_CLASS
* of +initialize.
*/
+ (void) initialize;
-+ (IMP) instanceMethodForSelector: (SEL)aSelector;
-+ (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector;
++ (IMP _Nullable) instanceMethodForSelector: (SEL)aSelector;
++ (NSMethodSignature *_Nullable) instanceMethodSignatureForSelector: (SEL)aSelector;
+ (BOOL) instancesRespondToSelector: (SEL)aSelector;
+ (BOOL) isSubclassOfClass: (Class)aClass;
+ (id) new;
@@ -392,12 +394,12 @@ GS_EXPORT_CLASS GS_ROOT_CLASS
- (void) doesNotRecognizeSelector: (SEL)aSelector;
- (void) forwardInvocation: (NSInvocation*)anInvocation;
- (id) init;
-- (IMP) methodForSelector: (SEL)aSelector;
-- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector;
+- (IMP _Nullable) methodForSelector: (SEL)aSelector;
+- (NSMethodSignature *_Nullable) methodSignatureForSelector: (SEL)aSelector;
- (id) mutableCopy;
- (id) replacementObjectForArchiver: (NSArchiver*)anArchiver;
- (id) replacementObjectForCoder: (NSCoder*)anEncoder;
-- (Class) superclass;
+- (Class _Nullable) superclass;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
/**
* This method will be called when attempting to send a message a class that
@@ -450,11 +452,13 @@ GS_EXPORT_CLASS GS_ROOT_CLASS
* runtime, you must also implement -forwardInvocation: with equivalent
* semantics. This will be considerably slower, but more portable.
*/
-- (id) forwardingTargetForSelector: (SEL)aSelector;
+- (id _Nullable) forwardingTargetForSelector: (SEL)aSelector;
#endif
@end
+NS_ASSUME_NONNULL_END
+
/**
* Used to allocate memory to hold an object, and initialise the
* class of the object to be aClass etc. The allocated memory will
@@ -520,6 +524,8 @@ NSIncrementExtraRefCount(id anObject);
* Declares some methods for sending messages to self after a fixed delay.
* (These methods are in OpenStep and OS X.)
*/
+NS_ASSUME_NONNULL_BEGIN
+
@interface NSObject (TimedPerformers)
/**
@@ -537,13 +543,13 @@ NSIncrementExtraRefCount(id anObject);
*/
+ (void) cancelPreviousPerformRequestsWithTarget: (id)obj
selector: (SEL)s
- object: (id)arg;
+ object: (id _Nullable)arg;
/**
* Sets given message to be sent to this instance after given delay,
* in any run loop mode. See [NSRunLoop].
*/
- (void) performSelector: (SEL)s
- withObject: (id)arg
+ withObject: (id _Nullable)arg
afterDelay: (NSTimeInterval)seconds;
/**
@@ -551,7 +557,7 @@ NSIncrementExtraRefCount(id anObject);
* in given run loop modes. See [NSRunLoop].
*/
- (void) performSelector: (SEL)s
- withObject: (id)arg
+ withObject: (id _Nullable)arg
afterDelay: (NSTimeInterval)seconds
inModes: (NSArray*)modes;
@end
@@ -591,6 +597,8 @@ NSIncrementExtraRefCount(id anObject);
*/
- (BOOL) isContentDiscarded;
@end
+
+NS_ASSUME_NONNULL_END
#endif
#if defined(__cplusplus)
}
diff --git a/Headers/Foundation/NSString.h b/Headers/Foundation/NSString.h
index e0f842ecbd..6a03c1c29e 100644
--- a/Headers/Foundation/NSString.h
+++ b/Headers/Foundation/NSString.h
@@ -513,6 +513,8 @@ DEFINE_BLOCK_TYPE(GSNSStringLineEnumerationBlock, void, NSString *line, BOOL *st
*
*/
+NS_ASSUME_NONNULL_BEGIN
+
GS_EXPORT_CLASS
@interface NSString :NSObject
@@ -520,51 +522,51 @@ GS_EXPORT_CLASS
+ (instancetype) stringWithCharacters: (const unichar*)chars
length: (NSUInteger)length;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST) && GS_API_VERSION( 10200,GS_API_LATEST)
-+ (instancetype) stringWithCString: (const char*)byteString
- encoding: (NSStringEncoding)encoding;
++ (instancetype _Nullable) stringWithCString: (const char*)byteString
+ encoding: (NSStringEncoding)encoding;
#endif
-+ (instancetype) stringWithCString: (const char*)byteString
- length: (NSUInteger)length;
-+ (instancetype) stringWithCString: (const char*)byteString;
++ (instancetype _Nullable) stringWithCString: (const char*)byteString
+ length: (NSUInteger)length;
++ (instancetype _Nullable) stringWithCString: (const char*)byteString;
+ (instancetype) stringWithFormat: (NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
-+ (instancetype) stringWithContentsOfFile: (NSString *)path;
++ (instancetype _Nullable) stringWithContentsOfFile: (NSString *)path;
// Initializing Newly Allocated Strings
- (instancetype) init;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST) && GS_API_VERSION( 10200,GS_API_LATEST)
-- (instancetype) initWithBytes: (const void*)bytes
- length: (NSUInteger)length
- encoding: (NSStringEncoding)encoding;
-- (instancetype) initWithBytesNoCopy: (void*)bytes
- length: (NSUInteger)length
- encoding: (NSStringEncoding)encoding
- freeWhenDone: (BOOL)flag;
+- (instancetype _Nullable) initWithBytes: (const void*)bytes
+ length: (NSUInteger)length
+ encoding: (NSStringEncoding)encoding;
+- (instancetype _Nullable) initWithBytesNoCopy: (void*)bytes
+ length: (NSUInteger)length
+ encoding: (NSStringEncoding)encoding
+ freeWhenDone: (BOOL)flag;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST)
-+ (instancetype) stringWithContentsOfFile: (NSString*)path
- usedEncoding: (NSStringEncoding*)enc
- error: (NSError**)error;
-- (instancetype) initWithContentsOfFile: (NSString*)path
- usedEncoding: (NSStringEncoding*)enc
- error: (NSError**)error;
-+ (instancetype) stringWithContentsOfFile: (NSString*)path
- encoding: (NSStringEncoding)enc
- error: (NSError**)error;
-- (instancetype) initWithContentsOfFile: (NSString*)path
- encoding: (NSStringEncoding)enc
- error: (NSError**)error;
-+ (instancetype) stringWithContentsOfURL: (NSURL*)url
- usedEncoding: (NSStringEncoding*)enc
- error: (NSError**)error;
-- (instancetype) initWithContentsOfURL: (NSURL*)url
- usedEncoding: (NSStringEncoding*)enc
- error: (NSError**)error;
-+ (instancetype) stringWithContentsOfURL: (NSURL*)url
- encoding: (NSStringEncoding)enc
- error: (NSError**)error;
-- (instancetype) initWithContentsOfURL: (NSURL*)url
- encoding: (NSStringEncoding)enc
- error: (NSError**)error;
++ (instancetype _Nullable) stringWithContentsOfFile: (NSString*)path
+ usedEncoding: (NSStringEncoding *_Nullable)enc
+ error: (NSError**)error;
+- (instancetype _Nullable) initWithContentsOfFile: (NSString*)path
+ usedEncoding: (NSStringEncoding *_Nullable)enc
+ error: (NSError**)error;
++ (instancetype _Nullable) stringWithContentsOfFile: (NSString*)path
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
+- (instancetype _Nullable) initWithContentsOfFile: (NSString*)path
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
++ (instancetype _Nullable) stringWithContentsOfURL: (NSURL*)url
+ usedEncoding: (NSStringEncoding *_Nullable)enc
+ error: (NSError**)error;
+- (instancetype _Nullable) initWithContentsOfURL: (NSURL*)url
+ usedEncoding: (NSStringEncoding *_Nullable)enc
+ error: (NSError**)error;
++ (instancetype _Nullable) stringWithContentsOfURL: (NSURL*)url
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
+- (instancetype _Nullable) initWithContentsOfURL: (NSURL*)url
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
- (BOOL) writeToFile: (NSString*)path
atomically: (BOOL)atomically
encoding: (NSStringEncoding)enc
@@ -592,16 +594,16 @@ GS_EXPORT_CLASS
- (instancetype) initWithCStringNoCopy: (char*)byteString
length: (NSUInteger)length
freeWhenDone: (BOOL)flag;
-- (instancetype) initWithCString: (const char*)byteString
- length: (NSUInteger)length;
-- (instancetype) initWithCString: (const char*)byteString;
+- (instancetype _Nullable) initWithCString: (const char*)byteString
+ length: (NSUInteger)length;
+- (instancetype _Nullable) initWithCString: (const char*)byteString;
- (instancetype) initWithString: (NSString*)string;
- (instancetype) initWithFormat: (NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
- (instancetype) initWithFormat: (NSString*)format
arguments: (va_list)argList NS_FORMAT_FUNCTION(1,0);
-- (instancetype) initWithData: (NSData*)data
- encoding: (NSStringEncoding)encoding;
-- (instancetype) initWithContentsOfFile: (NSString*)path;
+- (instancetype _Nullable) initWithData: (NSData*)data
+ encoding: (NSStringEncoding)encoding;
+- (instancetype _Nullable) initWithContentsOfFile: (NSString*)path;
// Getting a String's Length
- (NSUInteger) length;
@@ -658,8 +660,8 @@ GS_EXPORT_CLASS
#endif
// Converting String Contents into a Property List
-- (id) propertyList;
-- (NSDictionary*) propertyListFromStringsFileFormat;
+- (id _Nullable) propertyList;
+- (NSDictionary *_Nullable) propertyListFromStringsFileFormat;
// Identifying and Comparing Strings
- (NSComparisonResult) compare: (NSString*)aString;
@@ -670,7 +672,7 @@ GS_EXPORT_CLASS
range: (NSRange)aRange;
- (BOOL) hasPrefix: (NSString*)aString;
- (BOOL) hasSuffix: (NSString*)aString;
-- (BOOL) isEqual: (id)anObject;
+- (BOOL) isEqual: (id _Nullable)anObject;
- (BOOL) isEqualToString: (NSString*)aString;
- (NSUInteger) hash;
@@ -692,8 +694,8 @@ GS_EXPORT_CLASS
- (BOOL) getCString: (char*)buffer
maxLength: (NSUInteger)maxLength
encoding: (NSStringEncoding)encoding;
-- (instancetype) initWithCString: (const char*)byteString
- encoding: (NSStringEncoding)encoding;
+- (instancetype _Nullable) initWithCString: (const char*)byteString
+ encoding: (NSStringEncoding)encoding;
- (NSUInteger) lengthOfBytesUsingEncoding: (NSStringEncoding)encoding;
- (NSUInteger) maximumLengthOfBytesUsingEncoding: (NSStringEncoding)encoding;
#endif
@@ -714,13 +716,13 @@ GS_EXPORT_CLASS
// Working With Encodings
- (BOOL) canBeConvertedToEncoding: (NSStringEncoding)encoding;
-- (NSData*) dataUsingEncoding: (NSStringEncoding)encoding;
+- (NSData *_Nullable) dataUsingEncoding: (NSStringEncoding)encoding;
/** Conversion to an encoding where byte order matters but is not specified
* (NSUnicodeStringEncoding, NSUTF16StringEncoding, NSUTF32StringEncoding)
* produces data with a Byte Order Marker (BOM) at the start of the data.
*/
-- (NSData*) dataUsingEncoding: (NSStringEncoding)encoding
- allowLossyConversion: (BOOL)flag;
+- (NSData *_Nullable) dataUsingEncoding: (NSStringEncoding)encoding
+ allowLossyConversion: (BOOL)flag;
+ (NSStringEncoding) defaultCStringEncoding;
- (NSString*) description;
- (NSStringEncoding) fastestEncoding;
@@ -736,9 +738,9 @@ GS_EXPORT_CLASS
* completions. Returns 0 if no match found, else a positive number that is
* only accurate if outputArray was non-nil.
*/
-- (NSUInteger) completePathIntoString: (NSString**)outputName
+- (NSUInteger) completePathIntoString: (NSString * _Nullable * _Nonnull)outputName
caseSensitive: (BOOL)flag
- matchesIntoArray: (NSArray**)outputArray
+ matchesIntoArray: (NSArray * _Nullable * _Nullable)outputArray
filterTypes: (NSArray*)filterTypes;
/**
@@ -752,7 +754,7 @@ GS_EXPORT_CLASS
* This method uses [NSFileManager-fileSystemRepresentationWithPath:] to
* perform the conversion.
*/
-- (const GSNativeChar*) fileSystemRepresentation;
+- (const GSNativeChar *_Nullable) fileSystemRepresentation;
/**
* Converts the receiver to a C string path using the character encoding
@@ -1003,15 +1005,15 @@ GS_EXPORT_CLASS
NS_FORMAT_FUNCTION(1,2);
+ (instancetype) stringWithString: (NSString*)aString;
-+ (instancetype) stringWithContentsOfURL: (NSURL*)url;
-+ (instancetype) stringWithUTF8String: (const char*)bytes;
++ (instancetype _Nullable) stringWithContentsOfURL: (NSURL*)url;
++ (instancetype _Nullable) stringWithUTF8String: (const char*)bytes;
- (instancetype) initWithFormat: (NSString*)format
locale: (NSDictionary*)locale, ... NS_FORMAT_FUNCTION(1,3);
- (instancetype) initWithFormat: (NSString*)format
locale: (NSDictionary*)locale
arguments: (va_list)argList NS_FORMAT_FUNCTION(1,0);
-- (instancetype) initWithUTF8String: (const char *)bytes;
-- (instancetype) initWithContentsOfURL: (NSURL*)url;
+- (instancetype _Nullable) initWithUTF8String: (const char *)bytes;
+- (instancetype _Nullable) initWithContentsOfURL: (NSURL*)url;
- (NSString*) substringWithRange: (NSRange)aRange;
- (NSComparisonResult) caseInsensitiveCompare: (NSString*)aString;
- (NSComparisonResult) compare: (NSString*)string
@@ -1033,18 +1035,18 @@ GS_EXPORT_CLASS
forRange: (NSRange)aRange;
- (NSRange) lineRangeForRange: (NSRange)aRange;
- (const char*) lossyCString;
-- (NSString*) stringByAddingPercentEscapesUsingEncoding: (NSStringEncoding)e;
+- (NSString *_Nullable) stringByAddingPercentEscapesUsingEncoding: (NSStringEncoding)e;
- (NSString*) stringByPaddingToLength: (NSUInteger)newLength
withString: (NSString*)padString
startingAtIndex: (NSUInteger)padIndex;
-- (NSString*) stringByReplacingPercentEscapesUsingEncoding: (NSStringEncoding)e;
+- (NSString *_Nullable) stringByReplacingPercentEscapesUsingEncoding: (NSStringEncoding)e;
- (NSString*) stringByTrimmingCharactersInSet: (NSCharacterSet*)aSet;
- (const char *)UTF8String;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_9,GS_API_LATEST)
- (NSString *) stringByAddingPercentEncodingWithAllowedCharacters: (NSCharacterSet *)aSet;
-- (NSString *) stringByRemovingPercentEncoding;
+- (NSString *_Nullable) stringByRemovingPercentEncoding;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_3,GS_API_LATEST)
@@ -1111,11 +1113,11 @@ GS_EXPORT_CLASS
+ (instancetype) string;
+ (instancetype) stringWithCharacters: (const unichar*)characters
length: (NSUInteger)length;
-+ (instancetype) stringWithCString: (const char*)byteString
- length: (NSUInteger)length;
-+ (instancetype) stringWithCString: (const char*)byteString;
++ (instancetype _Nullable) stringWithCString: (const char*)byteString
+ length: (NSUInteger)length;
++ (instancetype _Nullable) stringWithCString: (const char*)byteString;
+ (instancetype) stringWithFormat: (NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
-+ (instancetype) stringWithContentsOfFile: (NSString*)path;
++ (instancetype _Nullable) stringWithContentsOfFile: (NSString*)path;
+ (NSMutableString*) stringWithCapacity: (NSUInteger)capacity;
// Initializing Newly Allocated Strings
@@ -1136,6 +1138,8 @@ GS_EXPORT_CLASS
@end
+NS_ASSUME_NONNULL_END
+
#ifdef __OBJC_GNUSTEP_RUNTIME_ABI__
# if __OBJC_GNUSTEP_RUNTIME_ABI__ >= 20
# define GNUSTEP_NEW_STRING_ABI
diff --git a/Headers/Foundation/NSURL.h b/Headers/Foundation/NSURL.h
index cc13f9b155..df77c70379 100644
--- a/Headers/Foundation/NSURL.h
+++ b/Headers/Foundation/NSURL.h
@@ -40,6 +40,8 @@ extern "C" {
@class NSDictionary;
@class NSArray;
+NS_ASSUME_NONNULL_BEGIN
+
/**
* URL scheme constant for use with [NSURL-initWithScheme:host:path:].
*/
@@ -73,9 +75,9 @@ GS_EXPORT_CLASS
#if GS_EXPOSE(NSURL)
@private
NSString *_urlString;
- NSURL *_baseURL;
- void *_clients;
- void *_data;
+ NSURL *_Nullable _baseURL;
+ void *_Nullable _clients;
+ void *_Nullable _data;
#endif
}
@@ -100,12 +102,12 @@ GS_EXPORT_CLASS
#if OS_API_VERSION(MAC_OS_X_VERSION_10_11, GS_API_LATEST)
+ (instancetype) fileURLWithPath: (NSString *)aPath
isDirectory: (BOOL)isDir
- relativeToURL: (NSURL *)baseURL;
+ relativeToURL: (NSURL *_Nullable)baseURL;
/** Create and return a file URL with the supplied path, relative to a base URL.
*/
+ (instancetype) fileURLWithPath: (NSString *)aPath
- relativeToURL: (NSURL *)baseURL;
+ relativeToURL: (NSURL *_Nullable)baseURL;
#endif
/**
@@ -114,12 +116,12 @@ GS_EXPORT_CLASS
* conforming to the description (in RFC2396) of an absolute URL.
* Calls -initWithString:
*/
-+ (instancetype) URLWithString: (NSString*)aUrlString;
++ (instancetype _Nullable) URLWithString: (NSString*)aUrlString;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST)
-+ (instancetype) URLByResolvingAliasFileAtURL: (NSURL*)url
- options: (NSURLBookmarkResolutionOptions)options
- error: (NSError**)error;
++ (instancetype _Nullable) URLByResolvingAliasFileAtURL: (NSURL*)url
+ options: (NSURLBookmarkResolutionOptions)options
+ error: (NSError**)error;
#endif
/**
@@ -128,8 +130,8 @@ GS_EXPORT_CLASS
* conforming to the description (in RFC2396) of a relative URL.
* Calls -initWithString:relativeToURL:
*/
-+ (instancetype) URLWithString: (NSString*)aUrlString
- relativeToURL: (NSURL*)aBaseUrl;
++ (instancetype _Nullable) URLWithString: (NSString*)aUrlString
+ relativeToURL: (NSURL *_Nullable)aBaseUrl;
/**
* Initialise as a file URL with the specified path (which must
@@ -167,7 +169,7 @@ GS_EXPORT_CLASS
* Calls -initWithScheme:host:path:
*/
- (instancetype) initFileURLWithPath: (NSString *)aPath
- relativeToURL: (NSURL *)baseURL;
+ relativeToURL: (NSURL *_Nullable)baseURL;
/**
* Initialise as a file URL with the specified path (which must
@@ -180,7 +182,7 @@ GS_EXPORT_CLASS
*/
- (instancetype) initFileURLWithPath: (NSString *)aPath
isDirectory: (BOOL)isDir
- relativeToURL: (NSURL *)baseURL;
+ relativeToURL: (NSURL *_Nullable)baseURL;
#endif
/**
@@ -194,15 +196,15 @@ GS_EXPORT_CLASS
* Permits the 'aHost' part to contain 'username:password@host:port' or
* 'host:port' in addition to a simple host name or address.
*/
-- (instancetype) initWithScheme: (NSString*)aScheme
- host: (NSString*)aHost
- path: (NSString*)aPath;
+- (instancetype _Nullable) initWithScheme: (NSString*)aScheme
+ host: (NSString *_Nullable)aHost
+ path: (NSString*)aPath;
/**
* Initialise as an absolute URL.
* Calls -initWithString:relativeToURL:
*/
-- (instancetype) initWithString: (NSString*)aUrlString;
+- (instancetype _Nullable) initWithString: (NSString*)aUrlString;
/**
* Initialised using aUrlString and aBaseUrl. The value of aBaseUrl
@@ -212,8 +214,8 @@ GS_EXPORT_CLASS
* Parses an empty string as an empty path.
* If the string cannot be parsed the method returns nil.
*/
-- (instancetype) initWithString: (NSString*)aUrlString
- relativeToURL: (NSURL*)aBaseUrl;
+- (instancetype _Nullable) initWithString: (NSString*)aUrlString
+ relativeToURL: (NSURL *_Nullable)aBaseUrl;
#if GS_HAS_DECLARED_PROPERTIES
@property (readonly, getter=isFileURL) BOOL fileURL;
@@ -236,7 +238,7 @@ GS_EXPORT_CLASS
* If the receiver is a relative URL, returns its base URL.
* Otherwise, returns nil.
*/
-- (NSURL*) baseURL;
+- (NSURL *_Nullable) baseURL;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6,GS_API_LATEST)
/** Attempts to load from the specified URL and provides an error
@@ -252,7 +254,7 @@ GS_EXPORT_CLASS
* The fragment is everything in the original URL string after a '#'
* File URLs do not have fragments.
*/
-- (NSString*) fragment;
+- (NSString *_Nullable) fragment;
/**
* Returns the host portion of the receiver or nil if there is no
@@ -262,7 +264,7 @@ GS_EXPORT_CLASS
* Returns IPv6 addresses without the enclosing square brackets
* required (by RFC2732) in URL strings.
*/
-- (NSString*) host;
+- (NSString *_Nullable) host;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6,GS_API_LATEST)
/** Returns the last (rightmost) path component of the receiver.
@@ -292,7 +294,7 @@ GS_EXPORT_CLASS
* background load operation to operate!
*
*/
-- (void) loadResourceDataNotifyingClient: (id)client
+- (void) loadResourceDataNotifyingClient: (id _Nullable)client
usingCache: (BOOL)shouldUseCache;
/**
@@ -302,7 +304,7 @@ GS_EXPORT_CLASS
* but before the query.
* File URLs do not have parameters.
*/
-- (NSString*) parameterString;
+- (NSString *_Nullable) parameterString;
/**
* Returns the password portion of the receiver or nil if there is no
@@ -312,7 +314,7 @@ GS_EXPORT_CLASS
* NB. because of its security implications it is recommended that you
* do not use URLs with users and passwords unless necessary.
*/
-- (NSString*) password;
+- (NSString *_Nullable) password;
/**
* Returns the path portion of the receiver.
@@ -346,13 +348,13 @@ GS_EXPORT_CLASS
* Percent escape sequences in the user string are translated in GNUstep
* but this appears to be broken in MacOS-X.
*/
-- (NSNumber*) port;
+- (NSNumber *_Nullable) port;
/**
* Asks a URL handle to return the property for the specified key and
* returns the result.
*/
-- (id) propertyForKey: (NSString*)propertyKey;
+- (id _Nullable) propertyForKey: (NSString*)propertyKey;
/**
* Returns the query portion of the receiver or nil if there is no
@@ -361,14 +363,14 @@ GS_EXPORT_CLASS
* but before the fragment.
* File URLs do not have queries.
*/
-- (NSString*) query;
+- (NSString *_Nullable) query;
/**
* Returns the path of the receiver, without taking any base URL into account.
* If the receiver is an absolute URL, -relativePath is the same as -path.
* Returns nil if there is no path specified for the URL.
*/
-- (NSString*) relativePath;
+- (NSString *_Nullable) relativePath;
/**
* Returns the relative portion of the URL string. If the receiver is not
@@ -382,7 +384,7 @@ GS_EXPORT_CLASS
* an existing NSURLHandle can be used to provide the data, or if it should
* be refetched.
*/
-- (NSData*) resourceDataUsingCache: (BOOL)shouldUseCache;
+- (NSData *_Nullable) resourceDataUsingCache: (BOOL)shouldUseCache;
/**
* Returns the resource specifier of the URL ... the part which lies
@@ -393,7 +395,7 @@ GS_EXPORT_CLASS
/**
* Returns the scheme of the receiver.
*/
-- (NSString*) scheme;
+- (NSString *_Nullable) scheme;
/**
* Calls [NSURLHandle-writeProperty:forKey:] to set the named property.
@@ -463,11 +465,11 @@ GS_EXPORT_CLASS
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
- (BOOL) isFileReferenceURL;
-- (NSURL *) fileReferenceURL;
+- (NSURL *_Nullable) fileReferenceURL;
-- (NSURL *) filePathURL;
+- (NSURL *_Nullable) filePathURL;
-- (BOOL) getResourceValue: (id*)value
+- (BOOL) getResourceValue: (id _Nullable * _Nullable)value
forKey: (NSString *)key
error: (NSError**)error;
#endif
@@ -487,7 +489,7 @@ GS_EXPORT_CLASS
* NB. because of its security implications it is recommended that you
* do not use URLs with users and passwords unless necessary.
*/
-- (NSString*) user;
+- (NSString *_Nullable) user;
@end
@@ -518,6 +520,8 @@ GS_EXPORT_CLASS
resourceDidFailLoadingWithReason: (NSString*)reason;
@end
+NS_ASSUME_NONNULL_END
+
/** URL Resource Value Constants **/
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
GS_EXPORT NSString* const NSURLNameKey;
@@ -794,5 +798,3 @@ GS_NSURLComponents_IVARS;
#endif /* __NSURL_h_GNUSTEP_BASE_INCLUDE */
-
-
From 5bc8a5d565719af5d4c7f1fbe04271b0029da07b Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Fri, 3 Apr 2026 14:23:43 -0500
Subject: [PATCH 03/12] Add Foundation module map for Swift import
---
Headers/module.modulemap | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 Headers/module.modulemap
diff --git a/Headers/module.modulemap b/Headers/module.modulemap
new file mode 100644
index 0000000000..7f498d055a
--- /dev/null
+++ b/Headers/module.modulemap
@@ -0,0 +1,10 @@
+module Foundation [system] {
+ header "Foundation/Foundation.h"
+
+ textual header "GNUstepBase/GSVersionMacros.h"
+ textual header "GNUstepBase/GSConfig.h"
+ textual header "GNUstepBase/GNUstep.h"
+ textual header "GNUstepBase/GSBlocks.h"
+
+ export *
+}
From 97dd53793bbb515e8e1a5135f62daa73c13467c8 Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Fri, 17 Apr 2026 15:15:15 -0500
Subject: [PATCH 04/12] Tighten NSData and NSURL Swift nullability
---
Headers/Foundation/NSData.h | 8 ++++----
Headers/Foundation/NSURL.h | 8 ++++++--
Source/NSURL.m | 5 +++++
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/Headers/Foundation/NSData.h b/Headers/Foundation/NSData.h
index d881bba486..d60f554bec 100644
--- a/Headers/Foundation/NSData.h
+++ b/Headers/Foundation/NSData.h
@@ -106,8 +106,8 @@ GS_EXPORT_CLASS
// Allocating and Initializing a Data Object
+ (instancetype) data;
-+ (instancetype) dataWithBytes: (const void *_Nullable)bytes
- length: (NSUInteger)length;
++ (nonnull instancetype) dataWithBytes: (const void *_Nullable)bytes
+ length: (NSUInteger)length;
+ (instancetype) dataWithBytesNoCopy: (void *_Nullable)bytes
length: (NSUInteger)length;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
@@ -143,8 +143,8 @@ GS_EXPORT_CLASS
length: (NSUInteger)length
deallocator: (GSDataDeallocatorBlock)deallocBlock;
#endif
-- (instancetype) initWithBytes: (const void *_Nullable)aBuffer
- length: (NSUInteger)bufferSize;
+- (nonnull instancetype) initWithBytes: (const void *_Nullable)aBuffer
+ length: (NSUInteger)bufferSize;
- (instancetype) initWithBytesNoCopy: (void *_Nullable)aBuffer
length: (NSUInteger)bufferSize;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
diff --git a/Headers/Foundation/NSURL.h b/Headers/Foundation/NSURL.h
index df77c70379..d314a162d5 100644
--- a/Headers/Foundation/NSURL.h
+++ b/Headers/Foundation/NSURL.h
@@ -80,7 +80,12 @@ GS_EXPORT_CLASS
void *_Nullable _data;
#endif
}
-
+
+/**
+ * Initialize an empty URL object.
+ */
+- (nonnull instancetype) init;
+
/**
* Create and return a file URL with the supplied path.
* The value of aPath must be a valid filesystem path.
@@ -797,4 +802,3 @@ GS_NSURLComponents_IVARS;
#endif /* __NSURL_h_GNUSTEP_BASE_INCLUDE */
-
diff --git a/Source/NSURL.m b/Source/NSURL.m
index b97b7a960b..be1db02c95 100644
--- a/Source/NSURL.m
+++ b/Source/NSURL.m
@@ -727,6 +727,11 @@ + (id) URLByResolvingAliasFileAtURL: (NSURL*)url
return nil;
}
+- (id) init
+{
+ return [self initWithString: @""];
+}
+
- (id) initFileURLWithPath: (NSString *)aPath
{
/* isDirectory flag will be overwritten if a directory exists. */
From 89fd3ce54ae0b351834d962a5efe6c5f46fc0fc5 Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Fri, 17 Apr 2026 15:27:34 -0500
Subject: [PATCH 05/12] Tighten retained NSError out parameter nullability
---
Headers/Foundation/NSData.h | 8 ++++----
Headers/Foundation/NSJSONSerialization.h | 8 ++++----
Headers/Foundation/NSPropertyList.h | 8 ++++----
Headers/Foundation/NSRegularExpression.h | 8 ++++----
Headers/Foundation/NSURL.h | 3 +--
5 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/Headers/Foundation/NSData.h b/Headers/Foundation/NSData.h
index d60f554bec..5e73dc7e5f 100644
--- a/Headers/Foundation/NSData.h
+++ b/Headers/Foundation/NSData.h
@@ -117,13 +117,13 @@ GS_EXPORT_CLASS
#endif
+ (instancetype _Nullable) dataWithContentsOfFile: (NSString *)path
options: (NSDataReadingOptions)readOptionsMask
- error: (NSError **)errorPtr;
+ error: (NSError *_Nullable *_Nullable)errorPtr;
+ (instancetype _Nullable) dataWithContentsOfFile: (NSString*)path;
+ (instancetype _Nullable) dataWithContentsOfMappedFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+ (instancetype _Nullable) dataWithContentsOfURL: (NSURL *)url
options: (NSDataReadingOptions)readOptionsMask
- error: (NSError **)errorPtr;
+ error: (NSError *_Nullable *_Nullable)errorPtr;
+ (instancetype _Nullable) dataWithContentsOfURL: (NSURL*)url;
#endif
+ (instancetype) dataWithData: (NSData*)data;
@@ -155,13 +155,13 @@ GS_EXPORT_CLASS
- (instancetype _Nullable) initWithContentsOfFile: (NSString*)path;
- (instancetype _Nullable) initWithContentsOfFile: (NSString *) path
options: (NSDataReadingOptions) readOptionsMask
- error: (NSError **) errorPtr;
+ error: (NSError *_Nullable *_Nullable) errorPtr;
- (instancetype _Nullable) initWithContentsOfMappedFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (instancetype _Nullable) initWithContentsOfURL: (NSURL*)url;
- (instancetype _Nullable) initWithContentsOfURL: (NSURL *)url
options: (NSDataReadingOptions)readOptionsMask
- error: (NSError **)errorPtr;
+ error: (NSError *_Nullable *_Nullable)errorPtr;
#endif
- (instancetype) initWithData: (NSData*)data;
diff --git a/Headers/Foundation/NSJSONSerialization.h b/Headers/Foundation/NSJSONSerialization.h
index d86debeae0..0feb5e6c67 100644
--- a/Headers/Foundation/NSJSONSerialization.h
+++ b/Headers/Foundation/NSJSONSerialization.h
@@ -91,18 +91,18 @@ GS_EXPORT_CLASS
@interface NSJSONSerialization : NSObject
+ (NSData *_Nullable) dataWithJSONObject: (id)obj
options: (NSJSONWritingOptions)opt
- error: (NSError **)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (BOOL) isValidJSONObject: (id)obj;
+ (id _Nullable) JSONObjectWithData: (NSData *)data
options: (NSJSONReadingOptions)opt
- error: (NSError **)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (id _Nullable) JSONObjectWithStream: (NSInputStream *)stream
options: (NSJSONReadingOptions)opt
- error: (NSError **)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (NSInteger) writeJSONObject: (id)obj
toStream: (NSOutputStream *)stream
options: (NSJSONWritingOptions)opt
- error: (NSError **)error;
+ error: (NSError *_Nullable *_Nullable)error;
@end
NS_ASSUME_NONNULL_END
diff --git a/Headers/Foundation/NSPropertyList.h b/Headers/Foundation/NSPropertyList.h
index 5dddbd3126..65b7aeae27 100644
--- a/Headers/Foundation/NSPropertyList.h
+++ b/Headers/Foundation/NSPropertyList.h
@@ -269,20 +269,20 @@ GS_EXPORT_CLASS
+ (NSData *) dataWithPropertyList: (id)aPropertyList
format: (NSPropertyListFormat)aFormat
options: (NSPropertyListWriteOptions)anOption
- error: (out NSError**)error;
+ error: (out NSError *_Nullable *_Nullable)error;
+ (id) propertyListWithData: (NSData*)data
options: (NSPropertyListReadOptions)anOption
format: (NSPropertyListFormat*)aFormat
- error: (out NSError**)error;
+ error: (out NSError *_Nullable *_Nullable)error;
+ (id) propertyListWithStream: (NSInputStream*)stream
options: (NSPropertyListReadOptions)anOption
format: (NSPropertyListFormat*)aFormat
- error: (out NSError**)error;
+ error: (out NSError *_Nullable *_Nullable)error;
+ (NSInteger) writePropertyList: (id)aPropertyList
toStream: (NSOutputStream*)stream
format: (NSPropertyListFormat)aFormat
options: (NSPropertyListWriteOptions)anOption
- error: (out NSError**)error;
+ error: (out NSError *_Nullable *_Nullable)error;
#endif
@end
diff --git a/Headers/Foundation/NSRegularExpression.h b/Headers/Foundation/NSRegularExpression.h
index bd9ef23dc5..b6233b3fcb 100644
--- a/Headers/Foundation/NSRegularExpression.h
+++ b/Headers/Foundation/NSRegularExpression.h
@@ -118,16 +118,16 @@ GS_EXPORT_CLASS
#if GS_USE_ICU || GS_UNSAFE_REGEX
+ (NSRegularExpression*) regularExpressionWithPattern: (NSString*)aPattern
options: (NSRegularExpressionOptions)opts
- error: (NSError**)e;
+ error: (NSError *_Nullable *_Nullable)e;
- (id) initWithPattern: (NSString*)aPattern
options: (NSRegularExpressionOptions)opts
- error: (NSError**)e;
+ error: (NSError *_Nullable *_Nullable)e;
+ (NSRegularExpression*) regularExpressionWithPattern: (NSString*)aPattern
options: (NSRegularExpressionOptions)opts
- error: (NSError**)e;
+ error: (NSError *_Nullable *_Nullable)e;
- (id) initWithPattern: (NSString*)aPattern
options: (NSRegularExpressionOptions)opts
- error: (NSError**)e;
+ error: (NSError *_Nullable *_Nullable)e;
- (NSString*) pattern;
#if GS_API_VERSION( 13100, GS_API_LATEST)
/** In the GNUstep implementation this method is the fundametal primitive
diff --git a/Headers/Foundation/NSURL.h b/Headers/Foundation/NSURL.h
index d314a162d5..9a0d750c6b 100644
--- a/Headers/Foundation/NSURL.h
+++ b/Headers/Foundation/NSURL.h
@@ -250,7 +250,7 @@ GS_EXPORT_CLASS
* response if the data is unrachable.
* Returns YES on success, NO on failure.
*/
-- (BOOL) checkResourceIsReachableAndReturnError: (NSError **)error;
+- (BOOL) checkResourceIsReachableAndReturnError: (NSError *_Nullable *_Nullable)error;
#endif
/**
@@ -801,4 +801,3 @@ GS_NSURLComponents_IVARS;
#endif /* GS_API_MACOSX */
#endif /* __NSURL_h_GNUSTEP_BASE_INCLUDE */
-
From 37dddc8e4931a03d6fa653ab29943cd1493454a7 Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Mon, 27 Apr 2026 13:52:03 -0500
Subject: [PATCH 06/12] Tighten NSFileManager retained NSError annotations
---
Headers/Foundation/NSFileManager.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Headers/Foundation/NSFileManager.h b/Headers/Foundation/NSFileManager.h
index b6b6f0efa9..13e136d5fa 100644
--- a/Headers/Foundation/NSFileManager.h
+++ b/Headers/Foundation/NSFileManager.h
@@ -310,7 +310,7 @@ GS_EXPORT_CLASS
*/
- (BOOL) createSymbolicLinkAtPath: (NSString*)path
withDestinationPath: (NSString*)destPath
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
- (BOOL) setAttributes:(NSDictionary *)attributes ofItemAtPath:(NSString *)path error:(NSError **)error;
#endif
@@ -391,7 +391,7 @@ GS_EXPORT_CLASS
- (NSArray*) contentsOfDirectoryAtPath: (NSString*)path error: (NSError**)error;
- (NSDictionary*) attributesOfFileSystemForPath: (NSString*)path
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
#endif
- (BOOL) copyPath: (NSString*)source
From f863f6c565ec15fcf98b8c8ed1b9eebb3193c661 Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Mon, 27 Apr 2026 14:20:11 -0500
Subject: [PATCH 07/12] Implement basic file URL resource values
---
Source/NSURL.m | 61 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/Source/NSURL.m b/Source/NSURL.m
index be1db02c95..f14ca0908e 100644
--- a/Source/NSURL.m
+++ b/Source/NSURL.m
@@ -1744,7 +1744,66 @@ - (BOOL) getResourceValue: (id*)value
forKey: (NSString *)key
error: (NSError**)error
{
- // TODO: unimplemented
+ if (value != 0)
+ {
+ *value = nil;
+ }
+
+ if (NO == [self isFileURL])
+ {
+ return NO;
+ }
+
+ if (nil == key)
+ {
+ return NO;
+ }
+
+ if ([key isEqualToString: NSURLNameKey])
+ {
+ if (value != 0)
+ {
+ *value = [self lastPathComponent];
+ }
+ return YES;
+ }
+ else if ([key isEqualToString: NSURLIsDirectoryKey]
+ || [key isEqualToString: NSURLFileSizeKey])
+ {
+ NSDictionary *attributes;
+ NSString *path = [self path];
+
+ if (nil == path)
+ {
+ return NO;
+ }
+
+ attributes = [[NSFileManager defaultManager] fileAttributesAtPath: path
+ traverseLink: YES];
+ if (nil == attributes)
+ {
+ return NO;
+ }
+
+ if ([key isEqualToString: NSURLIsDirectoryKey])
+ {
+ if (value != 0)
+ {
+ NSString *fileType = [attributes objectForKey: NSFileType];
+
+ *value = [NSNumber numberWithBool:
+ [fileType isEqualToString: NSFileTypeDirectory]];
+ }
+ return YES;
+ }
+
+ if (value != 0)
+ {
+ *value = [attributes objectForKey: NSFileSize];
+ }
+ return (*value != nil);
+ }
+
return NO;
}
From 1bb56920d5d17c1680d331c43bab0b1f1f81e676 Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Mon, 27 Apr 2026 15:08:29 -0500
Subject: [PATCH 08/12] Widen file URL resource values
---
Source/NSURL.m | 91 ++++++++++++++++++++++++--
Tests/base/NSURL/resourceValues.m | 103 ++++++++++++++++++++++++++++++
2 files changed, 189 insertions(+), 5 deletions(-)
create mode 100644 Tests/base/NSURL/resourceValues.m
diff --git a/Source/NSURL.m b/Source/NSURL.m
index f14ca0908e..0a413bd077 100644
--- a/Source/NSURL.m
+++ b/Source/NSURL.m
@@ -1767,11 +1767,20 @@ - (BOOL) getResourceValue: (id*)value
}
return YES;
}
- else if ([key isEqualToString: NSURLIsDirectoryKey]
+ else if ([key isEqualToString: NSURLIsRegularFileKey]
+ || [key isEqualToString: NSURLIsDirectoryKey]
+ || [key isEqualToString: NSURLIsSymbolicLinkKey]
+ || [key isEqualToString: NSURLIsPackageKey]
+ || [key isEqualToString: NSURLIsHiddenKey]
+ || [key isEqualToString: NSURLCreationDateKey]
+ || [key isEqualToString: NSURLContentAccessDateKey]
+ || [key isEqualToString: NSURLContentModificationDateKey]
+ || [key isEqualToString: NSURLAttributeModificationDateKey]
|| [key isEqualToString: NSURLFileSizeKey])
{
NSDictionary *attributes;
NSString *path = [self path];
+ NSString *fileType;
if (nil == path)
{
@@ -1779,23 +1788,95 @@ - (BOOL) getResourceValue: (id*)value
}
attributes = [[NSFileManager defaultManager] fileAttributesAtPath: path
- traverseLink: YES];
+ traverseLink: NO];
if (nil == attributes)
{
return NO;
}
- if ([key isEqualToString: NSURLIsDirectoryKey])
+ fileType = [attributes objectForKey: NSFileType];
+ if ([key isEqualToString: NSURLIsRegularFileKey])
+ {
+ if (value != 0)
+ {
+ *value = [NSNumber numberWithBool:
+ [fileType isEqualToString: NSFileTypeRegular]];
+ }
+ return YES;
+ }
+ else if ([key isEqualToString: NSURLIsDirectoryKey])
{
if (value != 0)
{
- NSString *fileType = [attributes objectForKey: NSFileType];
-
*value = [NSNumber numberWithBool:
[fileType isEqualToString: NSFileTypeDirectory]];
}
return YES;
}
+ else if ([key isEqualToString: NSURLIsSymbolicLinkKey])
+ {
+ if (value != 0)
+ {
+ *value = [NSNumber numberWithBool:
+ [fileType isEqualToString: NSFileTypeSymbolicLink]];
+ }
+ return YES;
+ }
+ else if ([key isEqualToString: NSURLIsPackageKey])
+ {
+ if (value != 0)
+ {
+ NSString *extension = [[path pathExtension] lowercaseString];
+
+ *value = [NSNumber numberWithBool:
+ [extension isEqualToString: @"app"]
+ || [extension isEqualToString: @"bundle"]
+ || [extension isEqualToString: @"framework"]
+ || [extension isEqualToString: @"plugin"]];
+ }
+ return YES;
+ }
+ else if ([key isEqualToString: NSURLIsHiddenKey])
+ {
+ if (value != 0)
+ {
+ *value = [NSNumber numberWithBool:
+ [[path lastPathComponent] hasPrefix: @"."]];
+ }
+ return YES;
+ }
+ else if ([key isEqualToString: NSURLCreationDateKey])
+ {
+ if (value != 0)
+ {
+ *value = [attributes objectForKey: NSFileCreationDate];
+ }
+ return (*value != nil);
+ }
+ else if ([key isEqualToString: NSURLContentAccessDateKey])
+ {
+ if (value != 0)
+ {
+ *value = [attributes objectForKey: NSFileModificationDate];
+ }
+ return (*value != nil);
+ }
+ else if ([key isEqualToString: NSURLContentModificationDateKey])
+ {
+ if (value != 0)
+ {
+ *value = [attributes objectForKey: NSFileModificationDate];
+ }
+ return (*value != nil);
+ }
+ else if ([key isEqualToString: NSURLAttributeModificationDateKey])
+ {
+ if (value != 0)
+ {
+ *value = [attributes objectForKey: NSFileModificationDate];
+ }
+ return (*value != nil);
+ }
if (value != 0)
{
diff --git a/Tests/base/NSURL/resourceValues.m b/Tests/base/NSURL/resourceValues.m
new file mode 100644
index 0000000000..9e78919cd9
--- /dev/null
+++ b/Tests/base/NSURL/resourceValues.m
@@ -0,0 +1,103 @@
+#import
+#import "Testing.h"
+#import "ObjectTesting.h"
+
+#if !defined(_WIN32)
+#include
+#endif
+
+static BOOL
+getValue(NSURL *url, NSString *key, id *value)
+{
+ NSError *error = nil;
+
+ return [url getResourceValue: value forKey: key error: &error];
+}
+
+int
+main()
+{
+ NSAutoreleasePool *arp = [NSAutoreleasePool new];
+ NSFileManager *fm = [NSFileManager defaultManager];
+ NSString *root = [NSTemporaryDirectory()
+ stringByAppendingPathComponent: @"NSURLResourceValuesTest"];
+ NSString *filePath = [root stringByAppendingPathComponent: @"file.txt"];
+ NSString *hiddenPath = [root stringByAppendingPathComponent: @".hidden"];
+ NSString *dirPath = [root stringByAppendingPathComponent: @"Sample.app"];
+ NSString *linkPath = [root stringByAppendingPathComponent: @"link.txt"];
+ NSURL *fileURL;
+ NSURL *hiddenURL;
+ NSURL *dirURL;
+ NSURL *linkURL;
+ id value = nil;
+
+ START_SET("NSURL resource values");
+
+ [fm removeFileAtPath: root handler: nil];
+ PASS([fm createDirectoryAtPath: root attributes: nil],
+ "created resource value test directory");
+ PASS([@"hello" writeToFile: filePath atomically: YES],
+ "created regular file");
+ PASS([@"secret" writeToFile: hiddenPath atomically: YES],
+ "created hidden file");
+ PASS([fm createDirectoryAtPath: dirPath attributes: nil],
+ "created package directory");
+#if !defined(_WIN32)
+ PASS(0 == symlink([filePath fileSystemRepresentation],
+ [linkPath fileSystemRepresentation]), "created symbolic link");
+#endif
+
+ fileURL = [NSURL fileURLWithPath: filePath];
+ hiddenURL = [NSURL fileURLWithPath: hiddenPath];
+ dirURL = [NSURL fileURLWithPath: dirPath];
+ linkURL = [NSURL fileURLWithPath: linkPath];
+
+ PASS(getValue(fileURL, NSURLNameKey, &value), "NSURLNameKey succeeds");
+ PASS_EQUAL(value, @"file.txt", "NSURLNameKey returns last path component");
+
+ PASS(getValue(fileURL, NSURLIsRegularFileKey, &value),
+ "NSURLIsRegularFileKey succeeds");
+ PASS_EQUAL(value, [NSNumber numberWithBool: YES],
+ "regular file reports regular");
+ PASS(getValue(fileURL, NSURLIsDirectoryKey, &value),
+ "NSURLIsDirectoryKey succeeds");
+ PASS_EQUAL(value, [NSNumber numberWithBool: NO],
+ "regular file is not a directory");
+ PASS(getValue(fileURL, NSURLFileSizeKey, &value),
+ "NSURLFileSizeKey succeeds");
+ PASS_EQUAL(value, [NSNumber numberWithUnsignedLongLong: 5],
+ "file size is reported");
+
+ PASS(getValue(dirURL, NSURLIsDirectoryKey, &value),
+ "directory NSURLIsDirectoryKey succeeds");
+ PASS_EQUAL(value, [NSNumber numberWithBool: YES],
+ "directory reports directory");
+ PASS(getValue(dirURL, NSURLIsPackageKey, &value),
+ "NSURLIsPackageKey succeeds");
+ PASS_EQUAL(value, [NSNumber numberWithBool: YES],
+ ".app directory reports package");
+
+ PASS(getValue(hiddenURL, NSURLIsHiddenKey, &value),
+ "NSURLIsHiddenKey succeeds");
+ PASS_EQUAL(value, [NSNumber numberWithBool: YES],
+ "dot file reports hidden");
+
+#if !defined(_WIN32)
+ PASS(getValue(linkURL, NSURLIsSymbolicLinkKey, &value),
+ "NSURLIsSymbolicLinkKey succeeds");
+ PASS_EQUAL(value, [NSNumber numberWithBool: YES],
+ "symbolic link reports symbolic link");
+#endif
+
+ PASS(getValue(fileURL, NSURLContentModificationDateKey, &value),
+ "NSURLContentModificationDateKey succeeds");
+ PASS([value isKindOfClass: [NSDate class]],
+ "modification date is an NSDate");
+
+ [fm removeFileAtPath: root handler: nil];
+
+ END_SET("NSURL resource values");
+
+ DESTROY(arp);
+ return 0;
+}
From 086fbfbffe9a1bcf349d006d917901d8c1fc2d6b Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Mon, 27 Apr 2026 15:33:19 -0500
Subject: [PATCH 09/12] Skip package descendants in URL enumerators
---
Headers/Foundation/NSFileManager.h | 1 +
Source/NSFileManager.m | 27 ++++++++++++++++++++++++++
Tests/base/NSFileManager/general.m | 31 ++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+)
diff --git a/Headers/Foundation/NSFileManager.h b/Headers/Foundation/NSFileManager.h
index 13e136d5fa..4128ab56a0 100644
--- a/Headers/Foundation/NSFileManager.h
+++ b/Headers/Foundation/NSFileManager.h
@@ -590,6 +590,7 @@ GS_EXPORT_CLASS
BOOL justContents: 1;
BOOL skipHidden: 1;
BOOL currentIsDir: 1;
+ BOOL skipPackages: 1;
} _flags;
#endif
#if GS_NONFRAGILE
diff --git a/Source/NSFileManager.m b/Source/NSFileManager.m
index 3de1b0f8e0..27004b32e2 100644
--- a/Source/NSFileManager.m
+++ b/Source/NSFileManager.m
@@ -194,6 +194,7 @@ - (id) initWithDirectoryPath: (NSString*)path
followSymlinks: (BOOL)follow
justContents: (BOOL)justContents
skipHidden: (BOOL)skipHidden
+ skipPackages: (BOOL)skipPackages
errorHandler: (GSDirEnumErrorHandler) handler
for: (NSFileManager*)mgr;
@@ -958,6 +959,7 @@ - (NSDirectoryEnumerator*) enumeratorAtURL: (NSURL*)url
NSString *path;
BOOL shouldRecurse;
BOOL shouldSkipHidden;
+ BOOL shouldSkipPackages;
[self _setLastError: nil code: 0];
@@ -986,6 +988,16 @@ - (NSDirectoryEnumerator*) enumeratorAtURL: (NSURL*)url
{
shouldSkipHidden = NO;
}
+
+ if ((mask & NSDirectoryEnumerationSkipsPackageDescendants)
+ == NSDirectoryEnumerationSkipsPackageDescendants)
+ {
+ shouldSkipPackages = YES;
+ }
+ else
+ {
+ shouldSkipPackages = NO;
+ }
direnum = [[GSURLEnumerator alloc]
initWithDirectoryPath: path
@@ -993,6 +1005,7 @@ - (NSDirectoryEnumerator*) enumeratorAtURL: (NSURL*)url
followSymlinks: NO
justContents: NO
skipHidden: shouldSkipHidden
+ skipPackages: shouldSkipPackages
errorHandler: handler
for: self];
@@ -2752,6 +2765,7 @@ - (id) initWithDirectoryPath: (NSString*)path
followSymlinks: (BOOL)follow
justContents: (BOOL)justContents
skipHidden: (BOOL)skipHidden
+ skipPackages: (BOOL)skipPackages
errorHandler: (GSDirEnumErrorHandler) handler
for: (NSFileManager*)mgr
{
@@ -2770,6 +2784,7 @@ - (id) initWithDirectoryPath: (NSString*)path
_flags.isFollowing = follow ? 1 : 0;
_flags.justContents = justContents ? 1 : 0;
_flags.skipHidden = skipHidden ? 1 : 0;
+ _flags.skipPackages = skipPackages ? 1 : 0;
_errorHandler = handler;
_topPath = [[NSString alloc] initWithString: path];
@@ -2830,6 +2845,7 @@ - (id) initWithDirectoryPath: (NSString*)path
followSymlinks: follow
justContents: justContents
skipHidden: NO
+ skipPackages: NO
errorHandler: NULL
for: mgr];
}
@@ -3041,6 +3057,17 @@ - (id) nextObject
if (S_IFDIR == (S_IFMT & statbuf.st_mode))
{
_DIR *dir_pointer;
+ NSString *extension;
+
+ extension = [[_currentFilePath pathExtension] lowercaseString];
+ if (_flags.skipPackages
+ && ([extension isEqualToString: @"app"]
+ || [extension isEqualToString: @"bundle"]
+ || [extension isEqualToString: @"framework"]
+ || [extension isEqualToString: @"plugin"]))
+ {
+ break;
+ }
dir_pointer
= _OPENDIR([_mgr fileSystemRepresentationWithPath:
diff --git a/Tests/base/NSFileManager/general.m b/Tests/base/NSFileManager/general.m
index 3431849452..c86a2d1242 100644
--- a/Tests/base/NSFileManager/general.m
+++ b/Tests/base/NSFileManager/general.m
@@ -287,6 +287,12 @@ int main()
PASS([mgr createDirectoryAtPath: @"subdir" attributes: nil],
"NSFileManager can create a subdirectory");
+ PASS([mgr createDirectoryAtPath: @"Sample.app" attributes: nil],
+ "NSFileManager can create a package directory");
+ PASS([mgr createFileAtPath: @"Sample.app/Info.plist"
+ contents: [@"{}" dataUsingEncoding: NSASCIIStringEncoding]
+ attributes: nil],
+ "NSFileManager can create a package leaf");
{
NSURL *u;
@@ -310,6 +316,31 @@ int main()
PASS(2 == found, "URL enumerator finds expected file and subdirectory")
}
+ {
+ NSURL *u;
+ NSDirectoryEnumerator *e;
+ BOOL foundPackage = NO;
+ BOOL foundPackageLeaf = NO;
+
+ e = [mgr enumeratorAtURL: [NSURL fileURLWithPath: @"."]
+ includingPropertiesForKeys: nil
+ options: NSDirectoryEnumerationSkipsPackageDescendants
+ errorHandler: nil];
+
+ while (nil != (u = [e nextObject]))
+ {
+ NSString *c = [[u path] lastPathComponent];
+
+ if ([c isEqualToString: @"Sample.app"])
+ foundPackage = YES;
+ if ([c isEqualToString: @"Info.plist"])
+ foundPackageLeaf = YES;
+ }
+ PASS(foundPackage, "URL enumerator lists package directory")
+ PASS(!foundPackageLeaf,
+ "URL enumerator skips package descendants when requested")
+ }
+
PASS([mgr changeCurrentDirectoryPath: @"subdir"],
"NSFileManager can move into subdir");
From bda5a3d90cc7c72e526f50043b8cb60b3cbf9beb Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Thu, 30 Apr 2026 16:14:55 -0500
Subject: [PATCH 10/12] Tighten NSFileHandle retained NSError annotations
---
Headers/Foundation/NSFileHandle.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Headers/Foundation/NSFileHandle.h b/Headers/Foundation/NSFileHandle.h
index c7ff19e030..1df77e1df2 100644
--- a/Headers/Foundation/NSFileHandle.h
+++ b/Headers/Foundation/NSFileHandle.h
@@ -55,11 +55,11 @@ GS_EXPORT_CLASS
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+ (instancetype) fileHandleForReadingFromURL: (NSURL*)url
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (instancetype) fileHandleForWritingToURL: (NSURL*)url
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (instancetype) fileHandleForUpdatingURL: (NSURL*)url
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
#endif
- (id) initWithFileDescriptor: (int)desc;
From 498a344d17f8355955f3c7a3d9239487d7d84538 Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Mon, 4 May 2026 13:57:03 -0500
Subject: [PATCH 11/12] Return NSError for invalid keyed unarchive data
---
Source/NSKeyedUnarchiver.m | 39 ++++++++++++++++++++++++++--
Tests/base/NSKeyedArchiver/general.m | 18 +++++++++++++
2 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/Source/NSKeyedUnarchiver.m b/Source/NSKeyedUnarchiver.m
index 70b60e0a50..92a7cc1bd5 100644
--- a/Source/NSKeyedUnarchiver.m
+++ b/Source/NSKeyedUnarchiver.m
@@ -27,7 +27,9 @@
#import "Foundation/NSAutoreleasePool.h"
#import "Foundation/NSData.h"
#import "Foundation/NSDictionary.h"
+#import "Foundation/NSError.h"
#import "Foundation/NSException.h"
+#import "Foundation/FoundationErrors.h"
#import "Foundation/NSMapTable.h"
#import "Foundation/NSNull.h"
#import "Foundation/NSValue.h"
@@ -55,6 +57,25 @@ @implementation NilMarker
static NSMapTable *globalClassMap = 0;
+static NSError *
+GSNSErrorFromUnarchiverException(NSException *exception)
+{
+ NSDictionary *info;
+ NSString *reason = [exception reason];
+
+ if (reason == nil)
+ {
+ reason = @"The archive data could not be decoded.";
+ }
+ info = [NSDictionary dictionaryWithObjectsAndKeys:
+ reason, NSLocalizedDescriptionKey,
+ [exception name], @"NSExceptionName",
+ nil];
+ return [NSError errorWithDomain: NSCocoaErrorDomain
+ code: NSFileReadCorruptFileError
+ userInfo: info];
+}
+
#define GETVAL \
id o; \
\
@@ -387,8 +408,23 @@ + (id) unarchivedObjectOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)classes
fromData: (NSData*)data
error: (NSError**)error
{
+ id object = nil;
+
/* FIXME: implement proper secure coding support */
- return [self unarchiveObjectWithData: data];
+ NS_DURING
+ {
+ object = RETAIN([self unarchiveObjectWithData: data]);
+ }
+ NS_HANDLER
+ {
+ if (error != 0)
+ {
+ *error = GSNSErrorFromUnarchiverException(localException);
+ }
+ DESTROY(object);
+ }
+ NS_ENDHANDLER
+ return AUTORELEASE(object);
}
+ (NSArray*) unarchivedArrayOfObjectsOfClass: (Class)cls
@@ -1007,4 +1043,3 @@ + (Class) classForKeyedUnarchiver
return self;
}
@end
-
diff --git a/Tests/base/NSKeyedArchiver/general.m b/Tests/base/NSKeyedArchiver/general.m
index c7d5d3efea..304864723b 100644
--- a/Tests/base/NSKeyedArchiver/general.m
+++ b/Tests/base/NSKeyedArchiver/general.m
@@ -3,6 +3,7 @@
#import
#import
#import
+#import
#import
#import
#import
@@ -21,6 +22,7 @@ int main()
NSArray *a;
NSURL *u;
NSMutableSet *ms;
+ NSError *error = nil;
NSKeyedArchiver *archiver = nil;
NSKeyedUnarchiver *unarchiver = nil;
@@ -67,6 +69,22 @@ int main()
PASS((a != nil && [a isKindOfClass:[NSArray class]] && [a isEqual:vals2]),
"unarchiveObjectWithFile: seems ok");
+ data1 = [NSData dataWithBytes: "nope" length: 4];
+ error = nil;
+ a = [NSKeyedUnarchiver unarchivedObjectOfClass: [NSString class]
+ fromData: data1
+ error: &error];
+ PASS((a == nil && error != nil),
+ "unarchivedObjectOfClass:fromData:error: reports invalid data as NSError");
+
+ error = nil;
+ a = [NSKeyedUnarchiver unarchivedObjectOfClasses:
+ [NSSet setWithObject: [NSString class]]
+ fromData: data1
+ error: &error];
+ PASS((a == nil && error != nil),
+ "unarchivedObjectOfClasses:fromData:error: reports invalid data as NSError");
+
// encode
data2 = [NSMutableData dataWithCapacity: 10240];
archiver = AUTORELEASE([[NSKeyedArchiver alloc]
From 09bfdd78b40f00407782ccc0434d492a4bcdb15e Mon Sep 17 00:00:00 2001
From: Daniel Boyd
Date: Mon, 4 May 2026 14:25:27 -0500
Subject: [PATCH 12/12] Tighten NSKeyedArchiver retained NSError annotations
---
Headers/Foundation/NSKeyedArchiver.h | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/Headers/Foundation/NSKeyedArchiver.h b/Headers/Foundation/NSKeyedArchiver.h
index ea5856650e..cbbd8febf1 100644
--- a/Headers/Foundation/NSKeyedArchiver.h
+++ b/Headers/Foundation/NSKeyedArchiver.h
@@ -98,7 +98,7 @@ GS_EXPORT_CLASS
*/
+ (NSData *) archivedDataWithRootObject: (id)anObject
requiringSecureCoding: (BOOL)requiresSecureCoding
- error: (NSError **)error;
+ error: (NSError *_Nullable *_Nullable)error;
#endif
/**
@@ -315,11 +315,11 @@ GS_EXPORT_CLASS
+ (id) unarchivedObjectOfClass: (Class)cls
fromData: (NSData*)data
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (id) unarchivedObjectOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)classes
fromData: (NSData*)data
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
#endif
@@ -327,21 +327,21 @@ GS_EXPORT_CLASS
+ (NSArray*) unarchivedArrayOfObjectsOfClass: (Class)cls
fromData: (NSData*)data
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (NSArray*) unarchivedArrayOfObjectsOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)classes
fromData: (NSData*)data
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (NSDictionary*) unarchivedDictionaryWithKeysOfClass: (Class)keyCls
objectsOfClass: (Class)valueCls
fromData: (NSData*)data
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
+ (NSDictionary*) unarchivedDictionaryWithKeysOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)keyClasses
objectsOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)valueClasses
fromData: (NSData*)data
- error: (NSError**)error;
+ error: (NSError *_Nullable *_Nullable)error;
#endif
@@ -668,4 +668,3 @@ willReplaceObject: (id)anObject
#endif /* GS_API_MACOSX */
#endif /* __NSKeyedArchiver_h_GNUSTEP_BASE_INCLUDE */
-