aaron.ballman created this revision. aaron.ballman added reviewers: rsmith, erichkeane, cor3ntin. aaron.ballman requested review of this revision. Herald added a project: clang.
C++20 and later allow you to pass no argument for the ... parameter in a variadic macro, whereas earlier language modes and C disallow it. We no longer diagnose in C++20 and later modes. This fixes PR51609. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D111459 Files: clang/include/clang/Basic/DiagnosticLexKinds.td clang/lib/Lex/PPMacroExpansion.cpp clang/test/Preprocessor/empty_va_arg.cpp Index: clang/test/Preprocessor/empty_va_arg.cpp =================================================================== --- /dev/null +++ clang/test/Preprocessor/empty_va_arg.cpp @@ -0,0 +1,12 @@ +// 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 + +#define FOO(x, ...) // expected-note {{macro 'FOO' defined here}} \ + // compat-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}} +} + Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -988,7 +988,11 @@ // If the macro contains the comma pasting extension, the diagnostic // is suppressed; we know we'll get another diagnostic later. if (!MI->hasCommaPasting()) { - Diag(Tok, diag::ext_missing_varargs_arg); + // 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); Diag(MI->getDefinitionLoc(), diag::note_macro_here) << MacroName.getIdentifierInfo(); } Index: clang/include/clang/Basic/DiagnosticLexKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticLexKinds.td +++ clang/include/clang/Basic/DiagnosticLexKinds.td @@ -412,6 +412,10 @@ def ext_missing_varargs_arg : Extension< "must specify at least one argument for '...' parameter of variadic macro">, InGroup<GNUZeroVariadicMacroArguments>; +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">, + InGroup<CXXPre20Compat>, DefaultIgnore; def ext_empty_fnmacro_arg : Extension< "empty macro arguments are a C99 feature">, InGroup<C99>; def warn_cxx98_compat_empty_fnmacro_arg : Warning<
Index: clang/test/Preprocessor/empty_va_arg.cpp =================================================================== --- /dev/null +++ clang/test/Preprocessor/empty_va_arg.cpp @@ -0,0 +1,12 @@ +// 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 + +#define FOO(x, ...) // expected-note {{macro 'FOO' defined here}} \ + // compat-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}} +} + Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -988,7 +988,11 @@ // If the macro contains the comma pasting extension, the diagnostic // is suppressed; we know we'll get another diagnostic later. if (!MI->hasCommaPasting()) { - Diag(Tok, diag::ext_missing_varargs_arg); + // 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); Diag(MI->getDefinitionLoc(), diag::note_macro_here) << MacroName.getIdentifierInfo(); } Index: clang/include/clang/Basic/DiagnosticLexKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticLexKinds.td +++ clang/include/clang/Basic/DiagnosticLexKinds.td @@ -412,6 +412,10 @@ def ext_missing_varargs_arg : Extension< "must specify at least one argument for '...' parameter of variadic macro">, InGroup<GNUZeroVariadicMacroArguments>; +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">, + InGroup<CXXPre20Compat>, DefaultIgnore; def ext_empty_fnmacro_arg : Extension< "empty macro arguments are a C99 feature">, InGroup<C99>; def warn_cxx98_compat_empty_fnmacro_arg : Warning<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits