[clang] [Clang][Docs] Documented sentinel attribute (PR #196088)
Tony Guillot via cfe-commits
cfe-commits at lists.llvm.org
Thu May 28 04:07:17 PDT 2026
https://github.com/to268 updated https://github.com/llvm/llvm-project/pull/196088
>From dd07939ce8128b9d54cca3a4f68fc3f137d9f60b Mon Sep 17 00:00:00 2001
From: Tony Guillot <tony.guillot at protonmail.com>
Date: Wed, 6 May 2026 16:48:40 +0200
Subject: [PATCH 1/4] Documented sentinel attribute
---
clang/include/clang/Basic/Attr.td | 2 +-
clang/include/clang/Basic/AttrDocs.td | 28 +++++++++++++++++++++++++++
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 70b5773f95b08..81993146e6d0c 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3419,7 +3419,7 @@ def Sentinel : InheritableAttr {
let Args = [DefaultIntArgument<"Sentinel", 0>,
DefaultIntArgument<"NullPos", 0>];
// let Subjects = SubjectList<[Function, ObjCMethod, Block, Var]>;
- let Documentation = [Undocumented];
+ let Documentation = [SentinelDocs];
}
def StdCall : DeclOrTypeAttr {
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 87b9053be7cb6..edafc335a1dd1 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -10055,3 +10055,31 @@ different languages to coexist on the same call stack while each interpreting
exceptions according to their own rules.
}];
}
+
+def SentinelDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``sentinel`` attribute can only be applied to variadic functions to
+diagnose each function call that do not pass a sentinel value at the end of the
+argument list. It checks if a null pointer constant exists at the end of the
+argument list by default, or at the (N+1)th position starting from the end when
+an argument is provided.
+
+.. code-block:: c
+
+ #include <stddef.h>
+
+ void foo(const char*, ...) __attribute__((sentinel));
+ void bar(int, ...) __attribute__((sentinel(1)));
+
+ void example() {
+ foo("Example", (void*)0);
+ foo("Another", "example", NULL);
+ foo("Missing", "sentinel"); // Not OK
+
+ bar(1, 2, NULL, 3); // OK: sentinel value at the 2nd to last positon
+ bar(1, 2, 3, nullptr, 4); // OK: `nullptr` is valid in C23
+ bar(1, 2, 3, 4, NULL); // Not OK
+ }
+ }];
+}
>From bc01b2c64936708f7b2fba926bbf8744a2ff8ce2 Mon Sep 17 00:00:00 2001
From: Tony Guillot <tony.guillot at protonmail.com>
Date: Sun, 24 May 2026 19:27:39 +0200
Subject: [PATCH 2/4] Added mention of pointers to variadic functions
---
clang/include/clang/Basic/AttrDocs.td | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index edafc335a1dd1..074c8b3b03244 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9314,8 +9314,8 @@ def HLSLMatrixLayoutDocs : Documentation {
let Category = DocCatVariable;
let Heading = "row_major, column_major";
let Content = [{
-The ``row_major`` and ``column_major`` keywords specify the memory layout
-of an HLSL matrix type.
+The ``row_major`` and ``column_major`` keywords specify the memory layout
+of an HLSL matrix type.
* ``row_major``: Matrices are stored in memory row-by-row.
* ``column_major``: Matrices are stored in memory column-by-column (default).
@@ -10059,11 +10059,11 @@ exceptions according to their own rules.
def SentinelDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
-The ``sentinel`` attribute can only be applied to variadic functions to
-diagnose each function call that do not pass a sentinel value at the end of the
-argument list. It checks if a null pointer constant exists at the end of the
-argument list by default, or at the (N+1)th position starting from the end when
-an argument is provided.
+The ``sentinel`` attribute can be applied to variadic functions and pointers to
+variadic functions, to diagnose each function call that do not pass a sentinel
+value at the end of the argument list. It checks if a null pointer constant
+exists at the end of the argument list by default, or at the (N+1)th position
+starting from the end when an argument is provided.
.. code-block:: c
@@ -10080,6 +10080,9 @@ an argument is provided.
bar(1, 2, NULL, 3); // OK: sentinel value at the 2nd to last positon
bar(1, 2, 3, nullptr, 4); // OK: `nullptr` is valid in C23
bar(1, 2, 3, 4, NULL); // Not OK
+
+ void (*ptr) (int arg, ...) __attribute__ ((__sentinel__));
+ ptr(1, 2, 3, NULL);
}
}];
}
>From a57b4d8123cbfea29ba72e1c3fca0cb36b8eeeb2 Mon Sep 17 00:00:00 2001
From: Tony Guillot <tony.guillot at protonmail.com>
Date: Thu, 28 May 2026 13:04:16 +0200
Subject: [PATCH 3/4] Improved documentation
---
clang/include/clang/Basic/AttrDocs.td | 37 ++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 074c8b3b03244..1d67b54044f40 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -10061,16 +10061,17 @@ def SentinelDocs : Documentation {
let Content = [{
The ``sentinel`` attribute can be applied to variadic functions and pointers to
variadic functions, to diagnose each function call that do not pass a sentinel
-value at the end of the argument list. It checks if a null pointer constant
-exists at the end of the argument list by default, or at the (N+1)th position
-starting from the end when an argument is provided.
+value (a null pointer constant) in the argument list, at the end by default.
+The attribute accepts 2 optional parameters: the first parameter is the
+position of the expected sentinel value, starting from the last parameter which
+defaults to 0, and the second parameter describes whether the last fixed
+parameter is treated as a valid sentinel value when set to 1 (defaults to 0).
+The attribute is also supported with blocks and in Objective-C.
.. code-block:: c
-
- #include <stddef.h>
-
void foo(const char*, ...) __attribute__((sentinel));
void bar(int, ...) __attribute__((sentinel(1)));
+ void baz(const char*, const char*, ...) __attribute__((sentinel(0, 1)));
void example() {
foo("Example", (void*)0);
@@ -10081,8 +10082,32 @@ starting from the end when an argument is provided.
bar(1, 2, 3, nullptr, 4); // OK: `nullptr` is valid in C23
bar(1, 2, 3, 4, NULL); // Not OK
+ baz("Test", "with", "multiple", "args", NULL);
+ baz("One", NULL); // OK: last fixed parameter is a valid sentinel
+
void (*ptr) (int arg, ...) __attribute__ ((__sentinel__));
ptr(1, 2, 3, NULL);
}
+
+.. code-block:: c++
+ struct Ty {
+ int value;
+
+ template<typename T>
+ auto&& foo(T&& val, ...) __attribute__((sentinel(1))) {
+ return std::forward<T>(val);
+ }
+
+ template<class Self>
+ auto&& bar(this Self&& self, ...) __attribute__((sentinel(1))) {
+ return std::forward<Self>(self).value;
+ }
+ };
+
+ void example2() {
+ auto sty = Ty{};
+ sty.foo(1, nullptr, 3);
+ sty.bar(1, nullptr, 3);
+ }
}];
}
>From 0577024e5fcc2927d34aea8943d1c184534c31d3 Mon Sep 17 00:00:00 2001
From: Tony Guillot <tony.guillot at protonmail.com>
Date: Thu, 28 May 2026 13:06:47 +0200
Subject: [PATCH 4/4] Added lambda example
---
clang/include/clang/Basic/AttrDocs.td | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 1d67b54044f40..be1bb3da05abd 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -10108,6 +10108,9 @@ The attribute is also supported with blocks and in Objective-C.
auto sty = Ty{};
sty.foo(1, nullptr, 3);
sty.bar(1, nullptr, 3);
+
+ auto lmbd = [](int a, ...) __attribute__((sentinel)) {};
+ lmbd(1, 2, nullptr);
}
}];
}
More information about the cfe-commits
mailing list