void updated this revision to Diff 469805.
void added a comment.

Integrate the new flag level into the FAM predicate.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134902/new/

https://reviews.llvm.org/D134902

Files:
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/AST/Expr.cpp
  clang/lib/AST/ExprConstant.cpp
  clang/lib/StaticAnalyzer/Core/MemRegion.cpp
  clang/test/CodeGen/bounds-checking-fam.c
  clang/test/CodeGen/object-size-flex-array.c
  clang/test/Sema/array-bounds-ptr-arith.c
  clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp

Index: clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp
===================================================================
--- clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp
+++ clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify=relaxed -fstrict-flex-arrays=1 %s
-// RUN: %clang_cc1 -verify=relaxed,strict -fstrict-flex-arrays=2 %s
+// RUN: %clang_cc1 -verify=relaxed                    -fstrict-flex-arrays=1 %s
+// RUN: %clang_cc1 -verify=relaxed,strict             -fstrict-flex-arrays=2 %s
+// RUN: %clang_cc1 -verify=relaxed,strict,very-strict -fstrict-flex-arrays=3 %s
 
 // We cannot know for sure the size of a flexible array.
 struct t {
@@ -10,7 +11,7 @@
   s2->a[2] = 0; // no-warning
 }
 
-// Under -fstrict-flex-arrays={1,2} `a` is not a flexible array
+// Under -fstrict-flex-arrays={1,2,3} `a` is not a flexible array
 struct t0 {
   int f;
   int a[10]; // relaxed-note {{array 'a' declared here}}
@@ -29,11 +30,11 @@
   s2->a[2] = 0; // strict-warning {{array index 2 is past the end of the array (that has type 'int[1]')}}
 }
 
-// Under -fstrict-flex-arrays={1,2} `a` is a flexible array.
+// Under -fstrict-flex-arrays={1,2} `a` is a flexible array, but not under -fstrict-flex-arrays=3.
 struct t2 {
   int f;
-  int a[0];
+  int a[0]; // very-strict-note {{array 'a' declared here}}
 };
 void test1(t2 *s2) {
-  s2->a[2] = 0; // no-warning
+  s2->a[2] = 0; // very-strict-warning {{array index 2 is past the end of the array (that has type 'int[0]')}}
 }
Index: clang/test/Sema/array-bounds-ptr-arith.c
===================================================================
--- clang/test/Sema/array-bounds-ptr-arith.c
+++ clang/test/Sema/array-bounds-ptr-arith.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -verify=expected        -Warray-bounds-pointer-arithmetic %s
 // RUN: %clang_cc1 -verify=expected        -Warray-bounds-pointer-arithmetic %s -fstrict-flex-arrays=0
 // RUN: %clang_cc1 -verify=expected,strict -Warray-bounds-pointer-arithmetic %s -fstrict-flex-arrays=2
