[clang] cdfa15d - Revert "[clang] Introduce -fstrict-flex-arrays=<n> for stricter handling of flexible arrays"

Vitaly Buka via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 27 14:03:21 PDT 2022


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: }
 }
+
+ at interface FlexibleArray2 {
+ at public
+  char chars[0];
+}
+ at end
+ at implementation FlexibleArray2 {
+ at public
+  char chars2[0];
+}
+ at 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: }
+}
+
+ at interface FlexibleArray3 {
+ at public
+  char chars[0];
+}
+ at end
+ at implementation FlexibleArray3 {
+ at public
+  int i;
+}
+ at 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)}}
-}


        


More information about the cfe-commits mailing list