Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -15891,17 +15891,24 @@ << 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, - const NamedDecl *ND, - unsigned StrictFlexArraysLevel) { +/// 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... @@ -15967,11 +15974,21 @@ const ConstantArrayType *ArrayTy = Context.getAsConstantArrayType(BaseExpr->getType()); + const unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays; + + const NamedDecl *ND = nullptr; + if (const auto *DRE = dyn_cast(BaseExpr)) + ND = DRE->getDecl(); + else if (const auto *ME = dyn_cast(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())) + !IsUnboundedArray && BaseType->isDependentType()) return; Expr::EvalResult Result; @@ -15984,12 +16001,6 @@ index = -index; } - const NamedDecl *ND = nullptr; - if (const DeclRefExpr *DRE = dyn_cast(BaseExpr)) - ND = DRE->getDecl(); - if (const MemberExpr *ME = dyn_cast(BaseExpr)) - ND = ME->getMemberDecl(); - if (IsUnboundedArray) { if (EffectiveType->isFunctionType()) return; @@ -16067,17 +16078,10 @@ // 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 @@ -16107,11 +16111,6 @@ 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.