[binutils-gdb] [gdb/exp] Handle recursive namespace import
Tom de Vries via Gdb-cvs <[email protected]> Tue, 14 Jul 2026 08:43:30 +0000 (GMT)
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D2e2f760e5765= fbc923aac825ea3118c06ff5d827 commit 2e2f760e5765fbc923aac825ea3118c06ff5d827 Author: Tom de Vries <[email protected]> Date: Tue Jul 14 10:43:14 2026 +0200 [gdb/exp] Handle recursive namespace import =20 Consider test.c, compiled to a.out using "g++ -g test.c": ... 1 namespace mod_a { int xxx =3D 10; } 2 namespace mod_b { using namespace mod_a; 3 int yyy =3D 20; } 4 int main (void) { 5 using namespace mod_b; 6 void (xxx + yyy); 7 return 0; 8 } ... =20 When trying to print the value of variable xxx we get: ... $ gdb -q -batch a.out -ex start -ex "print xxx" ... Temporary breakpoint 1, main () at test.c:7 7 return 0; No symbol "xxx" in current context. ... =20 The symbol xxx is defined in namespace mod_a, so it's available as: ... (gdb) p mod_a::xxx $1 =3D 10 ... and namespace mod_b uses namespace mod_a, so it's available as: ... (gdb) p mod_b::xxx $2 =3D 10 ... =20 Then main uses namespace mod_b so xxx should also be available in main,= but it's not. =20 The problem happens here in cp_lookup_symbol_via_imports: ... Thread 1 "gdb" hit Breakpoint 1, cp_lookup_symbol_via_imports (scope=3D= 0x5f43d0 "", name=3D0xfffffffface0 "xxx", block=3D0x2fba5a0, domain=3D..., searc= h_scope_first=3D0, declaration_only=3D0, search_parents=3D1, found_symbols=3D...) at /home/vries/gdb/src/gdb/cp-namespace.c:505 505 cp_lookup_symbol_via_imports (current->import_src= , name, ... =20 We're about to follow the "using namespace mod_b" statement: ... (gdb) p *current $1 =3D {import_src =3D 0x2ed2140 "mod_b", import_dest =3D 0x66e910 "", = alias =3D 0x0, declaration =3D 0x0, next =3D 0x0, decl_line =3D 5, searched =3D = 1, excludes =3D {0x0}} ... =20 But it does so using the current block, which is the function block for= main: ... (gdb) p block->function ().m_name $7 =3D 0x2f8bc20 "main()" ... and the block containing the "using namespace mod_a" statement is the s= tatic block. =20 Fix this by additionally iterating over the static and global blocks in= stead of only using the current block. =20 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D34034 Diff: --- gdb/cp-namespace.c | 10 +++++++--- gdb/testsuite/gdb.cp/nsusing-2.exp | 21 ++++++++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 17c4d40e294..ce7cba3d264 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -520,9 +520,13 @@ cp_lookup_symbol_via_imports (const char *scope, /* If this import statement creates no alias, pass current->inner as NAMESPACE to direct the search towards the imported namespace. */ - cp_lookup_symbol_via_imports (current->import_src, name, - block, domain, 1, 0, 0, - found_symbols); + for (const struct block *b =3D block; b !=3D nullptr; + b =3D ((b->is_static_block () || b->is_global_block ()) + ? b->superblock () + : b->static_block ())) + cp_lookup_symbol_via_imports (current->import_src, name, + b, domain, 1, 0, 0, + found_symbols); } =20 } diff --git a/gdb/testsuite/gdb.cp/nsusing-2.exp b/gdb/testsuite/gdb.cp/nsus= ing-2.exp index 65e685d0d32..417b4097989 100644 --- a/gdb/testsuite/gdb.cp/nsusing-2.exp +++ b/gdb/testsuite/gdb.cp/nsusing-2.exp @@ -22,6 +22,11 @@ if {[prepare_for_testing "failed to prepare" $testfile $= srcfile \ return } =20 +# 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}] + with_test_prefix pre-main { gdb_test "print mod_a::xxx" " =3D 10" gdb_test "print mod_b::yyy" " =3D 20" @@ -45,8 +50,19 @@ with_test_prefix start-of-main { gdb_test "print mod_b::xxx" " =3D 10" =20 # Same command as in end-of-main, but not a regression test for PR3403= 4. - gdb_test "print xxx" \ - [string_to_regexp {No symbol "xxx" in current context.}] + set re_pass [string_to_regexp {No symbol "xxx" in current context.}] + set re_xfail "$valnum_re =3D 10" + gdb_test_multiple "print xxx" "" { + -re -wrap $re_pass { + pass $gdb_test_name + } + -re -wrap $re_xfail { + if {$have_gcc108716_xfail} { + setup_xfail *-*-* gcc/108716 + } + fail $gdb_test_name + } + } =20 # Same test as in end-of-main, but not a regression test for PR34051. gdb_test "print mod_a::yyy" \ @@ -66,7 +82,6 @@ foreach_with_prefix n {1 2 3 4} { # Function main is using namespace mod_b, and namespace mod_b is using # namespace mod_a, so mod_a::xxx is available as xxx. Regression test= for # PR34034. - setup_kfail exp/34034 *-*-* gdb_test "print xxx" " =3D 10" =20 # This used to print " $<n> =3D 20". Regression test for PR34051.