On Thu, Sep 21, 2023 at 3:21 PM Jochen Topf <jochen@xxxxxxxxxx> wrote: > > On Thu, Sep 21, 2023 at 10:11:34AM +0100, Jonathan Wakely wrote: > > Date: Thu, 21 Sep 2023 10:11:34 +0100 > > From: Jonathan Wakely <jwakely.gcc@xxxxxxxxx> > > To: Jochen Topf <jochen@xxxxxxxxxx> > > Cc: gcc-help <gcc-help@xxxxxxxxxxx> > > Subject: Re: Problems with -Warray-bounds and -Wstringop-overread > > > > On Thu, 21 Sept 2023, 09:27 Jochen Topf, <jochen@xxxxxxxxxx> wrote: > > > > > Hi! > > > > > > In my C++ code I have been using a pattern to store large and diverse sets > > > of > > > data as follows: > > > > > > * Reserve a block of memory ("the buffer") > > > * Put class X in the beginning of that block (with placement new) > > > * Add extra data after the class in certain formats, for instance lists of > > > 0-terminated strings or lists of (type field, length field, some data) > > > * Repeat with next class X until buffer is full > > > > > > You then know the first instance of class X is at offset 0 in the buffer. > > > The > > > class knows how to access and interpret that extra data beyond its nominal > > > end > > > and it knows how to calculate where the next instance of class X is. So > > > you can > > > access all instance data and iterate over the buffer getting to all the > > > instances of X. > > > > > > If you align everything properly this has always worked well. It means I > > > only > > > need a single memory allocation instead of lots of allocation for bits and > > > pieces and I don't need to store pointers to those bits and pieces, but can > > > derive where they are from the knowledge I have about the structure of > > > those > > > buffers which keeps the data smaller. > > > > > > (In a way this is similar to the pattern of having a zero/one-element > > > array at > > > the end of a struct and storing extra data in that array "beyond the end > > > of the > > > struct", but greatly extended.) > > > > > > Now here is the problem: In the last years GCC has added more and more > > > warnings, specifically -Warray-bounds and -Wstringop-overread that get > > > triggered by my code all over the place because it (understandably) finds > > > that > > > I am accessing stuff outside the class X or some other part of my buffer. > > > > > > I can just disable those warnings, but because that code is in a > > > header-only-library I have to tell every user to disable it or sprinkle my > > > code > > > with pragmas which has its own problems. > > > > > > What are the problems with pragmas? That was going to be my suggestion. > > I had some bad experiences with pragmas between compilers and compiler > versions not understanding some pragmas which meant I had to wrap them > in other pragmas to disable warnings about pragrams that weren't > understood or shenenigans like that. True. But you can still make it somewhat readable, eg.: https://github.com/google/highway/blob/master/hwy/ops/x86_128-inl.h#L25-L30 I see you are using cmake as a build tool. You can take advantage of target_compile_options + PUBLIC to tell your users which flags are required when consuming your header library. > But the bigger problem is in this case that they seem to not work in > some of the cases. I am returning raw pointers from lots of functions > and if I wrap those functions in pragmas that does nothing. Only at the > points where those pointers are used, the warning triggers. But that is > not in the library code any more, but in the users code. So if, for > instance, I want to return a "char *" to one of the strings I am storing > in the buffer, that pointer triggers the warning the first time it is > used. I don't know how I can avoid that warning there. > > > And because GCC has been adding more > > > of those checks over time (or tightening existing checks) I have more > > > places in > > > my code that trigger those warnings with every GCC release and I fear that > > > will > > > go on. > > > > > > My question are: > > > > > > * Is there something "illegal" (against C++ spec) in what I am doing? > > > > > > > Only if you don't do it correctly :-) > > > > * Is there a better way of doing this that avoids triggering those warnings > > > or to tell the compiler that "I know what I am doing"? > > > > > > > That's what the pragmas are for. > > > > It might also be possible to create a compiler firewall with [[gnu::noipa]] > > on some key functions which produce the pointers to the next item in the > > buffer, to stop gcc from analyzing through them. > > I just tested this and at least in the one case I tested it, it did > work, getting rid of the warning where the pragma approach didn't. But > reading through the docs it looks like this disables some optimizations > which doesn't sound great to me. And it says " This attribute is > supported mainly for the purpose of testing the compiler." And it feels > strange that a large "hammer" like this is needed to disable a warning. > > > > (In case you are interested: The code in question is in the libosmium > > > library > > > https://github.com/osmcode/libosmium and is used in all sorts of software > > > that works with OpenStreetMap data.) > > > > > > Jochen > > > -- > > > Jochen Topf jochen@xxxxxxxxxx https://www.jochentopf.com/ > > > +49-351-31778688 > > > > > -- > Jochen Topf jochen@xxxxxxxxxx https://www.jochentopf.com/ +49-351-31778688 -- Mathieu