diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 16 | ||||
-rw-r--r-- | gdb/f-exp.h | 16 | ||||
-rw-r--r-- | gdb/f-exp.y | 9 | ||||
-rw-r--r-- | gdb/f-lang.c | 40 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.exp | 158 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.f90 | 93 |
7 files changed, 333 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 072fa09..42d4bf5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,21 @@ 2021-04-07 Andrew Burgess <andrew.burgess@embecosm.com> + * f-exp.h (class fortran_structop_operation): New class. + * f-exp.y (exp): Create fortran_structop_operation instead of the + generic structop_operation. + * f-lang.c (fortran_undetermined::evaluate): Re-evaluate + expression as EVAL_NORMAL if the result type was dynamic so we can + extract the actual array bounds. + (fortran_structop_operation::evaluate): New function. + +2021-04-07 Andrew Burgess <andrew.burgess@embecosm.com> + + * eval.c (evaluate_subexp_standard): Remove + EVAL_AVOID_SIDE_EFFECTS handling from STRUCTOP_STRUCT and + STRUCTOP_PTR. + +2021-04-07 Andrew Burgess <andrew.burgess@embecosm.com> + * valops.c (value_cast): Call value_deeply_equal before performing any cast. diff --git a/gdb/f-exp.h b/gdb/f-exp.h index b3d0e0e..955d187 100644 --- a/gdb/f-exp.h +++ b/gdb/f-exp.h @@ -273,6 +273,22 @@ public: { return std::get<0> (m_storage); } }; +/* Implement STRUCTOP_STRUCT for Fortran. */ +class fortran_structop_operation + : public structop_base_operation +{ +public: + + using structop_base_operation::structop_base_operation; + + value *evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) override; + + enum exp_opcode opcode () const override + { return STRUCTOP_STRUCT; } +}; + } /* namespace expr */ #endif /* FORTRAN_EXP_H */ diff --git a/gdb/f-exp.y b/gdb/f-exp.y index ce11b09..6608831 100644 --- a/gdb/f-exp.y +++ b/gdb/f-exp.y @@ -492,7 +492,7 @@ exp : '(' type ')' exp %prec UNARY exp : exp '%' name { - pstate->push_new<structop_operation> + pstate->push_new<fortran_structop_operation> (pstate->pop (), copy_name ($3)); } ; @@ -500,8 +500,8 @@ exp : exp '%' name exp : exp '%' name COMPLETE { structop_base_operation *op - = new structop_operation (pstate->pop (), - copy_name ($3)); + = new fortran_structop_operation (pstate->pop (), + copy_name ($3)); pstate->mark_struct_expression (op); pstate->push (operation_up (op)); } @@ -510,7 +510,8 @@ exp : exp '%' name COMPLETE exp : exp '%' COMPLETE { structop_base_operation *op - = new structop_operation (pstate->pop (), ""); + = new fortran_structop_operation (pstate->pop (), + ""); pstate->mark_struct_expression (op); pstate->push (operation_up (op)); } diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 0c49420..7e921b9 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -1405,6 +1405,9 @@ fortran_undetermined::evaluate (struct type *expect_type, enum noside noside) { value *callee = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); + if (noside == EVAL_AVOID_SIDE_EFFECTS + && is_dynamic_type (value_type (callee))) + callee = std::get<0> (m_storage)->evaluate (nullptr, exp, EVAL_NORMAL); struct type *type = check_typedef (value_type (callee)); enum type_code code = type->code (); @@ -1490,6 +1493,43 @@ fortran_bound_2arg::evaluate (struct type *expect_type, return fortran_bounds_for_dimension (lbound_p, exp->gdbarch, arg1, arg2); } +/* Implement STRUCTOP_STRUCT for Fortran. See operation::evaluate in + expression.h for argument descriptions. */ + +value * +fortran_structop_operation::evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) +{ + value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); + const char *str = std::get<1> (m_storage).c_str (); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + struct type *type = lookup_struct_elt_type (value_type (arg1), str, 1); + + if (type != nullptr && is_dynamic_type (type)) + arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, EVAL_NORMAL); + } + + value *elt = value_struct_elt (&arg1, NULL, str, NULL, "structure"); + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + struct type *elt_type = value_type (elt); + if (is_dynamic_type (elt_type)) + { + const gdb_byte *valaddr = value_contents_for_printing (elt); + CORE_ADDR address = value_address (elt); + gdb::array_view<const gdb_byte> view + = gdb::make_array_view (valaddr, TYPE_LENGTH (elt_type)); + elt_type = resolve_dynamic_type (elt_type, view, address); + } + elt = value_zero (elt_type, VALUE_LVAL (elt)); + } + + return elt; +} + } /* namespace expr */ /* See language.h. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 0a081fc..1980315 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2021-04-07 Andrew Burgess <andrew.burgess@embecosm.com> + * gdb.fortran/dynamic-ptype-whatis.exp: New file. + * gdb.fortran/dynamic-ptype-whatis.f90: New file. + +2021-04-07 Andrew Burgess <andrew.burgess@embecosm.com> + * gdb.cp/rvalue-ref-params.cc (f3): New function. (f4): New function. (global_int): New global variable. diff --git a/gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.exp b/gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.exp new file mode 100644 index 0000000..d2ffd6d --- /dev/null +++ b/gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.exp @@ -0,0 +1,158 @@ +# Copyright 2021 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 <http://www.gnu.org/licenses/> . + +# Test using whatis and ptype on different configurations of dynamic +# types. + +if {[skip_fortran_tests]} { return -1 } + +standard_testfile ".f90" +load_lib fortran.exp + +if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \ + {debug f90}]} { + return -1 +} + +if {![fortran_runto_main]} { + perror "Could not run to main." + continue +} + +gdb_breakpoint [gdb_get_line_number "Break Here"] +gdb_continue_to_breakpoint "Break Here" + +gdb_test "whatis var1" "type = real\\(kind=4\\) \\(3\\)" +gdb_test "whatis var2" "type = real\\(kind=4\\), allocatable \\(4\\)" +gdb_test "whatis var3" "type = Type type1" +gdb_test "whatis var4" "type = Type type2" +gdb_test "whatis var5" "type = Type type3" +gdb_test "whatis var6" "type = Type type4" +gdb_test "whatis var7" "type = Type type5" +gdb_test "ptype var1" "type = real\\(kind=4\\) \\(3\\)" +gdb_test "ptype var2" "type = real\\(kind=4\\), allocatable \\(4\\)" +gdb_test "ptype var3" \ + [ multi_line "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1" ] +gdb_test "ptype var4" \ + [multi_line "type = Type type2" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type1, allocatable :: t2_array\\(3\\)" \ + "End Type type2"] +gdb_test "ptype var5" \ + [ multi_line "type = Type type3" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type1 :: t3_array\\(3\\)"\ + "End Type type3" ] +gdb_test "ptype var6" \ + [ multi_line "type = Type type4" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type2, allocatable :: t4_array\\(3\\)" \ + "End Type type4" ] +gdb_test "ptype var7" \ + [ multi_line "type = Type type5" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type2 :: t5_array\\(4\\)" \ + "End Type type5" ] +gdb_test "whatis var3%t1_i" "type = integer\\(kind=4\\)" +gdb_test "whatis var4%t2_array" "type = Type type1, allocatable \\(3\\)" +gdb_test "whatis var5%t3_array" "type = Type type1 \\(3\\)" +gdb_test "whatis var6%t4_array" "type = Type type2, allocatable \\(3\\)" +gdb_test "whatis var7%t5_array" "type = Type type2 \\(4\\)" +gdb_test "ptype var3%t1_i" [ multi_line "type = integer\\(kind=4\\)" ] +gdb_test "ptype var4%t2_array" [ multi_line "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1, allocatable \\(3\\)" ] +gdb_test "ptype var5%t3_array" [ multi_line "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1 \\(3\\)" ] +gdb_test "ptype var6%t4_array" \ + [ multi_line "type = Type type2" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type1, allocatable :: t2_array\\(:\\)" \ + "End Type type2, allocatable \\(3\\)" ] +gdb_test "ptype var7%t5_array" \ + [ multi_line "type = Type type2" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type1, allocatable :: t2_array\\(:\\)" \ + "End Type type2 \\(4\\)" ] +gdb_test "whatis var4%t2_array(1)" "type = Type type1" +gdb_test "whatis var5%t3_array(1)" "type = Type type1" +gdb_test "whatis var6%t4_array(1)" "type = Type type2" +gdb_test "whatis var7%t5_array(1)" "type = Type type2" +gdb_test "ptype var4%t2_array(1)" \ + [ multi_line "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1" ] +gdb_test "ptype var5%t3_array(1)" \ + [ multi_line "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1" ] +gdb_test "ptype var6%t4_array(1)" \ + [ multi_line "type = Type type2" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type1, allocatable :: t2_array\\(2\\)" \ + "End Type type2" ] +gdb_test "ptype var7%t5_array(1)" \ + [ multi_line "type = Type type2" \ + " integer\\(kind=4\\) :: spacer" \ + " Type type1, allocatable :: t2_array\\(2\\)" \ + "End Type type2" ] +gdb_test "whatis var4%t2_array(1)%t1_i" "type = integer\\(kind=4\\)" +gdb_test "whatis var5%t3_array(1)%t1_i" "type = integer\\(kind=4\\)" +gdb_test "whatis var6%t4_array(1)%t2_array" \ + "type = Type type1, allocatable \\(2\\)" +gdb_test "whatis var7%t5_array(1)%t2_array" \ + "type = Type type1, allocatable \\(2\\)" +gdb_test "ptype var4%t2_array(1)%t1_i" "type = integer\\(kind=4\\)" +gdb_test "ptype var5%t3_array(1)%t1_i" "type = integer\\(kind=4\\)" +gdb_test "ptype var6%t4_array(1)%t2_array" \ + [ multi_line "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1, allocatable \\(2\\)" ] +gdb_test "ptype var7%t5_array(1)%t2_array" \ + [ multi_line "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1, allocatable \\(2\\)" ] +gdb_test "whatis var6%t4_array(1)%t2_array(1)" \ + "type = Type type1" +gdb_test "whatis var7%t5_array(1)%t2_array(1)" \ + "type = Type type1" +gdb_test "ptype var6%t4_array(1)%t2_array(1)" \ + [ multi_line \ + "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1" ] +gdb_test "ptype var7%t5_array(1)%t2_array(1)" \ + [ multi_line \ + "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1" ] +gdb_test "ptype var8%ptr_1%t2_array" \ + [ multi_line \ + "type = Type type1" \ + " integer\\(kind=4\\) :: spacer" \ + " integer\\(kind=4\\) :: t1_i" \ + "End Type type1, allocatable \\(3\\)" ] diff --git a/gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.f90 b/gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.f90 new file mode 100644 index 0000000..e56bf79 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/dynamic-ptype-whatis.f90 @@ -0,0 +1,93 @@ +! Copyright 2021 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 <http://www.gnu.org/licenses/>. + +program main + + ! A non-dynamic type. + type type1 + integer(kind=4) :: spacer + integer(kind=4) t1_i + end type type1 + + ! A first dynamic type. The array is of a static type. + type type2 + integer(kind=4) :: spacer + type(type1), allocatable :: t2_array(:) + end type type2 + + ! Another dynamic type, the array is again a static type. + type type3 + integer(kind=4) :: spacer + type(type1), pointer :: t3_array(:) + end type type3 + + ! A dynamic type, this time the array contains a dynamic type. + type type4 + integer(kind=4) :: spacer + type(type2), allocatable :: t4_array(:) + end type type4 + + ! A static type, the array though contains dynamic types. + type type5 + integer(kind=4) :: spacer + type(type2) :: t5_array (4) + end type type5 + + ! A static type containing pointers to a type that contains a + ! dynamic array. + type type6 + type(type2), pointer :: ptr_1 + type(type2), pointer :: ptr_2 + end type type6 + + real, dimension(:), pointer :: var1 + real, dimension(:), allocatable :: var2 + type(type1) :: var3 + type(type2), target :: var4 + type(type3) :: var5 + type(type4) :: var6 + type(type5) :: var7 + type(type6) :: var8 + + allocate (var1 (3)) + + allocate (var2 (4)) + + allocate (var4%t2_array(3)) + + allocate (var5%t3_array(3)) + + allocate (var6%t4_array(3)) + allocate (var6%t4_array(1)%t2_array(2)) + allocate (var6%t4_array(2)%t2_array(5)) + allocate (var6%t4_array(3)%t2_array(4)) + + allocate (var7%t5_array(1)%t2_array(2)) + allocate (var7%t5_array(2)%t2_array(5)) + allocate (var7%t5_array(3)%t2_array(4)) + allocate (var7%t5_array(4)%t2_array(1)) + + var8%ptr_1 => var4 + var8%ptr_2 => var4 + + print *, var1 ! Break Here + print *, var2 + print *, var3 + print *, var4%t2_array(1) + print *, var5%t3_array(2) + print *, var6%t4_array(1)%t2_array(1) + print *, var7%t5_array(1)%t2_array(1) + +end program main |