The improved detection of accesses to interior zero-length arrays
fails to consider the case when the array is a member of a union.
Such accesses are documented as supported so warning for them is
not expected. The attached patch adjusts the component_ref_size
function to return the size of the enclosing union instead of
the member array.
The VRP bit of the patch remove a couple of redundant tests and
unreachable blocks from the check_mem_ref function. The change
is not directly related to the fix except that I noticed them
while working on it and it seems safe either to include in this
patch or commit on its own.
Tested on x86_64-linux.
Martin
PR middle-end/94940 - spurious -Warray-bounds for a zero length array member of union
gcc/testsuite/ChangeLog:
PR middle-end/94940
* gcc.dg/Warray-bounds-61.c: New test.
gcc/ChangeLog:
PR middle-end/94940
* tree-vrp.c (vrp_prop::check_mem_ref): Remove unreachable code.
* tree.c (component_ref_size): Correct the handling or array members
of unions.
Drop a pointless test.
Rename a local variable.
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-61.c b/gcc/testsuite/gcc.dg/Warray-bounds-61.c
new file mode 100644
index 000..5b66cdc0aab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-61.c
@@ -0,0 +1,190 @@
+/* PR middle-end/94940 - spurious -Warray-bounds for a zero length array
+ member of union
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+extern int n;
+
+extern union Ua3_a0 {
+ int a3[3];
+ int a2[2]; // can only alias a3[0 - 2]
+ int a1[1]; // can alias all of the union
+ int a0[0]; // ditto
+} ua3_a0;
+
+void test_ua3_ua0_a0 (int i)
+{
+ ua3_a0.a0[0] = 0; // { dg-bogus "\\\[-Warray-bounds" }
+ ua3_a0.a0[1] = 0; // { dg-bogus "\\\[-Warray-bounds" }
+ ua3_a0.a0[2] = 0; // { dg-bogus "\\\[-Warray-bounds" }
+ ua3_a0.a0[3] = 0; // { dg-warning "\\\[-Warray-bounds" }
+ ua3_a0.a0[4] = 0; // { dg-warning "\\\[-Warray-bounds" }
+ ua3_a0.a0[i] = 0; // { dg-bogus "\\\[-Warray-bounds" }
+
+ if (i < __LINE__)
+i = 5;
+ ua3_a0.a0[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
+
+ if (i > -1)
+i = -1;
+ ua3_a0.a0[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
+}
+
+void test_ua3_ua0_a1 (int i)
+{
+ /* Abusing one-element array members the same way as those of
+ length zero is discouraged but so far acceted without warnings.
+ This should change at some point. */
+
+ ua3_a0.a1[0] = 0;
+ ua3_a0.a1[1] = 0;
+ ua3_a0.a1[2] = 0;
+ ua3_a0.a1[3] = 0; // { dg-warning "\\\[-Warray-bounds" }
+ ua3_a0.a1[i] = 0;
+
+ if (i > -1)
+i = -1;
+ ua3_a0.a1[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
+
+ if (i < 7)
+i = 7;
+ ua3_a0.a1[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
+}
+
+void test_ua3_ua0_a2 (int i)
+{
+ ua3_a0.a2[0] = 0;
+ ua3_a0.a2[1] = 0;
+ ua3_a0.a2[2] = 0; // { dg-warning "\\\[-Warray-bounds" }
+ ua3_a0.a2[i] = 0;
+
+ if (i < __LINE__)
+i = __LINE__;
+ ua3_a0.a2[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
+
+ if (i > -1)
+i = -1;
+ ua3_a0.a2[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
+}
+
+
+extern union Ua2_a3 {
+ int a2[2]; // can only alias a3[0 - 1]
+ int a3[3];
+} ua2_a3;
+
+void test_ua2_ua3 (int i)
+{
+ ua2_a3.a2[0] = 0; // { dg-bogus "\\\[-Warray-bounds" }
+ ua2_a3.a2[1] = 0; // { dg-bogus "\\\[-Warray-bounds" }
+ ua2_a3.a2[2] = 0; // { dg-warning "\\\[-Warray-bounds" }
+ ua2_a3.a2[i] = 0;
+
+ if (i < __LINE__)
+i = __LINE__;
+ ua2_a3.a2[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
+}
+
+
+extern struct SUa2_a0 {
+ union Ua2_a0 {
+int a2[2];
+int a0[0];
+ } u;
+} sua2_a0;
+
+void test_sua2_sua0 (int i)
+{
+ n += sua2_a0.u.a0[0];
+ n += sua2_a0.u.a0[1];
+ n += sua2_a0.u.a0[2]; // { dg-warning "\\\[-Warray-bounds" }
+ n += sua2_a0.u.a0[i];
+
+ if (i < __LINE__)
+i = __LINE__;
+ n += sua2_a0.u.a0[i]; // { dg-warning "\\\[-Warray-bounds" }
+}
+
+void test_sua2_sua0_ptr (int i)
+{
+ union Ua2_a0 *p = _a0.u;
+
+ n += p->a0[0];
+ n += p->a0[1];
+ n += p->a0[2]; // { dg-warning "\\\[-Warray-bounds" }
+ n += p->a0[i];
+}
+
+
+extern struct SUSa3_a0 {
+ union USa3_a0 {
+struct {
+ int a3[3];
+} s;
+int a2[2];// can alias s.a3[0 - 2]
+int a1[1];// can alias s.a3[0 - 2]
+int a0[0];// can alias s.a3[0]
+ } u;
+} susa3_ua0;
+
+void test_susa3_sua0 (int i, int j)
+{
+ n += susa3_ua0.u.a0[0];
+ n += susa3_ua0.u.a0[1];
+ n += susa3_ua0.u.a0[2];
+ n += susa3_ua0.u.a0[3]; // { dg-warning "\\\[-Warray-bounds" }
+}
+
+void test_susa3_sua0_ptr (int i, int j)
+{
+ union USa3_a0 *p = _ua0.u;
+ n += p->a0[0];
+ n += p->a0[1];
+ n += p->a0[2];
+ n += p->a0[3]; // {