[clang] [clang] Suggest using __VA_OPT__(,) instead of GNU zero variadic macro argument (PR #188624)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 25 14:55:32 PDT 2026
https://github.com/serge-sans-paille created https://github.com/llvm/llvm-project/pull/188624
Also provide an appropriate fixit.
>From 174b065d76f254b59ffc6ae5b0080592d42c457f Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Wed, 25 Mar 2026 22:52:31 +0100
Subject: [PATCH] [clang] Suggest using __VA_OPT__(,) instead of GNU zero
variadic macro argument
Also provide an appropriate fixit.
---
clang/include/clang/Basic/DiagnosticLexKinds.td | 3 ++-
clang/lib/Lex/TokenLexer.cpp | 11 ++++++++++-
.../Lexer/gnu-zero-variadic-macro-argument-fixit.c | 9 +++++++++
3 files changed, 21 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Lexer/gnu-zero-variadic-macro-argument-fixit.c
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 5eceeced311f2..99a3109baa01c 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -769,7 +769,8 @@ def err_paste_at_start : Error<
"'##' cannot appear at start of macro expansion">;
def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">;
def ext_paste_comma : Extension<
- "token pasting of ',' and __VA_ARGS__ is a GNU extension">, InGroup<GNUZeroVariadicMacroArguments>;
+ "token pasting of ',' and __VA_ARGS__ is a GNU extension.%select{| Consider using __VA_OPT__(,) instead}0">,
+ InGroup<GNUZeroVariadicMacroArguments>;
def err_unterm_macro_invoc : Error<
"unterminated function-like macro invocation">;
def err_too_many_args_in_macro_invoc : Error<
diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp
index db4313f766812..699b3a6a6c7d8 100644
--- a/clang/lib/Lex/TokenLexer.cpp
+++ b/clang/lib/Lex/TokenLexer.cpp
@@ -523,7 +523,16 @@ void TokenLexer::ExpandFunctionArguments() {
Macro->isVariadic()) {
VaArgsPseudoPaste = true;
// Remove the paste operator, report use of the extension.
- PP.Diag(ResultToks.pop_back_val().getLocation(), diag::ext_paste_comma);
+ const bool hint = PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus20;
+ auto diag = PP.Diag(ResultToks.pop_back_val().getLocation(),
+ diag::ext_paste_comma)
+ << hint;
+ if (hint) {
+ diag << FixItHint::CreateReplacement(
+ SourceRange(ResultToks[ResultToks.size() - 1].getLocation(),
+ CurTok.getLocation()),
+ " __VA_OPT__(,) __VA_ARGS__");
+ }
}
ResultToks.append(ArgToks, ArgToks+NumToks);
diff --git a/clang/test/Lexer/gnu-zero-variadic-macro-argument-fixit.c b/clang/test/Lexer/gnu-zero-variadic-macro-argument-fixit.c
new file mode 100644
index 0000000000000..e796ed001c0be
--- /dev/null
+++ b/clang/test/Lexer/gnu-zero-variadic-macro-argument-fixit.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fdiagnostics-parseable-fixits %s -Wgnu-zero-variadic-macro-arguments -std=c23
+
+void foo(const char* fmt, ...);
+// expected-warning at +1 {{token pasting of ',' and __VA_ARGS__ is a GNU extension. Consider using __VA_OPT__(,) instead}}
+#define FOO(format, ...) foo(format, ##__VA_ARGS__)
+
+void bar(void) {
+ FOO("", 0);
+}
More information about the cfe-commits
mailing list