https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87363

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2018-09-19
                 CC|                            |msebor at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning code tries to avoid duplicate warning by checking and setting
TREE_NO_WARNING.  But because it doesn't have access to the tree node
representing the strlen(arg) call it uses TREE_NO_WARNING(arg).  When the arg
tree node changes for the same strlen(arg) call duplicate warnings aren't
suppressed.

Other than that, since

  When a value is stored in a member of an object of union type, the bytes of
the object representation that do not correspond to that member but do
correspond to other members take unspecified values.

the value of u.z is unspecified after the initialization of the union u in the
test case.

In strlen(u.z) the warning actually considers the value of u.x returned by
string_constant().  This is because the function determines the initializer of
an aggregate subobject by calling get_addr_base_and_unit_offset(), i.e., based
on the subobject's offset.  For the union in the test case, the offset of u.x
is the same as u.z (there is no initializer for u.z and so the values of some
of its bytes are unspecified).

To avoid the warning, string_constant() could be enhanced to detect this case
(i.e., referencing a union member) and give up.  Or, we could consider the
warning a useful reminder for people to avoid relying on unspecified behavior. 
Or we could add a different warning to help point out this sort of buggy code.

To determine the number of non-nul bytes in aggregate object that includes
multiple members, use memchr(&u, 0, sizeof u) instead of abusing strlen.

Reply via email to