aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaBoundsSafety.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaBoundsSafety.cpp')
-rw-r--r--clang/lib/Sema/SemaBoundsSafety.cpp23
1 files changed, 20 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp
index 39ab136..de9adf8 100644
--- a/clang/lib/Sema/SemaBoundsSafety.cpp
+++ b/clang/lib/Sema/SemaBoundsSafety.cpp
@@ -132,9 +132,23 @@ bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes,
// `BoundsSafetyCheckUseOfCountAttrPtr`
//
// * When the pointee type is always an incomplete type (e.g.
- // `void`) the attribute is disallowed by this method because we know the
- // type can never be completed so there's no reason to allow it.
- InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE;
+ // `void` in strict C mode) the attribute is disallowed by this method
+ // because we know the type can never be completed so there's no reason
+ // to allow it.
+ //
+ // 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).
+ bool IsVoidPtr = PointeeTy->isVoidType();
+ if (IsVoidPtr) {
+ // Emit a warning that this is a GNU extension.
+ Diag(FD->getBeginLoc(), diag::ext_gnu_counted_by_void_ptr) << Kind;
+ Diag(FD->getBeginLoc(), diag::note_gnu_counted_by_void_ptr_use_sized_by)
+ << Kind;
+ assert(InvalidTypeKind == CountedByInvalidPointeeTypeKind::VALID);
+ } else {
+ InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE;
+ }
} else if (PointeeTy->isSizelessType()) {
InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS;
} else if (PointeeTy->isFunctionType()) {
@@ -272,6 +286,9 @@ GetCountedByAttrOnIncompletePointee(QualType Ty, NamedDecl **ND) {
if (!PointeeTy->isIncompleteType(ND))
return {};
+ if (PointeeTy->isVoidType())
+ return {};
+
return {CATy, PointeeTy};
}