mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 23:08:16 +00:00
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:
@@ -13545,13 +13545,12 @@ static bool item_compare_numeric;
|
|||||||
static char_u *item_compare_func;
|
static char_u *item_compare_func;
|
||||||
static dict_T *item_compare_selfdict;
|
static dict_T *item_compare_selfdict;
|
||||||
static int item_compare_func_err;
|
static int item_compare_func_err;
|
||||||
static bool item_compare_keep_zero;
|
|
||||||
#define ITEM_COMPARE_FAIL 999
|
#define ITEM_COMPARE_FAIL 999
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare functions for f_sort() and f_uniq() below.
|
* 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;
|
sortItem_T *si1, *si2;
|
||||||
char_u *p1, *p2;
|
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
|
// When the result would be zero, compare the item indexes. Makes the
|
||||||
// sort stable.
|
// sort stable.
|
||||||
if (res == 0 && !item_compare_keep_zero) {
|
if (res == 0 && !keep_zero) {
|
||||||
res = si1->idx > si2->idx ? 1 : -1;
|
res = si1->idx > si2->idx ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13613,7 +13612,17 @@ static int item_compare(const void *s1, const void *s2)
|
|||||||
return res;
|
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;
|
sortItem_T *si1, *si2;
|
||||||
int res;
|
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
|
// When the result would be zero, compare the pointers themselves. Makes
|
||||||
// the sort stable.
|
// the sort stable.
|
||||||
if (res == 0 && !item_compare_keep_zero) {
|
if (res == 0 && !keep_zero) {
|
||||||
res = si1->idx > si2->idx ? 1 : -1;
|
res = si1->idx > si2->idx ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
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
|
* "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_func_err = FALSE;
|
||||||
item_compare_keep_zero = false;
|
|
||||||
// Test the compare function.
|
// Test the compare function.
|
||||||
if (item_compare_func != NULL
|
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"));
|
EMSG(_("E702: Sort compare function failed"));
|
||||||
} else {
|
} else {
|
||||||
// Sort the array with item pointers.
|
// Sort the array with item pointers.
|
||||||
qsort(ptrs, (size_t)len, sizeof (sortItem_T),
|
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) {
|
if (!item_compare_func_err) {
|
||||||
// Clear the list and append the items in the sorted order.
|
// 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.
|
// f_uniq(): ptrs will be a stack of items to remove.
|
||||||
item_compare_func_err = FALSE;
|
item_compare_func_err = FALSE;
|
||||||
item_compare_keep_zero = true;
|
item_compare_func_ptr = item_compare_func ? item_compare2_keeping_zero :
|
||||||
item_compare_func_ptr = item_compare_func ? item_compare2 : item_compare;
|
item_compare_keeping_zero;
|
||||||
|
|
||||||
for (li = l->lv_first; li != NULL && li->li_next != NULL; li = li->li_next) {
|
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) {
|
if (item_compare_func_ptr(&li, &li->li_next) == 0) {
|
||||||
|
Reference in New Issue
Block a user