]> git.saurik.com Git - apple/xnu.git/blobdiff - libkern/os/base.h
xnu-6153.141.1.tar.gz
[apple/xnu.git] / libkern / os / base.h
index e37800e814fd1f2bbb592e41858d5ba5af5b30ab..bea2772a4b2f0aa134df392d328ba4783aa81ee0 100644 (file)
@@ -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))
 #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)
 #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")
 #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
 #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__))
 #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__