Skip to content

[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

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^^^^^^^^^^^^

Expand Down
18 changes: 15 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
28 changes: 28 additions & 0 deletions clang/test/C/C2y/n3344.c
Original file line number Diff line number Diff line change
@@ -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}}

2 changes: 1 addition & 1 deletion clang/www/c_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Loading