[llvm-branch-commits] [BoundsSafety][NFC] Add counted_by type-shape validation helper (PR #224557)
Mohammed Ashraf via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 30 09:48:08 PDT 2026
================
@@ -49,6 +77,90 @@ enum class CountedByInvalidPointeeTypeKind {
VALID,
};
+bool Sema::ValidateBoundsAttrTypeShape(QualType Ty, SourceLocation AttrLoc,
+ SourceRange AttrRange,
+ BoundsAttrFlags &Flags,
+ StringRef AttrSpelling, bool AllowRedecl,
+ Expr *AttrArg) {
+ // The downstream leaf runs a `hasBoundsSafetyAttributes()`-gated
+ // `checkBoundsAttrTypeConflictsAndMisc` preamble and an `ended_by` early
+ // path; both depend on machinery (`DynamicRangePointerType`,
+ // `ValueTerminatedType`, the `err_bounds_safety_*` diagnostics) that does not
+ // exist here, so they are the omitted bounds-safety arms. The rest matches.
+ BoundsAttributedType::BoundsAttrKind Kind = getBoundsAttrKind(Flags);
+
+ // counted_by/sized_by: must be pointer or array.
+ if (!Ty->isPointerType() && !Ty->isArrayType()) {
+ Diag(AttrLoc, diag::err_count_attr_not_on_ptr_or_flexible_array_member)
+ << Kind << 0;
+ return false;
+ }
+
+ // Arrays with sized_by or _or_null variants are not allowed under the
+ // non -fbounds-safety path; emit the "did you mean to use 'counted_by'" hint.
+ if (!getLangOpts().hasBoundsSafetyAttributes() && Ty->isArrayType() &&
+ (Flags.CountInBytes || Flags.OrNull)) {
+ Diag(AttrLoc, diag::err_count_attr_not_on_ptr_or_flexible_array_member)
+ << Kind << /*suggest counted_by*/ 1;
+ return false;
+ }
+
+ // Pointee/element type validation.
+ QualType PointeeTy;
+ int SelectPtrOrArr;
+ if (Ty->isPointerType()) {
+ PointeeTy = Ty->getPointeeType();
+ SelectPtrOrArr = 0;
+ } else {
+ const ArrayType *AT = getASTContext().getAsArrayType(Ty);
+ PointeeTy = AT->getElementType();
+ SelectPtrOrArr = 1;
+ }
+
+ auto InvalidTypeKind = CountedByInvalidPointeeTypeKind::VALID;
+ bool ShouldWarn = false;
+ if (!Flags.CountInBytes && PointeeTy->isAlwaysIncompleteType()) {
+ // Exception: void has an implicit size of 1 byte for pointer arithmetic
+ // (following GNU convention). Therefore, counted_by on void* is allowed
+ // and behaves equivalently to sized_by (treating the count as bytes).
+ if (PointeeTy->isVoidType() && !getLangOpts().hasBoundsSafetyAttributes()) {
+ // Emit a warning that this is a GNU extension.
+ Diag(AttrLoc, diag::ext_gnu_counted_by_void_ptr) << Kind;
+ Diag(AttrLoc, diag::note_gnu_counted_by_void_ptr_use_sized_by) << Kind;
+ Flags.CountInBytes = true;
+ return true;
+ }
+ InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE;
+ } else if (PointeeTy->isSizelessType()) {
+ InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS;
+ } else if (PointeeTy->isFunctionType()) {
+ InvalidTypeKind = CountedByInvalidPointeeTypeKind::FUNCTION;
+ } else if (!Flags.CountInBytes &&
+ PointeeTy->isStructureTypeWithFlexibleArrayMember()) {
+ if (Ty->isArrayType() && !getLangOpts().BoundsSafety) {
----------------
Holo-xy wrote:
@rapidsna I have kept it. let me know if you think we should handle it like downstream.
https://github.com/llvm/llvm-project/pull/224557
More information about the llvm-branch-commits
mailing list