diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f3faf73..ad6da2d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,19 @@
 2017-09-30  Tom Tromey  <tom@tromey.com>
 
+	* event-top.c (stdin_event_handler): Update.
+	* main.c (captured_main_1): Update.
+	* top.h (make_delete_ui_cleanup): Remove.
+	(struct ui): Add constructor and destructor.
+	(new_ui, delete_ui): Remove.
+	* top.c (make_delete_ui_cleanup): Remove.
+	(new_ui_command): Use std::unique_ptr.
+	(delete_ui_cleanup): Remove.
+	(ui::ui): Rename from new_ui.  Update.
+	(free_ui): Remove.
+	(ui::~ui): Rename from delete_ui.  Update.
+
+2017-09-30  Tom Tromey  <tom@tromey.com>
+
 	* symfile.c (load_progress): Use gdb::byte_vector.
 
 2017-09-30  Tom Tromey  <tom@tromey.com>
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 54fe471..43e2a27 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -487,7 +487,7 @@ stdin_event_handler (int error, gdb_client_data client_data)
       else
 	{
 	  /* Simply delete the UI.  */
-	  delete_ui (ui);
+	  delete ui;
 	}
     }
   else
diff --git a/gdb/main.c b/gdb/main.c
index f174a24..79f14b7 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -528,7 +528,7 @@ captured_main_1 (struct captured_main_args *context)
   setvbuf (stderr, NULL, _IONBF, BUFSIZ);
 #endif
 
-  main_ui = new_ui (stdin, stdout, stderr);
+  main_ui = new ui (stdin, stdout, stderr);
   current_ui = main_ui;
 
   gdb_stdtargerr = gdb_stderr;	/* for moment */
diff --git a/gdb/top.c b/gdb/top.c
index 56117a3..7efc3d5 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -249,91 +249,62 @@ static int highest_ui_num;
 
 /* See top.h.  */
 
-struct ui *
-new_ui (FILE *instream, FILE *outstream, FILE *errstream)
+ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
+  : next (nullptr),
+    num (++highest_ui_num),
+    call_readline (nullptr),
+    input_handler (nullptr),
+    command_editing (0),
+    interp_info (nullptr),
+    async (0),
+    secondary_prompt_depth (0),
+    stdin_stream (instream_),
+    instream (instream_),
+    outstream (outstream_),
+    errstream (errstream_),
+    input_fd (fileno (instream)),
+    input_interactive_p (ISATTY (instream)),
+    prompt_state (PROMPT_NEEDED),
+    m_gdb_stdout (new stdio_file (outstream)),
+    m_gdb_stdin (new stdio_file (instream)),
+    m_gdb_stderr (new stderr_file (errstream)),
+    m_gdb_stdlog (m_gdb_stderr),
+    m_current_uiout (nullptr)
 {
-  struct ui *ui;
-
-  ui = XCNEW (struct ui);
-
-  ui->num = ++highest_ui_num;
-  ui->stdin_stream = instream;
-  ui->instream = instream;
-  ui->outstream = outstream;
-  ui->errstream = errstream;
-
-  ui->input_fd = fileno (ui->instream);
-
-  ui->input_interactive_p = ISATTY (ui->instream);
-
-  ui->m_gdb_stdin = new stdio_file (ui->instream);
-  ui->m_gdb_stdout = new stdio_file (ui->outstream);
-  ui->m_gdb_stderr = new stderr_file (ui->errstream);
-  ui->m_gdb_stdlog = ui->m_gdb_stderr;
-
-  ui->prompt_state = PROMPT_NEEDED;
+  buffer_init (&line_buffer);
 
   if (ui_list == NULL)
-    ui_list = ui;
+    ui_list = this;
   else
     {
       struct ui *last;
 
       for (last = ui_list; last->next != NULL; last = last->next)
 	;
-      last->next = ui;
+      last->next = this;
     }
-
-  return ui;
-}
-
-static void
-free_ui (struct ui *ui)
-{
-  delete ui->m_gdb_stdin;
-  delete ui->m_gdb_stdout;
-  delete ui->m_gdb_stderr;
-
-  xfree (ui);
 }
 
