diff mbox

[5/8] Change compile_instance/compile_c_instance into classes

Message ID 20180503184153.31183-6-keiths@redhat.com
State New
Headers show

Commit Message

Keith Seitz May 3, 2018, 6:41 p.m. UTC
This patch changes structs compile_instance and compile_c_instance into
classes.

Because of the nature of the change, there are a number of unavoidably
mechanical changes buried in here, such as turning variable access of the
POD struct into method calls, removing the struct keyword, and changing
access of the plugin from "c_plugin->operation()" to
"plugin ()->operation ()".

There is one "non-trivial" change associated with this patch, though.
The type cache and symbol error maps have been moved into the base class,
believing these facilities would be used other language implementations.
[They are indeed re-used by C++.]

gdb/ChangeLog:

	* compile/compile-c-support.c (c_get_compile_context): Use `new'
	instead of `new_compile_instance'.
	* compile/compile-c-symbols.c (compile_instance::insert_symbol_error):
	Update description.
	If the symbol error map is not initialized, create it.
	(generate_c_for_for_one_symbol): Do not check/initialize
	the symbol error map.
	* compile/compile-c-types.c (compile_c_instance): Make a class.
	Update all callers.
	(compile_instance::compile_instance): Initialize the type cache.
	(insert_type): Update description.
	(compile_c_instance::m_default_cflags): Define.
	(convert_type): Update description.
	(delete_instance): Moved to destructor.
	(new_compile_instance): Moved to constructor.
	* compile/compile-c.h (compile_c_instance): Make class inheriting
	from compile_instance.
	<base>: Remove field.
	<type_map, symbol_err_map>: Move to base class.
	<c_plugin>: Rename to `m_plugin' and remove pointer type.
	* compile/compile-internal.h (compile_instance): Make class.
	<type_map_t, symbol_err_map_t>: Define.
	<fe>: Rename to `m_gcc_fe'.
	<scope, block, gcc_target_options>: Add `m_' prefix.
	<m_type_map, m_symbol_err_map>: New fields, moved from
	compile_c_instance.
	<destroy>: Remove.
	(convert_type, new_compile_instance): Remove.
	* compile/compile.c (cleanup_compile_instance): Remove.
	(compile_to_object): Use unique_ptr to eliminate cleanups.
	(compile_instance::set_print_callback, compile_instance::version)
	(compile_instance::set_verbose)
	(compile_instance::set_driver_filename)
	(compile_instance::set_triplet_regexp)
	(compile_instance::set_arguments)
	(compile_instance::set_source_file)
	(compile_instance::compile): Define.
---
 gdb/c-lang.h                    |   4 +-
 gdb/compile/compile-c-support.c |  29 +++---
 gdb/compile/compile-c-symbols.c |  84 +++++++++--------
 gdb/compile/compile-c-types.c   | 197 +++++++++++++++++-----------------------
 gdb/compile/compile-c.h         |  37 +++++---
 gdb/compile/compile-internal.h  | 122 ++++++++++++++++++++-----
 gdb/compile/compile.c           | 153 ++++++++++++++++++++-----------
 gdb/language.h                  |   6 +-
 8 files changed, 375 insertions(+), 257 deletions(-)
diff mbox

Patch

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,