preprocessor: Enable __VA_OPT__ for C2x

C2x supports __VA_OPT__, so adjust libcpp not to pedwarn for uses of
it (or of not passing any variable arguments to a variable-arguments
macro) in standard C2x mode.

I didn't try to duplicate existing tests for the details of the
feature, just verified -pedantic-errors handling is as expected.  And
there's a reasonable argument (bug 98859) that __VA_OPT__ shouldn't be
diagnosed in older standard modes at all (as opposed to not passing
any variable arguments to a variable-arguments macro, for which older
versions of the C standard require a diagnostic as a constraint
violation); that argument applies to C as much as to C++, but I
haven't made any changes in that regard.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

libcpp/
	* init.cc (lang_defaults): Enable va_opt for STDC2X.
	* lex.cc (maybe_va_opt_error): Adjust diagnostic message for C.
	* macro.cc (_cpp_arguments_ok): Update comment.

gcc/testsuite/
	* gcc.dg/cpp/c11-vararg-1.c, gcc.dg/cpp/c2x-va-opt-1.c: New tests.
This commit is contained in:
Joseph Myers 2022-12-07 19:18:06 +00:00
parent eb9491baf5
commit ce53cf7b61
5 changed files with 30 additions and 4 deletions

View file

@ -0,0 +1,9 @@
/* Test error in C11 for no arguments passed for variable arguments to a
macro. */
/* { dg-do preprocess } */
/* { dg-options "-std=c11 -pedantic-errors" } */
#define M(X, ...) X
M (x); /* { dg-error "requires at least one argument" } */
M (x, y);

View file

@ -0,0 +1,11 @@
/* Test __VA_OPT__ and no "..." arguments in a call to a variable-arguments
macro accepted for C2X. */
/* { dg-do preprocess } */
/* { dg-options "-std=c2x -pedantic-errors" } */
#define CALL(F, ...) F (7 __VA_OPT__(,) __VA_ARGS__)
#define M(X, ...) X
CALL (a);
CALL (b, 1);
M (x);

View file

@ -114,7 +114,7 @@ static const struct lang_flags lang_defaults[] =
/* STDC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC17 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC2X */ { 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
/* STDC2X */ { 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1 },
/* GNUCXX */ { 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
/* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1 },
/* GNUCXX11 */ { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1 },

View file

@ -2135,8 +2135,14 @@ maybe_va_opt_error (cpp_reader *pfile)
/* __VA_OPT__ should not be accepted at all, but allow it in
system headers. */
if (!_cpp_in_system_header (pfile))
cpp_error (pfile, CPP_DL_PEDWARN,
"__VA_OPT__ is not available until C++20");
{
if (CPP_OPTION (pfile, cplusplus))
cpp_error (pfile, CPP_DL_PEDWARN,
"__VA_OPT__ is not available until C++20");
else
cpp_error (pfile, CPP_DL_PEDWARN,
"__VA_OPT__ is not available until C2X");
}
}
else if (!pfile->state.va_args_ok)
{

View file

@ -1093,7 +1093,7 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node
if (argc < macro->paramc)
{
/* In C++20 (here the va_opt flag is used), and also as a GNU
/* In C++20 and C2X (here the va_opt flag is used), and also as a GNU
extension, variadic arguments are allowed to not appear in
the invocation at all.
e.g. #define debug(format, args...) something