[1/1] gdb, fortran: Fix local variable lookup in Fortran parser.

Message ID 20260429210720.150319-1-abdul.b.ijaz@intel.com
State New
Headers
Series [1/1] gdb, fortran: Fix local variable lookup in Fortran parser. |

Commit Message

Abdul Basit Ijaz April 29, 2026, 9:07 p.m. UTC
  This changes 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 (virtual function tables)
- 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)
'''
---
 gdb/f-exp.y                               |  2 +-
 gdb/testsuite/gdb.fortran/vars-lookup.exp | 38 +++++++++++++++++++++++
 gdb/testsuite/gdb.fortran/vars-lookup.f90 | 29 +++++++++++++++++
 3 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.fortran/vars-lookup.exp
 create mode 100644 gdb/testsuite/gdb.fortran/vars-lookup.f90
  

Comments

Kevin Buettner April 30, 2026, 3:44 a.m. UTC | #1
Hi Abdul,

On Wed, 29 Apr 2026 23:07:20 +0200
Abdul Basit Ijaz <abdul.b.ijaz@intel.com> wrote:

> This changes 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 (virtual function tables)

I think that your parenthetical description of SEARCH_VFT is wrong.
In symtab.h, it's defined as:

/* A convenience define for "C-like" name lookups, matching variables,
   types, and functions.  */
#define SEARCH_VFT \
  (SEARCH_VAR_DOMAIN | SEARCH_FUNCTION_DOMAIN | SEARCH_TYPE_DOMAIN)


> - 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)
> '''
> ---
>  gdb/f-exp.y                               |  2 +-
>  gdb/testsuite/gdb.fortran/vars-lookup.exp | 38 +++++++++++++++++++++++
>  gdb/testsuite/gdb.fortran/vars-lookup.f90 | 29 +++++++++++++++++
>  3 files changed, 68 insertions(+), 1 deletion(-)
>  create mode 100644 gdb/testsuite/gdb.fortran/vars-lookup.exp
>  create mode 100644 gdb/testsuite/gdb.fortran/vars-lookup.f90
> 
> 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;

This fix makes sense to me.

> diff --git a/gdb/testsuite/gdb.fortran/vars-lookup.exp
> b/gdb/testsuite/gdb.fortran/vars-lookup.exp new file mode 100644
> index 00000000000..2c9be02f1dc
> --- /dev/null
> +++ b/gdb/testsuite/gdb.fortran/vars-lookup.exp

I'd like to see a more descriptive name that describes this exact test.
If the test were sufficiently general, testing all manner of fortran
variables, then I'd be okay with the name you're giving it.  Maybe
something like "local-var-shadows-type" or "var-type-precedence"?
Those are just suggestions.  If you can think of a better name, then
use that.

> @@ -0,0 +1,38 @@
> +# 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 the variable lookup.

Perhaps say a bit more than "Test the variable lookup", above?

> +
> +require allow_fortran_tests
> +
> +standard_testfile .f90
> +load_lib fortran.exp
> +
> +if {[prepare_for_testing "failed to prepare" $testfile \
> +	${srcfile} {debug f90}]} {
> +    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]
> +gdb_test "print array" "= \\(1, 1, 1, 1, 1\\)"
> +gdb_test "ptype array" "type = $integer4 \\(-2:2\\)"

An unpatched GDB will only fail if debuginfo from a system library
is present and loaded with a conflicting 'array' declaration, right?

I'd like this test to somehow replicate that scenario without
requiring the system library.  Perhaps create a shared lib that is
loaded with this test that has a suitably conflicting declaration /
definition ?

Kevin
  
Abdul Basit Ijaz April 30, 2026, 8:21 a.m. UTC | #2
Thanks Kevin for your feedback.

>> - SEARCH_VFT (virtual function tables)

Kevin>I think that your parenthetical description of SEARCH_VFT is wrong.

Abdul> Thanks for pointing out. Will fix it accordingly in the next patch.

>> +++ b/gdb/testsuite/gdb.fortran/vars-lookup.exp

Kevin>I'd like to see a more descriptive name that describes this exact test.
If the test were sufficiently general, testing all manner of fortran variables, then I'd be okay with the name you're giving it.  Maybe something like "local-var-shadows-type" or "var-type-precedence"?

Abdul> Sure, I will rename it to "var-type-precedence" in next patch.


Kevin>An unpatched GDB will only fail if debuginfo from a system library is present and loaded with a conflicting 'array' declaration, right?

Abdul> Yes its right.

