[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
alejandro-colomar wrote: No problem. Thanks! :-D https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > > > @AaronBallman > > > I'm not sure who's responsible for `` in LLVM. > > > > > > Yeah, it's never really clear who is expected to provide these headers. > > > In GCC it's a header provided by the compiler. I see that this PR does > > > not add the header, so I was wondering if that's to be added in a > > > separate commit, or if it's not supported by Clang and depends on library > > > support. > > > > > > I think Clang should probably provide the header as well. We do so for > > stdalign.h, stdbool.h, stdnoreturn.h and this is morally equivalent to > > those. Thanks for bringing this up! > > Okay, I'll see if I can write this patch. I'm much less busy these days. :) Thank you for the offer and sorry for stepping on toes, but I actually just posted the patch for it (https://github.com/llvm/llvm-project/pull/140890). :-D https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
alejandro-colomar wrote: > > @AaronBallman > > I'm not sure who's responsible for `` in LLVM. > > Yeah, it's never really clear who is expected to provide these headers. > > > In GCC it's a header provided by the compiler. I see that this PR does not > > add the header, so I was wondering if that's to be added in a separate > > commit, or if it's not supported by Clang and depends on library support. > > I think Clang should probably provide the header as well. We do so for > stdalign.h, stdbool.h, stdnoreturn.h and this is morally equivalent to those. > Thanks for bringing this up! Okay, I'll see if I can write this patch. I'm much less busy these days. :) https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > @AaronBallman > > I'm not sure who's responsible for `` in LLVM. Yeah, it's never really clear who is expected to provide these headers. > In GCC it's a header provided by the compiler. I see that this PR does not > add the header, so I was wondering if that's to be added in a separate > commit, or if it's not supported by Clang and depends on library support. I think Clang should probably provide the header as well. We do so for stdalign.h, stdbool.h, stdnoreturn.h and this is morally equivalent to those. Thanks for bringing this up! https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
alejandro-colomar wrote: @AaronBallman I'm not sure who's responsible for `` in LLVM. In GCC it's a header provided by the compiler. I see that this PR does not add the header, so I was wondering if that's to be added in a separate commit, or if it's not supported by Clang and depends on library support. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 01/11] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
AaronBallman wrote:
> `_Countof array`
FWIW, this is already covered by:
```
void test_constant_expression_behavior(int n) {
static_assert(_Countof(global_array) == 12);
static_assert(_Countof global_array == 12); // This one
static_assert(_Countof(int[12]) == 12);
}
```
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > Did WG14 considered some sort of macros for this feature? Otherwise I'd be > tempted to ask you to add something to `__has_feature`. I can see user > wanting to use `_Countof` when available and fallback to something else when > not. There is weak consensus to add `stdcountof.h` which supplies a `countof` macro. However, there's no changes to the standard which add one (yet), so I figured that can be done in a follow-up. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > > So you want this to be a FEATURE in C2y and an EXTENSION in older language > > modes? > > Presumably yes. > > > And when we get the countof macro in a few months, this becomes unnecessary? > > Are most users going to include `stdcountof.h` ? > > My assumption is that they would not, so having the feature thingy is useful > (especially in a library that may be concerned about not defining `countof`) Hmmm okay, that seems reasonable enough. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 1/3] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 1/9] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
alejandro-colomar wrote: > > Thanks @AaronBallman !! I am still working on my patch, so just for > > learning about Clang internals, I'll try to finish mine, and compare it to > > yours. :-) > > Sorry for stealing this one out from under you! No problem. :-) > It turns out it was a bit more involved than I expected because I didn't > realize how we represented multidimensional VLAs in the type system. Yep, the GCC patches were also non-trivial; at least for some corner cases. I had to wait for Martin to patch something unrelated to make it work. BTW, I'll check all the tests I wrote for GCC, and contribute anything that might be missing here (if any). > > > Sorry for being so slow! > > No worries! I wasn't certain if you had gotten busy or not, and I had some > spare bandwidth and wanted to write code for a bit. :) https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > Thanks @AaronBallman !! I am still working on my patch, so just for learning > about Clang internals, I'll try to finish mine, and compare it to yours. :-) Sorry for stealing this one out from under you! It turns out it was a bit more involved than I expected because I didn't realize how we represented multidimensional VLAs in the type system. > Sorry for being so slow! No worries! I wasn't certain if you had gotten busy or not, and I had some spare bandwidth and wanted to write code for a bit. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman closed https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
alejandro-colomar wrote: Thanks @AaronBallman !! I am still working on my patch, so just for learning about Clang internals, I'll try to finish mine, and compare it to yours. :-) Sorry for being so slow! Cheers, Alex https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/alejandro-colomar edited https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/alejandro-colomar edited https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment
-fexperimental-new-constant-interpreter -verify %s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+#if !__has_feature(c_countof)
+#error "Expected to have _Countof support"
+#endif
+
+#if !__has_extension(c_countof)
+// __has_extension returns true if __has_feature returns true.
+#error "Expected to have _Countof support"
+#endif
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+}
+
+void test_constant_expression_behavior(int n) {
+ static_assert(_Countof(global_array) == 12);
+ static_assert(_Countof global_array == 12);
+ static_assert(_Countof(int[12]) == 12);
+
+ // Use of a VLA makes it not a constant expression, same as with sizeof.
+ int array[n];
+ static_assert(_Countof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[n]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[n])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Constant folding works the same way as sizeof, too.
+ const int m = 12;
+ int other_array[m];
+ static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Note that this applies to each array dimension.
+ int another_array[n][7];
+ static_assert(_Countof(another_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(*another_array) == 7);
+
+ // Only the first dimension is needed for constant evaluation; other
+ // dimensions can be ignored.
+ int yet_another_array[7][n];
+ static_assert(_Countof(yet_another_array) == 7);
+ static_assert(_Countof(*yet_another_array)); // expected-error {{static
assertion expression is not an integral constant expression}}
+
+ int one_more_time[n][n][7];
+ static_assert(_Countof(one_more_time)); // expected-error {{static
assertion expression is not an integral constant expression}}
+ static_assert(_Countof(*one_more_time)); // expected-error {{static
assertion expression is not an integral constant expression}}
+ static_assert(_Countof(**one_more_time) == 7);
+}
+
+void test_with_function_param(int array[12], int (*array_ptr)[12], int
static_array[static 12]) {
+ (void)_Countof(array); // expected-error {{'_Countof' requires an argument
of array type; 'int *' invalid}}
+ static_assert(_Countof(*array_ptr) == 12);
+ (void)_Countof(static_array); // expected-error {{'_Countof' requires an
argument of array type; 'int *' invalid}}
+}
+
+void test_multidimensional_arrays() {
+ int array[12][7];
+ static_assert(_Countof(array) == 12);
+ static_assert(_Countof(*array) == 7);
+
+ int mdarray[12][7][100][3];
+ static_assert(_Countof(mdarray) == 12);
+ static_assert(_Countof(*mdarray) == 7);
+ static_assert(_Countof(**mdarray) == 100);
+ static_assert(_Countof(***mdarray) == 3);
+}
+
+void test_unspecified_array_length() {
+ static_assert(_Countof(int[])); // expected-error {{invalid application of
'_Countof' to an incomplete type 'int[]'}}
+
+ extern int x[][6][3];
+ static_assert(_Countof(x)); // expected-error {{invalid application of
'_Countof' to an incomplete type 'int[][6][3]'}}
+ static_assert(_Countof(*x) == 6);
+ static_assert(_Countof(**x) == 3);
+}
+
+// Test that the return type of _Countof is what you'd expect (size_t).
+void test_return_type() {
+ static_assert(_Gen
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment
-fexperimental-new-constant-interpreter -verify %s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+#if !__has_feature(c_countof)
+#error "Expected to have _Countof support"
+#endif
+
+#if !__has_extension(c_countof)
+// __has_extension returns true if __has_feature returns true.
+#error "Expected to have _Countof support"
+#endif
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+}
+
+void test_constant_expression_behavior(int n) {
+ static_assert(_Countof(global_array) == 12);
+ static_assert(_Countof global_array == 12);
+ static_assert(_Countof(int[12]) == 12);
+
+ // Use of a VLA makes it not a constant expression, same as with sizeof.
+ int array[n];
+ static_assert(_Countof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[n]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[n])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Constant folding works the same way as sizeof, too.
+ const int m = 12;
+ int other_array[m];
+ static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Note that this applies to each array dimension.
+ int another_array[n][7];
+ static_assert(_Countof(another_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(*another_array) == 7);
+
+ // Only the first dimension is needed for constant evaluation; other
+ // dimensions can be ignored.
+ int yet_another_array[7][n];
+ static_assert(_Countof(yet_another_array) == 7);
+ static_assert(_Countof(*yet_another_array)); // expected-error {{static
assertion expression is not an integral constant expression}}
+
+ int one_more_time[n][n][7];
+ static_assert(_Countof(one_more_time)); // expected-error {{static
assertion expression is not an integral constant expression}}
+ static_assert(_Countof(*one_more_time)); // expected-error {{static
assertion expression is not an integral constant expression}}
+ static_assert(_Countof(**one_more_time) == 7);
+}
+
+void test_with_function_param(int array[12], int (*array_ptr)[12], int
static_array[static 12]) {
+ (void)_Countof(array); // expected-error {{'_Countof' requires an argument
of array type; 'int *' invalid}}
+ static_assert(_Countof(*array_ptr) == 12);
+ (void)_Countof(static_array); // expected-error {{'_Countof' requires an
argument of array type; 'int *' invalid}}
+}
+
+void test_multidimensional_arrays() {
+ int array[12][7];
+ static_assert(_Countof(array) == 12);
+ static_assert(_Countof(*array) == 7);
+
+ int mdarray[12][7][100][3];
+ static_assert(_Countof(mdarray) == 12);
+ static_assert(_Countof(*mdarray) == 7);
+ static_assert(_Countof(**mdarray) == 100);
+ static_assert(_Countof(***mdarray) == 3);
+}
+
+void test_unspecified_array_length() {
+ static_assert(_Countof(int[])); // expected-error {{invalid application of
'_Countof' to an incomplete type 'int[]'}}
+
+ extern int x[][6][3];
+ static_assert(_Countof(x)); // expected-error {{invalid application of
'_Countof' to an incomplete type 'int[][6][3]'}}
+ static_assert(_Countof(*x) == 6);
+ static_assert(_Countof(**x) == 3);
+}
+
+// Test that the return type of _Countof is what you'd expect (size_t).
+void test_return_type() {
+ static_assert(_Gen
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment
-fexperimental-new-constant-interpreter -verify %s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+#if !__has_feature(c_countof)
+#error "Expected to have _Countof support"
+#endif
+
+#if !__has_extension(c_countof)
+// __has_extension returns true if __has_feature returns true.
+#error "Expected to have _Countof support"
+#endif
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
AaronBallman wrote:
Good call, I've added some more tests for that.
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 01/10] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment
-fexperimental-new-constant-interpreter -verify %s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+#if !__has_feature(c_countof)
+#error "Expected to have _Countof support"
+#endif
+
+#if !__has_extension(c_countof)
+// __has_extension returns true if __has_feature returns true.
+#error "Expected to have _Countof support"
+#endif
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
shafik wrote:
Maybe try on a struct and a function?
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment
-fexperimental-new-constant-interpreter -verify %s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+#if !__has_feature(c_countof)
+#error "Expected to have _Countof support"
+#endif
+
+#if !__has_extension(c_countof)
+// __has_extension returns true if __has_feature returns true.
+#error "Expected to have _Countof support"
+#endif
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+}
+
+void test_constant_expression_behavior(int n) {
+ static_assert(_Countof(global_array) == 12);
+ static_assert(_Countof global_array == 12);
+ static_assert(_Countof(int[12]) == 12);
+
+ // Use of a VLA makes it not a constant expression, same as with sizeof.
+ int array[n];
+ static_assert(_Countof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[n]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[n])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Constant folding works the same way as sizeof, too.
+ const int m = 12;
+ int other_array[m];
+ static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Note that this applies to each array dimension.
+ int another_array[n][7];
+ static_assert(_Countof(another_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(*another_array) == 7);
+
+ // Only the first dimension is needed for constant evaluation; other
+ // dimensions can be ignored.
+ int yet_another_array[7][n];
+ static_assert(_Countof(yet_another_array) == 7);
+ static_assert(_Countof(*yet_another_array)); // expected-error {{static
assertion expression is not an integral constant expression}}
+
+ int one_more_time[n][n][7];
+ static_assert(_Countof(one_more_time)); // expected-error {{static
assertion expression is not an integral constant expression}}
+ static_assert(_Countof(*one_more_time)); // expected-error {{static
assertion expression is not an integral constant expression}}
+ static_assert(_Countof(**one_more_time) == 7);
+}
+
+void test_with_function_param(int array[12], int (*array_ptr)[12], int
static_array[static 12]) {
+ (void)_Countof(array); // expected-error {{'_Countof' requires an argument
of array type; 'int *' invalid}}
+ static_assert(_Countof(*array_ptr) == 12);
+ (void)_Countof(static_array); // expected-error {{'_Countof' requires an
argument of array type; 'int *' invalid}}
+}
+
+void test_multidimensional_arrays() {
+ int array[12][7];
+ static_assert(_Countof(array) == 12);
+ static_assert(_Countof(*array) == 7);
+
+ int mdarray[12][7][100][3];
+ static_assert(_Countof(mdarray) == 12);
+ static_assert(_Countof(*mdarray) == 7);
+ static_assert(_Countof(**mdarray) == 100);
+ static_assert(_Countof(***mdarray) == 3);
+}
+
+void test_unspecified_array_length() {
+ static_assert(_Countof(int[])); // expected-error {{invalid application of
'_Countof' to an incomplete type 'int[]'}}
+
+ extern int x[][6][3];
+ static_assert(_Countof(x)); // expected-error {{invalid application of
'_Countof' to an incomplete type 'int[][6][3]'}}
+ static_assert(_Countof(*x) == 6);
+ static_assert(_Countof(**x) == 3);
+}
+
+// Test that the return type of _Countof is what you'd expect (size_t).
+void test_return_type() {
+ static_assert(_Gen
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > > > So you want this to be a FEATURE in C2y and an EXTENSION in older > > > language modes? > > > > > > Presumably yes. > > > And when we get the countof macro in a few months, this becomes > > > unnecessary? > > > > > > Are most users going to include `stdcountof.h` ? > > My assumption is that they would not, so having the feature thingy is > > useful (especially in a library that may be concerned about not defining > > `countof`) > > Hmmm okay, that seems reasonable enough. I've added that now. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -14926,6 +14926,42 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return false;
}
+ case UETT_CountOf: {
+QualType Ty = E->getTypeOfArgument();
+assert(Ty->isArrayType());
+
+// We don't need to worry about array element qualifiers, so getting the
+// unsafe array type is fine.
+if (const auto *CAT =
+dyn_cast(Ty->getAsArrayTypeUnsafe())) {
+ return Success(CAT->getSize(), E);
+}
+
+assert(!Ty->isConstantSizeType());
+
+// If it's a variable-length array type, we need to check whether it is a
+// multidimensional array. If so, we need to check the size expression of
+// the VLA to see if it's a constant size. If so, we can return that value.
+const auto *VAT = Info.Ctx.getAsVariableArrayType(Ty);
+assert(VAT);
+if (VAT->getElementType()->isArrayType()) {
+ std::optional Res =
+ VAT->getSizeExpr()->getIntegerConstantExpr(Info.Ctx);
+ if (Res) {
+// The resulting value always has type size_t, so we need to make the
+// returned APInt have the correct sign and bit-width.
+APInt Val{
+
static_cast(Info.Ctx.getTypeSize(Info.Ctx.getSizeType())),
+Res->getZExtValue()};
+return Success(Val, E);
+ }
+}
cor3ntin wrote:
I can't find a test that exercises this
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/cor3ntin approved this pull request. Thanks! https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 1/8] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
AaronBallman wrote:
Fair point!
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
cor3ntin wrote: > So you want this to be a FEATURE in C2y and an EXTENSION in older language > modes? Presumably yes. > And when we get the countof macro in a few months, this becomes unnecessary? Are most users going to include `stdcountof.h` ? My assumption is that they would not, so having the feature thingy is useful (especially in a library that may be concerned about not defining `countof`) https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify %s + +/* WG14 N3369: Clang 21 + * _Lengthof operator + * + * Adds an operator to get the length of an array. Note that WG14 N3469 renamed + * this operator to _Countof. + */ AaronBallman wrote: Then it wouldn't be testing constant folding, so I feel like I must be misunderstanding something. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > > There is weak consensus to add `stdcountof.h` which supplies a `countof` > > macro. However, there's no changes to the standard which add one (yet), so > > I figured that can be done in a follow-up. > > Then I'd really like a feature. We already have a bunch, It makes sense to > add one for that imo > > ``` > include/clang/Basic/Features.def:FEATURE(c_alignas, LangOpts.C11) > include/clang/Basic/Features.def:FEATURE(c_alignof, LangOpts.C11) > include/clang/Basic/Features.def:FEATURE(c_atomic, LangOpts.C11) > include/clang/Basic/Features.def:FEATURE(c_generic_selections, LangOpts.C11) > include/clang/Basic/Features.def:FEATURE(c_static_assert, LangOpts.C11) > include/clang/Basic/Features.def:FEATURE(c_thread_local, LangOpts.C11 > &&PP.getTargetInfo().isTLSSupported()) > include/clang/Basic/Features.def:FEATURE(c_fixed_enum, LangOpts.C23) > ``` So you want this to be a `FEATURE` in C2y and an `EXTENSION` in older language modes? And when we get the `countof` macro in a few months, this becomes unnecessary? https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -14926,6 +14926,42 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return false;
}
+ case UETT_CountOf: {
+QualType Ty = E->getTypeOfArgument();
+assert(Ty->isArrayType());
+
+// We don't need to worry about array element qualifiers, so getting the
+// unsafe array type is fine.
+if (const auto *CAT =
+dyn_cast(Ty->getAsArrayTypeUnsafe())) {
+ return Success(CAT->getSize(), E);
+}
+
+assert(!Ty->isConstantSizeType());
+
+// If it's a variable-length array type, we need to check whether it is a
+// multidimensional array. If so, we need to check the size expression of
+// the VLA to see if it's a constant size. If so, we can return that value.
+const auto *VAT = Info.Ctx.getAsVariableArrayType(Ty);
+assert(VAT);
+if (VAT->getElementType()->isArrayType()) {
+ std::optional Res =
+ VAT->getSizeExpr()->getIntegerConstantExpr(Info.Ctx);
+ if (Res) {
+// The resulting value always has type size_t, so we need to make the
+// returned APInt have the correct sign and bit-width.
+APInt Val{
+
static_cast(Info.Ctx.getTypeSize(Info.Ctx.getSizeType())),
+Res->getZExtValue()};
+return Success(Val, E);
+ }
+}
AaronBallman wrote:
Sure, added!
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
cor3ntin wrote: > There is weak consensus to add `stdcountof.h` which supplies a `countof` > macro. However, there's no changes to the standard which add one (yet), so I > figured that can be done in a follow-up. Then I'd really like a feature. We already have a bunch, It makes sense to add one for that imo ``` include/clang/Basic/Features.def:FEATURE(c_alignas, LangOpts.C11) include/clang/Basic/Features.def:FEATURE(c_alignof, LangOpts.C11) include/clang/Basic/Features.def:FEATURE(c_atomic, LangOpts.C11) include/clang/Basic/Features.def:FEATURE(c_generic_selections, LangOpts.C11) include/clang/Basic/Features.def:FEATURE(c_static_assert, LangOpts.C11) include/clang/Basic/Features.def:FEATURE(c_thread_local, LangOpts.C11 &&PP.getTargetInfo().isTLSSupported()) include/clang/Basic/Features.def:FEATURE(c_fixed_enum, LangOpts.C23) ``` https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify %s + +/* WG14 N3369: Clang 21 + * _Lengthof operator + * + * Adds an operator to get the length of an array. Note that WG14 N3469 renamed + * this operator to _Countof. + */ cor3ntin wrote: Can you make `m` non-const for added clarity? https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -14926,6 +14926,42 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return false;
}
+ case UETT_CountOf: {
+QualType Ty = E->getTypeOfArgument();
+assert(Ty->isArrayType());
+
+// We don't need to worry about array element qualifiers, so getting the
+// unsafe array type is fine.
+if (const auto *CAT =
+dyn_cast(Ty->getAsArrayTypeUnsafe())) {
+ return Success(CAT->getSize(), E);
+}
+
+assert(!Ty->isConstantSizeType());
+
+// If it's a variable-length array type, we need to check whether it is a
+// multidimensional array. If so, we need to check the size expression of
+// the VLA to see if it's a constant size. If so, we can return that value.
+const auto *VAT = Info.Ctx.getAsVariableArrayType(Ty);
+assert(VAT);
+if (VAT->getElementType()->isArrayType()) {
+ std::optional Res =
+ VAT->getSizeExpr()->getIntegerConstantExpr(Info.Ctx);
+ if (Res) {
+// The resulting value always has type size_t, so we need to make the
+// returned APInt have the correct sign and bit-width.
+APInt Val{
+
static_cast(Info.Ctx.getTypeSize(Info.Ctx.getSizeType())),
+Res->getZExtValue()};
+return Success(Val, E);
+ }
+}
cor3ntin wrote:
How about `int another_array[n][n][7];` ?
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify %s + +/* WG14 N3369: Clang 21 + * _Lengthof operator + * + * Adds an operator to get the length of an array. Note that WG14 N3469 renamed + * this operator to _Countof. + */ cor3ntin wrote: I'm blind! https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 1/7] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -14926,6 +14926,42 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return false;
}
+ case UETT_CountOf: {
AaronBallman wrote:
I'll add support for this there.
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 1/6] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 1/5] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -14926,6 +14926,42 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return false;
}
+ case UETT_CountOf: {
+QualType Ty = E->getTypeOfArgument();
+assert(Ty->isArrayType());
+
+// We don't need to worry about array element qualifiers, so getting the
+// unsafe array type is fine.
+if (const auto *CAT =
+dyn_cast(Ty->getAsArrayTypeUnsafe())) {
+ return Success(CAT->getSize(), E);
+}
+
+assert(!Ty->isConstantSizeType());
+
+// If it's a variable-length array type, we need to check whether it is a
+// multidimensional array. If so, we need to check the size expression of
+// the VLA to see if it's a constant size. If so, we can return that value.
+const auto *VAT = Info.Ctx.getAsVariableArrayType(Ty);
+assert(VAT);
+if (VAT->getElementType()->isArrayType()) {
+ std::optional Res =
+ VAT->getSizeExpr()->getIntegerConstantExpr(Info.Ctx);
+ if (Res) {
+// The resulting value always has type size_t, so we need to make the
+// returned APInt have the correct sign and bit-width.
+APInt Val{
+
static_cast(Info.Ctx.getTypeSize(Info.Ctx.getSizeType())),
+Res->getZExtValue()};
+return Success(Val, E);
+ }
+}
AaronBallman wrote:
See `test_constant_expression_behavior()`:
```
// Note that this applies to each array dimension.
int another_array[n][7];
static_assert(_Countof(another_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
static_assert(_Countof(*another_array) == 7);
// Only the first dimension is needed for constant evaluation; other
// dimensions can be ignored.
int yet_another_array[7][n];
static_assert(_Countof(yet_another_array) == 7);
static_assert(_Countof(*yet_another_array)); // expected-error {{static
assertion expression is not an integral constant expression}}
```
Without this code, `static_assert(_Countof(yet_another_array) == 7);` would
give an error that the assertion is not an ICE.
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
AaronBallman wrote:
Good call, I'll add these tests. FWIW, I already show constant folding:
```
// Constant folding works the same way as sizeof, too.
const int m = 12;
int other_array[m];
static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
```
or did you have something else in mind?
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -4338,6 +4338,21 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
E->getSourceRange(), ExprKind))
return true;
+ if (ExprKind == UETT_CountOf) {
+// The type has to be an array type. We already checked for incomplete
+// types above.
+QualType ExprType = E->IgnoreParens()->getType();
+if (!ExprType->isArrayType()) {
+ Diag(E->getExprLoc(), diag::err_countof_arg_not_array_type) << ExprType;
+ return true;
AaronBallman wrote:
Absolutely!
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
frederick-vs-ja wrote:
```suggestion
modes (``std::extent`` and ``std::size`` already provide the same
```
I guess it's better to say `std::size` (which gets the count of built-in array
values) here, as `_Countof` doesn't get the rank of an array.
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -4338,6 +4338,21 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
E->getSourceRange(), ExprKind))
return true;
+ if (ExprKind == UETT_CountOf) {
+// The type has to be an array type. We already checked for incomplete
+// types above.
+QualType ExprType = E->IgnoreParens()->getType();
+if (!ExprType->isArrayType()) {
+ Diag(E->getExprLoc(), diag::err_countof_arg_not_array_type) << ExprType;
+ return true;
cor3ntin wrote:
Can you add tests for arrays of unspecified length, though?
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -14926,6 +14926,42 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
return false;
}
+ case UETT_CountOf: {
cor3ntin wrote:
Did you consider the new interpreter? @tbaederr
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify %s + +/* WG14 N3369: Clang 21 + * _Lengthof operator + * + * Adds an operator to get the length of an array. Note that WG14 N3469 renamed + * this operator to _Countof. + */ cor3ntin wrote: More tests for you to consider: - unspecified arrays length - arrays of rank 3 - `_Countof array` - typedefs - `static_assert(__is_same_as(typeof(_Countof(foo)), size_t))` - Constant folding tests https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/cor3ntin commented: Did WG14 considered some sort of macros for this feature? Otherwise I'd be tempted to ask you to add something to `__has_feature`. I can see user wanting to use `_Countof` when available and fallback to something else when not. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/jyknight approved this pull request. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
jyknight wrote: > We make a VariableArrayType whose element type is a VariableArrayType rather > than a ConstantArrayType of size 7 whose element type is a VariableArrayType. Yea. Up till now I think there was no observable difference between the outer array having a constant or variable bound when the inner array is already a VLA, so it's perhaps not surprising it was modeled that way. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: Good catch on the VLA test cases @jyknight! It turns out we model VLAs very oddly in the type system. Given: ``` extern int n; int array[7][n]; ``` We make a VariableArrayType whose element type is a VariableArrayType rather than a ConstantArrayType of size 7 whose element type is a VariableArrayType. This made `_Countof` a little bit more complicated because we need to look through that design choice. I've implement that (in both ExprConstant.cpp and CGExprScalar.cpp), but we may someday want to do a deeper repair. Instead, I added a FIXME and a note in Type.h so others aren't surprised by this as well. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman updated
https://github.com/llvm/llvm-project/pull/133125
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH 1/4] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,92 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
UTC_ARGS: --version 5
+// RUN: %clang_cc1 -std=c2y -emit-llvm -o - %s | FileCheck %s
+
+// This tests the codegen behavior for _Countof.
+// CHECK-LABEL: define dso_local i32 @test1(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[ARRAY:%.*]] = alloca [12 x i32], align 16
+// CHECK-NEXT:ret i32 12
+//
+int test1() {
+ int array[12];
+ return _Countof(array);
+}
+
+// CHECK-LABEL: define dso_local i32 @test2(
+// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[SAVED_STACK:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[__VLA_EXPR0:%.*]] = alloca i64, align 8
+// CHECK-NEXT:store i32 [[N]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT:[[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
+// CHECK-NEXT:store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:[[VLA:%.*]] = alloca i32, i64 [[TMP1]], align 16
+// CHECK-NEXT:store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8
+// CHECK-NEXT:[[CONV:%.*]] = trunc i64 [[TMP1]] to i32
+// CHECK-NEXT:[[TMP3:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:call void @llvm.stackrestore.p0(ptr [[TMP3]])
+// CHECK-NEXT:ret i32 [[CONV]]
+//
+int test2(int n) {
+ int array[n];
+ return _Countof(array);
+}
+
+// CHECK-LABEL: define dso_local i32 @test3(
+// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:store i32 [[N]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT:[[CONV:%.*]] = trunc i64 [[TMP1]] to i32
+// CHECK-NEXT:ret i32 [[CONV]]
+//
+int test3(int n) {
+ return _Countof(int[n]);
+}
+
+// CHECK-LABEL: define dso_local i32 @test4(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:ret i32 100
+//
+int test4() {
+ return _Countof(float[100]);
+}
+
+// CHECK-LABEL: define dso_local i32 @test5(
+// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[SAVED_STACK:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[__VLA_EXPR0:%.*]] = alloca i64, align 8
+// CHECK-NEXT:[[X:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[Y:%.*]] = alloca i32, align 4
+// CHECK-NEXT:store i32 [[N]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT:[[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
+// CHECK-NEXT:store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:[[VLA:%.*]] = alloca [7 x i32], i64 [[TMP1]], align 16
+// CHECK-NEXT:store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8
+// CHECK-NEXT:[[CONV:%.*]] = trunc i64 [[TMP1]] to i32
+// CHECK-NEXT:store i32 [[CONV]], ptr [[X]], align 4
+// CHECK-NEXT:store i32 7, ptr [[Y]], align 4
+// CHECK-NEXT:[[TMP3:%.*]] = load i32, ptr [[X]], align 4
+// CHECK-NEXT:[[TMP4:%.*]] = load i32, ptr [[Y]], align 4
+// CHECK-NEXT:[[ADD:%.*]] = add nsw i32 [[TMP3]], [[TMP4]]
+// CHECK-NEXT:[[TMP5:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:call void @llvm.stackrestore.p0(ptr [[TMP5]])
+// CHECK-NEXT:ret i32 [[ADD]]
+//
+int test5(int n) {
+ int array[n][7];
+ int x = _Countof(array);
+ int y = _Countof(*array);
+ return x + y;
+}
AaronBallman wrote:
Good call, this has the same bug as the earlier test regarding what is and
isn't an operand resulting in a constant expression.
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,92 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
UTC_ARGS: --version 5
+// RUN: %clang_cc1 -std=c2y -emit-llvm -o - %s | FileCheck %s
+
+// This tests the codegen behavior for _Countof.
+// CHECK-LABEL: define dso_local i32 @test1(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[ARRAY:%.*]] = alloca [12 x i32], align 16
+// CHECK-NEXT:ret i32 12
+//
+int test1() {
+ int array[12];
+ return _Countof(array);
+}
+
+// CHECK-LABEL: define dso_local i32 @test2(
+// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[SAVED_STACK:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[__VLA_EXPR0:%.*]] = alloca i64, align 8
+// CHECK-NEXT:store i32 [[N]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT:[[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
+// CHECK-NEXT:store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:[[VLA:%.*]] = alloca i32, i64 [[TMP1]], align 16
+// CHECK-NEXT:store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8
+// CHECK-NEXT:[[CONV:%.*]] = trunc i64 [[TMP1]] to i32
+// CHECK-NEXT:[[TMP3:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:call void @llvm.stackrestore.p0(ptr [[TMP3]])
+// CHECK-NEXT:ret i32 [[CONV]]
+//
+int test2(int n) {
+ int array[n];
+ return _Countof(array);
+}
+
+// CHECK-LABEL: define dso_local i32 @test3(
+// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:store i32 [[N]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT:[[CONV:%.*]] = trunc i64 [[TMP1]] to i32
+// CHECK-NEXT:ret i32 [[CONV]]
+//
+int test3(int n) {
+ return _Countof(int[n]);
+}
+
+// CHECK-LABEL: define dso_local i32 @test4(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:ret i32 100
+//
+int test4() {
+ return _Countof(float[100]);
+}
+
+// CHECK-LABEL: define dso_local i32 @test5(
+// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:[[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[SAVED_STACK:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[__VLA_EXPR0:%.*]] = alloca i64, align 8
+// CHECK-NEXT:[[X:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[Y:%.*]] = alloca i32, align 4
+// CHECK-NEXT:store i32 [[N]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT:[[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
+// CHECK-NEXT:store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:[[VLA:%.*]] = alloca [7 x i32], i64 [[TMP1]], align 16
+// CHECK-NEXT:store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8
+// CHECK-NEXT:[[CONV:%.*]] = trunc i64 [[TMP1]] to i32
+// CHECK-NEXT:store i32 [[CONV]], ptr [[X]], align 4
+// CHECK-NEXT:store i32 7, ptr [[Y]], align 4
+// CHECK-NEXT:[[TMP3:%.*]] = load i32, ptr [[X]], align 4
+// CHECK-NEXT:[[TMP4:%.*]] = load i32, ptr [[Y]], align 4
+// CHECK-NEXT:[[ADD:%.*]] = add nsw i32 [[TMP3]], [[TMP4]]
+// CHECK-NEXT:[[TMP5:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8
+// CHECK-NEXT:call void @llvm.stackrestore.p0(ptr [[TMP5]])
+// CHECK-NEXT:ret i32 [[ADD]]
+//
+int test5(int n) {
+ int array[n][7];
+ int x = _Countof(array);
+ int y = _Countof(*array);
+ return x + y;
+}
jyknight wrote:
Missing tests of the silly side-effect behavior for VLAs. Examples from the
spec:
```
_Countof(int [7][n++]); // integer constant expression; n++ side-effect not
evaluated
_Countof(int [n++][7]); // runtime value; n++ side-effect _is_ evaluated
```
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+}
+
+void test_constant_expression_behavior(int n) {
+ static_assert(_Countof(global_array) == 12);
+ static_assert(_Countof global_array == 12);
+ static_assert(_Countof(int[12]) == 12);
+
+ // Use of a VLA makes it not a constant expression, same as with sizeof.
+ int array[n];
+ static_assert(_Countof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[n]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[n])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Constant folding works the same way as sizeof, too.
+ const int m = 12;
+ int other_array[m];
+ static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Note that this applies to each array dimension.
+ int another_array[n][7];
+ static_assert(_Countof(another_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(*another_array) == 7);
+}
+
+void test_with_function_param(int array[12], int (*array_ptr)[12]) {
AaronBallman wrote:
Correct, still decays to a pointer. I've added a test for this.
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+}
+
+void test_constant_expression_behavior(int n) {
+ static_assert(_Countof(global_array) == 12);
+ static_assert(_Countof global_array == 12);
+ static_assert(_Countof(int[12]) == 12);
+
+ // Use of a VLA makes it not a constant expression, same as with sizeof.
+ int array[n];
+ static_assert(_Countof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[n]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[n])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Constant folding works the same way as sizeof, too.
+ const int m = 12;
+ int other_array[m];
+ static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Note that this applies to each array dimension.
jyknight wrote:
Mising a test for a non-toplevel VLA array, e.g. `int array[7][n];`, where,
unlike sizeof, this _should_ be a constant-expression (e.g.
`static_assert(_Countof(array) == 7)`).
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+}
+
+void test_constant_expression_behavior(int n) {
+ static_assert(_Countof(global_array) == 12);
+ static_assert(_Countof global_array == 12);
+ static_assert(_Countof(int[12]) == 12);
+
+ // Use of a VLA makes it not a constant expression, same as with sizeof.
+ int array[n];
+ static_assert(_Countof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[n]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[n])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Constant folding works the same way as sizeof, too.
+ const int m = 12;
+ int other_array[m];
+ static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Note that this applies to each array dimension.
AaronBallman wrote:
Good call, that exposed an issue. I'll add test coverage and correct the
problem.
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify
%s
+
+/* WG14 N3369: Clang 21
+ * _Lengthof operator
+ *
+ * Adds an operator to get the length of an array. Note that WG14 N3469 renamed
+ * this operator to _Countof.
+ */
+
+int global_array[12];
+
+void test_parsing_failures() {
+ (void)_Countof; // expected-error {{expected expression}}
+ (void)_Countof(;// expected-error {{expected expression}}
+ (void)_Countof(); // expected-error {{expected expression}}
+ (void)_Countof int; // expected-error {{expected expression}}
+}
+
+void test_semantic_failures() {
+ (void)_Countof(1); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ int non_array;
+ (void)_Countof non_array; // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+ (void)_Countof(int); // expected-error {{'_Countof' requires an
argument of array type; 'int' invalid}}
+}
+
+void test_constant_expression_behavior(int n) {
+ static_assert(_Countof(global_array) == 12);
+ static_assert(_Countof global_array == 12);
+ static_assert(_Countof(int[12]) == 12);
+
+ // Use of a VLA makes it not a constant expression, same as with sizeof.
+ int array[n];
+ static_assert(_Countof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[n]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[n])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Constant folding works the same way as sizeof, too.
+ const int m = 12;
+ int other_array[m];
+ static_assert(sizeof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(other_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(sizeof(int[m]));// expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(int[m])); // expected-error {{static assertion
expression is not an integral constant expression}}
+
+ // Note that this applies to each array dimension.
+ int another_array[n][7];
+ static_assert(_Countof(another_array)); // expected-error {{static assertion
expression is not an integral constant expression}}
+ static_assert(_Countof(*another_array) == 7);
+}
+
+void test_with_function_param(int array[12], int (*array_ptr)[12]) {
jyknight wrote:
I presume `void fn(int array[static 12])` also doesn't work, as it also doesn't
get an array type then (which always seemed really odd to me but _shrug_.)
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
AaronBallman wrote: > Although C++ might have good alternatives, that's not so helpful for C > headers being included from C++ that might end up using this (e.g. some > static inline function in a system header). (i.e. if it's not too much effort > to do, I would encourage exposing it in C++) We can contrive reasons to expose this in C++, and it would be a conforming extension there, but I'm still not convinced that's a good idea. Historically, many of the things we expose from C into C++ have some really rough edges we mostly ignore, like VLAs, _Complex vs std::complex, etc and I'd like to break that cycle by not exposing everything to both languages just because we can. I'm not strongly opposed in this case, but I'd still rather wait for a real world use case beyond "it could be used there" before we expose it to C++. https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
jrtc27 wrote: Although C++ might have good alternatives, that's not so helpful for C headers being included from C++ that might end up using this (e.g. some static inline function in a system header). https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
llvmbot wrote:
@llvm/pr-subscribers-clang
Author: Aaron Ballman (AaronBallman)
Changes
C2y adds the _Countof operator which returns the number of elements in an
array. As with sizeof, _Countof either accepts a parenthesized type name or an
expression. Its operand must be (of) an array type. When passed a constant-size
array operand, the operator is a constant expression which is valid for use as
an integer constant expression.
This is being exposed as an extension in earlier C language modes, but not in
C++. C++ already has `std::extent` and `std::rank` to cover these needs, so the
operator doesn't seem to get the user enough benefit to warrant carrying this
as an extension.
Fixes #102836
---
Patch is 25.31 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/133125.diff
15 Files Affected:
- (modified) clang/docs/LanguageExtensions.rst (+1)
- (modified) clang/docs/ReleaseNotes.rst (+6)
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+5)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2)
- (modified) clang/include/clang/Basic/TokenKinds.def (+2)
- (modified) clang/lib/AST/ExprConstant.cpp (+18-1)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+1)
- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+10-5)
- (modified) clang/lib/Parse/ParseExpr.cpp (+17-4)
- (modified) clang/lib/Sema/SemaExpr.cpp (+32-7)
- (added) clang/test/C/C2y/n3369.c (+61)
- (added) clang/test/C/C2y/n3369_1.c (+25)
- (added) clang/test/C/C2y/n3369_2.c (+92)
- (added) clang/test/C/C2y/n3469.c (+14)
- (modified) clang/www/c_status.html (+2-2)
``diff
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C2y">,
+ InGroup, DefaultIgnore;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..1e900437d41ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7022,6 +7022,8 @@ def err_sizeof_alignof_typeof_bitfield : Error<
"bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being
defined">;
+def err_countof_arg_not_array_type : Error<
+ "'_Countof' requires an argument of array
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman created
https://github.com/llvm/llvm-project/pull/133125
C2y adds the _Countof operator which returns the number of elements in an
array. As with sizeof, _Countof either accepts a parenthesized type name or an
expression. Its operand must be (of) an array type. When passed a constant-size
array operand, the operator is a constant expression which is valid for use as
an integer constant expression.
This is being exposed as an extension in earlier C language modes, but not in
C++. C++ already has `std::extent` and `std::rank` to cover these needs, so the
operator doesn't seem to get the user enough benefit to warrant carrying this
as an extension.
Fixes #102836
>From 75ef42d644da9136fb07014ade18b6be137426a1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman
Date: Wed, 26 Mar 2025 12:54:29 -0400
Subject: [PATCH] [C2y] Implement WG14 N3369 and N3469 (_Countof)
C2y adds the _Countof operator which returns the number of elements in
an array. As with sizeof, _Countof either accepts a parenthesized type
name or an expression. Its operand must be (of) an array type. When
passed a constant-size array operand, the operator is a constant
expression which is valid for use as an integer constant expression.
Fixes #102836
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 6 ++
.../clang/Basic/DiagnosticParseKinds.td | 5 +
.../clang/Basic/DiagnosticSemaKinds.td| 2 +
clang/include/clang/Basic/TokenKinds.def | 2 +
clang/lib/AST/ExprConstant.cpp| 19 +++-
clang/lib/AST/ItaniumMangle.cpp | 1 +
clang/lib/CodeGen/CGExprScalar.cpp| 15 ++-
clang/lib/Parse/ParseExpr.cpp | 21 -
clang/lib/Sema/SemaExpr.cpp | 39 ++--
clang/test/C/C2y/n3369.c | 61
clang/test/C/C2y/n3369_1.c| 25 +
clang/test/C/C2y/n3369_2.c| 92 +++
clang/test/C/C2y/n3469.c | 14 +++
clang/www/c_status.html | 4 +-
15 files changed, 288 insertions(+), 19 deletions(-)
create mode 100644 clang/test/C/C2y/n3369.c
create mode 100644 clang/test/C/C2y/n3369_1.c
create mode 100644 clang/test/C/C2y/n3369_2.c
create mode 100644 clang/test/C/C2y/n3469.c
diff --git a/clang/docs/LanguageExtensions.rst
b/clang/docs/LanguageExtensions.rst
index d4771775c9739..8b5707ce2acac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1653,6 +1653,7 @@ Array & element qualification (N2607)
C
Attributes (N2335)
C23 C89
``#embed`` (N3017)
C23 C89, C++
Octal literals prefixed with ``0o`` or ``0O``
C2y C89, C++
+``_Countof`` (N3369, N3469)
C2y C89
=
= =
Builtin type aliases
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..b82e79c092c4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,6 +141,12 @@ C2y Feature Support
paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
``"\x{12}\o{12}"``) which are also supported as an extension in older C
language modes.
+- Implemented `WG14 N3369
`_
+ which introduces the ``_Lengthof`` operator, and `WG14 N3469
`_
+ which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
+ a conforming extension in earlier C language modes, but not in C++ language
+ modes (``std::extent`` and ``std::rank`` already provide the same
+ functionality but with more granularity).
C23 Feature Support
^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4dc956f7ae6f7..86c361b4dbcf7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -171,12 +171,17 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup;
+def ext_c2y_feature : Extension<
+ "'%0' is a C2y extension">, InGroup;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup, DefaultIgnore;
+def warn_c2y_compat_keyword : Warning<
+ "'%0' is incompatible with C standards befo
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
github-actions[bot] wrote:
:warning: C/C++ code formatter, clang-format found issues in your code.
:warning:
You can test this locally with the following command:
``bash
git-clang-format --diff 15f5a7a3ec71c624cea0cbdf02e3c5205ba81d9d
75ef42d644da9136fb07014ade18b6be137426a1 --extensions c,cpp --
clang/test/C/C2y/n3369.c clang/test/C/C2y/n3369_1.c clang/test/C/C2y/n3369_2.c
clang/test/C/C2y/n3469.c clang/lib/AST/ExprConstant.cpp
clang/lib/AST/ItaniumMangle.cpp clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/Parse/ParseExpr.cpp clang/lib/Sema/SemaExpr.cpp
``
View the diff from clang-format here.
``diff
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 92b1f41bf2..31589ec553 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17442,7 +17442,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext
&Ctx) {
}
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *Exp = cast(E);
-if ((Exp->getKind() == UETT_SizeOf || Exp->getKind() == UETT_CountOf) &&
+if ((Exp->getKind() == UETT_SizeOf || Exp->getKind() == UETT_CountOf) &&
Exp->getTypeOfArgument()->isVariableArrayType())
return ICEDiag(IK_NotICE, E->getBeginLoc());
return NoDiag();
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 0a22f7372a..14c9b59926 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -953,20 +953,18 @@ ExprResult Parser::ParseBuiltinPtrauthTypeDiscriminator()
{
/// [OBJC] '\@encode' '(' type-name ')'
/// [OBJC] objc-string-literal
/// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
-/// [C++11] simple-type-specifier braced-init-list [C++11
5.2.3]
-/// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
-/// [C++11] typename-specifier braced-init-list [C++11
5.2.3]
-/// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
-/// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
-/// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
-/// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
-/// [C++] 'typeid' '(' expression ')' [C++ 5.2p1]
-/// [C++] 'typeid' '(' type-id ')'[C++ 5.2p1]
-/// [C++] 'this' [C++ 9.3.2]
-/// [G++] unary-type-trait '(' type-id ')'
-/// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO]
-/// [EMBT] array-type-trait '(' type-id ',' integer ')'
-/// [clang] '^' block-literal
+/// [C++11] simple-type-specifier braced-init-list [C++11 5.2.3] [C++]
+/// typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3] [C++11]
+/// typename-specifier braced-init-list [C++11 5.2.3] [C++]
+/// 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] [C++]
+/// 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] [C++]
+/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] [C++]
+/// 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] [C++]
+/// 'typeid' '(' expression ')' [C++ 5.2p1] [C++]
+/// 'typeid' '(' type-id ')'[C++ 5.2p1] [C++]
+/// 'this' [C++ 9.3.2] [G++] unary-type-trait '(' type-id ')' [G++]
+/// binary-type-trait '(' type-id ',' type-id ')' [TODO] [EMBT]
+/// array-type-trait '(' type-id ',' integer ')' [clang] '^' block-literal
///
/// constant: [C99 6.4.4]
/// integer-constant
``
https://github.com/llvm/llvm-project/pull/133125
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C2y] Implement WG14 N3369 and N3469 (_Countof) (PR #133125)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/133125 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
