[binutils-gdb] gdb, fortran: Fix local variable lookup in Fortran parser
Abdul Basit Ijaz via Gdb-cvs <[email protected]>
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8c0ac471835ec86a67c5b42713d9f138f31e4014 commit 8c0ac471835ec86a67c5b42713d9f138f31e4014 Author: Abdul Basit Ijaz <[email protected]> Date: Tue Apr 14 23:23:51 2026 +0200 gdb, fortran: Fix local variable lookup in Fortran parser This change fixes https://sourceware.org/bugzilla/show_bug.cgi?id=34059. The Fortran expression parser in GDB ("gdb/f-exp.y") previously performed symbol lookup in this order when parsing identifiers: - SEARCH_STRUCT_DOMAIN (types/structs) - SEARCH_VFT ("C-like" name lookups for variables/types/functions) - SEARCH_MODULE_DOMAIN (modules) It searched for "types before variables", causing type names from shared libraries to shadow local variable names. For a reproducer like the one given below, the Fortran parser fails to look up local variable name "array" and treats it as a type value instead of a variable, because there's a conflicting "array" type from system libraries. 1 program test 2 3 ! Declare variables used in this test. 4 integer, dimension (-2:2) :: array 5 6 array = 1 7 8 print *, "" ! Break here 9 print *, array 10 11 end program test Before the change, GDB shows: ''' ./gdb --data-directory=./data-directory --args /tmp/a.out GNU gdb (GDB) 18.0.50.20260408-git Copyright (C) 2026 Free Software Foundation, Inc. ... Reading symbols from /tmp/a.out... (gdb) break 8 Breakpoint 1 at 0x11b3: file test.f90, line 8. (gdb) run Starting program: /tmp/a.out [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, test () at test.f90:8 8 print *, "" ! Break here (gdb) info locals array = (1, 1, 1, 1, 1) (gdb) print array Attempt to use a type name as an expression (gdb) ptype array type = Type array Type, C_Union :: :: u PTR TO -> ( char :: scratch(0:15 )) End Type array ''' This issue is fixed in the Fortran expression parser in GDB ("gdb/f-exp.y") by prioritizing SEARCH_VFT over other search domains during symbol lookup. After the change, the 'array' variable is resolved to the correct value. ''' (gdb) print array $1 = (1, 1, 1, 1, 1) (gdb) ptype array type = integer(kind=4) (-2:2) ''' Approved-by: Kevin Buettner <[email protected]> Diff: --- gdb/f-exp.y | 2 +- .../gdb.fortran/var-type-precedence-lib.c | 30 +++++++++++ gdb/testsuite/gdb.fortran/var-type-precedence.exp | 60 ++++++++++++++++++++++ gdb/testsuite/gdb.fortran/var-type-precedence.f90 | 40 +++++++++++++++ 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/gdb/f-exp.y b/gdb/f-exp.y index 278e2091403..4216112c10b 100644 --- a/gdb/f-exp.y +++ b/gdb/f-exp.y @@ -1651,8 +1651,8 @@ yylex (void) struct block_symbol result; const domain_search_flags lookup_domains[] = { - SEARCH_STRUCT_DOMAIN, SEARCH_VFT, + SEARCH_STRUCT_DOMAIN, SEARCH_MODULE_DOMAIN }; int hextype; diff --git a/gdb/testsuite/gdb.fortran/var-type-precedence-lib.c b/gdb/testsuite/gdb.fortran/var-type-precedence-lib.c new file mode 100644 index 00000000000..87bd19fad84 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/var-type-precedence-lib.c @@ -0,0 +1,30 @@ +/* Copyright 2026 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/>. */ + +/* Define a struct type that will conflict with Fortran variable name. */ +struct type_shadowing_var +{ + int value; +}; + +/* Global variables to ensure types are in debug info. */ +static struct type_shadowing_var global_conflicting_var = {42}; + +/* Function to ensure library is linked and types are used. */ +void +fortran_var_type_order_test (void) +{ + global_conflicting_var.value = 42; +} diff --git a/gdb/testsuite/gdb.fortran/var-type-precedence.exp b/gdb/testsuite/gdb.fortran/var-type-precedence.exp new file mode 100644 index 00000000000..8c9f80d43d9 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/var-type-precedence.exp @@ -0,0 +1,60 @@ +# Copyright 2026 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 variable lookup when local Fortran variable names conflict with +# type names from a C shared library. + +require allow_fortran_tests + +standard_testfile var-type-precedence.f90 var-type-precedence-lib.c +load_lib fortran.exp + +set libname "${testfile}-lib" +set srcfile_lib ${srcdir}/${subdir}/${srcfile2} +set binfile_lib [standard_output_file ${libname}.so] + +# Compile the C shared library. +if {[gdb_compile_shlib ${srcfile_lib} ${binfile_lib} \ + {debug}] != ""} { + untested "failed to compile C shared library" + return +} + +# Compile the Fortran main program with the C shared library. +if {[prepare_for_testing "failed to prepare" $testfile \ + ${srcfile} [list debug f90 shlib=${binfile_lib}]]} { + return +} + +if {![fortran_runto_main]} { + return +} + +set bp_loc [gdb_get_line_number "break-here"] +gdb_breakpoint "$srcfile:$bp_loc" +gdb_continue_to_breakpoint "stop-at-bp" ".*$srcfile:$bp_loc.*" + +set integer4 [fortran_int4] + +# Test that local variable 'type_shadowing_var' is resolved correctly. +gdb_test "print type_shadowing_var" "= \\(1, 1, 1, 1, 1\\)" \ + "print local type_shadowing_var variable" +gdb_test "ptype type_shadowing_var" "type = $integer4 \\(-2:2\\)" \ + "ptype local type_shadowing_var" + +# Verify the C types exist in debug info by checking info types. +gdb_test "info types type_shadowing_var" \ + ".*File.*var-type-precedence-lib\\.c:.*struct type_shadowing_var.*" \ + "C type type_shadowing_var exists in debug info" diff --git a/gdb/testsuite/gdb.fortran/var-type-precedence.f90 b/gdb/testsuite/gdb.fortran/var-type-precedence.f90 new file mode 100644 index 00000000000..c0707cacda6 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/var-type-precedence.f90 @@ -0,0 +1,40 @@ +! Copyright 2026 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/>. + +! Source code for var-type-precedence test to verify that local Fortran +! variables take precedence over conflicting C type names from shared +! libraries. + +program test + use iso_c_binding + implicit none + + interface + subroutine fortran_var_type_order_test () bind (C) + end subroutine fortran_var_type_order_test + end interface + + ! Declare variables with names that conflict with types in C library. + integer, dimension (-2:2) :: type_shadowing_var + + ! Call C library function to ensure it's linked. + call fortran_var_type_order_test () + + type_shadowing_var = 1 + + print *, "" ! break-here + print *, type_shadowing_var + +end program test