diff --git a/gcc/ada/gcc-interface/misc.cc b/gcc/ada/gcc-interface/misc.cc
index 453ae8087a6..7d6d4466d56 100644
--- a/gcc/ada/gcc-interface/misc.cc
+++ b/gcc/ada/gcc-interface/misc.cc
@@ -336,7 +336,7 @@ internal_error_function (diagnostic_context *context, const char *msgid,
   else
     {
       xloc = expand_location (input_location);
-      if (context->show_column && xloc.column != 0)
+      if (context->m_show_column && xloc.column != 0)
 	loc = xasprintf ("%s:%d:%d", xloc.file, xloc.line, xloc.column);
       else
 	loc = xasprintf ("%s:%d", xloc.file, xloc.line);
@@ -375,7 +375,7 @@ gnat_init (void)
   line_table->default_range_bits = 0;
 
   /* Register our internal error function.  */
-  global_dc->internal_error = &internal_error_function;
+  global_dc->m_internal_error = &internal_error_function;
 
   return true;
 }
diff --git a/gcc/analyzer/bounds-checking.cc b/gcc/analyzer/bounds-checking.cc
index f49cf7cf2af..583b5ab36a0 100644
--- a/gcc/analyzer/bounds-checking.cc
+++ b/gcc/analyzer/bounds-checking.cc
@@ -163,7 +163,7 @@ protected:
     if (op.get_valid_bits ().empty_p ())
       return;
 
-    if (const text_art::theme *theme = global_dc->m_diagrams.m_theme)
+    if (const text_art::theme *theme = global_dc->get_diagram_theme ())
       {
 	text_art::style_manager sm;
 	text_art::canvas canvas (make_access_diagram (op, sm, *theme, logger));
@@ -177,7 +177,7 @@ protected:
 	  (canvas,
 	   /* Alt text.  */
 	   _("Diagram visualizing the predicted out-of-bounds access"));
-	diagnostic_emit_diagram (global_dc, diagram);
+	global_dc->emit_diagram (diagram);
       }
   }
 
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 0efdc677217..b250694803e 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -6694,7 +6694,7 @@ c_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
 {
   diagnostic_info diagnostic;
   diagnostic_t dlevel;
-  bool save_warn_system_headers = global_dc->dc_warn_system_headers;
+  bool save_warn_system_headers = global_dc->m_warn_system_headers;
   bool ret;
 
   switch (level)
@@ -6702,7 +6702,7 @@ c_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
     case CPP_DL_WARNING_SYSHDR:
       if (flag_no_output)
 	return false;
-      global_dc->dc_warn_system_headers = 1;
+      global_dc->m_warn_system_headers = 1;
       /* Fall through.  */
     case CPP_DL_WARNING:
       if (flag_no_output)
@@ -6738,7 +6738,7 @@ c_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
      c_option_controlling_cpp_diagnostic (reason));
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
-    global_dc->dc_warn_system_headers = save_warn_system_headers;
+    global_dc->m_warn_system_headers = save_warn_system_headers;
   return ret;
 }
 
diff --git a/gcc/c-family/c-indentation.cc b/gcc/c-family/c-indentation.cc
index e8d3dece770..5b4614f5fd5 100644
--- a/gcc/c-family/c-indentation.cc
+++ b/gcc/c-family/c-indentation.cc
@@ -331,7 +331,7 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
   if (guard_loc == body_loc || body_loc == next_stmt_loc)
     return false;
 
-  const unsigned int tab_width = global_dc->tabstop;
+  const unsigned int tab_width = global_dc->m_tabstop;
 
   /* They must be in the same file.  */
   if (next_stmt_exploc.file != body_exploc.file)
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index e9f7e6d424d..a980912f7e1 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -186,7 +186,7 @@ void
 c_common_diagnostics_set_defaults (diagnostic_context *context)
 {
   diagnostic_finalizer (context) = c_diagnostic_finalizer;
-  context->opt_permissive = OPT_fpermissive;
+  context->m_opt_permissive = OPT_fpermissive;
 }
 
 /* Input charset configuration for diagnostics.  */
@@ -523,7 +523,7 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 
     case OPT_fpermissive:
       flag_permissive = value;
