#include "rust-lang.h"
 #include "gdbsupport/pathstuff.h"
 #include "count-one-bits.h"
+#include <unordered_set>
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  if (!per_objfile->per_bfd->filenames_cache)
-    {
-      per_objfile->per_bfd->filenames_cache.emplace ();
-
-      htab_up visited (htab_create_alloc (10,
-                                         htab_hash_pointer, htab_eq_pointer,
-                                         NULL, xcalloc, xfree));
+  /* Use caches to ensure we only call FUN once for each filename.  */
+  filename_seen_cache filenames_cache;
+  std::unordered_set<quick_file_names *> qfn_cache;
 
-      /* The rule is CUs specify all the files, including those used
-        by any TU, so there's no need to scan TUs here.  We can
-        ignore file names coming from already-expanded CUs.  */
+  /* The rule is CUs specify all the files, including those used by any TU,
+     so there's no need to scan TUs here.  We can ignore file names coming
+     from already-expanded CUs.  It is possible that an expanded CU might
+     reuse the file names data from a currently unexpanded CU, in this
+     case we don't want to report the files from the unexpanded CU.  */
 
-      for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+    {
+      if (per_objfile->symtab_set_p (per_cu))
        {
-         if (per_objfile->symtab_set_p (per_cu))
-           {
-             void **slot = htab_find_slot (visited.get (),
-                                           per_cu->v.quick->file_names,
-                                           INSERT);
-
-             *slot = per_cu->v.quick->file_names;
-           }
+         if (per_cu->v.quick->file_names != nullptr)
+           qfn_cache.insert (per_cu->v.quick->file_names);
        }
+    }
 
-      for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-       {
-         /* We only need to look at symtabs not already expanded.  */
-         if (per_objfile->symtab_set_p (per_cu))
-           continue;
-
-         quick_file_names *file_data
-           = dw2_get_file_names (per_cu, per_objfile);
-         if (file_data == NULL)
-           continue;
+  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+    {
+      /* We only need to look at symtabs not already expanded.  */
+      if (per_objfile->symtab_set_p (per_cu))
+       continue;
 
-         void **slot = htab_find_slot (visited.get (), file_data, INSERT);
-         if (*slot)
-           {
-             /* Already visited.  */
-             continue;
-           }
-         *slot = file_data;
+      quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
+      if (file_data == nullptr
+         || qfn_cache.find (file_data) != qfn_cache.end ())
+       continue;
 
-         for (int j = 0; j < file_data->num_file_names; ++j)
-           {
-             const char *filename = file_data->file_names[j];
-             per_objfile->per_bfd->filenames_cache->seen (filename);
-           }
+      for (int j = 0; j < file_data->num_file_names; ++j)
+       {
+         const char *filename = file_data->file_names[j];
+         filenames_cache.seen (filename);
        }
     }
 
-  per_objfile->per_bfd->filenames_cache->traverse ([&] (const char *filename)
+  filenames_cache.traverse ([&] (const char *filename)
     {
       gdb::unique_xmalloc_ptr<char> this_real_name;
 
 
 # in the output.  Similarly, EXPECT_SEEN_INFO_SOURCES_BASE indicates that the source file
 # info_sources_base.c must be seen in the output.
 proc test_info_sources {args expect_seen_info_sources expect_seen_info_sources_base} {
-    global gdb_prompt
+    global gdb_prompt srcfile srcfile2
 
     set seen_info_sources 0
     set seen_info_sources_base 0
     set cmd [concat "info sources " $args]
     gdb_test_multiple $cmd $cmd {
-       -re "^\[^,\]*info_sources.c(, |\[\r\n\]+)" {
-           set seen_info_sources 1
+       -re "^\[^,\]*${srcfile}(, |\[\r\n\]+)" {
+           incr seen_info_sources
            exp_continue
        }
-       -re "^\[^,\]*info_sources_base.c(, |\[\r\n\]+)" {
-           set seen_info_sources_base 1
+       -re "^\[^,\]*${srcfile2}(, |\[\r\n\]+)" {
+           incr seen_info_sources_base 1
            exp_continue
        }
        -re ", " {
     untested $testfile.exp
     return -1
 }
-gdb_test "break some_other_func" ""
 
+# List both files with no regexp:
+with_test_prefix "in main" {
+    test_info_sources "" 1 1
+}
+
+gdb_test "break some_other_func" ""
 gdb_test "continue"
 
 # List both files with no regexp: