summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-08-23 10:48:56 +0200
committerLuca Boccassi <luca.boccassi@gmail.com>2021-08-23 16:07:28 +0100
commit3e4ca3940d22f0d5f03a88fe44a6e445fca87948 (patch)
treede4d79c9743485de9df4871af78149bf274e6ffd
parentf95d1ef5fafd96c65a9da57fa2bcdd503fce694c (diff)
downloadsystemd-3e4ca3940d22f0d5f03a88fe44a6e445fca87948.tar.gz
json: rework JSON_BUILD_XYZ() macros to use compound literals instead of compound statements
Compound statements is this stuff: ({ … }) Compound literals is this stuff: (type) { … } We use compound statements a lot in macro definitions: they have one drawback though: they define a code block of their own, hence if macro invocations are nested within them that use compound literals their lifetime is limited to the code block, which might be unexpected. Thankfully, we can rework things from compound statements to compund literals in the case of json.h: they don't open a new codeblack, and hence do not suffer by the problem explained above. The interesting thing about compound statements is that they also work for simple types, not just for structs/unions/arrays. We can use this here for a typechecked implicit conversion: we want to superficially typecheck arguments to the json_build() varargs function, and we do that by assigning the specified arguments to our compound literals, which does the minimal amount of typechecks and ensures that types are propagated on correctly. We need one special tweak for this: sd_id128_t is not a simple type but a union. Using compound literals for initialzing that would mean specifiying the components of the union, not a complete sd_id128_t. Our hack around that: instead of passing the object directly via the stack we now take a pointer (and thus a simple type) instead. Nice side-effect of all this: compound literals is C99, while compound statements are a GCC extension, hence we move closer to standard C. Fixes: #20501 Replaces: #20512
-rw-r--r--src/shared/json.c6
-rw-r--r--src/shared/json.h30
2 files changed, 18 insertions, 18 deletions
diff --git a/src/shared/json.c b/src/shared/json.c
index a1608d6aa4..0282992960 100644
--- a/src/shared/json.c
+++ b/src/shared/json.c
@@ -3648,17 +3648,17 @@ int json_buildv(JsonVariant **ret, va_list ap) {
}
case _JSON_BUILD_ID128: {
- sd_id128_t id;
+ const sd_id128_t *id;
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
r = -EINVAL;
goto finish;
}
- id = va_arg(ap, sd_id128_t);
+ assert_se(id = va_arg(ap, sd_id128_t*));
if (current->n_suppress == 0) {
- r = json_variant_new_id128(&add, id);
+ r = json_variant_new_id128(&add, *id);
if (r < 0)
goto finish;
}
diff --git a/src/shared/json.h b/src/shared/json.h
index c679f8f1ab..3912fbd9cc 100644
--- a/src/shared/json.h
+++ b/src/shared/json.h
@@ -239,26 +239,26 @@ enum {
_JSON_BUILD_MAX,
};
-#define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, ({ const char *_x = s; _x; })
-#define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, ({ intmax_t _x = i; _x; })
-#define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, ({ uintmax_t _x = u; _x; })
-#define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, ({ long double _x = d; _x; })
-#define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, ({ bool _x = b; _x; })
+#define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, (const char*) { s }
+#define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, (intmax_t) { i }
+#define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, (uintmax_t) { u }
+#define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, (long double) { d }
+#define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, (bool) { b }
#define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END
#define JSON_BUILD_EMPTY_ARRAY _JSON_BUILD_ARRAY_BEGIN, _JSON_BUILD_ARRAY_END
#define JSON_BUILD_OBJECT(...) _JSON_BUILD_OBJECT_BEGIN, __VA_ARGS__, _JSON_BUILD_OBJECT_END
#define JSON_BUILD_EMPTY_OBJECT _JSON_BUILD_OBJECT_BEGIN, _JSON_BUILD_OBJECT_END
-#define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, ({ const char *_x = n; _x; }), __VA_ARGS__
-#define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, ({ bool _x = c; _x; }), ({ const char *_x = n; _x; }), __VA_ARGS__
+#define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, (const char*) { n }, __VA_ARGS__
+#define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, (bool) { c }, (const char*) { n }, __VA_ARGS__
#define JSON_BUILD_NULL _JSON_BUILD_NULL
-#define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, ({ JsonVariant *_x = v; _x; })
-#define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, ({ JsonVariant **_x = v; _x; }), ({ size_t _y = n; _y; })
-#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, ({ const char *_x = l; _x; })
-#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, ({ char **_x = l; _x; })
-#define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, ({ const void *_x = p; _x; }), ({ size_t _y = n; _y; })
-#define JSON_BUILD_HEX(p, n) _JSON_BUILD_HEX, ({ const void *_x = p; _x; }), ({ size_t _y = n; _y; })
-#define JSON_BUILD_ID128(id) _JSON_BUILD_ID128, ({ sd_id128_t _x = id; _x; })
-#define JSON_BUILD_BYTE_ARRAY(v, n) _JSON_BUILD_BYTE_ARRAY, ({ const void *_x = v; _x; }), ({ size_t _y = n; _y; })
+#define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, (JsonVariant*) { v }
+#define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, (JsonVariant **) { v }, (size_t) { n }
+#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, (const char*) { l }
+#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, (char**) { l }
+#define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, (const void*) { p }, (size_t) { n }
+#define JSON_BUILD_HEX(p, n) _JSON_BUILD_HEX, (const void*) { p }, (size_t) { n }
+#define JSON_BUILD_ID128(id) _JSON_BUILD_ID128, (const sd_id128_t*) { &(id) }
+#define JSON_BUILD_BYTE_ARRAY(v, n) _JSON_BUILD_BYTE_ARRAY, (const void*) { v }, (size_t) { n }
int json_build(JsonVariant **ret, ...);
int json_buildv(JsonVariant **ret, va_list ap);