aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-12-01 15:10:30 -0700
committerMartin Sebor <msebor@redhat.com>2020-12-01 15:11:23 -0700
commitb76f83e3859f738809d3aa8bd9dc14e10fc40e24 (patch)
treecea67a727e59839591dffa2a523f0e4552f2eea3 /gcc
parentc7e2ef13149791be24bc563428fcb864e770d843 (diff)
downloadgcc-b76f83e3859f738809d3aa8bd9dc14e10fc40e24.zip
gcc-b76f83e3859f738809d3aa8bd9dc14e10fc40e24.tar.gz
gcc-b76f83e3859f738809d3aa8bd9dc14e10fc40e24.tar.bz2
PR middle-end/97595 - bogus -Wstringop-overflow due to DECL_SIZE_UNIT underreporting field size
gcc/ChangeLog: PR middle-end/97595 * tree.c (component_ref_size): Fail when DECL_SIZE != TYPE_SIZE. * tree.h (DECL_SIZE, TYPE_SIZE): Update comment. gcc/testsuite/ChangeLog: PR middle-end/97595 * g++.dg/warn/Warray-bounds-14.C: New test. * g++.dg/warn/Wstringop-overflow-6.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.dg/warn/Warray-bounds-14.C25
-rw-r--r--gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C8
-rw-r--r--gcc/tree.c12
-rw-r--r--gcc/tree.h10
4 files changed, 49 insertions, 6 deletions
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-14.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-14.C
new file mode 100644
index 0000000..0812f83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-14.C
@@ -0,0 +1,25 @@
+/* PR middle-end/97595 - bogus -Wstringop-overflow due to DECL_SIZE_UNIT
+ underreporting field size
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+struct A { char a[32]; };
+struct B: virtual A { };
+struct C: B { };
+
+struct D
+{
+ B &b;
+ D (B&);
+};
+
+D::D (B &b): b (b) { } // { dg-bogus "-Warray-bounds" }
+
+void f (void*);
+
+void g ()
+{
+ C c;
+ D d (c);
+ f (&d);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C
new file mode 100644
index 0000000..8173e60
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C
@@ -0,0 +1,8 @@
+/* PR middle-end/97595 - bogus -Wstringop-overflow due to DECL_SIZE_UNIT
+ underreporting field size
+ { dg-do compile { target c++11 } }
+ { dg-options "-O2 -Wall -Wsystem-headers" } */
+
+#include <iostream>
+
+template void std::basic_iostream<char>::swap (basic_iostream&);
diff --git a/gcc/tree.c b/gcc/tree.c
index d6ba553..52a145d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13740,9 +13740,9 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
{
gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
- special_array_member arkbuf;
+ special_array_member sambuf;
if (!sam)
- sam = &arkbuf;
+ sam = &sambuf;
*sam = special_array_member::none;
/* The object/argument referenced by the COMPONENT_REF and its type. */
@@ -13756,7 +13756,13 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
{
tree memtype = TREE_TYPE (member);
if (TREE_CODE (memtype) != ARRAY_TYPE)
- return memsize;
+ /* DECL_SIZE may be less than TYPE_SIZE in C++ when referring
+ to the type of a class with a virtual base which doesn't
+ reflect the size of the virtual's members (see pr97595).
+ If that's the case fail for now and implement something
+ more robust in the future. */
+ return (tree_int_cst_equal (memsize, TYPE_SIZE_UNIT (memtype))
+ ? memsize : NULL_TREE);
bool trailing = array_at_struct_end_p (ref);
bool zero_length = integer_zerop (memsize);
diff --git a/gcc/tree.h b/gcc/tree.h
index 078919b..ecdb11e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1987,8 +1987,10 @@ class auto_suppress_location_wrappers
so they must be checked as well. */
#define TYPE_UID(NODE) (TYPE_CHECK (NODE)->type_common.uid)
-/* Type size in bits as a tree expression. Need not be constant
- and may be null. */
+/* Type size in bits as a tree expression. Need not be constant and may
+ be greater than TYPE_SIZE for a C++ FIELD_DECL representing a base
+ class subobject with its own virtual base classes (which are laid out
+ separately). */
#define TYPE_SIZE(NODE) (TYPE_CHECK (NODE)->type_common.size)
/* Likewise, type size in bytes. */
#define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type_common.size_unit)
@@ -2521,7 +2523,9 @@ extern tree vector_element_bits_tree (const_tree);
#define DECL_INITIAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.initial)
/* Holds the size of the datum, in bits, as a tree expression.
- Need not be constant and may be null. */
+ Need not be constant and may be null. May be less than TYPE_SIZE
+ for a C++ FIELD_DECL representing a base class subobject with its
+ own virtual base classes (which are laid out separately). */
#define DECL_SIZE(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.size)
/* Likewise for the size in bytes. */
#define DECL_SIZE_UNIT(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.size_unit)