[llvm-branch-commits] [clang] [BoundsSafety] Support the counted_by family on function parameters (PR #234941)

Dan Liew via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 23 10:50:28 PDT 2026


================
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s
+
+// The counted_by family on a function parameter. The count is parsed where it
+// is written, also with late parsing, so it names a parameter declared before
+// the annotated one.
+
+#define __counted_by(f)  __attribute__((counted_by(f)))
+#define __counted_by_or_null(f)  __attribute__((counted_by_or_null(f)))
+#define __sized_by(f)  __attribute__((sized_by(f)))
+#define __sized_by_or_null(f)  __attribute__((sized_by_or_null(f)))
+
+typedef int *int_ptr;
+int global_count;
+
+//==============================================================================
+// Valid: the count is declared before the annotated pointer
+//==============================================================================
+
+void back_ref(int count, int *__counted_by(count) buf);
+void back_ref_or_null(int count, int *__counted_by_or_null(count) buf);
+void back_ref_sized(int count, void *__sized_by(count) buf);
+void back_ref_sized_or_null(int count, void *__sized_by_or_null(count) buf);
+
+// Two pointers may share a count, but a pointer has only one.
+void two_buffers(int count, int *__counted_by(count) a,
+                 int *__counted_by(count) b);
+// expected-error at +1{{'counted_by' attribute cannot be applied to a pointer that already has a 'counted_by' attribute}}
+void repeated(int n, int m, int *buf __counted_by(n) __counted_by(m));
+
+// Written after the declarator, or in the declaration specifiers.
+void trailing(int count, int *buf __counted_by(count));
+void declspec(int count, int_ptr __counted_by(count) buf);
+
+// The C23 spelling is checked the same way.
+void c23_spelling(int count, int *[[clang::counted_by(count)]] buf);
+
+int sum(int count, int *__counted_by(count) buf) {
+  int total = 0;
+  for (int i = 0; i < count; ++i)
+    total += buf[i];
+  return total;
+}
+
+//==============================================================================
+// The count is parsed where it is written
+//==============================================================================
+
+// expected-error at +1{{use of undeclared identifier 'count'}}
+void fwd_ref(int *__counted_by(count) buf, int count);
+
+//==============================================================================
+// What the count may name
+//==============================================================================
+
+// A parameter of the function, or of an enclosing function declarator.
+void inner(void (*cb)(int len, int *__counted_by(len) p));
+void outer(int n, void (*cb)(int *__counted_by(n) p));
+
+// expected-error at +1{{count expression in function declaration may only reference function parameters}}
+void not_a_param(int *__counted_by(global_count) buf);
+// expected-error at +1{{'counted_by' requires a non-boolean integer type argument}}
+void not_an_integer(float count, int *__counted_by(count) buf);
+// expected-error at +1{{'counted_by' argument must be a simple declaration reference}}
+void not_a_reference(int count, int *__counted_by(count + 1) buf);
----------------
delcypher wrote:

What happens with a nested pointer?

```
void nested_outer(int **__counted_by(global_count) buf);
void nested_inner(int *__counted_by(global_count) * buf);
```

We should probably test them here, even if they don't do the right thing yet.

https://github.com/llvm/llvm-project/pull/234941


More information about the llvm-branch-commits mailing list