-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Implement P3176R1: The Oxford variadic comma #117524
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
Conversation
Emit a warning when a variadic parameter in a parameter-declaration-clause is not preceded by a comma for C++26.
@llvm/pr-subscribers-clang Author: None (antangelo) ChangesEmit a deprecation warning when a variadic parameter in a parameter-declaration-clause is not preceded by a comma for C++26. Full diff: https://github.com/llvm/llvm-project/pull/117524.diff 7 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8bd06fadfdc984..b8d5c4201aeaef 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -227,6 +227,8 @@ C++2c Feature Support
- Added the ``__builtin_is_within_lifetime`` builtin, which supports
`P2641R4 Checking if a union alternative is active <https://wg21.link/p2641r4>`_
+- Implemented `P3176R1 The Oxford variadic comma <https://wg21.link/P3176R1>`_
+
C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
- Removed the restriction to literal types in constexpr functions in C++23 mode.
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index df9bf94b5d0398..7ad8ac0e7a2e46 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -211,6 +211,7 @@ def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
[CXX11CompatDeprecatedWritableStr]>;
def DeprecatedPragma : DiagGroup<"deprecated-pragma">;
def DeprecatedType : DiagGroup<"deprecated-type">;
+def DeprecatedMissingCommaVariadicParam : DiagGroup<"deprecated-missing-comma-variadic-parameter">;
// FIXME: Why is DeprecatedImplementations not in this group?
def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion,
DeprecatedArrayCompare,
@@ -235,7 +236,8 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion,
DeprecatedType,
DeprecatedVolatile,
DeprecatedWritableStr,
- DeprecatedRedundantConstexprStaticDef
+ DeprecatedRedundantConstexprStaticDef,
+ DeprecatedMissingCommaVariadicParam
]>,
DiagCategory<"Deprecations">;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 77bf08453dea51..7c3961059d1d0d 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -413,6 +413,9 @@ def err_function_scope_depth_exceeded : Error<
"function scope depth exceeded maximum of %0">, DefaultFatal;
def err_missing_comma_before_ellipsis : Error<
"C requires a comma prior to the ellipsis in a variadic function type">;
+def warn_deprecated_missing_comma_before_ellipsis : Warning<
+ "variadic parameters that are not preceded by a comma are deprecated">,
+ InGroup<DeprecatedMissingCommaVariadicParam>;
def err_unexpected_typedef_ident : Error<
"unexpected type name %0: expected identifier">;
def warn_cxx98_compat_decltype : Warning<
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index aa5c2d28d429ac..d28a74662aefe0 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -8119,6 +8119,14 @@ void Parser::ParseParameterDeclarationClause(
}
if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
+ if (getLangOpts().CPlusPlus26) {
+ // C++26 [dcl.dcl.fct]p3:
+ // A parameter-declaration-clause of the form
+ // parameter-list '...' is deprecated
+ Diag(EllipsisLoc, diag::warn_deprecated_missing_comma_before_ellipsis)
+ << FixItHint::CreateInsertion(EllipsisLoc, ", ");
+ }
+
if (!getLangOpts().CPlusPlus) {
// We have ellipsis without a preceding ',', which is ill-formed
// in C. Complain and provide the fix.
diff --git a/clang/test/CXX/drs/cwg722.cpp b/clang/test/CXX/drs/cwg722.cpp
index e90d9af360d9d0..6e7d4569c55381 100644
--- a/clang/test/CXX/drs/cwg722.cpp
+++ b/clang/test/CXX/drs/cwg722.cpp
@@ -14,7 +14,7 @@ namespace std {
using nullptr_t = decltype(nullptr);
}
-void f(std::nullptr_t...);
+void f(std::nullptr_t, ...);
std::nullptr_t g();
void h() {
std::nullptr_t np;
diff --git a/clang/test/Parser/cxx2c-oxford-variadic-comma.cpp b/clang/test/Parser/cxx2c-oxford-variadic-comma.cpp
new file mode 100644
index 00000000000000..dc78dcbb6b074f
--- /dev/null
+++ b/clang/test/Parser/cxx2c-oxford-variadic-comma.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify %s
+
+void a(...);
+
+void b(auto...);
+void c(auto, ...);
+
+void d(auto......); // expected-warning {{variadic parameters that are not preceded by a comma are deprecated}} \
+ // expected-warning {{'...' in this location creates a C-style varargs function}} \
+ // expected-note {{preceding '...' declares a function parameter pack}} \
+ // expected-note {{insert ',' before '...' to silence this warning}}
+void e(auto..., ...);
+
+void f(auto x...); // expected-warning {{variadic parameters that are not preceded by a comma are deprecated}}
+void g(auto x, ...);
+
+void h(auto... x...); // expected-warning {{variadic parameters that are not preceded by a comma are deprecated}} \
+ // expected-warning {{'...' in this location creates a C-style varargs function}} \
+ // expected-note {{preceding '...' declares a function parameter pack}} \
+ // expected-note {{insert ',' before '...' to silence this warning}}
+void i(auto... x, ...);
+
+template<class ...T>
+void j(T... t...); // expected-warning {{variadic parameters that are not preceded by a comma are deprecated}} \
+ // expected-warning {{'...' in this location creates a C-style varargs function}} \
+ // expected-note {{preceding '...' declares a function parameter pack}} \
+ // expected-note {{insert ',' before '...' to silence this warning}}
+template<class ...T>
+void k(T... t, ...);
+
+void l(int...); // expected-warning {{variadic parameters that are not preceded by a comma are deprecated}}
+void m(int, ...);
+
+void n(int x...); // expected-warning {{variadic parameters that are not preceded by a comma are deprecated}}
+void o(int x, ...);
+
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index da01cf6ceab59b..fdb9807b1168c7 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -249,7 +249,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>The Oxford variadic comma</td>
<td><a href="https://wg21.link/P3176R1">P3176R1</a></td>
- <td class="none" align="center">No</td>
+ <td class="unreleased" align="center">Clang 20</td>
</tr>
</table>
</details>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I managed to think of a few more test cases, but other than that, this looks fine imo.
Diag(EllipsisLoc, diag::warn_deprecated_missing_comma_before_ellipsis) | ||
<< FixItHint::CreateInsertion(EllipsisLoc, ", "); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
below: else if (!getLangOpts().CPlusPlus) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had intended to fallthrough to those if blocks so that the else if (ParmDeclarator.getEllipsisLoc().isValid() || Actions.containsUnexpandedParameterPacks(ParmDeclarator))
block would be evaluated to also emit the parameter pack diagnostics. Do you think those should be omitted in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, nah, lets leave it like that
@@ -413,6 +413,9 @@ def err_function_scope_depth_exceeded : Error< | |||
"function scope depth exceeded maximum of %0">, DefaultFatal; | |||
def err_missing_comma_before_ellipsis : Error< | |||
"C requires a comma prior to the ellipsis in a variadic function type">; | |||
def warn_deprecated_missing_comma_before_ellipsis : Warning< | |||
"variadic parameters that are not preceded by a comma are deprecated">, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe "declaration of a variadic function without a comma before '...' is deprecated"
("variadic parameter" is not defined and somewhat confusing)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the diagnostic to use your suggested wording.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks
Diag(EllipsisLoc, diag::warn_deprecated_missing_comma_before_ellipsis) | ||
<< FixItHint::CreateInsertion(EllipsisLoc, ", "); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, nah, lets leave it like that
// expected-note {{insert ',' before '...' to silence this warning}} | ||
|
||
template<class T> | ||
void r(T...) {} // expected-warning {{declaration of a variadic function without a comma before '...' is deprecated}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other test cases:
// Testing that a type specifier is also diagnosed
auto a = (void (*)(int...))nullptr;
// Testing that a lambda parameter list is also diagnosed
(void)[](int...){};
// Testing that a block parameter list is also diagnosed
(void)^(int...){};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I've added these test cases
@antangelo Thanks! Feel free to merge |
Emit a deprecation warning when a variadic parameter in a parameter-declaration-clause is not preceded by a comma for C++26.