1# Copyright 2013-2024 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# Test namespace aliases. 17# PRs c++/7935, c++/10541 18 19load_lib dwarf.exp 20 21require dwarf2_support allow_cplus_tests 22 23standard_testfile .cc nsalias-dw.S 24 25# Make the DWARF used for the test. This is necessary to work 26# around compiler issues. Not all versions of gcc output the 27# correct debuginfo we need. 28# 29# This should create the equivalent DWARF to: 30# 31# namespace outer 32# { 33# namespace inner 34# { 35# namespace innermost 36# { 37# const int x = 2; 38# int foo (void) { return x; } 39# } 40# 41# namespace Innermost = innermost; 42# 43# const int x = 1; 44# int foo (void) { return x + Innermost::foo (); } 45# } 46# 47# namespace Inner = inner; 48# 49# const int x = 0; 50# int foo (void) { return x + Inner::foo (); } 51# } 52# 53# namespace Outer = outer; 54# namespace oi = Outer::Inner; 55 56set asm_file [standard_output_file $srcfile2] 57Dwarf::assemble $asm_file { 58 cu {} { 59 compile_unit {{language @DW_LANG_C_plus_plus}} { 60 declare_labels int_label outer_label inner_label innermost_label 61 declare_labels im_foo_label i_foo_label o_foo_label 62 declare_labels OuterInner_label oi1_label oi2_label 63 64 int_label: base_type { 65 {name int} 66 {encoding @DW_ATE_signed} 67 {byte_size 4 DW_FORM_sdata} 68 } 69 70 outer_label: DW_TAG_namespace { 71 {name outer} 72 } { 73 inner_label: DW_TAG_namespace { 74 {name inner} 75 } { 76 innermost_label: DW_TAG_namespace { 77 {name innermost} 78 } { 79 DW_TAG_variable { 80 {name x} 81 {type :$int_label} 82 {const_value 2 DW_FORM_data1} 83 } 84 85 im_foo_label: DW_TAG_subprogram { 86 {name foo} 87 {external 1 flag_present} 88 {declaration 1 flag_present} 89 } 90 } 91 92 imported_declaration { 93 {name Innermost} 94 {import :$innermost_label} 95 } 96 97 DW_TAG_variable { 98 {name x} 99 {type :$int_label} 100 {const_value 1 DW_FORM_data1} 101 } 102 103 i_foo_label: subprogram { 104 {name foo} 105 {external 1 flag_present} 106 {declaration 1 flag_present} 107 } 108 } 109 110 OuterInner_label: imported_declaration { 111 {name Inner} 112 {import :$inner_label} 113 } 114 115 DW_TAG_variable { 116 {name x} 117 {type :$int_label} 118 {const_value 0 DW_FORM_data1} 119 } 120 121 o_foo_label: subprogram { 122 {name foo} 123 {external 1 flag_present} 124 {declaration 1 flag_present} 125 } 126 } 127 128 imported_declaration { 129 {name Outer} 130 {import :$outer_label} 131 } 132 133 oi1_label: imported_declaration { 134 {name oi1} 135 {import :$OuterInner_label} 136 } 137 138 oi2_label: imported_declaration { 139 {name oi2} 140 {import :$oi1_label} 141 } 142 143 imported_declaration { 144 {name oi3} 145 {import :$oi2_label} 146 } 147 148 subprogram { 149 {specification :$im_foo_label} 150 {low_pc 0x4 DW_FORM_addr} 151 {high_pc 0x7 DW_FORM_addr} 152 } 153 154 subprogram { 155 {specification :$i_foo_label} 156 {low_pc 0x8 DW_FORM_addr} 157 {high_pc 0xb DW_FORM_addr} 158 } 159 160 subprogram { 161 {specification :$o_foo_label} 162 {low_pc 0xc DW_FORM_addr} 163 {high_pc 0xf DW_FORM_addr} 164 } 165 } 166 } 167} 168 169if {[gdb_compile $srcdir/$subdir/$srcfile ${binfile}1.o \ 170 object {c++ debug}] != ""} { 171 return -1 172} 173 174if {[gdb_compile $asm_file ${binfile}2.o object {nodebug}] != ""} { 175 return -1 176} 177 178if {[gdb_compile [list ${binfile}1.o ${binfile}2.o] \ 179 $binfile executable {c++}] != ""} { 180 return -1 181} 182 183clean_restart $testfile 184 185# A procedure to run various tests on aliased namespaces. 186proc do_alias_tests {ns {real ""} {x ""}} { 187 188 # The "real" namespace is simply NS in all lowercase. 189 if {$real == ""} { 190 set real [string tolower $ns] 191 } 192 193 # The value of `x' is the number of '::' in NS. 194 if {$x == ""} { 195 set x [expr {[llength [split $ns ":"]] / 2}] 196 } 197 198 # Test "whatis" 199 gdb_test "whatis $ns" "type = $real" 200 201 # Test "ptype" 202 gdb_test "ptype $ns" "type = namespace $real" 203 204 # Print 'x' 205 send_log "expecting x = $x\n" 206 gdb_test "print ${ns}::x" " = $x" 207 208 # Attempt to list the function. 209 gdb_test_no_output "list ${ns}::foo" 210 211 # Attempt to break on the start of the function. 212 gdb_breakpoint "*${ns}::foo" 213 214 # And then erase it 215 with_test_prefix "($ns)" { 216 gdb_test_no_output "delete \$bpnum" 217 } 218} 219 220# This is a list of all the permutations to be tested. For troubleshooting 221# purposes, this list is explicitly enumerated. 222 223set permutations {} 224lappend permutations "outer" 225lappend permutations "Outer" 226lappend permutations "outer::inner" 227lappend permutations "Outer::inner" 228lappend permutations "outer::Inner" 229lappend permutations "Outer::Inner" 230lappend permutations "outer::inner::innermost" 231lappend permutations "outer::inner::Innermost" 232lappend permutations "outer::Inner::innermost" 233lappend permutations "outer::Inner::Innermost" 234lappend permutations "Outer::inner::innermost" 235lappend permutations "Outer::inner::Innermost" 236lappend permutations "Outer::Inner::innermost" 237lappend permutations "Outer::Inner::Innermost" 238 239foreach p $permutations { 240 do_alias_tests $p 241} 242 243# Test recursively imported aliases. 244foreach ns {"oi1" "oi2" "oi3"} { 245 do_alias_tests $ns "outer::inner" 1 246 do_alias_tests "${ns}::innermost" "outer::inner::innermost" 2 247 do_alias_tests "${ns}::Innermost" "outer::inner::innermost" 2 248} 249 250# Generate another objfile with nested imported declarations. 251 252set imports { 253 declare_labels n0_label 254 255 n0_label: DW_TAG_namespace { 256 {name n0} 257 } { 258 DW_TAG_variable { 259 {name x} 260 {type :$int_label} 261 {const_value 3 DW_FORM_data1} 262 } 263 } 264 265 declare_labels n0_import 266 n0_import: imported_declaration { 267 {name N0} 268 {import :$n0_label} 269 } 270} 271 272for {set i 1} {$i <= 100} {incr i} { 273 append imports [format " 274 declare_labels n%d_import 275 n%d_import: imported_declaration { 276 {name N%d} 277 {import :\$n%d_import} 278 }" $i $i $i [expr {$i - 1}]] 279} 280 281standard_testfile .cc nsalias-r-dw.S 282 283set asm_file [standard_output_file $srcfile2] 284set the_dwarf [format { 285 cu {} { 286 compile_unit {{language @DW_LANG_C_plus_plus}} { 287 declare_labels int_label n0_label 288 289 int_label: base_type { 290 {name int} 291 {encoding @DW_ATE_signed} 292 {byte_size 4 DW_FORM_sdata} 293 } 294 295%s 296 } 297 } 298} $imports] 299 300Dwarf::assemble $asm_file $the_dwarf 301 302if {[gdb_compile $asm_file ${binfile}3.o object {nodebug}] != ""} { 303 return -1 304} 305 306if {[gdb_compile [list ${binfile}1.o ${binfile}3.o] \ 307 ${binfile}-r executable {c++}] != ""} { 308 return -1 309} 310 311clean_restart 312 313# Set complaints before loading the file. Otherwise the complaint won't 314# trigger for -readnow. 315gdb_test_no_output "set complaints 1" 316 317gdb_load [standard_output_file ${testfile}-r] 318 319set readnow_p [readnow] 320 321set test "complaint for too many recursively imported declarations" 322set re ".* has too many recursively imported declarations.*" 323if { $readnow_p } { 324 global gdb_file_cmd_msg 325 gdb_assert {[regexp $re $gdb_file_cmd_msg]} $test 326} else { 327 gdb_test "maint expand-symtabs" $re $test 328} 329