Kevin>I'd like this test to somehow replicate that scenario without requiring the system library.  Perhaps create a shared lib that is loaded with this test that has a suitably conflicting declaration / definition ?

Abdul>Sure, will load a test library to simulate same behavior and make it independent on system library. Will be added in the next patch.

Thanks & Best Regards
Abdul Basit

-----Original Message-----
From: Kevin Buettner <kevinb@redhat.com> 
Sent: Thursday, April 30, 2026 5:44 AM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; tom@tromey.com
Subject: Re: [PATCH 1/1] gdb, fortran: Fix local variable lookup in Fortran parser.

Hi Abdul,

On Wed, 29 Apr 2026 23:07:20 +0200
Abdul Basit Ijaz <abdul.b.ijaz@intel.com> wrote:

> This changes 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 (virtual function tables)

I think that your parenthetical description of SEARCH_VFT is wrong.
In symtab.h, it's defined as:

/* A convenience define for "C-like" name lookups, matching variables,
   types, and functions.  */
#define SEARCH_VFT \
  (SEARCH_VAR_DOMAIN | SEARCH_FUNCTION_DOMAIN | SEARCH_TYPE_DOMAIN)


> - 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)
> '''
> ---
>  gdb/f-exp.y                               |  2 +-
>  gdb/testsuite/gdb.fortran/vars-lookup.exp | 38 
> +++++++++++++++++++++++
>  gdb/testsuite/gdb.fortran/vars-lookup.f90 | 29 +++++++++++++++++
>  3 files changed, 68 insertions(+), 1 deletion(-)  create mode 100644 
> gdb/testsuite/gdb.fortran/vars-lookup.exp
>  create mode 100644 gdb/testsuite/gdb.fortran/vars-lookup.f90
> 
> 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;

This fix makes sense to me.

> diff --git a/gdb/testsuite/gdb.fortran/vars-lookup.exp
> b/gdb/testsuite/gdb.fortran/vars-lookup.exp new file mode 100644 index 
> 00000000000..2c9be02f1dc
> --- /dev/null
> +++ b/gdb/testsuite/gdb.fortran/vars-lookup.exp

I'd like to see a more descriptive name that describes this exact test.
If the test were sufficiently general, testing all manner of fortran variables, then I'd be okay with the name you're giving it.  Maybe something like "local-var-shadows-type" or "var-type-precedence"?
Those are just suggestions.  If you can think of a better name, then use that.

> @@ -0,0 +1,38 @@
> +# 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 the variable lookup.

Perhaps say a bit more than "Test the variable lookup", above?

> +
> +require allow_fortran_tests
> +
> +standard_testfile .f90
> +load_lib fortran.exp
> +
> +if {[prepare_for_testing "failed to prepare" $testfile \
> +	${srcfile} {debug f90}]} {
> +    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]
> +gdb_test "print array" "= \\(1, 1, 1, 1, 1\\)"
> +gdb_test "ptype array" "type = $integer4 \\(-2:2\\)"

An unpatched GDB will only fail if debuginfo from a system library is present and loaded with a conflicting 'array' declaration, right?

I'd like this test to somehow replicate that scenario without requiring the system library.  Perhaps create a shared lib that is loaded with this test that has a suitably conflicting declaration / definition ?

Kevin

Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  

Patch

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/vars-lookup.exp b/gdb/testsuite/gdb.fortran/vars-lookup.exp
new file mode 100644
index 00000000000..2c9be02f1dc
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/vars-lookup.exp
@@ -0,0 +1,38 @@ 
+# 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 the variable lookup.
+
+require allow_fortran_tests
+
+standard_testfile .f90
+load_lib fortran.exp
+
+if {[prepare_for_testing "failed to prepare" $testfile \
+	${srcfile} {debug f90}]} {
+    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]
+gdb_test "print array" "= \\(1, 1, 1, 1, 1\\)"
+gdb_test "ptype array" "type = $integer4 \\(-2:2\\)"
diff --git a/gdb/testsuite/gdb.fortran/vars-lookup.f90 b/gdb/testsuite/gdb.fortran/vars-lookup.f90
new file mode 100644
index 00000000000..9121cd007e6
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/vars-lookup.f90
@@ -0,0 +1,29 @@ 
+! 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 vars-lookup.exp.
+
+program test
+
+  implicit none
+  ! Declare variables used in this test.
+  integer, dimension (-2:2) :: array
+
+  array = 1
+
+  print *, "" ! break-here
+  print *, array
+
+end program test