public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [pushed] input.h: eliminate implicit users of global_dc's file_cache
@ 2023-11-14 16:32 David Malcolm
  0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2023-11-14 16:32 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

This patch eliminates the following functions that implicitly used
global_dc's file cache:

  extern char_span location_get_source_line (const char *file_path, int line);
  extern char_span get_source_file_content (const char *file_path);
  extern bool location_missing_trailing_newline (const char *file_path);

in favor of explicitly using a specific file_cache throughout, and only
using global_dc's file_cache in gcc-specific code.

Rather than creating global_dc's file_cache the first time its needed,
this patch simply creates one when a diagnostic_context is initialized,
and eliminates diagnostic_file_cache_init.

No functional change intended.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r14-5452-g1bdd665a025a74.

gcc/c-family/ChangeLog:
	* c-common.cc (c_get_substring_location): Use global_dc's
	file_cache.
	* c-format.cc (get_corrected_substring): Likewise.
	* c-indentation.cc (get_visual_column): Add file_cache param.
	(get_first_nws_vis_column): Likewise.
	(detect_intervening_unindent): Likewise.
	(should_warn_for_misleading_indentation): Use global_dc's
	file_cache.
	(assert_get_visual_column_succeeds): Add file_cache param.
	(ASSERT_GET_VISUAL_COLUMN_SUCCEEDS): Likewise.
	(assert_get_visual_column_fails): Likewise.
	(define ASSERT_GET_VISUAL_COLUMN_FAILS): Likewise.
	(selftest::test_get_visual_column): Create and use a temporary
	file_cache.

gcc/cp/ChangeLog:
	* contracts.cc (build_comment): Use global_dc's file_cache.

gcc/ChangeLog:
	* diagnostic-format-sarif.cc (sarif_builder::get_sarif_column):
	Use m_context's file_cache.
	(sarif_builder::maybe_make_artifact_content_object): Likewise.
	(sarif_builder::get_source_lines): Likewise.
	* diagnostic-show-locus.cc
	(exploc_with_display_col::exploc_with_display_col): Add file_cache
	param.
	(layout::m_file_cache): New field.
	(make_range): Add file_cache param.
	(selftest::test_layout_range_for_single_point): Create and use a
	temporary file_cache.
	(selftest::test_layout_range_for_single_line): Likewise.
	(selftest::test_layout_range_for_multiple_lines): Likewise.
	(layout::layout): Initialize m_file_cache from the context and use it.
	(layout::maybe_add_location_range): Use m_file_cache.
	(layout::calculate_x_offset_display): Likewise.
	(get_affected_range): Add file_cache param.
	(get_printed_columns): Likewise.
	(line_corrections::line_corrections): Likewwise.
	(line_corrections::m_file_cache): New field.
	(source_line::source_line): Add file_cache param.
	(line_corrections::add_hint): Use m_file_cache.
	(layout::print_trailing_fixits): Likewise.
	(layout::print_line): Likewise.
	(selftest::test_layout_x_offset_display_utf8): Create and use a
	temporary file_cache.
	(selftest::test_layout_x_offset_display_tab): Likewise.
	(selftest::test_diagnostic_show_locus_one_liner_utf8): Likewise.
	(selftest::test_add_location_if_nearby): Pass global_dc's
	file_cache to temp_source_file ctor.
	(selftest::test_overlapped_fixit_printing): Create and use a
	temporary file_cache.
	(selftest::test_overlapped_fixit_printing_utf8): Likewise.
	(selftest::test_overlapped_fixit_printing_2): Use dc's file_cache.
	* diagnostic.cc (diagnostic_context::initialize): Always create a
	file_cache.
	(diagnostic_context::initialize_input_context): Assume
	m_file_cache has already been created.
	(diagnostic_context::create_edit_context): Pass m_file_cache to
	edit_context.
	(convert_column_unit): Add file_cache param.
	(diagnostic_context::converted_column): Use context's file_cache.
	(print_parseable_fixits): Add file_cache param.
	(diagnostic_context::report_diagnostic): Use context's file_cache.
	(selftest::test_print_parseable_fixits_none): Create and use a
	temporary file_cache.
	(selftest::test_print_parseable_fixits_insert): Likewise.
	(selftest::test_print_parseable_fixits_remove): Likewise.
	(selftest::test_print_parseable_fixits_replace): Likewise.
	(selftest::test_print_parseable_fixits_bytes_vs_display_columns):
	Likewise.
	* diagnostic.h (diagnostic_context::file_cache_init): Delete.
	(diagnostic_context::get_file_cache): Convert return type from
	pointer to reference.
	* edit-context.cc (edited_file::get_file_cache): New.
	(edited_file::m_edit_context): New.
	(edit_context::edit_context): Add file_cache param.
	(edit_context::get_or_insert_file): Pass this to edited_file's
	ctor.
	(edited_file::edited_file): Add edit_context param.
	(edited_file::print_content): Use get_file_cache.
	(edited_file::print_diff_hunk): Likewise.
	(edited_file::print_run_of_changed_lines): Likewise.
	(edited_file::get_or_insert_line): Likewise.
	(edited_file::get_num_lines): Likewise.
	(edited_line::edited_line): Pass in file_cache and use it.
	(selftest::test_get_content): Create and use a
	temporary file_cache.
	(selftest::test_applying_fixits_insert_before): Likewise.
	(selftest::test_applying_fixits_insert_after): Likewise.
	(selftest::test_applying_fixits_insert_after_at_line_end):
	Likewise.
	(selftest::test_applying_fixits_insert_after_failure): Likewise.
	(selftest::test_applying_fixits_insert_containing_newline):
	Likewise.
	(selftest::test_applying_fixits_growing_replace): Likewise.
	(selftest::test_applying_fixits_shrinking_replace): Likewise.
	(selftest::test_applying_fixits_replace_containing_newline):
	Likewise.
	(selftest::test_applying_fixits_remove): Likewise.
	(selftest::test_applying_fixits_multiple): Likewise.
	(selftest::test_applying_fixits_multiple_lines): Likewise.
	(selftest::test_applying_fixits_modernize_named_init): Likewise.
	(selftest::test_applying_fixits_modernize_named_init): Likewise.
	(selftest::test_applying_fixits_unreadable_file): Likewise.
	(selftest::test_applying_fixits_line_out_of_range): Likewise.
	(selftest::test_applying_fixits_column_validation): Likewise.
	(selftest::test_applying_fixits_column_validation): Likewise.
	(selftest::test_applying_fixits_column_validation): Likewise.
	(selftest::test_applying_fixits_column_validation): Likewise.
	* edit-context.h (edit_context::edit_context): Add file_cache
	param.
	(edit_context::get_file_cache): New.
	(edit_context::m_file_cache): New.
	* final.cc: Include "diagnostic.h".
	(asm_show_source): Use global_dc's file_cache.
	* gcc-rich-location.cc (blank_line_before_p): Add file_cache
	param.
	(use_new_line): Likewise.
	(gcc_rich_location::add_fixit_insert_formatted): Use global dc's
	file_cache.
	* input.cc (diagnostic_file_cache_init): Delete.
	(diagnostic_context::file_cache_init): Delete.
	(diagnostics_file_cache_forcibly_evict_file): Delete.
	(file_cache::missing_trailing_newline_p): New.
	(file_cache::evicted_cache_tab_entry): Don't call
	diagnostic_file_cache_init.
	(location_get_source_line): Delete.
	(get_source_text_between): Add file_cache param.
	(get_source_file_content): Delete.
	(location_missing_trailing_newline): Delete.
	(location_compute_display_column): Add file_cache param.
	(dump_location_info): Create and use temporary file_cache.
	(get_substring_ranges_for_loc): Add file_cache param.
	(get_location_within_string): Likewise.
	(get_source_range_for_char): Likewise.
	(get_num_source_ranges_for_substring): Likewise.
	(selftest::test_reading_source_line): Create and use temporary
	file_cache.
	(selftest::lexer_test::m_file_cache): New field.
	(selftest::assert_char_at_range): Use test.m_file_cache.
	(selftest::assert_num_substring_ranges): Likewise.
	(selftest::assert_has_no_substring_ranges): Likewise.
	(selftest::test_lexer_string_locations_concatenation_2): Likewise.
	* input.h (class file_cache): New forward decl.
	(location_compute_display_column): Add file_cache param.
	(location_get_source_line): Delete.
	(get_source_text_between): Add file_cache param.
	(get_source_file_content): Delete.
	(location_missing_trailing_newline): Delete.
	(file_cache::missing_trailing_newline_p): New decl.
	(diagnostics_file_cache_forcibly_evict_file): Delete.
	* selftest.cc (named_temp_file::named_temp_file): Add file_cache
	param.
	(named_temp_file::~named_temp_file): Optionally evict the file
	from the given file_cache.
	(temp_source_file::temp_source_file): Add file_cache param.
	* selftest.h (class file_cache): New forward decl.
	(named_temp_file::named_temp_file): Add file_cache param.
	(named_temp_file::m_file_cache): New field.
	(temp_source_file::temp_source_file): Add file_cache param.
	* substring-locations.h (get_location_within_string): Add
	file_cache param.

gcc/testsuite/ChangeLog:
	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Use
	global_dc's file cache.
	* gcc.dg/plugin/expensive_selftests_plugin.c: Likewise.
