Commit cc99baa4 authored by David Rowley's avatar David Rowley

Improve pg_list.h's linitial(), lsecond() and co macros

Prior to this commit, the linitial(), lsecond(), lthird(), lfourth()
macros and their int and Oid list cousins would call their corresponding
inlined function to fetch the cell of interest.  Those inline functions
were kind enough to return NULL if the particular cell did not exist.
Unfortunately, the care that these functions took was of no relevance to
the calling macros as they proceeded to directly dereference the returned
value without any regard to whether that value was NULL or not.  If it had
been, we'd have segfaulted.

Of course, the fact that we would have segfaulted on misuse of these
macros just goes to prove that nobody is relying on the empty or list too
small checks.  So here we just get rid of those checks completely.

The existing inline functions have been left alone as someone may be using
those directly.  We just replace the call within each macro to use
list_nth_cell().

For the llast*() case we require a new list_last_cell() inline function to
get away from the multiple evaluation hazard that we'd get if we fetched
->length on the macro's parameter.

Author: David Rowley
Reviewed-by: Tom Lane
Discussion: https://postgr.es/m/CAApHDvpo1zj9KhEpU2cCRZfSM3Q6XGdhzuAS2v79PH7WJBkYVA@mail.gmail.com
parent 4d29e6db
......@@ -186,35 +186,34 @@ list_length(const List *l)
* linitial() than lfirst(): given a List, lsecond() returns the data
* in the second list cell.
*/
#define lfirst(lc) ((lc)->ptr_value)
#define lfirst_int(lc) ((lc)->int_value)
#define lfirst_oid(lc) ((lc)->oid_value)
#define lfirst_node(type,lc) castNode(type, lfirst(lc))
#define linitial(l) lfirst(list_head(l))
#define linitial_int(l) lfirst_int(list_head(l))
#define linitial_oid(l) lfirst_oid(list_head(l))
#define linitial(l) lfirst(list_nth_cell(l, 0))
#define linitial_int(l) lfirst_int(list_nth_cell(l, 0))
#define linitial_oid(l) lfirst_oid(list_nth_cell(l, 0))
#define linitial_node(type,l) castNode(type, linitial(l))
#define lsecond(l) lfirst(list_second_cell(l))
#define lsecond_int(l) lfirst_int(list_second_cell(l))
#define lsecond_oid(l) lfirst_oid(list_second_cell(l))
#define lsecond(l) lfirst(list_nth_cell(l, 1))
#define lsecond_int(l) lfirst_int(list_nth_cell(l, 1))
#define lsecond_oid(l) lfirst_oid(list_nth_cell(l, 1))
#define lsecond_node(type,l) castNode(type, lsecond(l))
#define lthird(l) lfirst(list_third_cell(l))
#define lthird_int(l) lfirst_int(list_third_cell(l))
#define lthird_oid(l) lfirst_oid(list_third_cell(l))
#define lthird(l) lfirst(list_nth_cell(l, 2))
#define lthird_int(l) lfirst_int(list_nth_cell(l, 2))
#define lthird_oid(l) lfirst_oid(list_nth_cell(l, 2))
#define lthird_node(type,l) castNode(type, lthird(l))
#define lfourth(l) lfirst(list_fourth_cell(l))
#define lfourth_int(l) lfirst_int(list_fourth_cell(l))
#define lfourth_oid(l) lfirst_oid(list_fourth_cell(l))
#define lfourth(l) lfirst(list_nth_cell(l, 3))
#define lfourth_int(l) lfirst_int(list_nth_cell(l, 3))
#define lfourth_oid(l) lfirst_oid(list_nth_cell(l, 3))
#define lfourth_node(type,l) castNode(type, lfourth(l))
#define llast(l) lfirst(list_tail(l))
#define llast_int(l) lfirst_int(list_tail(l))
#define llast_oid(l) lfirst_oid(list_tail(l))
#define llast(l) lfirst(list_last_cell(l))
#define llast_int(l) lfirst_int(list_last_cell(l))
#define llast_oid(l) lfirst_oid(list_last_cell(l))
#define llast_node(type,l) castNode(type, llast(l))
/*
......@@ -269,6 +268,16 @@ list_nth_cell(const List *list, int n)
return &list->elements[n];
}
/*
* Return the last cell in a non-NIL List.
*/
static inline ListCell *
list_last_cell(const List *list)
{
Assert(list != NIL);
return &list->elements[list->length - 1];
}
/*
* Return the pointer value contained in the n'th element of the
* specified list. (List elements begin at 0.)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment