]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/sys/queue.h
xnu-6153.11.26.tar.gz
[apple/xnu.git] / bsd / sys / queue.h
index 8791385d7d4b31959fa21089c50c81f909bf5b23..23dc242c63061ab6219c66b8581a74628d737089 100644 (file)
@@ -207,14 +207,44 @@ struct qm_trace {
 #define __MISMATCH_TAGS_POP
 #endif
 
+/*!
+ * Ensures that these macros can safely be used in structs when compiling with
+ * clang. The macros do not allow for nullability attributes to be specified due
+ * to how they are expanded. For example:
+ *
+ *     SLIST_HEAD(, foo _Nullable) bar;
+ *
+ * expands to
+ *
+ *     struct {
+ *         struct foo _Nullable *slh_first;
+ *     }
+ *
+ * which is not valid because the nullability specifier has to apply to the
+ * pointer. So just ignore nullability completeness in all the places where this
+ * is an issue.
+ */
+#if defined(__clang__)
+#define __NULLABILITY_COMPLETENESS_PUSH \
+       _Pragma("clang diagnostic push") \
+       _Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")
+#define __NULLABILITY_COMPLETENESS_POP \
+       _Pragma("clang diagnostic pop")
+#else
+#define __NULLABILITY_COMPLETENESS_PUSH
+#define __NULLABILITY_COMPLETENESS_POP
+#endif
+
 /*
  * Singly-linked List declarations.
  */
 #define SLIST_HEAD(name, type)                                          \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *slh_first; /* first element */                     \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define SLIST_HEAD_INITIALIZER(head)                                    \
@@ -222,9 +252,11 @@ __MISMATCH_TAGS_POP
 
 #define SLIST_ENTRY(type)                                               \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *sle_next;  /* next element */                      \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -267,6 +299,7 @@ __MISMATCH_TAGS_POP
 
 #define SLIST_REMOVE(head, elm, type, field)                            \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        if (SLIST_FIRST((head)) == (elm)) {                             \
                SLIST_REMOVE_HEAD((head), field);                       \
@@ -279,6 +312,7 @@ do {                                                                    \
        }                                                               \
        TRASHIT((elm)->field.sle_next);                                 \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                      \
 __MISMATCH_TAGS_POP
 
 #define SLIST_REMOVE_AFTER(elm, field) do {                             \
@@ -295,10 +329,12 @@ __MISMATCH_TAGS_POP
  */
 #define STAILQ_HEAD(name, type)                                         \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *stqh_first;/* first element */                     \
        struct type **stqh_last;/* addr of last next element */         \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define STAILQ_HEAD_INITIALIZER(head)                                   \
@@ -306,9 +342,11 @@ __MISMATCH_TAGS_POP
 
 #define STAILQ_ENTRY(type)                                              \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *stqe_next; /* next element */                      \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                         \
 __MISMATCH_TAGS_POP
 
 /*
@@ -362,16 +400,19 @@ __MISMATCH_TAGS_POP
 
 #define STAILQ_LAST(head, type, field)                                  \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
        (STAILQ_EMPTY((head)) ?                                         \
                NULL :                                                  \
                ((struct type *)(void *)                                \
                ((char *)((head)->stqh_last) - __offsetof(struct type, field))))\
+__NULLABILITY_COMPLETENESS_POP                                         \
 __MISMATCH_TAGS_POP
 
 #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
 
 #define STAILQ_REMOVE(head, elm, type, field)                           \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        if (STAILQ_FIRST((head)) == (elm)) {                            \
                STAILQ_REMOVE_HEAD((head), field);                      \
@@ -384,6 +425,7 @@ do {                                                                    \
        }                                                               \
        TRASHIT((elm)->field.stqe_next);                                \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                      \
 __MISMATCH_TAGS_POP
 
 #define STAILQ_REMOVE_HEAD(head, field) do {                            \
@@ -405,6 +447,7 @@ __MISMATCH_TAGS_POP
 
 #define STAILQ_SWAP(head1, head2, type)                                 \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        struct type *swap_first = STAILQ_FIRST(head1);                  \
        struct type **swap_last = (head1)->stqh_last;                   \
@@ -417,6 +460,7 @@ do {                                                                    \
        if (STAILQ_EMPTY(head2))                                        \
                (head2)->stqh_last = &STAILQ_FIRST(head2);              \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 
@@ -425,9 +469,11 @@ __MISMATCH_TAGS_POP
  */
 #define LIST_HEAD(name, type)                                           \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *lh_first;  /* first element */                     \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define LIST_HEAD_INITIALIZER(head)                                     \
@@ -435,10 +481,12 @@ __MISMATCH_TAGS_POP
 
 #define LIST_ENTRY(type)                                                \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *le_next;   /* next element */                      \
        struct type **le_prev;  /* address of previous next element */  \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -530,6 +578,7 @@ __MISMATCH_TAGS_POP
 
 #define LIST_SWAP(head1, head2, type, field)                            \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        struct type *swap_tmp = LIST_FIRST((head1));                    \
        LIST_FIRST((head1)) = LIST_FIRST((head2));                      \
@@ -539,6 +588,7 @@ do {                                                                    \
        if ((swap_tmp = LIST_FIRST((head2))) != NULL)                   \
                swap_tmp->field.le_prev = &LIST_FIRST((head2));         \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -546,11 +596,13 @@ __MISMATCH_TAGS_POP
  */
 #define TAILQ_HEAD(name, type)                                          \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *tqh_first; /* first element */                     \
        struct type **tqh_last; /* addr of last next element */         \
        TRACEBUF                                                        \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define TAILQ_HEAD_INITIALIZER(head)                                    \
@@ -558,11 +610,13 @@ __MISMATCH_TAGS_POP
 
 #define TAILQ_ENTRY(type)                                               \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *tqe_next;  /* next element */                      \
        struct type **tqe_prev; /* address of previous next element */  \
        TRACEBUF                                                        \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -630,6 +684,17 @@ __MISMATCH_TAGS_POP
            (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);  \
            (var) = (tvar))
 
+#if XNU_KERNEL_PRIVATE
+/*
+ * Can be used when the initialized HEAD was just bzeroed
+ * Works around deficiencies in clang analysis of initialization patterns.
+ * See: <rdar://problem/47939050>
+ */
+#define TAILQ_INIT_AFTER_BZERO(head) do {                               \
+       (head)->tqh_last = &TAILQ_FIRST((head));                        \
+} while (0)
+#endif /* XNU_KERNEL_PRIVATE */
+
 #define TAILQ_INIT(head) do {                                           \
        TAILQ_FIRST((head)) = NULL;                                     \
        (head)->tqh_last = &TAILQ_FIRST((head));                        \
