[clang] 4b455a9 - [BoundsSafety][Sema] Allow `sized_by`/`sized_by_or_null` on pointers to structs with a flexible array member (#209603)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 15 02:40:49 PDT 2026
Author: Dan Liew
Date: 2026-07-15T10:40:44+01:00
New Revision: 4b455a91141d59ace3a29870c885f5f5e4ff0506
URL: https://github.com/llvm/llvm-project/commit/4b455a91141d59ace3a29870c885f5f5e4ff0506
DIFF: https://github.com/llvm/llvm-project/commit/4b455a91141d59ace3a29870c885f5f5e4ff0506.diff
LOG: [BoundsSafety][Sema] Allow `sized_by`/`sized_by_or_null` on pointers to structs with a flexible array member (#209603)
`Sema::CheckCountedByAttrOnField()` in `SemaBoundsSafety.cpp` rejects
the `counted_by` family of attributes when the pointee is a struct that
contains a flexible array member (FAM). For example:
```
struct has_unannotated_fam {
int count;
int buffer[];
};
struct on_member_pointer_struct_with_fam {
int size;
struct has_unannotated_fam *objects __counted_by(size);
};
```
This restriction makes sense for `counted_by`/`counted_by_or_null`
because the size of a struct with a FAM is not statically known, so the
count of elements cannot be used to compute the size of the buffer.
However, the same check was incorrectly applied to `sized_by` and
`sized_by_or_null`. Unlike `counted_by`, these attributes describe the
size of the buffer in *bytes* rather than in *elements*, so the pointee
size is irrelevant and there is no ambiguity. Previously the following
would be rejected:
```
struct on_member_pointer_struct_with_fam {
int size;
struct has_unannotated_fam *objects __sized_by(size);
};
```
with the diagnostic:
```
error: 'sized_by' cannot be applied to a pointer with pointee of unknown
size because 'struct has_unannotated_fam' is a struct type with a
flexible array member
```
This patch guards the FAM check with `!CountInBytes` so that it only
applies to `counted_by`/`counted_by_or_null`. `sized_by` and
`sized_by_or_null` on such pointers are now correctly accepted.
The obsolete `expected-error` directives in the affected `sized_by` and
`sized_by_or_null` Sema tests are removed, turning those cases into
positive tests.
Assisted-by: Claude Code
rdar://182226884
Added:
Modified:
clang/docs/ReleaseNotes.md
clang/lib/Sema/SemaBoundsSafety.cpp
clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c
clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c
clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c
clang/test/Sema/attr-sized-by-struct-ptrs.c
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index e61455acc12a4..e31871c9c9340 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -134,6 +134,13 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
#### Bug Fixes to Attribute Support
+- The `counted_by`/`counted_by_or_null` diagnostic that rejects a pointer whose
+ pointee is a struct with a flexible array member (e.g.
+ ``struct with_fam * __sized_by(size) ptr;``) was incorrectly also applied to
+ the `sized_by`/`sized_by_or_null` attributes. Because `sized_by` and
+ `sized_by_or_null` describe the size in bytes rather than a count of elements,
+ they are now correctly accepted on such pointers.
+
#### Bug Fixes to C++ Support
#### Bug Fixes to AST Handling
diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp
index b01250ccd0ffc..6cfa505d3dc77 100644
--- a/clang/lib/Sema/SemaBoundsSafety.cpp
+++ b/clang/lib/Sema/SemaBoundsSafety.cpp
@@ -152,7 +152,8 @@ bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes,
InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS;
} else if (PointeeTy->isFunctionType()) {
InvalidTypeKind = CountedByInvalidPointeeTypeKind::FUNCTION;
- } else if (PointeeTy->isStructureTypeWithFlexibleArrayMember()) {
+ } else if (PointeeTy->isStructureTypeWithFlexibleArrayMember() &&
+ !CountInBytes) {
if (FieldTy->isArrayType() && !getLangOpts().BoundsSafety) {
// This is a workaround for the Linux kernel that has already adopted
// `counted_by` on a FAM where the pointee is a struct with a FAM. This
diff --git a/clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c b/clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c
index 07f8801787d66..cfdf3407332c9 100644
--- a/clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c
+++ b/clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c
@@ -66,7 +66,6 @@ struct has_unannotated_vla {
};
struct on_member_pointer_struct_with_vla {
- // expected-error at +1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
struct has_unannotated_vla* objects __sized_by(size);
int size;
};
@@ -78,7 +77,6 @@ struct has_annotated_vla {
};
struct on_member_pointer_struct_with_annotated_vla {
- // expected-error at +1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
struct has_annotated_vla* objects __sized_by(size);
int size;
};
diff --git a/clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c b/clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c
index afe5f0af28083..b726a9b005b9b 100644
--- a/clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c
+++ b/clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c
@@ -66,7 +66,6 @@ struct has_unannotated_vla {
};
struct on_member_pointer_struct_with_vla {
- // expected-error at +1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
struct has_unannotated_vla* objects __sized_by_or_null(size);
int size;
};
@@ -78,7 +77,6 @@ struct has_annotated_vla {
};
struct on_member_pointer_struct_with_annotated_vla {
- // expected-error at +1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
struct has_annotated_vla* objects __sized_by_or_null(size);
int size;
};
diff --git a/clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c b/clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c
index 4200c9275a180..82819e5cf43ff 100644
--- a/clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c
+++ b/clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c
@@ -69,7 +69,6 @@ struct has_unannotated_vla {
struct on_member_pointer_struct_with_vla {
int size;
// we know the size so this is fine for tracking size, however indexing would be an issue
- // expected-error at +1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
struct has_unannotated_vla* objects __sized_by_or_null(size);
};
@@ -81,7 +80,6 @@ struct has_annotated_vla {
struct on_member_pointer_struct_with_annotated_vla {
int size;
// we know the size so this is fine for tracking size, however indexing would be an issue
- // expected-error at +1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
struct has_annotated_vla* objects __sized_by_or_null(size);
};
@@ -160,13 +158,11 @@ struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
struct on_member_pointer_struct_with_vla_ty_pos {
int size;
- // expected-error at +1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
struct has_unannotated_vla *__sized_by_or_null(size) objects;
};
struct on_member_pointer_struct_with_annotated_vla_ty_pos {
int size;
- // expected-error at +1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
struct has_annotated_vla* __sized_by_or_null(size) objects;
};
diff --git a/clang/test/Sema/attr-sized-by-struct-ptrs.c b/clang/test/Sema/attr-sized-by-struct-ptrs.c
index 07373b247d0f7..6dc76b8bc7081 100644
--- a/clang/test/Sema/attr-sized-by-struct-ptrs.c
+++ b/clang/test/Sema/attr-sized-by-struct-ptrs.c
@@ -69,7 +69,6 @@ struct has_unannotated_vla {
struct on_member_pointer_struct_with_vla {
int size;
// we know the size so this is fine for tracking size, however indexing would be an issue
- // expected-error at +1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
struct has_unannotated_vla* objects __sized_by(size);
};
@@ -81,7 +80,6 @@ struct has_annotated_vla {
struct on_member_pointer_struct_with_annotated_vla {
int size;
// we know the size so this is fine for tracking size, however indexing would be an issue
- // expected-error at +1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
struct has_annotated_vla* objects __sized_by(size);
};
@@ -160,13 +158,11 @@ struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
struct on_member_pointer_struct_with_vla_ty_pos {
int size;
- // expected-error at +1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}}
struct has_unannotated_vla *__sized_by(size) objects;
};
struct on_member_pointer_struct_with_annotated_vla_ty_pos {
int size;
- // expected-error at +1{{'sized_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}}
struct has_annotated_vla* __sized_by(size) objects;
};
More information about the cfe-commits
mailing list