aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/private/helpers.c2
-rw-r--r--src/nvim/eval.c11
-rw-r--r--src/nvim/eval/encode.c4
-rw-r--r--src/nvim/eval/typval_encode.c.h50
4 files changed, 40 insertions, 27 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index d3564b4ede..701a1cbf2b 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -369,7 +369,7 @@ void set_option_to(void *to, int type, String name, Object value, Error *err)
#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
kv_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 })))
-#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \
+#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
kv_push(edata->stack, \
DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 })))
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index ac00d04630..e31e3118fa 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -19127,11 +19127,14 @@ static inline void _nothing_conv_func_end(typval_T *const tv)
tv->v_lock = VAR_UNLOCKED; \
} while (0)
-#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \
+#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
do { \
- dict_unref(tv->vval.v_dict); \
- tv->vval.v_dict = NULL; \
- tv->v_lock = VAR_UNLOCKED; \
+ assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \
+ dict_unref((dict_T *)dict); \
+ *((dict_T **)&dict) = NULL; \
+ if (tv != NULL) { \
+ ((typval_T *)tv)->v_lock = VAR_UNLOCKED; \
+ } \
} while (0)
static inline int _nothing_conv_list_start(typval_T *const tv)
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index e3fd857529..071fbc3923 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -369,7 +369,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
ga_append(gap, '[')
-#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \
+#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
ga_concat(gap, "{}")
#define TYPVAL_ENCODE_CONV_NIL(tv) \
@@ -933,7 +933,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
msgpack_pack_array(packer, (size_t)(len))
-#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \
+#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
msgpack_pack_map(packer, 0)
#define TYPVAL_ENCODE_CONV_NIL(tv) \
diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h
index 5795d339f0..668bdfb26a 100644
--- a/src/nvim/eval/typval_encode.c.h
+++ b/src/nvim/eval/typval_encode.c.h
@@ -117,8 +117,10 @@
/// @def TYPVAL_ENCODE_CONV_EMPTY_DICT
/// @brief Macros used to convert an empty dictionary
///
-/// @param tv Pointer to typval where value is stored. May not be NULL. May
+/// @param tv Pointer to typval where value is stored. May be NULL. May
/// point to a special dictionary.
+/// @param dict Converted dictionary, lvalue or #TYPVAL_ENCODE_NODICT_VAR
+/// (for dictionaries represented as special lists).
/// @def TYPVAL_ENCODE_CONV_LIST_START
/// @brief Macros used before starting to convert non-empty list
@@ -142,7 +144,7 @@
///
/// @param tv Pointer to typval where dictionary is stored. May be NULL. May
/// point to a special dictionary.
-/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR
+/// @param dict Converted dictionary, lvalue or #TYPVAL_ENCODE_NODICT_VAR
/// (for dictionaries represented as special lists).
/// @param len Dictionary length. Is an expression which evaluates to an
/// integer.
@@ -158,7 +160,7 @@
///
/// @param tv Pointer to typval where dictionary is stored. May be NULL. May
/// point to a special dictionary.
-/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR
+/// @param dict Converted dictionary, lvalue or #TYPVAL_ENCODE_NODICT_VAR
/// (for dictionaries represented as special lists).
/// @def TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
@@ -166,7 +168,7 @@
///
/// @param tv Pointer to typval where dictionary is stored. May be NULL. May
/// point to a special dictionary.
-/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR
+/// @param dict Converted dictionary, lvalue or #TYPVAL_ENCODE_NODICT_VAR
/// (for dictionaries represented as special lists).
/// @def TYPVAL_ENCODE_CONV_DICT_END
@@ -174,7 +176,7 @@
///
/// @param tv Pointer to typval where dictionary is stored. May be NULL. May
/// point to a special dictionary.
-/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR
+/// @param dict Converted dictionary, lvalue or #TYPVAL_ENCODE_NODICT_VAR
/// (for dictionaries represented as special lists).
/// @def TYPVAL_ENCODE_CONV_RECURSE
@@ -224,6 +226,10 @@
#include "nvim/func_attr.h"
#include "nvim/eval/typval_encode.h"
+/// Dummy variable used because some macros need lvalue
+///
+/// Must not be written to, if needed one must check that address of the
+/// macros argument is (not) equal to `&TYPVAL_ENCODE_NODICT_VAR`.
const dict_T *const TYPVAL_ENCODE_NODICT_VAR = NULL;
static inline int _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(
@@ -367,7 +373,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
case VAR_DICT: {
if (tv->vval.v_dict == NULL
|| tv->vval.v_dict->dv_hashtab.ht_used == 0) {
- TYPVAL_ENCODE_CONV_EMPTY_DICT(tv);
+ TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, tv->vval.v_dict);
break;
}
const dictitem_T *type_di;
@@ -490,7 +496,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
}
list_T *const val_list = val_di->di_tv.vval.v_list;
if (val_list == NULL || val_list->lv_len == 0) {
- TYPVAL_ENCODE_CONV_EMPTY_DICT(tv);
+ TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, TYPVAL_ENCODE_NODICT_VAR);
break;
}
for (const listitem_T *li = val_list->lv_first; li != NULL;
@@ -708,20 +714,24 @@ typval_encode_stop_converting_one_item:
continue;
}
}
- TYPVAL_ENCODE_CONV_DICT_START(NULL, pt->pt_dict,
- dict->dv_hashtab.ht_used);
- _mp_push(mpstack, ((MPConvStackVal) {
- .type = kMPConvDict,
- .tv = NULL,
- .data = {
- .d = {
- .dict = dict,
- .dictp = &pt->pt_dict,
- .hi = dict->dv_hashtab.ht_array,
- .todo = dict->dv_hashtab.ht_used,
+ if (dict->dv_hashtab.ht_used == 0) {
+ TYPVAL_ENCODE_CONV_EMPTY_DICT(NULL, pt->pt_dict);
+ } else {
+ TYPVAL_ENCODE_CONV_DICT_START(NULL, pt->pt_dict,
+ dict->dv_hashtab.ht_used);
+ _mp_push(mpstack, ((MPConvStackVal) {
+ .type = kMPConvDict,
+ .tv = NULL,
+ .data = {
+ .d = {
+ .dict = dict,
+ .dictp = &pt->pt_dict,
+ .hi = dict->dv_hashtab.ht_array,
+ .todo = dict->dv_hashtab.ht_used,
+ },
},
- },
- }));
+ }));
+ }
} else {
TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1);
}