diff --git a/gdb/stack.c b/gdb/stack.c
index f7fd9433b5..1a66de16a5 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2733,6 +2733,9 @@ frame_apply_level_command (const char *cmd, int from_tty)
   const char *levels_str = cmd;
   number_or_range_parser levels (levels_str);
 
+  /* Changing this parsing logic probably implies to similarly update
+     frame_apply_level_command below.  */
+
   /* Skip the LEVEL list to find the flags and command args.  */
   while (!levels.finished ())
     {
@@ -2769,6 +2772,46 @@ frame_apply_level_command (const char *cmd, int from_tty)
     }
 }
 
+/* Skips the known arguments of frame apply level
+   and then invokes the usual command_completer.  */
+
+static void
+frame_apply_level_command_completer (struct cmd_list_element *cmd,
+				     completion_tracker &tracker,
+				     const char *text, const char *word)
+{
+  number_or_range_parser levels (text);
+  bool level_found = false;
+
+  while (!levels.finished ())
+    {
+      /* Call for effect.  */
+      levels.get_number ();
+
+      level_found = true;
+      if (levels.in_range ())
+	levels.skip_range ();
+    }
+
+  if (!level_found)
+    return;
+
+  text = levels.cur_tok ();
+
+  while (text != NULL)
+    {
+      qcs_flags dummy;
+
+      if (parse_flags_qcs ("frame apply level COMMAND completer",
+			   &text, &dummy))
+	continue;
+
+      break;
+    }
+
+  command_completer (cmd, tracker, text, word);
+}
+
 /* Implementation of the "frame apply all" command.  */
 
 static void
@@ -2781,6 +2824,28 @@ frame_apply_all_command (const char *cmd, int from_tty)
 			     get_current_frame (), INT_MAX);
 }
 
+/* Skips the known arguments of frame apply all
+   and then invokes the usual command_completer.  */
+
+static void
+frame_apply_all_command_completer (struct cmd_list_element *cmd,
+				   completion_tracker &tracker,
+				   const char *text, const char *word)
+{
+  while (text != NULL)
+    {
+      qcs_flags dummy;
+
+      if (parse_flags_qcs ("frame apply all COMMAND completer",
+			   &text, &dummy))
+	continue;
+
+      break;
+    }
+
+  command_completer (cmd, tracker, text, word);
+}
+
 /* Implementation of the "frame apply" command.  */
 
 static void
@@ -2810,6 +2875,31 @@ frame_apply_command (const char* cmd, int from_tty)
 			     trailing, count);
 }
 
+/* Skips the known arguments of frame apply COUNT
+   and then invokes the usual command_completer.  */
+
+static void
+frame_apply_command_completer (struct cmd_list_element *cmd,
+			       completion_tracker &tracker,
+			       const char *text, const char *word)
+{
+  if (get_number_trailer (&text, 0) == 0)
+    return;
+
+  while (text != NULL)
+    {
+      qcs_flags dummy;
+
+      if (parse_flags_qcs ("frame apply COUNT COMMAND completer",
+			   &text, &dummy))
+	continue;
+
+      break;
+    }
+
+  command_completer (cmd, tracker, text, word);
+}
+
 /* Implementation of the "faas" command.  */
 
 static void
@@ -2916,22 +3006,24 @@ Flag -c indicates to print the error and continue.\n\
 Flag -s indicates to silently ignore a COMMAND that raises an error\n\
 or produces no output."
 
-  add_prefix_cmd ("apply", class_stack, frame_apply_command,
+  cmd = add_prefix_cmd ("apply", class_stack, frame_apply_command,
 		  _("Apply a command to a number of frames.\n\
 Usage: frame apply COUNT [FLAG]... COMMAND\n\
 With a negative COUNT argument, applies the command on outermost -COUNT frames.\n"
 FRAME_APPLY_FLAGS_HELP),
 		  &frame_apply_cmd_list, "frame apply ", 1, &frame_cmd_list);
+  set_cmd_completer (cmd, frame_apply_command_completer);
 
-  add_cmd ("all", class_stack, frame_apply_all_command,
+  cmd = add_cmd ("all", class_stack, frame_apply_all_command,
 	   _("\
 Apply a command to all frames.\n\
 \n\
 Usage: frame apply all [FLAG]... COMMAND\n"
 FRAME_APPLY_FLAGS_HELP),
 	   &frame_apply_cmd_list);
+  set_cmd_completer (cmd, frame_apply_all_command_completer);
 
-  add_cmd ("level", class_stack, frame_apply_level_command,
+  cmd = add_cmd ("level", class_stack, frame_apply_level_command,
 	   _("\
 Apply a command to a list of frames.\n\
 \n\
@@ -2939,12 +3031,13 @@ Usage: frame apply level LEVEL... [FLAG]... COMMAND\n\
 ID is a space-separated list of LEVELs of frames to apply COMMAND on.\n"
 FRAME_APPLY_FLAGS_HELP),
 	   &frame_apply_cmd_list);
+  set_cmd_completer (cmd, frame_apply_level_command_completer);
 
-  add_com ("faas", class_stack, faas_command, _("\
+  cmd = add_com ("faas", class_stack, faas_command, _("\
 Apply a command to all frames (ignoring errors and empty output).\n\
 Usage: faas COMMAND\n\
 shortcut for 'frame apply all -s COMMAND'"));
-
+  set_cmd_completer (cmd, command_completer);
 
   add_prefix_cmd ("frame", class_stack,
 		  &frame_cmd.base_command, _("\
diff --git a/gdb/testsuite/gdb.base/frameapply.exp b/gdb/testsuite/gdb.base/frameapply.exp
index ccf30f2079..6b23d42143 100644
--- a/gdb/testsuite/gdb.base/frameapply.exp
+++ b/gdb/testsuite/gdb.base/frameapply.exp
@@ -18,6 +18,8 @@
 
 # Test 'frame apply [all | COUNT | -COUNT | level LEVEL...] [FLAG]... COMMAND'.
 
+load_lib completion-support.exp
+
 standard_testfile
 
 if { [prepare_for_testing "failed to prepare" ${testfile}] } {
@@ -36,6 +38,25 @@ set any "\[^\r\n\]*"
 set ws "\[ \t\]\+"
 set number "\[0-9]\+"
 
+# Check completion.
+test_gdb_complete_cmd_unique "frame apply al" "frame apply all"
+test_gdb_complete_cmd_unique "frame apply all info local" \
+    "frame apply all info locals"
+test_gdb_complete_cmd_unique "frame apply all -q info local" \
+    "frame apply all -q info locals"
+
+test_gdb_complete_cmd_unique "frame apply 3 info local" \
+    "frame apply 3 info locals"
+test_gdb_complete_cmd_unique "frame apply 3 -q info local" \
+    "frame apply 3 -q info locals"
+
+test_gdb_complete_cmd_unique "frame apply level 3 info local" \
+    "frame apply level 3 info locals"
+test_gdb_complete_cmd_unique "frame apply level 3 -q info local" \
+    "frame apply level 3 -q info locals"
+
+test_gdb_complete_cmd_unique "faas info local" "faas info locals"
+
 
 # Check all | COUNT | -COUNT | level LEVEL... with a simple command.
 with_test_prefix "simple command" {