-void
-delete_ui (struct ui *todel)
+ui::~ui ()
 {
   struct ui *ui, *uiprev;
 
   uiprev = NULL;
 
   for (ui = ui_list; ui != NULL; uiprev = ui, ui = ui->next)
-    if (ui == todel)
+    if (ui == this)
       break;
 
   gdb_assert (ui != NULL);
 
   if (uiprev != NULL)
-    uiprev->next = ui->next;
+    uiprev->next = next;
   else
-    ui_list = ui->next;
-
-  free_ui (ui);
-}
-
-/* Cleanup that deletes a UI.  */
-
-static void
-delete_ui_cleanup (void *void_ui)
-{
-  struct ui *ui = (struct ui *) void_ui;
+    ui_list = next;
 
-  delete_ui (ui);
-}
-
-/* See top.h.  */
-
-struct cleanup *
-make_delete_ui_cleanup (struct ui *ui)
-{
-  return make_cleanup (delete_ui_cleanup, ui);
+  delete m_gdb_stdin;
+  delete m_gdb_stdout;
+  delete m_gdb_stderr;
 }
 
 /* Open file named NAME for read/write, making sure not to make it the
@@ -356,7 +327,6 @@ open_terminal_stream (const char *name)
 static void
 new_ui_command (const char *args, int from_tty)
 {
-  struct ui *ui;
   struct interp *interp;
   gdb_file_up stream[3];
   int i;
@@ -364,7 +334,6 @@ new_ui_command (const char *args, int from_tty)
   int argc;
   const char *interpreter_name;
   const char *tty_name;
-  struct cleanup *failure_chain;
 
   dont_repeat ();
 
@@ -385,12 +354,12 @@ new_ui_command (const char *args, int from_tty)
     for (i = 0; i < 3; i++)
       stream[i] = open_terminal_stream (tty_name);
 
-    ui = new_ui (stream[0].get (), stream[1].get (), stream[2].get ());
-    failure_chain = make_cleanup (delete_ui_cleanup, ui);
+    std::unique_ptr<ui> ui
+      (new struct ui (stream[0].get (), stream[1].get (), stream[2].get ()));
 
     ui->async = 1;
 
-    current_ui = ui;
+    current_ui = ui.get ();
 
     set_top_level_interpreter (interpreter_name);
 
@@ -401,7 +370,7 @@ new_ui_command (const char *args, int from_tty)
     stream[1].release ();
     stream[2].release ();
 
-    discard_cleanups (failure_chain);
+    ui.release ();
   }
 
   printf_unfiltered ("New UI allocated\n");
diff --git a/gdb/top.h b/gdb/top.h
index 6b66083..99ba010 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -54,6 +54,12 @@ enum prompt_state
 
 struct ui
 {
+  /* Create a new UI.  */
+  ui (FILE *instream, FILE *outstream, FILE *errstream);
+  ~ui ();
+
+  DISABLE_COPY_AND_ASSIGN (ui);
+
   /* Pointer to next in singly-linked list.  */
   struct ui *next;
 
@@ -203,13 +209,6 @@ public:
 #define ALL_UIS(UI)				\
   for (UI = ui_list; UI; UI = UI->next)		\
 
-/* Create a new UI.  */
-extern struct ui *new_ui (FILE *instream, FILE *outstream, FILE *errstream);
-extern void delete_ui (struct ui *todel);
-
-/* Cleanup that deletes a UI.  */
-extern struct cleanup *make_delete_ui_cleanup (struct ui *ui);
-
 /* Register the UI's input file descriptor in the event loop.  */
 extern void ui_register_input_event_handler (struct ui *ui);
 
