Skip to content

[Clang] Update missing varargs arg extension warnings #84520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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