[clang] [C2y] Implement WG14 N3344 (PR #115313)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 7 05:11:42 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Aaron Ballman (AaronBallman)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/115313.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+6)
- (modified) clang/lib/Sema/SemaDecl.cpp (+15-3)
- (added) clang/test/C/C2y/n3344.c (+28)
- (modified) clang/www/c_status.html (+1-1)
``````````diff
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>
``````````
</details>
https://github.com/llvm/llvm-project/pull/115313
More information about the cfe-commits
mailing list