Author: Vitaly Buka Date: 2022-06-27T14:03:09-07:00 New Revision: cdfa15da94f06289dcf86173d18b6627f92ac403
URL: https://github.com/llvm/llvm-project/commit/cdfa15da94f06289dcf86173d18b6627f92ac403 DIFF: https://github.com/llvm/llvm-project/commit/cdfa15da94f06289dcf86173d18b6627f92ac403.diff LOG: Revert "[clang] Introduce -fstrict-flex-arrays=<n> for stricter handling of flexible arrays" This reverts D126864 and related fixes. This reverts commit 572b08790a69f955ae0cbb1b4a7d4a215f15dad9. This reverts commit 886715af962de2c92fac4bd37104450345711e4a. Added: Modified: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/include/clang/AST/Expr.h clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h clang/lib/AST/Expr.cpp clang/lib/AST/ExprConstant.cpp clang/lib/CodeGen/CGExpr.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/StaticAnalyzer/Core/MemRegion.cpp clang/test/CodeGen/bounds-checking.c clang/test/CodeGenObjC/ubsan-array-bounds.m clang/test/Sema/array-bounds-ptr-arith.c Removed: clang/test/CodeGen/bounds-checking-fma.c clang/test/CodeGen/object-size-flex-array.c clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp ################################################################################ diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 17892e3461707..7e53f45c59689 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -2639,12 +2639,6 @@ Enable unstable and experimental features .. option:: -fuse-init-array, -fno-use-init-array -.. option:: -fstrict-flex-arrays=<arg>, -fno-strict-flex-arrays - -Control which arrays are considered as flexible arrays members. <arg> -can be 1 (array of size 0, 1 and undefined are considered), 2 (array of size 0 -and undefined are considered) or 3 (only array of undefined size are considered). - .. option:: -fuse-ld=<arg> .. option:: -fuse-line-directives, -fno-use-line-directives diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c73d448459d7c..f8c6aaa069994 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -68,16 +68,11 @@ Major New Features Randomizing structure layout is a C-only feature. -- Clang now supports the ``-fstrict-flex-arrays=<arg>`` option to control which - array bounds lead to flexible array members. The option yields more accurate - ``__builtin_object_size`` and ``__builtin_dynamic_object_size`` results in - most cases but may be overly conservative for some legacy code. - Experimental support for HLSL has been added. The implementation is incomplete and highly experimental. For more information about the ongoing work to support HLSL see the `documentation <https://clang.llvm.org/docs/HLSLSupport.html>`_, or the `GitHub project <https://github.com/orgs/llvm/projects/4>`_. - Bug Fixes --------- - ``CXXNewExpr::getArraySize()`` previously returned a ``llvm::Optional`` diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 392c5bcb1e20a..574d2fad216ea 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -443,16 +443,6 @@ class Expr : public ValueStmt { return (OK == OK_Ordinary || OK == OK_BitField); } - /// True when this expression refers to a flexible array member in a - /// struct. \c StrictFlexArraysLevel controls which array bounds are - /// acceptable for such arrays: - /// - /// - 0 => any array bound, - /// - 1 => [0], [1], [ ] - /// - 2 => [0], [ ] - /// - 3 => [ ] - bool isFlexibleArrayMember(ASTContext &Ctx, int StrictFlexArraysLevel) const; - /// setValueKind - Set the value kind produced by this expression. void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; } diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index ba6ce4e9250f4..c41b5ddc7fa11 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -424,7 +424,6 @@ LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0, LANGOPT(RegisterStaticDestructors, 1, 1, "Register C++ static destructors") LANGOPT(MatrixTypes, 1, 0, "Enable or disable the builtin matrix type") -LANGOPT(StrictFlexArrays, 2, 0, "Rely on strict definition of flexible arrays") COMPATIBLE_VALUE_LANGOPT(MaxTokens, 32, 0, "Max number of tokens per TU or 0") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3682f7cab4824..d379ec8285103 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1140,12 +1140,6 @@ def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group<f_Group>; def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use Apple's kernel extensions ABI">, MarshallingInfoFlag<LangOpts<"AppleKext">>; -def fstrict_flex_arrays_EQ : Joined<["-"], "fstrict-flex-arrays=">,Group<f_Group>, - MetaVarName<"<n>">, Values<"0,1,2,3">, - LangOpts<"StrictFlexArrays">, - Flags<[CC1Option]>, - HelpText<"Enable optimizations based on the strict definition of flexible arrays">, - MarshallingInfoInt<LangOpts<"StrictFlexArrays">>; defm apple_pragma_pack : BoolFOption<"apple-pragma-pack", LangOpts<"ApplePragmaPack">, DefaultFalse, PosFlag<SetTrue, [CC1Option], "Enable Apple gcc-compatible #pragma pack handling">, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 34d44f709883d..2cb9a6a0a0ed6 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -1364,7 +1364,6 @@ class MemRegionManager { ~MemRegionManager(); ASTContext &getContext() { return Ctx; } - const ASTContext &getContext() const { return Ctx; } llvm::BumpPtrAllocator &getAllocator() { return A; } diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index ac1642ef37aca..79d092acccec9 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -203,91 +203,6 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const { return false; } -bool Expr::isFlexibleArrayMember(ASTContext &Ctx, - int StrictFlexArraysLevel) const { - const NamedDecl *ND = nullptr; - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(this)) - ND = DRE->getDecl(); - if (const MemberExpr *ME = dyn_cast<MemberExpr>(this)) - ND = ME->getMemberDecl(); - if (const ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(this)) - ND = RE->getDecl(); - if (!ND) - return false; - - const ConstantArrayType *ArrayTy = Ctx.getAsConstantArrayType(getType()); - - const Type *BaseType = - ArrayTy == nullptr ? nullptr : ArrayTy->getElementType().getTypePtr(); - bool IsUnboundedArray = (BaseType == nullptr); - - if (!IsUnboundedArray) { - llvm::APInt Size = ArrayTy->getSize(); - - switch (StrictFlexArraysLevel) { - case 3: - return false; - case 2: - if (Size != 0) - return false; - break; - case 1: - if (Size.ugt(1)) - return false; - break; - case 0: - break; - default: - llvm_unreachable("Invalid strict flex arrays level"); - } - } - - const FieldDecl *FD = dyn_cast<FieldDecl>(ND); - if (!FD) - return false; - - // Don't consider sizes resulting from macro expansions or template argument - // substitution to form C89 tail-padded arrays. - - TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); - while (TInfo) { - TypeLoc TL = TInfo->getTypeLoc(); - // Look through typedefs. - if (TypedefTypeLoc TTL = TL.getAs<TypedefTypeLoc>()) { - const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); - TInfo = TDL->getTypeSourceInfo(); - continue; - } - if (ConstantArrayTypeLoc CTL = TL.getAs<ConstantArrayTypeLoc>()) { - const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr()); - if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) - return false; - } - break; - } - - const ObjCInterfaceDecl *ID = - dyn_cast<ObjCInterfaceDecl>(FD->getDeclContext()); - const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext()); - if (RD) { - if (RD->isUnion()) - return false; - if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { - if (!CRD->isStandardLayout()) - return false; - } - } else if (!ID) - return false; - - // See if this is the last field decl in the record. - const Decl *D = FD; - while ((D = D->getNextDeclInContext())) - if (isa<FieldDecl>(D)) - return false; - - return true; -} - const ValueDecl * Expr::getAsBuiltinConstantDeclRef(const ASTContext &Context) const { Expr::EvalResult Eval; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index c9ecfb170b040..910f943c00adc 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11592,16 +11592,9 @@ static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) { // conservative with the last element in structs (if it's an array), so our // current behavior is more compatible than an explicit list approach would // be. - int StrictFlexArraysLevel = Ctx.getLangOpts().StrictFlexArrays; return LVal.InvalidBase && Designator.Entries.size() == Designator.MostDerivedPathLength && Designator.MostDerivedIsArrayElement && - (Designator.isMostDerivedAnUnsizedArray() || - (Designator.getMostDerivedArraySize() == 0 && - StrictFlexArraysLevel < 3) || - (Designator.getMostDerivedArraySize() == 1 && - StrictFlexArraysLevel < 2) || - StrictFlexArraysLevel == 0) && isDesignatorAtObjectEnd(Ctx, LVal); } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 0fed82d3e68cc..cbeb6c938bee7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -875,6 +875,44 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, } } +/// Determine whether this expression refers to a flexible array member in a +/// struct. We disable array bounds checks for such members. +static bool isFlexibleArrayMemberExpr(const Expr *E) { + // For compatibility with existing code, we treat arrays of length 0 or + // 1 as flexible array members. + // FIXME: This is inconsistent with the warning code in SemaChecking. Unify + // the two mechanisms. + const ArrayType *AT = E->getType()->castAsArrayTypeUnsafe(); + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { + // FIXME: Sema doesn't treat [1] as a flexible array member if the bound + // was produced by macro expansion. + if (CAT->getSize().ugt(1)) + return false; + } else if (!isa<IncompleteArrayType>(AT)) + return false; + + E = E->IgnoreParens(); + + // A flexible array member must be the last member in the class. + if (const auto *ME = dyn_cast<MemberExpr>(E)) { + // FIXME: If the base type of the member expr is not FD->getParent(), + // this should not be treated as a flexible array member access. + if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) { + // FIXME: Sema doesn't treat a T[1] union member as a flexible array + // member, only a T[0] or T[] member gets that treatment. + if (FD->getParent()->isUnion()) + return true; + RecordDecl::field_iterator FI( + DeclContext::decl_iterator(const_cast<FieldDecl *>(FD))); + return ++FI == FD->getParent()->field_end(); + } + } else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E)) { + return IRE->getDecl()->getNextIvar() == nullptr; + } + + return false; +} + llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E, QualType EltTy) { ASTContext &C = getContext(); @@ -916,11 +954,8 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E, /// If Base is known to point to the start of an array, return the length of /// that array. Return 0 if the length cannot be determined. -static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, - const Expr *Base, - QualType &IndexedType, - ASTContext &Context, - int StrictFlexArraysLevel) { +static llvm::Value *getArrayIndexingBound( + CodeGenFunction &CGF, const Expr *Base, QualType &IndexedType) { // For the vector indexing extension, the bound is the number of elements. if (const VectorType *VT = Base->getType()->getAs<VectorType>()) { IndexedType = Base->getType(); @@ -931,8 +966,7 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, if (const auto *CE = dyn_cast<CastExpr>(Base)) { if (CE->getCastKind() == CK_ArrayToPointerDecay && - !CE->getSubExpr()->IgnoreParens()->isFlexibleArrayMember( - Context, std::max(StrictFlexArraysLevel, 1))) { + !isFlexibleArrayMemberExpr(CE->getSubExpr())) { IndexedType = CE->getSubExpr()->getType(); const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe(); if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) @@ -960,8 +994,7 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, SanitizerScope SanScope(this); QualType IndexedType; - llvm::Value *Bound = getArrayIndexingBound( - *this, Base, IndexedType, getContext(), getLangOpts().StrictFlexArrays); + llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType); if (!Bound) return; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 5142b72a160fb..c9bbdb2ac72e3 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6221,8 +6221,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_funroll_loops, options::OPT_fno_unroll_loops); - Args.AddLastArg(CmdArgs, options::OPT_fstrict_flex_arrays_EQ); - Args.AddLastArg(CmdArgs, options::OPT_pthread); if (Args.hasFlag(options::OPT_mspeculative_load_hardening, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 4635bcc32ab3d..f0f13413c9d7a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -15716,6 +15716,53 @@ 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. +/// +/// 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) { + if (Size != 1 || !ND) return false; + + const FieldDecl *FD = dyn_cast<FieldDecl>(ND); + if (!FD) return false; + + // Don't consider sizes resulting from macro expansions or template argument + // substitution to form C89 tail-padded arrays. + + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); + while (TInfo) { + TypeLoc TL = TInfo->getTypeLoc(); + // Look through typedefs. + if (TypedefTypeLoc TTL = TL.getAs<TypedefTypeLoc>()) { + const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); + TInfo = TDL->getTypeSourceInfo(); + continue; + } + if (ConstantArrayTypeLoc CTL = TL.getAs<ConstantArrayTypeLoc>()) { + const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr()); + if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) + return false; + } + break; + } + + const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext()); + if (!RD) return false; + if (RD->isUnion()) return false; + if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { + if (!CRD->isStandardLayout()) return false; + } + + // See if this is the last field decl in the record. + const Decl *D = FD; + while ((D = D->getNextDeclInContext())) + if (isa<FieldDecl>(D)) + return false; + return true; +} + void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE, bool AllowOnePastEnd, bool IndexNegated) { @@ -15868,9 +15915,10 @@ 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 members. - if (BaseExpr->isFlexibleArrayMember(Context, - getLangOpts().StrictFlexArrays)) + // Also don't warn for arrays of size 1 which are members of some + // structure. These are often used to approximate flexible arrays in C89 + // code. + if (IsTailPaddedMemberArray(*this, size, ND)) return; // Suppress the warning if the subscript expression (as identified by the diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 389223e0b7766..f0cda835e07c2 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -789,9 +789,6 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, if (isa<IncompleteArrayType>(AT)) return true; - if (getContext().getLangOpts().StrictFlexArrays) - return false; - if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { const llvm::APInt &Size = CAT->getSize(); if (Size.isZero()) diff --git a/clang/test/CodeGen/bounds-checking-fma.c b/clang/test/CodeGen/bounds-checking-fma.c deleted file mode 100644 index fbc51dc7a5e19..0000000000000 --- a/clang/test/CodeGen/bounds-checking-fma.c +++ /dev/null @@ -1,42 +0,0 @@ -// REQUIRES: x86-registered-target -// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-0 -// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=array-bounds -fstrict-flex-arrays=1 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1 -// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize=array-bounds -fstrict-flex-arrays=2 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2 - -// Before flexible array member was added to C99, many projects use a -// one-element array as the last emember of a structure as an alternative. -// E.g. https://github.com/python/cpython/issues/94250 -// Suppress such errors with -fstrict-flex-arrays=0. -struct One { - int a[1]; -}; -struct Two { - int a[2]; -}; -struct Three { - int a[3]; -}; - -// CHECK-LABEL: define {{.*}} @test_one( -int test_one(struct One *p, int i) { - // CHECK-STRICT-0-NOT: @__ubsan - // CHECK-STRICT-1-NOT: @__ubsan - // CHECK-STRICT-2: call void @__ubsan_handle_out_of_bounds_abort( - return p->a[i] + (p->a)[i]; -} - -// CHECK-LABEL: define {{.*}} @test_two( -int test_two(struct Two *p, int i) { - // CHECK-STRICT-0: call void @__ubsan_handle_out_of_bounds_abort( - // CHECK-STRICT-1: call void @__ubsan_handle_out_of_bounds_abort( - // CHECK-STRICT-2: call void @__ubsan_handle_out_of_bounds_abort( - return p->a[i] + (p->a)[i]; -} - -// CHECK-LABEL: define {{.*}} @test_three( -int test_three(struct Three *p, int i) { - // CHECK-STRICT-0: call void @__ubsan_handle_out_of_bounds_abort( - // CHECK-STRICT-1: call void @__ubsan_handle_out_of_bounds_abort( - // CHECK-STRICT-2: call void @__ubsan_handle_out_of_bounds_abort( - return p->a[i] + (p->a)[i]; -} diff --git a/clang/test/CodeGen/bounds-checking.c b/clang/test/CodeGen/bounds-checking.c index 62a49fd40d943..ca44adf5a1f27 100644 --- a/clang/test/CodeGen/bounds-checking.c +++ b/clang/test/CodeGen/bounds-checking.c @@ -35,9 +35,8 @@ union U { int a[0]; int b[1]; int c[2]; }; // CHECK-LABEL: define {{.*}} @f4 int f4(union U *u, int i) { - // a and b bounds are treated as flexible array members, but they are inside a union - // and that prevent them from being considered as flexible array members. - // NONLOCAL: @llvm.ubsantrap + // a and b are treated as flexible array members. + // CHECK-NOT: @llvm.ubsantrap return u->a[i] + u->b[i]; // CHECK: } } diff --git a/clang/test/CodeGen/object-size-flex-array.c b/clang/test/CodeGen/object-size-flex-array.c deleted file mode 100644 index 9611485bef7e2..0000000000000 --- a/clang/test/CodeGen/object-size-flex-array.c +++ /dev/null @@ -1,106 +0,0 @@ -// RUN: %clang -fstrict-flex-arrays=3 -target x86_64-apple-darwin -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-3 %s -// RUN: %clang -fstrict-flex-arrays=2 -target x86_64-apple-darwin -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-2 %s -// RUN: %clang -fstrict-flex-arrays=1 -target x86_64-apple-darwin -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-1 %s -// RUN: %clang -fstrict-flex-arrays=0 -target x86_64-apple-darwin -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-0 %s - -#define OBJECT_SIZE_BUILTIN __builtin_object_size - -typedef struct { - float f; - double c[]; -} foo_t; - -typedef struct { - float f; - double c[0]; -} foo0_t; - -typedef struct { - float f; - double c[1]; -} foo1_t; - -typedef struct { - float f; - double c[2]; -} foo2_t; - -// CHECK-LABEL: @bar -unsigned bar(foo_t *f) { - // CHECK-STRICT-0: ret i32 % - // CHECK-STRICT-1: ret i32 % - // CHECK-STRICT-2: ret i32 % - // CHECK-STRICT-3: ret i32 % - return OBJECT_SIZE_BUILTIN(f->c, 1); -} - -// CHECK-LABEL: @bar0 -unsigned bar0(foo0_t *f) { - // CHECK-STRICT-0: ret i32 % - // CHECK-STRICT-1: ret i32 % - // CHECK-STRICT-2: ret i32 % - // CHECK-STRICT-3: ret i32 0 - return OBJECT_SIZE_BUILTIN(f->c, 1); -} - -// CHECK-LABEL: @bar1 -unsigned bar1(foo1_t *f) { - // CHECK-STRICT-0: ret i32 % - // CHECK-STRICT-1: ret i32 % - // CHECK-STRICT-2: ret i32 8 - // CHECK-STRICT-3: ret i32 8 - return OBJECT_SIZE_BUILTIN(f->c, 1); -} - -// CHECK-LABEL: @bar2 -unsigned bar2(foo2_t *f) { - // CHECK-STRICT-0: ret i32 % - // CHECK-STRICT-1: ret i32 16 - // CHECK-STRICT-2: ret i32 16 - // CHECK-STRICT-3: ret i32 16 - return OBJECT_SIZE_BUILTIN(f->c, 1); -} - -// Also checks for non-trailing flex-array like members - -typedef struct { - double c[0]; - float f; -} foofoo0_t; - -typedef struct { - double c[1]; - float f; -} foofoo1_t; - -typedef struct { - double c[2]; - float f; -} foofoo2_t; - -// CHECK-LABEL: @babar0 -unsigned babar0(foofoo0_t *f) { - // CHECK-STRICT-0: ret i32 0 - // CHECK-STRICT-1: ret i32 0 - // CHECK-STRICT-2: ret i32 0 - // CHECK-STRICT-3: ret i32 0 - return OBJECT_SIZE_BUILTIN(f->c, 1); -} - -// CHECK-LABEL: @babar1 -unsigned babar1(foofoo1_t *f) { - // CHECK-STRICT-0: ret i32 8 - // CHECK-STRICT-1: ret i32 8 - // CHECK-STRICT-2: ret i32 8 - // CHECK-STRICT-3: ret i32 8 - return OBJECT_SIZE_BUILTIN(f->c, 1); -} - -// CHECK-LABEL: @babar2 -unsigned babar2(foofoo2_t *f) { - // CHECK-STRICT-0: ret i32 16 - // CHECK-STRICT-1: ret i32 16 - // CHECK-STRICT-2: ret i32 16 - // CHECK-STRICT-3: ret i32 16 - return OBJECT_SIZE_BUILTIN(f->c, 1); -} diff --git a/clang/test/CodeGenObjC/ubsan-array-bounds.m b/clang/test/CodeGenObjC/ubsan-array-bounds.m index ebb7517adca98..38d1eb310d21e 100644 --- a/clang/test/CodeGenObjC/ubsan-array-bounds.m +++ b/clang/test/CodeGenObjC/ubsan-array-bounds.m @@ -14,3 +14,46 @@ char test_FlexibleArray1(FlexibleArray1 *FA1) { return FA1->chars[1]; // CHECK: } } + +@interface FlexibleArray2 { +@public + char chars[0]; +} +@end +@implementation FlexibleArray2 { +@public + char chars2[0]; +} +@end + +// CHECK-LABEL: test_FlexibleArray2_1 +char test_FlexibleArray2_1(FlexibleArray2 *FA2) { + // CHECK: !nosanitize + return FA2->chars[1]; + // CHECK: } +} + +// CHECK-LABEL: test_FlexibleArray2_2 +char test_FlexibleArray2_2(FlexibleArray2 *FA2) { + // CHECK-NOT: !nosanitize + return FA2->chars2[1]; + // CHECK: } +} + +@interface FlexibleArray3 { +@public + char chars[0]; +} +@end +@implementation FlexibleArray3 { +@public + int i; +} +@end + +// CHECK-LABEL: test_FlexibleArray3 +char test_FlexibleArray3(FlexibleArray3 *FA3) { + // CHECK: !nosanitize + return FA3->chars[1]; + // CHECK: } +} diff --git a/clang/test/Sema/array-bounds-ptr-arith.c b/clang/test/Sema/array-bounds-ptr-arith.c index 6ae705a218641..fd2a00e9e8a4b 100644 --- a/clang/test/Sema/array-bounds-ptr-arith.c +++ b/clang/test/Sema/array-bounds-ptr-arith.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -Warray-bounds-pointer-arithmetic -fstrict-flex-arrays=1 %s +// RUN: %clang_cc1 -verify -Warray-bounds-pointer-arithmetic %s // Test case from PR10615 struct ext2_super_block{ @@ -12,3 +12,40 @@ void* broken (struct ext2_super_block *es,int a) { return (void *)es->s_uuid + 80; // expected-warning {{refers past the end of the array}} } + +// Test case reduced from PR11594 +struct S { int n; }; +void pr11594(struct S *s) { + int a[10]; + int *p = a - s->n; +} + +// Test case reduced from <rdar://problem/11387038>. This resulted in +// an assertion failure because of the typedef instead of an explicit +// constant array type. +struct RDar11387038 {}; +typedef struct RDar11387038 RDar11387038Array[1]; +struct RDar11387038_Table { + RDar11387038Array z; +}; +typedef struct RDar11387038_Table * TPtr; +typedef TPtr *TabHandle; +struct RDar11387038_B { TabHandle x; }; +typedef struct RDar11387038_B RDar11387038_B; + +void radar11387038(void) { + RDar11387038_B *pRDar11387038_B; + struct RDar11387038* y = &(*pRDar11387038_B->x)->z[4]; +} + +void pr51682 (void) { + int arr [1]; + switch (0) { + case 0: + break; + case 1: + asm goto (""::"r"(arr[42] >> 1)::failed); // no-warning + break; + } +failed:; +} diff --git a/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp b/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp deleted file mode 100644 index dde683fb5390f..0000000000000 --- a/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// RUN: %clang_cc1 -verify -fstrict-flex-arrays=3 %s - -// We cannot know for sure the size of a flexible array. -void test() { - struct { - int f; - int a[]; - } s2; - s2.a[2] = 0; // no-warning -} - -// Under -fstrict-flex-arrays `a` is not a flexible array. -void test1() { - struct { - int f; - int a[1]; // expected-note {{declared here}} - } s2; - s2.a[2] = 0; // expected-warning 1 {{array index 2 is past the end of the array (which contains 1 element)}} -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits