[clang] Suggest using __VA_OPT__(,) instead of GNU zero variadic macro argument (#188624)
Also provide an appropriate fixit.
This commit is contained in:
parent
26b755c09b
commit
c67092066e
@ -350,6 +350,9 @@ Improvements to Clang's diagnostics
|
||||
``-Wunused-private-field`` no longer emits a warning for annotated private
|
||||
fields.
|
||||
|
||||
- Improved ``-Wgnu-zero-variadic-macro-arguments`` to suggest using
|
||||
``__VA_OPT__`` if the current language version supports it(#GH188624)
|
||||
|
||||
Improvements to Clang's time-trace
|
||||
----------------------------------
|
||||
|
||||
|
||||
@ -769,7 +769,9 @@ 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<
|
||||
|
||||
@ -137,6 +137,10 @@ void TokenLexer::destroy() {
|
||||
if (ActualArgs) ActualArgs->destroy(PP);
|
||||
}
|
||||
|
||||
static bool hasVaOptSupport(const LangOptions &LangOpts) {
|
||||
return LangOpts.C23 || LangOpts.CPlusPlus20;
|
||||
}
|
||||
|
||||
bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
|
||||
SmallVectorImpl<Token> &ResultToks, bool HasPasteOperator, MacroInfo *Macro,
|
||||
unsigned MacroArgNo, Preprocessor &PP) {
|
||||
@ -164,8 +168,10 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
|
||||
return false;
|
||||
|
||||
// Issue an extension diagnostic for the paste operator.
|
||||
if (HasPasteOperator)
|
||||
PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);
|
||||
if (HasPasteOperator) {
|
||||
PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma)
|
||||
<< hasVaOptSupport(PP.getLangOpts());
|
||||
}
|
||||
|
||||
// Remove the comma.
|
||||
ResultToks.pop_back();
|
||||
@ -523,7 +529,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);
|
||||
bool VaOptSupport = hasVaOptSupport(PP.getLangOpts());
|
||||
auto Diag = PP.Diag(ResultToks.pop_back_val().getLocation(),
|
||||
diag::ext_paste_comma)
|
||||
<< VaOptSupport;
|
||||
if (VaOptSupport) {
|
||||
Diag << FixItHint::CreateReplacement(
|
||||
SourceRange(ResultToks.back().getLocation(),
|
||||
CurTok.getLocation()),
|
||||
" __VA_OPT__(,) __VA_ARGS__");
|
||||
}
|
||||
}
|
||||
|
||||
ResultToks.append(ArgToks, ArgToks+NumToks);
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
#if ALL || ZEROARGS
|
||||
// expected-warning@+9 {{passing no argument for the '...' parameter of a variadic macro is a C23 extension}}
|
||||
// expected-note@+4 {{macro 'efoo' defined here}}
|
||||
// expected-warning@+3 {{token pasting of ',' and __VA_ARGS__ is a GNU extension}}
|
||||
// expected-warning@+3 {{token pasting of ',' and '__VA_ARGS__' is a GNU extension}}
|
||||
#endif
|
||||
|
||||
#define efoo(format, args...) foo(format , ##args)
|
||||
|
||||
13
clang/test/Lexer/gnu-zero-variadic-macro-argument-fixit.c
Normal file
13
clang/test/Lexer/gnu-zero-variadic-macro-argument-fixit.c
Normal file
@ -0,0 +1,13 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s -Wgnu-zero-variadic-macro-arguments -std=c23
|
||||
// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s -Wgnu-zero-variadic-macro-arguments -std=c23 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s -Wgnu-zero-variadic-macro-arguments -xc++ -std=c++20
|
||||
// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s -Wgnu-zero-variadic-macro-arguments -xc++ -std=c++20 2>&1 | FileCheck %s
|
||||
|
||||
void foo(const char* fmt, ...);
|
||||
// CHECK: fix-it:"{{.*}}":{[[@LINE+2]]:36-[[@LINE+2]]:51}:" __VA_OPT__(,) __VA_ARGS__"
|
||||
// expected-warning@+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);
|
||||
}
|
||||
@ -60,7 +60,7 @@ one_dot() /* empty first argument, elided ... */
|
||||
SomeComplicatedStuff((desc), ##__VA_ARGS__)
|
||||
|
||||
#ifndef VARIADIC_MACRO_ARGS_REMOVE_COMMA
|
||||
/* expected-warning@-3 {{token pasting of ',' and __VA_ARGS__ is a GNU extension}} */
|
||||
/* expected-warning@-3 {{token pasting of ',' and '__VA_ARGS__' is a GNU extension}} */
|
||||
#endif
|
||||
|
||||
NSAssert(somecond, somedesc)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user