summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Moskyto Matejka <mq@ucw.cz>2016-03-23 01:45:37 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2016-03-23 02:21:42 +0100
commit54bb032d21d25a2221877e15325e79add10278ec (patch)
treecf5fbb8388001ef2a9af3a55548f612264ef64ea
parent665b8e5283df4f64eb44d8fb434489be1474b5d4 (diff)
Birdlib: Modify lists to avoid problems with pointer aliasing rules
The old linked list implementation used some wild typecasts and required GCC option -fno-strict-aliasing to work properly. This patch fixes that. However, we still keep the option due to other potential problems. (Commited by Ondrej Santiago Zajicek)
-rw-r--r--lib/lists.c10
-rw-r--r--lib/lists.h17
2 files changed, 20 insertions, 7 deletions
diff --git a/lib/lists.c b/lib/lists.c
index 20a9a072..12ef3cc6 100644
--- a/lib/lists.c
+++ b/lib/lists.c
@@ -41,7 +41,7 @@ add_tail(list *l, node *n)
{
node *z = l->tail;
- n->next = (node *) &l->null;
+ n->next = &l->tail_node;
n->prev = z;
z->next = n;
l->tail = n;
@@ -60,7 +60,7 @@ add_head(list *l, node *n)
node *z = l->head;
n->next = z;
- n->prev = (node *) &l->head;
+ n->prev = &l->head_node;
z->prev = n;
l->head = n;
}
@@ -133,9 +133,9 @@ replace_node(node *old, node *new)
LIST_INLINE void
init_list(list *l)
{
- l->head = (node *) &l->null;
+ l->head = &l->tail_node;
l->null = NULL;
- l->tail = (node *) &l->head;
+ l->tail = &l->head_node;
}
/**
@@ -155,6 +155,6 @@ add_tail_list(list *to, list *l)
p->next = q;
q->prev = p;
q = l->tail;
- q->next = (node *) &to->null;
+ q->next = &to->tail_node;
to->tail = q;
}
diff --git a/lib/lists.h b/lib/lists.h
index 4204cbc5..51856b05 100644
--- a/lib/lists.h
+++ b/lib/lists.h
@@ -26,10 +26,23 @@ typedef struct node {
struct node *next, *prev;
} node;
-typedef struct list { /* In fact two overlayed nodes */
- struct node *head, *null, *tail;
+typedef union list { /* In fact two overlayed nodes */
+ struct { /* Head node */
+ struct node head_node;
+ void *head_padding;
+ };
+ struct { /* Tail node */
+ void *tail_padding;
+ struct node tail_node;
+ };
+ struct { /* Split to separate pointers */
+ struct node *head;
+ struct node *null;
+ struct node *tail;
+ };
} list;
+
#define NODE (node *)
#define HEAD(list) ((void *)((list).head))
#define TAIL(list) ((void *)((list).tail))