diff options
Diffstat (limited to 'clang/lib/Sema/SemaBoundsSafety.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaBoundsSafety.cpp | 23 |
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}; } |
