# Copyright 2024 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 # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Test complex types, and their parts. Dwarf assembly counterpart of # gdb.base/complex-parts.exp. # # In dwarf, base types are not allowed to have references to other types. And # because complex types are modeled as base types, gdb has to figure out what # the part type is. # # It would be easier for gdb if compilers would add a dwarf extension and # supply this information, but that may or may not happen # ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115272 ). load_lib dwarf.exp # This test can only be run on targets which support DWARF-2 and use gas. require dwarf2_support standard_testfile main.c -debug.S if [prepare_for_testing "failed to prepare" $testfile \ "${srcfile}" {}] { return -1 } set float_size [get_sizeof float 0] set double_size [get_sizeof double 0] set long_double_size [get_sizeof "long double" 0] set int_size [get_sizeof int 0] # Create the DWARF. set asm_file [standard_output_file $srcfile2] Dwarf::assemble $asm_file { cu { version 2 } { compile_unit {} { # Main. declare_labels int_type int_type: DW_TAG_base_type { {DW_AT_byte_size $::int_size DW_FORM_sdata} {DW_AT_encoding @DW_ATE_signed} {DW_AT_name int} } DW_TAG_subprogram { {MACRO_AT_func {main}} {type :$int_type} } # GCC complex float. declare_labels cf_type cd_type cld_type cf_type: DW_TAG_base_type { {DW_AT_byte_size [expr 2 * $::float_size] DW_FORM_sdata} {DW_AT_encoding @DW_ATE_complex_float} {DW_AT_name "complex float"} } cd_type: DW_TAG_base_type { {DW_AT_byte_size [expr 2 * $::double_size] DW_FORM_sdata} {DW_AT_encoding @DW_ATE_complex_float} {DW_AT_name "complex double"} } cld_type: DW_TAG_base_type { {DW_AT_byte_size [expr 2 * $::long_double_size] DW_FORM_sdata} {DW_AT_encoding @DW_ATE_complex_float} {DW_AT_name "complex long double"} } DW_TAG_variable { {name var_complex_float} {DW_AT_type :$cf_type} } DW_TAG_variable { {name var_complex_double} {DW_AT_type :$cd_type} } DW_TAG_variable { {name var_complex_long_double} {DW_AT_type :$cld_type} } # GCC complex int. # This is what gcc currently generates, see gcc PR debug/93988. declare_labels ci_type ci_type: DW_TAG_base_type { {DW_AT_byte_size [expr 2 * $::int_size] DW_FORM_sdata} {DW_AT_encoding @DW_ATE_lo_user} {DW_AT_name "complex int"} } DW_TAG_variable { {name var_complex_int} {DW_AT_type :$ci_type} } # Clang complex float. # This is what clang currently generates, see this issue ( # https://github.com/llvm/llvm-project/issues/52996 ). declare_labels clang_cf_type clang_cd_type clang_cld_type clang_cf_type: DW_TAG_base_type { {DW_AT_byte_size [expr 2 * $::float_size] DW_FORM_sdata} {DW_AT_encoding @DW_ATE_complex_float} {DW_AT_name "complex"} } DW_TAG_variable { {name var_complex_clang_float} {DW_AT_type :$clang_cf_type} } clang_cd_type: DW_TAG_base_type { {DW_AT_byte_size [expr 2 * $::double_size] DW_FORM_sdata} {DW_AT_encoding @DW_ATE_complex_float} {DW_AT_name "complex"} } DW_TAG_variable { {name var_complex_clang_double} {DW_AT_type :$clang_cd_type} } clang_cld_type: DW_TAG_base_type { {DW_AT_byte_size [expr 2 * $::long_double_size] DW_FORM_sdata} {DW_AT_encoding @DW_ATE_complex_float} {DW_AT_name "complex"} } DW_TAG_variable { {name var_complex_clang_long_double} {DW_AT_type :$clang_cld_type} } } } } if [prepare_for_testing "failed to prepare" $testfile \ "${asm_file} ${srcfile}" {}] { return -1 } if ![runto_main] { return -1 } proc do_test { type {clang 0}} { with_test_prefix $type { with_test_prefix clang=$clang { if { $clang } { set type_id [regsub -all " " $type _] set var "var_complex_clang_$type_id" # Gdb could try to synthesize better names, see enhancement # PR symtab/31858. set ctype "complex" set ctype_id "complex" } else { set ctype "complex $type" set type_id [regsub -all " " $type _] set ctype_id [regsub -all " " $ctype _] set var "var_$ctype_id" } gdb_test "ptype '$type'" \ "type = $type" gdb_test "ptype '$ctype'" \ "type = $ctype" eval set type_size \$::${type_id}_size gdb_test "p sizeof ('$type')" \ " = $type_size" if { ! $clang } { # With clang, the ctype name does not uniquely map to a type, # so the size is unpredictable. gdb_test "p sizeof ('$ctype')" \ " = [expr 2 * $type_size]" } set re_kfail \ [string_to_regexp \ "'var_complex_int' has unknown type; cast it to its declared type"] foreach f { {$_cimag} {$_creal} } { gdb_test_multiple "p $f ($var)" "" { -re -wrap " = " { pass $gdb_test_name } -re -wrap $re_kfail { kfail gdb/31857 $gdb_test_name } } if { $clang } { # Without a specific complex type name, it's # unpredictable which type name the part will have. gdb_test {ptype $} \ "type = (float|double|long double)" \ "ptype $f" } else { gdb_test {ptype $} \ "type = $type" \ "ptype $f" } } } } } do_test "float" do_test "double" do_test "long double" do_test "int" do_test "float" 1 do_test "double" 1 do_test "long double" 1