mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 22:16:05 +00:00
[clang] Rework IsTailPaddedMemberArray into isFlexibleArrayMemberExpr
This fixes a bunch of FIXME within IsTailPaddedMemberArray related code. As a side effect, this now also triggers a warning when trying to access a "struct hack" member with an index above address space index range. Differential Revision: https://reviews.llvm.org/D133108
This commit is contained in:
parent
2e9118f1e4
commit
dad36245a5
@ -208,6 +208,8 @@ Improvements to Clang's diagnostics
|
||||
underlying type is ``long long`` or ``unsigned long long`` as an extension in
|
||||
C89 mode . Clang previously only diagnosed if the literal had an explicit
|
||||
``LL`` suffix.
|
||||
- Clang now correctly diagnoses index that refers past the last possible element
|
||||
of FAM-like arrays.
|
||||
|
||||
Non-comprehensive list of changes in this release
|
||||
-------------------------------------------------
|
||||
|
@ -15898,17 +15898,24 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
|
||||
<< TRange << Op->getSourceRange();
|
||||
}
|
||||
|
||||
/// Check whether this array fits the idiom of a size-one tail padded
|
||||
/// array member of a struct.
|
||||
/// Check whether this array fits the idiom of a flexible array member,
|
||||
/// depending on the value of -fstrict-flex-array.
|
||||
///
|
||||
/// We avoid emitting out-of-bounds access warnings for such arrays as they are
|
||||
/// commonly used to emulate flexible arrays in C89 code.
|
||||
static bool IsTailPaddedMemberArray(Sema &S, const llvm::APInt &Size,
|
||||
/// We avoid emitting out-of-bounds access warnings for such arrays.
|
||||
static bool isFlexibleArrayMemberExpr(Sema &S, const Expr *E,
|
||||
const NamedDecl *ND,
|
||||
unsigned StrictFlexArraysLevel) {
|
||||
|
||||
if (!ND)
|
||||
return false;
|
||||
|
||||
const ConstantArrayType *ArrayTy =
|
||||
S.Context.getAsConstantArrayType(E->getType());
|
||||
llvm::APInt Size = ArrayTy->getSize();
|
||||
|
||||
if (Size == 0)
|
||||
return true;
|
||||
|
||||
// FIXME: While the default -fstrict-flex-arrays=0 permits Size>1 trailing
|
||||
// arrays to be treated as flexible-array-members, we still emit diagnostics
|
||||
// as if they are not. Pending further discussion...
|
||||
@ -15974,9 +15981,19 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
|
||||
const ConstantArrayType *ArrayTy =
|
||||
Context.getAsConstantArrayType(BaseExpr->getType());
|
||||
|
||||
unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays;
|
||||
|
||||
const NamedDecl *ND = nullptr;
|
||||
if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
|
||||
ND = DRE->getDecl();
|
||||
else if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
|
||||
ND = ME->getMemberDecl();
|
||||
|
||||
const Type *BaseType =
|
||||
ArrayTy == nullptr ? nullptr : ArrayTy->getElementType().getTypePtr();
|
||||
bool IsUnboundedArray = (BaseType == nullptr);
|
||||
bool IsUnboundedArray =
|
||||
BaseType == nullptr ||
|
||||
isFlexibleArrayMemberExpr(*this, BaseExpr, ND, StrictFlexArraysLevel);
|
||||
if (EffectiveType->isDependentType() ||
|
||||
(!IsUnboundedArray && BaseType->isDependentType()))
|
||||
return;
|
||||
@ -15991,12 +16008,6 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
|
||||
index = -index;
|
||||
}
|
||||
|
||||
const NamedDecl *ND = nullptr;
|
||||
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
|
||||
ND = DRE->getDecl();
|
||||
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
|
||||
ND = ME->getMemberDecl();
|
||||
|
||||
if (IsUnboundedArray) {
|
||||
if (EffectiveType->isFunctionType())
|
||||
return;
|
||||
@ -16074,17 +16085,10 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
|
||||
// example). In this case we have no information about whether the array
|
||||
// access exceeds the array bounds. However we can still diagnose an array
|
||||
// access which precedes the array bounds.
|
||||
//
|
||||
// FIXME: this check should be redundant with the IsUnboundedArray check
|
||||
// above.
|
||||
if (BaseType->isIncompleteType())
|
||||
return;
|
||||
|
||||
// FIXME: this check should be used to set IsUnboundedArray from the
|
||||
// beginning.
|
||||
llvm::APInt size = ArrayTy->getSize();
|
||||
if (!size.isStrictlyPositive())
|
||||
return;
|
||||
|
||||
if (BaseType != EffectiveType) {
|
||||
// Make sure we're comparing apples to apples when comparing index to size
|
||||
@ -16114,11 +16118,6 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
|
||||
if (AllowOnePastEnd ? index.ule(size) : index.ult(size))
|
||||
return;
|
||||
|
||||
// Also don't warn for Flexible Array Member emulation.
|
||||
const unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays;
|
||||
if (IsTailPaddedMemberArray(*this, size, ND, StrictFlexArraysLevel))
|
||||
return;
|
||||
|
||||
// Suppress the warning if the subscript expression (as identified by the
|
||||
// ']' location) and the index expression are both from macro expansions
|
||||
// within a system header.
|
||||
|
@ -84,3 +84,33 @@ void pr50741(void) {
|
||||
void func() {
|
||||
func + 0xdead000000000000UL; // no crash
|
||||
}
|
||||
|
||||
struct {
|
||||
int _;
|
||||
char tail[]; // addr16-note {{declared here}} addr32-note {{declared here}}
|
||||
} fam;
|
||||
|
||||
struct {
|
||||
int _;
|
||||
char tail[0]; // addr16-note {{declared here}} addr32-note {{declared here}}
|
||||
} fam0;
|
||||
|
||||
struct {
|
||||
int _;
|
||||
char tail[1]; // addr16-note {{declared here}} addr32-note {{declared here}}
|
||||
} fam1;
|
||||
|
||||
void fam_ily() {
|
||||
++fam.tail[7073650413200313099];
|
||||
// addr16-warning@-1 {{array index 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 8-bit (1-byte) elements (max possible 65536 elements)}}
|
||||
// addr32-warning@-2 {{array index 7073650413200313099 refers past the last possible element for an array in 32-bit address space containing 8-bit (1-byte) elements (max possible 4294967296 elements)}}
|
||||
// No warning for addr64 because the array index is inbound in that case.
|
||||
++fam0.tail[7073650413200313099];
|
||||
// addr16-warning@-1 {{array index 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 8-bit (1-byte) elements (max possible 65536 elements)}}
|
||||
// addr32-warning@-2 {{array index 7073650413200313099 refers past the last possible element for an array in 32-bit address space containing 8-bit (1-byte) elements (max possible 4294967296 elements)}}
|
||||
// No warning for addr64 because the array index is inbound in that case.
|
||||
++fam1.tail[7073650413200313099];
|
||||
// addr16-warning@-1 {{array index 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 8-bit (1-byte) elements (max possible 65536 elements)}}
|
||||
// addr32-warning@-2 {{array index 7073650413200313099 refers past the last possible element for an array in 32-bit address space containing 8-bit (1-byte) elements (max possible 4294967296 elements)}}
|
||||
// No warning for addr64 because the array index is inbound in that case.
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user