[Bug debug/126632] New: [15/16 Regression] next/step over steps into a guarded function-local static of a polymorphic type instead of continuing past it

jaap at jcz dot nl via Gcc-bugs <[email protected]> Tue, 04 Aug 2026 09:06:57 +0000
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D126632

            Bug ID: 126632
           Summary: [15/16 Regression] next/step over steps into a guarded
                    function-local static of a polymorphic type instead of
                    continuing past it
           Product: gcc
           Version: 16.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jaap at jcz dot nl
  Target Milestone: ---

Created attachment 65237
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=3D65237&action=3Dedit
g++ ii output file from -save-temps flag

At -O0 -ggdb, stepping over (next in GDB, step over in LLDB) a call to a
function containing a guarded function-local static of a class with a virtu=
al
destructor incorrectly stops inside the called function instead of continui=
ng
to the next line of the caller. This is a regression: works correctly with =
GCC
14.3.1, broken with GCC 15.x and GCC 16.1.1. Reproduces identically in two
independent debuggers (GDB 17.2 and LLDB 22.1.8), is absent when the identi=
cal
source is compiled with Clang, and reproduces on two independent distributi=
ons
(Arch Linux and Ubuntu 26.10) =E2=80=94 isolating the defect to GCC's debug=
-info
generation for this pattern rather than to either debugger, to DWARF itself=
, or
to distro packaging.

Exact command line that triggers the bug

g++ -v -save-temps -O0 -ggdb -o step_over_issue step_over_issue.cpp

gcc -v output:

Using built-in specs.
COLLECT_GCC=3Dg++
COLLECT_LTO_WRAPPER=3D/usr/lib/gcc/x86_64-pc-linux-gnu/16/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc/configure
--enable-languages=3Dada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust,cobol
--enable-bootstrap --prefix=3D/usr --libdir=3D/usr/lib --libexecdir=3D/usr/=
lib
--mandir=3D/usr/share/man --infodir=3D/usr/share/info
--with-bugurl=3Dhttps://gitlab.archlinux.org/archlinux/packaging/packages/g=
cc/-/issues
--with-build-config=3Dbootstrap-lto --with-gcc-major-version-only
--with-linker-hash-style=3Dgnu --with-system-zlib --enable-cet=3Dauto
--enable-checking=3Drelease --enable-clocale=3Dgnu --enable-default-pie
--enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-obj=
ect
--enable-libstdcxx-backtrace --enable-link-serialization=3D1
--enable-linker-build-id --enable-lto --enable-multilib --enable-plugin
--enable-shared --enable-threads=3Dposix --disable-fixincludes --disable-li=
bssp
--disable-libstdcxx-pch --disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 16.1.1 20260728 (GCC)
GNU C++20 (GCC) version 16.1.1 20260728 (x86_64-pc-linux-gnu)
        compiled by GNU C version 16.1.1 20260728, GMP version 6.3.0, MPFR
version 4.2.2, MPC version 1.4.1, isl version isl-0.28-GMP
GNU assembler version 2.46.1 (x86_64-pc-linux-gnu) using BFD version (GNU
Binutils) 2.46.1

System type: x86_64-pc-linux-gnu, Arch Linux, kernel 7.1.3-arch1-3

Compiler output: clean build, no warnings or errors, with the reproducer be=
low.

Attachment: step_over_issue.ii (generated by the -save-temps command above)=
 =E2=80=94
attach this preprocessed file.

Minimal testcase (small, self-contained, no external headers beyond the
standard library):

#include <cstdio>
#include <string>

class LogBase {
public:
    LogBase() { printf("base ctor\n"); }
    virtual ~LogBase() { printf("base dtor\n"); }
};

class LogSingleton : public LogBase {
public:
    static LogSingleton& get_instance(const std::string& name =3D "") {
        static LogSingleton instance(name);
        return instance;
    }
    LogSingleton(const std::string& name) { printf("ctor %s\n", name.c_str(=
));
}
    ~LogSingleton() override { printf("dtor\n"); }
};

int main() {
    printf("before\n");
    LogSingleton::get_instance();
    printf("after\n");
    return 0;
}


Expected behavior: stepping over the LogSingleton::get_instance() call on l=
ine
22 should not stop until control returns to main, at line 23.


Actual behavior (GDB 17.2):

(gdb) b main
(gdb) r
(gdb) n
21          printf("before\n");
(gdb) n
before
12          static LogSingleton& get_instance(const std::string& name =3D "=
") {


Actual behavior (LLDB 22.1.8):

(lldb) b main
(lldb) r
(lldb) n
before
frame #0: ... at step_over_issue.cpp:12:65


Cross-compiler comparison: the identical source compiled with clang++ -O0 -=
ggdb
steps over correctly in both GDB and LLDB, landing on line 23 as expected.
Since only the compiler changes between the working and failing case, this
isolates the defect to GCC('s debug-info generation.).

Cross-distro confirmation: reproduced on a clean ubuntu:26.10 instance with=
 g++
(Ubuntu 15.3.0-1ubuntu1) 15.3.0, identical source and flags =E2=80=94 rules=
 out
Arch-specific packaging/build configuration.

Version bisection: reproduces on GCC 15.x (both Arch's build and Ubuntu's
15.3.0-1ubuntu1) and GCC 16.1.1 (20260625 and 20260728 builds). Does not
reproduce on GCC 14.3.1 20250603, otherwise identical source/flags.



Isolation already performed:

* Function-local static of a non-polymorphic type: steps over correctly.
* Function-local static of a polymorphic type (virtual destructor present):
steps into instead of over.
* -fno-threadsafe-statics does not fix it
* Two independent debuggers fail identically =E2=86=92 points at GCC's gene=
rated debug
info, not the debuggers.
* Absent under Clang ( 22.1.8 ) with identical source/flags.
* Reproduces on two independent distributions.


Debugger versions used:

GNU gdb (GDB) 17.2
lldb version 22.1.8=