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 19 load_lib dwarf.exp 20 21 require dwarf2_support allow_cplus_tests 22 23 standard_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 56 set asm_file [standard_output_file $srcfile2] 57 Dwarf::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 169 if {[gdb_compile $srcdir/$subdir/$srcfile ${binfile}1.o \ 170 object {c++ debug}] != ""} { 171 return -1 172 } 173 174 if {[gdb_compile $asm_file ${binfile}2.o object {nodebug}] != ""} { 175 return -1 176 } 177 178 if {[gdb_compile [list ${binfile}1.o ${binfile}2.o] \ 179 $binfile executable {c++}] != ""} { 180 return -1 181 } 182 183 clean_restart $testfile 184 185 # A procedure to run various tests on aliased namespaces. 186 proc 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 223 set permutations {} 224 lappend permutations "outer" 225 lappend permutations "Outer" 226 lappend permutations "outer::inner" 227 lappend permutations "Outer::inner" 228 lappend permutations "outer::Inner" 229 lappend permutations "Outer::Inner" 230 lappend permutations "outer::inner::innermost" 231 lappend permutations "outer::inner::Innermost" 232 lappend permutations "outer::Inner::innermost" 233 lappend permutations "outer::Inner::Innermost" 234 lappend permutations "Outer::inner::innermost" 235 lappend permutations "Outer::inner::Innermost" 236 lappend permutations "Outer::Inner::innermost" 237 lappend permutations "Outer::Inner::Innermost" 238 239 foreach p $permutations { 240 do_alias_tests $p 241 } 242 243 # Test recursively imported aliases. 244 foreach 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 252 set 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 272 for {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 281 standard_testfile .cc nsalias-r-dw.S 282 283 set asm_file [standard_output_file $srcfile2] 284 set 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 300 Dwarf::assemble $asm_file $the_dwarf 301 302 if {[gdb_compile $asm_file ${binfile}3.o object {nodebug}] != ""} { 303 return -1 304 } 305 306 if {[gdb_compile [list ${binfile}1.o ${binfile}3.o] \ 307 ${binfile}-r executable {c++}] != ""} { 308 return -1 309 } 310 311 clean_restart 312 313 # Set complaints before loading the file. Otherwise the complaint won't 314 # trigger for -readnow. 315 gdb_test_no_output "set complaints 1" 316 317 gdb_load [standard_output_file ${testfile}-r] 318 319 set readnow_p [readnow] 320 321 set test "complaint for too many recursively imported declarations" 322 set re ".* has too many recursively imported declarations.*" 323 if { $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