This is a recent regression since commit
6359b79847 which added various assert(0)
calls (often replacing return-s).
With Ming-W64 compiler, json-c build was failing with various errors of
the sort:
> /home/jehan/dev/src/json-c/json_object.c: In function 'json_object_int_inc':
> /home/jehan/dev/src/json-c/json_object.c:841:1: error: control reaches end of non-void function [-Werror=return-type]
> 841 | }
> | ^
> In file included from /home/jehan/dev/src/json-c/json_object.c:17:
> /home/jehan/dev/src/json-c/json_object.c: In function 'json_object_get_double':
> /home/jehan/.local/share/crossroad/roads/w64/json-c/include/assert.h:76:4: error: this statement may fall through [-Werror=implicit-fallthrough=]
> 76 | (_assert(#_Expression,__FILE__,__LINE__),0))
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /home/jehan/dev/src/json-c/json_object.c:1070:7: note: in expansion of macro 'assert'
> 1070 | assert(0);
> | ^~~~~~
> /home/jehan/dev/src/json-c/json_object.c:1072:3: note: here
> 1072 | case json_type_boolean:
> | ^~~~
The problem is that Mingw-w64 does not consider assert() as a noreturn
(even assert(0)), because it has to be compatible by Microsoft
libraries. See the discussion here:
https://sourceforge.net/p/mingw-w64/bugs/306/
Instead let's create a new json_abort() function which is basically just
an abort() function with an optional message, for such cases where
abortion was non-conditional (using assert() and using the assertion
condition as a message here was clearly a misuse of the function). And
mark json_abort() as 'noreturn', as well as 'cold' for optimization
purpose (this is code we expect to never run, unless there is a bug,
that is).
Finally let's use this json_abort() instead of previous misused assert()
calls.
tags/json-c-0.14-20200419
| @@ -597,7 +597,7 @@ json_bool json_object_get_boolean(const struct json_object *jso) | |||||
| case json_object_int_type_uint64: | case json_object_int_type_uint64: | ||||
| return (jso->o.c_int.cint.c_uint64 != 0); | return (jso->o.c_int.cint.c_uint64 != 0); | ||||
| default: | default: | ||||
| assert(!"invalid cint_type"); | |||||
| json_abort("invalid cint_type"); | |||||
| } | } | ||||
| case json_type_double: | case json_type_double: | ||||
| return (jso->o.c_double != 0); | return (jso->o.c_double != 0); | ||||
| @@ -734,7 +734,7 @@ int64_t json_object_get_int64(const struct json_object *jso) | |||||
| return INT64_MAX; | return INT64_MAX; | ||||
| return (int64_t)jso->o.c_int.cint.c_uint64; | return (int64_t)jso->o.c_int.cint.c_uint64; | ||||
| default: | default: | ||||
| assert(!"invalid cint_type"); | |||||
| json_abort("invalid cint_type"); | |||||
| } | } | ||||
| case json_type_double: | case json_type_double: | ||||
| // INT64_MAX can't be exactly represented as a double | // INT64_MAX can't be exactly represented as a double | ||||
| @@ -772,7 +772,7 @@ uint64_t json_object_get_uint64(const struct json_object *jso) | |||||
| case json_object_int_type_uint64: | case json_object_int_type_uint64: | ||||
| return jso->o.c_int.cint.c_uint64; | return jso->o.c_int.cint.c_uint64; | ||||
| default: | default: | ||||
| assert(!"invalid cint_type"); | |||||
| json_abort("invalid cint_type"); | |||||
| } | } | ||||
| case json_type_double: | case json_type_double: | ||||
| // UINT64_MAX can't be exactly represented as a double | // UINT64_MAX can't be exactly represented as a double | ||||
| @@ -836,7 +836,7 @@ int json_object_int_inc(struct json_object *jso, int64_t val) { | |||||
| } | } | ||||
| return 1; | return 1; | ||||
| default: | default: | ||||
| assert(!"invalid cint_type"); | |||||
| json_abort("invalid cint_type"); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1067,7 +1067,7 @@ double json_object_get_double(const struct json_object *jso) | |||||
| case json_object_int_type_uint64: | case json_object_int_type_uint64: | ||||
| return jso->o.c_int.cint.c_uint64; | return jso->o.c_int.cint.c_uint64; | ||||
| default: | default: | ||||
| assert(!"invalid cint_type"); | |||||
| json_abort("invalid cint_type"); | |||||
| } | } | ||||
| case json_type_boolean: | case json_type_boolean: | ||||
| return jso->o.c_boolean; | return jso->o.c_boolean; | ||||
| @@ -282,3 +282,10 @@ const char *json_type_to_name(enum json_type o_type) | |||||
| return json_type_name[o_type]; | return json_type_name[o_type]; | ||||
| } | } | ||||
| void json_abort(const char *message) | |||||
| { | |||||
| if (message != NULL) | |||||
| fprintf (stderr, "json-c aborts with error: %s\n", message); | |||||
| abort(); | |||||
| } | |||||
| @@ -112,6 +112,23 @@ JSON_EXPORT int json_parse_double(const char *buf, double *retval); | |||||
| */ | */ | ||||
| JSON_EXPORT const char *json_type_to_name(enum json_type o_type); | JSON_EXPORT const char *json_type_to_name(enum json_type o_type); | ||||
| #ifndef JSON_NORETURN | |||||
| #if defined(_MSC_VER) | |||||
| #define JSON_NORETURN __declspec(noreturn) | |||||
| #else | |||||
| /* 'cold' attribute is for optimization, telling the computer this code | |||||
| * path is unlikely. | |||||
| */ | |||||
| #define JSON_NORETURN __attribute__ ((noreturn, cold)) | |||||
| #endif | |||||
| #endif | |||||
| /** | |||||
| * Abort and optionally print a message on standard error. | |||||
| * This should be used rather than assert() for unconditional abortion | |||||
| * (in particular for code paths which are never supposed to be run). | |||||
| * */ | |||||
| JSON_NORETURN JSON_EXPORT void json_abort(const char *message); | |||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| } | } | ||||
| #endif | #endif | ||||