]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/symtab] Skip local variables in cooked index
authorTom de Vries <tdevries@suse.de>
Sat, 19 Oct 2024 05:57:21 +0000 (07:57 +0200)
committerTom de Vries <tdevries@suse.de>
Sat, 19 Oct 2024 05:57:21 +0000 (07:57 +0200)
Consider test-case gdb.dwarf2/local-var.exp.  The corresponding source
contains a function with a local variable:
...
program test
  logical :: local_var
  local_var = .TRUE.
end
...

Currently, the local variable shows up in the cooked index:
...
    [2] ((cooked_index_entry *) 0xfffec40063b0)
    name:       local_var
    canonical:  local_var
    qualified:  local_var
    DWARF tag:  DW_TAG_variable
    flags:      0x2 [IS_STATIC]
    DIE offset: 0xa3
    parent:     ((cooked_index_entry *) 0xfffec4006380) [test]
...
making the cooked index larger than necessary.

Fix this by skipping it in cooked_indexer::index_dies.

Tested on aarch64-linux.

PR symtab/32276
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32276

gdb/dwarf2/read.c
gdb/testsuite/gdb.dwarf2/local-var.exp [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/local-var.f90 [new file with mode: 0644]

index ea31d8dd851b4ac717c3ef94041177859765ce97..95498bf01ed4caa48c2243fc2826975ca572cbbe 100644 (file)
@@ -16524,7 +16524,23 @@ cooked_indexer::index_dies (cutu_reader *reader,
          continue;
        }
 
-      if (!abbrev->interesting)
+      parent_map::addr_type defer {};
+      if (std::holds_alternative<parent_map::addr_type> (parent))
+       defer = std::get<parent_map::addr_type> (parent);
+      const cooked_index_entry *parent_entry = nullptr;
+      if (std::holds_alternative<const cooked_index_entry *> (parent))
+       parent_entry = std::get<const cooked_index_entry *> (parent);
+
+      /* If a DIE parent is a DW_TAG_subprogram, then the DIE is only
+        interesting if it's a DW_TAG_subprogram or a DW_TAG_entry_point.  */
+      bool die_interesting
+       = (abbrev->interesting
+          && (parent_entry == nullptr
+              || parent_entry->tag != DW_TAG_subprogram
+              || abbrev->tag == DW_TAG_subprogram
+              || abbrev->tag == DW_TAG_entry_point));
+
+      if (!die_interesting)
        {
          info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully);
          if (fully && abbrev->has_children)
@@ -16534,14 +16550,8 @@ cooked_indexer::index_dies (cutu_reader *reader,
 
       const char *name = nullptr;
       const char *linkage_name = nullptr;
-      parent_map::addr_type defer {};
-      if (std::holds_alternative<parent_map::addr_type> (parent))
-       defer = std::get<parent_map::addr_type> (parent);
       cooked_index_flag flags = IS_STATIC;
       sect_offset sibling {};
-      const cooked_index_entry *parent_entry = nullptr;
-      if (std::holds_alternative<const cooked_index_entry *> (parent))
-       parent_entry = std::get<const cooked_index_entry *> (parent);
       const cooked_index_entry *this_parent_entry = parent_entry;
       bool is_enum_class = false;
 
diff --git a/gdb/testsuite/gdb.dwarf2/local-var.exp b/gdb/testsuite/gdb.dwarf2/local-var.exp
new file mode 100644 (file)
index 0000000..6c53305
--- /dev/null
@@ -0,0 +1,30 @@
+# 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 <http://www.gnu.org/licenses/>.
+
+# Check that local variables do not occur in the cooked index.
+
+standard_testfile .f90
+
+if { [prepare_for_testing "failed to prepare" ${testfile} $srcfile {debug f90}] } {
+    return -1
+}
+
+# Regression test for PR32276.
+gdb_test_lines "maint print objfiles" "local var not in index" "" -re-not "local_var"
+
+# Check that we still can find the type of the local variable, even when not
+# in the function.
+set hs \[^\r\n\]+
+gdb_test "ptype test::local_var" " = $hs"
diff --git a/gdb/testsuite/gdb.dwarf2/local-var.f90 b/gdb/testsuite/gdb.dwarf2/local-var.f90
new file mode 100644 (file)
index 0000000..eea0b13
--- /dev/null
@@ -0,0 +1,19 @@
+! 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 <http://www.gnu.org/licenses/>.
+
+program test
+  logical :: local_var
+  local_var = .TRUE.
+end