-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[C2y] Implement WG14 N3344 #115313
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
[C2y] Implement WG14 N3344 #115313
Conversation
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3344.pdf This paper disallows a single `void` parameter from having qualifiers or storage class specifiers. Clang has diagnosed most of these as an error for a long time, but `register void` was previously accepted in all C language modes and is now being rejected in all C language modes.
@llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) Changeshttps://www.open-std.org/jtc1/sc22/wg14/www/docs/n3344.pdf This paper disallows a single Full diff: https://github.com/llvm/llvm-project/pull/115313.diff 4 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 061a1fed3f7d48..3e7d8e15110f9d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -280,6 +280,12 @@ C2y Feature Support
this is now a C2y extension in C. ``-Wgnu-case-range`` still applies in C++
modes.
+- Clang implemented support for `N3344 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3344.pdf>`_
+ which disallows a ``void`` parameter from having a qualifier or storage class
+ specifier. Note that ``register void`` was previously accepted in all C
+ language modes but is now rejected (all of the other qualifiers and storage
+ class specifiers were previously rejected).
+
C23 Feature Support
^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index aba6b555ff28f3..c9cd81a48fbe51 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15002,6 +15002,12 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D,
const DeclSpec &DS = D.getDeclSpec();
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+ // C2y 6.7.7.4p4: A parameter declaration shall not specify a void type,
+ // except for the special case of a single unnamed parameter of type void
+ // with no storage class specifier, no type qualifier, and no following
+ // ellipsis terminator.
+ // Clang applies the C2y rules for 'register void' in all C language modes,
+ // same as GCC, because it's questionable what that could possibly mean.
// C++03 [dcl.stc]p2 also permits 'auto'.
StorageClass SC = SC_None;
@@ -15010,10 +15016,16 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D,
// In C++11, the 'register' storage class specifier is deprecated.
// In C++17, it is not allowed, but we tolerate it as an extension.
if (getLangOpts().CPlusPlus11) {
+ Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus17
+ ? diag::ext_register_storage_class
+ : diag::warn_deprecated_register)
+ << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+ } else if (!getLangOpts().CPlusPlus &&
+ DS.getTypeSpecType() == DeclSpec::TST_void) {
Diag(DS.getStorageClassSpecLoc(),
- getLangOpts().CPlusPlus17 ? diag::ext_register_storage_class
- : diag::warn_deprecated_register)
- << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+ diag::err_invalid_storage_class_in_func_decl)
+ << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+ D.getMutableDeclSpec().ClearStorageClassSpecs();
}
} else if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
diff --git a/clang/test/C/C2y/n3344.c b/clang/test/C/C2y/n3344.c
new file mode 100644
index 00000000000000..bd3d440cb5d12a
--- /dev/null
+++ b/clang/test/C/C2y/n3344.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s
+// RUN: %clang_cc1 -verify -Wall -pedantic %s
+
+/* WG14 N3344: Yes
+ * Slay Some Earthly Demons VI
+ *
+ * A 'void' parameter cannot have any qualifiers, storage class specifiers, or
+ * be followed by an ellipsis.
+ *
+ * Note: Clang treats 'register void' as being a DR and rejects it in all
+ * language modes; there's no evidence that this will break users and it's not
+ * clear what the programmer intended if they wrote such code anyway. This
+ * matches GCC's behavior.
+ */
+
+void baz(volatile void); // expected-error {{'void' as parameter must not have type qualifiers}}
+void bar(const void); // expected-error {{'void' as parameter must not have type qualifiers}}
+void foo(register void); // expected-error {{invalid storage class specifier in function declarator}}
+void quux(static void); // expected-error {{invalid storage class specifier in function declarator}}
+void quobble(auto void); // expected-error {{invalid storage class specifier in function declarator}}
+void quubble(extern void); // expected-error {{invalid storage class specifier in function declarator}}
+// FIXME: it's odd that these aren't diagnosed as storage class specifiers.
+#if __STDC_VERSION__ >= 202311L
+void quibble(constexpr void); // expected-error {{function parameter cannot be constexpr}}
+#endif
+void quabble(_Thread_local void); // expected-error {{'_Thread_local' is only allowed on variable declarations}}
+void bing(void, ...); // expected-error {{'void' must be the first and only parameter if specified}}
+
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 8b677095cee182..e66424290e6d50 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -201,7 +201,7 @@ <h2 id="c2y">C2y implementation status</h2>
<tr>
<td>Slay Some Earthly Demons VI</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3344.pdf">N3344</a></td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 20</td>
</tr>
<tr>
<td>Slay Some Earthly Demons VII</td>
|
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.
Paper doesn't say, but presumably based on this patch, 'alternative #1' is what was accepted?
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/144/builds/11070 Here is the relevant piece of the build log for the reference
|
This change broke building Wine, which bundles the lcms2 library. The case there, which broke, seems to be somewhat different than what the paper talks about though. The paper talks about rejecting I don't see the See https://github.com/mm2/Little-CMS/blob/lcms2.16/include/lcms2.h#L1311-L1317 for the full context of the breaking case (plus a dozen of more cases scattered around in the definition of static functions). |
That seems like an accidental result of how this was implemented. I’m surprised we didn’t have |
Thank you for letting me know I broke this -- that was not intentional, and I'll get on a fix or revert this morning. |
This should be addressed now with 0daca80, sorry for the trouble! |
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3344.pdf This paper disallows a single `void` parameter from having qualifiers or storage class specifiers. Clang has diagnosed most of these as an error for a long time, but `register void` was previously accepted in all C language modes and is now being rejected in all C language modes.
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3344.pdf
This paper disallows a single
void
parameter from having qualifiers or storage class specifiers. Clang has diagnosed most of these as an error for a long time, butregister void
was previously accepted in all C language modes and is now being rejected in all C language modes.