diff options
author | Martin Sebor <msebor@redhat.com> | 2022-01-14 11:13:08 -0700 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2022-01-14 11:13:08 -0700 |
commit | 72332337e3d8acbb21398b8d123f1bfe77a8327e (patch) | |
tree | 94b31c445e4d8804a4bd5e3abc3b2d63fec14e82 /gcc/pointer-query.cc | |
parent | 1e6294bb15d2169147c7838f89a9168980b94b47 (diff) | |
download | gcc-72332337e3d8acbb21398b8d123f1bfe77a8327e.zip gcc-72332337e3d8acbb21398b8d123f1bfe77a8327e.tar.gz gcc-72332337e3d8acbb21398b8d123f1bfe77a8327e.tar.bz2 |
Use enclosing object size if it's smaller than member [PR 101475].
Resolves:
PR middle-end/101475 - missing -Wstringop-overflow storing a compound literal
gcc/ChangeLog:
PR middle-end/101475
* pointer-query.cc (handle_component_ref): Use the size of
the enclosing object if it's smaller than the member.
gcc/testsuite/ChangeLog:
PR middle-end/101475
* gcc.dg/Wstringop-overflow-15.c: Remove xfails.
* gcc.dg/Wstringop-overflow-68.c: Adjust, remove xfails.
* gcc.dg/Wstringop-overflow-88.c: New test.
Diffstat (limited to 'gcc/pointer-query.cc')
-rw-r--r-- | gcc/pointer-query.cc | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index 1efe7e0..9f932e9 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -1914,36 +1914,41 @@ handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype, gcc_assert (TREE_CODE (cref) == COMPONENT_REF); const tree base = TREE_OPERAND (cref, 0); + const tree field = TREE_OPERAND (cref, 1); + access_ref base_ref = *pref; + + /* Unconditionally determine the size of the base object (it could + be smaller than the referenced member when the object is stored + in a buffer with an insufficient size). */ + if (!compute_objsize_r (base, stmt, addr, 0, &base_ref, snlim, qry)) + return false; + + /* Add the offset of the member to the offset into the object computed + so far. */ + tree offset = byte_position (field); + if (TREE_CODE (offset) == INTEGER_CST) + base_ref.add_offset (wi::to_offset (offset)); + else + base_ref.add_max_offset (); + + if (!base_ref.ref) + /* PREF->REF may have been already set to an SSA_NAME earlier + to provide better context for diagnostics. In that case, + leave it unchanged. */ + base_ref.ref = base; + const tree base_type = TREE_TYPE (base); if (TREE_CODE (base_type) == UNION_TYPE) /* In accesses through union types consider the entire unions rather than just their members. */ ostype = 0; - tree field = TREE_OPERAND (cref, 1); - if (ostype == 0) { /* In OSTYPE zero (for raw memory functions like memcpy), use the maximum size instead if the identity of the enclosing object cannot be determined. */ - if (!compute_objsize_r (base, stmt, addr, ostype, pref, snlim, qry)) - return false; - - /* Otherwise, use the size of the enclosing object and add - the offset of the member to the offset computed so far. */ - tree offset = byte_position (field); - if (TREE_CODE (offset) == INTEGER_CST) - pref->add_offset (wi::to_offset (offset)); - else - pref->add_max_offset (); - - if (!pref->ref) - /* PREF->REF may have been already set to an SSA_NAME earlier - to provide better context for diagnostics. In that case, - leave it unchanged. */ - pref->ref = base; - + *pref = base_ref; return true; } @@ -1958,6 +1963,11 @@ handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype, } set_component_ref_size (cref, pref); + + if (base_ref.size_remaining () < pref->size_remaining ()) + /* Use the base object if it's smaller than the member. */ + *pref = base_ref; + return true; } |