I had Claude look into this, and it returned an explanation. Importantly,
it doesn't seem to be an IPO problem.
M

<snip>

I ran the ChatGPT review past Claude Code and then reproduced both problems
in
an Arch container: `archlinux:latest`, gcc 16.2.1, cmake 4.4.2, clean trunk
r13196, test suite r13178. Both are real, they are independent of each
other,
and neither is caused by the concurrency rework. The segfault is ours, not
gcc's, and the fix is two lines.

Point 1, the warnings

The LTO hypothesis is right, and there is a gcc bug number for it. `#pragma
GCC
diagnostic` state has never been streamed into LTO, so a diagnostic emitted
during LTRANS cannot see it. That is PR lto/107936, filed by Jakub Jelinek
on
2022-11-30. Lewis Hyatt's fix landed on gcc trunk on 2026-07-17 as commit
4c85f7cf587f, after the gcc 16 branch, so it will first ship in gcc 17.
Until
then all 24 `HAVE_PRAGMA_GCC_STRINGOPOVERFLOW` sites in our six files are
inert
whenever LTO is on, which is why the warning fires on lines that look
protected.
The gcc manual's `-flto` section is the counterpart: "Diagnostic options
such as
-Wstringop-overflow are passed through to the link stage and their setting
matches that of the compile-step at function granularity." Command-line
options
survive into LTRANS; pragmas do not.

The warnings track IPO, not the concurrency rework and not gcc 16. Measured
on
the same source in the same container:

* gcc 16.2.1, Release, IPO on: 61 `-Wstringop-overflow`
* gcc 16.2.1, Release, IPO off: 0
* gcc 15.3.0, Release, IPO on: 61
* gcc 15.3.0, Release, IPO off: 0

Every warning appears after `Linking CXX shared library lib/librexx.so`,
none
during compilation. So this is r13194 turning IPO back on, and it explains
the
platform split in your table exactly: the Linux machines have gcc and IPO,
macOS
and the BSDs use clang which has no `-Wstringop-overflow`, and Windows uses
/GL and /LTCG. The count is independent of the gcc version, which is why
Ubuntu22 on gcc 11.4 shows it too.

If we want the warnings gone while keeping IPO, I would not disable the
diagnostic globally. Per the manual sentence above the setting propagates at
function granularity, so it is enough to put it on the affected files:

```cmake
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  set_source_files_properties (
    interpreter/classes/StringClass.cpp
    interpreter/classes/StringClassBit.cpp
    interpreter/classes/StringClassConversion.cpp
    interpreter/classes/StringClassSub.cpp
    PROPERTIES COMPILE_OPTIONS -Wno-stringop-overflow)
endif ()
```

That keeps the diagnostic everywhere else. The manual also warns that
inlining
can move a region to another function's setting, so this wants a build to
confirm rather than a claim from me.

Point 2, the ArchLinux and Manjaro segfaults

These are not IPO and not a gcc miscompilation. They are undefined
behaviour in
our parser that gcc 16 now exploits.

What reproduces: any Rexx program at all, not just the test suite. `rexx -v`
works, `say 1` and even an empty program segfault, 10 out of 10. The Jenkins
build job fails because the test suite cannot start.

The evidence, all same source, same container:

* gcc 16, Release, IPO on: crash. IPO off: crash. `-fno-strict-aliasing`:
crash.
  `-O1`: crash. Debug (-O0): clean.
* gcc 15, Release, IPO on and off: clean.
* gcc 16 binary with the gcc 15 `rexx.img`: clean. gcc 15 binary with the
gcc 16
  `rexx.img`: crash.

So the image is what is broken, and the reader is fine. `rexx.img` is built
during the build by running the freshly built interpreter, which is why the
build succeeds and ships a corrupt image. The crash lands in
RexxActivation.cpp:639 with `nextInst = 0x16f568`, a raw image offset that
restore never converted back into a pointer.

The cause is in `LanguageParser::sourceNewObject`,
InstructionParser.cpp:498:

```cpp
RexxInternalObject *newObject = new_object(size);
newObject->setBehaviour(_behaviour);                      // store
::new((void *)newObject)RexxInstruction(clause, type);    // lifetime
starts here
```

The store happens before the placement new begins the object's lifetime. A
store
outside an object's lifetime is dead by [basic.life], and gcc's
`-flifetime-dse`
is entitled to delete it. gcc 16 does delete it at -O1 and above, gcc 15
does
not. Every parsed instruction then has no behaviour, that goes into the
image,
restore mis-relocates and we walk into a bogus pointer. `RexxInstruction`'s
constructor only sets `instructionType` and `instructionLocation`, so
nothing
puts the behaviour back.

Two independent confirmations. `-fno-lifetime-dse` on the whole project
makes
gcc 16 correct again, and applied to one file at a time only
`interpreter/parser/InstructionParser.cpp` fixes it, with all seven other
parser
files still crashing.

