-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[C2y] Implement WG14 N3409 #130299
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 N3409 #130299
Conversation
This paper removes UB around use of void expressions. Previously, code like this had undefined behavior: void foo(void) { (void)(void)1; extern void x; x; } and this is now well-defined in C2y. Functionally, this now means that it is valid to use `void` as a `_Generic` association.
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesThis paper removes UB around use of void expressions. Previously, code like this had undefined behavior:
and this is now well-defined in C2y. Functionally, this now means that it is valid to use Full diff: https://github.com/llvm/llvm-project/pull/130299.diff 4 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 577b3f2130df7..df8d2eed1ec0c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -114,6 +114,10 @@ C2y Feature Support
- Implemented N3411 which allows a source file to not end with a newline
character. This is still reported as a conforming extension in earlier
language modes.
+- Implement `WG14 N3409 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3409.pdf>`_
+ which removes UB around use of ``void`` expressions. In practice, this means
+ that ``_Generic`` selection associations may now have ``void`` type, but it
+ also removes UB with code like ``(void)(void)1;``.
C23 Feature Support
^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1b46920e09619..d6e5005003322 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10425,8 +10425,13 @@ def warn_type_safety_null_pointer_required : Warning<
"specified %0 type tag requires a null pointer">, InGroup<TypeSafety>;
// Generic selections.
-def err_assoc_type_incomplete : Error<
- "type %0 in generic association incomplete">;
+def ext_assoc_type_incomplete : Extension<
+ "ISO C requires a complete type in a '_Generic' association; %0 is an "
+ "incomplete type">;
+def warn_c2y_compat_assoc_type_incomplete : Warning<
+ "use of an incomplete type in a '_Generic' association is incompatible with "
+ "C standards before C2y; %0 is an incomplete type">,
+ InGroup<CPre2yCompat>, DefaultIgnore;
def err_assoc_type_nonobject : Error<
"type %0 in generic association not an object type">;
def err_assoc_type_variably_modified : Error<
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index f896ccab53a54..de7be6b2805af 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1748,9 +1748,14 @@ ExprResult Sema::CreateGenericSelectionExpr(
//
// C11 6.5.1.1p2 "The type name in a generic association shall specify a
// complete object type other than a variably modified type."
+ // C2y removed the requirement that an expression form must
+ // use a complete type, though it's still as-if the type has undergone
+ // lvalue conversion. We support this as an extension in C23 and
+ // earlier because GCC does so.
unsigned D = 0;
if (ControllingExpr && Types[i]->getType()->isIncompleteType())
- D = diag::err_assoc_type_incomplete;
+ D = LangOpts.C2y ? diag::warn_c2y_compat_assoc_type_incomplete
+ : diag::ext_assoc_type_incomplete;
else if (ControllingExpr && !Types[i]->getType()->isObjectType())
D = diag::err_assoc_type_nonobject;
else if (Types[i]->getType()->isVariablyModifiedType())
diff --git a/clang/test/C/C2y/n3409.c b/clang/test/C/C2y/n3409.c
new file mode 100644
index 0000000000000..2fc789891c71d
--- /dev/null
+++ b/clang/test/C/C2y/n3409.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -verify -std=c2y -pedantic %s
+// RUN: %clang_cc1 -verify=pre-c2y -std=c2y -Wpre-c2y-compat %s
+// RUN: %clang_cc1 -verify=ext -std=c23 -pedantic %s
+// expected-no-diagnostics
+
+/* WG14 N3409: Clang 21
+ * Slay Some Earthly Demons X
+ *
+ * Removes the requirement that an expression with type void cannot be used in
+ * any way. This was making it UB to use a void expression in a _Generic
+ * selection expression for no good reason, as well as making it UB to cast a
+ * void expression to void, etc.
+ */
+
+extern void x;
+void foo() {
+ // FIXME: this is technically an extension before C2y and should be diagnosed
+ // under -pedantic.
+ (void)(void)1;
+ // FIXME: same with this.
+ x;
+ _Generic(x, void: 1); /* pre-c2y-warning {{use of an incomplete type in a '_Generic' association is incompatible with C standards before C2y; 'void' is an incomplete type}}
+ ext-warning {{ISO C requires a complete type in a '_Generic' association; 'void' is an incomplete type}}
+ */
+ _Generic(x, typeof(x): 1); /* pre-c2y-warning {{use of an incomplete type in a '_Generic' association is incompatible with C standards before C2y; 'typeof (x)' (aka 'void') is an incomplete type}}
+ ext-warning {{ISO C requires a complete type in a '_Generic' association; 'typeof (x)' (aka 'void') is an incomplete type}}
+ */
+ (void)_Generic(void, default : 1); /* pre-c2y-warning {{passing a type argument as the first operand to '_Generic' is incompatible with C standards before C2y}}
+ ext-warning {{passing a type argument as the first operand to '_Generic' is a C2y extension}}
+ */
+}
+
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/60/builds/21425 Here is the relevant piece of the build log for the reference
|
This paper removes UB around use of void expressions. Previously, code like this had undefined behavior: ``` void foo(void) { (void)(void)1; extern void x; x; } ``` and this is now well-defined in C2y. Functionally, this now means that it is valid to use `void` as a `_Generic` association.
This paper removes UB around use of void expressions. Previously, code like this had undefined behavior:
and this is now well-defined in C2y. Functionally, this now means that it is valid to use
void
as a_Generic
association.