Hi all,
I ran your findings by my agent, and this is what it suggested. I can't
read too much into it because I'm not fluent enough with C++ and its
linking intricacies to validate whether it's findings are correct or not,
but at least it seems to make sense from reading its arguments.

M

Here it is:

Your test is not wrong. The approach cannot work, and neither can the
`-Wl,-plugin-opt=` variant. But there is a form that does work, and I have
measured it on your exact toolchain (Ubuntu 22.04, gcc 11.4.0) as well as on
gcc 15.3.0.

## Why the per-file property is dropped

Under LTO the diagnostic is produced by the LTRANS compilation that
`lto-wrapper` starts at link time, so what matters is the option set
`lto-wrapper` hands to that compilation. It builds that set from two sources
(gcc/lto-wrapper.cc, `run_gcc`):

- `append_compiler_options()` for the options recorded in each object file's
  `.gnu.lto_.opts` section. This one has a hard filter: everything that is
not
  `CL_TARGET` or one of about twenty whitelisted options (`-O`, `-g`,
`-fPIC`,
  `-fcommon`, the `-fdiagnostics-show-*` family, ...) hits `continue` and is
  discarded. `-Wno-stringop-overflow` is neither, so a per-source-file
  `COMPILE_OPTIONS` never reaches LTRANS.
- `append_linker_options()` for the options on the *link* command line. This
  one passes through anything carrying `CL_COMMON`, `CL_TARGET`, `CL_DRIVER`
  or `CL_LTO`.

`Wstringop-overflow=` is declared in gcc/c-family/c.opt as

    C ObjC C++ LTO ObjC++ Joined ... Var(warn_stringop_overflow) ...
Warning ...

Note the `LTO` in that language list: the option has `CL_LTO`, so it
survives
the second filter. That is the whole difference between your test and the
one
below.

`-Wl,-plugin-opt=-Wno-stringop-overflow` goes to the linker plugin, which is
not the thing that runs the diagnostic, so it has no effect either.

## What works

Plain compiler option on the link line of the one target that emits the
warnings. In our tree all 61 (resp. 67) come from the single `librexx.so`
LTO
link, so this is enough, and no other target loses the diagnostic:

```cmake
# after target_link_libraries(rexx ...) at CMakeLists.txt:981
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  target_link_options (rexx PRIVATE -Wno-stringop-overflow)
endif ()

Measured on a pristine checkout of trunk r13196, Release, IPO on:

┌───────────────────┬────────────────────────────────────┬──────────┐
│     toolchain     │            arrangement             │ warnings │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 11.4.0 Ubuntu │ as-is                              │ 67       │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 11.4.0 Ubuntu │ + per-file COMPILE_OPTIONS (yours) │ 67       │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 11.4.0 Ubuntu │ + target_link_options above        │ 0        │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 11.4.0 Ubuntu │ IPO off                            │ 0        │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 15.3.0 Debian │ as-is                              │ 61       │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 15.3.0 Debian │ + per-file COMPILE_OPTIONS         │ 61       │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 15.3.0 Debian │ + target_link_options above        │ 0        │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 15.3.0 Debian │ IPO off                            │ 0        │
├───────────────────┼────────────────────────────────────┼──────────┤
│ gcc 15.3.0 Debian │ IPO off + target_link_options      │ 0        │
└───────────────────┴────────────────────────────────────┴──────────┘

The last row is there to show the flag is inert in a non-LTO build: the log
is
byte-for-byte the same two pre-existing -Wwrite-strings warnings from
cmdparse.cpp, nothing added.

One more reason the per-file property could not have worked: 10 of the 61
warnings on gcc 15 point into headers (NumberStringClass.hpp,
StringClass.hpp),
and a header has no source file property of its own.

Side question: how dangerous is -Wno-stringop-overflow?

Not dangerous in the codegen sense. In c.opt the option is marked Warning
and not Optimization, so it does not enter the per-function optimization
node and cannot change what the compiler emits. It silences a diagnostic and
nothing else.

The cost is the lost detector, and the scope of the loss is small: with
target_link_options it applies to the LTRANS phase of librexx.so only.
Note from the table that an IPO-off build reports zero of these warnings
anyway - the 12 #pragma GCC diagnostic ignored regions already suppress
every
instance the non-LTO compiler finds. So the flag suppresses exactly the
instances that appear only because LTO inlines across translation units,
which
is the set we already decided to ignore. What it also hides is a
hypothetical
genuine cross-module overflow in librexx.so. I think that is an acceptable
trade for one target.

The part I would not wave away: these diagnostics are not purely bogus. A
write past stringData[3] in a char stringData[4] really is out of bounds as
the type system sees it, and gcc 16 has already shown, in the segfault I
reported, that it will act on this class of assumption when it suits the
optimiser. The durable fix is to declare those trailing arrays as flexible
array members so the compiler knows the size is not 4. That is a much larger
change (sizeof and every allocation computation move), I have not tested it,
and it is a separate discussion.

On disabling IPO for gcc < 17

It works, and it is a bigger hammer than the problem needs. gcc 17 is not
released, so the gate turns LTO off for essentially every Linux build for
the
next year or more, to silence a diagnostic that one guarded line silences.

Two things worth having on the record before you decide:

- Disabling IPO does not fix Point 2. The Arch/Manjaro segfault reproduces
  with IPO off, at -O1 and -O2, on gcc 16. It is the sourceNewObject
  lifetime bug from my previous mail, and the two-line change fixes it with
  IPO on.
- What IPO is worth here, measured on Debian gcc 15.3.0, interleaved runs in
  both orders: no run-time difference I can distinguish from noise on a
mixed
  arithmetic/string/method benchmark (0.879-0.901 s with IPO, 0.859-0.883 s
  without), no difference on interpreter start-up, and librexx.so 36 KB
(1.1%)
  smaller with IPO. That is one workload on one machine. If IPO was enabled
on
  the strength of a measurement somewhere else, that measurement should
decide,
  not mine.

So my suggestion is the one-line target_link_options and keep IPO. If IPO
turns out not to pay for its build time, drop it on that ground rather than
on
account of a diagnostic.

Finally, on gating anything at 17: the pragma fix for PR lto/107936 (commit
4c85f7cf587f) landed on trunk on 2026-07-17, after the gcc 16 branch, so
from
gcc 17 the existing #pragma GCC diagnostic ignored regions should be
honoured
under LTO and no flag would be needed. I have not been able to test that -
gcc
17 is not out - so it is an expectation, not a measurement.
-- 
Moritz Hoffmann;
http://antiguru.de/
_______________________________________________
Oorexx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to