The fix, swapping two lines:

```cpp
RexxInternalObject *newObject = new_object(size);
::new((void *)newObject)RexxInstruction(clause, type);
newObject->setBehaviour(_behaviour);
```

With that patch and no special flags, gcc 16.2.1, Release, IPO on: `say 1`
returns 0 five times out of five, and the full suite runs to completion.
Three
suite runs in the same container, all 24372 tests, all 0 errors:

* gcc 15.3.0, unpatched, IPO on: 9 failures
* gcc 16.2.1, patched, IPO on: 9 failures
* gcc 15.3.0, patched, IPO on: 9 failures

The failing nine are the same nine tests in all three runs, all file,
stream and
stdout cases, so they are this container (running as root, no tty) rather
than
anything the patch did. gcc 15 is unaffected by the change.

One thing for you to decide rather than me. InstructionParser.cpp has 73
placement-new sites, because a second placement new constructs the derived
instruction over the same storage after `sourceNewObject` returns, which is
the
"Step 4" its comment describes. That starts another lifetime over the same
bytes, so formally the base constructor's stores are dead there too. gcc 16
does
not currently delete those, which is why the two-line fix suffices today,
but
the pattern stays undefined and the next optimiser change can take a
different
store. Replacing the two-phase construction with ordinary constructor
chaining
is the real repair, and that is a bigger change than I want to make unasked.
The comment above the function, "The information we set up here will remain
untouched", is the assumption that expired.

Proposal: commit the two-line fix now, since it unbreaks gcc 16 with IPO on
and
leaves gcc 15 with an unchanged suite result, and keep IPO. Separately
decide on
the per-file `-Wno-stringop-overflow` for the warnings, and on whether the
two-phase instruction construction gets rewritten. I can also file the
gcc-16
finding upstream if you want it on record, though I do not think it is a gcc
bug.

(Analysis and measurements by Claude Code; the container recipe and logs are
reproducible on request.)

On Tue, Aug 18, 2026 at 1:48 PM Michael Lueck <[email protected]>
wrote:

> Greetings Jean Louis,
>
>
> Jean Louis Faucher wrote:
> >
> >
> > The point 2 is for P.O..
> >
> >
> > Here, we have a "normal" number of warnings:
> >
> > ooRexx-macOS10-X86_64-build5 warnings
> > ooRexx-macOS15-X86_64-build10 warnings
> > ooRexx-macOS26-M4-build5 warnings
> > ooRexx-FreeBSD14-build10 warnings
> > ooRexx-NetBSD10-build2 warnings
> > ooRexx-OpenBSD7-build7 warnings
> > ooRexx-OpenIndiana-build2 warnings
> > ooRexx-OpenSuse15-build2 warnings
> > ooRexx-RaspberryPiOS32-build2 warnings
> > ooRexx-RaspberryPiOS64-build2 warnings
> > ooRexx-Solaris11-build2 warnungs
> > oorexx-ubuntu16-build2 warnings
> > ooRexx-windows10_32-build2 warnings
> > ooRexx-windows10_64-build1 warning
> > ooRexx-windows11_32-build2 warnings
> > ooRexx-windows11_64-build1 warning
> > ooRexx-windows32-build2 warnings
> > ooRexx-windows64-build1 warning
> > ooRexx-windows7_32-build2 warnings
> > ooRexx-windows7_64-build1 warning
> > ooRexx-windows8_32-build2 warnings
> > ooRexx-windows8_64-build1 warning
> >
> >
> > Here, we have a bunch of new warnings after the concurrency rework:
> > warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
> >
> > ooRexx-ArchLinux-buildaround 60 warnings, segmentation fault
> > ooRexx-CentOS10-buildaround 160 warnings
> > ooRexx-Controller-Ubuntu-buildaround 80 warnings
> > ooRexx-Debian12-buildaround 80 warnings
> > ooRexx-Fedora43-buildaround 60 warnings
> > ooRexx-linux-aarch64-buildaround 35 warnings
> > ooRexx-LinuxMint22-buildaround 80 warnings
> > ooRexx-Manjaro-buildaround 60 warnings, segmentation fault
> > ooRexx-Ubuntu22-buildaround 70 warnings
> > ooRexx-Ubuntu24-buildaround 80 warnings
>
>
> (snip)
>
>
> THAT type of example list is wonderful! As someone who's best programming
> language is Rexx / ooRexx, then any time the Rexx interpreter gripes at me
> it is a very big deal that I must change the code
> to deal with. I am NOT comfortable seeing "warning" that is safe to just
> ignore.
>
> I am thankful,
>
> --
> Michael Lueck
> Lueck Data Systems
> http://www.lueckdatasystems.com/
>
>
> _______________________________________________
> Oorexx-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/oorexx-devel
>


-- 
Moritz Hoffmann;
http://antiguru.de/
_______________________________________________
Oorexx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to