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@+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@+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@+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@+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@+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@+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@+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@+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@+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@+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@+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@+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;
 };
 


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to