On 8/3/20 10:58 PM, Paul Smith wrote:
On Mon, 2020-08-03 at 17:02 -0600, Martin Sebor wrote:
If the code is designed to treat Node sort of like a struct with
a flexible array member I would suggest to make that explicit by
adding a zero-element array member to Node and using it to access
other memory. E.g., add:
unsigned char data[0];
as the last member of Node and change getPayload to:
PAYLOAD& getPayload() {
return *(reinterpret_cast<PAYLOAD*>(data) +
Node::actualSize(_keyLength, alignof(PAYLOAD)));
}
Thanks Martin; I suspected it was something like that. However, I
haven't been able to get a workaround to work.
My understanding is that you suggest replacing:
struct {} key;
with:
unsigned char key[0];
Yes (I said add but replacing it is what you would probably want
but see below).
in Node. And I think you have a paren in the wrong place in the
getPayLoad() example above; shouldn't it be:
return *(reinterpret_cast<PAYLOAD*>(data +
Node::actualSize(_keyLength, alignof(PAYLOAD))));
(that is, the size should be added to data then the whole thing cast).
However, even trying this I still get the same failures:
stringop.cpp: In function 'void applyTo(LeafNode*)':
stringop.cpp:37:33: error: writing 1 byte into a region of size 0
[-Werror=stringop-overflow=]
37 | void markUpdate() { flags() |= UPDATE; }
| ~~~~~~~~^~~~~~~~~
stringop.cpp:15:19: note: at offset 0 to object 'Node::key' with size 0
declared here
15 | unsigned char key[0];
| ^~~
cc1plus: all warnings being treated as errors
Were you able to get this working and I just am not understanding what
you mean?
The suggested change avoids the warning with trunk but not with
GCC 10. I suspect the warning in this case has been removed in
the bug fix for pr95353.
But looking more carefully at the test case, I would actually
expect the warning even with the zero-length array because when
it's in a base class it's not considered the same as a flexible
array member.
In general, it's not safe to access a trailing member of a struct
(or class) outside its bounds in an object of which is a member
of another class because when the latter is followed by another
member, accesses to the two alias one another. GCC assumes that
doesn't happen.
In other words, what the code in the test case does is not safe
and I would recommend to find a different way (e.g. avoid deriving
from Node).
Martin