diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index e83e9c683f7..78e53fd82ed 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1248,7 +1248,7 @@ c_parser_require (c_parser *parser,
       bool added_matching_location = false;
       if (matching_location != UNKNOWN_LOCATION)
 	added_matching_location
-	  = richloc.add_location_if_nearby (matching_location);
+	  = richloc.add_location_if_nearby (*global_dc, matching_location);
 
       if (c_parser_error_richloc (parser, msgid, &richloc))
 	/* If we weren't able to consolidate matching_location, then
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index e7409b856f1..3fd0c5fc5b4 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -3297,7 +3297,8 @@ cp_parser_error_1 (cp_parser* parser, const char* gmsgid,
 	   secondary range within the main diagnostic.  */
 	if (matching_location != UNKNOWN_LOCATION)
 	  added_matching_location
-	    = richloc.add_location_if_nearby (matching_location);
+	    = richloc.add_location_if_nearby (*global_dc,
+					      matching_location);
       }
 
   /* If we were parsing a string-literal and there is an unknown name
@@ -16651,7 +16652,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 		break;
 	      gcc_rich_location richloc (token->location);
 	      location_t oloc = decl_specs->locations[ds_storage_class];
-	      richloc.add_location_if_nearby (oloc);
+	      richloc.add_location_if_nearby (*global_dc, oloc);
 	      error_at (&richloc,
 			"%<typedef%> specifier conflicts with %qs",
 			cp_storage_class_name[decl_specs->storage_class]);
@@ -34429,7 +34430,8 @@ cp_parser_set_storage_class (cp_parser *parser,
       if (decl_specs->conflicting_specifiers_p)
 	return;
       gcc_rich_location richloc (token->location);
-      richloc.add_location_if_nearby (decl_specs->locations[ds_storage_class]);
+      richloc.add_location_if_nearby (*global_dc,
+				      decl_specs->locations[ds_storage_class]);
       if (decl_specs->storage_class == storage_class)
 	error_at (&richloc, "duplicate %qD specifier", ridpointers[keyword]);
       else
@@ -34460,7 +34462,8 @@ cp_parser_set_storage_class (cp_parser *parser,
       && !decl_specs->conflicting_specifiers_p)
     {
       gcc_rich_location richloc (token->location);
-      richloc.add_location_if_nearby (decl_specs->locations[ds_typedef]);
+      richloc.add_location_if_nearby (*global_dc,
+				      decl_specs->locations[ds_typedef]);
       error_at (&richloc,
 		"%qD specifier conflicts with %<typedef%>",
 		ridpointers[keyword]);
diff --git a/gcc/diagnostic-path.cc b/gcc/diagnostic-path.cc
index ea5b1f65e02..e470bd29fdd 100644
--- a/gcc/diagnostic-path.cc
+++ b/gcc/diagnostic-path.cc
@@ -224,8 +224,10 @@ namespace {
 class path_label : public range_label
 {
  public:
-  path_label (const diagnostic_path *path, unsigned start_idx)
-  : m_path (path), m_start_idx (start_idx), m_effects (*this)
+  path_label (const diagnostic_context &ctxt,
+	      const diagnostic_path *path,
+	      unsigned start_idx)
+  : m_ctxt (ctxt), m_path (path), m_start_idx (start_idx), m_effects (*this)
   {}
 
   label_text get_text (unsigned range_idx) const final override
@@ -236,7 +238,7 @@ class path_label : public range_label
     /* Get the description of the event, perhaps with colorization:
        normally, we don't colorize within a range_label, but this
        is special-cased for diagnostic paths.  */
-    const bool colorize = pp_show_color (global_dc->printer);
+    const bool colorize = pp_show_color (m_ctxt.printer);
     label_text event_text (event.get_desc (colorize));
     gcc_assert (event_text.get ());
 
@@ -250,7 +252,7 @@ class path_label : public range_label
     pp_space (&pp);
 
     if (meaning.m_verb == diagnostic_event::VERB_danger)
