difficult to get at present without calling cc1 directly, as the
driver will usually give a generic error itself; they should be easier
to get once the driver is sharing the common option processing code.

If you're concerned about text size increase from adding a pointer to
the cl_option structure (of which there are about 900 constant
instances in GCC, depending on the target), note that this patch
series will end up replacing the flag_var pointer in that structure
with an offset that should certainly fit in a "short".  I think the
int-sized elements other than "flags" should also fit in "short" (or
in unsigned char in some cases), although I have no plans to work on
such text size reductions.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
commit (the non-C, non-exgettext parts of both this and
<http://gcc.gnu.org/ml/gcc-patches/2010-06/msg01968.html>)?

2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* common.opt (o): Add MissingArgError.
	* doc/options.texi (MissingArgError): Document.
	* hooks.c (hook_bool_constcharptr_size_t_false): Remove.
	* hooks.h (hook_bool_constcharptr_size_t_false): Remove.
	* langhooks-def.h (LANG_HOOKS_MISSING_ARGUMENT): Remove.
	(LANG_HOOKS_INITIALIZER): Remove missing_argument hook
	initializer.
	* langhooks.h (struct lang_hooks): Remove missing_argument.
	* optc-gen.awk: Handle MissingArgError and output new structure
	field initializers.
	* opts.c (read_cmdline_option): Use missing_argument_error field
	instead of missing_argument langhook.
	* opts.h (struct cl_option): Add missing_argument_error field.
	* system.h (LANG_HOOKS_MISSING_ARGUMENT): Poison.

c-family:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* c-common.h (c_common_missing_argument): Remove.
	* c-opts.c (c_common_missing_argument): Remove.
	* c.opt (A, D, F, I, MD, MMD, MQ, MT, U, fconstant-string-class=,
	idirafter, imacros, include, isysroot, isystem, iquote): Add
	MissingArgError.
	* c-objc-common.h (LANG_HOOKS_MISSING_ARGUMENT): Remove.

cp:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* cp-objcp-common.h (LANG_HOOKS_MISSING_ARGUMENT): Remove.

po:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* exgettext: Also extract MissingArgError texts from .opt files.

diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/c-family/c-common.h gcc-mainline/gcc/c-family/c-common.h
--- gcc-mainline-opt1/gcc/c-family/c-common.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/c-family/c-common.h	2010-06-21 14:38:50.000000000 -0700
@@ -653,7 +653,6 @@ extern tree handle_format_attribute (tre
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
 extern bool attribute_takes_identifier_p (const_tree);
 extern int c_common_handle_option (size_t code, const char *arg, int value, int kind);
-extern bool c_common_missing_argument (const char *opt, size_t code);
 extern tree c_common_type_for_mode (enum machine_mode, int);
 extern tree c_common_type_for_size (unsigned int, int);
 extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/c-family/c-opts.c gcc-mainline/gcc/c-family/c-opts.c
--- gcc-mainline-opt1/gcc/c-family/c-opts.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/c-family/c-opts.c	2010-06-21 14:53:58.000000000 -0700
@@ -135,59 +135,6 @@ static struct deferred_opt
 static const unsigned int 
 c_family_lang_mask = (CL_C | CL_CXX | CL_ObjC | CL_ObjCXX);
 
-/* Complain that switch CODE expects an argument but none was
-   provided.  OPT was the command-line option.  Return FALSE to get
-   the default message in opts.c, TRUE if we provide a specialized
-   one.  */
-bool
-c_common_missing_argument (const char *opt, size_t code)
-{
-  switch (code)
-    {
-    default:
-      /* Pick up the default message.  */
-      return false;
-
-    case OPT_fconstant_string_class_:
-      error ("no class name specified with %qs", opt);
-      break;
-
-    case OPT_A:
-      error ("assertion missing after %qs", opt);
-      break;
-
-    case OPT_D:
-    case OPT_U:
-      error ("macro name missing after %qs", opt);
-      break;
-
-    case OPT_F:
-    case OPT_I:
-    case OPT_idirafter:
-    case OPT_isysroot:
-    case OPT_isystem:
-    case OPT_iquote:
-      error ("missing path after %qs", opt);
-      break;
-
-    case OPT_MF:
-    case OPT_MD:
-    case OPT_MMD:
-    case OPT_include:
-    case OPT_imacros:
-    case OPT_o:
-      error ("missing filename after %qs", opt);
-      break;
-
-    case OPT_MQ:
-    case OPT_MT:
-      error ("missing makefile target after %qs", opt);
-      break;
-    }
-
-  return true;
-}
-
 /* Defer option CODE with argument ARG.  */
 static void
 defer_opt (enum opt_code code, const char *arg)
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/c-family/c.opt gcc-mainline/gcc/c-family/c.opt
--- gcc-mainline-opt1/gcc/c-family/c.opt	2010-06-21 05:03:53.000000000 -0700
+++ gcc-mainline/gcc/c-family/c.opt	2010-06-21 14:52:52.000000000 -0700
@@ -38,7 +38,7 @@ ObjC++
 C ObjC C++ ObjC++ Joined Separate
 
 A
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(assertion missing after %qs)
 -A<question>=<answer>	Assert the <answer> to <question>.  Putting '-' before <question> disables the <answer> to <question>
 
 C
@@ -50,14 +50,14 @@ C ObjC C++ ObjC++
 Do not discard comments in macro expansions
 
 D
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
 -D<macro>[=<val>]	Define a <macro> with <val> as its value.  If just <macro> is given, <val> is taken to be 1
 
 E
 C ObjC C++ ObjC++ Undocumented Var(flag_preprocess_only)
 
 F
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -F <dir>	Add <dir> to the end of the main framework include path
 
 H
@@ -65,7 +65,7 @@ C ObjC C++ ObjC++
 Print the name of header files as they are used
 
 I
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -I <dir>	Add <dir> to the end of the main include path
 
 M
@@ -73,11 +73,11 @@ C ObjC C++ ObjC++
 Generate make dependencies
 
 MD
-C ObjC C++ ObjC++ Separate
+C ObjC C++ ObjC++ Separate MissingArgError(missing filename after %qs)
 Generate make dependencies and compile
 
 MF
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
 -MF <file>	Write dependency output to the given file
 
 MG
@@ -89,7 +89,7 @@ C ObjC C++ ObjC++
 Like -M but ignore system header files
 
 MMD
-C ObjC C++ ObjC++ Separate
+C ObjC C++ ObjC++ Separate MissingArgError(missing filename after %qs)
 Like -MD but ignore system header files
 
 MP
@@ -97,11 +97,11 @@ C ObjC C++ ObjC++
 Generate phony targets for all headers
 
 MQ
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
 -MQ <target>	Add a MAKE-quoted target
 
 MT
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
 -MT <target>	Add an unquoted target
 
 P
@@ -109,7 +109,7 @@ C ObjC C++ ObjC++
 Do not generate #line directives
 
 U
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
 -U<macro>	Undefine <macro>
 
 Wabi
@@ -564,7 +564,7 @@ C++ ObjC++ Var(flag_conserve_space)
 Reduce the size of object files
 
 fconstant-string-class=
-ObjC ObjC++ Joined
+ObjC ObjC++ Joined MissingArgError(no class name specified with %qs)
 -fconst-string-class=<name>	Use class <name> for constant strings
 
 fdeduce-init-list
@@ -886,11 +886,11 @@ C ObjC C++ ObjC++ Joined
 -femit-struct-debug-detailed=<spec-list>	Detailed reduced debug info for structs
 
 idirafter
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -idirafter <dir>	Add <dir> to the end of the system include path
 
 imacros
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
 -imacros <file>	Accept definition of macros in <file>
 
 imultilib
@@ -898,7 +898,7 @@ C ObjC C++ ObjC++ Joined Separate
 -imultilib <dir>	Set <dir> to be the multilib include subdirectory
 
 include
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
 -include <file>	Include the contents of <file> before other files
 
 iprefix
@@ -906,15 +906,15 @@ C ObjC C++ ObjC++ Joined Separate
 -iprefix <path>	Specify <path> as a prefix for next two options
 
 isysroot
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -isysroot <dir>	Set <dir> to be the system root directory
 
 isystem
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -isystem <dir>	Add <dir> to the start of the system include path
 
 iquote
-C ObjC C++ ObjC++ Joined Separate
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -iquote <dir>	Add <dir> to the end of the quote include path
 
 iwithprefix
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/c-objc-common.h gcc-mainline/gcc/c-objc-common.h
--- gcc-mainline-opt1/gcc/c-objc-common.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/c-objc-common.h	2010-06-21 14:39:26.000000000 -0700
@@ -39,8 +39,6 @@ along with GCC; see the file COPYING3.  
 #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS c_initialize_diagnostics
 #undef LANG_HOOKS_HANDLE_OPTION
 #define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
-#undef LANG_HOOKS_MISSING_ARGUMENT
-#define LANG_HOOKS_MISSING_ARGUMENT c_common_missing_argument
 #undef LANG_HOOKS_POST_OPTIONS
 #define LANG_HOOKS_POST_OPTIONS c_common_post_options
 #undef LANG_HOOKS_GET_ALIAS_SET
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/common.opt gcc-mainline/gcc/common.opt
--- gcc-mainline-opt1/gcc/common.opt	2010-06-17 03:29:54.000000000 -0700
+++ gcc-mainline/gcc/common.opt	2010-06-21 14:53:19.000000000 -0700
@@ -1572,7 +1572,7 @@ Common Joined Var(plugindir_string) Init
 -iplugindir=<dir>	Set <dir> to be the default plugin directory
 
 o
-Common Joined Separate
+Common Joined Separate MissingArgError(missing filename after %qs)
 -o <file>	Place output into <file>
 
 p
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/cp/cp-objcp-common.h gcc-mainline/gcc/cp/cp-objcp-common.h
--- gcc-mainline-opt1/gcc/cp/cp-objcp-common.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/cp/cp-objcp-common.h	2010-06-21 14:38:40.000000000 -0700
@@ -53,8 +53,6 @@ extern bool cp_function_decl_explicit_p 
 #define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
 #undef LANG_HOOKS_HANDLE_FILENAME
 #define LANG_HOOKS_HANDLE_FILENAME c_common_handle_filename
-#undef LANG_HOOKS_MISSING_ARGUMENT
-#define LANG_HOOKS_MISSING_ARGUMENT c_common_missing_argument
 #undef LANG_HOOKS_POST_OPTIONS
 #define LANG_HOOKS_POST_OPTIONS c_common_post_options
 #undef LANG_HOOKS_GET_ALIAS_SET
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/doc/options.texi gcc-mainline/gcc/doc/options.texi
--- gcc-mainline-opt1/gcc/doc/options.texi	2009-12-30 09:03:08.000000000 -0800
+++ gcc-mainline/gcc/doc/options.texi	2010-06-21 15:40:50.000000000 -0700
@@ -1,4 +1,4 @@
-@c Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+@c Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
 @c Free Software Foundation, Inc.
 @c This is part of the GCC manual.
 @c For copying conditions, see the file gcc.texi.
@@ -135,6 +135,14 @@ it will be part of the same @code{argv} 
 
 This property cannot be used alongside @code{Joined} or @code{Separate}.
 
+@item MissingArgError(@var{message})
+For an option marked @code{Joined} or @code{Separate}, the message
+@var{message} will be used as an error message if the mandatory
+argument is missing; for options without @code{MissingArgError}, a
+generic error message is used.  @var{message} should contain a single
+@samp{%qs} format, which will be used to format the name of the option
+passed.
+
 @item UInteger
 The option's argument is a non-negative integer.  The option parser
 will check and convert the argument before passing it to the relevant
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/hooks.c gcc-mainline/gcc/hooks.c
--- gcc-mainline-opt1/gcc/hooks.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/hooks.c	2010-06-21 14:38:03.000000000 -0700
@@ -119,13 +119,6 @@ hook_bool_const_tree_hwi_hwi_const_tree_
 }
 
 bool
-hook_bool_constcharptr_size_t_false (const char *a ATTRIBUTE_UNUSED,
-				     size_t b ATTRIBUTE_UNUSED)
-{
-  return false;
-}
-
-bool
 hook_bool_size_t_constcharptr_int_true (size_t a ATTRIBUTE_UNUSED,
 					const char *b ATTRIBUTE_UNUSED,
 					int c ATTRIBUTE_UNUSED)
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/hooks.h gcc-mainline/gcc/hooks.h
--- gcc-mainline-opt1/gcc/hooks.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/hooks.h	2010-06-21 14:38:18.000000000 -0700
@@ -48,7 +48,6 @@ extern bool hook_bool_const_tree_hwi_hwi
 extern bool hook_bool_rtx_false (rtx);
 extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
 extern bool hook_bool_rtx_int_int_intp_bool_false (rtx, int, int, int *, bool);
-extern bool hook_bool_constcharptr_size_t_false (const char *, size_t);
 extern bool hook_bool_size_t_constcharptr_int_true (size_t, const char *, int);
 extern bool hook_bool_tree_tree_false (tree, tree);
 extern bool hook_bool_tree_tree_true (tree, tree);
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/langhooks-def.h gcc-mainline/gcc/langhooks-def.h
--- gcc-mainline-opt1/gcc/langhooks-def.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/langhooks-def.h	2010-06-21 14:39:18.000000000 -0700
@@ -90,7 +90,6 @@ extern void lhd_omp_firstprivatize_type_
 #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS lhd_initialize_diagnostics
 #define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lhd_complain_wrong_lang_p
 #define LANG_HOOKS_HANDLE_OPTION	hook_int_size_t_constcharptr_int_0
-#define LANG_HOOKS_MISSING_ARGUMENT	hook_bool_constcharptr_size_t_false
 #define LANG_HOOKS_POST_OPTIONS		lhd_post_options
 #define LANG_HOOKS_MISSING_NORETURN_OK_P hook_bool_tree_true
 #define LANG_HOOKS_GET_ALIAS_SET	lhd_get_alias_set
@@ -267,7 +266,6 @@ extern void lhd_end_section (void);
   LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \
   LANG_HOOKS_COMPLAIN_WRONG_LANG_P, \
   LANG_HOOKS_HANDLE_OPTION, \
-  LANG_HOOKS_MISSING_ARGUMENT, \
   LANG_HOOKS_POST_OPTIONS, \
   LANG_HOOKS_INIT, \
   LANG_HOOKS_FINISH, \
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/langhooks.h gcc-mainline/gcc/langhooks.h
--- gcc-mainline-opt1/gcc/langhooks.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/langhooks.h	2010-06-21 14:39:04.000000000 -0700
@@ -298,10 +298,6 @@ struct lang_hooks
      valid and should not be treated as language-independent too.  */
   int (*handle_option) (size_t code, const char *arg, int value, int kind);
 
-  /* Return false to use the default complaint about a missing
-     argument, otherwise output a complaint and return true.  */
-  bool (*missing_argument) (const char *opt, size_t code);
-
   /* Called when all command line options have been parsed to allow
      further processing and initialization
 
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/optc-gen.awk gcc-mainline/gcc/optc-gen.awk
--- gcc-mainline-opt1/gcc/optc-gen.awk	2010-06-11 07:58:21.000000000 -0700
+++ gcc-mainline/gcc/optc-gen.awk	2010-06-21 14:56:03.000000000 -0700
@@ -194,6 +194,12 @@ for (i = 0; i < n_opts; i++) {
 	else
 		hlp = quote help[i] quote;
 
+	missing_arg_error = opt_args("MissingArgError", flags[i])
+	if (missing_arg_error == "")
+		missing_arg_error = "0"
+	else
+		missing_arg_error = quote missing_arg_error quote
+
 	neg = opt_args("Negative", flags[i]);
 	if (neg != "")
 		idx = indices[neg]
@@ -209,8 +215,9 @@ for (i = 0; i < n_opts; i++) {
 	}
 	# Split the printf after %u to work around an ia64-hp-hpux11.23
 	# awk bug.
-	printf("  { %c-%s%c,\n    %s,\n    %s, %u,",
-	       quote, opts[i], quote, hlp, back_chain[i], len)
+	printf("  { %c-%s%c,\n    %s,\n    %s,\n    %s, %u,",
+	       quote, opts[i], quote, hlp, missing_arg_error,
+	       back_chain[i], len)
 	printf(" %d,\n", idx)
 	condition = opt_args("Condition", flags[i])
 	cl_flags = switch_flags(flags[i])
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/opts.c gcc-mainline/gcc/opts.c
--- gcc-mainline-opt1/gcc/opts.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/opts.c	2010-06-21 14:40:58.000000000 -0700
@@ -547,7 +547,9 @@ read_cmdline_option (struct cl_decoded_o
 
   if (decoded->errors & CL_ERR_MISSING_ARG)
     {
-      if (!lang_hooks.missing_argument (opt, decoded->opt_index))
+      if (option->missing_argument_error)
+	error (option->missing_argument_error, opt);
+      else
 	error ("missing argument to %qs", opt);
       return;
     }
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/opts.h gcc-mainline/gcc/opts.h
--- gcc-mainline-opt1/gcc/opts.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/opts.h	2010-06-21 15:24:55.000000000 -0700
@@ -44,6 +44,7 @@ struct cl_option
 {
   const char *opt_text;
   const char *help;
+  const char *missing_argument_error;
   unsigned short back_chain;
   unsigned char opt_len;
   int neg_index;
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/po/exgettext gcc-mainline/gcc/po/exgettext
--- gcc-mainline-opt1/gcc/po/exgettext	2010-06-07 02:48:58.000000000 -0700
+++ gcc-mainline/gcc/po/exgettext	2010-06-21 15:40:17.000000000 -0700
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Wrapper around gettext for programs using the msgid convention.
-# Copyright 1998, 2001, 2002, 2003, 2009 Free Software Foundation, Inc.
+# Copyright 1998, 2001, 2002, 2003, 2009, 2010 Free Software Foundation, Inc.
 
 # Written by Paul Eggert <eggert@twinsun.com>.
 # Revised by Zack Weinberg <zackw@stanford.edu> for no-POTFILES operation.
@@ -223,6 +223,13 @@ echo "scanning option files..." >&2
 	if (/^[ \t]*(;|$)/ || !/^[^ \t]/) {
 	    field = 0
 	} else {
+	    if ((field == 1) && /MissingArgError/) {
+		line = $0
+		sub(".*MissingArgError\\(", "", line)
+		sub("\\).*", "", line)
+		printf("#line %d \"%s\"\n", lineno, file)
+		printf("_(\"%s\")\n", line)
+	    }
 	    if (field == 2) {
 		line = $0
 		printf("#line %d \"%s\"\n", lineno, file)
diff -rupN --exclude=.svn gcc-mainline-opt1/gcc/system.h gcc-mainline/gcc/system.h
--- gcc-mainline-opt1/gcc/system.h	2010-06-16 09:07:33.000000000 -0700
+++ gcc-mainline/gcc/system.h	2010-06-21 15:27:06.000000000 -0700
@@ -778,7 +778,8 @@ extern void fancy_abort (const char *, i
 	LANG_HOOKS_PUSHLEVEL LANG_HOOKS_SET_BLOCK \
 	LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \
 	LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION \
-	TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN
+	TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN \
+	LANG_HOOKS_MISSING_ARGUMENT
 
 /* Miscellaneous macros that are no longer used.  */
  #pragma GCC poison USE_MAPPED_LOCATION
