diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 18dedcc1fa..ebe2124652 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -153,7 +153,7 @@ extern int c_textual_element_type (struct type *, char);
    exception on failure.  This is suitable for use as the
    la_get_compile_instance language method.  */
 
-extern struct compile_instance *c_get_compile_context (void);
+extern compile_instance *c_get_compile_context (void);
 
 /* This takes the user-supplied text and returns a new bit of code to
    compile.
@@ -161,7 +161,7 @@ extern struct compile_instance *c_get_compile_context (void);
    This is used as the la_compute_program language method; see that
    for a description of the arguments.  */
 
-extern std::string c_compute_program (struct compile_instance *inst,
+extern std::string c_compute_program (compile_instance *inst,
 				      const char *input,
 				      struct gdbarch *gdbarch,
 				      const struct block *expr_block,
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index 41fead9ad1..d77c7d9625 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -96,7 +96,7 @@ load_libcc (void)
    This function calls the symbol returned from the load_libcc
    function.  This will provide the gcc_c_context.  */
 
-struct compile_instance *
+compile_instance *
 c_get_compile_context (void)
 {
   static gcc_c_fe_context_function *func;
@@ -114,7 +114,7 @@ c_get_compile_context (void)
     error (_("The loaded version of GCC does not support the required version "
 	     "of the API."));
 
-  return new_compile_instance (context);
+  return new compile_c_instance (context);
 }
 
 
@@ -334,13 +334,14 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
    indicates the value of $PC.  */
 
 std::string
-c_compute_program (struct compile_instance *inst,
+c_compute_program (compile_instance *inst,
 		   const char *input,
 		   struct gdbarch *gdbarch,
 		   const struct block *expr_block,
 		   CORE_ADDR expr_pc)
 {
-  struct compile_c_instance *context = (struct compile_c_instance *) inst;
+  compile_c_instance *context
+    = static_cast<compile_c_instance *> (inst);
 
   string_file buf;
   string_file var_stream;
@@ -350,7 +351,7 @@ c_compute_program (struct compile_instance *inst,
   /* Do not generate local variable information for "raw"
      compilations.  In this case we aren't emitting our own function
      and the user's code may only refer to globals.  */
-  if (inst->scope != COMPILE_I_RAW_SCOPE)
+  if (inst->scope () != COMPILE_I_RAW_SCOPE)
     {
       int i;
 
@@ -384,11 +385,11 @@ c_compute_program (struct compile_instance *inst,
       generate_register_struct (&buf, gdbarch, registers_used.get ());
     }
 
-  add_code_header (inst->scope, &buf);
+  add_code_header (inst->scope (), &buf);
 
-  if (inst->scope == COMPILE_I_SIMPLE_SCOPE
-      || inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
-      || inst->scope == COMPILE_I_PRINT_VALUE_SCOPE)
+  if (inst->scope () == COMPILE_I_SIMPLE_SCOPE
+      || inst->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE
+      || inst->scope () == COMPILE_I_PRINT_VALUE_SCOPE)
     {
       buf.write (var_stream.c_str (), var_stream.size ());
       buf.puts ("#pragma GCC user_expression\n");
@@ -398,12 +399,12 @@ c_compute_program (struct compile_instance *inst,
      works properly.  Otherwise gcc thinks that the "extern"
      declaration is in the same scope as the declaration provided by
      gdb.  */
-  if (inst->scope != COMPILE_I_RAW_SCOPE)
+  if (inst->scope () != COMPILE_I_RAW_SCOPE)
     buf.puts ("{\n");
 
   buf.puts ("#line 1 \"gdb command line\"\n");
 
-  switch (inst->scope)
+  switch (inst->scope ())
     {
     case COMPILE_I_PRINT_ADDRESS_SCOPE:
     case COMPILE_I_PRINT_VALUE_SCOPE:
@@ -413,7 +414,7 @@ c_compute_program (struct compile_instance *inst,
 "memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s" COMPILE_I_EXPR_VAL ",\n"
 	 "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
 			  , input, input,
-			  (inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
+			  (inst->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE
 			   ? "&" : ""));
       break;
     default:
@@ -428,9 +429,9 @@ c_compute_program (struct compile_instance *inst,
   if (strchr (input, '\n') == NULL)
     buf.puts (";\n");
 
-  if (inst->scope != COMPILE_I_RAW_SCOPE)
+  if (inst->scope () != COMPILE_I_RAW_SCOPE)
     buf.puts ("}\n");
 
-  add_code_footer (inst->scope, &buf);
+  add_code_footer (inst->scope (), &buf);
   return std::move (buf.string ());
 }
diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c
index abd829838b..7bc30a5b3d 100644
--- a/gdb/compile/compile-c-symbols.c
+++ b/gdb/compile/compile-c-symbols.c
@@ -79,16 +79,27 @@ del_symbol_error (void *a)
   xfree (se);
 }
 
-/* Associate SYMBOL with some error text.  */
+/* See compile-internal.h.  */
 
-static void
-insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text)
+void
+compile_instance::insert_symbol_error (const struct symbol *sym,
+				       const char *text)
 {
   struct symbol_error e;
   void **slot;
 
+  if (m_symbol_err_map == NULL)
+    {
+      m_symbol_err_map = htab_create_alloc (10,
+					    hash_symbol_error,
+					    eq_symbol_error,
+					    del_symbol_error,
+					    xcalloc,
+					    xfree);
+    }
+
   e.sym = sym;
-  slot = htab_find_slot (hash, &e, INSERT);
+  slot = htab_find_slot (m_symbol_err_map, &e, INSERT);
   if (*slot == NULL)
     {
       struct symbol_error *e = XNEW (struct symbol_error);
@@ -99,21 +110,19 @@ insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text)
     }
 }
 
-/* Emit the error message corresponding to SYM, if one exists, and
-   arrange for it not to be emitted again.  */
+/* See compile-internal.h.  */
 
-static void
-error_symbol_once (struct compile_c_instance *context,
-		   const struct symbol *sym)
+void
+compile_instance::error_symbol_once (const struct symbol *sym)
 {
   struct symbol_error search;
   struct symbol_error *err;
 
-  if (context->symbol_err_map == NULL)
+  if (m_symbol_err_map == NULL)
     return;
 
   search.sym = sym;
-  err = (struct symbol_error *) htab_find (context->symbol_err_map, &search);
+  err = (struct symbol_error *) htab_find (m_symbol_err_map, &search);
   if (err == NULL || err->message == NULL)
     return;
 
@@ -142,7 +151,7 @@ c_symbol_substitution_name (struct symbol *sym)
    scope.)  */
 
 static void
-convert_one_symbol (struct compile_c_instance *context,
+convert_one_symbol (compile_c_instance *context,
 		    struct block_symbol sym,
 		    int is_global,
 		    int is_local)
@@ -151,17 +160,17 @@ convert_one_symbol (struct compile_c_instance *context,
   const char *filename = symbol_symtab (sym.symbol)->filename;
   unsigned short line = SYMBOL_LINE (sym.symbol);
 
-  error_symbol_once (context, sym.symbol);
+  context->error_symbol_once (sym.symbol);
 
   if (SYMBOL_CLASS (sym.symbol) == LOC_LABEL)
     sym_type = 0;
   else
-    sym_type = convert_type (context, SYMBOL_TYPE (sym.symbol));
+    sym_type = context->convert_type (SYMBOL_TYPE (sym.symbol));
 
   if (SYMBOL_DOMAIN (sym.symbol) == STRUCT_DOMAIN)
     {
       /* Binding a tag, so we don't need to build a decl.  */
-      context->c_plugin->tagbind (SYMBOL_NATURAL_NAME (sym.symbol),
+      context->plugin ()->tagbind (SYMBOL_NATURAL_NAME (sym.symbol),
 				  sym_type, filename, line);
     }
   else
@@ -195,7 +204,7 @@ convert_one_symbol (struct compile_c_instance *context,
 	      /* Already handled by convert_enum.  */
 	      return;
 	    }
-	  context->c_plugin->build_constant
+	  context->plugin ()->build_constant
 	    (sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
 	     SYMBOL_VALUE (sym.symbol),
 	     filename, line);
@@ -280,17 +289,17 @@ convert_one_symbol (struct compile_c_instance *context,
 	}
 
       /* Don't emit local variable decls for a raw expression.  */
-      if (context->base.scope != COMPILE_I_RAW_SCOPE
+      if (context->scope () != COMPILE_I_RAW_SCOPE
 	  || symbol_name == NULL)
 	{
-	  decl = context->c_plugin->build_decl
+	  decl = context->plugin ()->build_decl
 	    (SYMBOL_NATURAL_NAME (sym.symbol),
 	     kind,
 	     sym_type,
 	     symbol_name.get (), addr,
 	     filename, line);
 
-	  context->c_plugin->bind (decl, is_global);
+	  context->plugin ()->bind (decl, is_global);
 	}
     }
 }
@@ -300,7 +309,7 @@ convert_one_symbol (struct compile_c_instance *context,
    itself, and DOMAIN is the domain which was searched.  */
 
 static void
-convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
+convert_symbol_sym (compile_c_instance *context, const char *identifier,
 		    struct block_symbol sym, domain_enum domain)
 {
   const struct block *static_block;
@@ -350,7 +359,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
    to use and BMSYM is the minimal symbol to convert.  */
 
 static void
-convert_symbol_bmsym (struct compile_c_instance *context,
+convert_symbol_bmsym (compile_c_instance *context,
 		      struct bound_minimal_symbol bmsym)
 {
   struct minimal_symbol *msym = bmsym.minsym;
@@ -398,11 +407,11 @@ convert_symbol_bmsym (struct compile_c_instance *context,
       break;
     }
 
-  sym_type = convert_type (context, type);
-  decl = context->c_plugin->build_decl (MSYMBOL_NATURAL_NAME (msym),
+  sym_type = context->convert_type (type);
+  decl = context->plugin ()->build_decl (MSYMBOL_NATURAL_NAME (msym),
 					kind, sym_type, NULL, addr,
 					NULL, 0);
-  context->c_plugin->bind (decl, 1 /* is_global */);
+  context->plugin ()->bind (decl, 1 /* is_global */);
 }
 
 /* See compile-internal.h.  */
@@ -413,7 +422,8 @@ gcc_convert_symbol (void *datum,
 		    enum gcc_c_oracle_request request,
 		    const char *identifier)
 {
-  struct compile_c_instance *context = (struct compile_c_instance *) datum;
+  compile_c_instance *context
+    = static_cast<compile_c_instance *> (datum);
   domain_enum domain;
   int found = 0;
 
@@ -438,7 +448,7 @@ gcc_convert_symbol (void *datum,
     {
       struct block_symbol sym;
 
-      sym = lookup_symbol (identifier, context->base.block, domain, NULL);
+      sym = lookup_symbol (identifier, context->block (), domain, NULL);
       if (sym.symbol != NULL)
 	{
 	  convert_symbol_sym (context, identifier, sym, domain);
@@ -459,7 +469,7 @@ gcc_convert_symbol (void *datum,
 
   CATCH (e, RETURN_MASK_ALL)
     {
-      context->c_plugin->error (e.message);
+      context->plugin ()->error (e.message);
     }
   END_CATCH
 
@@ -476,7 +486,8 @@ gcc_address
 gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
 		    const char *identifier)
 {
-  struct compile_c_instance *context = (struct compile_c_instance *) datum;
+  compile_c_instance *context
+    = static_cast<compile_c_instance *> (datum);
   gcc_address result = 0;
   int found = 0;
 
@@ -521,7 +532,7 @@ gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
 
   CATCH (e, RETURN_MASK_ERROR)
     {
-      context->c_plugin->error (e.message);
+      context->plugin ()->error (e.message);
     }
   END_CATCH
 
@@ -575,7 +586,7 @@ symbol_seen (htab_t hashtab, struct symbol *sym)
 /* Generate C code to compute the length of a VLA.  */
 
 static void
-generate_vla_size (struct compile_c_instance *compiler,
+generate_vla_size (compile_c_instance *compiler,
 		   string_file &stream,
 		   struct gdbarch *gdbarch,
 		   unsigned char *registers_used,
@@ -629,7 +640,7 @@ generate_vla_size (struct compile_c_instance *compiler,
 /* Generate C code to compute the address of SYM.  */
 
 static void
-generate_c_for_for_one_variable (struct compile_c_instance *compiler,
+generate_c_for_for_one_variable (compile_c_instance *compiler,
 				 string_file &stream,
 				 struct gdbarch *gdbarch,
 				 unsigned char *registers_used,
@@ -691,14 +702,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
 
   CATCH (e, RETURN_MASK_ERROR)
     {
-      if (compiler->symbol_err_map == NULL)
-	compiler->symbol_err_map = htab_create_alloc (10,
-						      hash_symbol_error,
-						      eq_symbol_error,
-						      del_symbol_error,
-						      xcalloc,
-						      xfree);
-      insert_symbol_error (compiler->symbol_err_map, sym, e.message);
+      compiler->insert_symbol_error (sym, e.message);
     }
   END_CATCH
 }
@@ -706,7 +710,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
 /* See compile-c.h.  */
 
 gdb::unique_xmalloc_ptr<unsigned char>
-generate_c_for_variable_locations (struct compile_c_instance *compiler,
+generate_c_for_variable_locations (compile_c_instance *compiler,
 				   string_file &stream,
 				   struct gdbarch *gdbarch,
 				   const struct block *block,
diff --git a/gdb/compile/compile-c-types.c b/gdb/compile/compile-c-types.c
index 927445208a..44b8317739 100644
--- a/gdb/compile/compile-c-types.c
+++ b/gdb/compile/compile-c-types.c
@@ -58,25 +58,31 @@ eq_type_map_instance (const void *a, const void *b)
   return insta->type == instb->type;
 }
 
+/* Constructor for compile_instance.  */
+
+compile_instance::compile_instance (struct gcc_base_context *gcc_fe,
+				    const char *options)
+  : m_gcc_fe (gcc_fe), m_gcc_target_options (options),
+    m_symbol_err_map (NULL)
+{
+  m_type_map = htab_create_alloc (10, hash_type_map_instance,
+				  eq_type_map_instance,
+				  xfree, xcalloc, xfree);
+}
+
 
 
-/* Insert an entry into the type map associated with CONTEXT that maps
-   from the gdb type TYPE to the gcc type GCC_TYPE.  It is ok for a
-   given type to be inserted more than once, provided that the exact
-   same association is made each time.  This simplifies how type
-   caching works elsewhere in this file -- see how struct type caching
-   is handled.  */
+/* See compile-internal.h.  */
 
-static void
-insert_type (struct compile_c_instance *context, struct type *type,
-	     gcc_type gcc_type)
+void
+compile_instance::insert_type (struct type *type, gcc_type gcc_type)
 {
   struct type_map_instance inst, *add;
   void **slot;
 
   inst.type = type;
   inst.gcc_type_handle = gcc_type;
-  slot = htab_find_slot (context->type_map, &inst, INSERT);
+  slot = htab_find_slot (m_type_map, &inst, INSERT);
 
   add = (struct type_map_instance *) *slot;
   /* The type might have already been inserted in order to handle
@@ -95,28 +101,28 @@ insert_type (struct compile_c_instance *context, struct type *type,
 /* Convert a pointer type to its gcc representation.  */
 
 static gcc_type
-convert_pointer (struct compile_c_instance *context, struct type *type)
+convert_pointer (compile_c_instance *context, struct type *type)
 {
-  gcc_type target = convert_type (context, TYPE_TARGET_TYPE (type));
+  gcc_type target = context->convert_type (TYPE_TARGET_TYPE (type));
 
-  return context->c_plugin->build_pointer_type (target);
+  return context->plugin ()->build_pointer_type (target);
 }
 
 /* Convert an array type to its gcc representation.  */
 
 static gcc_type
-convert_array (struct compile_c_instance *context, struct type *type)
+convert_array (compile_c_instance *context, struct type *type)
 {
   gcc_type element_type;
   struct type *range = TYPE_INDEX_TYPE (type);
 
-  element_type = convert_type (context, TYPE_TARGET_TYPE (type));
+  element_type = context->convert_type (TYPE_TARGET_TYPE (type));
 
   if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST)
-    return context->c_plugin->error (_("array type with non-constant"
+    return context->plugin ()->error (_("array type with non-constant"
 				       " lower bound is not supported"));
   if (TYPE_LOW_BOUND (range) != 0)
-    return context->c_plugin->error (_("cannot convert array type with "
+    return context->plugin ()->error (_("cannot convert array type with "
 				       "non-zero lower bound to C"));
 
   if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
@@ -125,12 +131,12 @@ convert_array (struct compile_c_instance *context, struct type *type)
       gcc_type result;
 
       if (TYPE_VECTOR (type))
-	return context->c_plugin->error (_("variably-sized vector type"
+	return context->plugin ()->error (_("variably-sized vector type"
 					   " is not supported"));
 
       std::string upper_bound
 	= c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high);
-      result = context->c_plugin->build_vla_array_type (element_type,
+      result = context->plugin ()->build_vla_array_type (element_type,
 							upper_bound.c_str ());
       return result;
     }
@@ -147,15 +153,15 @@ convert_array (struct compile_c_instance *context, struct type *type)
 	}
 
       if (TYPE_VECTOR (type))
-	return context->c_plugin->build_vector_type (element_type, count);
-      return context->c_plugin->build_array_type (element_type, count);
+	return context->plugin ()->build_vector_type (element_type, count);
+      return context->plugin ()->build_array_type (element_type, count);
     }
 }
 
 /* Convert a struct or union type to its gcc representation.  */
 
 static gcc_type
-convert_struct_or_union (struct compile_c_instance *context, struct type *type)
+convert_struct_or_union (compile_c_instance *context, struct type *type)
 {
   int i;
   gcc_type result;
@@ -163,54 +169,52 @@ convert_struct_or_union (struct compile_c_instance *context, struct type *type)
   /* First we create the resulting type and enter it into our hash
      table.  This lets recursive types work.  */
   if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
-    result = context->c_plugin->build_record_type ();
+    result = context->plugin ()->build_record_type ();
   else
     {
       gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
-      result = context->c_plugin->build_union_type ();
+      result = context->plugin ()->build_union_type ();
     }
-  insert_type (context, type, result);
+  context->insert_type (type, result);
 
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
     {
       gcc_type field_type;
       unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i);
 
-      field_type = convert_type (context, TYPE_FIELD_TYPE (type, i));
+      field_type = context->convert_type (TYPE_FIELD_TYPE (type, i));
       if (bitsize == 0)
 	bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
-      context->c_plugin->build_add_field (result,
+      context->plugin ()->build_add_field (result,
 					  TYPE_FIELD_NAME (type, i),
 					  field_type,
 					  bitsize,
 					  TYPE_FIELD_BITPOS (type, i));
     }
 
-  context->c_plugin->finish_record_or_union (result, TYPE_LENGTH (type));
+  context->plugin ()->finish_record_or_union (result, TYPE_LENGTH (type));
   return result;
 }
 
 /* Convert an enum type to its gcc representation.  */
 
 static gcc_type
-convert_enum (struct compile_c_instance *context, struct type *type)
+convert_enum (compile_c_instance *context, struct type *type)
 {
   gcc_type int_type, result;
   int i;
-  const gcc_c_plugin *plugin = context->c_plugin;
 
-  int_type = plugin->int_type_v0 (TYPE_UNSIGNED (type),
-					    TYPE_LENGTH (type));
+  int_type = context->plugin ()->int_type_v0 (TYPE_UNSIGNED (type),
+					      TYPE_LENGTH (type));
 
-  result = plugin->build_enum_type (int_type);
+  result = context->plugin ()->build_enum_type (int_type);
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
     {
-      plugin->build_add_enum_constant (result,
-				       TYPE_FIELD_NAME (type, i),
-				       TYPE_FIELD_ENUMVAL (type, i));
+      context->plugin ()->build_add_enum_constant
+	(result, TYPE_FIELD_NAME (type, i), TYPE_FIELD_ENUMVAL (type, i));
     }
 
-  plugin->finish_enum_type (result);
+  context->plugin ()->finish_enum_type (result);
 
   return result;
 }
@@ -218,7 +222,7 @@ convert_enum (struct compile_c_instance *context, struct type *type)
 /* Convert a function type to its gcc representation.  */
 
 static gcc_type
-convert_func (struct compile_c_instance *context, struct type *type)
+convert_func (compile_c_instance *context, struct type *type)
 {
   int i;
   gcc_type result, return_type;
@@ -243,14 +247,14 @@ convert_func (struct compile_c_instance *context, struct type *type)
 
   /* This approach means we can't make self-referential function
      types.  Those are impossible in C, though.  */
-  return_type = convert_type (context, target_type);
+  return_type = context->convert_type (target_type);
 
   array.n_elements = TYPE_NFIELDS (type);
   array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type));
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
-    array.elements[i] = convert_type (context, TYPE_FIELD_TYPE (type, i));
+    array.elements[i] = context->convert_type (TYPE_FIELD_TYPE (type, i));
 
-  result = context->c_plugin->build_function_type (return_type,
+  result = context->plugin ()->build_function_type (return_type,
 						   &array, is_varargs);
   xfree (array.elements);
 
@@ -260,62 +264,62 @@ convert_func (struct compile_c_instance *context, struct type *type)
 /* Convert an integer type to its gcc representation.  */
 
 static gcc_type
-convert_int (struct compile_c_instance *context, struct type *type)
+convert_int (compile_c_instance *context, struct type *type)
 {
-  if (context->c_plugin->version () >= GCC_C_FE_VERSION_1)
+  if (context->plugin ()->version () >= GCC_C_FE_VERSION_1)
     {
       if (TYPE_NOSIGN (type))
 	{
 	  gdb_assert (TYPE_LENGTH (type) == 1);
-	  return context->c_plugin->char_type ();
+	  return context->plugin ()->char_type ();
 	}
-      return context->c_plugin->int_type (TYPE_UNSIGNED (type),
-					  TYPE_LENGTH (type),
-					  TYPE_NAME (type));
+      return context->plugin ()->int_type (TYPE_UNSIGNED (type),
+					   TYPE_LENGTH (type),
+					   TYPE_NAME (type));
     }
   else
-    return context->c_plugin->int_type_v0 (TYPE_UNSIGNED (type),
-					   TYPE_LENGTH (type));
+    return context->plugin ()->int_type_v0 (TYPE_UNSIGNED (type),
+					    TYPE_LENGTH (type));
 }
 
 /* Convert a floating-point type to its gcc representation.  */
 
 static gcc_type
-convert_float (struct compile_c_instance *context, struct type *type)
+convert_float (compile_c_instance *context, struct type *type)
 {
-  if (context->c_plugin->version () >= GCC_C_FE_VERSION_1)
-    return context->c_plugin->float_type (TYPE_LENGTH (type),
-					  TYPE_NAME (type));
+  if (context->plugin ()->version () >= GCC_C_FE_VERSION_1)
+    return context->plugin ()->float_type (TYPE_LENGTH (type),
+					   TYPE_NAME (type));
   else
-    return context->c_plugin->float_type_v0 (TYPE_LENGTH (type));
+    return context->plugin ()->float_type_v0 (TYPE_LENGTH (type));
 }
 
 /* Convert the 'void' type to its gcc representation.  */
 
 static gcc_type
-convert_void (struct compile_c_instance *context, struct type *type)
+convert_void (compile_c_instance *context, struct type *type)
 {
-  return context->c_plugin->void_type ();
+  return context->plugin ()->void_type ();
 }
 
 /* Convert a boolean type to its gcc representation.  */
 
 static gcc_type
-convert_bool (struct compile_c_instance *context, struct type *type)
+convert_bool (compile_c_instance *context, struct type *type)
 {
-  return context->c_plugin->bool_type ();
+  return context->plugin ()->bool_type ();
 }
 
 /* Convert a qualified type to its gcc representation.  */
 
 static gcc_type
-convert_qualified (struct compile_c_instance *context, struct type *type)
+convert_qualified (compile_c_instance *context, struct type *type)
 {
   struct type *unqual = make_unqualified_type (type);
   gcc_type unqual_converted;
   gcc_qualifiers_flags quals = 0;
 
-  unqual_converted = convert_type (context, unqual);
+  unqual_converted = context->convert_type (unqual);
 
   if (TYPE_CONST (type))
     quals |= GCC_QUALIFIER_CONST;
@@ -324,17 +328,17 @@ convert_qualified (struct compile_c_instance *context, struct type *type)
   if (TYPE_RESTRICT (type))
     quals |= GCC_QUALIFIER_RESTRICT;
 
-  return context->c_plugin->build_qualified_type (unqual_converted, quals);
+  return context->plugin ()->build_qualified_type (unqual_converted, quals);
 }
 
 /* Convert a complex type to its gcc representation.  */
 
 static gcc_type
-convert_complex (struct compile_c_instance *context, struct type *type)
+convert_complex (compile_c_instance *context, struct type *type)
 {
-  gcc_type base = convert_type (context, TYPE_TARGET_TYPE (type));
+  gcc_type base = context->convert_type (TYPE_TARGET_TYPE (type));
 
-  return context->c_plugin->build_complex_type (base);
+  return context->plugin ()->build_complex_type (base);
 }
 
 /* A helper function which knows how to convert most types from their
@@ -343,7 +347,7 @@ convert_complex (struct compile_c_instance *context, struct type *type)
    returns the gcc type.  */
 
 static gcc_type
-convert_type_basic (struct compile_c_instance *context, struct type *type)
+convert_type_basic (compile_c_instance *context, struct type *type)
 {
   /* If we are converting a qualified type, first convert the
      unqualified type and then apply the qualifiers.  */
@@ -401,13 +405,22 @@ convert_type_basic (struct compile_c_instance *context, struct type *type)
       }
     }
 
-  return context->c_plugin->error (_("cannot convert gdb type to gcc type"));
+  return context->plugin ()->error (_("cannot convert gdb type to gcc type"));
 }
 
-/* See compile-internal.h.  */
+/* Default compile flags for C.  */
+
+const char *compile_c_instance::m_default_cflags = "-std=gnu11"
+  /* Otherwise the .o file may need
+     "_Unwind_Resume" and
+     "__gcc_personality_v0".  */
+  " -fno-exceptions"
+  " -Wno-implicit-function-declaration";
+
+/* See compile-c.h.  */
 
 gcc_type
-convert_type (struct compile_c_instance *context, struct type *type)
+compile_c_instance::convert_type (struct type *type)
 {
   struct type_map_instance inst, *found;
   gcc_type result;
@@ -417,59 +430,17 @@ convert_type (struct compile_c_instance *context, struct type *type)
   type = check_typedef (type);
 
   inst.type = type;
-  found = (struct type_map_instance *) htab_find (context->type_map, &inst);
+  found = (struct type_map_instance *) htab_find (m_type_map, &inst);
   if (found != NULL)
     return found->gcc_type_handle;
 
-  result = convert_type_basic (context, type);
-  insert_type (context, type, result);
+  result = convert_type_basic (this, type);
+  insert_type (type, result);
   return result;
 }
 
 
 
-/* Delete the compiler instance C.  */
-
-static void
-delete_instance (struct compile_instance *c)
-{
-  struct compile_c_instance *context = (struct compile_c_instance *) c;
-
-  context->base.fe->ops->destroy (context->base.fe);
-  delete context->c_plugin;
-  htab_delete (context->type_map);
-  if (context->symbol_err_map != NULL)
-    htab_delete (context->symbol_err_map);
-  xfree (context);
-}
-
-/* See compile-internal.h.  */
-
-struct compile_instance *
-new_compile_instance (struct gcc_c_context *fe)
-{
-  struct compile_c_instance *result = XCNEW (struct compile_c_instance);
-
-  result->base.fe = &fe->base;
-  result->base.destroy = delete_instance;
-  result->base.gcc_target_options = ("-std=gnu11"
-				     /* Otherwise the .o file may need
-					"_Unwind_Resume" and
-					"__gcc_personality_v0".  */
-				     " -fno-exceptions");
-
-  result->type_map = htab_create_alloc (10, hash_type_map_instance,
-					eq_type_map_instance,
-					xfree, xcalloc, xfree);
-
-  result->c_plugin = new gcc_c_plugin (fe);
-
-  result->c_plugin->set_callbacks (gcc_convert_symbol, gcc_symbol_address,
-				   result);
-
-  return &result->base;
-}
-
 /* C plug-in wrapper.  */
 
 #define FORWARD(OP,...) m_context->c_ops->OP(m_context, ##__VA_ARGS__)
diff --git a/gdb/compile/compile-c.h b/gdb/compile/compile-c.h
index ffa58021e2..2b80755d4e 100644
--- a/gdb/compile/compile-c.h
+++ b/gdb/compile/compile-c.h
@@ -36,20 +36,35 @@ extern gcc_c_symbol_address_function gcc_symbol_address;
 /* A subclass of compile_instance that is specific to the C front
    end.  */
 
-struct compile_c_instance
+class compile_c_instance : public compile_instance
 {
-  /* Base class.  Note that the base class vtable actually points to a
-     gcc_c_fe_vtable.  */
-  struct compile_instance base;
+public:
+  explicit compile_c_instance (struct gcc_c_context *gcc_c)
+    : compile_instance (&gcc_c->base, m_default_cflags),
+      m_plugin (gcc_c)
+  {
+    m_plugin.set_callbacks (gcc_convert_symbol, gcc_symbol_address, this);
+  }
 
-  /* Map from gdb types to gcc types.  */
-  htab_t type_map;
+  ~compile_c_instance ()
+  {
+    m_gcc_fe->ops->destroy (m_gcc_fe);
+  }
 
-  /* Map from gdb symbols to gcc error messages to emit.  */
-  htab_t symbol_err_map;
+  /* Convert a gdb type, TYPE, to a GCC type.
 
-  /* GCC C plugin.  */
-  gcc_c_plugin *c_plugin;
+     The new GCC type is returned.  */
+  gcc_type convert_type (struct type *type);
+
+  /* Return a handle for the GCC plug-in.  */
+  gcc_c_plugin *plugin () { return &m_plugin; }
+
+private:
+  /* Default compiler flags for C.  */
+  static const char *m_default_cflags;
+
+  /* The GCC plug-in.  */
+  gcc_c_plugin m_plugin;
 };
 
 /* Emit code to compute the address for all the local variables in
@@ -59,7 +74,7 @@ struct compile_c_instance
 
 extern gdb::unique_xmalloc_ptr<unsigned char>
   generate_c_for_variable_locations
-     (struct compile_c_instance *compiler,
+     (compile_c_instance *compiler,
       string_file &stream,
       struct gdbarch *gdbarch,
       const struct block *block,
diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h
index afe20e5141..8cfb214c02 100644
--- a/gdb/compile/compile-internal.h
+++ b/gdb/compile/compile-internal.h
@@ -28,28 +28,116 @@ struct block;
 /* An object of this type holds state associated with a given
    compilation job.  */
 
-struct compile_instance
+class compile_instance
 {
-  /* The GCC front end.  */
+public:
+  compile_instance (struct gcc_base_context *gcc_fe, const char *options);
+
+  virtual ~compile_instance ()
+  {
+    htab_delete (m_type_map);
+    if (m_symbol_err_map != NULL)
+      htab_delete (m_symbol_err_map);
+  }
+
+  /* Returns the GCC options to be passed during compilation.  */
+  const std::string &gcc_target_options () const
+  {
+    return m_gcc_target_options;
+  }
+
+  /* Insert GCC_TYPE into the type cache for TYPE.
+
+     It is ok for a given type to be inserted more than once, provided that
+     the exact same association is made each time.  */
+  void insert_type (struct type *type, gcc_type gcc_type);
+
+  /* Associate SYMBOL with some error text.  */
+  void insert_symbol_error (const struct symbol *sym, const char *text);
+
+  /* Emit the error message corresponding to SYM, if one exists, and
+     arrange for it not to be emitted again.  */
+  void error_symbol_once (const struct symbol *sym);
+
+  /* These currently just forward to the underlying ops
+     vtable.  */
+
+  /* Set the plug-in print callback.  */
+  void set_print_callback (void (*print_function) (void *, const char *),
+			   void *datum);
+
+  /* Return the plug-in's front-end version.  */
+  unsigned int version () const;
+
+  /* Set the plug-in's verbosity level.  Nop for GCC_FE_VERSION_0.  */
+  void set_verbose (int level);
+
+  /* Set the plug-in driver program.  Nop for GCC_FE_VERSION_0.  */
+  void set_driver_filename (const char *filename);
+
+  /* Set the regular expression used to match the configury triplet
+     prefix to the compiler.  Nop for GCC_FE_VERSION_0.  */
+  void set_triplet_regexp (const char *regexp);
+
+  /* Set compilation arguments.  REGEXP is only used for protocol
+     version GCC_FE_VERSION_0.  */
+  char *set_arguments (int argc, char **argv, const char *regexp = NULL);
+
+  /* Set the filename of the program to compile.  Nop for GCC_FE_VERSION_0.  */
+  void set_source_file (const char *filename);
+
+  /* Compile the previously specified source file to FILENAME.
+     VERBOSE_LEVEL is only used for protocol version GCC_FE_VERSION_0.  */
+  bool compile (const char *filename, int verbose_level = -1);
+
+  /* Set the scope type for this compile.  */
+  void set_scope (enum compile_i_scope_types scope)
+  {
+    m_scope = scope;
+  }
+
+  /* Return the scope type.  */
+  enum compile_i_scope_types scope () const
+  {
+    return m_scope;
+  }
+
+  /* Set the block to be used for symbol searches.  */
+  void set_block (const struct block *block)
+  {
+    m_block = block;
+  }
+
+  /* Return the search block.  */
+  const struct block *block () const
+  {
+    return m_block;
+  }
+
+protected:
+  /* Map types used by the compile instance for caching type conversions.
+     and error tracking.  */
+  typedef htab_t type_map_t;
+  typedef htab_t symbol_err_map_t;
 
-  struct gcc_base_context *fe;
+  /* The GCC front end.  */
+  struct gcc_base_context *m_gcc_fe;
 
   /* The "scope" of this compilation.  */
-
-  enum compile_i_scope_types scope;
+  enum compile_i_scope_types m_scope;
 
   /* The block in which an expression is being parsed.  */
-
-  const struct block *block;
+  const struct block *m_block;
 
   /* Specify "-std=gnu11", "-std=gnu++11" or similar.  These options are put
      after CU's DW_AT_producer compilation options to override them.  */
+  std::string m_gcc_target_options;
 
-  const char *gcc_target_options;
+  /* Map from gdb types to gcc types.  */
+  type_map_t m_type_map;
 
-  /* How to destroy this object.  */
-
-  void (*destroy) (struct compile_instance *);
+  /* Map from gdb symbols to gcc error messages to emit.  */
+  symbol_err_map_t m_symbol_err_map;
 };
 
 /* Define header and footers for different scopes.  */
@@ -79,18 +167,6 @@ extern std::string compile_register_name_mangled (struct gdbarch *gdbarch,
 extern int compile_register_name_demangle (struct gdbarch *gdbarch,
 					   const char *reg_name);
 
-/* Convert a gdb type, TYPE, to a GCC type.  CONTEXT is used to do the
-   actual conversion.  The new GCC type is returned.  */
-
-struct type;
-extern gcc_type convert_type (struct compile_c_instance *context,
-			      struct type *type);
-
-/* Instantiate a GDB object holding state for the GCC context FE.  The
-   new object is returned.  */
-
-extern struct compile_instance *new_compile_instance (struct gcc_c_context *fe);
-
 /* Type used to hold and pass around the source and object file names
    to use for compilation.  */
 class compile_file_names
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 7f35272872..c965f575fd 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -415,7 +415,7 @@ filter_args (int *argcp, char **argv)
    generated above.  */
 
 static void
-get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
+get_args (const compile_instance *compiler, struct gdbarch *gdbarch,
 	  int *argcp, char ***argvp)
 {
   const char *cs_producer_options;
@@ -437,7 +437,7 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
       freeargv (argv_producer);
     }
 
-  build_argc_argv (compiler->gcc_target_options,
+  build_argc_argv (compiler->gcc_target_options ().c_str (),
 		   &argc_compiler, &argv_compiler);
   append_args (argcp, argvp, argc_compiler, argv_compiler);
   freeargv (argv_compiler);
@@ -445,16 +445,6 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
   append_args (argcp, argvp, compile_args_argc, compile_args_argv);
 }
 
-/* A cleanup function to destroy a gdb_gcc_instance.  */
-
-static void
-cleanup_compile_instance (void *arg)
-{
-  struct compile_instance *inst = (struct compile_instance *) arg;
-
-  inst->destroy (inst);
-}
-
 /* A helper function suitable for use as the "print_callback" in the
    compiler object.  */
 
@@ -472,8 +462,6 @@ static compile_file_names
 compile_to_object (struct command_line *cmd, const char *cmd_string,
 		   enum compile_i_scope_types scope)
 {
-  struct compile_instance *compiler;
-  struct cleanup *cleanup;
   const struct block *expr_block;
   CORE_ADDR trash_pc, expr_pc;
   int argc;
@@ -481,7 +469,6 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
   int ok;
   struct gdbarch *gdbarch = get_current_arch ();
   std::string triplet_rx;
-  char *error_message;
 
   if (!target_has_execution)
     error (_("The program must be running for the compile command to "\
@@ -494,13 +481,13 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
   if (current_language->la_get_compile_instance == NULL)
     error (_("No compiler support for language %s."),
 	   current_language->la_name);
-  compiler = current_language->la_get_compile_instance ();
-  cleanup = make_cleanup (cleanup_compile_instance, compiler);
 
-  compiler->fe->ops->set_print_callback (compiler->fe, print_callback, NULL);
-
-  compiler->scope = scope;
-  compiler->block = expr_block;
+  compile_instance *compiler_instance
+    = current_language->la_get_compile_instance ();
+  std::unique_ptr<compile_instance> compiler (compiler_instance);
+  compiler->set_print_callback (print_callback, NULL);
+  compiler->set_scope (scope);
+  compiler->set_block (expr_block);
 
   /* From the provided expression, build a scope to pass to the
      compiler.  */
@@ -526,21 +513,20 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
     error (_("Neither a simple expression, or a multi-line specified."));
 
   std::string code
-    = current_language->la_compute_program (compiler, input, gdbarch,
+    = current_language->la_compute_program (compiler.get (), input, gdbarch,
 					    expr_block, expr_pc);
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ());
 
-  if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-    compiler->fe->ops->set_verbose (compiler->fe, compile_debug);
+  compiler->set_verbose (compile_debug);
 
   if (compile_gcc[0] != 0)
     {
-      if (compiler->fe->ops->version < GCC_FE_VERSION_1)
+      if (compiler->version () < GCC_FE_VERSION_1)
 	error (_("Command 'set compile-gcc' requires GCC version 6 or higher "
 		 "(libcc1 interface version 1 or higher)"));
 
-      compiler->fe->ops->set_driver_filename (compiler->fe, compile_gcc);
+      compiler->set_driver_filename (compile_gcc);
     }
   else
     {
@@ -549,27 +535,19 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 
       /* Allow triplets with or without vendor set.  */
       triplet_rx = std::string (arch_rx) + "(-[^-]*)?-" + os_rx;
-
-      if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-	compiler->fe->ops->set_triplet_regexp (compiler->fe,
-					       triplet_rx.c_str ());
+      compiler->set_triplet_regexp (triplet_rx.c_str ());
     }
 
   /* Set compiler command-line arguments.  */
-  get_args (compiler, gdbarch, &argc, &argv);
+  get_args (compiler.get (), gdbarch, &argc, &argv);
   gdb_argv argv_holder (argv);
 
-  if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-    error_message = compiler->fe->ops->set_arguments (compiler->fe, argc, argv);
-  else
-    error_message = compiler->fe->ops->set_arguments_v0 (compiler->fe,
-							 triplet_rx.c_str (),
-							 argc, argv);
+  gdb::unique_xmalloc_ptr<char> error_message;
+  error_message.reset (compiler->set_arguments (argc, argv,
+						triplet_rx.c_str ()));
+
   if (error_message != NULL)
-    {
-      make_cleanup (xfree, error_message);
-      error ("%s", error_message);
-    }
+    error ("%s", error_message.get ());
 
   if (compile_debug)
     {
@@ -601,13 +579,8 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 			fnames.source_file ());
 
   /* Call the compiler and start the compilation process.  */
-  compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ());
-
-  if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-    ok = compiler->fe->ops->compile (compiler->fe, fnames.object_file ());
-  else
-    ok = compiler->fe->ops->compile_v0 (compiler->fe, fnames.object_file (),
-					compile_debug);
+  compiler->set_source_file (fnames.source_file ());
+  ok = compiler->compile (fnames.object_file (), compile_debug);
   if (!ok)
     error (_("Compilation failed."));
 
@@ -617,9 +590,6 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 
   /* Keep the source file.  */
   source_remover->keep ();
-
-  do_cleanups (cleanup);
-
   return fnames;
 }
 
@@ -691,6 +661,87 @@ compile_register_name_demangle (struct gdbarch *gdbarch,
   error (_("Cannot find gdbarch register \"%s\"."), regname);
 }
 
+/* Forwards to the plug-in.  */
+
+#define FORWARD(OP,...) (m_gcc_fe->ops->OP (m_gcc_fe, ##__VA_ARGS__))
+
+/* See compile-internal.h.  */
+
+void
+compile_instance::set_print_callback
+  (void (*print_function) (void *, const char *), void *datum)
+{
+  FORWARD (set_print_callback, print_function, datum);
+}
+
+/* See compile-internal.h.  */
+
+unsigned int
+compile_instance::version () const
+{
+  return m_gcc_fe->ops->version;
+}
+
+/* See compile-internal.h.  */
+
+void
+compile_instance::set_verbose (int level)
+{
+  if (version () >= GCC_FE_VERSION_1)
+    FORWARD (set_verbose, level);
+}
+
+/* See compile-internal.h.  */
+
+void
+compile_instance::set_driver_filename (const char *filename)
+{
+  if (version () >= GCC_FE_VERSION_1)
+    FORWARD (set_driver_filename, filename);
+}
+
+/* See compile-internal.h.  */
+
+void
+compile_instance::set_triplet_regexp (const char *regexp)
+{
+  if (version () >= GCC_FE_VERSION_1)
+    FORWARD (set_triplet_regexp, regexp);
+}
+
+/* See compile-internal.h.  */
+
+char *
+compile_instance::set_arguments (int argc, char **argv, const char *regexp)
+{
+  if (version () >= GCC_FE_VERSION_1)
+    return FORWARD (set_arguments, argc, argv);
+  else
+    return FORWARD (set_arguments_v0, regexp, argc, argv);
+}
+
+/* See compile-internal.h.  */
+
+void
+compile_instance::set_source_file (const char *filename)
+{
+  FORWARD (set_source_file, filename);
+}
+
+/* See compile-internal.h.  */
+
+bool
+compile_instance::compile (const char *filename, int verbose_level)
+{
+  if (version () >= GCC_FE_VERSION_1)
+    return FORWARD (compile, filename);
+  else
+    return FORWARD (compile_v0, filename, verbose_level);
+}
+
+#undef FORWARD
+
+
 void
 _initialize_compile (void)
 {
diff --git a/gdb/language.h b/gdb/language.h
index 029de4a7ab..662519bafd 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -36,7 +36,7 @@ struct value_print_options;
 struct type_print_options;
 struct lang_varobj_ops;
 struct parser_state;
-struct compile_instance;
+class compile_instance;
 struct completion_match_for_lcd;
 
 #define MAX_FORTRAN_DIMS  7	/* Maximum number of F77 array dims.  */
@@ -426,7 +426,7 @@ struct language_defn
        instance is owned by its caller and must be deallocated by
        calling its 'destroy' method.  */
 
-    struct compile_instance *(*la_get_compile_instance) (void);
+    compile_instance *(*la_get_compile_instance) (void);
 
     /* This method must be defined if 'la_get_gcc_context' is defined.
        If 'la_get_gcc_context' is not defined, then this method is
@@ -442,7 +442,7 @@ struct language_defn
        parsed.
        EXPR_PC is the PC at which the expression is being parsed.  */
 
-    std::string (*la_compute_program) (struct compile_instance *inst,
+    std::string (*la_compute_program) (compile_instance *inst,
 				       const char *input,
 				       struct gdbarch *gdbarch,
 				       const struct block *expr_block,
