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
