X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3903760236c30e3b5ace7a4eefac3a269d68957c..eb6b6ca394357805f2bdba989abae309f718b4d8:/libkern/os/base.h?ds=sidebyside diff --git a/libkern/os/base.h b/libkern/os/base.h index e37800e81..bea2772a4 100644 --- a/libkern/os/base.h +++ b/libkern/os/base.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2016 Apple Inc. All rights reserved. + * Copyright (c) 2008-2013 Apple Inc. All rights reserved. * * @APPLE_APACHE_LICENSE_HEADER_START@ * @@ -73,7 +73,7 @@ #define OS_ALWAYS_INLINE __attribute__((__always_inline__)) #define OS_TRANSPARENT_UNION __attribute__((__transparent_union__)) #define OS_ALIGNED(n) __attribute__((__aligned__((n)))) -#define OS_FORMAT_PRINTF(x,y) __attribute__((__format__(printf,x,y))) +#define OS_FORMAT_PRINTF(x, y) __attribute__((__format__(printf,x,y))) #define OS_EXPORT extern __attribute__((__visibility__("default"))) #define OS_INLINE static __inline__ #define OS_EXPECT(x, v) __builtin_expect((x), (v)) @@ -110,7 +110,7 @@ #define OS_ALWAYS_INLINE #define OS_TRANSPARENT_UNION #define OS_ALIGNED(n) -#define OS_FORMAT_PRINTF(x,y) +#define OS_FORMAT_PRINTF(x, y) #define OS_EXPORT extern #define OS_INLINE static inline #define OS_EXPECT(x, v) (x) @@ -122,6 +122,12 @@ #define OS_NOESCAPE #endif +#if defined(__cplusplus) && defined(__clang__) +#define OS_FALLTHROUGH [[clang::fallthrough]] +#else +#define OS_FALLTHROUGH +#endif + #if __has_feature(assume_nonnull) #define OS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #define OS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") @@ -142,18 +148,91 @@ #define OS_OVERLOADABLE #endif -#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums) +#if __has_attribute(enum_extensibility) +#define __OS_ENUM_ATTR __attribute__((enum_extensibility(open))) +#define __OS_ENUM_ATTR_CLOSED __attribute__((enum_extensibility(closed))) +#else +#define __OS_ENUM_ATTR +#define __OS_ENUM_ATTR_CLOSED +#endif // __has_attribute(enum_extensibility) + +#if __has_attribute(flag_enum) +/*! + * Compile with -Wflag-enum and -Wassign-enum to enforce at definition and + * assignment, respectively, i.e. -Wflag-enum prevents you from creating new + * enumeration values from illegal values within the enum definition, and + * -Wassign-enum prevents you from assigning illegal values to a variable of the + * enum type. + */ +#define __OS_OPTIONS_ATTR __attribute__((flag_enum)) +#else +#define __OS_OPTIONS_ATTR +#endif // __has_attribute(flag_enum) + +#if __has_feature(objc_fixed_enum) || __has_extension(cxx_fixed_enum) || \ + __has_extension(cxx_strong_enums) #define OS_ENUM(_name, _type, ...) \ - typedef enum : _type { __VA_ARGS__ } _name##_t + typedef enum : _type { __VA_ARGS__ } _name##_t +#define OS_CLOSED_ENUM(_name, _type, ...) \ + typedef enum : _type { __VA_ARGS__ } \ + __OS_ENUM_ATTR_CLOSED _name##_t +#define OS_OPTIONS(_name, _type, ...) \ + typedef enum : _type { __VA_ARGS__ } \ + __OS_ENUM_ATTR __OS_OPTIONS_ATTR _name##_t +#define OS_CLOSED_OPTIONS(_name, _type, ...) \ + typedef enum : _type { __VA_ARGS__ } \ + __OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR _name##_t #else +/*! + * There is unfortunately no good way in plain C to have both fixed-type enums + * and enforcement for clang's enum_extensibility extensions. The primary goal + * of these macros is to allow you to define an enum and specify its width in a + * single statement, and for plain C that is accomplished by defining an + * anonymous enum and then separately typedef'ing the requested type name to the + * requested underlying integer type. So the type emitted actually has no + * relationship at all to the enum, and therefore while the compiler could + * enforce enum extensibility if you used the enum type, it cannot do so if you + * use the "_t" type resulting from this expression. + * + * But we still define a named enum type and decorate it appropriately for you, + * so if you really want the enum extensibility enforcement, you can use the + * enum type yourself, i.e. when compiling with a C compiler: + * + * OS_CLOSED_ENUM(my_type, uint64_t, + * FOO, + * BAR, + * BAZ, + * ); + * + * my_type_t mt = 98; // legal + * enum my_type emt = 98; // illegal + * + * But be aware that the underlying enum type's width is subject only to the C + * language's guarantees -- namely that it will be compatible with int, char, + * and unsigned char. It is not safe to rely on the size of this type. + * + * When compiling in ObjC or C++, both of the above assignments are illegal. + */ +#define __OS_ENUM_C_FALLBACK(_name, _type, ...) \ + typedef _type _name##_t; enum _name { __VA_ARGS__ } + #define OS_ENUM(_name, _type, ...) \ - enum { __VA_ARGS__ }; typedef _type _name##_t -#endif + typedef _type _name##_t; enum { __VA_ARGS__ } +#define OS_CLOSED_ENUM(_name, _type, ...) \ + __OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \ + __OS_ENUM_ATTR_CLOSED +#define OS_OPTIONS(_name, _type, ...) \ + __OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \ + __OS_ENUM_ATTR __OS_OPTIONS_ATTR +#define OS_CLOSED_OPTIONS(_name, _type, ...) \ + __OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \ + __OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR +#endif // __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums) #if __has_feature(attribute_availability_swift) // equivalent to __SWIFT_UNAVAILABLE from Availability.h #define OS_SWIFT_UNAVAILABLE(_msg) \ - __attribute__((__availability__(swift, unavailable, message=_msg))) + __attribute__((__availability__(swift, unavailable, message=_msg))) #else #define OS_SWIFT_UNAVAILABLE(_msg) #endif @@ -178,12 +257,16 @@ #ifdef __GNUC__ #define os_prevent_tail_call_optimization() __asm__("") #define os_is_compile_time_constant(expr) __builtin_constant_p(expr) +#ifndef KERNEL #define os_compiler_barrier() __asm__ __volatile__("" ::: "memory") +#endif #else #define os_prevent_tail_call_optimization() do { } while (0) #define os_is_compile_time_constant(expr) 0 +#ifndef KERNEL #define os_compiler_barrier() do { } while (0) #endif +#endif #if __has_attribute(not_tail_called) #define OS_NOT_TAIL_CALLED __attribute__((__not_tail_called__)) @@ -191,6 +274,18 @@ #define OS_NOT_TAIL_CALLED #endif +/* + * LIBKERN_ALWAYS_DESTROY attribute can be applied to global variables with + * destructors. It specifies that and object should have its exit-time + * destructor run. This attribute is the default unless clang was invoked with + * -fno-c++-static-destructors. + */ +#if __has_attribute(always_destroy) +#define LIBKERN_ALWAYS_DESTROY __attribute__((always_destroy)) +#else +#define LIBKERN_ALWAYS_DESTROY +#endif + typedef void (*os_function_t)(void *_Nullable); #ifdef __BLOCKS__