[clang] 7f93ae8 - [clang] Implement -fstrict-flex-arrays=3
Bill Wendling via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 27 10:50:18 PDT 2022
Author: Bill Wendling
Date: 2022-10-27T10:50:04-07:00
New Revision: 7f93ae808634e33e4dc9bce753c909aa5f9a6eb4
URL: https://github.com/llvm/llvm-project/commit/7f93ae808634e33e4dc9bce753c909aa5f9a6eb4
DIFF: https://github.com/llvm/llvm-project/commit/7f93ae808634e33e4dc9bce753c909aa5f9a6eb4.diff
LOG: [clang] Implement -fstrict-flex-arrays=3
The -fstrict-flex-arrays=3 is the most restrictive type of flex arrays.
No number, including 0, is allowed in the FAM. In the cases where a "0"
is used, the resulting size is the same as if a zero-sized object were
substituted.
This is needed for proper _FORTIFY_SOURCE coverage in the Linux kernel,
among other reasons. So while the only reason for specifying a
zero-length array at the end of a structure is for specify a FAM,
treating it as such will cause _FORTIFY_SOURCE not to work correctly;
__builtin_object_size will report -1 instead of 0 for a destination
buffer size to keep any kernel internals from using the deprecated
members as fake FAMs.
For example:
struct broken {
int foo;
int fake_fam[0];
struct something oops;
};
There have been bugs where the above struct was created because "oops"
was added after "fake_fam" by someone not realizing. Under
__FORTIFY_SOURCE, doing:
memcpy(p->fake_fam, src, len);
raises no warnings when __builtin_object_size(p->fake_fam, 1) returns -1
and may stomp on "oops."
Omitting a warning when using the (invalid) zero-length array is how GCC
treats -fstrict-flex-arrays=3. A warning in that situation is likely an
irritant, because requesting this option level is explicitly requesting
this behavior.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836
Differential Revision: https://reviews.llvm.org/D134902
Added:
Modified:
clang/docs/ReleaseNotes.rst
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
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4a2f1f62a6bed..9d4738b64bd82 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -391,9 +391,27 @@ New Compiler Flags
`::operator new(size_t, std::aligned_val_t, nothrow_t)` if there is
`get_return_object_on_allocation_failure`. We feel this is more consistent
with the intention.
+
- Added ``--no-default-config`` to disable automatically loading configuration
files using default paths.
+- Added the new level, ``3``, to the ``-fstrict-flex-arrays=`` flag. The new
+ level is the strict, standards-conforming mode for flexible array members. It
+ recognizes only incomplete arrays as flexible array members (which is how the
+ feature is defined by the C standard).
+
+ .. code-block:: c
+
+ struct foo {
+ int a;
+ int b[]; // Flexible array member.
+ };
+
+ struct bar {
+ int a;
+ int b[0]; // NOT a flexible array member.
+ };
+
Deprecated Compiler Flags
-------------------------
- ``-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang``
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index a7903855222f6..30c96c101377c 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -377,7 +377,7 @@ class LangOptions : public LangOptionsBase {
/// 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:
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0a7de89206cb8..bc30ca9deb8a1 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1151,11 +1151,11 @@ 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">,
+ 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",
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 739851c843996..83e09988d47c2 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -214,11 +214,15 @@ bool Expr::isFlexibleArrayMemberLike(
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;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 80541e077d4e5..34e75723b3f30 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11635,17 +11635,31 @@ 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.
- 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);
}
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index e4235c4e65117..0b504c3d452d7 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -798,7 +798,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
const FAMKind StrictFlexArraysLevel =
Ctx.getLangOpts().getStrictFlexArraysLevel();
if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete ||
- StrictFlexArraysLevel == FAMKind::Incomplete)
+ StrictFlexArraysLevel == FAMKind::IncompleteOnly)
return false;
const AnalyzerOptions &Opts = SVB.getAnalyzerOptions();
diff --git a/clang/test/CodeGen/bounds-checking-fam.c b/clang/test/CodeGen/bounds-checking-fam.c
index 2442e727e2ee4..ae211c49ca1f5 100644
--- a/clang/test/CodeGen/bounds-checking-fam.c
+++ b/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 @@ int test_incomplete(struct Incomplete *p, int i) {
// 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 @@ int test_zero(struct Zero *p, int i) {
// 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 @@ 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(
+ // CHECK-STRICT-3: call void @__ubsan_handle_out_of_bounds_abort(
return p->a[i] + (p->a)[i];
}
@@ -68,6 +73,7 @@ int test_three(struct Three *p, int i) {
// 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 @@ int test_uzero(union uZero *p, int i) {
// 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 @@ int test_uone(union uOne *p, int i) {
// 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 @@ int test_utwo(union uTwo *p, int i) {
// 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 @@ int test_uthree(union uThree *p, int i) {
// 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 @@ int test_macro(struct Macro *p, int i) {
// 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];
}
diff --git a/clang/test/CodeGen/object-size-flex-array.c b/clang/test/CodeGen/object-size-flex-array.c
index 83c0bd634605d..a05aa9a20731e 100644
--- a/clang/test/CodeGen/object-size-flex-array.c
+++ b/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 @@ typedef struct {
// 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 @@ typedef struct {
// 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);
}
diff --git a/clang/test/Sema/array-bounds-ptr-arith.c b/clang/test/Sema/array-bounds-ptr-arith.c
index 974e420aa9e42..28d9a5ac7a827 100644
--- a/clang/test/Sema/array-bounds-ptr-arith.c
+++ b/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{
diff --git a/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp b/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp
index 639c072a849b2..35bc558d3f5b4 100644
--- a/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp
+++ b/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 @@ void test(t *s2) {
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 @@ void test1(t1 *s2) {
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]')}}
}
More information about the cfe-commits
mailing list