diff --git a/include/sys/util_internal.h b/include/sys/util_internal.h
index 3b70ec3deb7..45fd7af5766 100644
--- a/include/sys/util_internal.h
+++ b/include/sys/util_internal.h
@@ -67,9 +67,23 @@
#define __DEBRACKET(...) __VA_ARGS__
/* Used by IS_EMPTY() */
-#define Z_IS_EMPTY_(...) Z_IS_EMPTY__(__VA_ARGS__)
-#define Z_IS_EMPTY__(a, ...) Z_IS_EMPTY___(_ZZ##a##ZZ0, __VA_ARGS__)
-#define Z_IS_EMPTY___(...) GET_ARG_N(3, __VA_ARGS__)
+/* reference: https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ */
+#define Z_HAS_COMMA(...) \
+ NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
+#define Z_TRIGGER_PARENTHESIS_(...) ,
+#define Z_IS_EMPTY_(...) \
+ Z_IS_EMPTY__( \
+ Z_HAS_COMMA(__VA_ARGS__), \
+ Z_HAS_COMMA(Z_TRIGGER_PARENTHESIS_ __VA_ARGS__), \
+ Z_HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
+ Z_HAS_COMMA(Z_TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)))
+#define Z_CAT5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
+#define Z_IS_EMPTY__(_0, _1, _2, _3) \
+ Z_HAS_COMMA(Z_CAT5(Z_IS_EMPTY_CASE_, _0, _1, _2, _3))
+#define Z_IS_EMPTY_CASE_0001 ,
/* Used by LIST_DROP_EMPTY() */
/* Adding ',' after each element would add empty element at the end of
diff --git a/include/sys/util_macro.h b/include/sys/util_macro.h
index 8c3791762d4..fb212919502 100644
--- a/include/sys/util_macro.h
+++ b/include/sys/util_macro.h
@@ -210,15 +210,6 @@ extern "C" {
* This macro may be used with COND_CODE_1() and COND_CODE_0() while
* processing __VA_ARGS__ to avoid processing empty arguments.
*
- * Note that this macro is intended to check macro names that evaluate
- * to replacement lists being empty or containing numbers or macro name
- * like tokens.
- *
- * @note Not all arguments are accepted by this macro and compilation will fail
- * if argument cannot be concatenated with literal constant. That will
- * happen if argument does not start with letter or number. Example
- * arguments that will fail during compilation: .arg, (arg), "arg", {arg}.
- *
* Example:
*
* #define EMPTY
@@ -234,9 +225,9 @@ extern "C" {
* In above examples, the invocations of IS_EMPTY(...) return @p true,
* @p false, and @p true; @p some_conditional_code is included.
*
- * @param a macro to check for emptiness
+ * @param ... macro to check for emptiness (may be __VA_ARGS__)
*/
-#define IS_EMPTY(a) Z_IS_EMPTY_(a, 1, 0,)
+#define IS_EMPTY(...) Z_IS_EMPTY_(__VA_ARGS__)
/**
* @brief Remove empty arguments from list.
diff --git a/tests/unit/util/test.inc b/tests/unit/util/test.inc
index b39f76f9eee..4489a29ddf7 100644
--- a/tests/unit/util/test.inc
+++ b/tests/unit/util/test.inc
@@ -354,6 +354,10 @@ static void test_IS_EMPTY(void)
"Expected to be empty");
zassert_false(IS_EMPTY(test_IS_EMPTY_NOT_EMPTY),
"Expected to be non-empty");
+ zassert_false(IS_EMPTY("string"),
+ "Expected to be non-empty");
+ zassert_false(IS_EMPTY(&test_IS_EMPTY),
+ "Expected to be non-empty");
}
static void test_LIST_DROP_EMPTY(void)