Update assertion macros to support multiple arguments

This commit is contained in:
Richard Frith-Macdonald 2018-02-06 09:35:34 +00:00
parent 8450b94bc8
commit 1937b36b86
4 changed files with 90 additions and 92 deletions

View file

@ -1,3 +1,11 @@
2018-02-06 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSException.h:
* Source/NSAssertionHandler.m:
* Documentation/manual/ExceptionHandling.texi:
Update NSAssert() and NSCAssert() to handle variable arguments
(as OSX has done) and mark the numbered macros as obsolete.
2018-02-05 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSPortCoder.m: Remove redundant (always true) conditional.

View file

@ -475,7 +475,7 @@ issue bundled in the documentation with Sun's Java distribution.
Assertions allow the developer to establish that certain conditions hold
before undertaking an operation. In GNUstep, the standard means to make an
assertion is to use one of a collection of @code{NSAssert} macros. The
assertion is to use the @code{NSAssert} or @code{NSCAssert} macros. The
general form of these macros is:
@example
@ -485,7 +485,7 @@ NSAssert(<boolean test>, <formatString>, <argumentsToFormat>);
For instance:
@example
NSAssert1(x == 10, "X should have been 10, but it was %d.", x);
NSAssert(x == 10, "X should have been 10, but it was %d.", x);
@end example
If the test '@code{x == 10}' evaluates to @code{true}, @code{NSLog()} is
@ -502,15 +502,8 @@ After this is logged, an exception is raised of type
'@code{NSInternalInconsistencyException}', with this string as its
description.
In order to provide the method and line number information, the
@code{NSAssert()} routine must be implemented as a macro, and therefore to
handle different numbers of arguments to the format string, there are 5
assertion macros for methods: @code{NSAssert(condition, description)},
@code{NSAssert1(condition, format, arg1)}, @code{NSAssert2(condition, format,
arg1, arg2)}, ..., @code{NSAssert5(...)}.
If you need to make an assertion inside a regular C function (not an
Objective-C method), use the equivalent macros @code{NSCAssert()}, etc..
Objective-C method), use the equivalent macro @code{NSCAssert()}, etc..
@i{@b{Note}}, you can completely disable assertions (saving the time for the
boolean test and avoiding the exception if fails) by putting @code{#define

View file

@ -392,6 +392,32 @@ GS_EXPORT void _NSRemoveHandler( NSHandler *handler );
/* Assertion Handling */
/* ------------------------------------------------------------------------ */
/**
* <p>NSAssertionHandler objects are used to raise exceptions on behalf of
* macros implementing assertions.<br />
* Each thread has its own assertion handler instance.<br />
* </p>
* <p>The macros work together with the assertion handler object to
* produce meaningful exception messages containing the name of the
* source file, the position within that file, and the name of the
* ObjC method or C function in which the assertion failed.
* </p>
* <p>An NSAssertionHandler instance is created on demand for each thread
* and is stored in the thread's dictionary under the key NSAssertionHandler.
* A custom NSAssertionHandler can be used by adding it to the thread
* dictionary under this key.
* </p>
* The assertion macros are:
* NSAssert(), NSCAssert(),
* NSAssert1(), NSCAssert1(),
* NSAssert2(), NSCAssert2(),
* NSAssert3(), NSCAssert3(),
* NSAssert4(), NSCAssert4(),
* NSAssert5(), NSCAssert5(),
* NSParameterAssert(), NSCParameterAssert()<br />
* The numbered macros arre obsolete, dating from a time when NSAssert() and
* NSCAssert() did not support a variable number of arguments.
*/
@interface NSAssertionHandler : NSObject
+ (NSAssertionHandler*) currentHandler;
@ -411,127 +437,122 @@ GS_EXPORT void _NSRemoveHandler( NSHandler *handler );
extern NSString *const NSAssertionHandlerKey;
#ifdef NS_BLOCK_ASSERTIONS
#define _NSAssertArgs(condition, desc, args...)
#define _NSCAssertArgs(condition, desc, args...)
#define NSAssert(condition, desc, args...)
#define NSCAssert(condition, desc, args...)
#else
#define _NSAssertArgs(condition, desc, args...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInMethod: _cmd \
object: self \
file: [NSString stringWithUTF8String: __FILE__] \
lineNumber: __LINE__ \
description: (desc) , ## args]; \
} \
} while(0)
/** Used in an ObjC method body.<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and args. */
#define NSAssert(condition, desc, args...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInMethod: _cmd \
object: self \
file: [NSString stringWithUTF8String: __FILE__] \
lineNumber: __LINE__ \
description: (desc) , ## args]; \
} \
} while(0)
#define _NSCAssertArgs(condition, desc, args...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction: [NSString stringWithUTF8String: __PRETTY_FUNCTION__] \
file: [NSString stringWithUTF8String: __FILE__] \
lineNumber: __LINE__ \
description: (desc) , ## args]; \
} \
} while(0)
/** Used in plain C code (not in an ObjC method body).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc
*/
#define NSCAssert(condition, desc, args...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction: [NSString stringWithUTF8String: \
__PRETTY_FUNCTION__] \
file: [NSString stringWithUTF8String: __FILE__] \
lineNumber: __LINE__ \
description: (desc) , ## args]; \
} \
} while(0)
#endif
/** Used in an ObjC method body.<br />
/** Used in an ObjC method body (obsolete ... use NSAssert).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2,
* arg3, arg4, arg5 */
#define NSAssert5(condition, desc, arg1, arg2, arg3, arg4, arg5) \
_NSAssertArgs((condition), (desc), (arg1), (arg2), (arg3), (arg4), (arg5))
NSAssert((condition), (desc), (arg1), (arg2), (arg3), (arg4), (arg5))
/** Used in an ObjC method body.<br />
/** Used in an ObjC method body (obsolete ... use NSAssert).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2,
* arg3, arg4 */
#define NSAssert4(condition, desc, arg1, arg2, arg3, arg4) \
_NSAssertArgs((condition), (desc), (arg1), (arg2), (arg3), (arg4))
NSAssert((condition), (desc), (arg1), (arg2), (arg3), (arg4))
/** Used in an ObjC method body.<br />
/** Used in an ObjC method body (obsolete ... use NSAssert).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2,
* arg3 */
#define NSAssert3(condition, desc, arg1, arg2, arg3) \
_NSAssertArgs((condition), (desc), (arg1), (arg2), (arg3))
NSAssert((condition), (desc), (arg1), (arg2), (arg3))
/** Used in an ObjC method body.<br />
/** Used in an ObjC method body (obsolete ... use NSAssert).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2 */
#define NSAssert2(condition, desc, arg1, arg2) \
_NSAssertArgs((condition), (desc), (arg1), (arg2))
NSAssert((condition), (desc), (arg1), (arg2))
/** Used in an ObjC method body.<br />
/** Used in an ObjC method body (obsolete ... use NSAssert).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1 */
#define NSAssert1(condition, desc, arg1) \
_NSAssertArgs((condition), (desc), (arg1))
/** Used in an ObjC method body.<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc */
#define NSAssert(condition, desc) \
_NSAssertArgs((condition), (desc))
NSAssert((condition), (desc), (arg1))
/** Used in an ObjC method body.<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception saying that an invalid
* parameter was supplied to the method. */
#define NSParameterAssert(condition) \
_NSAssertArgs((condition), @"Invalid parameter not satisfying: %s", #condition)
NSAssert((condition), @"Invalid parameter not satisfying: %s", #condition)
/** Used in plain C code (not in an ObjC method body).<br />
/** Obsolete ... use NSCAssert().<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2,
* arg3, arg4, arg5 */
#define NSCAssert5(condition, desc, arg1, arg2, arg3, arg4, arg5) \
_NSCAssertArgs((condition), (desc), (arg1), (arg2), (arg3), (arg4), (arg5))
NSCAssert((condition), (desc), (arg1), (arg2), (arg3), (arg4), (arg5))
/** Used in plain C code (not in an ObjC method body).<br />
/** Obsolete ... use NSCAssert().<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2,
* arg3, arg4 */
#define NSCAssert4(condition, desc, arg1, arg2, arg3, arg4) \
_NSCAssertArgs((condition), (desc), (arg1), (arg2), (arg3), (arg4))
NSCAssert((condition), (desc), (arg1), (arg2), (arg3), (arg4))
/** Used in plain C code (not in an ObjC method body).<br />
/** Obsolete ... use NSCAssert().<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2,
* arg3 */
#define NSCAssert3(condition, desc, arg1, arg2, arg3) \
_NSCAssertArgs((condition), (desc), (arg1), (arg2), (arg3))
NSCAssert((condition), (desc), (arg1), (arg2), (arg3))
/** Used in plain C code (not in an ObjC method body).<br />
/** Obsolete ... use NSCAssert().<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1, arg2
*/
#define NSCAssert2(condition, desc, arg1, arg2) \
_NSCAssertArgs((condition), (desc), (arg1), (arg2))
NSCAssert((condition), (desc), (arg1), (arg2))
/** Used in plain C code (not in an ObjC method body).<br />
/** Obsolete ... use NSCAssert().<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc and arg1
*/
#define NSCAssert1(condition, desc, arg1) \
_NSCAssertArgs((condition), (desc), (arg1))
/** Used in plain C code (not in an ObjC method body).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception using desc
*/
#define NSCAssert(condition, desc) \
_NSCAssertArgs((condition), (desc))
NSCAssert((condition), (desc), (arg1))
/** Used in plain C code (not in an ObjC method body).<br />
* See [NSAssertionHandler] for details.<br />
* When condition is false, raise an exception saying that an invalid
* parameter was supplied to the method. */
#define NSCParameterAssert(condition) \
_NSCAssertArgs((condition), @"Invalid parameter not satisfying: %s", #condition)
NSCAssert((condition), @"Invalid parameter not satisfying: %s", #condition)
#if defined(__cplusplus)
}

View file

@ -30,30 +30,6 @@
#import "Foundation/NSDictionary.h"
#import "Foundation/NSThread.h"
/**
* <p>NSAssertionHandler objects are used to raise exceptions on behalf of
* macros implementing assertions.<br />
* Each thread has its own assertion handler instance.<br />
* </p>
* <p>The macros work together with the assertion handler object to
* produce meaningful exception messages containing the name of the
* source file, the position within that file, and the name of the
* ObjC method or C function in which the assertion failed.
* </p>
* <p>An NSAssertionHandler instance is created on demand for each thread
* and is stored in the thread's dictionary under the key NSAssertionHandler.
* A custom NSAssertionHandler can be used by adding it to the thread
* dictionary under this key.
* </p>
* The assertion macros are:
* NSAssert(), NSCAssert(),
* NSAssert1(), NSCAssert1(),
* NSAssert2(), NSCAssert2(),
* NSAssert3(), NSCAssert3(),
* NSAssert4(), NSCAssert4(),
* NSAssert5(), NSCAssert5(),
* NSParameterAssert(), NSCParameterAssert()
*/
@implementation NSAssertionHandler
/* Key for thread dictionary. */