https://gcc.gnu.org/g:518def14ef1a8e6e307079f205ff98ad619ccd7b

commit r15-7739-g518def14ef1a8e6e307079f205ff98ad619ccd7b
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Thu Feb 27 22:10:46 2025 +0100

    input: Fix up ICEs with --param=file-cache-files=N for N > 16 [PR118860]
    
    The following testcase ICEs, because we first construct file_cache object
    inside of *global_dc, then process options and then call file_cache::tune.
    The earlier construction allocates the m_file_slots array (using new)
    based on the static data member file_cache::num_file_slots, but then tune
    changes it, without actually reallocating all m_file_slots arrays in already
    constructed file_cache objects.
    
    I think it is just weird to have the count be a static data member and
    the pointer be non-static data member, that is just asking for issues like
    this.
    
    So, this patch changes num_file_slots into m_num_file_slots and turns tune
    into a non-static member function and changes toplev.cc to call it on the
    global_gc->get_file_cache () object.  And let's the tune just delete the
    array and allocate it freshly if there is a change in the number of slots
    or lines.
    
    Note, file_cache_slot has similar problem, but because there are many, I
    haven't moved the count into those objects; I just hope that when tune
    is called there is exactly one file_cache constructed and all the
    file_cache_slot objects constructed are pointed by its m_file_slots member,
    so also on lines change it just deletes it and allocates again.  I think
    it should be unlikely that the cache actually has any used slots by the time
    it is called.
    
    2025-02-27  Jakub Jelinek  <ja...@redhat.com>
    
            PR middle-end/118860
            * input.h (file_cache::tune): No longer static.  Rename argument
            from num_file_slots_ to num_file_slots.  Formatting fix.
            (file_cache::num_file_slots): Renamed to ...
            (file_cache::m_num_file_slots): ... this.  No longer static.
            * input.cc (file_cache_slot::tune): Change return type from void to
            size_t, return previous file_cache_slot::line_record_size value.
            Formatting fixes.
            (file_cache::tune): Rename argument from num_file_slots_ to
            num_file_slots.  Set m_num_file_slots rather than num_file_slots.
            If m_num_file_slots or file_cache_slot::line_record_size changes,
            delete[] m_file_slots and new it again.
            (file_cache::num_file_slots): Remove definition.
            (file_cache::lookup_file): Use m_num_file_slots rather than
            num_file_slots.
            (file_cache::evicted_cache_tab_entry): Likewise.
            (file_cache::file_cache): Likewise.  Initialize m_num_file_slots
            to 16.
            (file_cache::dump): Use m_num_file_slots rather than num_file_slots.
            (file_cache_slot::get_next_line): Formatting fixes.
            (file_cache_slot::read_line_num): Likewise.
            (get_source_text_between): Likewise.
            * toplev.cc (toplev::main): Call global_dc->get_file_cache ().tune
            rather than file_cache::tune.
    
            * gcc.dg/pr118860.c: New test.

Diff:
---
 gcc/input.cc                    | 71 +++++++++++++++++++++++------------------
 gcc/input.h                     |  4 +--
 gcc/testsuite/gcc.dg/pr118860.c |  5 +++
 gcc/toplev.cc                   |  3 +-
 4 files changed, 49 insertions(+), 34 deletions(-)

diff --git a/gcc/input.cc b/gcc/input.cc
index 44017589a3d1..797cc9925c19 100644
--- a/gcc/input.cc
+++ b/gcc/input.cc
@@ -79,8 +79,11 @@ public:
   void evict ();
   void set_content (const char *buf, size_t sz);
 
