[PATCH 3/7] gdb/fortran: Include module variables in 'info variables' output

Andrew Burgess
2019-07-27T16:22:56Z

Due to a work around in dwarf2read.c for gFortran issue #40040,
non-constant module variables don't show up in 'info variables'
output.

The reason is that issue #40040 means that the debug symbol definition
for these module variables can sometimes have the incorrect location
information attached to it. The work around in GDB is to ignore the
location information from the debug information, and mark these
symbols as LOC_UNRESOLVED, GDB will then fall back to using the
non-debug symbols in order to figure out the location of these
symbols.

The problem with this is that GDB uses LOC_UNRESOLVED to indicate a
variable declaration, and doesn't include such symbols in its output.

In an earlier commit I extended each symbol to now explicitly track if
it is marked as a declaration in the DWARF, so GDB can now use this
information rather than LOC_UNRESOLVED to exclude declarations from
the 'info variables' output.

You might think that we could just switch from checking:

SYMBOL_CLASS (sym) != LOC_UNRESOLVED

to checking:

!SYMBOL_IS_DECLARATION (sym)

However, this is not good enough, often in C or C++ the declaration is
_also_ the definition, in which case the symbol will be marked as a
declaration, but will _not_ be of address class LOC_UNRESOLVED. The
correct condition then is that we shouldn't show declarations that are
of class LOC_UNRESOLVED. The preserves the existing C/C++ behaviour
in every case I've tried so far, and also fixes the gFortran issues
that I was seeing.

gdb/ChangeLog:

* dwarf2read.c (new_symbol): Mark symbol as declaration when
appropriate.
* symtab.h (struct symbol): Add 'is_declaration' flag.
(SYMBOL_IS_DECLARATION): Define.

gdb/testsuite/ChangeLog:

* gdb.fortran/module.exp: Extend with 'info variables' test.
---
gdb/symtab.c | 3 ++-
gdb/testsuite/ChangeLog | 4 ++++
gdb/testsuite/gdb.fortran/module.exp | 24 ++++++++++++++++++++++++
3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/gdb/symtab.c b/gdb/symtab.c
index 1925edeeaa3..84038d15dff 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4520,8 +4520,9 @@ search_symbols (const char *regexp, enum search_domain kind,
|| preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
NULL, 0) == 0)
&& ((kind == VARIABLES_DOMAIN
+ && !(SYMBOL_CLASS (sym) == LOC_UNRESOLVED
+ && SYMBOL_IS_DECLARATION (sym))
&& SYMBOL_CLASS (sym) != LOC_TYPEDEF
- && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
&& SYMBOL_CLASS (sym) != LOC_BLOCK
/* LOC_CONST can be used for more than
just enums, e.g., c++ static const
diff --git a/gdb/testsuite/gdb.fortran/module.exp b/gdb/testsuite/gdb.fortran/module.exp
index 4d71e7efac5..276f7dc3c24 100644
--- a/gdb/testsuite/gdb.fortran/module.exp
+++ b/gdb/testsuite/gdb.fortran/module.exp
@@ -13,6 +13,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

+load_lib "fortran.exp"
+
standard_testfile .f90

if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug f90}] } {
@@ -32,6 +34,28 @@ if ![runto MAIN__] then {
continue
}

+set int_type [fortran_int4]
+
+# Test 'info variables' can find module variables.
+gdb_test "info variables -n" \
+ [multi_line \
+ "All defined variables:" \
+ "" \
+ "File .*$srcfile:" \
+ "18:\[ \t\]+${int_type} mod1::var_const;" \
+ "17:\[ \t\]+${int_type} mod1::var_i;" \
+ "23:\[ \t\]+${int_type} mod2::var_i;" \
+ "28:\[ \t\]+${int_type} mod3::mod1;" \
+ "27:\[ \t\]+${int_type} mod3::mod2;" \
+ "29:\[ \t\]+${int_type} mod3::var_i;" \
+ "33:\[ \t\]+${int_type} modmany::var_a;" \
+ "33:\[ \t\]+${int_type} modmany::var_b;" \
+ "33:\[ \t\]+${int_type} modmany::var_c;" \
+ "33:\[ \t\]+${int_type} modmany::var_i;" \
+ "37:\[ \t\]+${int_type} moduse::var_x;" \
+ "37:\[ \t\]+${int_type} moduse::var_y;" ]
+
+
# Do not use simple single-letter names as GDB would pick up for expectedly
# nonexisting symbols some static variables from system libraries debuginfos.

--
2.14.5