pw_preprocessor: PW_COMMA_ARGS improvements

- Update PW_COMMA_ARGS so that it drops the last argument if it is
  empty. This means that PW_COMMA_ARGS(1, ) expands to '1' instead of
  '1, ' as it did before. This makes PW_COMMA_ARGS more robust when
  working with nested variadic macros that may add arguments.
- Rename PW_HAS_NO_ARGS to PW_EMPTY_ARGS. This more accurately
  represents what it does: detect if there are zero arguments or one
  empty argument. It also switches to positive logic which is easier to
  reason about.

Change-Id: Ieeef9f1eda52c38239d46c50f095b2a06bb832f1
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/16221
Commit-Queue: Wyatt Hepler <hepler@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/pw_preprocessor/macro_arg_count_test.cc b/pw_preprocessor/macro_arg_count_test.cc
index 0ce8831..f450b24 100644
--- a/pw_preprocessor/macro_arg_count_test.cc
+++ b/pw_preprocessor/macro_arg_count_test.cc
@@ -22,10 +22,13 @@
 namespace pw {
 namespace {
 
+#define EMPTY_ARG
+
 TEST(HasArgs, WithoutArguments) {
   static_assert(PW_HAS_ARGS() == 0);
   static_assert(PW_HAS_ARGS(/**/) == 0);
   static_assert(PW_HAS_ARGS(/* uhm, hi */) == 0);
+  static_assert(PW_HAS_ARGS(EMPTY_ARG) == 0);
 
   // Test how the macro handles whitespace and comments.
   // clang-format off
@@ -38,9 +41,9 @@
       ) == 0);  // NOLINT
   // clang-format on
 
-  static_assert(PW_HAS_NO_ARGS() == 1);
-  static_assert(PW_HAS_NO_ARGS(/* hello */) == 1);
-  static_assert(PW_HAS_NO_ARGS(
+  static_assert(PW_EMPTY_ARGS() == 1);
+  static_assert(PW_EMPTY_ARGS(/* hello */) == 1);
+  static_assert(PW_EMPTY_ARGS(
                     // hello
                     /* goodbye */) == 1);
 }
@@ -53,11 +56,11 @@
   static_assert(PW_HAS_ARGS(PW_HAS_ARGS) == 1);
   static_assert(PW_HAS_ARGS(PW_HAS_ARGS()) == 1);
 
-  static_assert(PW_HAS_NO_ARGS(0) == 0);
-  static_assert(PW_HAS_NO_ARGS(, ) == 0);  // NOLINT
-  static_assert(PW_HAS_NO_ARGS(a, b, c) == 0);
-  static_assert(PW_HAS_NO_ARGS(PW_HAS_ARGS) == 0);
-  static_assert(PW_HAS_NO_ARGS(PW_HAS_ARGS()) == 0);
+  static_assert(PW_EMPTY_ARGS(0) == 0);
+  static_assert(PW_EMPTY_ARGS(, ) == 0);  // NOLINT
+  static_assert(PW_EMPTY_ARGS(a, b, c) == 0);
+  static_assert(PW_EMPTY_ARGS(PW_HAS_ARGS) == 0);
+  static_assert(PW_EMPTY_ARGS(PW_HAS_ARGS()) == 0);
 }
 
 constexpr int TestFunc(int arg, ...) { return arg; }
@@ -107,6 +110,16 @@
   static_assert(COUNT_ARGS_TEMPLATE(int, int, int) == 3);
 }
 
+TEST(CommaVarargs, EmptyFinalArgument) {
+  static_assert(COUNT_ARGS_TEMPLATE(EMPTY_ARG) == 0);
+  static_assert(COUNT_ARGS_TEMPLATE(int, ) == 1);
+  static_assert(COUNT_ARGS_TEMPLATE(int, EMPTY_ARG) == 1);
+  static_assert(COUNT_ARGS_TEMPLATE(int, /* EMPTY_ARG */) == 1);
+  static_assert(COUNT_ARGS_TEMPLATE(int, int, ) == 2);
+  static_assert(COUNT_ARGS_TEMPLATE(int, int, int, ) == 3);
+  static_assert(COUNT_ARGS_TEMPLATE(int, int, int, EMPTY_ARG) == 3);
+}
+
 TEST(CountArgs, Zero) {
   static_assert(PW_ARG_COUNT() == 0);
   static_assert(PW_ARG_COUNT(/**/) == 0);