From 595891729ecf39eac42536e12024435f5d8ea8fe Mon Sep 17 00:00:00 2001 From: Eric Haszlakiewicz Date: Sat, 11 Jun 2016 18:18:46 +0000 Subject: [PATCH] Issue #236: Add -Wcast-qual and fix casts to retain constness. To better distinguish between entry->k and entry->v being const within linkhash, but non-const outside, add lh_entry_v() and lh_entry_k() accessors. Make lh_entry->k const. --- configure.ac | 2 +- json_object.c | 26 +++++++++++++------------- json_object.h | 12 +++++++----- json_object_iterator.c | 6 +++--- linkhash.c | 10 +++++----- linkhash.h | 36 +++++++++++++++++++++++++++++++----- tests/test4.c | 2 +- 7 files changed, 61 insertions(+), 33 deletions(-) diff --git a/configure.ac b/configure.ac index 820d30e218..18f91dc6c0 100644 --- a/configure.ac +++ b/configure.ac @@ -103,7 +103,7 @@ AS_IF([test "x$enable_Bsymbolic" = "xcheck"], AS_IF([test "x$enable_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions]) AC_SUBST(JSON_BSYMBOLIC_LDFLAGS) -AX_APPEND_COMPILE_FLAGS([-Wall -Werror -Wno-error=deprecated-declarations]) +AX_APPEND_COMPILE_FLAGS([-Wall -Werror -Wcast-qual -Wno-error=deprecated-declarations]) AX_APPEND_COMPILE_FLAGS([-Wextra -Wwrite-string -Wno-unused-parameter]) AX_APPEND_COMPILE_FLAGS([-D_GNU_SOURCE -D_REENTRANT]) diff --git a/json_object.c b/json_object.c index 93aefd5d35..24cb7abdbe 100644 --- a/json_object.c +++ b/json_object.c @@ -84,7 +84,7 @@ static void json_object_fini(void) json_object_table->count); lh_foreach(json_object_table, ent) { - struct json_object* obj = (struct json_object*)ent->v; + struct json_object* obj = (struct json_object*)lh_entry_v(ent); MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj); } } @@ -385,8 +385,8 @@ static int json_object_object_to_json_string(struct json_object* jso, static void json_object_lh_entry_free(struct lh_entry *ent) { if (!ent->k_is_constant) - free(ent->k); - json_object_put((struct json_object*)ent->v); + free(lh_entry_k(ent)); + json_object_put((struct json_object*)lh_entry_v(ent)); } static void json_object_object_delete(struct json_object* jso) @@ -435,17 +435,17 @@ void json_object_object_add_ex(struct json_object* jso, // and re-adding it, so the existing key remains valid. json_object *existing_value = NULL; struct lh_entry *existing_entry; - const unsigned long hash = lh_get_hash(jso->o.c_object, (void*)key); + const unsigned long hash = lh_get_hash(jso->o.c_object, (const void *)key); existing_entry = (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW) ? NULL : - lh_table_lookup_entry_w_hash(jso->o.c_object, (void*)key, hash); + lh_table_lookup_entry_w_hash(jso->o.c_object, (const void *)key, hash); if (!existing_entry) { - void *const k = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ? - (void*)key : strdup(key); + const void *const k = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ? + (const void *)key : strdup(key); lh_table_insert_w_hash(jso->o.c_object, k, val, hash, opts); return; } - existing_value = (json_object *)existing_entry->v; + existing_value = (json_object *)lh_entry_v(existing_entry); if (existing_value) json_object_put(existing_value); existing_entry->v = val; @@ -458,8 +458,8 @@ int json_object_object_add(struct json_object* jso, const char *key, // and re-adding it, so the existing key remains valid. json_object *existing_value = NULL; struct lh_entry *existing_entry; - const unsigned long hash = lh_get_hash(jso->o.c_object, (void*)key); - existing_entry = lh_table_lookup_entry_w_hash(jso->o.c_object, (void*)key, hash); + const unsigned long hash = lh_get_hash(jso->o.c_object, (const void *)key); + existing_entry = lh_table_lookup_entry_w_hash(jso->o.c_object, (const void *)key, hash); if (!existing_entry) { char *keydup = strdup(key); @@ -468,7 +468,7 @@ int json_object_object_add(struct json_object* jso, const char *key, return lh_table_insert_w_hash(jso->o.c_object, keydup, val, hash, 0); } - existing_value = (json_object *)existing_entry->v; + existing_value = (json_object *)lh_entry_v(existing_entry); if (existing_value) json_object_put(existing_value); existing_entry->v = val; @@ -500,7 +500,7 @@ json_bool json_object_object_get_ex(const struct json_object* jso, const char *k switch(jso->o_type) { case json_type_object: - return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value); + return lh_table_lookup_ex(jso->o.c_object, (const void *)key, (void**)value); default: if (value != NULL) *value = NULL; @@ -865,7 +865,7 @@ struct json_object* json_object_new_string_len(const char *s, int len) } dstbuf = jso->o.c_string.str.ptr; } - memcpy(dstbuf, (void *)s, len); + memcpy(dstbuf, (const void *)s, len); dstbuf[len] = '\0'; jso->o.c_string.len = len; return jso; diff --git a/json_object.h b/json_object.h index 33b0d2fbcb..4bcfcbcca1 100644 --- a/json_object.h +++ b/json_object.h @@ -455,8 +455,8 @@ extern void json_object_object_del(struct json_object* obj, const char *key); struct json_object *val __attribute__((__unused__)) = NULL; \ for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \ ({ if(entry ## key) { \ - key = (char*)entry ## key->k; \ - val = (struct json_object*)entry ## key->v; \ + key = (char*)lh_entry_k(entry ## key); \ + val = (struct json_object*)lh_entry_v(entry ## key); \ entry_next ## key = entry ## key->next; \ } ; entry ## key; }); \ entry ## key = entry_next ## key ) @@ -470,8 +470,8 @@ extern void json_object_object_del(struct json_object* obj, const char *key); struct lh_entry *entry_next ## key = NULL; \ for(entry ## key = json_object_get_object(obj)->head; \ (entry ## key ? ( \ - key = (char*)entry ## key->k, \ - val = (struct json_object*)entry ## key->v, \ + key = (char*)lh_entry_k(entry ## key), \ + val = (struct json_object*)lh_entry_v(entry ## key), \ entry_next ## key = entry ## key->next, \ entry ## key) : 0); \ entry ## key = entry_next ## key) @@ -483,7 +483,9 @@ extern void json_object_object_del(struct json_object* obj, const char *key); * @param iter the object iterator */ #define json_object_object_foreachC(obj,iter) \ - for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next) + for(iter.entry = json_object_get_object(obj)->head; \ + (iter.entry ? (iter.key = (char*)lh_entry_k(iter.entry), iter.val = (struct json_object*)lh_entry_v(iter.entry), iter.entry) : 0); \ + iter.entry = iter.entry->next) /* Array type methods */ diff --git a/json_object_iterator.c b/json_object_iterator.c index 7066649c3b..7c2a25b0c1 100644 --- a/json_object_iterator.c +++ b/json_object_iterator.c @@ -105,7 +105,7 @@ json_object_iter_next(struct json_object_iterator* iter) JASSERT(NULL != iter); JASSERT(kObjectEndIterValue != iter->opaque_); - iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next; + iter->opaque_ = ((const struct lh_entry *)iter->opaque_)->next; } @@ -118,7 +118,7 @@ json_object_iter_peek_name(const struct json_object_iterator* iter) JASSERT(NULL != iter); JASSERT(kObjectEndIterValue != iter->opaque_); - return (const char*)(((struct lh_entry *)iter->opaque_)->k); + return (const char*)(((const struct lh_entry *)iter->opaque_)->k); } @@ -131,7 +131,7 @@ json_object_iter_peek_value(const struct json_object_iterator* iter) JASSERT(NULL != iter); JASSERT(kObjectEndIterValue != iter->opaque_); - return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v); + return (struct json_object*)lh_entry_v((const struct lh_entry *)iter->opaque_); } diff --git a/linkhash.c b/linkhash.c index 1a5c1b8bfc..64074ac62a 100644 --- a/linkhash.c +++ b/linkhash.c @@ -441,7 +441,7 @@ static uint32_t hashlittle( const void *key, size_t length, uint32_t initval) */ static unsigned long lh_perllike_str_hash(const void *k) { - const char *rkey = (char*) k; + const char *rkey = (const char *)k; unsigned hashval = 1; while (*rkey) @@ -572,7 +572,7 @@ void lh_table_free(struct lh_table *t) } -int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const unsigned long h, const unsigned opts) +int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts) { unsigned long n; @@ -604,7 +604,7 @@ int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const uns return 0; } -int lh_table_insert(struct lh_table *t, void *k, const void *v) +int lh_table_insert(struct lh_table *t, const void *k, const void *v) { return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k), 0); } @@ -641,11 +641,11 @@ json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v) { struct lh_entry *e = lh_table_lookup_entry(t, k); if (e != NULL) { - if (v != NULL) *v = (void *)e->v; + if (v != NULL) *v = lh_entry_v(e); return TRUE; /* key found */ } if (v != NULL) *v = NULL; - return FALSE; /* key not found */ + return FALSE; /* key not found */ } int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) diff --git a/linkhash.h b/linkhash.h index ead4818405..8be625a7f2 100644 --- a/linkhash.h +++ b/linkhash.h @@ -78,12 +78,16 @@ typedef int (lh_equal_fn) (const void *k1, const void *k2); */ struct lh_entry { /** - * The key. + * The key. Use lh_entry_k() instead of accessing this directly. + */ + const void *k; + /** + * A flag for users of linkhash to know whether or not they + * need to free k. */ - void *k; int k_is_constant; /** - * The value. + * The value. Use lh_entry_v() instead of accessing this directly. */ const void *v; /** @@ -211,7 +215,7 @@ extern void lh_table_free(struct lh_table *t); * @return On success, 0 is returned. * On error, a negative value is returned. */ -extern int lh_table_insert(struct lh_table *t, void *k, const void *v); +extern int lh_table_insert(struct lh_table *t, const void *k, const void *v); /** @@ -226,7 +230,7 @@ extern int lh_table_insert(struct lh_table *t, void *k, const void *v); * @param h hash value of the key to insert * @param opts opts, a subset of JSON_OBJECT_ADD_* flags is supported */ -extern int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const unsigned long h, const unsigned opts); +extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts); /** @@ -335,6 +339,28 @@ static inline unsigned long lh_get_hash(const struct lh_table *t, const void *k) return t->hash_fn(k); } +/* Don't use this outside of linkhash.h: */ +#ifdef __UNCONST +#define _LH_UNCONST(a) __UNCONST(a) +#else +#define _LH_UNCONST(a) ((void *)(unsigned long)(const void *)(a)) +#endif + +/** + * Return a non-const version of lh_entry->k. + * k is const to indicate and help ensure that linkhash itself doesn't modify + * it, but callers are allowed to do what they want with it. + * See also lh_entry->k_is_constant + */ +#define lh_entry_k(entry) _LH_UNCONST((entry)->k) + +/** + * Return a non-const version of lh_entry->v. + * v is const to indicate and help ensure that linkhash itself doesn't modify + * it, but callers are allowed to do what they want with it. + */ +#define lh_entry_v(entry) _LH_UNCONST((entry)->v) + #ifdef __cplusplus } #endif diff --git a/tests/test4.c b/tests/test4.c index 23e97dac1b..628fef5668 100644 --- a/tests/test4.c +++ b/tests/test4.c @@ -28,7 +28,7 @@ int main() { const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\""; const char *expected = "\xF0\xA0\x84\xA6,\xF0\xA0\x84\xA7,\xF0\x90\x84\xA6,\xF0\x90\x84\xA7"; - struct json_object *parse_result = json_tokener_parse((char*)input); + struct json_object *parse_result = json_tokener_parse(input); const char *unjson = json_object_get_string(parse_result); printf("input: %s\n", input);