From 2e2f760e5765fbc923aac825ea3118c06ff5d827 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Tue, 14 Jul 2026 10:43:14 +0200 Subject: [PATCH] [gdb/exp] Handle recursive namespace import Consider test.c, compiled to a.out using "g++ -g test.c": ... 1 namespace mod_a { int xxx = 10; } 2 namespace mod_b { using namespace mod_a; 3 int yyy = 20; } 4 int main (void) { 5 using namespace mod_b; 6 void (xxx + yyy); 7 return 0; 8 } ... 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. ... The symbol xxx is defined in namespace mod_a, so it's available as: ... (gdb) p mod_a::xxx $1 = 10 ... and namespace mod_b uses namespace mod_a, so it's available as: ... (gdb) p mod_b::xxx $2 = 10 ... Then main uses namespace mod_b so xxx should also be available in main, but it's not. The problem happens here in cp_lookup_symbol_via_imports: ... Thread 1 "gdb" hit Breakpoint 1, cp_lookup_symbol_via_imports (scope=0x5f43d0 "", name=0xfffffffface0 "xxx", block=0x2fba5a0, domain=..., search_scope_first=0, declaration_only=0, search_parents=1, found_symbols=...) at /home/vries/gdb/src/gdb/cp-namespace.c:505 505 cp_lookup_symbol_via_imports (current->import_src, name, ... We're about to follow the "using namespace mod_b" statement: ... (gdb) p *current $1 = {import_src = 0x2ed2140 "mod_b", import_dest = 0x66e910 "", alias = 0x0, declaration = 0x0, next = 0x0, decl_line = 5, searched = 1, excludes = {0x0}} ... But it does so using the current block, which is the function block for main: ... (gdb) p block->function ().m_name $7 = 0x2f8bc20 "main()" ... and the block containing the "using namespace mod_a" statement is the static block. Fix this by additionally iterating over the static and global blocks instead of only using the current block. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34034 --- 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 = block; b != nullptr; + b = ((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); } } diff --git a/gdb/testsuite/gdb.cp/nsusing-2.exp b/gdb/testsuite/gdb.cp/nsusing-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 } +# 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" " = 10" gdb_test "print mod_b::yyy" " = 20" @@ -45,8 +50,19 @@ with_test_prefix start-of-main { gdb_test "print mod_b::xxx" " = 10" # Same command as in end-of-main, but not a regression test for PR34034. - 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 = 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 + } + } # 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" " = 10" # This used to print " $ = 20". Regression test for PR34051.