[clang] [BoundsSafety] Allow 'counted_by' attribute on pointers in structs in C (PR #90786)
Dan Liew via cfe-commits
cfe-commits at lists.llvm.org
Fri May 3 10:27:02 PDT 2024
================
@@ -8588,31 +8588,71 @@ 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)
+ << FD->getLocation();
+ return true;
+ }
+
+ if (FieldTy->isPointerType()) {
----------------
delcypher wrote:
Good catch!
## Flexible array member
```
struct Has_VLA {
int count;
char buffer[] __counted_by(count);
};
struct Test {
int count;
struct Has_VLA Arr[] __counted_by(count);
};
```
There's no diagnostic here currently. I think the code above is something we should disallow (at least for `-fbounds-safety`). I'll adjust the patch to disallow this.
@isanbard Is the above code pattern something you actually want to support? In `-fbounds-safety` we disallow it because it means computing the bounds of `Arr` is not constant time because the size of `Has_VLA` is not a compile time constant. To compute the bounds of `Arr` at runtime it would require walking every `Has_VLA` object in `Arr` to get its `count` field. That seems expensive and is also at risk of running into a race condition (i.e. the size of a VLA changes while the bounds are being computed).
## Incomplete type
```
struct Test {
int count;
void Arr[] __counted_by(count);
};
```
We already have these diagnostics:
```
tmp/arr_sizeless_ty.c:5:13: error: array has incomplete element type 'void'
5 | void Arr[] __counted_by(count);
| ^
tmp/arr_sizeless_ty.c:5:5: error: 'counted_by' only applies to pointers or C99 flexible array members
5 | void Arr[] __counted_by(count);
| ^ ~~~
2 errors generated.
```
I don't think we need to add another.
## Sizeless types
```
struct Test {
int count;
__SVInt8_t Arr[] __counted_by(count);
};
```
We already have these diagnostics:
```
tmp/arr_sizeless_ty.c:5:19: error: array has sizeless element type '__SVInt8_t'
5 | __SVInt8_t Arr[] __counted_by(count);
| ^
tmp/arr_sizeless_ty.c:5:5: error: 'counted_by' only applies to pointers or C99 flexible array members
5 | __SVInt8_t Arr[] __counted_by(count);
| ^ ~~~
2 errors generated.
```
I don't think we need to add another.
## Function Type
```
typedef void(foo_fn)(int);
struct Test {
int count;
foo_fn Arr[] __counted_by(count);
};
```
We already have these diagnostics:
```
tmp/arr_sizeless_ty.c:7:15: error: 'Arr' declared as array of functions of type 'foo_fn' (aka 'void (int)')
7 | foo_fn Arr[] __counted_by(count);
| ^
tmp/arr_sizeless_ty.c:7:5: error: 'counted_by' only applies to pointers or C99 flexible array members
7 | foo_fn Arr[] __counted_by(count);
| ^ ~~~
2 errors generated.
```
I don't think we need to add another.
https://github.com/llvm/llvm-project/pull/90786
More information about the cfe-commits
mailing list