Skip to content

Commit

Permalink
[Clang] Update missing varargs arg extension warnings (#84520)
Browse files Browse the repository at this point in the history
This updates a few warnings that were diagnosing no arguments for a
`...` variadic macro parameter as a GNU extension when it actually is a
C++20/C23 extension now.

This fixes #84495.
  • Loading branch information
Sirraide committed Mar 20, 2024
1 parent 62ed009 commit 5231005
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 21 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ Improvements to Clang's diagnostics
operands, distinguishing it from potential typographical errors or unintended
bitwise operations. Fixes #GH77601.

- Clang now correctly diagnoses no arguments to a variadic macro parameter as a C23/C++20 extension.
Fixes #GH84495.

Improvements to Clang's time-trace
----------------------------------

Expand Down
13 changes: 10 additions & 3 deletions clang/include/clang/Basic/DiagnosticLexKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -465,9 +465,16 @@ def err_embedded_directive : Error<
def ext_embedded_directive : Extension<
"embedding a directive within macro arguments has undefined behavior">,
InGroup<DiagGroup<"embedded-directive">>;
def ext_missing_varargs_arg : Extension<
"must specify at least one argument for '...' parameter of variadic macro">,
InGroup<GNUZeroVariadicMacroArguments>;
def ext_c_missing_varargs_arg : Extension<
"passing no argument for the '...' parameter of a variadic macro is "
"a C23 extension">, InGroup<C23>;
def ext_cxx_missing_varargs_arg : Extension<
"passing no argument for the '...' parameter of a variadic macro is "
"a C++20 extension">, InGroup<CXX20>;
def warn_c17_compat_missing_varargs_arg : Warning<
"passing no argument for the '...' parameter of a variadic macro is "
"incompatible with C standards before C23">,
InGroup<CPre23Compat>, DefaultIgnore;
def warn_cxx17_compat_missing_varargs_arg : Warning<
"passing no argument for the '...' parameter of a variadic macro is "
"incompatible with C++ standards before C++20">,
Expand Down
19 changes: 14 additions & 5 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,11 +993,20 @@ MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName,
// If the macro contains the comma pasting extension, the diagnostic
// is suppressed; we know we'll get another diagnostic later.
if (!MI->hasCommaPasting()) {
// C++20 allows this construct, but standards before C++20 and all C
// standards do not allow the construct (we allow it as an extension).
Diag(Tok, getLangOpts().CPlusPlus20
? diag::warn_cxx17_compat_missing_varargs_arg
: diag::ext_missing_varargs_arg);
// C++20 [cpp.replace]p15, C23 6.10.5p12
//
// C++20 and C23 allow this construct, but standards before that
// do not (we allow it as an extension).
unsigned ID;
if (getLangOpts().CPlusPlus20)
ID = diag::warn_cxx17_compat_missing_varargs_arg;
else if (getLangOpts().CPlusPlus)
ID = diag::ext_cxx_missing_varargs_arg;
else if (getLangOpts().C23)
ID = diag::warn_c17_compat_missing_varargs_arg;
else
ID = diag::ext_c_missing_varargs_arg;
Diag(Tok, ID);
Diag(MI->getDefinitionLoc(), diag::note_macro_here)
<< MacroName.getIdentifierInfo();
}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/C/C2x/n2975.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
void func(...) { // expected-warning {{'...' as the only parameter of a function is incompatible with C standards before C23}}
// Show that va_start doesn't require the second argument in C23 mode.
va_list list;
va_start(list); // FIXME: it would be nice to issue a portability warning to C17 and earlier here.
va_start(list); // expected-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23}} expected-note@* {{macro 'va_start' defined here}}
va_end(list);

// Show that va_start doesn't expand or evaluate the second argument.
Expand All @@ -26,7 +26,7 @@ void func(...) { // expected-warning {{'...' as the only parameter of a function
__builtin_va_start(list); // expected-error {{too few arguments to function call, expected 2, have 1}}

// Verify that the return type of a call to va_start is 'void'.
_Static_assert(__builtin_types_compatible_p(__typeof__(va_start(list)), void), "");
_Static_assert(__builtin_types_compatible_p(__typeof__(va_start(list)), void), ""); // expected-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23}} expected-note@* {{macro 'va_start' defined here}}
_Static_assert(__builtin_types_compatible_p(__typeof__(__builtin_va_start(list, 0)), void), "");
}

Expand Down
2 changes: 0 additions & 2 deletions clang/test/Lexer/gnu-flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@


#if ALL || ZEROARGS
// expected-warning@+9 {{must specify at least one argument for '...' parameter of variadic macro}}
// expected-note@+4 {{macro 'efoo' defined here}}
// expected-warning@+3 {{token pasting of ',' and __VA_ARGS__ is a GNU extension}}
#endif

Expand Down
18 changes: 11 additions & 7 deletions clang/test/Preprocessor/empty_va_arg.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
// RUN: %clang_cc1 -Eonly -std=c++17 -pedantic -verify %s
// RUN: %clang_cc1 -Eonly -std=c17 -pedantic -verify -x c %s
// RUN: %clang_cc1 -Eonly -std=c++20 -pedantic -Wpre-c++20-compat -verify=compat %s
// RUN: %clang_cc1 -Eonly -std=c17 -pedantic -verify=c17,expected -x c %s
// RUN: %clang_cc1 -Eonly -std=c23 -pedantic -Wpre-c23-compat -verify=c23,expected -x c %s
// RUN: %clang_cc1 -Eonly -std=c++17 -pedantic -verify=cxx17,expected %s
// RUN: %clang_cc1 -Eonly -std=c++20 -pedantic -Wpre-c++20-compat -verify=cxx20,expected %s

#define FOO(x, ...) // expected-note {{macro 'FOO' defined here}} \
// compat-note {{macro 'FOO' defined here}}
// silent-no-diagnostics

#define FOO(x, ...) // expected-note {{macro 'FOO' defined here}}

int main() {
FOO(42) // expected-warning {{must specify at least one argument for '...' parameter of variadic macro}} \
// compat-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C++ standards before C++20}}
FOO(42) // c17-warning {{passing no argument for the '...' parameter of a variadic macro is a C23 extension}} \
// cxx17-warning {{passing no argument for the '...' parameter of a variadic macro is a C++20 extension}} \
// c23-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23}} \
// cxx20-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C++ standards before C++20}}
}

4 changes: 2 additions & 2 deletions clang/test/Preprocessor/macro_fn.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ e(x)
e()

zero_dot()
one_dot(x) /* empty ... argument: expected-warning {{must specify at least one argument for '...' parameter of variadic macro}} */
one_dot() /* empty first argument, elided ...: expected-warning {{must specify at least one argument for '...' parameter of variadic macro}} */
one_dot(x) /* empty ... argument: expected-warning {{passing no argument for the '...' parameter of a variadic macro is a C23 extension}} */
one_dot() /* empty first argument, elided ...: expected-warning {{passing no argument for the '...' parameter of a variadic macro is a C23 extension}} */


/* Crash with function-like macro test at end of directive. */
Expand Down

0 comments on commit 5231005

Please sign in to comment.