-      if (text_art::theme *theme = global_dc->get_diagram_theme ())
+      if (text_art::theme *theme = m_ctxt.get_diagram_theme ())
 	if (theme->emojis_p ())
 	  {
 	    pp_unicode_character (&pp, 0x26A0); /* U+26A0 WARNING SIGN.  */
@@ -314,6 +316,7 @@ class path_label : public range_label
     return &m_path->get_event (event_idx);
   }
 
+  const diagnostic_context &m_ctxt;
   const diagnostic_path *m_path;
   unsigned m_start_idx;
   path_label_effects m_effects;
@@ -504,7 +507,8 @@ struct event_range
     int m_max_label_source_column;
   };
 
-  event_range (const diagnostic_path *path, unsigned start_idx,
+  event_range (const diagnostic_context &ctxt,
+	       const diagnostic_path *path, unsigned start_idx,
 	       const diagnostic_event &initial_event,
 	       per_thread_summary &t,
 	       bool show_event_links)
@@ -513,7 +517,7 @@ struct event_range
     m_logical_loc (initial_event.get_logical_location ()),
     m_stack_depth (initial_event.get_stack_depth ()),
     m_start_idx (start_idx), m_end_idx (start_idx),
-    m_path_label (path, start_idx),
+    m_path_label (ctxt, path, start_idx),
     m_richloc (initial_event.get_location (), &m_path_label),
     m_thread_id (initial_event.get_thread_id ()),
     m_per_thread_summary (t),
@@ -550,7 +554,8 @@ struct event_range
     return result;
   }
 