-  static void tune(size_t line_record_size_) {
-      line_record_size = line_record_size_;
+  static size_t tune (size_t line_record_size_)
+  {
+    size_t ret = line_record_size;
+    line_record_size = line_record_size_;
+    return ret;
   }
 
  private:
@@ -200,14 +203,17 @@ size_t file_cache_slot::recent_cached_lines_shift = 8;
 
 /* Tune file_cache.  */
 void
-file_cache::tune (size_t num_file_slots_, size_t lines)
+file_cache::tune (size_t num_file_slots, size_t lines)
 {
-  num_file_slots = num_file_slots_;
-  file_cache_slot::tune (lines);
+  if (file_cache_slot::tune (lines) != lines
+      || m_num_file_slots != num_file_slots)
+    {
+      delete[] m_file_slots;
+      m_file_slots = new file_cache_slot[num_file_slots];
+    }
+  m_num_file_slots = num_file_slots;
 }
 
-size_t file_cache::num_file_slots = 16;
-
 static const char *
 find_end_of_line (const char *s, size_t len);
 
@@ -325,7 +331,7 @@ file_cache::lookup_file (const char *file_path)
 
   /* This will contain the found cached file.  */
   file_cache_slot *r = NULL;
-  for (unsigned i = 0; i < num_file_slots; ++i)
+  for (unsigned i = 0; i < m_num_file_slots; ++i)
     {
       file_cache_slot *c = &m_file_slots[i];
       if (c->get_file_path () && !strcmp (c->get_file_path (), file_path))
@@ -419,7 +425,7 @@ file_cache::evicted_cache_tab_entry (unsigned 
*highest_use_count)
 {
   file_cache_slot *to_evict = &m_file_slots[0];
   unsigned huc = to_evict->get_use_count ();
-  for (unsigned i = 1; i < num_file_slots; ++i)
+  for (unsigned i = 1; i < m_num_file_slots; ++i)
     {
       file_cache_slot *c = &m_file_slots[i];
       bool c_is_empty = (c->get_file_path () == NULL);
@@ -449,7 +455,7 @@ file_cache::evicted_cache_tab_entry (unsigned 
*highest_use_count)
    accessed by caret diagnostic.  This cache is added to an array of
    cache and can be retrieved by lookup_file_in_cache_tab.  This
    function returns the created cache.  Note that only the last
-   num_file_slots files are cached.
+   m_num_file_slots files are cached.
 
    This can return nullptr if the FILE_PATH can't be opened for
    reading, or if the content can't be converted to the input_charset.  */
@@ -558,7 +564,7 @@ file_cache_slot::set_content (const char *buf, size_t sz)
 /* file_cache's ctor.  */
 
 file_cache::file_cache ()
-: m_file_slots (new file_cache_slot[num_file_slots])
+: m_num_file_slots (16), m_file_slots (new file_cache_slot[m_num_file_slots])
 {
   initialize_input_context (nullptr, false);
 }
@@ -573,7 +579,7 @@ file_cache::~file_cache ()
 void
 file_cache::dump (FILE *out, int indent) const
 {
-  for (size_t i = 0; i < num_file_slots; ++i)
+  for (size_t i = 0; i < m_num_file_slots; ++i)
     {
       fprintf (out, "%*sslot[%i]:\n", indent, "", (int)i);
       m_file_slots[i].dump (out, indent + 2);
@@ -869,10 +875,12 @@ file_cache_slot::get_next_line (char **line, ssize_t 
*line_len)
   /* Only update when beyond the previously cached region.  */
   if (rlen == 0 || m_line_record[rlen - 1].line_num < m_line_num)
     {
-      size_t spacing = rlen >= 2 ?
-       m_line_record[rlen - 1].line_num - m_line_record[rlen - 2].line_num : 1;
-      size_t delta = rlen >= 1 ?
-       m_line_num - m_line_record[rlen - 1].line_num : 1;
+      size_t spacing
+       = (rlen >= 2
+          ? (m_line_record[rlen - 1].line_num
+             - m_line_record[rlen - 2].line_num) : 1);
+      size_t delta
+       = rlen >= 1 ? m_line_num - m_line_record[rlen - 1].line_num : 1;
 
       size_t max_size = line_record_size;
       /* One anchor per hundred input lines.  */
@@ -880,7 +888,7 @@ file_cache_slot::get_next_line (char **line, ssize_t 
*line_len)
        max_size = m_line_num / 100;
 
       /* If we're too far beyond drop half of the lines to rebalance.  */
-      if (rlen == max_size && delta >= spacing*2)
+      if (rlen == max_size && delta >= spacing * 2)
        {
          size_t j = 0;
          for (size_t i = 1; i < rlen; i += 2)
@@ -891,24 +899,25 @@ file_cache_slot::get_next_line (char **line, ssize_t 
*line_len)
        }
 
       if (rlen < max_size && delta >= spacing)
-       m_line_record.safe_push
-         (file_cache_slot::line_info (m_line_num,
-                                      m_line_start_idx,
-                                      line_end - m_data));
+       {
+         file_cache_slot::line_info li (m_line_num, m_line_start_idx,
+                                        line_end - m_data);
+         m_line_record.safe_push (li);
+       }
     }
 
   /* Cache recent tail lines separately for fast access. This assumes
      most accesses do not skip backwards.  */
   if (m_line_recent_last == m_line_recent_first
-       || m_line_recent[m_line_recent_last].line_num == m_line_num - 1)
+      || m_line_recent[m_line_recent_last].line_num == m_line_num - 1)
     {
-      size_t mask = ((size_t)1 << recent_cached_lines_shift) - 1;
+      size_t mask = ((size_t) 1 << recent_cached_lines_shift) - 1;
       m_line_recent_last = (m_line_recent_last + 1) & mask;
       if (m_line_recent_last == m_line_recent_first)
        m_line_recent_first = (m_line_recent_first + 1) & mask;
-      m_line_recent[m_line_recent_last] =
-       file_cache_slot::line_info (m_line_num, m_line_start_idx,
-                                   line_end - m_data);
+      m_line_recent[m_line_recent_last]
+       = file_cache_slot::line_info (m_line_num, m_line_start_idx,
+                                     line_end - m_data);
     }
 
   /* Update m_line_start_idx so that it points to the next line to be
@@ -952,7 +961,7 @@ file_cache_slot::goto_next_line ()
 
 bool
 file_cache_slot::read_line_num (size_t line_num,
-                      char ** line, ssize_t *line_len)
+                               char ** line, ssize_t *line_len)
 {
   gcc_assert (line_num > 0);
 
@@ -1044,10 +1053,10 @@ file_cache::get_source_line (const char *file_path, int 
line)
 char *
 get_source_text_between (file_cache &fc, location_t start, location_t end)
 {
-  expanded_location expstart =
-    expand_location_to_spelling_point (start, LOCATION_ASPECT_START);
-  expanded_location expend =
-    expand_location_to_spelling_point (end, LOCATION_ASPECT_FINISH);
+  expanded_location expstart
+    = expand_location_to_spelling_point (start, LOCATION_ASPECT_START);
+  expanded_location expend
+    = expand_location_to_spelling_point (end, LOCATION_ASPECT_FINISH);
 
   /* If the locations are in different files or the end comes before the
      start, give up and return nothing.  */
diff --git a/gcc/input.h b/gcc/input.h
index a60afe80681f..b0a1ca0f58f2 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -161,7 +161,7 @@ class file_cache
                             const char *buffer,
                             size_t sz);
 
-  static void tune(size_t num_file_slots_, size_t lines);
+  void tune (size_t num_file_slots, size_t lines);
 
  private:
   file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
@@ -169,7 +169,7 @@ class file_cache
   file_cache_slot *lookup_file (const char *file_path);
 
  private:
-  static size_t num_file_slots;
+  size_t m_num_file_slots;
   file_cache_slot *m_file_slots;
   input_context m_input_context;
 };
diff --git a/gcc/testsuite/gcc.dg/pr118860.c b/gcc/testsuite/gcc.dg/pr118860.c
new file mode 100644
index 000000000000..4da31723d266
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr118860.c
@@ -0,0 +1,5 @@
+/* PR middle-end/118860 */
+/* { dg-do compile } */
+/* { dg-options "--param=file-cache-files=180 -Wunused" } */
+
+static void foo ();    /* { dg-warning "'foo' declared 'static' but never 
defined" } */
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index e03af8b18056..c5d46ec98015 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2333,7 +2333,8 @@ toplev::main (int argc, char **argv)
                  UNKNOWN_LOCATION, global_dc,
                  targetm.target_option.override);
 
-  file_cache::tune (param_file_cache_files, param_file_cache_lines);
+  global_dc->get_file_cache ().tune (param_file_cache_files,
+                                    param_file_cache_lines);
 
   handle_common_deferred_options ();

Reply via email to