Fix warnings: eval.c: item_compare(): Garbage value: MI.

Problem    : Result of operation is garbage or undefined @ 13565.
Diagnostic : Multithreading issue.
Rationale  : Problem occurs only if global (static) variable
             `item_compare_keep_zero` changes after being used by
             `do_sort_uniq` but before being used by `item_compare` or
             `item_compare2`.
Resolution : This is not an intra-function problem, as other MI's
             before, but rather an inter-function one. Thus, it can't be
             solved by using local copy of global. Therefore, we are
             forced to do a bit refactoring. We can't simply add a bool
             param to item_compare/item_compare2, as they couldn't be
             passed to qsort() that way. So, item_compare/item_compare2
             are added a bool param and curried versions of them are
             added and used in their place.
This commit is contained in:
Eliseo Martínez
2014-11-17 09:31:54 +01:00
parent be90cdf4f9
commit ece19651c6

View File

@@ -13545,13 +13545,12 @@ static bool item_compare_numeric;
static char_u *item_compare_func;
static dict_T *item_compare_selfdict;
static int item_compare_func_err;
static bool item_compare_keep_zero;
#define ITEM_COMPARE_FAIL 999
/*
* Compare functions for f_sort() and f_uniq() below.
*/
static int item_compare(const void *s1, const void *s2)
static int item_compare(const void *s1, const void *s2, bool keep_zero)
{
sortItem_T *si1, *si2;
char_u *p1, *p2;
@@ -13604,7 +13603,7 @@ static int item_compare(const void *s1, const void *s2)
// When the result would be zero, compare the item indexes. Makes the
// sort stable.
if (res == 0 && !item_compare_keep_zero) {
if (res == 0 && !keep_zero) {
res = si1->idx > si2->idx ? 1 : -1;
}
@@ -13613,7 +13612,17 @@ static int item_compare(const void *s1, const void *s2)
return res;
}
static int item_compare2(const void *s1, const void *s2)
static int item_compare_keeping_zero(const void *s1, const void *s2)
{
return item_compare(s1, s2, true);
}
static int item_compare_not_keeping_zero(const void *s1, const void *s2)
{
return item_compare(s1, s2, false);
}
static int item_compare2(const void *s1, const void *s2, bool keep_zero)
{
sortItem_T *si1, *si2;
int res;
@@ -13650,13 +13659,23 @@ static int item_compare2(const void *s1, const void *s2)
// When the result would be zero, compare the pointers themselves. Makes
// the sort stable.
if (res == 0 && !item_compare_keep_zero) {
if (res == 0 && !keep_zero) {
res = si1->idx > si2->idx ? 1 : -1;
}
return res;
}
static int item_compare2_keeping_zero(const void *s1, const void *s2)
{
return item_compare2(s1, s2, true);
}
static int item_compare2_not_keeping_zero(const void *s1, const void *s2)
{
return item_compare2(s1, s2, false);
}
/*
* "sort({list})" function
*/
@@ -13737,15 +13756,16 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
}
item_compare_func_err = FALSE;
item_compare_keep_zero = false;
// Test the compare function.
if (item_compare_func != NULL
&& item_compare2(&ptrs[0], &ptrs[1]) == ITEM_COMPARE_FAIL) {
&& item_compare2_not_keeping_zero(&ptrs[0], &ptrs[1])
== ITEM_COMPARE_FAIL) {
EMSG(_("E702: Sort compare function failed"));
} else {
// Sort the array with item pointers.
qsort(ptrs, (size_t)len, sizeof (sortItem_T),
item_compare_func == NULL ? item_compare : item_compare2);
item_compare_func == NULL ? item_compare_not_keeping_zero :
item_compare2_not_keeping_zero);
if (!item_compare_func_err) {
// Clear the list and append the items in the sorted order.
@@ -13764,8 +13784,8 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
// f_uniq(): ptrs will be a stack of items to remove.
item_compare_func_err = FALSE;
item_compare_keep_zero = true;
item_compare_func_ptr = item_compare_func ? item_compare2 : item_compare;
item_compare_func_ptr = item_compare_func ? item_compare2_keeping_zero :
item_compare_keeping_zero;
for (li = l->lv_first; li != NULL && li->li_next != NULL; li = li->li_next) {
if (item_compare_func_ptr(&li, &li->li_next) == 0) {