https://github.com/hkleynhans updated https://github.com/llvm/llvm-project/pull/178479
>From 722ec904999f402cf15f695ab1c3c65573542530 Mon Sep 17 00:00:00 2001 From: Henry Kleynhans <[email protected]> Date: Wed, 28 Jan 2026 18:17:04 +0000 Subject: [PATCH 1/3] [clang] add test for ISO-C n3605 Add a test for N3605: Generic replacement (v. 2 of quasi-literals) The paper clarifies existing behavior of _Generic selection and parenthesis. This PR adds tests along the same lines and mark the feature as supported. --- clang/test/C/C2y/n3605.c | 50 ++++++++++++++++++++++++++++++++++++++ clang/test/C/C2y/n3605_1.c | 3 +++ clang/www/c_status.html | 2 +- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 clang/test/C/C2y/n3605.c create mode 100644 clang/test/C/C2y/n3605_1.c diff --git a/clang/test/C/C2y/n3605.c b/clang/test/C/C2y/n3605.c new file mode 100644 index 0000000000000..a8eaf34a37d3a --- /dev/null +++ b/clang/test/C/C2y/n3605.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s +// expected-no-diagnostics +// RUN: %clang_cc1 -std=c2y %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s + +enum A{ a=(int)(_Generic(0, int: (2.5))) }; +enum B{ b=(int)(_Generic(0, int: (2 + 1))) }; + +constexpr int c = _Generic((float*)0, default: 0); + +constexpr int d = _Generic((float*)0, default: (sizeof(c))); + +char s[] = _Generic(0, default: ("word")); + +// static_assert(1, _Generic(1, default: "Error Message")); + +int value_of_a() { + // CHECK: ret i32 2 + return a; +} + +int value_of_b() { + // CHECK: ret i32 3 + return b; +} + +int value_of_c() { + // CHECK: ret i32 0 + return c; +} + +int value_of_d() { + // CHECK: ret i32 4 + return d; +} + +char *value_of_s() { + // CHECK: ret ptr @s + return s; +} + +float value_of_float() { + // CHECK: %f = alloca ptr, align 8 + // CHECK: store ptr null, ptr %f, align 8 + // CHECK: %0 = load ptr, ptr %f, align 8 + // CHECK: %call = call float %0() + // CHECK: ret float %call + + float (*f)(void) = _Generic(1, default: (void*)0); + return f(); +} \ No newline at end of file diff --git a/clang/test/C/C2y/n3605_1.c b/clang/test/C/C2y/n3605_1.c new file mode 100644 index 0000000000000..3e0975d338c6f --- /dev/null +++ b/clang/test/C/C2y/n3605_1.c @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s + +static_assert(1, _Generic(1, default: "Error Message")); // expected-error{{expected string literal for diagnostic message in static_assert}} diff --git a/clang/www/c_status.html b/clang/www/c_status.html index ccf19ea86957a..6c920773aba61 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -354,7 +354,7 @@ <h2 id="c2y">C2y implementation status</h2> <tr> <td>Generic replacement (v. 2 of quasi-literals)</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3605.pdf">N3605</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>Member access of an incomplete object</td> >From d7a4743fcf16d5cfb5615512a8f6bced69055f19 Mon Sep 17 00:00:00 2001 From: Henry Kleynhans <[email protected]> Date: Thu, 29 Jan 2026 18:47:43 +0000 Subject: [PATCH 2/3] Test C versions from C11 --- clang/test/C/C2y/n3605.c | 26 +++++++++++-------- clang/test/C/C2y/n3605_1.c | 52 ++++++++++++++++++++++++++++++++++++-- clang/test/C/C2y/n3605_2.c | 4 +++ 3 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 clang/test/C/C2y/n3605_2.c diff --git a/clang/test/C/C2y/n3605.c b/clang/test/C/C2y/n3605.c index a8eaf34a37d3a..0a8b21ab0ad58 100644 --- a/clang/test/C/C2y/n3605.c +++ b/clang/test/C/C2y/n3605.c @@ -1,44 +1,48 @@ // RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s // expected-no-diagnostics // RUN: %clang_cc1 -std=c2y %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c23 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s enum A{ a=(int)(_Generic(0, int: (2.5))) }; enum B{ b=(int)(_Generic(0, int: (2 + 1))) }; -constexpr int c = _Generic((float*)0, default: 0); - +#if (__STDC_VERSION__ >= 202311L) +constexpr int c = _Generic((float*)0, default: 0); constexpr int d = _Generic((float*)0, default: (sizeof(c))); +#else +int c = _Generic((float*)0, default: 0); +int d = _Generic((float*)0, default: (sizeof(c))); +#endif char s[] = _Generic(0, default: ("word")); -// static_assert(1, _Generic(1, default: "Error Message")); - -int value_of_a() { +int value_of_a(void) { // CHECK: ret i32 2 return a; } -int value_of_b() { +int value_of_b(void) { // CHECK: ret i32 3 return b; } -int value_of_c() { +int value_of_c(void) { // CHECK: ret i32 0 return c; } -int value_of_d() { +int value_of_d(void) { // CHECK: ret i32 4 return d; } -char *value_of_s() { +char *value_of_s(void) { // CHECK: ret ptr @s return s; } -float value_of_float() { +float value_of_float(void) { // CHECK: %f = alloca ptr, align 8 // CHECK: store ptr null, ptr %f, align 8 // CHECK: %0 = load ptr, ptr %f, align 8 @@ -47,4 +51,4 @@ float value_of_float() { float (*f)(void) = _Generic(1, default: (void*)0); return f(); -} \ No newline at end of file +} diff --git a/clang/test/C/C2y/n3605_1.c b/clang/test/C/C2y/n3605_1.c index 3e0975d338c6f..3478f74502132 100644 --- a/clang/test/C/C2y/n3605_1.c +++ b/clang/test/C/C2y/n3605_1.c @@ -1,3 +1,51 @@ -// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c17 -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c11 -Wall -pedantic %s +// expected-no-diagnostics +// RUN: %clang_cc1 -std=c17 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c11 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s -static_assert(1, _Generic(1, default: "Error Message")); // expected-error{{expected string literal for diagnostic message in static_assert}} +enum A{ a=(int)(_Generic(0, int: (2.5))) }; +enum B{ b=(int)(_Generic(0, int: (2 + 1))) }; + +int c = _Generic((float*)0, default: 0); +int d = _Generic((float*)0, default: (sizeof(c))); + +char s[] = _Generic(0, default: ("word")); + +int value_of_a(void) { + // CHECK: ret i32 2 + return a; +} + +int value_of_b(void) { + // CHECK: ret i32 3 + return b; +} + +int value_of_c(void) { + // CHECK: %0 = load i32, ptr @c, align 4 + // CHECK: ret i32 %0 + return c; +} + +int value_of_d(void) { + // CHECK: %0 = load i32, ptr @d, align 4 + // CHECK: ret i32 %0 + return d; +} + +char *value_of_s(void) { + // CHECK: ret ptr @s + return s; +} + +float value_of_float(void) { + // CHECK: %f = alloca ptr, align 8 + // CHECK: store ptr null, ptr %f, align 8 + // CHECK: %0 = load ptr, ptr %f, align 8 + // CHECK: %call = call float %0() + // CHECK: ret float %call + + float (*f)(void) = _Generic(1, default: (void*)0); + return f(); +} diff --git a/clang/test/C/C2y/n3605_2.c b/clang/test/C/C2y/n3605_2.c new file mode 100644 index 0000000000000..cb336ab9af7fa --- /dev/null +++ b/clang/test/C/C2y/n3605_2.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s + +static_assert(1, _Generic(1, default: "Error Message")); // expected-error{{expected string literal for diagnostic message in static_assert}} >From 028f50cd7765208afaa6344ecd3b498b4ad2b7e8 Mon Sep 17 00:00:00 2001 From: Henry Kleynhans <[email protected]> Date: Fri, 30 Jan 2026 09:25:19 +0000 Subject: [PATCH 3/3] Remove duplication --- clang/test/C/C2y/n3605.c | 17 ++++++++------ clang/test/C/C2y/n3605_1.c | 48 +++++++------------------------------- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/clang/test/C/C2y/n3605.c b/clang/test/C/C2y/n3605.c index 0a8b21ab0ad58..f04ec557ddc11 100644 --- a/clang/test/C/C2y/n3605.c +++ b/clang/test/C/C2y/n3605.c @@ -1,19 +1,18 @@ // RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s // RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c17 -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c11 -Wall -pedantic %s // expected-no-diagnostics // RUN: %clang_cc1 -std=c2y %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -std=c23 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c17 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c11 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s enum A{ a=(int)(_Generic(0, int: (2.5))) }; enum B{ b=(int)(_Generic(0, int: (2 + 1))) }; -#if (__STDC_VERSION__ >= 202311L) -constexpr int c = _Generic((float*)0, default: 0); -constexpr int d = _Generic((float*)0, default: (sizeof(c))); -#else int c = _Generic((float*)0, default: 0); int d = _Generic((float*)0, default: (sizeof(c))); -#endif char s[] = _Generic(0, default: ("word")); @@ -28,12 +27,14 @@ int value_of_b(void) { } int value_of_c(void) { - // CHECK: ret i32 0 + // CHECK: %0 = load i32, ptr @c, align 4 + // CHECK: ret i32 %0 return c; } int value_of_d(void) { - // CHECK: ret i32 4 + // CHECK: %0 = load i32, ptr @d, align 4 + // CHECK: ret i32 %0 return d; } @@ -52,3 +53,5 @@ float value_of_float(void) { float (*f)(void) = _Generic(1, default: (void*)0); return f(); } + + diff --git a/clang/test/C/C2y/n3605_1.c b/clang/test/C/C2y/n3605_1.c index 3478f74502132..ee33beadeaadd 100644 --- a/clang/test/C/C2y/n3605_1.c +++ b/clang/test/C/C2y/n3605_1.c @@ -1,51 +1,19 @@ -// RUN: %clang_cc1 -verify -std=c17 -Wall -pedantic %s -// RUN: %clang_cc1 -verify -std=c11 -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s // expected-no-diagnostics -// RUN: %clang_cc1 -std=c17 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -std=c11 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c2y %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c23 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s -enum A{ a=(int)(_Generic(0, int: (2.5))) }; -enum B{ b=(int)(_Generic(0, int: (2 + 1))) }; - -int c = _Generic((float*)0, default: 0); -int d = _Generic((float*)0, default: (sizeof(c))); - -char s[] = _Generic(0, default: ("word")); +constexpr int a = _Generic((float*)0, default: 0); +constexpr int b = _Generic((float*)0, default: (sizeof(a))); int value_of_a(void) { - // CHECK: ret i32 2 + // CHECK: ret i32 0 return a; } int value_of_b(void) { - // CHECK: ret i32 3 + // CHECK: ret i32 4 return b; } -int value_of_c(void) { - // CHECK: %0 = load i32, ptr @c, align 4 - // CHECK: ret i32 %0 - return c; -} - -int value_of_d(void) { - // CHECK: %0 = load i32, ptr @d, align 4 - // CHECK: ret i32 %0 - return d; -} - -char *value_of_s(void) { - // CHECK: ret ptr @s - return s; -} - -float value_of_float(void) { - // CHECK: %f = alloca ptr, align 8 - // CHECK: store ptr null, ptr %f, align 8 - // CHECK: %0 = load ptr, ptr %f, align 8 - // CHECK: %call = call float %0() - // CHECK: ret float %call - - float (*f)(void) = _Generic(1, default: (void*)0); - return f(); -} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
