================ @@ -8663,31 +8663,95 @@ static const RecordDecl *GetEnclosingNamedOrTopAnonRecord(const FieldDecl *FD) { return RD; } -static bool -CheckCountExpr(Sema &S, FieldDecl *FD, Expr *E, - llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls) { +enum class CountedByInvalidPointeeTypeKind { + INCOMPLETE, + SIZELESS, + FUNCTION, + FLEXIBLE_ARRAY_MEMBER, + VALID, +}; + +static bool CheckCountedByAttrOnField( + Sema &S, FieldDecl *FD, Expr *E, + llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls) { + // Check the context the attribute is used in + if (FD->getParent()->isUnion()) { S.Diag(FD->getBeginLoc(), diag::err_counted_by_attr_in_union) << FD->getSourceRange(); return true; } - if (!E->getType()->isIntegerType() || E->getType()->isBooleanType()) { - S.Diag(E->getBeginLoc(), diag::err_counted_by_attr_argument_not_integer) - << E->getSourceRange(); + const auto FieldTy = FD->getType(); + if (!FieldTy->isArrayType() && !FieldTy->isPointerType()) { + S.Diag(FD->getBeginLoc(), + diag::err_counted_by_attr_not_on_ptr_or_flexible_array_member) + << FD->getLocation(); return true; } LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = LangOptions::StrictFlexArraysLevelKind::IncompleteOnly; - - if (!Decl::isFlexibleArrayMemberLike(S.getASTContext(), FD, FD->getType(), + if (FieldTy->isArrayType() && + !Decl::isFlexibleArrayMemberLike(S.getASTContext(), FD, FieldTy, StrictFlexArraysLevel, true)) { - // The "counted_by" attribute must be on a flexible array member. - SourceRange SR = FD->getLocation(); - S.Diag(SR.getBegin(), - diag::err_counted_by_attr_not_on_flexible_array_member) - << SR; + S.Diag(FD->getBeginLoc(), + diag::err_counted_by_attr_on_array_not_flexible_array_member) ---------------- hnrklssn wrote:
I believe the question is not why only flexible array members are allowed the attribute, but why only incomplete arrays are. Some old projects use this as syntax as incomplete array: ``` struct S { int len; char fam[0]; }; ``` Would converting the above to an incomplete array like this be an issue in those projects? It seems to me that if you're introducing `__counted_by`, removing any old integer constant isn't much more extra work. ``` struct S { int len; char fam[__counted_by(len)]; }; ``` The reason is that a complete array already has a bound, which we use for bounds checking with `-fbounds-safety` enabled. In fact, an array parameter like this will decay into a `int * __counted_by(len)` pointer: ``` void foo(int len, int arr[len]); ``` If you allow annotating these arrays with `__counted_by` also, you effectively end up with two separate sources of bounds info. https://github.com/llvm/llvm-project/pull/93121 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits