diff --git a/gdb/testsuite/gdb.cp/call-method-register.cc b/gdb/testsuite/gdb.cp/call-method-register.cc index d60fee03701..91cbf13ebca 100644 --- a/gdb/testsuite/gdb.cp/call-method-register.cc +++ b/gdb/testsuite/gdb.cp/call-method-register.cc @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 1993-2022 Free Software Foundation, Inc. + Copyright 2022 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 @@ -15,54 +15,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#if defined __x86_64__ -# define ASM_REG "rax" -#elif defined __i386__ -# define ASM_REG "eax" -#elif defined __powerpc64__ -# define ASM_REG "r9" -#else -# error "port me" -#endif - -/* A class small enough that it fits in a register. */ -struct small -{ - int x; - int method (); -}; - -int -small::method () -{ - return x + 5; -} - -int -register_class () -{ - /* Given the use of the GNU register-asm local variables extension, - the compiler puts this variable in a register. This means that - GDB can't call any methods for this variable, which is what we - want to test. */ - register small v asm (ASM_REG); - - int i; - - /* Perform a computation sufficiently complicated that optimizing - compilers won't optimize out the variable. If some compiler - constant-folds this whole loop, maybe using a parameter to this - function here would help. */ - v.x = 0; - for (i = 0; i < 13; ++i) - v.x += i; - --v.x; /* v.x is now 77 */ - return v.x + 5; /* set breakpoint here */ -} - int main () { - register_class (); + asm ("main_label: .globl main_label"); return 0; } diff --git a/gdb/testsuite/gdb.cp/call-method-register.exp b/gdb/testsuite/gdb.cp/call-method-register.exp index a98b11e4c11..2c9a1d4ec2a 100644 --- a/gdb/testsuite/gdb.cp/call-method-register.exp +++ b/gdb/testsuite/gdb.cp/call-method-register.exp @@ -19,43 +19,92 @@ if { [skip_cplus_tests] } { continue } load_lib "cp-support.exp" +load_lib dwarf.exp -standard_testfile .cc +standard_testfile .cc -dw.S -if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} { +if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ + {debug c++}]} { return -1 } -if {![test_compiler_info gcc-*-* c++]} { - untested "test relies on a gcc extension" - return -} +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { -proc test_call_register_class {} { - global gdb_prompt + set main_result \ + [function_range main ${::srcdir}/${::subdir}/${::srcfile}] + set main_start [lindex $main_result 0] + set main_length [lindex $main_result 1] - if ![runto_main] { - return + cu {} { + compile_unit { + {DW_AT_language @DW_LANG_C_plus_plus} + {DW_AT_name $::srcfile} + {DW_AT_comp_dir /tmp} + } { + declare_labels int_type_label struct_type_label \ + struct_ptr_type_label + set ptr_size [get_sizeof "void *" 96] + + DW_TAG_subprogram { + {name main} + {low_pc $main_start addr} + {high_pc $main_length data8} + {DW_AT_type :$int_type_label} + } + + int_type_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name int} + } + + struct_type_label: DW_TAG_structure_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_name small} + } { + member { + {name xxx} + {type :$int_type_label} + {data_member_location 0 data1} + } + subprogram { + {name yyy} + {type :$int_type_label} + } { + formal_parameter { + {type :$struct_ptr_type_label} + {artificial 1 flag_present} + } + } + } + + struct_ptr_type_label: DW_TAG_pointer_type { + {DW_AT_byte_size $ptr_size DW_FORM_data1} + {type :$struct_type_label} + } + + DW_TAG_variable { + {DW_AT_name global_var} + {DW_AT_type :$struct_type_label} + {DW_AT_location { + DW_OP_reg0 + } SPECIAL_expr} + {external 1 flag} + } + } } - - set bp_location [gdb_get_line_number "set breakpoint here"] - gdb_breakpoint $bp_location - gdb_continue_to_breakpoint "break here" - - # This class is so small that an instance of it can fit in a register. - # When gdb tries to call a method, it gets embarrassed about taking - # the address of a register. - # - # That message is a PASS, not an XFAIL, because gdb prints an - # informative message and declines to do something impossible. - # - # The method call actually succeeds if the compiler allocates very - # small classes in memory instead of registers. If that happens, - # it's a FAIL, because the testcase is written in a form such that - # it should not happen. - gdb_test "print v.method ()" \ - "Address requested for identifier \"v\" which is in register .*" \ - "call method on register local" } -test_call_register_class +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {nodebug}] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +gdb_test "print global_var.yyy ()" \ + "Address requested for identifier \"global_var\" which is in register .*" \ + "call method on register local"