@@ -686,14 +751,18 @@ __MISMATCH_TAGS_POP
 
 #define TAILQ_LAST(head, headname)                                      \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
        (*(((struct headname *)((head)->tqh_last))->tqh_last))          \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
 
 #define TAILQ_PREV(elm, headname, field)                                \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))     \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define TAILQ_REMOVE(head, elm, field) do {                             \
@@ -717,6 +786,7 @@ __MISMATCH_TAGS_POP
  */
 #define TAILQ_SWAP(head1, head2, type, field)                           \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 do {                                                                    \
        struct type *swap_first = (head1)->tqh_first;                   \
        struct type **swap_last = (head1)->tqh_last;                    \
@@ -733,6 +803,7 @@ do {                                                                    \
        else                                                            \
                (head2)->tqh_last = &(head2)->tqh_first;                \
 } while (0)                                                             \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 /*
@@ -740,18 +811,22 @@ __MISMATCH_TAGS_POP
  */
 #define CIRCLEQ_HEAD(name, type)                                        \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct name {                                                           \
        struct type *cqh_first;         /* first element */             \
        struct type *cqh_last;          /* last element */              \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                          \
 __MISMATCH_TAGS_POP
 
 #define CIRCLEQ_ENTRY(type)                                             \
 __MISMATCH_TAGS_PUSH                                                    \
+__NULLABILITY_COMPLETENESS_PUSH                                         \
 struct {                                                                \
        struct type *cqe_next;          /* next element */              \
        struct type *cqe_prev;          /* previous element */          \
 }                                                                       \
+__NULLABILITY_COMPLETENESS_POP                                         \
 __MISMATCH_TAGS_POP
 
 /*