---
 gcc/c-family/c-common.cc                      |   4 +-
 gcc/c-family/c-format.cc                      |   3 +-
 gcc/c-family/c-indentation.cc                 |  73 +++++---
 gcc/cp/contracts.cc                           |   3 +-
 gcc/diagnostic-format-sarif.cc                |   7 +-
 gcc/diagnostic-show-locus.cc                  | 166 +++++++++++-------
 gcc/diagnostic.cc                             |  47 +++--
 gcc/diagnostic.h                              |   7 +-
 gcc/edit-context.cc                           | 108 ++++++++----
 gcc/edit-context.h                            |   5 +-
 gcc/final.cc                                  |   4 +-
 gcc/gcc-rich-location.cc                      |  13 +-
 gcc/input.cc                                  | 125 +++++--------
 gcc/input.h                                   |  15 +-
 gcc/selftest.cc                               |  12 +-
 gcc/selftest.h                                |  11 +-
 gcc/substring-locations.h                     |   1 +
 .../diagnostic_plugin_test_show_locus.c       |   3 +-
 .../plugin/expensive_selftests_plugin.c       |   2 +-
 19 files changed, 346 insertions(+), 263 deletions(-)

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 77faf179cca8..eade580a0206 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -894,7 +894,9 @@ c_get_substring_location (const substring_loc &substr_loc,
   if (tok_type == CPP_OTHER)
     return "unrecognized string type";
 
-  return get_location_within_string (parse_in, g_string_concat_db,
+  return get_location_within_string (parse_in,
+				     global_dc->get_file_cache (),
+				     g_string_concat_db,
 				     substr_loc.get_fmt_string_loc (),
 				     tok_type,
 				     substr_loc.get_caret_idx (),
diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index 1a25141071f3..a6497c662dca 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -4570,7 +4570,8 @@ get_corrected_substring (const substring_loc &fmt_loc,
   if (caret.column > finish.column)
     return NULL;
 
-  char_span line = location_get_source_line (start.file, start.line);
+  char_span line
+    = global_dc->get_file_cache ().get_source_line (start.file, start.line);
   if (!line)
     return NULL;
 
diff --git a/gcc/c-family/c-indentation.cc b/gcc/c-family/c-indentation.cc
index 5b4614f5fd53..a81dffdcbd0c 100644
--- a/gcc/c-family/c-indentation.cc
+++ b/gcc/c-family/c-indentation.cc
@@ -45,12 +45,13 @@ next_tab_stop (unsigned int vis_column, unsigned int tab_width)
    on the line (up to or before EXPLOC).  */
 
 static bool
-get_visual_column (expanded_location exploc,
+get_visual_column (file_cache &fc,
+		   expanded_location exploc,
 		   unsigned int *out,
 		   unsigned int *first_nws,
 		   unsigned int tab_width)
 {
-  char_span line = location_get_source_line (exploc.file, exploc.line);
+  char_span line = fc.get_source_line (exploc.file, exploc.line);
   if (!line)
     return false;
   if ((size_t)exploc.column > line.length ())
@@ -87,13 +88,14 @@ get_visual_column (expanded_location exploc,
    Otherwise, return false, leaving *FIRST_NWS untouched.  */
 
 static bool
-get_first_nws_vis_column (const char *file, int line_num,
+get_first_nws_vis_column (file_cache &fc,
+			  const char *file, int line_num,
 			  unsigned int *first_nws,
 			  unsigned int tab_width)
 {
   gcc_assert (first_nws);
 
-  char_span line = location_get_source_line (file, line_num);
+  char_span line = fc.get_source_line (file, line_num);
   if (!line)
     return false;
   unsigned int vis_column = 0;
@@ -158,7 +160,8 @@ get_first_nws_vis_column (const char *file, int line_num,
    Return true if such an unindent/outdent is detected.  */
 
 static bool
-detect_intervening_unindent (const char *file,
+detect_intervening_unindent (file_cache &fc,
+			     const char *file,
 			     int body_line,
 			     int next_stmt_line,
 			     unsigned int vis_column,
@@ -170,7 +173,7 @@ detect_intervening_unindent (const char *file,
   for (int line = body_line + 1; line < next_stmt_line; line++)
     {
       unsigned int line_vis_column;
-      if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width))
+      if (get_first_nws_vis_column (fc, file, line, &line_vis_column, tab_width))
 	if (line_vis_column < vis_column)
 	  return true;
     }
@@ -337,6 +340,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
   if (next_stmt_exploc.file != body_exploc.file)
     return false;
 
+  file_cache &fc = global_dc->get_file_cache ();
+
   /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
      the location of the guard.
 
@@ -376,7 +381,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
 	  gcc_assert (guard_exploc.line == next_stmt_exploc.line);
 	  unsigned int guard_vis_column;
 	  unsigned int guard_line_first_nws;
-	  if (!get_visual_column (guard_exploc,
+	  if (!get_visual_column (fc,
+				  guard_exploc,
 				  &guard_vis_column,
 				  &guard_line_first_nws, tab_width))
 	    return false;
@@ -436,15 +442,18 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
 	 the case for input files containing #line directives, and these
 	 are often for autogenerated sources (e.g. from .md files), where
 	 it's not clear that it's meaningful to look at indentation.  */
-      if (!get_visual_column (next_stmt_exploc,
+      if (!get_visual_column (fc,
+			      next_stmt_exploc,
 			      &next_stmt_vis_column,
 			      &next_stmt_line_first_nws, tab_width))
 	return false;
-      if (!get_visual_column (body_exploc,
+      if (!get_visual_column (fc,
+			      body_exploc,
 			      &body_vis_column,
 			      &body_line_first_nws, tab_width))
 	return false;
-      if (!get_visual_column (guard_exploc,
+      if (!get_visual_column (fc,
+			      guard_exploc,
 			      &guard_vis_column,
 			      &guard_line_first_nws, tab_width))
 	return false;
@@ -528,7 +537,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
 
 	  /* Don't warn if there is an unindent between the two statements. */
 	  int vis_column = MIN (next_stmt_vis_column, body_vis_column);
-	  if (detect_intervening_unindent (body_exploc.file, body_exploc.line,
+	  if (detect_intervening_unindent (fc,
+					   body_exploc.file, body_exploc.line,
 					   next_stmt_exploc.line,
 					   vis_column, tab_width))
 	    return false;
@@ -686,6 +696,7 @@ test_next_tab_stop ()
 
 static void
 assert_get_visual_column_succeeds (const location &loc,
+				   file_cache &fc,
 				   const char *file, int line, int column,
 				   const unsigned int tab_width,
 				   unsigned int expected_visual_column,
@@ -699,7 +710,8 @@ assert_get_visual_column_succeeds (const location &loc,
   exploc.sysp = false;
   unsigned int actual_visual_column;
   unsigned int actual_first_nws;
-  bool result = get_visual_column (exploc,
+  bool result = get_visual_column (fc,
+				   exploc,
 				   &actual_visual_column,
 				   &actual_first_nws, tab_width);
   ASSERT_TRUE_AT (loc, result);
@@ -710,12 +722,14 @@ assert_get_visual_column_succeeds (const location &loc,
 /* Verify that the given call to get_visual_column succeeds, with
    the given results.  */
 
-#define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILENAME, LINE, COLUMN,	\
+#define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILE_CACHE,			\
+					  FILENAME, LINE, COLUMN,	\
 					  TAB_WIDTH,			\
 					  EXPECTED_VISUAL_COLUMN,	\
 					  EXPECTED_FIRST_NWS)		\
   SELFTEST_BEGIN_STMT							\
     assert_get_visual_column_succeeds (SELFTEST_LOCATION,		\
+				       FILE_CACHE,			\
 				       FILENAME, LINE, COLUMN,		\
 				       TAB_WIDTH,			\
 				       EXPECTED_VISUAL_COLUMN,		\
@@ -726,6 +740,7 @@ assert_get_visual_column_succeeds (const location &loc,
 
 static void
 assert_get_visual_column_fails (const location &loc,
+				file_cache &fc,
 				const char *file, int line, int column,
 				const unsigned int tab_width)
 {
@@ -737,7 +752,8 @@ assert_get_visual_column_fails (const location &loc,
   exploc.sysp = false;
   unsigned int actual_visual_column;
   unsigned int actual_first_nws;
-  bool result = get_visual_column (exploc,
+  bool result = get_visual_column (fc,
+				   exploc,
 				   &actual_visual_column,
 				   &actual_first_nws, tab_width);
   ASSERT_FALSE_AT (loc, result);
@@ -745,10 +761,12 @@ assert_get_visual_column_fails (const location &loc,
 
 /* Verify that the given call to get_visual_column fails gracefully.  */
 
-#define ASSERT_GET_VISUAL_COLUMN_FAILS(FILENAME, LINE, COLUMN,	\
+#define ASSERT_GET_VISUAL_COLUMN_FAILS(FILE_CACHE,		\
+				       FILENAME, LINE, COLUMN,	\
 				       TAB_WIDTH)		\
   SELFTEST_BEGIN_STMT						\
     assert_get_visual_column_fails (SELFTEST_LOCATION,		\
+				    FILE_CACHE,			\
 				    FILENAME, LINE, COLUMN,	\
 				    TAB_WIDTH);		\
   SELFTEST_END_STMT
@@ -770,6 +788,7 @@ test_get_visual_column ()
 			 "\t line 2\n");
   line_table_test ltt;
   temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
+  file_cache fc;
 
   const unsigned int tab_width = 8;
   const char *file = tmp.get_filename ();
@@ -777,27 +796,27 @@ test_get_visual_column ()
   /* Line 1 (space-based indentation).  */
   {
     const int line = 1;
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 1, 1);
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 2, 2);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 1, tab_width, 0, 0);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 2, tab_width, 1, 1);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 3, tab_width, 2, 2);
     /* first_nws should have stopped increasing.  */
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 3, 2);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 4, tab_width, 3, 2);
     /* Verify the end-of-line boundary.  */
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 7, 2);
-    ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 8, tab_width, 7, 2);
+    ASSERT_GET_VISUAL_COLUMN_FAILS (fc, file, line, 9, tab_width);
   }
 
   /* Line 2 (tab-based indentation).  */
   {
     const int line = 2;
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 8, 8);
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 9, 9);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 1, tab_width, 0, 0);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 2, tab_width, 8, 8);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 3, tab_width, 9, 9);
     /* first_nws should have stopped increasing.  */
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 10, 9);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 4, tab_width, 10, 9);
     /* Verify the end-of-line boundary.  */
-    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 14, 9);
-    ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
+    ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 8, tab_width, 14, 9);
+    ASSERT_GET_VISUAL_COLUMN_FAILS (fc, file, line, 9, tab_width);
   }
 }
 
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index 9d1cb558f4f7..66d2298a9bfa 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -722,7 +722,8 @@ build_comment (cp_expr condition)
 {
   /* Try to get the actual source text for the condition; if that fails pretty
      print the resulting tree.  */
-  char *str = get_source_text_between (condition.get_start (),
+  char *str = get_source_text_between (global_dc->get_file_cache (),
+				       condition.get_start (),
 				       condition.get_finish ());
   if (!str)
     {
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index fa3ca2e9ae9a..9510f4add80f 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -921,7 +921,8 @@ int
 sarif_builder::get_sarif_column (expanded_location exploc) const
 {
   cpp_char_column_policy policy (m_tabstop, cpp_wcwidth);
-  return location_compute_display_column (exploc, policy);
+  return location_compute_display_column (m_context->get_file_cache (),
+					  exploc, policy);
 }
 
 /* Make a region object (SARIF v2.1.0 section 3.30) for LOC,
@@ -1534,7 +1535,7 @@ sarif_builder::maybe_make_artifact_content_object (const char *filename) const
 {
   /* Let input.cc handle any charset conversion.  */
   char_span utf8_content
-    = m_context->get_file_cache ()->get_source_file_content (filename);
+    = m_context->get_file_cache ().get_source_file_content (filename);
   if (!utf8_content)
     return NULL;
 
@@ -1562,7 +1563,7 @@ sarif_builder::get_source_lines (const char *filename,
   for (int line = start_line; line <= end_line; line++)
     {
       char_span line_content
-	= m_context->get_file_cache ()->get_source_line (filename, line);
+	= m_context->get_file_cache ().get_source_line (filename, line);
       if (!line_content.get_buffer ())
 	return NULL;
       result.reserve (line_content.length () + 1);
diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index 5edc319c3130..169f59cb0573 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -175,11 +175,12 @@ enum column_unit {
 class exploc_with_display_col : public expanded_location
 {
  public:
-  exploc_with_display_col (const expanded_location &exploc,
+  exploc_with_display_col (file_cache &fc,
+			   const expanded_location &exploc,
 			   const cpp_char_column_policy &policy,
 			   enum location_aspect aspect)
   : expanded_location (exploc),
-    m_display_col (location_compute_display_column (exploc, policy))
+    m_display_col (location_compute_display_column (fc, exploc, policy))
   {
     if (exploc.column > 0)
       {
@@ -190,7 +191,7 @@ class exploc_with_display_col : public expanded_location
 	    expanded_location prev_exploc (exploc);
 	    prev_exploc.column--;
 	    int prev_display_col
-	      = (location_compute_display_column (prev_exploc, policy));
+	      = (location_compute_display_column (fc, prev_exploc, policy));
 	    m_display_col = prev_display_col + 1;
 	  }
       }
@@ -432,6 +433,7 @@ class layout
 
   const diagnostic_source_printing_options &m_options;
   const line_maps *m_line_table;
+  file_cache &m_file_cache;
   pretty_printer *m_pp;
   char_display_policy m_policy;
   location_t m_primary_loc;
@@ -707,18 +709,22 @@ static cpp_char_column_policy def_policy ()
    e.g. in test_diagnostic_show_locus_one_liner_utf8().  */
 
 static layout_range
-make_range (int start_line, int start_col, int end_line, int end_col)
+make_range (file_cache &fc,
+	    int start_line, int start_col, int end_line, int end_col)
 {
   const expanded_location start_exploc
     = {"", start_line, start_col, NULL, false};
   const expanded_location finish_exploc
     = {"", end_line, end_col, NULL, false};
-  return layout_range (exploc_with_display_col (start_exploc, def_policy (),
+  return layout_range (exploc_with_display_col (fc,
+						start_exploc, def_policy (),
 						LOCATION_ASPECT_START),
-		       exploc_with_display_col (finish_exploc, def_policy (),
+		       exploc_with_display_col (fc,
+						finish_exploc, def_policy (),
 						LOCATION_ASPECT_FINISH),
 		       SHOW_RANGE_WITHOUT_CARET,
-		       exploc_with_display_col (start_exploc, def_policy (),
+		       exploc_with_display_col (fc,
+						start_exploc, def_policy (),
 						LOCATION_ASPECT_CARET),
 		       0, NULL);
 }
@@ -732,7 +738,8 @@ make_range (int start_line, int start_col, int end_line, int end_col)
 static void
 test_layout_range_for_single_point ()
 {
-  layout_range point = make_range (7, 10, 7, 10);
+  file_cache fc;
+  layout_range point = make_range (fc, 7, 10, 7, 10);
 
   /* Tests for layout_range::contains_point.  */
 
@@ -768,7 +775,8 @@ test_layout_range_for_single_point ()
 static void
 test_layout_range_for_single_line ()
 {
-  layout_range example_a = make_range (2, 22, 2, 38);
+  file_cache fc;
+  layout_range example_a = make_range (fc, 2, 22, 2, 38);
 
   /* Tests for layout_range::contains_point.  */
 
@@ -810,7 +818,8 @@ test_layout_range_for_single_line ()
 static void
 test_layout_range_for_multiple_lines ()
 {
-  layout_range example_b = make_range (3, 14, 5, 8);
+  file_cache fc;
+  layout_range example_b = make_range (fc, 3, 14, 5, 8);
 
   /* Tests for layout_range::contains_point.  */
 
@@ -1188,10 +1197,12 @@ layout::layout (const diagnostic_context &context,
 		pretty_printer *pp)
 : m_options (context.m_source_printing),
   m_line_table (richloc.get_line_table ()),
+  m_file_cache (context.get_file_cache ()),
   m_pp (pp ? pp : context.printer),
   m_policy (make_policy (context, richloc)),
   m_primary_loc (richloc.get_range (0)->m_loc),
-  m_exploc (richloc.get_expanded_location (0), m_policy,
+  m_exploc (m_file_cache,
+	    richloc.get_expanded_location (0), m_policy,
 	    LOCATION_ASPECT_CARET),
   m_colorizer (m_pp, diagnostic_kind),
   m_diagnostic_path_p (diagnostic_kind == DK_DIAGNOSTIC_PATH),
@@ -1286,12 +1297,15 @@ layout::maybe_add_location_range (const location_range *loc_range,
 
   /* Everything is now known to be in the correct source file,
      but it may require further sanitization.  */
-  layout_range ri (exploc_with_display_col (start, m_policy,
+  layout_range ri (exploc_with_display_col (m_file_cache,
+					    start, m_policy,
 					    LOCATION_ASPECT_START),
-		   exploc_with_display_col (finish, m_policy,
+		   exploc_with_display_col (m_file_cache,
+					    finish, m_policy,
 					    LOCATION_ASPECT_FINISH),
 		   loc_range->m_range_display_kind,
-		   exploc_with_display_col (caret, m_policy,
+		   exploc_with_display_col (m_file_cache,
+					    caret, m_policy,
 					    LOCATION_ASPECT_CARET),
 		   original_idx, loc_range->m_label);
 
@@ -1614,8 +1628,8 @@ layout::calculate_x_offset_display ()
       return;
     }
 
-  const char_span line = location_get_source_line (m_exploc.file,
-						   m_exploc.line);
+  const char_span line = m_file_cache.get_source_line (m_exploc.file,
+						       m_exploc.line);
   if (!line)
     {
       /* Nothing to do, we couldn't find the source line.  */
@@ -2252,7 +2266,8 @@ public:
 
 /* Get the range of bytes or display columns that HINT would affect.  */
 static column_range
-get_affected_range (const cpp_char_column_policy &policy,
+get_affected_range (file_cache &fc,
+		    const cpp_char_column_policy &policy,
 		    const fixit_hint *hint, enum column_unit col_unit)
 {
   expanded_location exploc_start = expand_location (hint->get_start_loc ());
@@ -2263,11 +2278,12 @@ get_affected_range (const cpp_char_column_policy &policy,
   int finish_column;
   if (col_unit == CU_DISPLAY_COLS)
     {
-      start_column = location_compute_display_column (exploc_start, policy);
+      start_column = location_compute_display_column (fc, exploc_start, policy);
       if (hint->insertion_p ())
 	finish_column = start_column - 1;
       else
-	finish_column = location_compute_display_column (exploc_finish, policy);
+	finish_column
+	  = location_compute_display_column (fc, exploc_finish, policy);
     }
   else
     {
@@ -2280,11 +2296,12 @@ get_affected_range (const cpp_char_column_policy &policy,
 /* Get the range of display columns that would be printed for HINT.  */
 
 static column_range
-get_printed_columns (const cpp_char_column_policy &policy,
+get_printed_columns (file_cache &fc,
+		     const cpp_char_column_policy &policy,
 		     const fixit_hint *hint)
 {
   expanded_location exploc = expand_location (hint->get_start_loc ());
-  int start_column = location_compute_display_column (exploc, policy);
+  int start_column = location_compute_display_column (fc, exploc, policy);
   int hint_width = cpp_display_width (hint->get_string (), hint->get_length (),
 				      policy);
   int final_hint_column = start_column + hint_width - 1;
@@ -2296,7 +2313,7 @@ get_printed_columns (const cpp_char_column_policy &policy,
     {
       exploc = expand_location (hint->get_next_loc ());
       --exploc.column;
-      int finish_column = location_compute_display_column (exploc, policy);
+      int finish_column = location_compute_display_column (fc, exploc, policy);
       return column_range (start_column,
 			   MAX (finish_column, final_hint_column));
     }
@@ -2402,15 +2419,18 @@ correction::ensure_terminated ()
 class line_corrections
 {
 public:
-  line_corrections (const char_display_policy &policy,
+  line_corrections (file_cache &fc,
+		    const char_display_policy &policy,
 		    const char *filename,
 		    linenum_type row)
-  : m_policy (policy), m_filename (filename), m_row (row)
+  : m_file_cache (fc),
+    m_policy (policy), m_filename (filename), m_row (row)
   {}
   ~line_corrections ();
 
   void add_hint (const fixit_hint *hint);
 
+  file_cache &m_file_cache;
   const char_display_policy &m_policy;
   const char *m_filename;
   linenum_type m_row;
@@ -2433,7 +2453,7 @@ line_corrections::~line_corrections ()
 class source_line
 {
 public:
-  source_line (const char *filename, int line);
+  source_line (file_cache &fc, const char *filename, int line);
 
   char_span as_span () { return char_span (chars, width); }
 
@@ -2443,9 +2463,9 @@ public:
 
 /* source_line's ctor.  */
 
-source_line::source_line (const char *filename, int line)
+source_line::source_line (file_cache &fc, const char *filename, int line)
 {
-  char_span span = location_get_source_line (filename, line);
+  char_span span = fc.get_source_line (filename, line);
   chars = span.get_buffer ();
   width = span.length ();
 }
@@ -2457,10 +2477,12 @@ source_line::source_line (const char *filename, int line)
 void
 line_corrections::add_hint (const fixit_hint *hint)
 {
-  column_range affected_bytes = get_affected_range (m_policy, hint, CU_BYTES);
-  column_range affected_columns = get_affected_range (m_policy, hint,
-						      CU_DISPLAY_COLS);
-  column_range printed_columns = get_printed_columns (m_policy, hint);
+  column_range affected_bytes
+    = get_affected_range (m_file_cache, m_policy, hint, CU_BYTES);
+  column_range affected_columns
+    = get_affected_range (m_file_cache, m_policy, hint, CU_DISPLAY_COLS);
+  column_range printed_columns
+    = get_printed_columns (m_file_cache, m_policy, hint);
 
   /* Potentially consolidate.  */
   if (!m_corrections.is_empty ())
@@ -2489,7 +2511,7 @@ line_corrections::add_hint (const fixit_hint *hint)
 				affected_bytes.start - 1);
 
 	  /* Try to read the source.  */
-	  source_line line (m_filename, m_row);
+	  source_line line (m_file_cache, m_filename, m_row);
 	  if (line.chars && between.finish < line.width)
 	    {
 	      /* Consolidate into the last correction:
@@ -2545,7 +2567,7 @@ layout::print_trailing_fixits (linenum_type row)
 {
   /* Build a list of correction instances for the line,
      potentially consolidating hints (for the sake of readability).  */
-  line_corrections corrections (m_policy, m_exploc.file, row);
+  line_corrections corrections (m_file_cache, m_policy, m_exploc.file, row);
   for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
     {
       const fixit_hint *hint = m_fixit_hints[i];
@@ -2783,7 +2805,7 @@ layout::show_ruler (int max_column) const
 void
 layout::print_line (linenum_type row)
 {
-  char_span line = location_get_source_line (m_exploc.file, row);
+  char_span line = m_file_cache.get_source_line (m_exploc.file, row);
   if (!line)
     return;
 
@@ -3005,6 +3027,7 @@ test_layout_x_offset_display_utf8 (const line_table_case &case_)
   const int emoji_col = 102;
 
   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+  file_cache fc;
   line_table_test ltt (case_);
 
   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
@@ -3019,12 +3042,13 @@ test_layout_x_offset_display_utf8 (const line_table_case &case_)
   ASSERT_EQ (1, LOCATION_LINE (line_end));
   ASSERT_EQ (line_bytes, LOCATION_COLUMN (line_end));
 
-  char_span lspan = location_get_source_line (tmp.get_filename (), 1);
+  char_span lspan = fc.get_source_line (tmp.get_filename (), 1);
   ASSERT_EQ (line_display_cols,
 	     cpp_display_width (lspan.get_buffer (), lspan.length (),
 				def_policy ()));
   ASSERT_EQ (line_display_cols,
-	     location_compute_display_column (expand_location (line_end),
+	     location_compute_display_column (fc,
+					      expand_location (line_end),
 					      def_policy ()));
   ASSERT_EQ (0, memcmp (lspan.get_buffer () + (emoji_col - 1),
 			"\xf0\x9f\x98\x82\xf0\x9f\x98\x82", 8));
@@ -3160,6 +3184,7 @@ test_layout_x_offset_display_tab (const line_table_case &case_)
   ASSERT_EQ (7, extra_width[10]);
 
   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+  file_cache fc;
   line_table_test ltt (case_);
 
   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
@@ -3171,7 +3196,7 @@ test_layout_x_offset_display_tab (const line_table_case &case_)
     return;
 
   /* Check that cpp_display_width handles the tabs as expected.  */
-  char_span lspan = location_get_source_line (tmp.get_filename (), 1);
+  char_span lspan = fc.get_source_line (tmp.get_filename (), 1);
   ASSERT_EQ ('\t', *(lspan.get_buffer () + (tab_col - 1)));
   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
     {
@@ -3180,7 +3205,8 @@ test_layout_x_offset_display_tab (const line_table_case &case_)
 		 cpp_display_width (lspan.get_buffer (), lspan.length (),
 				    policy));
       ASSERT_EQ (line_bytes + extra_width[tabstop],
-		 location_compute_display_column (expand_location (line_end),
+		 location_compute_display_column (fc,
+						  expand_location (line_end),
 						  policy));
     }
 
@@ -4389,6 +4415,7 @@ test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_)
        1111222233334444567890122223333456789999000011112222345678999900001
        Byte columns.  */
   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+  file_cache fc;
   line_table_test ltt (case_);
 
   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
@@ -4403,10 +4430,11 @@ test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_)
   ASSERT_EQ (1, LOCATION_LINE (line_end));
   ASSERT_EQ (31, LOCATION_COLUMN (line_end));
 
-  char_span lspan = location_get_source_line (tmp.get_filename (), 1);
+  char_span lspan = fc.get_source_line (tmp.get_filename (), 1);
   ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length (),
 				    def_policy ()));
-  ASSERT_EQ (25, location_compute_display_column (expand_location (line_end),
+  ASSERT_EQ (25, location_compute_display_column (fc,
+						  expand_location (line_end),
 						  def_policy ()));
 
   test_one_liner_simple_caret_utf8 ();
@@ -4440,7 +4468,12 @@ test_add_location_if_nearby (const line_table_case &case_)
        "  double x;\n"                              /* line 4.  */
        "  double y;\n"                              /* line 5.  */
        ";\n");                                      /* line 6.  */
-  temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+  temp_source_file tmp (SELFTEST_LOCATION, ".c", content,
+
+			/* gcc_rich_location::add_location_if_nearby implicitly
+			   uses global_dc's file_cache, so we need to evict
+			   tmp when we're done.  */
+			&global_dc->get_file_cache ());
   line_table_test ltt (case_);
 
   const line_map_ordinary *ord_map
@@ -4748,6 +4781,7 @@ test_overlapped_fixit_printing (const line_table_case &case_)
   const char *content
     = ("  foo *f = (foo *)ptr->field;\n");
   temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
+  file_cache fc;
   line_table_test ltt (case_);
 
   const line_map_ordinary *ord_map
@@ -4797,27 +4831,27 @@ test_overlapped_fixit_printing (const line_table_case &case_)
     ASSERT_EQ (3, richloc.get_num_fixit_hints ());
     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
     ASSERT_EQ (column_range (12, 12),
-	       get_affected_range (policy, hint_0, CU_BYTES));
+	       get_affected_range (fc, policy, hint_0, CU_BYTES));
     ASSERT_EQ (column_range (12, 12),
-	       get_affected_range (policy, hint_0, CU_DISPLAY_COLS));
-    ASSERT_EQ (column_range (12, 22), get_printed_columns (policy, hint_0));
+	       get_affected_range (fc, policy, hint_0, CU_DISPLAY_COLS));
+    ASSERT_EQ (column_range (12, 22), get_printed_columns (fc, policy, hint_0));
     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
     ASSERT_EQ (column_range (18, 18),
-	       get_affected_range (policy, hint_1, CU_BYTES));
+	       get_affected_range (fc, policy, hint_1, CU_BYTES));
     ASSERT_EQ (column_range (18, 18),
-	       get_affected_range (policy, hint_1, CU_DISPLAY_COLS));
-    ASSERT_EQ (column_range (18, 20), get_printed_columns (policy, hint_1));
+	       get_affected_range (fc, policy, hint_1, CU_DISPLAY_COLS));
+    ASSERT_EQ (column_range (18, 20), get_printed_columns (fc, policy, hint_1));
     const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
     ASSERT_EQ (column_range (29, 28),
-	       get_affected_range (policy, hint_2, CU_BYTES));
+	       get_affected_range (fc, policy, hint_2, CU_BYTES));
     ASSERT_EQ (column_range (29, 28),
-	       get_affected_range (policy, hint_2, CU_DISPLAY_COLS));
-    ASSERT_EQ (column_range (29, 29), get_printed_columns (policy, hint_2));
+	       get_affected_range (fc, policy, hint_2, CU_DISPLAY_COLS));
+    ASSERT_EQ (column_range (29, 29), get_printed_columns (fc, policy, hint_2));
 
     /* Add each hint in turn to a line_corrections instance,
        and verify that they are consolidated into one correction instance
        as expected.  */
-    line_corrections lc (policy, tmp.get_filename (), 1);
+    line_corrections lc (fc, policy, tmp.get_filename (), 1);
 
     /* The first replace hint by itself.  */
     lc.add_hint (hint_0);
@@ -4991,6 +5025,7 @@ test_overlapped_fixit_printing_utf8 (const line_table_case &case_)
   /* Example where 3 fix-it hints are printed as one.  */
   {
     test_diagnostic_context dc;
+    file_cache &fc = dc.get_file_cache ();
     rich_location richloc (line_table, expr);
     richloc.add_fixit_replace (open_paren, "const_cast<");
     richloc.add_fixit_replace (close_paren, "> (");
@@ -5013,27 +5048,27 @@ test_overlapped_fixit_printing_utf8 (const line_table_case &case_)
     ASSERT_EQ (3, richloc.get_num_fixit_hints ());
     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
     ASSERT_EQ (column_range (14, 14),
-	       get_affected_range (policy, hint_0, CU_BYTES));
+	       get_affected_range (fc, policy, hint_0, CU_BYTES));
     ASSERT_EQ (column_range (12, 12),
-	       get_affected_range (policy, hint_0, CU_DISPLAY_COLS));
-    ASSERT_EQ (column_range (12, 22), get_printed_columns (policy, hint_0));
+	       get_affected_range (fc, policy, hint_0, CU_DISPLAY_COLS));
+    ASSERT_EQ (column_range (12, 22), get_printed_columns (fc, policy, hint_0));
     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
     ASSERT_EQ (column_range (22, 22),
-	       get_affected_range (policy, hint_1, CU_BYTES));
+	       get_affected_range (fc, policy, hint_1, CU_BYTES));
     ASSERT_EQ (column_range (18, 18),
-	       get_affected_range (policy, hint_1, CU_DISPLAY_COLS));
-    ASSERT_EQ (column_range (18, 20), get_printed_columns (policy, hint_1));
+	       get_affected_range (fc, policy, hint_1, CU_DISPLAY_COLS));
+    ASSERT_EQ (column_range (18, 20), get_printed_columns (fc, policy, hint_1));
     const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
     ASSERT_EQ (column_range (35, 34),
-	       get_affected_range (policy, hint_2, CU_BYTES));
+	       get_affected_range (fc, policy, hint_2, CU_BYTES));
     ASSERT_EQ (column_range (30, 29),
-	       get_affected_range (policy, hint_2, CU_DISPLAY_COLS));
-    ASSERT_EQ (column_range (30, 30), get_printed_columns (policy, hint_2));
+	       get_affected_range (fc, policy, hint_2, CU_DISPLAY_COLS));
+    ASSERT_EQ (column_range (30, 30), get_printed_columns (fc, policy, hint_2));
 
     /* Add each hint in turn to a line_corrections instance,
        and verify that they are consolidated into one correction instance
        as expected.  */
-    line_corrections lc (policy, tmp.get_filename (), 1);
+    line_corrections lc (fc, policy, tmp.get_filename (), 1);
 
     /* The first replace hint by itself.  */
     lc.add_hint (hint_0);
@@ -5221,6 +5256,7 @@ test_overlapped_fixit_printing_2 (const line_table_case &case_)
   /* Two insertions, in the wrong order.  */
   {
     test_diagnostic_context dc;
+    file_cache &fc = dc.get_file_cache ();
 
     rich_location richloc (line_table, col_20);
     richloc.add_fixit_insert_before (col_23, "{");
@@ -5231,12 +5267,12 @@ test_overlapped_fixit_printing_2 (const line_table_case &case_)
     ASSERT_EQ (2, richloc.get_num_fixit_hints ());
     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
     ASSERT_EQ (column_range (23, 22),
-	       get_affected_range (policy, hint_0, CU_BYTES));
-    ASSERT_EQ (column_range (23, 23), get_printed_columns (policy, hint_0));
+	       get_affected_range (fc, policy, hint_0, CU_BYTES));
+    ASSERT_EQ (column_range (23, 23), get_printed_columns (fc, policy, hint_0));
     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
     ASSERT_EQ (column_range (21, 20),
-	       get_affected_range (policy, hint_1, CU_BYTES));
-    ASSERT_EQ (column_range (21, 21), get_printed_columns (policy, hint_1));
+	       get_affected_range (fc, policy, hint_1, CU_BYTES));
+    ASSERT_EQ (column_range (21, 21), get_printed_columns (fc, policy, hint_1));
 
     /* Verify that they're printed correctly.  */
     diagnostic_show_locus (&dc, &richloc, DK_ERROR);
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index addd6606eaa0..24212b9668eb 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -211,7 +211,7 @@ diagnostic_context::initialize (int n_opts)
   this->printer = XNEW (pretty_printer);
   new (this->printer) pretty_printer ();
 
-  m_file_cache = nullptr;
+  m_file_cache = new file_cache ();
   memset (m_diagnostic_count, 0, sizeof m_diagnostic_count);
   m_warning_as_error_requested = false;
   m_n_opts = n_opts;
@@ -352,8 +352,6 @@ diagnostic_context::
 initialize_input_context (diagnostic_input_charset_callback ccb,
 			  bool should_skip_bom)
 {
-  if (!m_file_cache)
-    m_file_cache = new file_cache;
   m_file_cache->initialize_input_context (ccb, should_skip_bom);
 }
 
@@ -432,7 +430,8 @@ void
 diagnostic_context::create_edit_context ()
 {
   delete m_edit_context_ptr;
-  m_edit_context_ptr = new edit_context ();
+  gcc_assert (m_file_cache);
+  m_edit_context_ptr = new edit_context (*m_file_cache);
 }
 
 /* Initialize DIAGNOSTIC, where the message MSG has already been
@@ -485,7 +484,8 @@ diagnostic_get_color_for_kind (diagnostic_t kind)
    Return -1 if the column is invalid (<= 0).  */
 
 static int
-convert_column_unit (enum diagnostics_column_unit column_unit,
+convert_column_unit (file_cache &fc,
+		     enum diagnostics_column_unit column_unit,
 		     int tabstop,
 		     expanded_location s)
 {
@@ -500,7 +500,7 @@ convert_column_unit (enum diagnostics_column_unit column_unit,
     case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
       {
 	cpp_char_column_policy policy (tabstop, cpp_wcwidth);
-	return location_compute_display_column (s, policy);
+	return location_compute_display_column (fc, s, policy);
       }
 
     case DIAGNOSTICS_COLUMN_UNIT_BYTE:
@@ -514,7 +514,8 @@ convert_column_unit (enum diagnostics_column_unit column_unit,
 int
 diagnostic_context::converted_column (expanded_location s) const
 {
-  int one_based_col = convert_column_unit (m_column_unit, m_tabstop, s);
+  int one_based_col = convert_column_unit (get_file_cache (),
+					   m_column_unit, m_tabstop, s);
   if (one_based_col <= 0)
     return -1;
   return one_based_col + (m_column_origin - 1);
@@ -1205,7 +1206,8 @@ print_escaped_string (pretty_printer *pp, const char *text)
    Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY.  */
 
 static void
-print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
+print_parseable_fixits (file_cache &fc,
+			pretty_printer *pp, rich_location *richloc,
 			enum diagnostics_column_unit column_unit,
 			int tabstop)
 {
@@ -1226,9 +1228,9 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
       location_t next_loc = hint->get_next_loc ();
       expanded_location next_exploc = expand_location (next_loc);
       int start_col
-	= convert_column_unit (column_unit, tabstop, start_exploc);
+	= convert_column_unit (fc, column_unit, tabstop, start_exploc);
       int next_col
-	= convert_column_unit (column_unit, tabstop, next_exploc);
+	= convert_column_unit (fc, column_unit, tabstop, next_exploc);
       pp_printf (pp, ":{%i:%i-%i:%i}:",
 		 start_exploc.line, start_col,
 		 next_exploc.line, next_col);
@@ -1613,13 +1615,15 @@ diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
     default:
       break;
     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
-      print_parseable_fixits (this->printer, diagnostic->richloc,
+      print_parseable_fixits (get_file_cache (),
+			      this->printer, diagnostic->richloc,
 			      DIAGNOSTICS_COLUMN_UNIT_BYTE,
 			      m_tabstop);
       pp_flush (this->printer);
       break;
     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
-      print_parseable_fixits (this->printer, diagnostic->richloc,
+      print_parseable_fixits (get_file_cache (),
+			      this->printer, diagnostic->richloc,
 			      DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
 			      m_tabstop);
       pp_flush (this->printer);
@@ -2687,9 +2691,10 @@ static void
 test_print_parseable_fixits_none ()
 {
   pretty_printer pp;
+  file_cache fc;
   rich_location richloc (line_table, UNKNOWN_LOCATION);
 
-  print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+  print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   ASSERT_STREQ ("", pp_formatted_text (&pp));
 }
 
@@ -2700,6 +2705,7 @@ static void
 test_print_parseable_fixits_insert ()
 {
   pretty_printer pp;
+  file_cache fc;
   rich_location richloc (line_table, UNKNOWN_LOCATION);
 
   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
@@ -2708,7 +2714,7 @@ test_print_parseable_fixits_insert ()
   location_t where = linemap_position_for_column (line_table, 10);
   richloc.add_fixit_insert_before (where, "added content");
 
-  print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+  print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
 		pp_formatted_text (&pp));
 }
@@ -2720,6 +2726,7 @@ static void
 test_print_parseable_fixits_remove ()
 {
   pretty_printer pp;
+  file_cache fc;
   rich_location richloc (line_table, UNKNOWN_LOCATION);
 
   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
@@ -2730,7 +2737,7 @@ test_print_parseable_fixits_remove ()
   where.m_finish = linemap_position_for_column (line_table, 20);
   richloc.add_fixit_remove (where);
 
-  print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+  print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
 		pp_formatted_text (&pp));
 }
@@ -2742,6 +2749,7 @@ static void
 test_print_parseable_fixits_replace ()
 {
   pretty_printer pp;
+  file_cache fc;
   rich_location richloc (line_table, UNKNOWN_LOCATION);
 
   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
@@ -2752,7 +2760,7 @@ test_print_parseable_fixits_replace ()
   where.m_finish = linemap_position_for_column (line_table, 20);
   richloc.add_fixit_replace (where, "replacement");
 
-  print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+  print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
 		pp_formatted_text (&pp));
 }
@@ -2772,6 +2780,7 @@ test_print_parseable_fixits_bytes_vs_display_columns ()
   const int tabstop = 8;
 
   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+  file_cache fc;
   const char *const fname = tmp.get_filename ();
 
   linemap_add (line_table, LC_ENTER, false, fname, 0);
@@ -2792,7 +2801,8 @@ test_print_parseable_fixits_bytes_vs_display_columns ()
 
   {
     pretty_printer pp;
-    print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
+    print_parseable_fixits (fc, &pp, &richloc,
+			    DIAGNOSTICS_COLUMN_UNIT_BYTE,
 			    tabstop);
     snprintf (expected, buf_len,
 	      "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
@@ -2800,7 +2810,8 @@ test_print_parseable_fixits_bytes_vs_display_columns ()
   }
   {
     pretty_printer pp;
-    print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
+    print_parseable_fixits (fc, &pp, &richloc,
+			    DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
 			    tabstop);
     snprintf (expected, buf_len,
 	      "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 6a3228247b8a..7ae7cebf02ed 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -360,8 +360,6 @@ public:
   void color_init (int value);
   void urls_init (int value);
 
-  void file_cache_init ();
-
   void finish ();
 
   void set_set_locations_callback (set_locations_callback_t cb)
@@ -461,10 +459,11 @@ public:
     return m_escape_format;
   }
 
-  file_cache *
+  file_cache &
   get_file_cache () const
   {
-    return m_file_cache;
+    gcc_assert (m_file_cache);
+    return *m_file_cache;
   }
 
   edit_context *get_edit_context () const
diff --git a/gcc/edit-context.cc b/gcc/edit-context.cc
index 09b000c74c42..ee28bf60bebc 100644
--- a/gcc/edit-context.cc
+++ b/gcc/edit-context.cc
@@ -64,7 +64,7 @@ public:
 class edited_file
 {
  public:
-  edited_file (const char *filename);
+  edited_file (edit_context &ec, const char *filename);
   static void delete_cb (edited_file *file);
 
   const char *get_filename () const { return m_filename; }
@@ -84,6 +84,11 @@ class edited_file
     return 0;
   }
 
+  file_cache &get_file_cache () const
+  {
+    return m_edit_context.get_file_cache ();
+  }
+
  private:
   bool print_content (pretty_printer *pp);
   void print_diff (pretty_printer *pp, bool show_filenames);
@@ -100,6 +105,7 @@ class edited_file
 				   int start_of_run,
 				   int end_of_run);
 
+  edit_context &m_edit_context;
   const char *m_filename;
   typed_splay_tree<int, edited_line *> m_edited_lines;
   int m_num_lines;
@@ -163,7 +169,7 @@ class line_event
 class edited_line
 {
  public:
-  edited_line (const char *filename, int line_num);
+  edited_line (file_cache &fc, const char *filename, int line_num);
   ~edited_line ();
   static void delete_cb (edited_line *el);
 
@@ -208,8 +214,9 @@ print_diff_line (pretty_printer *pp, char prefix_char,
 
 /* edit_context's ctor.  */
 
-edit_context::edit_context ()
-: m_valid (true),
+edit_context::edit_context (file_cache &fc)
+: m_file_cache (fc),
+  m_valid (true),
   m_files (strcmp, NULL, edited_file::delete_cb)
 {}
 
@@ -334,7 +341,7 @@ edit_context::get_or_insert_file (const char *filename)
     return *file;
 
   /* Not found.  */
-  file = new edited_file (filename);
+  file = new edited_file (*this, filename);
   m_files.insert (filename, file);
   return *file;
 }
@@ -350,8 +357,9 @@ static int line_comparator (int a, int b)
 
 /* edited_file's constructor.  */
 
-edited_file::edited_file (const char *filename)
-: m_filename (filename),
+edited_file::edited_file (edit_context &ec, const char *filename)
+: m_edit_context (ec),
+  m_filename (filename),
   m_edited_lines (line_comparator, NULL, edited_line::delete_cb),
   m_num_lines (-1)
 {
@@ -422,7 +430,8 @@ edited_file::print_content (pretty_printer *pp)
 	el->print_content (pp);
       else
 	{
-	  char_span line = location_get_source_line (m_filename, line_num);
+	  char_span line
+	    = get_file_cache ().get_source_line (m_filename, line_num);
 	  if (!line)
 	    return false;
 	  for (size_t i = 0; i < line.length (); i++)
@@ -547,7 +556,8 @@ edited_file::print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
       else
 	{
 	  /* Unchanged line.  */
-	  char_span old_line = location_get_source_line (m_filename, line_num);
+	  char_span old_line
+	    = get_file_cache ().get_source_line (m_filename, line_num);
 	  print_diff_line (pp, ' ', old_line.get_buffer (), old_line.length ());
 	  line_num++;
 	}
@@ -576,7 +586,8 @@ edited_file::print_run_of_changed_lines (pretty_printer *pp,
       gcc_assert (el_in_run);
       if (el_in_run->actually_edited_p ())
 	{
-	  char_span old_line = location_get_source_line (m_filename, line_num);
+	  char_span old_line
+	    = get_file_cache ().get_source_line (m_filename, line_num);
 	  print_diff_line (pp, '-', old_line.get_buffer (),
 			   old_line.length ());
 	}
@@ -649,7 +660,7 @@ edited_file::get_or_insert_line (int line)
   edited_line *el = get_line (line);
   if (el)
     return el;
-  el = new edited_line (m_filename, line);
+  el = new edited_line (get_file_cache (), m_filename, line);
   if (el->get_content () == NULL)
     {
       delete el;
@@ -673,14 +684,15 @@ edited_file::get_num_lines (bool *missing_trailing_newline)
       while (true)
 	{
 	  char_span line
-	    = location_get_source_line (m_filename, m_num_lines + 1);
+	    = get_file_cache ().get_source_line (m_filename, m_num_lines + 1);
 	  if (line)
 	    m_num_lines++;
 	  else
 	    break;
 	}
     }
-  *missing_trailing_newline = location_missing_trailing_newline (m_filename);
+  *missing_trailing_newline
+    = get_file_cache ().missing_trailing_newline_p (m_filename);
   return m_num_lines;
 }
 
@@ -688,13 +700,13 @@ edited_file::get_num_lines (bool *missing_trailing_newline)
 
 /* edited_line's ctor.  */
 
-edited_line::edited_line (const char *filename, int line_num)
+edited_line::edited_line (file_cache &fc, const char *filename, int line_num)
 : m_line_num (line_num),
   m_content (NULL), m_len (0), m_alloc_sz (0),
   m_line_events (),
   m_predecessors ()
 {
-  char_span line = location_get_source_line (filename, line_num);
+  char_span line = fc.get_source_line (filename, line_num);
   if (!line)
     return;
   m_len = line.length ();
@@ -913,7 +925,8 @@ test_get_content ()
   {
     const char *content = ("");
     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     auto_free <char *> result = edit.get_content (tmp.get_filename ());
     ASSERT_STREQ ("", result);
   }
@@ -924,7 +937,8 @@ test_get_content ()
 			   "foo = bar.field;\n"
 			   "/* after */\n");
     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     auto_free <char *> result = edit.get_content (tmp.get_filename ());
     ASSERT_STREQ ("/* before */\n"
 		  "foo = bar.field;\n"
@@ -937,7 +951,8 @@ test_get_content ()
 			   "foo = bar.field;\n"
 			   "/* after */");
     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     auto_free <char *> result = edit.get_content (tmp.get_filename ());
     /* We should respect the omitted trailing newline.  */
     ASSERT_STREQ ("/* before */\n"
@@ -970,7 +985,8 @@ test_applying_fixits_insert_before (const line_table_case &case_)
   if (start > LINE_MAP_MAX_LOCATION_WITH_COLS)
     return;
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   if (start <= LINE_MAP_MAX_LOCATION_WITH_COLS)
@@ -1028,7 +1044,8 @@ test_applying_fixits_insert_after (const line_table_case &case_)
     return;
 
   /* Verify that the text was inserted after the end of "field". */
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   ASSERT_STREQ ("/* before */\n"
@@ -1070,7 +1087,8 @@ test_applying_fixits_insert_after_at_line_end (const line_table_case &case_)
   if (loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
     return;
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   ASSERT_STREQ ("/* before */\n"
@@ -1128,7 +1146,8 @@ test_applying_fixits_insert_after_failure (const line_table_case &case_)
   richloc.add_fixit_insert_after ("/* inserted */");
   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   ASSERT_FALSE (edit.valid_p ());
   ASSERT_EQ (NULL, edit.get_content (filename));
@@ -1165,7 +1184,8 @@ test_applying_fixits_insert_containing_newline (const line_table_case &case_)
   if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
     return;
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   ASSERT_STREQ (("    case 'a':\n"
@@ -1209,7 +1229,8 @@ test_applying_fixits_growing_replace (const line_table_case &case_)
   rich_location richloc (line_table, field);
   richloc.add_fixit_replace ("m_field");
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
@@ -1254,7 +1275,8 @@ test_applying_fixits_shrinking_replace (const line_table_case &case_)
   rich_location richloc (line_table, m_field);
   richloc.add_fixit_replace ("field");
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
@@ -1308,7 +1330,8 @@ test_applying_fixits_replace_containing_newline (const line_table_case &case_)
   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
     return;
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   //ASSERT_STREQ ("foo\n  = bar ();\n", new_content);
@@ -1339,7 +1362,8 @@ test_applying_fixits_remove (const line_table_case &case_)
   range.m_finish = finish;
   richloc.add_fixit_remove (range);
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&richloc);
   auto_free <char *> new_content = edit.get_content (filename);
   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
@@ -1404,7 +1428,8 @@ test_applying_fixits_multiple (const line_table_case &case_)
   replace_b.add_fixit_replace (source_range::from_locations (c11, c15),
 			       "meadow");
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   edit.add_fixits (&insert_a);
   ASSERT_EQ (100, edit.get_effective_column (filename, 1, 100));
   ASSERT_EQ (1, edit.get_effective_column (filename, 2, 1));
@@ -1506,7 +1531,8 @@ test_applying_fixits_multiple_lines (const line_table_case &case_)
   linemap_add (line_table, LC_ENTER, false, filename, 1);
   linemap_position_for_column (line_table, 127);
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
 
   /* A run of consecutive lines.  */
   change_line (edit, 2);
@@ -1594,7 +1620,8 @@ test_applying_fixits_modernize_named_init (const line_table_case &case_)
 
   /* The order should not matter.  Do r1 then r2. */
   {
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     edit.add_fixits (&r1);
 
     /* Verify state after first replacement.  */
@@ -1627,7 +1654,8 @@ test_applying_fixits_modernize_named_init (const line_table_case &case_)
 
   /* Try again, doing r2 then r1; the new_content should be the same.  */
   {
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     edit.add_fixits (&r2);
     edit.add_fixits (&r1);
     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
@@ -1655,7 +1683,8 @@ test_applying_fixits_unreadable_file ()
   insert.add_fixit_insert_before ("change 1");
   insert.add_fixit_insert_before ("change 2");
 
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   /* Attempting to add the fixits affecting the unreadable file
      should transition the edit from valid to invalid.  */
   ASSERT_TRUE (edit.valid_p ());
@@ -1688,7 +1717,8 @@ test_applying_fixits_line_out_of_range ()
 
   /* Verify that attempting the insertion puts an edit_context
      into an invalid state.  */
-  edit_context edit;
+  file_cache fc;
+  edit_context edit (fc);
   ASSERT_TRUE (edit.valid_p ());
   edit.add_fixits (&insert);
   ASSERT_FALSE (edit.valid_p ());
@@ -1725,7 +1755,8 @@ test_applying_fixits_column_validation (const line_table_case &case_)
 
     /* Col 15 is at the end of the line, so the insertion
        should succeed.  */
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     edit.add_fixits (&richloc);
     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
     if (c15 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
@@ -1741,7 +1772,8 @@ test_applying_fixits_column_validation (const line_table_case &case_)
 
     /* Col 16 is beyond the end of the line, so the insertion
        should fail gracefully.  */
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     ASSERT_TRUE (edit.valid_p ());
     edit.add_fixits (&richloc);
     ASSERT_FALSE (edit.valid_p ());
@@ -1759,7 +1791,8 @@ test_applying_fixits_column_validation (const line_table_case &case_)
 
     /* Col 14 is at the end of the line, so the replacement
        should succeed.  */
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     edit.add_fixits (&richloc);
     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
     if (c14 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
@@ -1776,7 +1809,8 @@ test_applying_fixits_column_validation (const line_table_case &case_)
 
     /* Col 15 is after the end of the line, so the replacement
        should fail; verify that the attempt fails gracefully.  */
-    edit_context edit;
+    file_cache fc;
+    edit_context edit (fc);
     ASSERT_TRUE (edit.valid_p ());
     edit.add_fixits (&richloc);
     ASSERT_FALSE (edit.valid_p ());
diff --git a/gcc/edit-context.h b/gcc/edit-context.h
index f2e69a664d6d..3ae9ba103ca7 100644
--- a/gcc/edit-context.h
+++ b/gcc/edit-context.h
@@ -42,7 +42,7 @@ class edited_file;
 class edit_context
 {
  public:
-  edit_context ();
+  edit_context (file_cache &);
 
   bool valid_p () const { return m_valid; }
 
@@ -55,11 +55,14 @@ class edit_context
   char *generate_diff (bool show_filenames);
   void print_diff (pretty_printer *pp, bool show_filenames);
 
+  file_cache &get_file_cache () const { return m_file_cache; }
+
  private:
   bool apply_fixit (const fixit_hint *hint);
   edited_file *get_file (const char *filename);
   edited_file &get_or_insert_file (const char *filename);
 
+  file_cache &m_file_cache;
   bool m_valid;
   typed_splay_tree<const char *, edited_file *> m_files;
 };
diff --git a/gcc/final.cc b/gcc/final.cc
index dd3e22547acf..e6f1b1e166b1 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -82,6 +82,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "print-rtl.h"
 #include "function-abi.h"
 #include "common/common-target.h"
+#include "diagnostic.h"
 
 #include "dwarf2out.h"
 
@@ -2103,7 +2104,8 @@ asm_show_source (const char *filename, int linenum)
   if (!filename)
     return;
 
-  char_span line = location_get_source_line (filename, linenum);
+  char_span line
+    = global_dc->get_file_cache ().get_source_line (filename, linenum);
   if (!line)
     return;
 
diff --git a/gcc/gcc-rich-location.cc b/gcc/gcc-rich-location.cc
index edecf07f81e7..068df1c51a8c 100644
--- a/gcc/gcc-rich-location.cc
+++ b/gcc/gcc-rich-location.cc
@@ -75,10 +75,11 @@ gcc_rich_location::add_fixit_misspelled_id (location_t misspelled_token_loc,
 /* Return true if there is nothing on LOC's line before LOC.  */
 
 static bool
-blank_line_before_p (location_t loc)
+blank_line_before_p (file_cache &fc,
+		     location_t loc)
 {
   expanded_location exploc = expand_location (loc);
-  char_span line = location_get_source_line (exploc.file, exploc.line);
+  char_span line = fc.get_source_line (exploc.file, exploc.line);
   if (!line)
     return false;
   if (line.length () < (size_t)exploc.column)
@@ -96,7 +97,8 @@ blank_line_before_p (location_t loc)
    If true is returned then *OUT_START_OF_LINE is written to.  */
 
 static bool
-use_new_line (location_t insertion_point, location_t indent,
+use_new_line (file_cache &fc,
+	      location_t insertion_point, location_t indent,
 	      location_t *out_start_of_line)
 {
   if (indent == UNKNOWN_LOCATION)
@@ -105,7 +107,7 @@ use_new_line (location_t insertion_point, location_t indent,
   if (linemap_macro_expansion_map_p (indent_map))
     return false;
 
-  if (!blank_line_before_p (insertion_point))
+  if (!blank_line_before_p (fc, insertion_point))
     return false;
 
   /* Locate the start of the line containing INSERTION_POINT.  */
@@ -162,7 +164,8 @@ gcc_rich_location::add_fixit_insert_formatted (const char *content,
 					       location_t indent)
 {
   location_t start_of_line;
-  if (use_new_line (insertion_point, indent, &start_of_line))
+  if (use_new_line (global_dc->get_file_cache (),
+		    insertion_point, indent, &start_of_line))
     {
       /* Add CONTENT on its own line, using the indentation of INDENT.  */
 
diff --git a/gcc/input.cc b/gcc/input.cc
index 1b229227d895..b520264f4a80 100644
--- a/gcc/input.cc
+++ b/gcc/input.cc
@@ -288,23 +288,6 @@ expand_location_1 (const line_maps *set,
   return xloc;
 }
 
-/* Initialize the set of cache used for files accessed by caret
-   diagnostic.  */
-
-static void
-diagnostic_file_cache_init (void)
-{
-  gcc_assert (global_dc);
-  global_dc->file_cache_init ();
-}
-
-void
-diagnostic_context::file_cache_init ()
-{
-  if (m_file_cache == nullptr)
-    m_file_cache = new file_cache ();
-}
-
 /* Return the total lines number that have been read so far by the
    line map (in the preprocessor) so far.  For languages like C++ that
    entirely preprocess the input file before starting to parse, this
@@ -355,17 +338,6 @@ file_cache::lookup_file (const char *file_path)
    printing source code.  For use in selftests when working
    with tempfiles.  */
 
-void
-diagnostics_file_cache_forcibly_evict_file (const char *file_path)
-{
-  gcc_assert (file_path);
-
-  auto file_cache = global_dc->get_file_cache ();
-  if (!file_cache)
-    return;
-  file_cache->forcibly_evict_file (file_path);
-}
-
 void
 file_cache::forcibly_evict_file (const char *file_path)
 {
@@ -379,6 +351,19 @@ file_cache::forcibly_evict_file (const char *file_path)
   r->evict ();
 }
 
+/* Determine if FILE_PATH missing a trailing newline on its final line.
+   Only valid to call once all of the file has been loaded, by
+   requesting a line number beyond the end of the file.  */
+
+bool
+file_cache::missing_trailing_newline_p (const char *file_path)
+{
+  gcc_assert (file_path);
+
+  file_cache_slot *r = lookup_or_add_file (file_path);
+  return r->missing_trailing_newline_p ();
+}
+
 void
 file_cache_slot::evict ()
 {
@@ -403,8 +388,6 @@ file_cache_slot::evict ()
 file_cache_slot*
 file_cache::evicted_cache_tab_entry (unsigned *highest_use_count)
 {
-  diagnostic_file_cache_init ();
-
   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)
@@ -968,19 +951,12 @@ file_cache::get_source_line (const char *file_path, int line)
   return char_span (buffer, len);
 }
 
-char_span
-location_get_source_line (const char *file_path, int line)
-{
-  diagnostic_file_cache_init ();
-  return global_dc->get_file_cache ()->get_source_line (file_path, line);
-}
-
 /* Return a NUL-terminated copy of the source text between two locations, or
    NULL if the arguments are invalid.  The caller is responsible for freeing
    the return value.  */
 
 char *
-get_source_text_between (location_t start, location_t end)
+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);
@@ -1005,7 +981,7 @@ get_source_text_between (location_t start, location_t end)
   /* For a single line we need to trim both edges.  */
   if (expstart.line == expend.line)
     {
-      char_span line = location_get_source_line (expstart.file, expstart.line);
+      char_span line = fc.get_source_line (expstart.file, expstart.line);
       if (line.length () < 1)
 	return NULL;
       int s = expstart.column - 1;
@@ -1022,7 +998,7 @@ get_source_text_between (location_t start, location_t end)
      parts of the start and end lines off depending on column values.  */
   for (int lnum = expstart.line; lnum <= expend.line; ++lnum)
     {
-      char_span line = location_get_source_line (expstart.file, lnum);
+      char_span line = fc.get_source_line (expstart.file, lnum);
       if (line.length () < 1 && (lnum != expstart.line && lnum != expend.line))
 	continue;
 
@@ -1077,33 +1053,6 @@ file_cache::get_source_file_content (const char *file_path)
   return c->get_full_file_content ();
 }
 
-
-/* Get a borrowed char_span to the full content of FILE_PATH
-   as decoded according to the input charset, encoded as UTF-8.  */
-
-char_span
-get_source_file_content (const char *file_path)
-{
-  diagnostic_file_cache_init ();
-  return global_dc->get_file_cache ()->get_source_file_content (file_path);
-}
-
-/* Determine if FILE_PATH missing a trailing newline on its final line.
-   Only valid to call once all of the file has been loaded, by
-   requesting a line number beyond the end of the file.  */
-
-bool
-location_missing_trailing_newline (const char *file_path)
-{
-  diagnostic_file_cache_init ();
-
-  file_cache_slot *c = global_dc->get_file_cache ()->lookup_or_add_file (file_path);
-  if (c == NULL)
-    return false;
-
-  return c->missing_trailing_newline_p ();
-}
-
 /* Test if the location originates from the spelling location of a
    builtin-tokens.  That is, return TRUE if LOC is a (possibly
    virtual) location of a built-in token that appears in the expansion
@@ -1236,12 +1185,13 @@ make_location (location_t caret, source_range src_range)
    source line in order to calculate the display width.  If that cannot be done
    for any reason, then returns the byte column as a fallback.  */
 int
-location_compute_display_column (expanded_location exploc,
+location_compute_display_column (file_cache &fc,
+				 expanded_location exploc,
 				 const cpp_char_column_policy &policy)
 {
   if (!(exploc.file && *exploc.file && exploc.line && exploc.column))
     return exploc.column;
-  char_span line = location_get_source_line (exploc.file, exploc.line);
+  char_span line = fc.get_source_line (exploc.file, exploc.line);
   /* If line is NULL, this function returns exploc.column which is the
      desired fallback.  */
   return cpp_byte_column_to_display_column (line.get_buffer (), line.length (),
@@ -1386,6 +1336,8 @@ dump_labelled_location_range (FILE *stream,
 void
 dump_location_info (FILE *stream)
 {
+  file_cache fc;
+
   /* Visualize the reserved locations.  */
   dump_labelled_location_range (stream, "RESERVED LOCATIONS",
 				0, RESERVED_LOCATION_COUNT);
@@ -1456,8 +1408,8 @@ dump_location_info (FILE *stream)
 	    {
 	      /* Beginning of a new source line: draw the line.  */
 
-	      char_span line_text = location_get_source_line (exploc.file,
-							      exploc.line);
+	      char_span line_text = fc.get_source_line (exploc.file,
+							exploc.line);
 	      if (!line_text)
 		break;
 	      fprintf (stream,
@@ -1705,6 +1657,7 @@ class auto_cpp_string_vec :  public auto_vec <cpp_string>
 
 static const char *
 get_substring_ranges_for_loc (cpp_reader *pfile,
+			      file_cache &fc,
 			      string_concat_db *concats,
 			      location_t strloc,
 			      enum cpp_ttype type,
@@ -1784,7 +1737,7 @@ get_substring_ranges_for_loc (cpp_reader *pfile,
       if (start.column > finish.column)
 	return "range endpoints are reversed";
 
-      char_span line = location_get_source_line (start.file, start.line);
+      char_span line = fc.get_source_line (start.file, start.line);
       if (!line)
 	return "unable to read source line";
 
@@ -1872,6 +1825,7 @@ get_substring_ranges_for_loc (cpp_reader *pfile,
 
 const char *
 get_location_within_string (cpp_reader *pfile,
+			    file_cache &fc,
 			    string_concat_db *concats,
 			    location_t strloc,
 			    enum cpp_ttype type,
@@ -1885,7 +1839,7 @@ get_location_within_string (cpp_reader *pfile,
 
   cpp_substring_ranges ranges;
   const char *err
-    = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
+    = get_substring_ranges_for_loc (pfile, fc, concats, strloc, type, ranges);
   if (err)
     return err;
 
@@ -1954,6 +1908,7 @@ namespace selftest {
 
 static const char *
 get_source_range_for_char (cpp_reader *pfile,
+			   file_cache &fc,
 			   string_concat_db *concats,
 			   location_t strloc,
 			   enum cpp_ttype type,
@@ -1965,7 +1920,7 @@ get_source_range_for_char (cpp_reader *pfile,
 
   cpp_substring_ranges ranges;
   const char *err
-    = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
+    = get_substring_ranges_for_loc (pfile, fc, concats, strloc, type, ranges);
   if (err)
     return err;
 
@@ -1981,6 +1936,7 @@ get_source_range_for_char (cpp_reader *pfile,
 
 static const char *
 get_num_source_ranges_for_substring (cpp_reader *pfile,
+				     file_cache &fc,
 				     string_concat_db *concats,
 				     location_t strloc,
 				     enum cpp_ttype type,
@@ -1990,7 +1946,7 @@ get_num_source_ranges_for_substring (cpp_reader *pfile,
 
   cpp_substring_ranges ranges;
   const char *err
-    = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
+    = get_substring_ranges_for_loc (pfile, fc, concats, strloc, type, ranges);
 
   if (err)
     return err;
@@ -2313,23 +2269,24 @@ test_reading_source_line ()
 			"01234567890123456789\n"
 			"This is the test text\n"
 			"This is the 3rd line");
+  file_cache fc;
 
   /* Read back a specific line from the tempfile.  */
-  char_span source_line = location_get_source_line (tmp.get_filename (), 3);
+  char_span source_line = fc.get_source_line (tmp.get_filename (), 3);
   ASSERT_TRUE (source_line);
   ASSERT_TRUE (source_line.get_buffer () != NULL);
   ASSERT_EQ (20, source_line.length ());
   ASSERT_TRUE (!strncmp ("This is the 3rd line",
 			 source_line.get_buffer (), source_line.length ()));
 
-  source_line = location_get_source_line (tmp.get_filename (), 2);
+  source_line = fc.get_source_line (tmp.get_filename (), 2);
   ASSERT_TRUE (source_line);
   ASSERT_TRUE (source_line.get_buffer () != NULL);
   ASSERT_EQ (21, source_line.length ());
   ASSERT_TRUE (!strncmp ("This is the test text",
 			 source_line.get_buffer (), source_line.length ()));
 
-  source_line = location_get_source_line (tmp.get_filename (), 4);
+  source_line = fc.get_source_line (tmp.get_filename (), 4);
   ASSERT_FALSE (source_line);
   ASSERT_TRUE (source_line.get_buffer () == NULL);
 }
@@ -2490,6 +2447,7 @@ public:
   line_table_test m_ltt;
   cpp_reader_ptr m_parser;
   temp_source_file m_tempfile;
+  file_cache m_file_cache;
   string_concat_db m_concats;
   bool m_implicitly_expect_EOF;
 };
@@ -2681,7 +2639,8 @@ assert_char_at_range (const location &loc,
 
   source_range actual_range = source_range();
   const char *err
-    = get_source_range_for_char (pfile, concats, strloc, type, idx,
+    = get_source_range_for_char (pfile, test.m_file_cache,
+				 concats, strloc, type, idx,
 				 &actual_range);
   if (should_have_column_data_p (strloc))
     ASSERT_EQ_AT (loc, NULL, err);
@@ -2736,7 +2695,8 @@ assert_num_substring_ranges (const location &loc,
 
   int actual_num_ranges = -1;
   const char *err
-    = get_num_source_ranges_for_substring (pfile, concats, strloc, type,
+    = get_num_source_ranges_for_substring (pfile, test.m_file_cache,
+					   concats, strloc, type,
 					   &actual_num_ranges);
   if (should_have_column_data_p (strloc))
     ASSERT_EQ_AT (loc, NULL, err);
@@ -2773,7 +2733,7 @@ assert_has_no_substring_ranges (const location &loc,
   string_concat_db *concats = &test.m_concats;
   cpp_substring_ranges ranges;
   const char *actual_err
-    = get_substring_ranges_for_loc (pfile, concats, strloc,
+    = get_substring_ranges_for_loc (pfile, test.m_file_cache, concats, strloc,
 				    type, ranges);
   if (should_have_column_data_p (strloc))
     ASSERT_STREQ_AT (loc, expected_err, actual_err);
@@ -3542,7 +3502,8 @@ test_lexer_string_locations_concatenation_2 (const line_table_case &case_)
 	 this case.  */
       source_range actual_range;
       const char *err
-	= get_source_range_for_char (test.m_parser, &test.m_concats,
+	= get_source_range_for_char (test.m_parser, test.m_file_cache,
+				     &test.m_concats,
 				     initial_loc, type, 0, &actual_range);
       ASSERT_STREQ ("range starts after LINE_MAP_MAX_LOCATION_WITH_COLS", err);
       return;
diff --git a/gcc/input.h b/gcc/input.h
index 5eac1dc40a67..9cc9d58d0b29 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "line-map.h"
 
+class file_cache;
+
 extern GTY(()) class line_maps *line_table;
 extern GTY(()) class line_maps *saved_line_table;
 
@@ -67,7 +69,8 @@ extern expanded_location expand_location (location_t);
 class cpp_char_column_policy;
 
 extern int
-location_compute_display_column (expanded_location exploc,
+location_compute_display_column (file_cache &fc,
+				 expanded_location exploc,
 				 const cpp_char_column_policy &policy);
 
 /* A class capturing the bounds of a buffer, to allow for run-time
@@ -113,11 +116,8 @@ class char_span
   size_t m_n_elts;
 };
 
-extern char_span location_get_source_line (const char *file_path, int line);
-extern char *get_source_text_between (location_t, location_t);
-extern char_span get_source_file_content (const char *file_path);
-
-extern bool location_missing_trailing_newline (const char *file_path);
+extern char *
+get_source_text_between (file_cache &, location_t, location_t);
 
 /* Forward decl of slot within file_cache, so that the definition doesn't
    need to be in this header.  */
@@ -152,6 +152,7 @@ class file_cache
 
   char_span get_source_file_content (const char *file_path);
   char_span get_source_line (const char *file_path, int line);
+  bool missing_trailing_newline_p (const char *file_path);
 
  private:
   file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
@@ -254,8 +255,6 @@ void dump_line_table_statistics (void);
 
 void dump_location_info (FILE *stream);
 
-void diagnostics_file_cache_forcibly_evict_file (const char *file_path);
-
 class GTY(()) string_concat
 {
 public:
diff --git a/gcc/selftest.cc b/gcc/selftest.cc
index 20c10bbd0558..2d0181b77fd9 100644
--- a/gcc/selftest.cc
+++ b/gcc/selftest.cc
@@ -161,10 +161,12 @@ assert_str_startswith (const location &loc,
 
 /* Constructor.  Generate a name for the file.  */
 
-named_temp_file::named_temp_file (const char *suffix)
+named_temp_file::named_temp_file (const char *suffix,
+				  file_cache *fc)
 {
   m_filename = make_temp_file (suffix);
   ASSERT_NE (m_filename, NULL);
+  m_file_cache = fc;
 }
 
 /* Destructor.  Delete the tempfile.  */
@@ -172,7 +174,8 @@ named_temp_file::named_temp_file (const char *suffix)
 named_temp_file::~named_temp_file ()
 {
   unlink (m_filename);
-  diagnostics_file_cache_forcibly_evict_file (m_filename);
+  if (m_file_cache)
+    m_file_cache->forcibly_evict_file (m_filename);
   free (m_filename);
 }
 
@@ -182,8 +185,9 @@ named_temp_file::~named_temp_file ()
 
 temp_source_file::temp_source_file (const location &loc,
 				    const char *suffix,
-				    const char *content)
-: named_temp_file (suffix)
+				    const char *content,
+				    file_cache *fc)
+: named_temp_file (suffix, fc)
 {
   FILE *out = fopen (get_filename (), "w");
   if (!out)
diff --git a/gcc/selftest.h b/gcc/selftest.h
index b0a4142fe34f..3bb4885014b5 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -25,6 +25,8 @@ along with GCC; see the file COPYING3.  If not see
 
 #if CHECKING_P
 
+class file_cache;
+
 namespace selftest {
 
 /* A struct describing the source-location of a selftest, to make it
@@ -91,17 +93,20 @@ extern void assert_str_startswith (const location &loc,
 /* A named temporary file for use in selftests.
    Usable for writing out files, and as the base class for
    temp_source_file.
-   The file is unlinked in the destructor.  */
+   The file is unlinked in the destructor.
+   If the file_cache is non-null, the filename is evicted from
+   the file_cache when the named_temp_file is destroyed.  */
 
 class named_temp_file
 {
  public:
-  named_temp_file (const char *suffix);
+  named_temp_file (const char *suffix, file_cache *fc = nullptr);
   ~named_temp_file ();
   const char *get_filename () const { return m_filename; }
 
  private:
   char *m_filename;
+  file_cache *m_file_cache;
 };
 
 /* A class for writing out a temporary sourcefile for use in selftests
@@ -111,7 +116,7 @@ class temp_source_file : public named_temp_file
 {
  public:
   temp_source_file (const location &loc, const char *suffix,
-		    const char *content);
+		    const char *content, file_cache *fc = nullptr);
   temp_source_file (const location &loc, const char *suffix,
 		    const char *content, size_t sz);
 };
diff --git a/gcc/substring-locations.h b/gcc/substring-locations.h
index ce9995709e87..ec49215da4c7 100644
--- a/gcc/substring-locations.h
+++ b/gcc/substring-locations.h
@@ -116,6 +116,7 @@ class format_string_diagnostic_t
    LANG_HOOKS_GET_SUBSTRING_LOCATION.  */
 
 extern const char *get_location_within_string (cpp_reader *pfile,
+					       file_cache &fc,
 					       string_concat_db *concats,
 					       location_t strloc,
 					       enum cpp_ttype type,
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
index 2b8cbc952ebc..6cc661b026d6 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
@@ -438,7 +438,8 @@ test_show_locus (function *fun)
       rich_location richloc (line_table, loc);
       for (int line = start_line; line <= finish_line; line++)
 	{
-	  char_span content = location_get_source_line (file, line);
+	  file_cache &fc = global_dc->get_file_cache ();
+	  char_span content = fc.get_source_line (file, line);
 	  gcc_assert (content);
 	  /* Split line up into words.  */
 	  for (int idx = 0; idx < content.length (); idx++)
diff --git a/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c b/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c
index a7c67284d3c0..3c534005a419 100644
--- a/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.c
@@ -51,7 +51,7 @@ test_richloc (rich_location *richloc)
   diagnostic_show_locus (&dc, richloc, DK_ERROR);
 
   /* Generate a diff.  */
-  edit_context ec;
+  edit_context ec (global_dc->get_file_cache ());
   ec.add_fixits (richloc);
   char *diff = ec.generate_diff (true);
   free (diff);
-- 
2.26.3


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-11-14 16:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-14 16:32 [pushed] input.h: eliminate implicit users of global_dc's file_cache David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).