[binutils-gdb] [gdb/exp] Limit workaround in using_direct::valid_line to broken GCC versions
Tom de Vries via Gdb-cvs <[email protected]> Mon, 13 Jul 2026 16:13:29 +0000 (GMT)
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dc20c23f2a738= cfc641ae2ffd9574f6288c248b81 commit c20c23f2a738cfc641ae2ffd9574f6288c248b81 Author: Tom de Vries <[email protected]> Date: Mon Jul 13 18:13:24 2026 +0200 [gdb/exp] Limit workaround in using_direct::valid_line to broken GCC ve= rsions =20 Consider test.c: ... 1 namespace mod_a { 2 int xxx =3D 10; 3 } 4 5 static void 6 foo () 7 { 8 } 9 10 int 11 main () 12 { 13 { 14 foo (); 15 using namespace mod_a; 16 } 17 18 return mod_a::xxx; 19 } ... compiled with "g++ test.c -g". =20 Attempting to print xxx at line 14 shouldn't find anything (because it's before the "using namespace mod_a"), but it does: ... $ gdb -q -batch a.out -ex start -ex "p xxx" ... Temporary breakpoint 1, main () at test.c:14 14 foo (); $1 =3D 10 ... =20 This happens because using_direct::valid_line returns true here: ... return (decl_line <=3D curr_sal.line) || (decl_line >=3D boundary); ... =20 Since we have decl_line =3D=3D 15 and curr_sal.line =3D=3D 14, "(decl_line <=3D curr_sal.line)" evaluates to false. =20 But boundary =3D=3D 14, so "(decl_line >=3D boundary)" evaluates to tru= e. =20 The "(decl_line >=3D boundary)" bit was added as a workaround for GCC PR debug/108716. =20 Since I'm using GCC 15, the workaround is not needed. =20 Fix this by limiting the workaround to broken GCC versions. =20 Tested on x86_64-linux, using GCC 15.2, and 7.5. =20 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D34203 Diff: --- gdb/cp-namespace.c | 26 ++++++++++++++++--- gdb/namespace.c | 9 +++++-- gdb/testsuite/gdb.cp/ns-before-using.c | 37 +++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/ns-before-using.exp | 44 ++++++++++++++++++++++++++++= ++++ 4 files changed, 110 insertions(+), 6 deletions(-) diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index c8cd5c245aa..073095f76f1 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -33,6 +33,7 @@ #include "namespace.h" #include "inferior.h" #include "gdbsupport/unordered_map.h" +#include "producer.h" #include <string> #include <string.h> =20 @@ -410,9 +411,26 @@ cp_lookup_symbol_via_imports (const char *scope, found_symbols[sym.symbol->m_name] =3D sym; } =20 - /* Due to a GCC bug, we need to know the boundaries of the current block - to know if a certain using directive is valid. */ - symtab_and_line boundary_sal =3D find_sal_for_pc (block->end () - 1, 0); + unsigned boundary_line =3D 0; + { + struct symbol *fn =3D block->containing_function (); + int major, minor; + if (fn !=3D nullptr + && producer_is_gcc (fn->symtab ()->compunit ().producer (), + &major, &minor) + && (major <=3D 9 + || (major =3D=3D 10 && minor < 5) + || (major =3D=3D 11 && minor < 4) + || (major =3D=3D 12 && minor < 3) + || (major =3D=3D 13 && minor < 1))) + { + /* Due to a GCC bug (PR debug/108716, fixed in 10.5, 11.4, 12.3, 13.1), + we need to know the boundaries of the current block to know if a + certain using directive is valid. */ + symtab_and_line boundary_sal =3D find_sal_for_pc (block->end () - 1, 0); + boundary_line =3D boundary_sal.line; + } + } =20 /* Go through the using directives. If any of them add new names to the namespace we're searching in, see if we can find a match by @@ -423,7 +441,7 @@ cp_lookup_symbol_via_imports (const char *scope, =20 /* If the using directive was below the place we are stopped at, do not use this directive. */ - if (!current->valid_line (boundary_sal.line)) + if (!current->valid_line (boundary_line)) continue; len =3D strlen (current->import_dest); directive_match =3D (search_parents diff --git a/gdb/namespace.c b/gdb/namespace.c index e67ddc5efa7..0c662e1dbfc 100644 --- a/gdb/namespace.c +++ b/gdb/namespace.c @@ -113,8 +113,13 @@ using_direct::valid_line (unsigned int boundary) const { CORE_ADDR curr_pc =3D get_frame_pc (get_selected_frame ()); symtab_and_line curr_sal =3D find_sal_for_pc (curr_pc, 0); - return (decl_line <=3D curr_sal.line) - || (decl_line >=3D boundary); + + /* Apply GCC PR debug/108716 workaround. */ + if (boundary !=3D 0 + && decl_line >=3D boundary) + return true; + + return decl_line <=3D curr_sal.line; } catch (const gdb_exception &ex) { diff --git a/gdb/testsuite/gdb.cp/ns-before-using.c b/gdb/testsuite/gdb.cp/= ns-before-using.c new file mode 100644 index 00000000000..f74c35b0d3f --- /dev/null +++ b/gdb/testsuite/gdb.cp/ns-before-using.c @@ -0,0 +1,37 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2026 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. = */ + +namespace mod_a +{ + int xxx =3D 10; +} + +static void +foo () +{ +} + +int +main () +{ + { + foo (); + using namespace mod_a; + } + + return mod_a::xxx; +} diff --git a/gdb/testsuite/gdb.cp/ns-before-using.exp b/gdb/testsuite/gdb.c= p/ns-before-using.exp new file mode 100644 index 00000000000..f891cf56c49 --- /dev/null +++ b/gdb/testsuite/gdb.cp/ns-before-using.exp @@ -0,0 +1,44 @@ +# Copyright 2026 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +standard_testfile .c + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ + {debug c++}]} { + return +} + +if {![runto_main]} { + continue +} + +# Xfail for incorrect decl_line on DW_TAG_imported_module, +# GCC PR debug/108716. +set have_gcc108716_xfail \ + [expr {[test_compiler_info gcc-*] && [gcc_major_version] < 13}] + +# Regression test for PR exp/34203. +set re_pass [string_to_regexp {No symbol "xxx" in current context.}] +gdb_test_multiple "print xxx" "" { + -re -wrap $re_pass { + pass $gdb_test_name + } + -re -wrap "$valnum_re =3D 10" { + if {$have_gcc108716_xfail} { + setup_xfail *-*-* gcc/108716 + } + fail $gdb_test_name + } +}