+// RUN: %clang_cc1 -verify=expected,strict -Warray-bounds-pointer-arithmetic %s -fstrict-flex-arrays=3
 
 // Test case from PR10615
 struct ext2_super_block{
Index: clang/test/CodeGen/object-size-flex-array.c
===================================================================
--- clang/test/CodeGen/object-size-flex-array.c
+++ clang/test/CodeGen/object-size-flex-array.c
@@ -1,6 +1,8 @@
-// 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
+// RUN: %clang                        -target x86_64 -O2 -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-NO-STRICT %s
+// RUN: %clang -fstrict-flex-arrays=0 -target x86_64 -O2 -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-0 %s
+// RUN: %clang -fstrict-flex-arrays=1 -target x86_64 -O2 -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-1 %s
+// RUN: %clang -fstrict-flex-arrays=2 -target x86_64 -O2 -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-2 %s
+// RUN: %clang -fstrict-flex-arrays=3 -target x86_64 -O2 -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-STRICT-3 %s
 
 #define OBJECT_SIZE_BUILTIN __builtin_object_size
 
@@ -26,36 +28,86 @@
 
 // CHECK-LABEL: @bar(
 unsigned bar(foo_t *f) {
-  // CHECK-STRICT-0: ret i32 %
-  // CHECK-STRICT-1: ret i32 %
-  // CHECK-STRICT-2: ret i32 %
+  // CHECK-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
+  // CHECK-STRICT-1: ret i32 -1
+  // CHECK-STRICT-2: ret i32 -1
+  // CHECK-STRICT-3: ret i32 -1
   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-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
+  // CHECK-STRICT-1: ret i32 -1
+  // CHECK-STRICT-2: ret i32 -1
+  // 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-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
+  // CHECK-STRICT-1: ret i32 -1
   // 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-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
   // 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);
 }
 
+#define DYNAMIC_OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size
+
+// CHECK-LABEL: @dyn_bar(
+unsigned dyn_bar(foo_t *f) {
+  // CHECK-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
+  // CHECK-STRICT-1: ret i32 -1
+  // CHECK-STRICT-2: ret i32 -1
+  // CHECK-STRICT-3: ret i32 -1
+  return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CHECK-LABEL: @dyn_bar0(
+unsigned dyn_bar0(foo0_t *f) {
+  // CHECK-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
+  // CHECK-STRICT-1: ret i32 -1
+  // CHECK-STRICT-2: ret i32 -1
+  // CHECK-STRICT-3: ret i32 0
+  return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CHECK-LABEL: @dyn_bar1(
+unsigned dyn_bar1(foo1_t *f) {
+  // CHECK-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
+  // CHECK-STRICT-1: ret i32 -1
+  // CHECK-STRICT-2: ret i32 8
+  // CHECK-STRICT-3: ret i32 8
+  return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CHECK-LABEL: @dyn_bar2(
+unsigned dyn_bar2(foo2_t *f) {
+  // CHECK-NO-STRICT: ret i32 -1
+  // CHECK-STRICT-0: ret i32 -1
+  // CHECK-STRICT-1: ret i32 16
+  // CHECK-STRICT-2: ret i32 16
+  // CHECK-STRICT-3: ret i32 16
+  return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
 // Also checks for non-trailing flex-array like members
 
 typedef struct {
@@ -75,24 +127,30 @@
 
 // CHECK-LABEL: @babar0(
 unsigned babar0(foofoo0_t *f) {
+  // CHECK-NO-STRICT: ret i32 0
   // 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-NO-STRICT: ret i32 8
   // 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-NO-STRICT: ret i32 16
   // 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);
 }
Index: clang/test/CodeGen/bounds-checking-fam.c
===================================================================
--- clang/test/CodeGen/bounds-checking-fam.c
+++ clang/test/CodeGen/bounds-checking-fam.c
@@ -5,6 +5,8 @@
 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=1 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1,CXX
 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=2 -fsanitize=array-bounds        %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2
 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=2 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2,CXX
+// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds        %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-3
+// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-3,CXX
 // Before flexible array member was added to C99, many projects use a
 // one-element array as the last member of a structure as an alternative.
 // E.g. https://github.com/python/cpython/issues/84301
@@ -36,6 +38,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1-NOT: @__ubsan
   // CHECK-STRICT-2-NOT: @__ubsan
+  // CHECK-STRICT-3-NOT: @__ubsan
   return p->a[i] + (p->a)[i];
 }
 
@@ -44,6 +47,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1-NOT: @__ubsan
   // CHECK-STRICT-2-NOT: @__ubsan
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
@@ -52,6 +56,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1-NOT: @__ubsan
   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
@@ -68,6 +73,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1:     call void @__ubsan_handle_out_of_bounds_abort(
   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
@@ -89,6 +95,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1-NOT: @__ubsan
   // CHECK-STRICT-2-NOT: @__ubsan
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
@@ -97,6 +104,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1-NOT: @__ubsan
   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
@@ -105,6 +113,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1:     call void @__ubsan_handle_out_of_bounds_abort(
   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
@@ -113,6 +122,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1:     call void @__ubsan_handle_out_of_bounds_abort(
   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
@@ -126,6 +136,7 @@
   // CHECK-STRICT-0-NOT: @__ubsan
   // CHECK-STRICT-1-NOT: @__ubsan
   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
+  // CHECK-STRICT-3:     call void @__ubsan_handle_out_of_bounds_abort(
   return p->a[i] + (p->a)[i];
 }
 
Index: clang/lib/StaticAnalyzer/Core/MemRegion.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -798,7 +798,7 @@
         const FAMKind StrictFlexArraysLevel =
           Ctx.getLangOpts().getStrictFlexArraysLevel();
         if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete ||
-            StrictFlexArraysLevel == FAMKind::Incomplete)
+            StrictFlexArraysLevel == FAMKind::IncompleteOnly)
           return false;
 
         const AnalyzerOptions &Opts = SVB.getAnalyzerOptions();
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -11621,17 +11621,31 @@
   //   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.
-  using FAMKind = LangOptions::StrictFlexArraysLevelKind;
-  FAMKind StrictFlexArraysLevel = Ctx.getLangOpts().getStrictFlexArraysLevel();
+  auto isFlexibleArrayMember = [&] {
+    using FAMKind = LangOptions::StrictFlexArraysLevelKind;
+    FAMKind StrictFlexArraysLevel =
+        Ctx.getLangOpts().getStrictFlexArraysLevel();
+
+    if (Designator.isMostDerivedAnUnsizedArray())
+      return true;
+
+    if (StrictFlexArraysLevel == FAMKind::Default)
+      return true;
+
+    if (Designator.getMostDerivedArraySize() == 0 &&
+        StrictFlexArraysLevel != FAMKind::IncompleteOnly)
+      return true;
+
+    if (Designator.getMostDerivedArraySize() == 1 &&
+        StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
+      return true;
+
+    return false;
+  };
+
   return LVal.InvalidBase &&
          Designator.Entries.size() == Designator.MostDerivedPathLength &&
-         Designator.MostDerivedIsArrayElement &&
-         (Designator.isMostDerivedAnUnsizedArray() ||
-          Designator.getMostDerivedArraySize() == 0 ||
-          (Designator.getMostDerivedArraySize() == 1 &&
-           StrictFlexArraysLevel != FAMKind::Incomplete &&
-           StrictFlexArraysLevel != FAMKind::ZeroOrIncomplete) ||
-          StrictFlexArraysLevel == FAMKind::Default) &&
+         Designator.MostDerivedIsArrayElement && isFlexibleArrayMember() &&
          isDesignatorAtObjectEnd(Ctx, LVal);
 }
 
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -214,11 +214,15 @@
   if (CAT) {
     llvm::APInt Size = CAT->getSize();
 
+    using FAMKind = LangOptions::StrictFlexArraysLevelKind;
+
+    if (StrictFlexArraysLevel == FAMKind::IncompleteOnly)
+      return false;
+
     // GCC extension, only allowed to represent a FAM.
     if (Size == 0)
       return true;
 
-    using FAMKind = LangOptions::StrictFlexArraysLevelKind;
     if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1))
       return false;
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1148,11 +1148,11 @@
   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">,
+  MetaVarName<"<n>">, Values<"0,1,2,3">,
   LangOpts<"StrictFlexArraysLevel">,
   Flags<[CC1Option]>,
   NormalizedValuesScope<"LangOptions::StrictFlexArraysLevelKind">,
-  NormalizedValues<["Default", "OneZeroOrIncomplete", "ZeroOrIncomplete"]>,
+  NormalizedValues<["Default", "OneZeroOrIncomplete", "ZeroOrIncomplete", "IncompleteOnly"]>,
   HelpText<"Enable optimizations based on the strict definition of flexible arrays">,
   MarshallingInfoEnum<LangOpts<"StrictFlexArraysLevel">, "Default">;
 defm apple_pragma_pack : BoolFOption<"apple-pragma-pack",
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -376,7 +376,7 @@
     /// Any trailing array member of undefined or 0 size is a FAM.
     ZeroOrIncomplete = 2,
     /// Any trailing array member of undefined size is a FAM.
-    Incomplete = 3,
+    IncompleteOnly = 3,
   };
 
 public:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to