Similar to the problem reported for -Wstringop-overflow in pr98266
and already fixed, -Warray-bounds is also susceptible to false
positives in assignments and copies involving virtual inheritance.
Because the two warnings don't share code yet (hopefully in GCC 12)
the attached patch adds its own workaround for this problem to
gimple-array-bounds.cc, this one slightly more crude because of
the limited insight the array bounds checking has into the checked
expressions.

Tested on x86_64-linux.

Martin
PR middle-end/98266 - bogus array subscript is partly outside array bounds on virtual inheritance

gcc/ChangeLog:

	PR middle-end/98266
	* gimple-array-bounds.cc (array_bounds_checker::check_array_bounds):
	Avoid checking references involving artificial members.

gcc/testsuite/ChangeLog:

	PR middle-end/98266
	* g++.dg/warn/Warray-bounds-15.C: New test.

diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 2576556f76b..413deacece4 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -911,8 +911,16 @@ array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
   else if (TREE_CODE (t) == ADDR_EXPR)
     {
       checker->check_addr_expr (location, t);
-      *walk_subtree = FALSE;
+      *walk_subtree = false;
     }
+  else if (TREE_CODE (t) == COMPONENT_REF
+	   && TREE_CODE (TREE_OPERAND (t, 0)) == MEM_REF
+	   && DECL_ARTIFICIAL (TREE_OPERAND (t, 1)))
+    /* Hack: Skip MEM_REF checking for artificial members to avoid false
+       positives for C++ classes with virtual bases.  See pr98266 and
+       pr97595.  */
+    *walk_subtree = false;
+
   /* Propagate the no-warning bit to the outer expression.  */
   if (warned)
     TREE_NO_WARNING (t) = true;
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-15.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-15.C
new file mode 100644
index 00000000000..eb75527dc3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-15.C
@@ -0,0 +1,30 @@
+/* PR middle-end/98266 - bogus array subscript is partly outside array
+   bounds on virtual inheritance
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#if __cplusplus < 201103L
+#  define noexcept   throw ()
+#endif
+
+struct A
+{
+  virtual ~A () noexcept;
+  const char* s;
+};
+
+struct B: virtual A { };
+struct C: virtual B { };
+struct D: virtual A { };      // { dg-bogus "\\\[-Warray-bounds" }
+
+struct E: virtual B, virtual D
+{
+  E (const char*);
+};
+
+void f (E);
+
+void g ()
+{
+  f (E (""));
+}

Reply via email to