-      global_dc->permissive = value;
+      global_dc->m_permissive = value;
       break;
 
     case OPT_fpreprocessed:
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index bc889cee6b9..b1bd8ba9f42 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1350,9 +1350,9 @@ conversion_warning (location_t loc, tree type, tree expr, tree result)
 	  break;
 
 	if (arith_ops
-	    && global_dc->option_enabled (warnopt,
-					  global_dc->lang_mask,
-					  global_dc->option_state))
+	    && global_dc->m_option_enabled (warnopt,
+					    global_dc->m_lang_mask,
+					    global_dc->m_option_state))
 	  {
 	    for (int i = 0; i < arith_ops; ++i)
 	      {
diff --git a/gcc/common.opt b/gcc/common.opt
index 1cf3bdd3b51..d21db5d4a20 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1514,10 +1514,6 @@ fdiagnostics-text-art-charset=
 Driver Common Joined RejectNegative Var(flag_diagnostics_text_art_charset) Enum(diagnostic_text_art_charset) Init(DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI)
 -fdiagnostics-text-art-charset=[none|ascii|unicode|emoji]	Determine which characters to use in text arg diagrams.
 
-; Required for these enum values.
-SourceInclude
-diagnostic-text-art.h
-
 Enum
 Name(diagnostic_text_art_charset) Type(int)
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index db7813bdd3d..aced50a4d0c 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -156,7 +156,7 @@ struct cl_optimization;
 struct cl_option;
 struct cl_decoded_option;
 struct cl_option_handlers;
-struct diagnostic_context;
+class diagnostic_context;
 class pretty_printer;
 class diagnostic_event_id_t;
 typedef const char * (*diagnostic_input_charset_callback)(const char *);
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 2eb54b5b6ed..4516677bcab 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13960,9 +13960,9 @@ maybe_warn_dangling_reference (const_tree decl, tree init)
      a system header.  If the DECL is not in a system header, or if
      -Wsystem-headers was provided, warn.  */
   auto wsh
-    = make_temp_override (global_dc->dc_warn_system_headers,
+    = make_temp_override (global_dc->m_warn_system_headers,
 			  (!in_system_header_at (DECL_SOURCE_LOCATION (decl))
-			   || global_dc->dc_warn_system_headers));
+			   || global_dc->m_warn_system_headers));
   if (tree call = do_warn_dangling_reference (init, /*arg_p=*/false))
     {
       auto_diagnostic_group d;
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 0d8b780ba2f..9d4d95f85bf 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -9122,7 +9122,7 @@ note_name_declared_in_class (tree name, tree decl)
 	 A name N used in a class S shall refer to the same declaration
 	 in its context and when re-evaluated in the completed scope of
 	 S.  */
-      auto ov = make_temp_override (global_dc->pedantic_errors);
+      auto ov = make_temp_override (global_dc->m_pedantic_errors);
       if (TREE_CODE (decl) == TYPE_DECL
 	  && TREE_CODE (olddecl) == TYPE_DECL
 	  && same_type_p (TREE_TYPE (decl), TREE_TYPE (olddecl)))
@@ -9131,7 +9131,7 @@ note_name_declared_in_class (tree name, tree decl)
 	/* Let -fpermissive make it a warning like past versions.  */;
       else
 	/* Make it an error.  */
-	global_dc->pedantic_errors = 1;
+	global_dc->m_pedantic_errors = 1;
       if (pedwarn (location_of (decl), OPT_Wchanges_meaning,
 		   "declaration of %q#D changes meaning of %qD",
 		   decl, OVL_NAME (decl)))
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 16af59de696..4a07c7e879b 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -18308,9 +18308,9 @@ finish_function (bool inline_p)
 	      && current_class_ref
 	      && same_type_ignoring_top_level_qualifiers_p
 		  (TREE_TYPE (valtype), TREE_TYPE (current_class_ref))
-	      && global_dc->option_enabled (OPT_Wreturn_type,
-					    global_dc->lang_mask,
-					    global_dc->option_state))
+	      && global_dc->m_option_enabled (OPT_Wreturn_type,
+					      global_dc->m_lang_mask,
+					      global_dc->m_option_state))
 	    add_return_star_this_fixit (&richloc, fndecl);
 	}
       if (cxx_dialect >= cxx14
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 0ed69bca6fc..785909c362a 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -3636,7 +3636,7 @@ cp_print_error_function (diagnostic_context *context,
 		  pp_newline (context->printer);
 		  if (s.file != NULL)
 		    {
-		      if (context->show_column && s.column != 0)
+		      if (context->m_show_column && s.column != 0)
 			pp_printf (context->printer,
 				   _("    inlined from %qD at %r%s:%d:%d%R"),
 				   fndecl,
@@ -3737,7 +3737,7 @@ print_instantiation_partial_context_line (diagnostic_context *context,
 
   expanded_location xloc = expand_location (loc);
 
-  if (context->show_column)
+  if (context->m_show_column)
     pp_verbatim (context->printer, _("%r%s:%d:%d:%R   "),
 		 "locus", xloc.file, xloc.line, xloc.column);
   else
@@ -3816,7 +3816,7 @@ print_instantiation_partial_context (diagnostic_context *context,
 	{
 	  expanded_location xloc;
 	  xloc = expand_location (loc);
-	  if (context->show_column)
+	  if (context->m_show_column)
 	    pp_verbatim (context->printer,
 			 _("%r%s:%d:%d:%R   [ skipping %d instantiation "
 			   "contexts, use -ftemplate-backtrace-limit=0 to "
@@ -3876,7 +3876,7 @@ maybe_print_constexpr_context (diagnostic_context *context)
     {
       expanded_location xloc = expand_location (EXPR_LOCATION (t));
       const char *s = expr_as_string (t, 0);
-      if (context->show_column)
+      if (context->m_show_column)
 	pp_verbatim (context->printer,
 		     _("%r%s:%d:%d:%R   in %<constexpr%> expansion of %qs"),
 		     "locus", xloc.file, xloc.line, xloc.column, s);
@@ -3893,7 +3893,7 @@ static void
 print_location (diagnostic_context *context, location_t loc)
 {
   expanded_location xloc = expand_location (loc);
-  if (context->show_column)
+  if (context->m_show_column)
     pp_verbatim (context->printer, _("%r%s:%d:%d:%R   "),
                  "locus", xloc.file, xloc.line, xloc.column);
   else
diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index e32efb30457..5591af49779 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -1117,9 +1117,9 @@ maybe_noexcept_warning (tree fn)
 {
   if (TREE_NOTHROW (fn)
       && (!DECL_IN_SYSTEM_HEADER (fn)
-	  || global_dc->dc_warn_system_headers))
+	  || global_dc->m_warn_system_headers))
     {
-      auto s = make_temp_override (global_dc->dc_warn_system_headers, true);
+      auto s = make_temp_override (global_dc->m_warn_system_headers, true);
       auto_diagnostic_group d;
       if (warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> "
 		   "because of a call to %qD", fn))
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 86c95b278ba..324f6f01555 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30469,7 +30469,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
   if (fndecl != error_mark_node && !any_dguides_p && (complain & tf_warning))
     {
       if ((!DECL_IN_SYSTEM_HEADER (fndecl)
-	   || global_dc->dc_warn_system_headers)
+	   || global_dc->m_warn_system_headers)
 	  && warning (OPT_Wctad_maybe_unsupported,
 		      "%qT may not intend to support class template argument "
 		      "deduction", type))
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 346abb31ac4..8321c488d28 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -97,7 +97,7 @@ json_from_expanded_location (diagnostic_context *context, location_t loc)
     result->set ("file", new json::string (exploc.file));
   result->set ("line", new json::integer_number (exploc.line));
 
-  const enum diagnostics_column_unit orig_unit = context->column_unit;
+  const enum diagnostics_column_unit orig_unit = context->m_column_unit;
   struct
   {
     const char *name;
@@ -109,15 +109,15 @@ json_from_expanded_location (diagnostic_context *context, location_t loc)
   int the_column = INT_MIN;
   for (int i = 0; i != ARRAY_SIZE (column_fields); ++i)
     {
-      context->column_unit = column_fields[i].unit;
-      const int col = diagnostic_converted_column (context, exploc);
+      context->m_column_unit = column_fields[i].unit;
+      const int col = context->converted_column (exploc);
       result->set (column_fields[i].name, new json::integer_number (col));
       if (column_fields[i].unit == orig_unit)
 	the_column = col;
     }
   gcc_assert (the_column != INT_MIN);
   result->set ("column", new json::integer_number (the_column));
-  context->column_unit = orig_unit;
+  context->m_column_unit = orig_unit;
   return result;
 }
 
@@ -220,18 +220,18 @@ json_output_format::on_end_diagnostic (diagnostic_info *diagnostic,
   pp_clear_output_area (m_context.printer);
 
   char *option_text;
-  option_text = m_context.option_name (&m_context, diagnostic->option_index,
-				       orig_diag_kind, diagnostic->kind);
+  option_text = m_context.m_option_name (&m_context, diagnostic->option_index,
+					 orig_diag_kind, diagnostic->kind);
   if (option_text)
     {
       diag_obj->set ("option", new json::string (option_text));
       free (option_text);
     }
 
-  if (m_context.get_option_url)
+  if (m_context.m_get_option_url)
     {
-      char *option_url = m_context.get_option_url (&m_context,
-						   diagnostic->option_index);
+      char *option_url = m_context.m_get_option_url (&m_context,
+						     diagnostic->option_index);
       if (option_url)
 	{
 	  diag_obj->set ("option_url", new json::string (option_url));
@@ -255,7 +255,7 @@ json_output_format::on_end_diagnostic (diagnostic_info *diagnostic,
       m_cur_children_array = new json::array ();
       diag_obj->set ("children", m_cur_children_array);
       diag_obj->set ("column-origin",
-		     new json::integer_number (m_context.column_origin));
+		     new json::integer_number (m_context.m_column_origin));
     }
 
   const rich_location *richloc = diagnostic->richloc;
@@ -296,9 +296,10 @@ json_output_format::on_end_diagnostic (diagnostic_info *diagnostic,
     }
 
   const diagnostic_path *path = richloc->get_path ();
-  if (path && m_context.make_json_for_path)
+  if (path && m_context.m_make_json_for_path)
     {
-      json::value *path_value = m_context.make_json_for_path (&m_context, path);
+      json::value *path_value
+	= m_context.m_make_json_for_path (&m_context, path);
       diag_obj->set ("path", path_value);
     }
 
@@ -359,14 +360,14 @@ static void
 diagnostic_output_format_init_json (diagnostic_context *context)
 {
   /* Override callbacks.  */
-  context->print_path = NULL; /* handled in json_end_diagnostic.  */
+  context->m_print_path = nullptr; /* handled in json_end_diagnostic.  */
 
   /* The metadata is handled in JSON format, rather than as text.  */
-  context->show_cwe = false;
-  context->show_rules = false;
+  context->set_show_cwe (false);
+  context->set_show_rules (false);
 
   /* The option is handled in JSON format, rather than as text.  */
-  context->show_option_requested = false;
+  context->set_show_option_requested (false);
 
   /* Don't colorize the text.  */
   pp_show_color (context->printer) = false;
@@ -378,8 +379,7 @@ void
 diagnostic_output_format_init_json_stderr (diagnostic_context *context)
 {
   diagnostic_output_format_init_json (context);
-  delete context->m_output_format;
-  context->m_output_format = new json_stderr_output_format (*context);
+  context->set_output_format (new json_stderr_output_format (*context));
 }
 
 /* Populate CONTEXT in preparation for JSON output to a file named
@@ -390,9 +390,8 @@ diagnostic_output_format_init_json_file (diagnostic_context *context,
 					 const char *base_file_name)
 {
   diagnostic_output_format_init_json (context);
-  delete context->m_output_format;
-  context->m_output_format = new json_file_output_format (*context,
-							  base_file_name);
+  context->set_output_format (new json_file_output_format (*context,
+							   base_file_name));
 }
 
 #if CHECKING_P
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index d8cca21d834..25f62392724 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -296,8 +296,8 @@ sarif_invocation::prepare_to_flush (diagnostic_context *context)
 
   /* Call client hook, allowing it to create a custom property bag for
      this object (SARIF v2.1.0 section 3.8) e.g. for recording time vars.  */
-  if (context->m_client_data_hooks)
-    context->m_client_data_hooks->add_sarif_invocation_properties (*this);
+  if (auto client_data_hooks = context->get_client_data_hooks ())
+    client_data_hooks->add_sarif_invocation_properties (*this);
 }
 
 /* class sarif_result : public sarif_object.  */
@@ -408,7 +408,7 @@ sarif_builder::sarif_builder (diagnostic_context *context)
   m_seen_any_relative_paths (false),
   m_rule_id_set (),
   m_rules_arr (new json::array ()),
-  m_tabstop (context->tabstop)
+  m_tabstop (context->m_tabstop)
 {
 }
 
@@ -536,8 +536,8 @@ sarif_builder::make_result_object (diagnostic_context *context,
   /* "ruleId" property (SARIF v2.1.0 section 3.27.5).  */
   /* Ideally we'd have an option_name for these.  */
   if (char *option_text
-	= context->option_name (context, diagnostic->option_index,
-				orig_diag_kind, diagnostic->kind))
+	= context->m_option_name (context, diagnostic->option_index,
+				  orig_diag_kind, diagnostic->kind))
     {
       /* Lazily create reportingDescriptor objects for and add to m_rules_arr.
 	 Set ruleId referencing them.  */
@@ -639,10 +639,10 @@ make_reporting_descriptor_object_for_warning (diagnostic_context *context,
      it seems redundant compared to "id".  */
 
   /* "helpUri" property (SARIF v2.1.0 section 3.49.12).  */
-  if (context->get_option_url)
+  if (context->m_get_option_url)
     {
       char *option_url
-	= context->get_option_url (context, diagnostic->option_index);
+	= context->m_get_option_url (context, diagnostic->option_index);
       if (option_url)
 	{
 	  reporting_desc->set ("helpUri", new json::string (option_url));
@@ -730,9 +730,8 @@ sarif_builder::make_locations_arr (diagnostic_info *diagnostic)
 {
   json::array *locations_arr = new json::array ();
   const logical_location *logical_loc = NULL;
-  if (m_context->m_client_data_hooks)
-    logical_loc
-      = m_context->m_client_data_hooks->get_current_logical_location ();
+  if (auto client_data_hooks = m_context->get_client_data_hooks ())
+    logical_loc = client_data_hooks->get_current_logical_location ();
 
   json::object *location_obj
     = make_location_object (*diagnostic->richloc, logical_loc);
@@ -1361,9 +1360,9 @@ sarif_builder::make_tool_object () const
 
   /* Report plugins via the "extensions" property
      (SARIF v2.1.0 section 3.18.3).  */
-  if (m_context->m_client_data_hooks)
+  if (auto client_data_hooks = m_context->get_client_data_hooks ())
     if (const client_version_info *vinfo
-	  = m_context->m_client_data_hooks->get_any_version_info ())
+	  = client_data_hooks->get_any_version_info ())
       {
 	class my_plugin_visitor : public client_version_info :: plugin_visitor
 	{
@@ -1414,9 +1413,9 @@ sarif_builder::make_driver_tool_component_object () const
 {
   json::object *driver_obj = new json::object ();
 
-  if (m_context->m_client_data_hooks)
+  if (auto client_data_hooks = m_context->get_client_data_hooks ())
     if (const client_version_info *vinfo
-	  = m_context->m_client_data_hooks->get_any_version_info ())
+	  = client_data_hooks->get_any_version_info ())
       {
 	/* "name" property (SARIF v2.1.0 section 3.19.8).  */
 	if (const char *name = vinfo->get_tool_name ())
@@ -1525,10 +1524,9 @@ sarif_builder::make_artifact_object (const char *filename)
     artifact_obj->set ("contents", artifact_content_obj);
 
   /* "sourceLanguage" property (SARIF v2.1.0 section 3.24.10).  */
-  if (m_context->m_client_data_hooks)
+  if (auto client_data_hooks = m_context->get_client_data_hooks ())
     if (const char *source_lang
-	= m_context->m_client_data_hooks->maybe_get_sarif_source_language
-	    (filename))
+	= client_data_hooks->maybe_get_sarif_source_language (filename))
       artifact_obj->set ("sourceLanguage", new json::string (source_lang));
 
   return artifact_obj;
@@ -1542,7 +1540,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->m_file_cache->get_source_file_content (filename);
+    = m_context->get_file_cache ()->get_source_file_content (filename);
   if (!utf8_content)
     return NULL;
 
@@ -1570,7 +1568,7 @@ sarif_builder::get_source_lines (const char *filename,
   for (int line = start_line; line <= end_line; line++)
     {
       char_span line_content
-	= m_context->m_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);
@@ -1791,15 +1789,15 @@ static void
 diagnostic_output_format_init_sarif (diagnostic_context *context)
 {
   /* Override callbacks.  */
-  context->print_path = NULL; /* handled in sarif_end_diagnostic.  */
-  context->ice_handler_cb = sarif_ice_handler;
+  context->m_print_path = nullptr; /* handled in sarif_end_diagnostic.  */
+  context->set_ice_handler_callback (sarif_ice_handler);
 
   /* The metadata is handled in SARIF format, rather than as text.  */
-  context->show_cwe = false;
-  context->show_rules = false;
+  context->set_show_cwe (false);
+  context->set_show_rules (false);
 
   /* The option is handled in SARIF format, rather than as text.  */
-  context->show_option_requested = false;
+  context->set_show_option_requested (false);
 
   /* Don't colorize the text.  */
   pp_show_color (context->printer) = false;
@@ -1811,8 +1809,8 @@ void
 diagnostic_output_format_init_sarif_stderr (diagnostic_context *context)
 {
   diagnostic_output_format_init_sarif (context);
-  delete context->m_output_format;
-  context->m_output_format = new sarif_stream_output_format (*context, stderr);
+  context->set_output_format (new sarif_stream_output_format (*context,
+							      stderr));
 }
 
 /* Populate CONTEXT in preparation for SARIF output to a file named
@@ -1823,9 +1821,8 @@ diagnostic_output_format_init_sarif_file (diagnostic_context *context,
 					  const char *base_file_name)
 {
   diagnostic_output_format_init_sarif (context);
-  delete context->m_output_format;
-  context->m_output_format = new sarif_file_output_format (*context,
-							   base_file_name);
+  context->set_output_format (new sarif_file_output_format (*context,
+							    base_file_name));
 }
 
 /* Populate CONTEXT in preparation for SARIF output to STREAM.  */
@@ -1835,7 +1832,6 @@ diagnostic_output_format_init_sarif_stream (diagnostic_context *context,
 					    FILE *stream)
 {
   diagnostic_output_format_init_sarif (context);
-  delete context->m_output_format;
-  context->m_output_format = new sarif_stream_output_format (*context,
-							     stream);
+  context->set_output_format (new sarif_stream_output_format (*context,
+							      stream));
 }
diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index 4439d9a4804..d7a471426b9 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -1146,14 +1146,14 @@ make_policy (const diagnostic_context &dc,
 {
   /* The default is to not escape non-ASCII bytes.  */
   char_display_policy result
-    (dc.tabstop, cpp_wcwidth, default_print_decoded_ch);
+    (dc.m_tabstop, cpp_wcwidth, default_print_decoded_ch);
 
   /* If the diagnostic suggests escaping non-ASCII bytes, then
      use policy from user-supplied options.  */
   if (richloc.escape_on_output_p ())
     {
       result.m_undecoded_byte_width = width_per_escaped_byte;
-      switch (dc.escape_format)
+      switch (dc.get_escape_format ())
 	{
 	default:
 	  gcc_unreachable ();
@@ -2849,13 +2849,13 @@ diagnostic_show_locus (diagnostic_context * context,
 
   /* Don't print the same source location twice in a row, unless we have
      fix-it hints, or multiple locations, or a label.  */
-  if (loc == context->last_location
+  if (loc == context->m_last_location
       && richloc->get_num_fixit_hints () == 0
       && richloc->get_num_locations () == 1
       && richloc->get_range (0)->m_label == NULL)
     return;
 
-  context->last_location = loc;
+  context->m_last_location = loc;
 
   layout layout (context, richloc, diagnostic_kind, pp);
   for (int line_span_idx = 0; line_span_idx < layout.get_num_line_spans ();
@@ -2924,7 +2924,7 @@ test_display_widths ()
 
   {
     test_diagnostic_context dc;
-    dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+    dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
     char_display_policy policy (make_policy (dc, richloc));
     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 9);
@@ -2936,7 +2936,7 @@ test_display_widths ()
 
   {
     test_diagnostic_context dc;
-    dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+    dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
     char_display_policy policy (make_policy (dc, richloc));
     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 16);
@@ -3185,7 +3185,7 @@ test_layout_x_offset_display_tab (const line_table_case &case_)
   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
     {
       test_diagnostic_context dc;
-      dc.tabstop = tabstop;
+      dc.m_tabstop = tabstop;
       layout test_layout (&dc, &richloc, DK_ERROR);
       test_layout.print_line (1);
       const char *out = pp_formatted_text (dc.printer);
@@ -3203,7 +3203,7 @@ test_layout_x_offset_display_tab (const line_table_case &case_)
   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
     {
       test_diagnostic_context dc;
-      dc.tabstop = tabstop;
+      dc.m_tabstop = tabstop;
       static const int small_width = 24;
       dc.m_source_printing.max_width = small_width - 4;
       dc.m_source_printing.min_margin_width
@@ -4321,7 +4321,7 @@ test_one_liner_labels_utf8 ()
 
     {
       test_diagnostic_context dc;
-      dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+      dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
       diagnostic_show_locus (&dc, &richloc, DK_ERROR);
       ASSERT_STREQ (" <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
 		    " ^~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
@@ -4333,7 +4333,7 @@ test_one_liner_labels_utf8 ()
     }
     {
       test_diagnostic_context dc;
-      dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+      dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
       diagnostic_show_locus (&dc, &richloc, DK_ERROR);
       ASSERT_STREQ
 	(" <f0><9f><98><82>_foo = <cf><80>_bar.<f0><9f><98><82>_field<cf><80>;\n"
@@ -5517,7 +5517,7 @@ test_tab_expansion (const line_table_case &case_)
      everything too.  */
   {
     test_diagnostic_context dc;
-    dc.tabstop = tabstop;
+    dc.m_tabstop = tabstop;
     rich_location richloc (line_table,
 			   linemap_position_for_column (line_table,
 							first_non_ws_byte_col));
@@ -5532,7 +5532,7 @@ test_tab_expansion (const line_table_case &case_)
      as well.  */
   {
     test_diagnostic_context dc;
-    dc.tabstop = tabstop;
+    dc.m_tabstop = tabstop;
     rich_location richloc (line_table,
 			   linemap_position_for_column (line_table,
 							right_quote_byte_col));
@@ -5583,7 +5583,7 @@ test_escaping_bytes_1 (const line_table_case &case_)
   richloc.set_escape_on_output (true);
   {
     test_diagnostic_context dc;
-    dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+    dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
     diagnostic_show_locus (&dc, &richloc, DK_ERROR);
     ASSERT_STREQ
       (" before<U+0000><U+0001><U+0002><U+0003><U+000B><80><ff>after\n"
@@ -5592,7 +5592,7 @@ test_escaping_bytes_1 (const line_table_case &case_)
   }
   {
     test_diagnostic_context dc;
-    dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+    dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
     diagnostic_show_locus (&dc, &richloc, DK_ERROR);
     ASSERT_STREQ (" before<00><01><02><03><0b><80><ff>after\n"
 		  "       ^~~~            ~~~~\n",
@@ -5636,7 +5636,7 @@ test_escaping_bytes_2 (const line_table_case &case_)
   richloc.set_escape_on_output (true);
   {
     test_diagnostic_context dc;
-    dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+    dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
     diagnostic_show_locus (&dc, &richloc, DK_ERROR);
     ASSERT_STREQ (" <U+0000>after\n"
 		  " ^~~~~~~~\n",
@@ -5644,7 +5644,7 @@ test_escaping_bytes_2 (const line_table_case &case_)
   }
   {
     test_diagnostic_context dc;
-    dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+    dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
     diagnostic_show_locus (&dc, &richloc, DK_ERROR);
     ASSERT_STREQ (" <00>after\n"
 		  " ^~~~\n",
diff --git a/gcc/diagnostic-text-art.h b/gcc/diagnostic-text-art.h
deleted file mode 100644
index a0d8a78f52a..00000000000
--- a/gcc/diagnostic-text-art.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright (C) 2023 Free Software Foundation, Inc.
-   Contributed by David Malcolm <dmalcolm@redhat.com>.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef GCC_DIAGNOSTIC_TEXT_ART_H
-#define GCC_DIAGNOSTIC_TEXT_ART_H
-
-/* Values for -fdiagnostics-text-art-charset=.  */
-
-enum diagnostic_text_art_charset
-{
-  /* No text art diagrams shall be emitted.  */
-  DIAGNOSTICS_TEXT_ART_CHARSET_NONE,
-
-  /* Use pure ASCII for text art diagrams.  */
-  DIAGNOSTICS_TEXT_ART_CHARSET_ASCII,
-
-  /* Use ASCII + conservative use of other unicode characters
-     in text art diagrams.  */
-  DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE,
-
-  /* Use Emoji.  */
-  DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
-};
-
-const enum diagnostic_text_art_charset DIAGNOSTICS_TEXT_ART_CHARSET_DEFAULT
-  = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI;
-
-extern void
-diagnostics_text_art_charset_init (diagnostic_context *context,
-				  enum diagnostic_text_art_charset charset);
-
-
-#endif /* ! GCC_DIAGNOSTIC_TEXT_ART_H */
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 0759fae916e..4b92f5461be 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -36,7 +36,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-metadata.h"
 #include "diagnostic-path.h"
 #include "diagnostic-client-data-hooks.h"
-#include "diagnostic-text-art.h"
 #include "diagnostic-diagram.h"
 #include "edit-context.h"
 #include "selftest.h"
@@ -61,9 +60,9 @@ along with GCC; see the file COPYING3.  If not see
 #endif
 
 #define pedantic_warning_kind(DC)			\
-  ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
-#define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
-#define permissive_error_option(DC) ((DC)->opt_permissive)
+  ((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 *,
@@ -74,7 +73,6 @@ static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
 			       const char *, const char *, va_list *,
 			       diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
 
-static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
 static void real_abort (void) ATTRIBUTE_NORETURN;
 
 /* Name of program invoked, sans directories.  */
@@ -151,84 +149,86 @@ diagnostic_set_caret_max_width (diagnostic_context *context, int value)
 }
 
 /* Initialize the diagnostic message outputting machinery.  */
+
 void
-diagnostic_initialize (diagnostic_context *context, int n_opts)
+diagnostic_context::initialize (int n_opts)
 {
   int i;
 
   /* Allocate a basic pretty-printer.  Clients will replace this a
      much more elaborated pretty-printer if they wish.  */
-  context->printer = XNEW (pretty_printer);
-  new (context->printer) pretty_printer ();
-
-  memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
-  context->warning_as_error_requested = false;
-  context->n_opts = n_opts;
-  context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
+  this->printer = XNEW (pretty_printer);
+  new (this->printer) pretty_printer ();
+
+  m_file_cache = nullptr;
+  memset (m_diagnostic_count, 0, sizeof m_diagnostic_count);
+  m_warning_as_error_requested = false;
+  m_n_opts = n_opts;
+  m_classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
   for (i = 0; i < n_opts; i++)
-    context->classify_diagnostic[i] = DK_UNSPECIFIED;
-  context->m_source_printing.enabled = false;
-  diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
+    m_classify_diagnostic[i] = DK_UNSPECIFIED;
+  m_source_printing.enabled = false;
+  diagnostic_set_caret_max_width (this, pp_line_cutoff (this->printer));
   for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
-    context->m_source_printing.caret_chars[i] = '^';
-  context->show_cwe = false;
-  context->show_rules = false;
-  context->path_format = DPF_NONE;
-  context->show_path_depths = false;
-  context->show_option_requested = false;
-  context->abort_on_error = false;
-  context->show_column = false;
-  context->pedantic_errors = false;
-  context->permissive = false;
-  context->opt_permissive = 0;
-  context->fatal_errors = false;
-  context->dc_inhibit_warnings = false;
-  context->dc_warn_system_headers = false;
-  context->max_errors = 0;
-  context->internal_error = NULL;
-  diagnostic_starter (context) = default_diagnostic_starter;
-  context->m_text_callbacks.start_span = default_diagnostic_start_span_fn;
-  diagnostic_finalizer (context) = default_diagnostic_finalizer;
-  context->option_enabled = NULL;
-  context->option_state = NULL;
-  context->option_name = NULL;
-  context->get_option_url = NULL;
-  context->last_location = UNKNOWN_LOCATION;
-  context->last_module = 0;
-  context->x_data = NULL;
-  context->lock = 0;
-  context->inhibit_notes_p = false;
-  context->m_source_printing.colorize_source_p = false;
-  context->m_source_printing.show_labels_p = false;
-  context->m_source_printing.show_line_numbers_p = false;
-  context->m_source_printing.min_margin_width = 0;
-  context->m_source_printing.show_ruler_p = false;
-  context->report_bug = false;
-  context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_none;
+    m_source_printing.caret_chars[i] = '^';
+  m_show_cwe = false;
+  m_show_rules = false;
+  m_path_format = DPF_NONE;
+  m_show_path_depths = false;
+  m_show_option_requested = false;
+  m_abort_on_error = false;
+  m_show_column = false;
+  m_pedantic_errors = false;
+  m_permissive = false;
+  m_opt_permissive = 0;
+  m_fatal_errors = false;
+  m_inhibit_warnings = false;
+  m_warn_system_headers = false;
+  m_max_errors = 0;
+  m_internal_error = nullptr;
+  m_text_callbacks.begin_diagnostic = default_diagnostic_starter;
+  m_text_callbacks.start_span = default_diagnostic_start_span_fn;
+  m_text_callbacks.end_diagnostic = default_diagnostic_finalizer;
+  m_option_enabled = nullptr;
+  m_option_state = nullptr;
+  m_option_name = nullptr;
+  m_get_option_url = nullptr;
+  m_last_location = UNKNOWN_LOCATION;
+  m_last_module = nullptr;
+  m_client_aux_data = nullptr;
+  m_lock = 0;
+  m_inhibit_notes_p = false;
+  m_source_printing.colorize_source_p = false;
+  m_source_printing.show_labels_p = false;
+  m_source_printing.show_line_numbers_p = false;
+  m_source_printing.min_margin_width = 0;
+  m_source_printing.show_ruler_p = false;
+  m_report_bug = false;
+  m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_none;
   if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
     {
       if (!strcmp (var, "fixits-v1"))
-	context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
+	m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
       else if (!strcmp (var, "fixits-v2"))
-	context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
+	m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
       /* Silently ignore unrecognized values.  */
     }
-  context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
-  context->column_origin = 1;
-  context->tabstop = 8;
-  context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
-  context->edit_context_ptr = NULL;
-  context->m_diagnostic_groups.m_nesting_depth = 0;
-  context->m_diagnostic_groups.m_emission_count = 0;
-  context->m_output_format = new diagnostic_text_output_format (*context);
-  context->set_locations_cb = nullptr;
-  context->ice_handler_cb = NULL;
-  context->includes_seen = NULL;
-  context->m_client_data_hooks = NULL;
-  context->m_diagrams.m_theme = NULL;
+  m_column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
+  m_column_origin = 1;
+  m_tabstop = 8;
+  m_escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+  m_edit_context_ptr = nullptr;
+  m_diagnostic_groups.m_nesting_depth = 0;
+  m_diagnostic_groups.m_emission_count = 0;
+  m_output_format = new diagnostic_text_output_format (*this);
+  m_set_locations_cb = nullptr;
+  m_ice_handler_cb = nullptr;
+  m_includes_seen = nullptr;
+  m_client_data_hooks = nullptr;
+  m_diagrams.m_theme = nullptr;
 
   enum diagnostic_text_art_charset text_art_charset
-    = DIAGNOSTICS_TEXT_ART_CHARSET_DEFAULT;
+    = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI;
   if (const char *lang = getenv ("LANG"))
     {
       /* For LANG=C, don't assume the terminal supports anything
@@ -236,7 +236,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
       if (!strcmp (lang, "C"))
 	text_art_charset = DIAGNOSTICS_TEXT_ART_CHARSET_ASCII;
     }
-  diagnostics_text_art_charset_init (context, text_art_charset);
+  set_text_art_charset (text_art_charset);
 }
 
 /* Maybe initialize the color support. We require clients to do this
@@ -244,7 +244,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
    without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT.  */
 
 void
-diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
+diagnostic_context::color_init (int value)
 {
   /* value == -1 is the default value.  */
   if (value < 0)
@@ -263,14 +263,15 @@ diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
       else
 	value = DIAGNOSTICS_COLOR_DEFAULT;
     }
-  pp_show_color (context->printer)
+  pp_show_color (this->printer)
     = colorize_init ((diagnostic_color_rule_t) value);
 }
 
-/* Initialize URL support within CONTEXT based on VALUE, handling "auto".  */
+/* Initialize URL support within this context based on VALUE,
+   handling "auto".  */
 
 void
-diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
+diagnostic_context::urls_init (int value)
 {
   /* value == -1 is the default value.  */
   if (value < 0)
@@ -290,65 +291,90 @@ diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
 	value = DIAGNOSTICS_URLS_DEFAULT;
     }
 
-  context->printer->url_format
+  this->printer->url_format
     = determine_url_format ((diagnostic_url_rule_t) value);
 }
 
 /* Create the file_cache, if not already created, and tell it how to
    translate files on input.  */
-void diagnostic_initialize_input_context (diagnostic_context *context,
-					  diagnostic_input_charset_callback ccb,
-					  bool should_skip_bom)
+void
+diagnostic_context::
+initialize_input_context (diagnostic_input_charset_callback ccb,
+			  bool should_skip_bom)
 {
-  if (!context->m_file_cache)
-    context->m_file_cache = new file_cache;
-  context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
+  if (!m_file_cache)
+    m_file_cache = new file_cache;
+  m_file_cache->initialize_input_context (ccb, should_skip_bom);
 }
 
 /* Do any cleaning up required after the last diagnostic is emitted.  */
 
 void
-diagnostic_finish (diagnostic_context *context)
+diagnostic_context::finish ()
 {
-  delete context->m_output_format;
-  context->m_output_format= nullptr;
+  delete m_output_format;
+  m_output_format= nullptr;
 
-  if (context->m_diagrams.m_theme)
+  if (m_diagrams.m_theme)
     {
-      delete context->m_diagrams.m_theme;
-      context->m_diagrams.m_theme = NULL;
+      delete m_diagrams.m_theme;
+      m_diagrams.m_theme = nullptr;
     }
 
-  diagnostic_file_cache_fini ();
+  delete m_file_cache;
+  m_file_cache = nullptr;
 
-  XDELETEVEC (context->classify_diagnostic);
-  context->classify_diagnostic = NULL;
+  XDELETEVEC (m_classify_diagnostic);
+  m_classify_diagnostic = nullptr;
 
-  /* diagnostic_initialize allocates context->printer using XNEW
+  /* diagnostic_context::initialize allocates this->printer using XNEW
      and placement-new.  */
-  context->printer->~pretty_printer ();
-  XDELETE (context->printer);
-  context->printer = NULL;
+  this->printer->~pretty_printer ();
+  XDELETE (this->printer);
+  this->printer = nullptr;
 
-  if (context->edit_context_ptr)
+  if (m_edit_context_ptr)
     {
-      delete context->edit_context_ptr;
-      context->edit_context_ptr = NULL;
+      delete m_edit_context_ptr;
+      m_edit_context_ptr = nullptr;
     }
 
-  if (context->includes_seen)
+  if (m_includes_seen)
     {
-      delete context->includes_seen;
-      context->includes_seen = nullptr;
+      delete m_includes_seen;
+      m_includes_seen = nullptr;
     }
 
-  if (context->m_client_data_hooks)
+  if (m_client_data_hooks)
     {
-      delete context->m_client_data_hooks;
-      context->m_client_data_hooks = NULL;
+      delete m_client_data_hooks;
+      m_client_data_hooks = nullptr;
     }
 }
 
+void
+diagnostic_context::set_output_format (diagnostic_output_format *output_format)
+{
+  /* Ideally we'd use a std::unique_ptr here.  */
+  delete m_output_format;
+  m_output_format = output_format;
+}
+
+void
+diagnostic_context::set_client_data_hooks (diagnostic_client_data_hooks *hooks)
+{
+  /* Ideally we'd use a std::unique_ptr here.  */
+  delete m_client_data_hooks;
+  m_client_data_hooks = hooks;
+}
+
+void
+diagnostic_context::create_edit_context ()
+{
+  delete m_edit_context_ptr;
+  m_edit_context_ptr = new edit_context ();
+}
+
 /* Initialize DIAGNOSTIC, where the message MSG has already been
    translated.  */
 void
@@ -426,13 +452,12 @@ convert_column_unit (enum diagnostics_column_unit column_unit,
    to the requested units and origin.  Return -1 if the column is
    invalid (<= 0).  */
 int
-diagnostic_converted_column (diagnostic_context *context, expanded_location s)
+diagnostic_context::converted_column (expanded_location s) const
 {
-  int one_based_col
-    = convert_column_unit (context->column_unit, context->tabstop, s);
+  int one_based_col = convert_column_unit (m_column_unit, m_tabstop, s);
   if (one_based_col <= 0)
     return -1;
-  return one_based_col + (context->column_origin - 1);
+  return one_based_col + (m_column_origin - 1);
 }
 
 /* Return a formatted line and column ':%line:%column'.  Elided if
@@ -473,8 +498,8 @@ diagnostic_get_location_text (diagnostic_context *context,
   if (strcmp (file, special_fname_builtin ()))
     {
       line = s.line;
-      if (context->show_column)
-	col = diagnostic_converted_column (context, s);
+      if (context->m_show_column)
+	col = context->converted_column (s);
     }
 
   const char *line_col = maybe_line_and_column (line, col);
@@ -612,26 +637,26 @@ bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
 }
 
 /* Check if we've met the maximum error limit, and if so fatally exit
-   with a message.  CONTEXT is the context to check, and FLUSH
-   indicates whether a diagnostic_finish call is needed.  */
+   with a message.
+   FLUSH indicates whether a diagnostic_context::finish call is needed.  */
 
 void
-diagnostic_check_max_errors (diagnostic_context *context, bool flush)
+diagnostic_context::check_max_errors (bool flush)
 {
-  if (!context->max_errors)
+  if (!m_max_errors)
     return;
 
-  int count = (diagnostic_kind_count (context, DK_ERROR)
-	       + diagnostic_kind_count (context, DK_SORRY)
-	       + diagnostic_kind_count (context, DK_WERROR));
+  int count = (diagnostic_kind_count (this, DK_ERROR)
+	       + diagnostic_kind_count (this, DK_SORRY)
+	       + diagnostic_kind_count (this, DK_WERROR));
 
-  if (count >= context->max_errors)
+  if (count >= m_max_errors)
     {
       fnotice (stderr,
 	       "compilation terminated due to -fmax-errors=%u.\n",
-	       context->max_errors);
+	       m_max_errors);
       if (flush)
-	diagnostic_finish (context);
+	finish ();
       exit (FATAL_EXIT_CODE);
     }
 }
@@ -639,8 +664,7 @@ diagnostic_check_max_errors (diagnostic_context *context, bool flush)
 /* Take any action which is expected to happen after the diagnostic
    is written out.  This function does not always return.  */
 void
-diagnostic_action_after_output (diagnostic_context *context,
-				diagnostic_t diag_kind)
+diagnostic_context::action_after_output (diagnostic_t diag_kind)
 {
   switch (diag_kind)
     {
@@ -652,12 +676,12 @@ diagnostic_action_after_output (diagnostic_context *context,
 
     case DK_ERROR:
     case DK_SORRY:
-      if (context->abort_on_error)
+      if (m_abort_on_error)
 	real_abort ();
-      if (context->fatal_errors)
+      if (m_fatal_errors)
 	{
 	  fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
-	  diagnostic_finish (context);
+	  finish ();
 	  exit (FATAL_EXIT_CODE);
 	}
       break;
@@ -666,13 +690,12 @@ diagnostic_action_after_output (diagnostic_context *context,
     case DK_ICE_NOBT:
       {
 	/* Optional callback for attempting to handle ICEs gracefully.  */
-	if (void (*ice_handler_cb) (diagnostic_context *)
-	      = context->ice_handler_cb)
+	if (void (*ice_handler_cb) (diagnostic_context *) = m_ice_handler_cb)
 	  {
 	    /* Clear the callback, to avoid potentially re-entering
 	       the routine if there's a crash within the handler.  */
-	    context->ice_handler_cb = NULL;
-	    ice_handler_cb (context);
+	    m_ice_handler_cb = NULL;
+	    ice_handler_cb (this);
 	  }
 	/* The context might have had diagnostic_finish called on
 	   it at this point.  */
@@ -685,10 +708,10 @@ diagnostic_action_after_output (diagnostic_context *context,
 	  backtrace_full (state, 2, bt_callback, bt_err_callback,
 			  (void *) &count);
 
-	if (context->abort_on_error)
+	if (m_abort_on_error)
 	  real_abort ();
 
-	if (context->report_bug)
+	if (m_report_bug)
 	  fnotice (stderr, "Please submit a full bug report, "
 		   "with preprocessed source.\n");
 	else
@@ -704,9 +727,9 @@ diagnostic_action_after_output (diagnostic_context *context,
       }
 
     case DK_FATAL:
-      if (context->abort_on_error)
+      if (m_abort_on_error)
 	real_abort ();
-      diagnostic_finish (context);
+      finish ();
       fnotice (stderr, "compilation terminated.\n");
       exit (FATAL_EXIT_CODE);
 
@@ -715,29 +738,10 @@ diagnostic_action_after_output (diagnostic_context *context,
     }
 }
 
-/* True if the last module or file in which a diagnostic was reported is
-   different from the current one.  */
-
-static bool
-last_module_changed_p (diagnostic_context *context,
-		       const line_map_ordinary *map)
-{
-  return context->last_module != map;
-}
-
-/* Remember the current module or file as being the last one in which we
-   report a diagnostic.  */
-
-static void
-set_last_module (diagnostic_context *context, const line_map_ordinary *map)
-{
-  context->last_module = map;
-}
-
 /* Only dump the "In file included from..." stack once for each file.  */
 
-static bool
-includes_seen (diagnostic_context *context, const line_map_ordinary *map)
+bool
+diagnostic_context::includes_seen_p (const line_map_ordinary *map)
 {
   /* No include path for main.  */
   if (MAIN_FILE_P (map))
@@ -751,23 +755,23 @@ includes_seen (diagnostic_context *context, const line_map_ordinary *map)
   if (MAP_MODULE_P (probe))
     return false;
 
-  if (!context->includes_seen)
-    context->includes_seen = new hash_set<location_t, false, location_hash>;
+  if (!m_includes_seen)
+    m_includes_seen = new hash_set<location_t, false, location_hash>;
 
   /* Hash the location of the #include directive to better handle files
      that are included multiple times with different macros defined.  */
-  return context->includes_seen->add (linemap_included_from (map));
+  return m_includes_seen->add (linemap_included_from (map));
 }
 
 void
-diagnostic_report_current_module (diagnostic_context *context, location_t where)
+diagnostic_context::report_current_module (location_t where)
 {
   const line_map_ordinary *map = NULL;
 
-  if (pp_needs_newline (context->printer))
+  if (pp_needs_newline (this->printer))
     {
-      pp_newline (context->printer);
-      pp_needs_newline (context->printer) = false;
+      pp_newline (this->printer);
+      pp_needs_newline (this->printer) = false;
     }
 
   if (where <= BUILTINS_LOCATION)
@@ -777,10 +781,10 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
 			    LRK_MACRO_DEFINITION_LOCATION,
 			    &map);
 
-  if (map && last_module_changed_p (context, map))
+  if (map && m_last_module != map)
     {
-      set_last_module (context, map);
-      if (!includes_seen (context, map))
+      m_last_module = map;
+      if (!includes_seen_p (map))
 	{
 	  bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
 	  expanded_location s = {};
@@ -792,10 +796,10 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
 	      s.file = LINEMAP_FILE (map);
 	      s.line = SOURCE_LINE (map, where);
 	      int col = -1;
-	      if (first && context->show_column)
+	      if (first && m_show_column)
 		{
 		  s.column = SOURCE_COLUMN (map, where);
-		  col = diagnostic_converted_column (context, s);
+		  col = converted_column (s);
 		}
 	      const char *line_col = maybe_line_and_column (s.line, col);
 	      static const char *const msgs[] =
@@ -813,32 +817,31 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
 	      unsigned index = (was_module ? 6 : is_module ? 4
 				: need_inc ? 2 : 0) + !first;
 
-	      pp_verbatim (context->printer, "%s%s %r%s%s%R",
+	      pp_verbatim (this->printer, "%s%s %r%s%s%R",
 			   first ? "" : was_module ? ", " : ",\n",
 			   _(msgs[index]),
 			   "locus", s.file, line_col);
 	      first = false, need_inc = was_module, was_module = is_module;
 	    }
-	  while (!includes_seen (context, map));
-	  pp_verbatim (context->printer, ":");
-	  pp_newline (context->printer);
+	  while (!includes_seen_p (map));
+	  pp_verbatim (this->printer, ":");
+	  pp_newline (this->printer);
 	}
     }
 }
 
-/* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
-   print the path.  */
+/* If DIAGNOSTIC has a diagnostic_path and this context supports
+   printing paths, print the path.  */
 
 void
-diagnostic_show_any_path (diagnostic_context *context,
-			  diagnostic_info *diagnostic)
+diagnostic_context::show_any_path (const diagnostic_info &diagnostic)
 {
-  const diagnostic_path *path = diagnostic->richloc->get_path ();
+  const diagnostic_path *path = diagnostic.richloc->get_path ();
   if (!path)
     return;
 
-  if (context->print_path)
-    context->print_path (context, path);
+  if (m_print_path)
+    m_print_path (this, path);
 }
 
 /* class diagnostic_event.  */
@@ -1036,19 +1039,18 @@ default_diagnostic_finalizer (diagnostic_context *context,
    range.  If OPTION_INDEX is zero, the new setting is for all the
    diagnostics.  */
 diagnostic_t
-diagnostic_classify_diagnostic (diagnostic_context *context,
-				int option_index,
-				diagnostic_t new_kind,
-				location_t where)
+diagnostic_context::classify_diagnostic (int option_index,
+					 diagnostic_t new_kind,
+					 location_t where)
 {
   diagnostic_t old_kind;
 
   if (option_index < 0
-      || option_index >= context->n_opts
+      || option_index >= m_n_opts
       || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
     return DK_UNSPECIFIED;
 
-  old_kind = context->classify_diagnostic[option_index];
+  old_kind = m_classify_diagnostic[option_index];
 
   /* Handle pragmas separately, since we need to keep track of *where*
      the pragmas were.  */
@@ -1059,65 +1061,65 @@ diagnostic_classify_diagnostic (diagnostic_context *context,
       /* Record the command-line status, so we can reset it back on DK_POP. */
       if (old_kind == DK_UNSPECIFIED)
 	{
-	  old_kind = !context->option_enabled (option_index,
-					       context->lang_mask,
-					       context->option_state)
-	    ? DK_IGNORED : (context->warning_as_error_requested
+	  old_kind = !m_option_enabled (option_index,
+					m_lang_mask,
+					m_option_state)
+	    ? DK_IGNORED : (m_warning_as_error_requested
 			    ? DK_ERROR : DK_WARNING);
-	  context->classify_diagnostic[option_index] = old_kind;
+	  m_classify_diagnostic[option_index] = old_kind;
 	}
 
-      for (i = context->n_classification_history - 1; i >= 0; i --)
-	if (context->classification_history[i].option == option_index)
+      for (i = m_n_classification_history - 1; i >= 0; i --)
+	if (m_classification_history[i].option == option_index)
 	  {
-	    old_kind = context->classification_history[i].kind;
+	    old_kind = m_classification_history[i].kind;
 	    break;
 	  }
 
-      i = context->n_classification_history;
-      context->classification_history =
-	(diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
+      i = m_n_classification_history;
+      m_classification_history =
+	(diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
 							 * sizeof (diagnostic_classification_change_t));
-      context->classification_history[i].location = where;
-      context->classification_history[i].option = option_index;
-      context->classification_history[i].kind = new_kind;
-      context->n_classification_history ++;
+      m_classification_history[i].location = where;
+      m_classification_history[i].option = option_index;
+      m_classification_history[i].kind = new_kind;
+      m_n_classification_history ++;
     }
   else
-    context->classify_diagnostic[option_index] = new_kind;
+    m_classify_diagnostic[option_index] = new_kind;
 
   return old_kind;
 }
 
 /* Save all diagnostic classifications in a stack.  */
 void
-diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
+diagnostic_context::push_diagnostics (location_t where ATTRIBUTE_UNUSED)
 {
-  context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
-  context->push_list[context->n_push ++] = context->n_classification_history;
+  m_push_list = (int *) xrealloc (m_push_list, (m_n_push + 1) * sizeof (int));
+  m_push_list[m_n_push ++] = m_n_classification_history;
 }
 
 /* Restore the topmost classification set off the stack.  If the stack
    is empty, revert to the state based on command line parameters.  */
 void
-diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
+diagnostic_context::pop_diagnostics (location_t where)
 {
   int jump_to;
   int i;
 
-  if (context->n_push)
-    jump_to = context->push_list [-- context->n_push];
+  if (m_n_push)
+    jump_to = m_push_list [-- m_n_push];
   else
     jump_to = 0;
 
-  i = context->n_classification_history;
-  context->classification_history =
-    (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
+  i = m_n_classification_history;
+  m_classification_history =
+    (diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
 						     * sizeof (diagnostic_classification_change_t));
-  context->classification_history[i].location = where;
-  context->classification_history[i].option = jump_to;
-  context->classification_history[i].kind = DK_POP;
-  context->n_classification_history ++;
+  m_classification_history[i].location = where;
+  m_classification_history[i].option = jump_to;
+  m_classification_history[i].kind = DK_POP;
+  m_n_classification_history ++;
 }
 
 /* Helper function for print_parseable_fixits.  Print TEXT to PP, obeying the
@@ -1206,19 +1208,18 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
   pp_set_prefix (pp, saved_prefix);
 }
 
-/* Update the inlining info in CONTEXT for a DIAGNOSTIC.  */
+/* Update the inlining info in this context for a DIAGNOSTIC.  */
 
-static void
-get_any_inlining_info (diagnostic_context *context,
-		       diagnostic_info *diagnostic)
+void
+diagnostic_context::get_any_inlining_info (diagnostic_info *diagnostic)
 {
   auto &ilocs = diagnostic->m_iinfo.m_ilocs;
 
-  if (context->set_locations_cb)
+  if (m_set_locations_cb)
     /* Retrieve the locations into which the expression about to be
        diagnosed has been inlined, including those of all the callers
        all the way down the inlining stack.  */
-    context->set_locations_cb (context, diagnostic);
+    m_set_locations_cb (this, diagnostic);
   else
     {
       /* When there's no callback use just the one location provided
@@ -1237,11 +1238,11 @@ get_any_inlining_info (diagnostic_context *context,
    Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
    otherwise.  */
 
-static diagnostic_t
-update_effective_level_from_pragmas (diagnostic_context *context,
-				     diagnostic_info *diagnostic)
+diagnostic_t
+diagnostic_context::
+update_effective_level_from_pragmas (diagnostic_info *diagnostic)
 {
-  if (context->n_classification_history <= 0)
+  if (m_n_classification_history <= 0)
     return DK_UNSPECIFIED;
 
   /* Iterate over the locations, checking the diagnostic disposition
@@ -1251,10 +1252,10 @@ update_effective_level_from_pragmas (diagnostic_context *context,
   for (location_t loc: diagnostic->m_iinfo.m_ilocs)
     {
       /* FIXME: Stupid search.  Optimize later. */
-      for (int i = context->n_classification_history - 1; i >= 0; i --)
+      for (int i = m_n_classification_history - 1; i >= 0; i --)
 	{
 	  const diagnostic_classification_change_t &hist
-	    = context->classification_history[i];
+	    = m_classification_history[i];
 
 	  location_t pragloc = hist.location;
 	  if (!linemap_location_before_p (line_table, pragloc, loc))
@@ -1297,21 +1298,20 @@ get_cwe_url (int cwe)
    " [CWE-119]" will be printed, suitably colorized, and with a URL of a
    description of the security issue.  */
 
-static void
-print_any_cwe (diagnostic_context *context,
-		    const diagnostic_info *diagnostic)
+void
+diagnostic_context::print_any_cwe (const diagnostic_info &diagnostic)
 {
-  if (diagnostic->metadata == NULL)
+  if (diagnostic.metadata == NULL)
     return;
 
-  int cwe = diagnostic->metadata->get_cwe ();
+  int cwe = diagnostic.metadata->get_cwe ();
   if (cwe)
     {
-      pretty_printer *pp = context->printer;
-      char *saved_prefix = pp_take_prefix (context->printer);
+      pretty_printer * const pp = this->printer;
+      char *saved_prefix = pp_take_prefix (pp);
       pp_string (pp, " [");
       pp_string (pp, colorize_start (pp_show_color (pp),
-				     diagnostic_kind_color[diagnostic->kind]));
+				     diagnostic_kind_color[diagnostic.kind]));
       if (pp->url_format != URL_FORMAT_NONE)
 	{
 	  char *cwe_url = get_cwe_url (cwe);
@@ -1319,7 +1319,7 @@ print_any_cwe (diagnostic_context *context,
 	  free (cwe_url);
 	}
       pp_printf (pp, "CWE-%i", cwe);
-      pp_set_prefix (context->printer, saved_prefix);
+      pp_set_prefix (pp, saved_prefix);
       if (pp->url_format != URL_FORMAT_NONE)
 	pp_end_url (pp);
       pp_string (pp, colorize_stop (pp_show_color (pp)));
@@ -1333,25 +1333,24 @@ print_any_cwe (diagnostic_context *context,
    named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
    with any URL provided by the rule.  */
 
-static void
-print_any_rules (diagnostic_context *context,
-		const diagnostic_info *diagnostic)
+void
+diagnostic_context::print_any_rules (const diagnostic_info &diagnostic)
 {
-  if (diagnostic->metadata == NULL)
+  if (diagnostic.metadata == NULL)
     return;
 
-  for (unsigned idx = 0; idx < diagnostic->metadata->get_num_rules (); idx++)
+  for (unsigned idx = 0; idx < diagnostic.metadata->get_num_rules (); idx++)
     {
       const diagnostic_metadata::rule &rule
-	= diagnostic->metadata->get_rule (idx);
+	= diagnostic.metadata->get_rule (idx);
       if (char *desc = rule.make_description ())
 	{
-	  pretty_printer *pp = context->printer;
-	  char *saved_prefix = pp_take_prefix (context->printer);
+	  pretty_printer * const pp = this->printer;
+	  char *saved_prefix = pp_take_prefix (pp);
 	  pp_string (pp, " [");
 	  pp_string (pp,
 		     colorize_start (pp_show_color (pp),
-				     diagnostic_kind_color[diagnostic->kind]));
+				     diagnostic_kind_color[diagnostic.kind]));
 	  char *url = NULL;
 	  if (pp->url_format != URL_FORMAT_NONE)
 	    {
@@ -1360,7 +1359,7 @@ print_any_rules (diagnostic_context *context,
 		pp_begin_url (pp, url);
 	    }
 	  pp_string (pp, desc);
-	  pp_set_prefix (context->printer, saved_prefix);
+	  pp_set_prefix (pp, saved_prefix);
 	  if (pp->url_format != URL_FORMAT_NONE)
 	    if (url)
 	      pp_end_url (pp);
@@ -1374,29 +1373,28 @@ print_any_rules (diagnostic_context *context,
 
 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
    printer, e.g. " [-Werror=uninitialized]".
-   Subroutine of diagnostic_report_diagnostic.  */
+   Subroutine of diagnostic_context::report_diagnostic.  */
 
-static void
-print_option_information (diagnostic_context *context,
-			  const diagnostic_info *diagnostic,
-			  diagnostic_t orig_diag_kind)
+void
+diagnostic_context::print_option_information (const diagnostic_info &diagnostic,
+					      diagnostic_t orig_diag_kind)
 {
   char *option_text;
 
-  option_text = context->option_name (context, diagnostic->option_index,
-				      orig_diag_kind, diagnostic->kind);
+  option_text = m_option_name (this, diagnostic.option_index,
+			       orig_diag_kind, diagnostic.kind);
 
   if (option_text)
     {
       char *option_url = NULL;
-      if (context->get_option_url
-	  && context->printer->url_format != URL_FORMAT_NONE)
-	option_url = context->get_option_url (context,
-					      diagnostic->option_index);
-      pretty_printer *pp = context->printer;
+      if (m_get_option_url
+	  && this->printer->url_format != URL_FORMAT_NONE)
+	option_url = m_get_option_url (this,
+				       diagnostic.option_index);
+      pretty_printer * const pp = this->printer;
       pp_string (pp, " [");
       pp_string (pp, colorize_start (pp_show_color (pp),
-				     diagnostic_kind_color[diagnostic->kind]));
+				     diagnostic_kind_color[diagnostic.kind]));
       if (option_url)
 	pp_begin_url (pp, option_url);
       pp_string (pp, option_text);
@@ -1414,36 +1412,33 @@ print_option_information (diagnostic_context *context,
 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
    as appropriate for #pragma GCC diagnostic and -Werror=foo.  */
 
-static bool
-diagnostic_enabled (diagnostic_context *context,
-		    diagnostic_info *diagnostic)
+bool
+diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
 {
   /* Update the inlining stack for this diagnostic.  */
-  get_any_inlining_info (context, diagnostic);
+  get_any_inlining_info (diagnostic);
 
   /* Diagnostics with no option or -fpermissive are always enabled.  */
   if (!diagnostic->option_index
-      || diagnostic->option_index == permissive_error_option (context))
+      || diagnostic->option_index == permissive_error_option (this))
     return true;
 
   /* This tests if the user provided the appropriate -Wfoo or
      -Wno-foo option.  */
-  if (! context->option_enabled (diagnostic->option_index,
-				 context->lang_mask,
-				 context->option_state))
+  if (! m_option_enabled (diagnostic->option_index,
+			  m_lang_mask,
+			  m_option_state))
     return false;
 
   /* This tests for #pragma diagnostic changes.  */
-  diagnostic_t diag_class
-    = update_effective_level_from_pragmas (context, diagnostic);
+  diagnostic_t diag_class = update_effective_level_from_pragmas (diagnostic);
 
   /* This tests if the user provided the appropriate -Werror=foo
      option.  */
   if (diag_class == DK_UNSPECIFIED
-      && (context->classify_diagnostic[diagnostic->option_index]
+      && (m_classify_diagnostic[diagnostic->option_index]
 	  != DK_UNSPECIFIED))
-    diagnostic->kind
-      = context->classify_diagnostic[diagnostic->option_index];
+    diagnostic->kind = m_classify_diagnostic[diagnostic->option_index];
 
   /* This allows for future extensions, like temporarily disabling
      warnings for ranges of source code.  */
@@ -1456,9 +1451,9 @@ diagnostic_enabled (diagnostic_context *context,
 /* Returns whether warning OPT is enabled at LOC.  */
 
 bool
-warning_enabled_at (location_t loc, int opt)
+diagnostic_context::warning_enabled_at (location_t loc, int opt)
 {
-  if (!diagnostic_report_warnings_p (global_dc, loc))
+  if (!diagnostic_report_warnings_p (this, loc))
     return false;
 
   rich_location richloc (line_table, loc);
@@ -1467,58 +1462,56 @@ warning_enabled_at (location_t loc, int opt)
   diagnostic.richloc = &richloc;
   diagnostic.message.m_richloc = &richloc;
   diagnostic.kind = DK_WARNING;
-  return diagnostic_enabled (global_dc, &diagnostic);
+  return diagnostic_enabled (&diagnostic);
 }
 
 /* Report a diagnostic message (an error or a warning) as specified by
-   DC.  This function is *the* subroutine in terms of which front-ends
-   should implement their specific diagnostic handling modules.  The
+   this diagnostic_context.
    front-end independent format specifiers are exactly those described
    in the documentation of output_format.
    Return true if a diagnostic was printed, false otherwise.  */
 
 bool
-diagnostic_report_diagnostic (diagnostic_context *context,
-			      diagnostic_info *diagnostic)
+diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
 {
   diagnostic_t orig_diag_kind = diagnostic->kind;
 
-  gcc_assert (context->m_output_format);
+  gcc_assert (m_output_format);
 
   /* Give preference to being able to inhibit warnings, before they
      get reclassified to something else.  */
   bool was_warning = (diagnostic->kind == DK_WARNING
 		      || diagnostic->kind == DK_PEDWARN);
-  if (was_warning && context->dc_inhibit_warnings)
+  if (was_warning && m_inhibit_warnings)
     return false;
 
   if (diagnostic->kind == DK_PEDWARN)
     {
-      diagnostic->kind = pedantic_warning_kind (context);
+      diagnostic->kind = pedantic_warning_kind (this);
       /* We do this to avoid giving the message for -pedantic-errors.  */
       orig_diag_kind = diagnostic->kind;
     }
 
-  if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
+  if (diagnostic->kind == DK_NOTE && m_inhibit_notes_p)
     return false;
 
-  if (context->lock > 0)
+  if (m_lock > 0)
     {
       /* If we're reporting an ICE in the middle of some other error,
 	 try to flush out the previous error, then let this one
 	 through.  Don't do this more than once.  */
       if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
-	  && context->lock == 1)
-	pp_newline_and_flush (context->printer);
+	  && m_lock == 1)
+	pp_newline_and_flush (this->printer);
       else
-	error_recursion (context);
+	error_recursion ();
     }
 
   /* If the user requested that warnings be treated as errors, so be
      it.  Note that we do this before the next block so that
      individual warnings can be overridden back to warnings with
      -Wno-error=*.  */
-  if (context->warning_as_error_requested
+  if (m_warning_as_error_requested
       && diagnostic->kind == DK_WARNING)
     diagnostic->kind = DK_ERROR;
 
@@ -1527,21 +1520,21 @@ diagnostic_report_diagnostic (diagnostic_context *context,
   /* Check to see if the diagnostic is enabled at the location and
      not disabled by #pragma GCC diagnostic anywhere along the inlining
      stack.  .  */
-  if (!diagnostic_enabled (context, diagnostic))
+  if (!diagnostic_enabled (diagnostic))
     return false;
 
   if ((was_warning || diagnostic->kind == DK_WARNING)
-      && ((!context->dc_warn_system_headers
+      && ((!m_warn_system_headers
 	   && diagnostic->m_iinfo.m_allsyslocs)
-	  || context->dc_inhibit_warnings))
+	  || m_inhibit_warnings))
     /* Bail if the warning is not to be reported because all locations in the
        inlining stack (if there is one) are in system headers.  */
     return false;
 
   if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
-    diagnostic_check_max_errors (context);
+    diagnostic_check_max_errors (this);
 
-  context->lock++;
+  m_lock++;
 
   if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
     {
@@ -1549,9 +1542,9 @@ diagnostic_report_diagnostic (diagnostic_context *context,
 	 error has already occurred.  This is counteracted by
 	 abort_on_error.  */
       if (!CHECKING_P
-	  && (diagnostic_kind_count (context, DK_ERROR) > 0
-	      || diagnostic_kind_count (context, DK_SORRY) > 0)
-	  && !context->abort_on_error)
+	  && (diagnostic_kind_count (this, DK_ERROR) > 0
+	      || diagnostic_kind_count (this, DK_SORRY) > 0)
+	  && !m_abort_on_error)
 	{
 	  expanded_location s 
 	    = expand_location (diagnostic_location (diagnostic));
@@ -1559,58 +1552,58 @@ diagnostic_report_diagnostic (diagnostic_context *context,
 		   s.file, s.line);
 	  exit (ICE_EXIT_CODE);
 	}
-      if (context->internal_error)
-	(*context->internal_error) (context,
-				    diagnostic->message.m_format_spec,
-				    diagnostic->message.m_args_ptr);
+      if (m_internal_error)
+	(*m_internal_error) (this,
+			     diagnostic->message.m_format_spec,
+			     diagnostic->message.m_args_ptr);
     }
   if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
-    ++diagnostic_kind_count (context, DK_WERROR);
+    ++diagnostic_kind_count (this, DK_WERROR);
   else
-    ++diagnostic_kind_count (context, diagnostic->kind);
+    ++diagnostic_kind_count (this, diagnostic->kind);
 
   /* Is this the initial diagnostic within the stack of groups?  */
-  if (context->m_diagnostic_groups.m_emission_count == 0)
-    context->m_output_format->on_begin_group ();
-  context->m_diagnostic_groups.m_emission_count++;
-
-  pp_format (context->printer, &diagnostic->message);
-  context->m_output_format->on_begin_diagnostic (diagnostic);
-  pp_output_formatted_text (context->printer);
-  if (context->show_cwe)
-    print_any_cwe (context, diagnostic);
-  if (context->show_rules)
-    print_any_rules (context, diagnostic);
-  if (context->show_option_requested)
-    print_option_information (context, diagnostic, orig_diag_kind);
-  context->m_output_format->on_end_diagnostic (diagnostic, orig_diag_kind);
-  switch (context->extra_output_kind)
+  if (m_diagnostic_groups.m_emission_count == 0)
+    m_output_format->on_begin_group ();
+  m_diagnostic_groups.m_emission_count++;
+
+  pp_format (this->printer, &diagnostic->message);
+  m_output_format->on_begin_diagnostic (diagnostic);
+  pp_output_formatted_text (this->printer);
+  if (m_show_cwe)
+    print_any_cwe (*diagnostic);
+  if (m_show_rules)
+    print_any_rules (*diagnostic);
+  if (m_show_option_requested)
+    print_option_information (*diagnostic, orig_diag_kind);
+  m_output_format->on_end_diagnostic (diagnostic, orig_diag_kind);
+  switch (m_extra_output_kind)
     {
     default:
       break;
     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
-      print_parseable_fixits (context->printer, diagnostic->richloc,
+      print_parseable_fixits (this->printer, diagnostic->richloc,
 			      DIAGNOSTICS_COLUMN_UNIT_BYTE,
-			      context->tabstop);
-      pp_flush (context->printer);
+			      m_tabstop);
+      pp_flush (this->printer);
       break;
     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
-      print_parseable_fixits (context->printer, diagnostic->richloc,
+      print_parseable_fixits (this->printer, diagnostic->richloc,
 			      DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
-			      context->tabstop);
-      pp_flush (context->printer);
+			      m_tabstop);
+      pp_flush (this->printer);
       break;
     }
-  diagnostic_action_after_output (context, diagnostic->kind);
+  diagnostic_action_after_output (this, diagnostic->kind);
   diagnostic->x_data = NULL;
 
-  if (context->edit_context_ptr)
+  if (m_edit_context_ptr)
     if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
-      context->edit_context_ptr->add_fixits (diagnostic->richloc);
+      m_edit_context_ptr->add_fixits (diagnostic->richloc);
 
-  context->lock--;
+  m_lock--;
 
-  diagnostic_show_any_path (context, diagnostic);
+  show_any_path (*diagnostic);
 
   return true;
 }
@@ -1695,7 +1688,7 @@ diagnostic_append_note (diagnostic_context *context,
 
   va_start (ap, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
-  if (context->inhibit_notes_p)
+  if (context->m_inhibit_notes_p)
     {
       va_end (ap);
       return;
@@ -1735,7 +1728,7 @@ diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
 	diagnostic.option_index = opt;
     }
   diagnostic.metadata = metadata;
-  return diagnostic_report_diagnostic (global_dc, &diagnostic);
+  return global_dc->report_diagnostic (&diagnostic);
 }
 
 /* Implement inform_n, warning_n, and error_n, as documented and
@@ -1763,7 +1756,7 @@ diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
   if (kind == DK_WARNING)
     diagnostic.option_index = opt;
   diagnostic.metadata = metadata;
-  return diagnostic_report_diagnostic (global_dc, &diagnostic);
+  return global_dc->report_diagnostic (&diagnostic);
 }
 
 /* Wrapper around diagnostic_impl taking a variable argument list.  */
@@ -2203,17 +2196,16 @@ internal_error_no_backtrace (const char *gmsgid, ...)
   gcc_unreachable ();
 }
 
-/* Emit DIAGRAM to CONTEXT, respecting the output format.  */
+/* Emit DIAGRAM to this context, respecting the output format.  */
 
 void
-diagnostic_emit_diagram (diagnostic_context *context,
-			 const diagnostic_diagram &diagram)
+diagnostic_context::emit_diagram (const diagnostic_diagram &diagram)
 {
-  if (context->m_diagrams.m_theme == nullptr)
+  if (m_diagrams.m_theme == nullptr)
     return;
 
-  gcc_assert (context->m_output_format);
-  context->m_output_format->on_diagram (diagram);
+  gcc_assert (m_output_format);
+  m_output_format->on_diagram (diagram);
 }
 
 /* Special case error functions.  Most are implemented in terms of the
@@ -2236,18 +2228,18 @@ fnotice (FILE *file, const char *cmsgid, ...)
    so give up now.  But do try to flush out the previous error.
    This mustn't use internal_error, that will cause infinite recursion.  */
 
-static void
-error_recursion (diagnostic_context *context)
+void
+diagnostic_context::error_recursion ()
 {
-  if (context->lock < 3)
-    pp_newline_and_flush (context->printer);
+  if (m_lock < 3)
+    pp_newline_and_flush (this->printer);
 
   fnotice (stderr,
 	   "internal compiler error: error reporting routines re-entered.\n");
 
   /* Call diagnostic_action_after_output to get the "please submit a bug
      report" message.  */
-  diagnostic_action_after_output (context, DK_ICE);
+  diagnostic_action_after_output (this, DK_ICE);
 
   /* Do not use gcc_unreachable here; that goes through internal_error
      and therefore would cause infinite recursion.  */
@@ -2296,7 +2288,7 @@ fancy_abort (const char *file, int line, const char *function)
   internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
 }
 
-/* struct diagnostic_context.  */
+/* class diagnostic_context.  */
 
 void
 diagnostic_context::begin_group ()
@@ -2342,7 +2334,7 @@ diagnostic_text_output_format::~diagnostic_text_output_format ()
   if (diagnostic_kind_count (&m_context, DK_WERROR))
     {
       /* -Werror was given.  */
-      if (m_context.warning_as_error_requested)
+      if (m_context.warning_as_error_requested_p ())
 	pp_verbatim (m_context.printer,
 		     _("%s: all warnings being treated as errors"),
 		     progname);
@@ -2416,34 +2408,34 @@ diagnostic_output_format_init (diagnostic_context *context,
     }
 }
 
-/* Initialize CONTEXT->m_diagrams based on CHARSET.
+/* Initialize this context's m_diagrams based on CHARSET.
    Specifically, make a text_art::theme object for m_diagrams.m_theme,
    (or NULL for "no diagrams").  */
 
 void
-diagnostics_text_art_charset_init (diagnostic_context *context,
-				   enum diagnostic_text_art_charset charset)
+diagnostic_context::
+set_text_art_charset (enum diagnostic_text_art_charset charset)
 {
-  delete context->m_diagrams.m_theme;
+  delete m_diagrams.m_theme;
   switch (charset)
     {
     default:
       gcc_unreachable ();
 
     case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
-      context->m_diagrams.m_theme = NULL;
+      m_diagrams.m_theme = nullptr;
       break;
 
     case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
-      context->m_diagrams.m_theme = new text_art::ascii_theme ();
+      m_diagrams.m_theme = new text_art::ascii_theme ();
       break;
 
     case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
-      context->m_diagrams.m_theme = new text_art::unicode_theme ();
+      m_diagrams.m_theme = new text_art::unicode_theme ();
       break;
 
     case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
-      context->m_diagrams.m_theme = new text_art::emoji_theme ();
+      m_diagrams.m_theme = new text_art::emoji_theme ();
       break;
     }
 }
@@ -2802,9 +2794,9 @@ assert_location_text (const char *expected_loc_text,
 			= DIAGNOSTICS_COLUMN_UNIT_BYTE)
 {
   test_diagnostic_context dc;
-  dc.show_column = show_column;
-  dc.column_unit = column_unit;
-  dc.column_origin = origin;
+  dc.m_show_column = show_column;
+  dc.m_column_unit = column_unit;
+  dc.m_column_origin = origin;
 
   expanded_location xloc;
   xloc.file = filename;
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index ed1b6c0c7b1..2def7bddce9 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -110,6 +110,24 @@ enum diagnostics_extra_output_kind
   EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
 };
 
+/* Values for -fdiagnostics-text-art-charset=.  */
+
+enum diagnostic_text_art_charset
+{
+  /* No text art diagrams shall be emitted.  */
+  DIAGNOSTICS_TEXT_ART_CHARSET_NONE,
+
+  /* Use pure ASCII for text art diagrams.  */
+  DIAGNOSTICS_TEXT_ART_CHARSET_ASCII,
+
+  /* Use ASCII + conservative use of other unicode characters
+     in text art diagrams.  */
+  DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE,
+
+  /* Use Emoji.  */
+  DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
+};
+
 /* A diagnostic is described by the MESSAGE to send, the FILE and LINE of
    its context and its KIND (ice, error, warning, note, ...)  See complete
    list in diagnostic.def.  */
@@ -224,29 +242,163 @@ public:
 
 /* This data structure bundles altogether any information relevant to
    the context of a diagnostic message.  */
-struct diagnostic_context
+class diagnostic_context
 {
 public:
+  typedef void (*ice_handler_callback_t) (diagnostic_context *);
+  typedef void (*set_locations_callback_t) (diagnostic_context *,
+					    diagnostic_info *);
+
+  void initialize (int n_opts);
+  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)
+  {
+    m_set_locations_cb = cb;
+  }
+
+  void
+  initialize_input_context (diagnostic_input_charset_callback ccb,
+			    bool should_skip_bom);
+
   void begin_group ();
   void end_group ();
 
-public:
+  bool warning_enabled_at (location_t loc, int opt);
 
+  bool option_unspecified_p (int opt) const
+  {
+    gcc_assert (opt < m_n_opts);
+    return m_classify_diagnostic[opt] == DK_UNSPECIFIED;
+  }
+
+  bool report_diagnostic (diagnostic_info *);
+
+  void report_current_module (location_t where);
+
+  void check_max_errors (bool flush);
+  void action_after_output (diagnostic_t diag_kind);
+
+  diagnostic_t
+  classify_diagnostic (int option_index,
+		       diagnostic_t new_kind,
+		       location_t where);
+  void push_diagnostics (location_t where ATTRIBUTE_UNUSED);
+  void pop_diagnostics (location_t where);
+
+  void emit_diagram (const diagnostic_diagram &diagram);
+
+  /* Various setters for use by option-handling logic.  */
+  void set_output_format (diagnostic_output_format *output_format);
+  void set_text_art_charset (enum diagnostic_text_art_charset charset);
+  void set_client_data_hooks (diagnostic_client_data_hooks *hooks);
+  void create_edit_context ();
+  void set_warning_as_error_requested (bool val)
+  {
+    m_warning_as_error_requested = val;
+  }
+  void set_report_bug (bool val) { m_report_bug = val; }
+  void set_extra_output_kind (enum diagnostics_extra_output_kind kind)
+  {
+    m_extra_output_kind = kind;
+  }
+  void set_show_cwe (bool val) { m_show_cwe = val;  }
+  void set_show_rules (bool val) { m_show_rules = val; }
+  void set_path_format (enum diagnostic_path_format val)
+  {
+    m_path_format = val;
+  }
+  void set_show_path_depths (bool val) { m_show_path_depths = val; }
+  void set_show_option_requested (bool val) { m_show_option_requested = val; }
+  void set_max_errors (int val) { m_max_errors = val; }
+  void set_escape_format (enum diagnostics_escape_format val)
+  {
+    m_escape_format = val;
+  }
+  void set_ice_handler_callback (ice_handler_callback_t cb)
+  {
+    m_ice_handler_cb = cb;
+  }
+
+  /* Various accessors.  */
+  bool warning_as_error_requested_p () const
+  {
+    return m_warning_as_error_requested;
+  }
+  bool show_path_depths_p () const { return m_show_path_depths; }
+  enum diagnostic_path_format get_path_format () const { return m_path_format; }
+  enum diagnostics_escape_format get_escape_format () const
+  {
+    return m_escape_format;
+  }
+
+  file_cache *
+  get_file_cache () const
+  {
+    return m_file_cache;
+  }
+
+  edit_context *get_edit_context () const
+  {
+    return m_edit_context_ptr;
+  }
+  const diagnostic_client_data_hooks *get_client_data_hooks ()
+  {
+    return m_client_data_hooks;
+  }
+  text_art::theme *get_diagram_theme () const { return m_diagrams.m_theme; }
+
+  int converted_column (expanded_location s) const;
+
+  int &diagnostic_count (diagnostic_t kind)
+  {
+    return m_diagnostic_count[kind];
+  }
+
+private:
+  bool includes_seen_p (const line_map_ordinary *map);
+
+  void print_any_cwe (const diagnostic_info &diagnostic);
+  void print_any_rules (const diagnostic_info &diagnostic);
+  void print_option_information (const diagnostic_info &diagnostic,
+				 diagnostic_t orig_diag_kind);
+
+  void show_any_path (const diagnostic_info &diagnostic);
+
+  void error_recursion () ATTRIBUTE_NORETURN;
+
+  bool diagnostic_enabled (diagnostic_info *diagnostic);
+
+  void get_any_inlining_info (diagnostic_info *diagnostic);
+  diagnostic_t
+  update_effective_level_from_pragmas (diagnostic_info *diagnostic);
+
+
+  /* Data members.
+     Ideally, all of these would be private and have "m_" prefixes.  */
+
+public:
   /* Where most of the diagnostic formatting work is done.  */
   pretty_printer *printer;
 
+private:
   /* Cache of source code.  */
   file_cache *m_file_cache;
 
   /* The number of times we have issued diagnostics.  */
-  int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
+  int m_diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
 
   /* True if it has been requested that warnings be treated as errors.  */
-  bool warning_as_error_requested;
+  bool m_warning_as_error_requested;
 
   /* The number of option indexes that can be passed to warning() et
      al.  */
-  int n_opts;
+  int m_n_opts;
 
   /* For each option index that can be passed to warning() et al
      (OPT_* from options.h when using this code with the core GCC
@@ -254,67 +406,70 @@ public:
      should be changed to before reporting, or DK_UNSPECIFIED to leave
      it as the reported kind, or DK_IGNORED to not report it at
      all.  */
-  diagnostic_t *classify_diagnostic;
+  diagnostic_t *m_classify_diagnostic;
 
   /* History of all changes to the classifications above.  This list
      is stored in location-order, so we can search it, either
      binary-wise or end-to-front, to find the most recent
      classification for a given diagnostic, given the location of the
      diagnostic.  */
-  diagnostic_classification_change_t *classification_history;
+  diagnostic_classification_change_t *m_classification_history;
 
   /* The size of the above array.  */
-  int n_classification_history;
+  int m_n_classification_history;
 
   /* For pragma push/pop.  */
-  int *push_list;
-  int n_push;
+  int *m_push_list;
+  int m_n_push;
 
   /* True if we should print any CWE identifiers associated with
      diagnostics.  */
-  bool show_cwe;
+  bool m_show_cwe;
 
   /* True if we should print any rules associated with diagnostics.  */
-  bool show_rules;
+  bool m_show_rules;
 
   /* How should diagnostic_path objects be printed.  */
-  enum diagnostic_path_format path_format;
+  enum diagnostic_path_format m_path_format;
 
   /* True if we should print stack depths when printing diagnostic paths.  */
-  bool show_path_depths;
+  bool m_show_path_depths;
 
   /* True if we should print the command line option which controls
      each diagnostic, if known.  */
-  bool show_option_requested;
+  bool m_show_option_requested;
 
+public:
   /* True if we should raise a SIGABRT on errors.  */
-  bool abort_on_error;
+  bool m_abort_on_error;
 
   /* True if we should show the column number on diagnostics.  */
-  bool show_column;
+  bool m_show_column;
 
   /* True if pedwarns are errors.  */
-  bool pedantic_errors;
+  bool m_pedantic_errors;
 
   /* True if permerrors are warnings.  */
-  bool permissive;
+  bool m_permissive;
 
   /* The index of the option to associate with turning permerrors into
      warnings.  */
-  int opt_permissive;
+  int m_opt_permissive;
 
   /* True if errors are fatal.  */
-  bool fatal_errors;
+  bool m_fatal_errors;
 
   /* True if all warnings should be disabled.  */
-  bool dc_inhibit_warnings;
+  bool m_inhibit_warnings;
 
   /* True if warnings should be given in system headers.  */
-  bool dc_warn_system_headers;
+  bool m_warn_system_headers;
 
+private:
   /* Maximum number of errors to report.  */
-  int max_errors;
+  int m_max_errors;
 
+public:
   /* Client-supplied callbacks for use in text output.  */
   struct {
     /* This function is called before any message is printed out.  It is
@@ -336,15 +491,15 @@ public:
   } m_text_callbacks;
 
   /* Client hook to report an internal error.  */
-  void (*internal_error) (diagnostic_context *, const char *, va_list *);
+  void (*m_internal_error) (diagnostic_context *, const char *, va_list *);
 
   /* Client hook to say whether the option controlling a diagnostic is
      enabled.  Returns nonzero if enabled, zero if disabled.  */
-  int (*option_enabled) (int, unsigned, void *);
+  int (*m_option_enabled) (int, unsigned, void *);
 
   /* Client information to pass as second argument to
      option_enabled.  */
-  void *option_state;
+  void *m_option_state;
 
   /* Client hook to return the name of an option that controls a
      diagnostic.  Returns malloced memory.  The first diagnostic_t
@@ -352,33 +507,39 @@ public:
      (of warnings as errors, etc.); the second is the kind after any
      reclassification.  May return NULL if no name is to be printed.
      May be passed 0 as well as the index of a particular option.  */
-  char *(*option_name) (diagnostic_context *, int, diagnostic_t, diagnostic_t);
+  char *(*m_option_name) (diagnostic_context *,
+			  int,
+			  diagnostic_t,
+			  diagnostic_t);
 
   /* Client hook to return a URL describing the option that controls
      a diagnostic.  Returns malloced memory.  May return NULL if no URL
      is available.  May be passed 0 as well as the index of a
      particular option.  */
-  char *(*get_option_url) (diagnostic_context *, int);
+  char *(*m_get_option_url) (diagnostic_context *, int);
 
-  void (*print_path) (diagnostic_context *, const diagnostic_path *);
-  json::value *(*make_json_for_path) (diagnostic_context *, const diagnostic_path *);
+  void (*m_print_path) (diagnostic_context *, const diagnostic_path *);
+  json::value *(*m_make_json_for_path) (diagnostic_context *,
+					const diagnostic_path *);
 
   /* Auxiliary data for client.  */
-  void *x_data;
+  void *m_client_aux_data;
 
   /* Used to detect that the last caret was printed at the same location.  */
-  location_t last_location;
+  location_t m_last_location;
 
+private:
   /* Used to detect when the input file stack has changed since last
      described.  */
-  const line_map_ordinary *last_module;
+  const line_map_ordinary *m_last_module;
 
-  int lock;
+  int m_lock;
 
+public:
   /* A copy of lang_hooks.option_lang_mask ().  */
-  unsigned lang_mask;
+  unsigned m_lang_mask;
 
-  bool inhibit_notes_p;
+  bool m_inhibit_notes_p;
 
   /* Fields relating to printing the user's source code (potentially with
      a margin, underlining, labels, etc).  */
@@ -424,30 +585,33 @@ public:
 
   } m_source_printing;
 
+private:
   /* True if -freport-bug option is used.  */
-  bool report_bug;
+  bool m_report_bug;
 
   /* Used to specify additional diagnostic output to be emitted after the
      rest of the diagnostic.  This is for implementing
      -fdiagnostics-parseable-fixits and GCC_EXTRA_DIAGNOSTIC_OUTPUT.  */
-  enum diagnostics_extra_output_kind extra_output_kind;
+  enum diagnostics_extra_output_kind m_extra_output_kind;
 
+public:
   /* What units to use when outputting the column number.  */
-  enum diagnostics_column_unit column_unit;
+  enum diagnostics_column_unit m_column_unit;
 
   /* The origin for the column number (1-based or 0-based typically).  */
-  int column_origin;
+  int m_column_origin;
 
   /* The size of the tabstop for tab expansion.  */
-  int tabstop;
+  int m_tabstop;
 
+private:
   /* How should non-ASCII/non-printable bytes be escaped when
      a diagnostic suggests escaping the source code on output.  */
-  enum diagnostics_escape_format escape_format;
+  enum diagnostics_escape_format m_escape_format;
 
   /* If non-NULL, an edit_context to which fix-it hints should be
      applied, for generating patches.  */
-  edit_context *edit_context_ptr;
+  edit_context *m_edit_context_ptr;
 
   /* Fields relating to diagnostic groups.  */
   struct {
@@ -467,14 +631,14 @@ public:
      stack corresponding to a diagnostic location.  Needed to traverse
      the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
      of a diagnostic's location.  */
-  void (*set_locations_cb)(diagnostic_context *, diagnostic_info *);
+  set_locations_callback_t m_set_locations_cb;
 
   /* Optional callback for attempting to handle ICEs gracefully.  */
-  void (*ice_handler_cb) (diagnostic_context *context);
+  ice_handler_callback_t m_ice_handler_cb;
 
   /* Include files that diagnostic_report_current_module has already listed the
      include path for.  */
-  hash_set<location_t, false, location_hash> *includes_seen;
+  hash_set<location_t, false, location_hash> *m_includes_seen;
 
   /* A bundle of hooks for providing data to the context about its client
      e.g. version information, plugins, etc.
@@ -495,7 +659,7 @@ public:
 inline void
 diagnostic_inhibit_notes (diagnostic_context * context)
 {
-  context->inhibit_notes_p = true;
+  context->m_inhibit_notes_p = true;
 }
 
 
@@ -508,7 +672,7 @@ diagnostic_inhibit_notes (diagnostic_context * context)
 #define diagnostic_finalizer(DC) (DC)->m_text_callbacks.end_diagnostic
 
 /* Extension hooks for client.  */
-#define diagnostic_context_auxiliary_data(DC) (DC)->x_data
+#define diagnostic_context_auxiliary_data(DC) (DC)->m_client_aux_data
 #define diagnostic_info_auxiliary_data(DI) (DI)->x_data
 
 /* Same as pp_format_decoder.  Works on 'diagnostic_context *'.  */
@@ -518,8 +682,11 @@ diagnostic_inhibit_notes (diagnostic_context * context)
 #define diagnostic_prefixing_rule(DC) ((DC)->printer->wrapping.rule)
 
 /* Raise SIGABRT on any diagnostic of severity DK_ERROR or higher.  */
-#define diagnostic_abort_on_error(DC) \
-  (DC)->abort_on_error = true
+inline void
+diagnostic_abort_on_error (diagnostic_context *context)
+{
+  context->m_abort_on_error = true;
+}
 
 /* This diagnostic_context is used by front-ends that directly output
    diagnostic messages without going through `error', `warning',
@@ -531,7 +698,13 @@ extern diagnostic_context *global_dc;
 #define diagnostic_ready_p() (global_dc->printer != NULL)
 
 /* The total count of a KIND of diagnostics emitted so far.  */
-#define diagnostic_kind_count(DC, DK) (DC)->diagnostic_count[(int) (DK)]
+
+inline int &
+diagnostic_kind_count (diagnostic_context *context,
+		       diagnostic_t kind)
+{
+  return context->diagnostic_count (kind);
+}
 
 /* The number of errors that have been issued so far.  Ideally, these
    would take a diagnostic_context as an argument.  */
@@ -545,8 +718,8 @@ extern diagnostic_context *global_dc;
 
 /* Returns nonzero if warnings should be emitted.  */
 #define diagnostic_report_warnings_p(DC, LOC)				\
-  (!(DC)->dc_inhibit_warnings						\
-   && !(in_system_header_at (LOC) && !(DC)->dc_warn_system_headers))
+  (!(DC)->m_inhibit_warnings						\
+   && !(in_system_header_at (LOC) && !(DC)->m_warn_system_headers))
 
 /* Override the option index to be used for reporting a
    diagnostic.  */
@@ -558,16 +731,42 @@ diagnostic_override_option_index (diagnostic_info *info, int optidx)
 }
 
 /* Diagnostic related functions.  */
-extern void diagnostic_initialize (diagnostic_context *, int);
-extern void diagnostic_color_init (diagnostic_context *, int value = -1);
-extern void diagnostic_urls_init (diagnostic_context *, int value = -1);
-extern void diagnostic_finish (diagnostic_context *);
-extern void diagnostic_report_current_module (diagnostic_context *, location_t);
+
+inline void
+diagnostic_initialize (diagnostic_context *context, int n_opts)
+{
+  context->initialize (n_opts);
+}
+
+inline void
+diagnostic_color_init (diagnostic_context *context, int value = -1)
+{
+  context->color_init (value);
+}
+
+inline void
+diagnostic_urls_init (diagnostic_context *context, int value = -1)
+{
+  context->urls_init (value);
+}
+
+inline void
+diagnostic_finish (diagnostic_context *context)
+{
+  context->finish ();
+}
+
+inline void
+diagnostic_report_current_module (diagnostic_context *context,
+				  location_t where)
+{
+  context->report_current_module (where);
+}
+
 extern void diagnostic_show_locus (diagnostic_context *,
 				   rich_location *richloc,
 				   diagnostic_t diagnostic_kind,
 				   pretty_printer *pp = nullptr);
-extern void diagnostic_show_any_path (diagnostic_context *, diagnostic_info *);
 
 /* Because we read source files a second time after the frontend did it the
    first time, we need to know how the frontend handled things like character
@@ -584,19 +783,51 @@ extern void diagnostic_show_any_path (diagnostic_context *, diagnostic_info *);
    beginning of the file.  (In case a conversion was performed, the BOM is
    rather skipped as part of the conversion process.)  */
 
-void diagnostic_initialize_input_context (diagnostic_context *context,
-					  diagnostic_input_charset_callback ccb,
-					  bool should_skip_bom);
+inline void
+diagnostic_initialize_input_context (diagnostic_context *context,
+				     diagnostic_input_charset_callback ccb,
+				     bool should_skip_bom)
+{
+  context->initialize_input_context (ccb, should_skip_bom);
+}
 
 /* Force diagnostics controlled by OPTIDX to be kind KIND.  */
-extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
-						    int /* optidx */,
-						    diagnostic_t /* kind */,
-						    location_t);
-extern void diagnostic_push_diagnostics (diagnostic_context *, location_t);
-extern void diagnostic_pop_diagnostics (diagnostic_context *, location_t);
-extern bool diagnostic_report_diagnostic (diagnostic_context *,
-					  diagnostic_info *);
+inline diagnostic_t
+diagnostic_classify_diagnostic (diagnostic_context *context,
+				int optidx,
+				diagnostic_t kind,
+				location_t where)
+{
+  return context->classify_diagnostic (optidx, kind, where);
+}
+
+inline void
+diagnostic_push_diagnostics (diagnostic_context *context,
+			     location_t where)
+{
+  context->push_diagnostics (where);
+}
+inline void
+diagnostic_pop_diagnostics (diagnostic_context *context,
+			    location_t where)
+{
+  context->pop_diagnostics (where);
+}
+
+/* Report a diagnostic message (an error or a warning) as specified by
+   DC.  This function is *the* subroutine in terms of which front-ends
+   should implement their specific diagnostic handling modules.  The
+   front-end independent format specifiers are exactly those described
+   in the documentation of output_format.
+   Return true if a diagnostic was printed, false otherwise.  */
+
+inline bool
+diagnostic_report_diagnostic (diagnostic_context *context,
+			      diagnostic_info *diagnostic)
+{
+  return context->report_diagnostic (diagnostic);
+}
+
 #ifdef ATTRIBUTE_GCC_DIAG
 extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
 				 rich_location *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
@@ -614,10 +845,19 @@ void default_diagnostic_start_span_fn (diagnostic_context *,
 void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *,
 				   diagnostic_t);
 void diagnostic_set_caret_max_width (diagnostic_context *context, int value);
-void diagnostic_action_after_output (diagnostic_context *, diagnostic_t);
-void diagnostic_check_max_errors (diagnostic_context *, bool flush = false);
 
-void diagnostic_file_cache_fini (void);
+inline void
+diagnostic_action_after_output (diagnostic_context *context,
+				diagnostic_t diag_kind)
+{
+  context->action_after_output (diag_kind);
+}
+
+inline void
+diagnostic_check_max_errors (diagnostic_context *context, bool flush = false)
+{
+  context->check_max_errors (flush);
+}
 
 int get_terminal_width (void);
 
@@ -667,8 +907,6 @@ diagnostic_same_line (const diagnostic_context *context,
 }
 
 extern const char *diagnostic_get_color_for_kind (diagnostic_t kind);
-extern int diagnostic_converted_column (diagnostic_context *context,
-					expanded_location s);
 
 /* Pure text formatting support functions.  */
 extern char *file_name_as_prefix (diagnostic_context *, const char *);
@@ -693,11 +931,18 @@ extern int num_digits (int);
 extern json::value *json_from_expanded_location (diagnostic_context *context,
 						 location_t loc);
 
-extern bool warning_enabled_at (location_t, int);
+inline bool
+warning_enabled_at (location_t loc, int opt)
+{
+  return global_dc->warning_enabled_at (loc, opt);
+}
+
+inline bool
+option_unspecified_p (int opt)
+{
+  return global_dc->option_unspecified_p (opt);
+}
 
 extern char *get_cwe_url (int cwe);
 
-extern void diagnostic_emit_diagram (diagnostic_context *context,
-				     const diagnostic_diagram &diagram);
-
 #endif /* ! GCC_DIAGNOSTIC_H */
diff --git a/gcc/fortran/cpp.cc b/gcc/fortran/cpp.cc
index 67e4d4ed170..02c28a74a2e 100644
--- a/gcc/fortran/cpp.cc
+++ b/gcc/fortran/cpp.cc
@@ -1084,13 +1084,13 @@ cb_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
 {
   diagnostic_info diagnostic;
   diagnostic_t dlevel;
-  bool save_warn_system_headers = global_dc->dc_warn_system_headers;
+  bool save_warn_system_headers = global_dc->m_warn_system_headers;
   bool ret;
 
   switch (level)
     {
     case CPP_DL_WARNING_SYSHDR:
-      global_dc->dc_warn_system_headers = 1;
+      global_dc->m_warn_system_headers = 1;
       /* Fall through.  */
     case CPP_DL_WARNING:
       dlevel = DK_WARNING;
@@ -1119,7 +1119,7 @@ cb_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
 				    cb_cpp_diagnostic_cpp_option (reason));
   ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
-    global_dc->dc_warn_system_headers = save_warn_system_headers;
+    global_dc->m_warn_system_headers = save_warn_system_headers;
   return ret;
 }
 
diff --git a/gcc/fortran/error.cc b/gcc/fortran/error.cc
index 1b346192738..ca31775c2dc 100644
--- a/gcc/fortran/error.cc
+++ b/gcc/fortran/error.cc
@@ -871,7 +871,7 @@ gfc_clear_pp_buffer (output_buffer *this_buffer)
   pp->buffer = tmp_buffer;
   /* We need to reset last_location, otherwise we may skip caret lines
      when we actually give a diagnostic.  */
-  global_dc->last_location = UNKNOWN_LOCATION;
+  global_dc->m_last_location = UNKNOWN_LOCATION;
 }
 
 /* The currently-printing diagnostic, for use by gfc_format_decoder,
@@ -903,7 +903,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap)
 
   diagnostic_info diagnostic;
   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
-  bool fatal_errors = global_dc->fatal_errors;
+  bool fatal_errors = global_dc->m_fatal_errors;
   pretty_printer *pp = global_dc->printer;
   output_buffer *tmp_buffer = pp->buffer;
 
@@ -912,7 +912,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap)
   if (buffered_p)
     {
       pp->buffer = pp_warning_buffer;
-      global_dc->fatal_errors = false;
+      global_dc->m_fatal_errors = false;
       /* To prevent -fmax-errors= triggering.  */
       --werrorcount;
     }
@@ -925,7 +925,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap)
   if (buffered_p)
     {
       pp->buffer = tmp_buffer;
-      global_dc->fatal_errors = fatal_errors;
+      global_dc->m_fatal_errors = fatal_errors;
 
       warningcount_buffered = 0;
       werrorcount_buffered = 0;
@@ -1156,7 +1156,7 @@ gfc_diagnostic_build_locus_prefix (diagnostic_context *context,
 	  ? build_message_string ("%s%s:%s", locus_cs, progname, locus_ce )
 	  : !strcmp (s.file, special_fname_builtin ())
 	  ? build_message_string ("%s%s:%s", locus_cs, s.file, locus_ce)
-	  : context->show_column
+	  : context->m_show_column
 	  ? build_message_string ("%s%s:%d:%d:%s", locus_cs, s.file, s.line,
 				  s.column, locus_ce)
 	  : build_message_string ("%s%s:%d:%s", locus_cs, s.file, s.line, locus_ce));
@@ -1176,7 +1176,7 @@ gfc_diagnostic_build_locus_prefix (diagnostic_context *context,
 	  ? build_message_string ("%s%s:%s", locus_cs, progname, locus_ce )
 	  : !strcmp (s.file, special_fname_builtin ())
 	  ? build_message_string ("%s%s:%s", locus_cs, s.file, locus_ce)
-	  : context->show_column
+	  : context->m_show_column
 	  ? build_message_string ("%s%s:%d:%d-%d:%s", locus_cs, s.file, s.line,
 				  MIN (s.column, s2.column),
 				  MAX (s.column, s2.column), locus_ce)
@@ -1224,7 +1224,7 @@ gfc_diagnostic_starter (diagnostic_context *context,
 
   if (!context->m_source_printing.enabled
       || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
-      || diagnostic_location (diagnostic, 0) == context->last_location)
+      || diagnostic_location (diagnostic, 0) == context->m_last_location)
     {
       pp_set_prefix (context->printer,
 		     concat (locus_prefix, " ", kind_prefix, NULL));
@@ -1437,7 +1437,7 @@ gfc_error_opt (int opt, const char *gmsgid, va_list ap)
 
   diagnostic_info diagnostic;
   rich_location richloc (line_table, UNKNOWN_LOCATION);
-  bool fatal_errors = global_dc->fatal_errors;
+  bool fatal_errors = global_dc->m_fatal_errors;
   pretty_printer *pp = global_dc->printer;
   output_buffer *tmp_buffer = pp->buffer;
 
@@ -1447,10 +1447,10 @@ gfc_error_opt (int opt, const char *gmsgid, va_list ap)
     {
       /* To prevent -dH from triggering an abort on a buffered error,
 	 save abort_on_error and restore it below.  */
-      saved_abort_on_error = global_dc->abort_on_error;
-      global_dc->abort_on_error = false;
+      saved_abort_on_error = global_dc->m_abort_on_error;
+      global_dc->m_abort_on_error = false;
       pp->buffer = pp_error_buffer;
-      global_dc->fatal_errors = false;
+      global_dc->m_fatal_errors = false;
       /* To prevent -fmax-errors= triggering, we decrease it before
 	 report_diagnostic increases it.  */
       --errorcount;
@@ -1462,8 +1462,8 @@ gfc_error_opt (int opt, const char *gmsgid, va_list ap)
   if (buffered_p)
     {
       pp->buffer = tmp_buffer;
-      global_dc->fatal_errors = fatal_errors;
-      global_dc->abort_on_error = saved_abort_on_error;
+      global_dc->m_fatal_errors = fatal_errors;
+      global_dc->m_abort_on_error = saved_abort_on_error;
 
     }
 
diff --git a/gcc/fortran/options.cc b/gcc/fortran/options.cc
index 2ad22478042..cfb195756a8 100644
--- a/gcc/fortran/options.cc
+++ b/gcc/fortran/options.cc
@@ -389,8 +389,7 @@ gfc_post_options (const char **pfilename)
       /* Enable -Werror=line-truncation when -Werror and -Wno-error have
 	 not been set.  */
       if (warn_line_truncation && !OPTION_SET_P (warnings_are_errors)
-	  && (global_dc->classify_diagnostic[OPT_Wline_truncation] ==
-	      DK_UNSPECIFIED))
+	  && option_unspecified_p (OPT_Wline_truncation))
 	diagnostic_classify_diagnostic (global_dc, OPT_Wline_truncation,
 					DK_ERROR, UNKNOWN_LOCATION);
     }
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 884284e66b4..0b7e07872cd 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -46,7 +46,6 @@ compilation is specified by a string called a "spec".  */
 #include "spellcheck.h"
 #include "opts-jobserver.h"
 #include "common/common-target.h"
-#include "diagnostic-text-art.h"
 
 #ifndef MATH_LIBRARY
 #define MATH_LIBRARY "m"
@@ -4355,8 +4354,7 @@ driver_handle_option (struct gcc_options *opts,
 	}
 
     case OPT_fdiagnostics_text_art_charset_:
-      diagnostics_text_art_charset_init (dc,
-					 (enum diagnostic_text_art_charset)value);
+      dc->set_text_art_charset ((enum diagnostic_text_art_charset)value);
       break;
 
     case OPT_Wa_:
diff --git a/gcc/input.cc b/gcc/input.cc
index 6256d81f531..f7c01637291 100644
--- a/gcc/input.cc
+++ b/gcc/input.cc
@@ -294,21 +294,14 @@ static void
 diagnostic_file_cache_init (void)
 {
   gcc_assert (global_dc);
-  if (global_dc->m_file_cache == NULL)
-    global_dc->m_file_cache = new file_cache ();
+  global_dc->file_cache_init ();
 }
 
-/* Free the resources used by the set of cache used for files accessed
-   by caret diagnostic.  */
-
 void
-diagnostic_file_cache_fini (void)
+diagnostic_context::file_cache_init ()
 {
-  if (global_dc->m_file_cache)
-    {
-      delete global_dc->m_file_cache;
-      global_dc->m_file_cache = NULL;
-    }
+  if (m_file_cache == nullptr)
+    m_file_cache = new file_cache ();
 }
 
 /* Return the total lines number that have been read so far by the
@@ -366,10 +359,10 @@ diagnostics_file_cache_forcibly_evict_file (const char *file_path)
 {
   gcc_assert (file_path);
 
-  if (!global_dc->m_file_cache)
+  auto file_cache = global_dc->get_file_cache ();
+  if (!file_cache)
     return;
-
-  global_dc->m_file_cache->forcibly_evict_file (file_path);
+  file_cache->forcibly_evict_file (file_path);
 }
 
 void
@@ -978,7 +971,7 @@ char_span
 location_get_source_line (const char *file_path, int line)
 {
   diagnostic_file_cache_init ();
-  return global_dc->m_file_cache->get_source_line (file_path, line);
+  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
@@ -1091,7 +1084,7 @@ char_span
 get_source_file_content (const char *file_path)
 {
   diagnostic_file_cache_init ();
-  return global_dc->m_file_cache->get_source_file_content (file_path);
+  return global_dc->get_file_cache ()->get_source_file_content (file_path);
 }
 
 /* Determine if FILE_PATH missing a trailing newline on its final line.
@@ -1103,7 +1096,7 @@ location_missing_trailing_newline (const char *file_path)
 {
   diagnostic_file_cache_init ();
 
-  file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
+  file_cache_slot *c = global_dc->get_file_cache ()->lookup_or_add_file (file_path);
   if (c == NULL)
     return false;
 
diff --git a/gcc/input.h b/gcc/input.h
index bfd71dfd619..5eac1dc40a6 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -254,8 +254,6 @@ void dump_line_table_statistics (void);
 
 void dump_location_info (FILE *stream);
 
-void diagnostics_file_cache_fini (void);
-
 void diagnostics_file_cache_forcibly_evict_file (const char *file_path);
 
 class GTY(()) string_concat
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 7249ce8cadb..18cc4da25b8 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -3512,7 +3512,7 @@ add_error_va (location *loc, const char *fmt, va_list ap)
 
 void
 playback::context::
-add_diagnostic (struct diagnostic_context *diag_context,
+add_diagnostic (diagnostic_context *diag_context,
 		struct diagnostic_info *diagnostic)
 {
   /* At this point the text has been formatted into the pretty-printer's
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 438f395f6d9..f9e29d0baec 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "jit-recording.h"
 
-struct diagnostic_context;
+class diagnostic_context;
 struct diagnostic_info;
 
 namespace gcc {
@@ -247,7 +247,7 @@ public:
   get_first_error () const;
 
   void
-  add_diagnostic (struct diagnostic_context *context,
+  add_diagnostic (diagnostic_context *context,
 		  struct diagnostic_info *diagnostic);
 
   void
diff --git a/gcc/langhooks.cc b/gcc/langhooks.cc
index 9a1a9eccca9..cf047d9e530 100644
--- a/gcc/langhooks.cc
+++ b/gcc/langhooks.cc
@@ -444,7 +444,7 @@ lhd_print_error_function (diagnostic_context *context, const char *file,
 		  pp_newline (context->printer);
 		  if (s.file != NULL)
 		    {
-		      if (context->show_column)
+		      if (context->m_show_column)
 			pp_printf (context->printer,
 				   _("    inlined from %qs at %r%s:%d:%d%R"),
 				   identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)),
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
index 5186d040ce0..a92fed3d25b 100644
--- a/gcc/lto-wrapper.cc
+++ b/gcc/lto-wrapper.cc
@@ -1355,7 +1355,7 @@ void
 print_lto_docs_link ()
 {
   bool print_url = global_dc->printer->url_format != URL_FORMAT_NONE;
-  const char *url = global_dc->get_option_url (global_dc, OPT_flto);
+  const char *url = global_dc->m_get_option_url (global_dc, OPT_flto);
 
   pretty_printer pp;
   pp.url_format = URL_FORMAT_DEFAULT;
@@ -2146,7 +2146,7 @@ main (int argc, char *argv[])
   diagnostic_initialize (global_dc, 0);
   diagnostic_color_init (global_dc);
   diagnostic_urls_init (global_dc);
-  global_dc->get_option_url = get_option_url;
+  global_dc->m_get_option_url = get_option_url;
 
   if (atexit (lto_wrapper_cleanup) != 0)
     fatal_error (input_location, "%<atexit%> failed");
diff --git a/gcc/opts.cc b/gcc/opts.cc
index f54cf8305ca..32fdfc3e3ce 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -35,7 +35,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "version.h"
 #include "selftest.h"
 #include "file-prefix-map.h"
-#include "diagnostic-text-art.h"
 
 /* In this file all option sets are explicit.  */
 #undef OPTION_SET_P
@@ -2773,7 +2772,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_Werror:
-      dc->warning_as_error_requested = value;
+      dc->set_warning_as_error_requested (value);
       break;
 
     case OPT_Werror_:
@@ -2785,7 +2784,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_Wfatal_errors:
-      dc->fatal_errors = value;
+      dc->m_fatal_errors = value;
       break;
 
     case OPT_Wstack_usage_:
@@ -2803,7 +2802,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_Wsystem_headers:
-      dc->dc_warn_system_headers = value;
+      dc->m_warn_system_headers = value;
       break;
 
     case OPT_aux_info:
@@ -2893,46 +2892,45 @@ common_handle_option (struct gcc_options *opts,
 	}
 
     case OPT_fdiagnostics_text_art_charset_:
-      diagnostics_text_art_charset_init (dc,
-					 (enum diagnostic_text_art_charset)value);
+      dc->set_text_art_charset ((enum diagnostic_text_art_charset)value);
       break;
 
     case OPT_fdiagnostics_parseable_fixits:
-      dc->extra_output_kind = (value
-			       ? EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
-			       : EXTRA_DIAGNOSTIC_OUTPUT_none);
+      dc->set_extra_output_kind (value
+				 ? EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
+				 : EXTRA_DIAGNOSTIC_OUTPUT_none);
       break;
 
     case OPT_fdiagnostics_column_unit_:
-      dc->column_unit = (enum diagnostics_column_unit)value;
+      dc->m_column_unit = (enum diagnostics_column_unit)value;
       break;
 
     case OPT_fdiagnostics_column_origin_:
-      dc->column_origin = value;
+      dc->m_column_origin = value;
       break;
 
     case OPT_fdiagnostics_escape_format_:
-      dc->escape_format = (enum diagnostics_escape_format)value;
+      dc->set_escape_format ((enum diagnostics_escape_format)value);
       break;
 
     case OPT_fdiagnostics_show_cwe:
-      dc->show_cwe = value;
+      dc->set_show_cwe (value);
       break;
 
     case OPT_fdiagnostics_show_rules:
-      dc->show_rules = value;
+      dc->set_show_rules (value);
       break;
 
     case OPT_fdiagnostics_path_format_:
-      dc->path_format = (enum diagnostic_path_format)value;
+      dc->set_path_format ((enum diagnostic_path_format)value);
       break;
 
     case OPT_fdiagnostics_show_path_depths:
-      dc->show_path_depths = value;
+      dc->set_show_path_depths (value);
       break;
 
     case OPT_fdiagnostics_show_option:
-      dc->show_option_requested = value;
+      dc->set_show_option_requested (value);
       break;
 
     case OPT_fdiagnostics_minimum_margin_width_:
@@ -3071,7 +3069,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fshow_column:
-      dc->show_column = value;
+      dc->m_show_column = value;
       break;
 
     case OPT_frandom_seed:
@@ -3199,7 +3197,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_pedantic_errors:
-      dc->pedantic_errors = 1;
+      dc->m_pedantic_errors = 1;
       control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value,
 			      loc, lang_mask,
 			      handlers, opts, opts_set,
@@ -3220,11 +3218,11 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_w:
-      dc->dc_inhibit_warnings = true;
+      dc->m_inhibit_warnings = true;
       break;
 
     case OPT_fmax_errors_:
-      dc->max_errors = value;
+      dc->set_max_errors (value);
       break;
 
     case OPT_fuse_ld_bfd:
@@ -3284,11 +3282,11 @@ common_handle_option (struct gcc_options *opts,
     case OPT_ftabstop_:
       /* It is documented that we silently ignore silly values.  */
       if (value >= 1 && value <= 100)
-	dc->tabstop = value;
+	dc->m_tabstop = value;
       break;
 
     case OPT_freport_bug:
-      dc->report_bug = value;
+      dc->set_report_bug (value);
       break;
 
     case OPT_fmultiflags:
@@ -3636,7 +3634,7 @@ option_name (diagnostic_context *context, int option_index,
   /* A warning without option classified as an error.  */
   else if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN
 	    || diag_kind == DK_WARNING)
-	   && context->warning_as_error_requested)
+	   && context->warning_as_error_requested_p ())
     return xstrdup (cl_options[OPT_Werror].opt_text);
   else
     return NULL;
diff --git a/gcc/selftest-diagnostic.cc b/gcc/selftest-diagnostic.cc
index d632c51b2d9..37e98ed3304 100644
--- a/gcc/selftest-diagnostic.cc
+++ b/gcc/selftest-diagnostic.cc
@@ -38,7 +38,7 @@ test_diagnostic_context::test_diagnostic_context ()
   diagnostic_initialize (this, 0);
   m_source_printing.enabled = true;
   m_source_printing.show_labels_p = true;
-  show_column = true;
+  m_show_column = true;
   m_text_callbacks.start_span = start_span_cb;
   m_source_printing.min_margin_width = 6;
   m_source_printing.max_width = 80;
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c
index 0a4f25efe24..e8903ba6ee3 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c
@@ -225,7 +225,7 @@ plugin_init (struct plugin_name_args *plugin_info,
 
   diagnostic_starter (global_dc) = test_diagnostic_starter;
   global_dc->m_text_callbacks.start_span = test_diagnostic_start_span_fn;
-  global_dc->m_output_format = new test_output_format (*global_dc);
+  global_dc->set_output_format (new test_output_format (*global_dc));
 
   pass_info.pass = new pass_test_groups (g);
   pass_info.reference_pass_name = "*warn_function_noreturn";
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c
index 58b219bb0dc..e28d69758da 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c
@@ -23,7 +23,7 @@ static void
 emit_canvas (const canvas &c, const char *alt_text)
 {
   diagnostic_diagram diagram (c, alt_text);
-  diagnostic_emit_diagram (global_dc, diagram);
+  global_dc->emit_diagram (diagram);
 }
 
 static void
@@ -149,7 +149,7 @@ test_chessboard ()
 static void
 emit_table (const table &table, const style_manager &sm, const char *alt_text)
 {
-  const text_art::theme *theme = global_dc->m_diagrams.m_theme;
+  const text_art::theme *theme = global_dc->get_diagram_theme ();
   if (!theme)
     return;
   canvas c (table.to_canvas (*theme, sm));
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 9a734890a18..d098a7c72a0 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -714,7 +714,7 @@ init_asm_output (const char *name)
 		     "cannot open %qs for writing: %m", asm_file_name);
     }
 
-  if (!flag_syntax_only && !(global_dc->lang_mask & CL_LTODump))
+  if (!flag_syntax_only && !(global_dc->m_lang_mask & CL_LTODump))
     {
       targetm.asm_out.file_start ();
 
@@ -986,7 +986,7 @@ internal_error_reentered (diagnostic_context *, const char *, va_list *)
 static void
 internal_error_function (diagnostic_context *, const char *, va_list *)
 {
-  global_dc->internal_error = internal_error_reentered;
+  global_dc->m_internal_error = internal_error_reentered;
   warn_if_plugins ();
   emergency_dump_function ();
 }
@@ -1019,7 +1019,7 @@ general_init (const char *argv0, bool init_signals)
   /* Initialize the diagnostics reporting machinery, so option parsing
      can give warnings and errors.  */
   diagnostic_initialize (global_dc, N_OPTS);
-  global_dc->lang_mask = lang_hooks.option_lang_mask ();
+  global_dc->m_lang_mask = lang_hooks.option_lang_mask ();
   /* Set a default printer.  Language specific initializations will
      override it later.  */
   tree_diagnostics_defaults (global_dc);
@@ -1030,25 +1030,24 @@ general_init (const char *argv0, bool init_signals)
     = global_options_init.x_flag_diagnostics_show_labels;
   global_dc->m_source_printing.show_line_numbers_p
     = global_options_init.x_flag_diagnostics_show_line_numbers;
-  global_dc->show_cwe
-    = global_options_init.x_flag_diagnostics_show_cwe;
-  global_dc->show_rules
-    = global_options_init.x_flag_diagnostics_show_rules;
-  global_dc->path_format
-    = (enum diagnostic_path_format)global_options_init.x_flag_diagnostics_path_format;
-  global_dc->show_path_depths
-    = global_options_init.x_flag_diagnostics_show_path_depths;
-  global_dc->show_option_requested
-    = global_options_init.x_flag_diagnostics_show_option;
+  global_dc->set_show_cwe (global_options_init.x_flag_diagnostics_show_cwe);
+  global_dc->set_show_rules (global_options_init.x_flag_diagnostics_show_rules);
+  global_dc->set_path_format
+    ((enum diagnostic_path_format)
+     global_options_init.x_flag_diagnostics_path_format);
+  global_dc->set_show_path_depths
+    (global_options_init.x_flag_diagnostics_show_path_depths);
+  global_dc->set_show_option_requested
+    (global_options_init.x_flag_diagnostics_show_option);
   global_dc->m_source_printing.min_margin_width
     = global_options_init.x_diagnostics_minimum_margin_width;
-  global_dc->show_column
+  global_dc->m_show_column
     = global_options_init.x_flag_show_column;
-  global_dc->internal_error = internal_error_function;
-  global_dc->option_enabled = option_enabled;
-  global_dc->option_state = &global_options;
-  global_dc->option_name = option_name;
-  global_dc->get_option_url = get_option_url;
+  global_dc->m_internal_error = internal_error_function;
+  global_dc->m_option_enabled = option_enabled;
+  global_dc->m_option_state = &global_options;
+  global_dc->m_option_name = option_name;
+  global_dc->m_get_option_url = get_option_url;
 
   if (init_signals)
     {
@@ -1235,7 +1234,7 @@ process_options ()
   input_location = saved_location;
 
   if (flag_diagnostics_generate_patch)
-      global_dc->edit_context_ptr = new edit_context ();
+    global_dc->create_edit_context ();
 
   /* Avoid any informative notes in the second run of -fcompare-debug.  */
   if (flag_compare_debug) 
@@ -1664,13 +1663,11 @@ process_options ()
   if (!OPTION_SET_P (warnings_are_errors))
     {
       if (warn_coverage_mismatch
-	  && (global_dc->classify_diagnostic[OPT_Wcoverage_mismatch] ==
-	      DK_UNSPECIFIED))
+	  && option_unspecified_p (OPT_Wcoverage_mismatch))
 	diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_mismatch,
 					DK_ERROR, UNKNOWN_LOCATION);
       if (warn_coverage_invalid_linenum
-	  && (global_dc->classify_diagnostic[OPT_Wcoverage_invalid_line_number] ==
-	      DK_UNSPECIFIED))
+	  && option_unspecified_p (OPT_Wcoverage_invalid_line_number))
 	diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_invalid_line_number,
 					DK_ERROR, UNKNOWN_LOCATION);
     }
@@ -2303,11 +2300,12 @@ toplev::main (int argc, char **argv)
 
   if (flag_diagnostics_generate_patch)
     {
-      gcc_assert (global_dc->edit_context_ptr);
+      auto edit_context_ptr = global_dc->get_edit_context ();
+      gcc_assert (edit_context_ptr);
 
       pretty_printer pp;
       pp_show_color (&pp) = pp_show_color (global_dc->printer);
-      global_dc->edit_context_ptr->print_diff (&pp, true);
+      edit_context_ptr->print_diff (&pp, true);
       pp_flush (&pp);
     }
 
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 97ee0f04091..cd983bc20ff 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -205,7 +205,7 @@ struct event_range
 	expanded_location exploc
 	  = linemap_client_expand_location_to_spelling_point
 	  (initial_loc, LOCATION_ASPECT_CARET);
-	if (exploc.file != LOCATION_FILE (dc->last_location))
+	if (exploc.file != LOCATION_FILE (dc->m_last_location))
 	  dc->m_text_callbacks.start_span (dc, exploc);
       }
 
@@ -599,7 +599,7 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
 
   const unsigned num_events = path->num_events ();
 
-  switch (context->path_format)
+  switch (context->get_path_format ())
     {
     case DPF_NONE:
       /* Do nothing.  */
@@ -614,7 +614,7 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
 	    label_text event_text (event.get_desc (false));
 	    gcc_assert (event_text.get ());
 	    diagnostic_event_id_t event_id (i);
-	    if (context->show_path_depths)
+	    if (context->show_path_depths_p ())
 	      {
 		int stack_depth = event.get_stack_depth ();
 		tree fndecl = event.get_fndecl ();
@@ -646,7 +646,7 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
 	char *saved_prefix = pp_take_prefix (context->printer);
 	pp_set_prefix (context->printer, NULL);
 	print_path_summary_as_text (&summary, context,
-				    context->show_path_depths);
+				    context->show_path_depths_p ());
 	pp_flush (context->printer);
 	pp_set_prefix (context->printer, saved_prefix);
       }
diff --git a/gcc/tree-diagnostic.cc b/gcc/tree-diagnostic.cc
index cae400cf372..de853bc4fd7 100644
--- a/gcc/tree-diagnostic.cc
+++ b/gcc/tree-diagnostic.cc
@@ -374,9 +374,8 @@ tree_diagnostics_defaults (diagnostic_context *context)
   diagnostic_starter (context) = default_tree_diagnostic_starter;
   diagnostic_finalizer (context) = default_diagnostic_finalizer;
   diagnostic_format_decoder (context) = default_tree_printer;
-  context->print_path = default_tree_diagnostic_path_printer;
-  context->make_json_for_path = default_tree_make_json_for_path;
-  context->set_locations_cb = set_inlining_locations;
-  delete context->m_client_data_hooks;
-  context->m_client_data_hooks = make_compiler_data_hooks ();
+  context->m_print_path = default_tree_diagnostic_path_printer;
+  context->m_make_json_for_path = default_tree_make_json_for_path;
+  context->set_set_locations_callback (set_inlining_locations);
+  context->set_client_data_hooks (make_compiler_data_hooks ());
 }