-  bool maybe_add_event (const diagnostic_event &new_ev,
+  bool maybe_add_event (const diagnostic_context &ctxt,
+			const diagnostic_event &new_ev,
 			unsigned new_ev_idx,
 			bool check_rich_locations)
   {
@@ -582,7 +587,7 @@ struct event_range
 
     /* Potentially verify that the locations are sufficiently close.  */
     if (check_rich_locations)
-      if (!m_richloc.add_location_if_nearby (new_ev.get_location (),
+      if (!m_richloc.add_location_if_nearby (ctxt, new_ev.get_location (),
 					     false, &m_path_label))
 	return false;
 
@@ -669,7 +674,8 @@ struct event_range
 
 struct path_summary
 {
-  path_summary (const diagnostic_path &path,
+  path_summary (const diagnostic_context &ctxt,
+		const diagnostic_path &path,
 		bool check_rich_locations,
 		bool show_event_links = true);
 
@@ -730,7 +736,8 @@ per_thread_summary::interprocedural_p () const
 
 /* path_summary's ctor.  */
 
-path_summary::path_summary (const diagnostic_path &path,
+path_summary::path_summary (const diagnostic_context &ctxt,
+			    const diagnostic_path &path,
 			    bool check_rich_locations,
 			    bool show_event_links)
 {
@@ -747,10 +754,11 @@ path_summary::path_summary (const diagnostic_path &path,
       pts.update_depth_limits (event.get_stack_depth ());
 
       if (cur_event_range)
-	if (cur_event_range->maybe_add_event (event, idx, check_rich_locations))
+	if (cur_event_range->maybe_add_event (ctxt, event,
+					      idx, check_rich_locations))
 	  continue;
 
-      cur_event_range = new event_range (&path, idx, event, pts,
+      cur_event_range = new event_range (ctxt, &path, idx, event, pts,
 					 show_event_links);
       m_ranges.safe_push (cur_event_range);
       pts.m_event_ranges.safe_push (cur_event_range);
@@ -1106,7 +1114,7 @@ diagnostic_context::print_path (const diagnostic_path *path)
     case DPF_INLINE_EVENTS:
       {
 	/* Consolidate related events.  */
-	path_summary summary (*path, true,
+	path_summary summary (*this, *path, true,
 			      m_source_printing.show_event_links_p);
 	char *saved_prefix = pp_take_prefix (this->printer);
 	pp_set_prefix (this->printer, NULL);
@@ -1152,10 +1160,10 @@ test_empty_path (pretty_printer *event_pp)
   test_diagnostic_path path (event_pp);
   ASSERT_FALSE (path.interprocedural_p ());
 
-  path_summary summary (path, false);
+  test_diagnostic_context dc;
+  path_summary summary (dc, path, false);
   ASSERT_EQ (summary.get_num_ranges (), 0);
 
-  test_diagnostic_context dc;
   print_path_summary_as_text (&summary, &dc, true);
   ASSERT_STREQ ("",
 		pp_formatted_text (dc.printer));
@@ -1173,10 +1181,10 @@ test_intraprocedural_path (pretty_printer *event_pp)
 
   ASSERT_FALSE (path.interprocedural_p ());
 
-  path_summary summary (path, false);
+  test_diagnostic_context dc;
+  path_summary summary (dc, path, false);
   ASSERT_EQ (summary.get_num_ranges (), 1);
 
-  test_diagnostic_context dc;
   print_path_summary_as_text (&summary, &dc, true);
   ASSERT_STREQ ("  `foo': events 1-2 (depth 0)\n"
 		" (1): first `free'\n"
@@ -1207,11 +1215,11 @@ test_interprocedural_path_1 (pretty_printer *event_pp)
 
   ASSERT_TRUE (path.interprocedural_p ());
 
-  path_summary summary (path, false);
-  ASSERT_EQ (summary.get_num_ranges (), 9);
-
   {
     test_diagnostic_context dc;
+    path_summary summary (dc, path, false);
+    ASSERT_EQ (summary.get_num_ranges (), 9);
+
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     print_path_summary_as_text (&summary, &dc, true);
     ASSERT_STREQ
@@ -1269,6 +1277,7 @@ test_interprocedural_path_1 (pretty_printer *event_pp)
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+    path_summary summary (dc, path, false);
     print_path_summary_as_text (&summary, &dc, true);
     ASSERT_STREQ
       ("  `test': events 1-2 (depth 0)\n"
@@ -1341,11 +1350,10 @@ test_interprocedural_path_2 (pretty_printer *event_pp)
 
   ASSERT_TRUE (path.interprocedural_p ());
 
-  path_summary summary (path, false);
-  ASSERT_EQ (summary.get_num_ranges (), 5);
-
   {
     test_diagnostic_context dc;
+    path_summary summary (dc, path, false);
+    ASSERT_EQ (summary.get_num_ranges (), 5);
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     print_path_summary_as_text (&summary, &dc, true);
     ASSERT_STREQ
@@ -1379,6 +1387,7 @@ test_interprocedural_path_2 (pretty_printer *event_pp)
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+    path_summary summary (dc, path, false);
     print_path_summary_as_text (&summary, &dc, true);
     ASSERT_STREQ
       ("  `foo': events 1-2 (depth 0)\n"
@@ -1424,12 +1433,13 @@ test_recursion (pretty_printer *event_pp)
 
   ASSERT_TRUE (path.interprocedural_p ());
 
-  path_summary summary (path, false);
-  ASSERT_EQ (summary.get_num_ranges (), 4);
-
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+
+    path_summary summary (dc, path, false);
+    ASSERT_EQ (summary.get_num_ranges (), 4);
+
     print_path_summary_as_text (&summary, &dc, true);
     ASSERT_STREQ
       ("  `factorial': events 1-2 (depth 0)\n"
@@ -1456,6 +1466,8 @@ test_recursion (pretty_printer *event_pp)
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+
+    path_summary summary (dc, path, false);
     print_path_summary_as_text (&summary, &dc, true);
     ASSERT_STREQ
       ("  `factorial': events 1-2 (depth 0)\n"
@@ -1570,12 +1582,12 @@ test_control_flow_1 (const line_table_case &case_,
   if (!path_events_have_column_data_p (path))
     return;
 
-  path_summary summary (path, true /*false*/);
 
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_event_links_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -1599,6 +1611,7 @@ test_control_flow_1 (const line_table_case &case_,
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_event_links_p = false;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -1620,6 +1633,7 @@ test_control_flow_1 (const line_table_case &case_,
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_line_numbers_p = true;
     dc.m_source_printing.show_event_links_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -1644,6 +1658,7 @@ test_control_flow_1 (const line_table_case &case_,
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_line_numbers_p = true;
     dc.m_source_printing.show_event_links_p = false;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -1664,6 +1679,7 @@ test_control_flow_1 (const line_table_case &case_,
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
     dc.m_source_printing.show_event_links_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -1688,6 +1704,7 @@ test_control_flow_1 (const line_table_case &case_,
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
     dc.m_source_printing.show_event_links_p = true;
     dc.m_source_printing.show_line_numbers_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -1751,13 +1768,12 @@ test_control_flow_2 (const line_table_case &case_,
   if (!path_events_have_column_data_p (path))
     return;
 
-  path_summary summary (path, true);
-
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_event_links_p = true;
     dc.m_source_printing.show_line_numbers_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -1837,13 +1853,12 @@ test_control_flow_3 (const line_table_case &case_,
   if (!path_events_have_column_data_p (path))
     return;
 
-  path_summary summary (path, true);
-
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_event_links_p = true;
     dc.m_source_printing.show_line_numbers_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-2\n"
@@ -1895,12 +1910,11 @@ assert_cfg_edge_path_streq (const location &loc,
   if (!path_events_have_column_data_p (path))
     return;
 
-  path_summary summary (path, true);
-
   test_diagnostic_context dc;
   dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
   dc.m_source_printing.show_event_links_p = true;
   dc.m_source_printing.show_line_numbers_p = true;
+  path_summary summary (dc, path, true);
   print_path_summary_as_text (&summary, &dc, false);
   ASSERT_STREQ_AT (loc, expected_str,
 		   pp_formatted_text (dc.printer));
@@ -2217,13 +2231,12 @@ test_control_flow_5 (const line_table_case &case_,
   if (!path_events_have_column_data_p (path))
     return;
 
-  path_summary summary (path, true);
-
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_event_links_p = true;
     dc.m_source_printing.show_line_numbers_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-5\n"
@@ -2305,13 +2318,12 @@ test_control_flow_6 (const line_table_case &case_,
   if (!path_events_have_column_data_p (path))
     return;
 
-  path_summary summary (path, true);
-
   {
     test_diagnostic_context dc;
     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
     dc.m_source_printing.show_event_links_p = true;
     dc.m_source_printing.show_line_numbers_p = true;
+    path_summary summary (dc, path, true);
     print_path_summary_as_text (&summary, &dc, false);
     ASSERT_STREQ
       ("  events 1-3\n"
@@ -2351,16 +2363,15 @@ test_control_flow_6 (const line_table_case &case_,
 static void
 control_flow_tests (const line_table_case &case_)
 {
-  std::unique_ptr<pretty_printer> event_pp
-    = std::unique_ptr<pretty_printer> (global_dc->printer->clone ());
-  pp_show_color (event_pp.get ()) = false;
-
-  test_control_flow_1 (case_, event_pp.get ());
-  test_control_flow_2 (case_, event_pp.get ());
-  test_control_flow_3 (case_, event_pp.get ());
-  test_control_flow_4 (case_, event_pp.get ());
-  test_control_flow_5 (case_, event_pp.get ());
-  test_control_flow_6 (case_, event_pp.get ());
+  pretty_printer pp;
+  pp_show_color (&pp) = false;
+
+  test_control_flow_1 (case_, &pp);
+  test_control_flow_2 (case_, &pp);
+  test_control_flow_3 (case_, &pp);
+  test_control_flow_4 (case_, &pp);
+  test_control_flow_5 (case_, &pp);
+  test_control_flow_6 (case_, &pp);
 }
 
 /* Run all of the selftests within this file.  */
@@ -2368,22 +2379,16 @@ control_flow_tests (const line_table_case &case_)
 void
 diagnostic_path_cc_tests ()
 {
-  /* In a few places we use the global dc's printer to determine
-     colorization so ensure this off during the tests.  */
-  bool saved_show_color = pp_show_color (global_dc->printer);
-  pp_show_color (global_dc->printer) = false;
+  pretty_printer pp;
+  pp_show_color (&pp) = false;
 
   auto_fix_quotes fix_quotes;
-  std::unique_ptr<pretty_printer> event_pp
-    = std::unique_ptr<pretty_printer> (global_dc->printer->clone ());
-  test_empty_path (event_pp.get ());
-  test_intraprocedural_path (event_pp.get ());
-  test_interprocedural_path_1 (event_pp.get ());
-  test_interprocedural_path_2 (event_pp.get ());
-  test_recursion (event_pp.get ());
+  test_empty_path (&pp);
+  test_intraprocedural_path (&pp);
+  test_interprocedural_path_1 (&pp);
+  test_interprocedural_path_2 (&pp);
+  test_recursion (&pp);
   for_each_line_table_case (control_flow_tests);
-
-  pp_show_color (global_dc->printer) = saved_show_color;
 }
 
 } // namespace selftest
diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index 007acc4e014..abd01827f47 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -3151,17 +3151,20 @@ layout::update_any_effects () const
 /* If LOC is within the spans of lines that will already be printed for
    this gcc_rich_location, then add it as a secondary location and return true.
 
-   Otherwise return false.  */
+   Otherwise return false.
+
+   Use CTXT for determining how spans of lines would be printed.  */
 
 bool
-gcc_rich_location::add_location_if_nearby (location_t loc,
+gcc_rich_location::add_location_if_nearby (const diagnostic_context &ctxt,
+					   location_t loc,
 					   bool restrict_to_current_line_spans,
 					   const range_label *label)
 {
   /* Use the layout location-handling logic to sanitize LOC,
      filtering it to the current line spans within a temporary
      layout instance.  */
-  layout layout (*global_dc, *this, DK_ERROR, nullptr);
+  layout layout (ctxt, *this, DK_ERROR, nullptr);
   location_range loc_range;
   loc_range.m_loc = loc;
   loc_range.m_range_display_kind = SHOW_RANGE_WITHOUT_CARET;
@@ -4817,12 +4820,7 @@ 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,
-
-			/* 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 ());
+  temp_source_file tmp (SELFTEST_LOCATION, ".c", content, nullptr);
   line_table_test ltt (case_);
 
   const line_map_ordinary *ord_map
@@ -4841,15 +4839,16 @@ test_add_location_if_nearby (const line_table_case &case_)
   /* Test of add_location_if_nearby on the same line as the
      primary location.  */
   {
+    test_diagnostic_context dc;
     const location_t missing_close_brace_1_39
       = linemap_position_for_line_and_column (line_table, ord_map, 1, 39);
     const location_t matching_open_brace_1_18
       = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
     gcc_rich_location richloc (missing_close_brace_1_39);
-    bool added = richloc.add_location_if_nearby (matching_open_brace_1_18);
+    bool added = richloc.add_location_if_nearby (dc,
+						 matching_open_brace_1_18);
     ASSERT_TRUE (added);
     ASSERT_EQ (2, richloc.get_num_locations ());
-    test_diagnostic_context dc;
     diagnostic_show_locus (&dc, &richloc, DK_ERROR);
     ASSERT_STREQ (" struct same_line { double x; double y; ;\n"
 		  "                  ~                    ^\n",
@@ -4859,12 +4858,14 @@ test_add_location_if_nearby (const line_table_case &case_)
   /* Test of add_location_if_nearby on a different line to the
      primary location.  */
   {
+    test_diagnostic_context dc;
     const location_t missing_close_brace_6_1
       = linemap_position_for_line_and_column (line_table, ord_map, 6, 1);
     const location_t matching_open_brace_3_1
       = linemap_position_for_line_and_column (line_table, ord_map, 3, 1);
     gcc_rich_location richloc (missing_close_brace_6_1);
-    bool added = richloc.add_location_if_nearby (matching_open_brace_3_1);
+    bool added = richloc.add_location_if_nearby (dc,
+						 matching_open_brace_3_1);
     ASSERT_FALSE (added);
     ASSERT_EQ (1, richloc.get_num_locations ());
   }
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 8fc22466b92..7854c74df9f 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -61,20 +61,6 @@ along with GCC; see the file COPYING3.  If not see
 #  pragma GCC diagnostic ignored "-Wformat-diag"
 #endif
 
-#define pedantic_warning_kind(DC)			\
-  ((DC)->m_pedantic_errors ? DK_ERROR : DK_WARNING)
-#define permissive_error_kind(DC) ((DC)->m_permissive ? DK_WARNING : DK_ERROR)
-#define permissive_error_option(DC) ((DC)->m_opt_permissive)
-
-/* Prototypes.  */
-static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
-			     int, const char *,
-			     va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
-static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
-			       int, unsigned HOST_WIDE_INT,
-			       const char *, const char *, va_list *,
-			       diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
-
 static void real_abort (void) ATTRIBUTE_NORETURN;
 
 /* Name of program invoked, sans directories.  */
@@ -1332,7 +1318,7 @@ diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
 
   /* Diagnostics with no option or -fpermissive are always enabled.  */
   if (!diagnostic->option_index
-      || diagnostic->option_index == permissive_error_option (this))
+      || diagnostic->option_index == m_opt_permissive)
     return true;
 
   /* This tests if the user provided the appropriate -Wfoo or
@@ -1405,7 +1391,8 @@ diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
 
   if (diagnostic->kind == DK_PEDWARN)
     {
-      diagnostic->kind = pedantic_warning_kind (this);
+      diagnostic->kind = m_pedantic_errors ? DK_ERROR : DK_WARNING;
+
       /* We do this to avoid giving the message for -pedantic-errors.  */
       orig_diag_kind = diagnostic->kind;
     }
@@ -1628,18 +1615,18 @@ diagnostic_append_note (diagnostic_context *context,
 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
    permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
    and internal_error_no_backtrace, as documented and defined below.  */
-static bool
-diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
-		 int opt, const char *gmsgid,
-		 va_list *ap, diagnostic_t kind)
+bool
+diagnostic_context::diagnostic_impl (rich_location *richloc,
+				     const diagnostic_metadata *metadata,
+				     int opt, const char *gmsgid,
+				     va_list *ap, diagnostic_t kind)
 {
   diagnostic_info diagnostic;
   if (kind == DK_PERMERROR)
     {
       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
-			   permissive_error_kind (global_dc));
-      diagnostic.option_index = (opt != -1 ? opt
-				 : permissive_error_option (global_dc));
+			   m_permissive ? DK_WARNING : DK_ERROR);
+      diagnostic.option_index = (opt != -1 ? opt : m_opt_permissive);
     }
   else
     {
@@ -1648,17 +1635,18 @@ diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
 	diagnostic.option_index = opt;
     }
   diagnostic.metadata = metadata;
-  return global_dc->report_diagnostic (&diagnostic);
+  return report_diagnostic (&diagnostic);
 }
 
 /* Implement inform_n, warning_n, and error_n, as documented and
    defined below.  */
-static bool
-diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
-		   int opt, unsigned HOST_WIDE_INT n,
-		   const char *singular_gmsgid,
-		   const char *plural_gmsgid,
-		   va_list *ap, diagnostic_t kind)
+bool
+diagnostic_context::diagnostic_n_impl (rich_location *richloc,
+				       const diagnostic_metadata *metadata,
+				       int opt, unsigned HOST_WIDE_INT n,
+				       const char *singular_gmsgid,
+				       const char *plural_gmsgid,
+				       va_list *ap, diagnostic_t kind)
 {
   diagnostic_info diagnostic;
   unsigned long gtn;
@@ -1676,7 +1664,7 @@ diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
   if (kind == DK_WARNING)
     diagnostic.option_index = opt;
   diagnostic.metadata = metadata;
-  return global_dc->report_diagnostic (&diagnostic);
+  return report_diagnostic (&diagnostic);
 }
 
 /* Wrapper around diagnostic_impl taking a variable argument list.  */
@@ -1689,7 +1677,8 @@ emit_diagnostic (diagnostic_t kind, location_t location, int opt,
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, location);
-  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
+  bool ret = global_dc->diagnostic_impl (&richloc, nullptr, opt, gmsgid, &ap,
+					 kind);
   va_end (ap);
   return ret;
 }
@@ -1703,7 +1692,8 @@ emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
+  bool ret = global_dc->diagnostic_impl (richloc, nullptr, opt, gmsgid, &ap,
+					 kind);
   va_end (ap);
   return ret;
 }
@@ -1715,7 +1705,7 @@ emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
 			const char *gmsgid, va_list *ap)
 {
   rich_location richloc (line_table, location);
-  return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
+  return global_dc->diagnostic_impl (&richloc, nullptr, opt, gmsgid, ap, kind);
 }
 
 /* As above, but with rich_location and metadata.  */
@@ -1727,7 +1717,7 @@ emit_diagnostic_valist_meta (diagnostic_t kind,
 			     int opt,
 			     const char *gmsgid, va_list *ap)
 {
-  return diagnostic_impl (richloc, metadata, opt, gmsgid, ap, kind);
+  return global_dc->diagnostic_impl (richloc, metadata, opt, gmsgid, ap, kind);
 }
 
 /* An informative note at LOCATION.  Use this for additional details on an error
@@ -1739,7 +1729,7 @@ inform (location_t location, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, location);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_NOTE);
   va_end (ap);
 }
 
@@ -1752,7 +1742,7 @@ inform (rich_location *richloc, const char *gmsgid, ...)
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
+  global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap, DK_NOTE);
   va_end (ap);
 }
 
@@ -1766,8 +1756,9 @@ inform_n (location_t location, unsigned HOST_WIDE_INT n,
   va_start (ap, plural_gmsgid);
   auto_diagnostic_group d;
   rich_location richloc (line_table, location);
-  diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
-		     &ap, DK_NOTE);
+  global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
+				singular_gmsgid, plural_gmsgid,
+				&ap, DK_NOTE);
   va_end (ap);
 }
 
@@ -1781,7 +1772,8 @@ warning (int opt, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, input_location);
-  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
+  bool ret = global_dc->diagnostic_impl (&richloc, nullptr, opt, gmsgid, &ap,
+					 DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1797,7 +1789,8 @@ warning_at (location_t location, int opt, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, location);
-  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
+  bool ret = global_dc->diagnostic_impl (&richloc, nullptr, opt, gmsgid, &ap,
+					 DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1812,7 +1805,8 @@ warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
+  bool ret = global_dc->diagnostic_impl (richloc, nullptr, opt, gmsgid, &ap,
+					 DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1829,9 +1823,8 @@ warning_meta (rich_location *richloc,
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret
-    = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
-		       DK_WARNING);
+  bool ret = global_dc->diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
+					 DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1847,9 +1840,9 @@ warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, plural_gmsgid);
-  bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
-				singular_gmsgid, plural_gmsgid,
-				&ap, DK_WARNING);
+  bool ret = global_dc->diagnostic_n_impl (richloc, nullptr, opt, n,
+					   singular_gmsgid, plural_gmsgid,
+					   &ap, DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1866,9 +1859,9 @@ warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
   va_list ap;
   va_start (ap, plural_gmsgid);
   rich_location richloc (line_table, location);
-  bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
-				singular_gmsgid, plural_gmsgid,
-				&ap, DK_WARNING);
+  bool ret = global_dc->diagnostic_n_impl (&richloc, nullptr, opt, n,
+					   singular_gmsgid, plural_gmsgid,
+					   &ap, DK_WARNING);
   va_end (ap);
   return ret;
 }
@@ -1893,7 +1886,8 @@ pedwarn (location_t location, int opt, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, location);
-  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
+  bool ret = global_dc->diagnostic_impl (&richloc, nullptr, opt, gmsgid, &ap,
+					 DK_PEDWARN);
   va_end (ap);
   return ret;
 }
@@ -1908,7 +1902,8 @@ pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
+  bool ret = global_dc->diagnostic_impl (richloc, nullptr, opt, gmsgid, &ap,
+					 DK_PEDWARN);
   va_end (ap);
   return ret;
 }
@@ -1927,7 +1922,8 @@ permerror (location_t location, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, location);
-  bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
+  bool ret = global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
+					 DK_PERMERROR);
   va_end (ap);
   return ret;
 }
@@ -1942,7 +1938,8 @@ permerror (rich_location *richloc, const char *gmsgid, ...)
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
+  bool ret = global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
+					 DK_PERMERROR);
   va_end (ap);
   return ret;
 }
@@ -1958,7 +1955,8 @@ permerror_opt (location_t location, int opt, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, location);
-  bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
+  bool ret = global_dc->diagnostic_impl (&richloc, nullptr, opt, gmsgid, &ap,
+					 DK_PERMERROR);
   va_end (ap);
   return ret;
 }
@@ -1973,7 +1971,8 @@ permerror_opt (rich_location *richloc, int opt, const char *gmsgid, ...)
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
+  bool ret = global_dc->diagnostic_impl (richloc, nullptr, opt, gmsgid, &ap,
+					 DK_PERMERROR);
   va_end (ap);
   return ret;
 }
@@ -1987,7 +1986,7 @@ error (const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, input_location);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ERROR);
   va_end (ap);
 }
 
@@ -2001,8 +2000,9 @@ error_n (location_t location, unsigned HOST_WIDE_INT n,
   va_list ap;
   va_start (ap, plural_gmsgid);
   rich_location richloc (line_table, location);
-  diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
-		     &ap, DK_ERROR);
+  global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
+				singular_gmsgid, plural_gmsgid,
+				&ap, DK_ERROR);
   va_end (ap);
 }
 
@@ -2014,7 +2014,7 @@ error_at (location_t loc, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, loc);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ERROR);
   va_end (ap);
 }
 
@@ -2028,7 +2028,7 @@ error_at (rich_location *richloc, const char *gmsgid, ...)
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
+  global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap, DK_ERROR);
   va_end (ap);
 }
 
@@ -2043,7 +2043,7 @@ error_meta (rich_location *richloc, const diagnostic_metadata &metadata,
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
+  global_dc->diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
   va_end (ap);
 }
 
@@ -2057,7 +2057,7 @@ sorry (const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, input_location);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_SORRY);
   va_end (ap);
 }
 
@@ -2069,7 +2069,7 @@ sorry_at (location_t loc, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, loc);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_SORRY);
   va_end (ap);
 }
 
@@ -2091,7 +2091,7 @@ fatal_error (location_t loc, const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, loc);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_FATAL);
   va_end (ap);
 
   gcc_unreachable ();
@@ -2106,7 +2106,7 @@ internal_error (const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, input_location);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ICE);
   va_end (ap);
 
   gcc_unreachable ();
@@ -2122,7 +2122,7 @@ internal_error_no_backtrace (const char *gmsgid, ...)
   va_list ap;
   va_start (ap, gmsgid);
   rich_location richloc (line_table, input_location);
-  diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
+  global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ICE_NOBT);
   va_end (ap);
 
   gcc_unreachable ();
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 4969f07836c..8c613234627 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -562,6 +562,14 @@ public:
 
   label_text get_location_text (const expanded_location &s) const;
 
+  bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
+			int, const char *,
+			va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(5,0);
+  bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
+			  int, unsigned HOST_WIDE_INT,
+			  const char *, const char *, va_list *,
+			  diagnostic_t) ATTRIBUTE_GCC_DIAG(7,0);
+
 private:
   bool includes_seen_p (const line_map_ordinary *map);
 
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
index 5664cb95f02..d5009f3ff59 100644
--- a/gcc/gcc-rich-location.h
+++ b/gcc/gcc-rich-location.h
@@ -59,14 +59,16 @@ class gcc_rich_location : public rich_location
      printing them via a note otherwise e.g.:
 
 	gcc_rich_location richloc (primary_loc);
-	bool added secondary = richloc.add_location_if_nearby (secondary_loc);
+	bool added secondary = richloc.add_location_if_nearby (*global_dc,
+							       secondary_loc);
 	error_at (&richloc, "main message");
 	if (!added secondary)
 	  inform (secondary_loc, "message for secondary");
 
      Implemented in diagnostic-show-locus.cc.  */
 
-  bool add_location_if_nearby (location_t loc,
+  bool add_location_if_nearby (const diagnostic_context &ctxt,
+			       location_t loc,
 			       bool restrict_to_current_line_spans = true,
 			       const range_label *label = NULL);
 
