diff options
author | Martin Sebor <msebor@redhat.com> | 2020-12-01 15:10:30 -0700 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-12-01 15:11:23 -0700 |
commit | b76f83e3859f738809d3aa8bd9dc14e10fc40e24 (patch) | |
tree | cea67a727e59839591dffa2a523f0e4552f2eea3 /gcc | |
parent | c7e2ef13149791be24bc563428fcb864e770d843 (diff) | |
download | gcc-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.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C | 8 | ||||
-rw-r--r-- | gcc/tree.c | 12 | ||||
-rw-r--r-- | gcc/tree.h | 10 |
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&); @@ -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); @@ -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) |