From patchwork Thu Aug 12 21:33:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 61646 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 8881FB70B8 for ; Fri, 13 Aug 2010 07:34:11 +1000 (EST) Received: (qmail 21323 invoked by alias); 12 Aug 2010 21:34:08 -0000 Received: (qmail 21263 invoked by uid 22791); 12 Aug 2010 21:33:57 -0000 X-SWARE-Spam-Status: No, hits=-0.3 required=5.0 tests=AWL, BAYES_50, TW_BG, TW_CP, TW_RG, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 12 Aug 2010 21:33:45 +0000 Received: (qmail 27192 invoked from network); 12 Aug 2010 21:33:42 -0000 Received: from unknown (HELO digraph.polyomino.org.uk) (joseph@127.0.0.2) by mail.codesourcery.com with ESMTPA; 12 Aug 2010 21:33:42 -0000 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.69) (envelope-from ) id 1OjfPB-000810-4G; Thu, 12 Aug 2010 21:33:41 +0000 Date: Thu, 12 Aug 2010 21:33:41 +0000 (UTC) From: "Joseph S. Myers" To: gcc-patches@gcc.gnu.org, fortran@gcc.gnu.org, java-patches@gcc.gnu.org Subject: Make driver process options with *.opt machinery Message-ID: MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch (relative to a tree with applied - that patch is pending review of the driver part) makes the compiler driver use the same option processing machinery as the core compilers, a necessary prerequisite for it to use the same option handlers as well in order that multilib selection can become based on feature settings computed the same way in the driver as in the compilers proper. This particular patch does not cause the option handlers to be shared; that will come later. What it does is mark options the driver needs to handle specially with Driver markings in the .opt files, adding entries for such options not previously in the .opt files. It would make sense for the driver to use the --help machinery from opts.c, but for now it stays with its own machinery and reporting of driver options by the opts.c machinery is disabled. (I have no current plans to work further on the --help side of things.) The common machinery is then used to handle the driver options, in place of a long chain of "if" statements; the callbacks for unknown options and wrong-language options are used to save options the driver doesn't handle itself for subsequent processing in specs. This patch replaces just the main option handling loop; I intend to move the decoding of options to an array earlier in future patches, so that stages such as lang_specific_driver also work on logical options, prune_options becomes part of the process of generating the array and translation of options becomes a general system for option aliases in .opt files. Bootstrapped with no regressions on x86_64-unknown-linux-gnu. OK to commit? 2010-08-12 Joseph Myers * common.opt: Add driver options. (auxbase, auxbase-strip, quiet, version): Mark RejectDriver. * doc/options.texi (Driver, RejectDriver): Document. * gcc.c (pass_exit_codes, print_search_dirs, print_file_name, print_prog_name, print_multi_directory, print_sysroot, print_multi_os_directory, print_multi_lib, print_sysroot_headers_suffix, report_times, combine_flag, use_pipes, wrapper_string): Remove. (save_switch, driver_unknown_option_callback, driver_wrong_lang_callback, driver_post_handling_callback, driver_handle_option): New. (spec_lang, last_language_n_infiles): Make file-scope static instead of local to process_command. (process_command): Use decode_cmdline_options_to_array and read_cmdline_option for option processing. Compute have_c in prescan of decoded options. * opt-functions.awk (switch_flags): Handle Driver and RejectDriver. (var_type, var_type_struct): Handle Separate options as generating const char * variables. * opts-common.c (decode_cmdline_option): Expect CL_COMMON and CL_TARGET to be passed by caller if required. (decode_cmdline_options_to_array): Update comment. * opts.c (complain_wrong_lang): Handle options only valid for the driver. (decode_options): Update call to decode_cmdline_options_to_array. (print_filtered_help): Ignore driver-only options. (print_specific_help): Ignore CL_DRIVER. (common_handle_option): Don't call print_specific_help for CL_DRIVER. * opts.h (CL_DRIVER, CL_REJECT_DRIVER): Define. (CL_PARAMS, CL_WARNING, CL_OPTIMIZATION, CL_TARGET, CL_COMMON): Update values. c-family: 2010-08-12 Joseph Myers * c.opt (MDX, MMDX, lang-asm): Mark RejectDriver. fortran: 2010-08-12 Joseph Myers * lang.opt (MDX, MMDX): Mark RejectDriver. java: 2010-08-12 Joseph Myers * lang.opt (MD_, MMD_, version): Mark RejectDriver. diff -rupN --exclude=.svn gcc-mainline-MD/gcc/c-family/c.opt gcc-mainline/gcc/c-family/c.opt --- gcc-mainline-MD/gcc/c-family/c.opt 2010-08-11 15:59:32.000000000 -0700 +++ gcc-mainline/gcc/c-family/c.opt 2010-08-12 02:48:01.000000000 -0700 @@ -73,7 +73,7 @@ C ObjC C++ ObjC++ Generate make dependencies MDX -C ObjC C++ ObjC++ Separate MissingArgError(missing filename after %qs) +C ObjC C++ ObjC++ RejectDriver Separate MissingArgError(missing filename after %qs) -MD Generate make dependencies and compile MF @@ -89,7 +89,7 @@ C ObjC C++ ObjC++ Like -M but ignore system header files MMDX -C ObjC C++ ObjC++ Separate MissingArgError(missing filename after %qs) +C ObjC C++ ObjC++ RejectDriver Separate MissingArgError(missing filename after %qs) -MMD Like -MD but ignore system header files MP @@ -926,7 +926,7 @@ C ObjC C++ ObjC++ Joined Separate -iwithprefixbefore Add to the end of the main include path lang-asm -C Undocumented +C Undocumented RejectDriver nostdinc C ObjC C++ ObjC++ diff -rupN --exclude=.svn gcc-mainline-MD/gcc/common.opt gcc-mainline/gcc/common.opt --- gcc-mainline-MD/gcc/common.opt 2010-08-11 15:25:33.000000000 -0700 +++ gcc-mainline/gcc/common.opt 2010-08-12 02:47:21.000000000 -0700 @@ -23,39 +23,51 @@ ; Please try to keep this file in ASCII collating order. +### +Driver + -help -Common +Common Driver Display this information -help= -Common Report Joined +Common Driver Report Joined --help= Display descriptions of a specific class of options. is one or more of optimizers, target, warnings, undocumented, params -target-help -Common +Common Driver Alias for --help=target ;; The following four entries are to work around the gcc driver ;; program's insatiable desire to turn options starting with a ;; double dash (--) into options starting with a dash f (-f). fhelp -Common Var(help_flag) +Common Driver Var(help_flag) fhelp= -Common Joined +Common Driver Joined ftarget-help -Common +Common Driver fversion -Common +Common Driver -param Common Separate --param = Set parameter to value. See below for a complete list of parameters +-sysroot= +Driver JoinedOrMissing + -version -Common +Common Driver + +B +Driver Joined Separate + +E +Driver O Common JoinedOrMissing Optimization @@ -69,10 +81,22 @@ Ofast Common Optimization Optimize for speed disregarding exact standards compliance +S +Driver + W Common RejectNegative Var(extra_warnings) Warning This switch is deprecated; use -Wextra instead +Wa, +Driver JoinedOrMissing + +Wl, +Driver JoinedOrMissing + +Wp, +Driver JoinedOrMissing + Waggregate-return Common Var(warn_aggregate_return) Warning Warn about returning structures, unions or arrays @@ -260,6 +284,15 @@ Wcoverage-mismatch Common Var(warn_coverage_mismatch) Init(1) Warning Warn in case profiles in -fprofile-use do not match +Xassembler +Driver Separate + +Xlinker +Driver Separate + +Xpreprocessor +Driver Separate + aux-info Common Separate -aux-info Emit declaration information into @@ -268,10 +301,16 @@ aux-info= Common Joined auxbase -Common Separate +Common Separate RejectDriver auxbase-strip -Common Separate +Common Separate RejectDriver + +combine +Driver Var(combine_flag) + +c +Driver d Common Joined @@ -285,6 +324,15 @@ dumpdir Common Separate -dumpdir Set the directory name to be used for dumps +dumpmachine +Driver + +dumpspecs +Driver + +dumpversion +Driver + ; The version of the C++ ABI in use. The following values are allowed: ; ; 0: The version of the ABI believed most conformant with the C++ ABI @@ -410,12 +458,16 @@ fcommon Common Report Var(flag_no_common,0) Optimization Do not put uninitialized globals in the common section +fcompare-debug +Driver +; Converted by the driver to -fcompare-debug= options. + fcompare-debug= -Common JoinedOrMissing RejectNegative Var(flag_compare_debug_opt) +Common Driver JoinedOrMissing RejectNegative Var(flag_compare_debug_opt) -fcompare-debug[=] Compile with and without e.g. -gtoggle, and compare the final-insns dump fcompare-debug-second -Common RejectNegative Var(flag_compare_debug) +Common Driver RejectNegative Var(flag_compare_debug) Run only the second compilation of -fcompare-debug fconserve-stack @@ -1587,14 +1639,23 @@ iplugindir= Common Joined Var(plugindir_string) Init(0) -iplugindir= Set to be the default plugin directory +l +Driver Joined Separate + +no-canonical-prefixes +Driver + o -Common Joined Separate MissingArgError(missing filename after %qs) +Common Driver Joined Separate MissingArgError(missing filename after %qs) -o Place output into p Common Var(profile_flag) Enable function profiling +pass-exit-codes +Driver Var(pass_exit_codes) + pedantic Common Var(pedantic) Issue warnings needed for strict compliance to the standard @@ -1603,22 +1664,92 @@ pedantic-errors Common Like -pedantic but issue them as errors +pipe +Driver Var(use_pipes) + +print-file-name= +Driver JoinedOrMissing Var(print_file_name) + +print-libgcc-file-name +Driver + +print-multi-directory +Driver Var(print_multi_directory) + +print-multi-lib +Driver Var(print_multi_lib) + +print-multi-os-directory +Driver Var(print_multi_os_directory) + +print-prog-name= +Driver JoinedOrMissing Var(print_prog_name) + +print-search-dirs +Driver Var(print_search_dirs) + +print-sysroot +Driver Var(print_sysroot) + +print-sysroot-headers-suffix +Driver Var(print_sysroot_headers_suffix) + quiet -Common Var(quiet_flag) +Common Var(quiet_flag) RejectDriver Do not display functions compiled or elapsed time +save-temps +Driver + +save-temps= +Driver Joined + +time +Driver Var(report_times) + +time= +Driver JoinedOrMissing + +v +Driver + version -Common Var(version_flag) +Common Var(version_flag) RejectDriver Display the compiler's version w Common Var(inhibit_warnings) Suppress warnings +wrapper +Driver Separate Var(wrapper_string) + +x +Driver Joined Separate + shared Common RejectNegative Negative(pie) Create a shared library +shared-libgcc +Driver + +specs +Driver Separate + +specs= +Driver Joined + +static-libgcc +Driver + +static-libgfortran +Driver +; Documented for Fortran, but always accepted by driver. + +static-libstdc++ +Driver + pie Common RejectNegative Negative(shared) Create a position independent executable diff -rupN --exclude=.svn gcc-mainline-MD/gcc/doc/options.texi gcc-mainline/gcc/doc/options.texi --- gcc-mainline-MD/gcc/doc/options.texi 2010-08-11 15:25:31.000000000 -0700 +++ gcc-mainline/gcc/doc/options.texi 2010-08-12 02:47:21.000000000 -0700 @@ -102,6 +102,10 @@ The option is available for all language @item Target The option is available for all languages but is target-specific. +@item Driver +The option is handled by the compiler driver using code not shared +with the compilers proper (@file{cc1} etc.). + @item @var{language} The option is available when compiling for the given language. @@ -109,6 +113,10 @@ It is possible to specify several differ option. Each @var{language} must have been declared by an earlier @code{Language} record. @xref{Option file format}. +@item RejectDriver +The option is only handled by the compilers proper (@file{cc1} etc.)@: +and should not be accepted by the driver. + @item RejectNegative The option does not have a ``no-'' form. All options beginning with ``f'', ``W'' or ``m'' are assumed to have a ``no-'' form unless this diff -rupN --exclude=.svn gcc-mainline-MD/gcc/fortran/lang.opt gcc-mainline/gcc/fortran/lang.opt --- gcc-mainline-MD/gcc/fortran/lang.opt 2010-08-11 16:00:04.000000000 -0700 +++ gcc-mainline/gcc/fortran/lang.opt 2010-08-12 02:48:14.000000000 -0700 @@ -61,7 +61,7 @@ Fortran ; Documented in C MDX -Fortran Separate +Fortran Separate RejectDriver ; Documented in C MF @@ -77,7 +77,7 @@ Fortran ; Documented in C MMDX -Fortran Separate +Fortran Separate RejectDriver ; Documented in C MP diff -rupN --exclude=.svn gcc-mainline-MD/gcc/gcc.c gcc-mainline/gcc/gcc.c --- gcc-mainline-MD/gcc/gcc.c 2010-08-11 16:00:28.000000000 -0700 +++ gcc-mainline/gcc/gcc.c 2010-08-12 09:49:05.000000000 -0700 @@ -140,44 +140,9 @@ int is_cpp_driver; /* Flag set to nonzero if an @file argument has been supplied to gcc. */ static bool at_file_supplied; -/* Flag saying to pass the greatest exit code returned by a sub-process - to the calling program. */ -static int pass_exit_codes; - /* Definition of string containing the arguments given to configure. */ #include "configargs.h" -/* Flag saying to print the directories gcc will search through looking for - programs, libraries, etc. */ - -static int print_search_dirs; - -/* Flag saying to print the full filename of this file - as found through our usual search mechanism. */ - -static const char *print_file_name = NULL; - -/* As print_file_name, but search for executable file. */ - -static const char *print_prog_name = NULL; - -/* Flag saying to print the relative path we'd use to - find libgcc.a given the current compiler flags. */ - -static int print_multi_directory; - -static int print_sysroot; - -/* Flag saying to print the relative path we'd use to - find OS libraries given the current compiler flags. */ - -static int print_multi_os_directory; - -/* Flag saying to print the list of subdirectories and - compiler flags used to select them in a standard form. */ - -static int print_multi_lib; - /* Flag saying to print the command line options understood by gcc and its sub-processes. */ @@ -187,11 +152,6 @@ static int print_help_list; static int print_version; -/* Flag saying to print the sysroot suffix used for searching for - headers. */ - -static int print_sysroot_headers_suffix; - /* Flag indicating whether we should print the command and arguments */ static int verbose_flag; @@ -207,11 +167,6 @@ static int verbose_only_flag; static int print_subprocess_help; -/* Flag indicating whether we should report subprocess execution times - (if this is supported by the system - see pexecute.c). */ - -static int report_times; - /* Whether we should report subprocess execution times to a file. */ FILE *report_times_to_file = NULL; @@ -250,15 +205,6 @@ static enum save_temps { static char *save_temps_prefix = 0; static size_t save_temps_length = 0; -/* Nonzero means pass multiple source files to the compiler at one time. */ - -static int combine_flag = 0; - -/* Nonzero means use pipes to communicate between subprocesses. - Overridden by either of the above two flags. */ - -static int use_pipes; - /* The compiler version. */ static const char *compiler_version; @@ -295,14 +241,6 @@ static struct obstack obstack; static struct obstack collect_obstack; -/* This is a list of a wrapper program and its arguments. - e.g. wrapper_string of "strace,-c" - will cause all programs to run as - strace -c program arguments - instead of just - program arguments */ -static const char *wrapper_string; - /* Forward declaration for prototypes. */ struct path_prefix; struct prefix_list; @@ -3506,6 +3444,448 @@ alloc_switch (void) } } +/* Save an option OPT with N_ARGS arguments in array ARGS, marking it + as validated if VALIDATED. */ + +static void +save_switch (const char *opt, size_t n_args, const char *const *args, + bool validated) +{ + alloc_switch (); + switches[n_switches].part1 = opt + 1; + if (n_args == 0) + switches[n_switches].args = 0; + else + { + switches[n_switches].args = XNEWVEC (const char *, n_args + 1); + memcpy (switches[n_switches].args, args, n_args * sizeof (const char *)); + switches[n_switches].args[n_args] = NULL; + } + + switches[n_switches].live_cond = 0; + switches[n_switches].validated = validated; + switches[n_switches].ordering = 0; + n_switches++; +} + +/* Handle an option DECODED that is unknown to the option-processing + machinery, but may be known to specs. */ + +static bool +driver_unknown_option_callback (const struct cl_decoded_option *decoded) +{ + save_switch (decoded->canonical_option[0], + decoded->canonical_option_num_elements - 1, + &decoded->canonical_option[1], false); + + return false; +} + +/* Handle an option DECODED that is not marked as CL_DRIVER. + LANG_MASK will always be CL_DRIVER. */ + +static void +driver_wrong_lang_callback (const struct cl_decoded_option *decoded, + unsigned int lang_mask ATTRIBUTE_UNUSED) +{ + /* At this point, non-driver options are accepted (and expected to + be passed down by specs) unless marked to be rejected by the + driver. Options to be rejected by the driver but accepted by the + compilers proper are treated just like completely unknown + options. */ + const struct cl_option *option = &cl_options[decoded->opt_index]; + + if (option->flags & CL_REJECT_DRIVER) + error ("unrecognized command line option %qs", + decoded->orig_option_with_args_text); + else + driver_unknown_option_callback (decoded); +} + +/* Note that an option (index OPT_INDEX, argument ARG, value VALUE) + has been successfully handled with a handler for mask MASK. */ + +static void +driver_post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED, + unsigned int mask ATTRIBUTE_UNUSED) +{ + /* Nothing to do here. */ +} + +static const char *spec_lang = 0; +static int last_language_n_infiles; + +/* Handle a driver option; arguments and return value as for + handle_option. */ + +static bool +driver_handle_option (const struct cl_decoded_option *decoded, + unsigned int lang_mask ATTRIBUTE_UNUSED, int kind, + const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) +{ + size_t opt_index = decoded->opt_index; + const char *arg = decoded->arg; + const char *compare_debug_replacement_opt; + int value = decoded->value; + bool validated = false; + bool do_save = true; + + gcc_assert (kind == DK_UNSPECIFIED); + + switch (opt_index) + { + case OPT_dumpspecs: + { + struct spec_list *sl; + init_spec (); + for (sl = specs; sl; sl = sl->next) + printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); + if (link_command_spec) + printf ("*link_command:\n%s\n\n", link_command_spec); + exit (0); + } + + case OPT_dumpversion: + printf ("%s\n", spec_version); + exit (0); + + case OPT_dumpmachine: + printf ("%s\n", spec_machine); + exit (0); + + case OPT_fversion: + /* translate_options () has turned --version into -fversion. */ + print_version = 1; + + /* CPP driver cannot obtain switch from cc1_options. */ + if (is_cpp_driver) + add_preprocessor_option ("--version", strlen ("--version")); + add_assembler_option ("--version", strlen ("--version")); + add_linker_option ("--version", strlen ("--version")); + break; + + case OPT_fhelp: + /* translate_options () has turned --help into -fhelp. */ + print_help_list = 1; + + /* CPP driver cannot obtain switch from cc1_options. */ + if (is_cpp_driver) + add_preprocessor_option ("--help", 6); + add_assembler_option ("--help", 6); + add_linker_option ("--help", 6); + break; + + case OPT_fhelp_: + /* translate_options () has turned --help into -fhelp. */ + print_subprocess_help = 2; + break; + + case OPT_ftarget_help: + /* translate_options() has turned --target-help into -ftarget-help. */ + print_subprocess_help = 1; + + /* CPP driver cannot obtain switch from cc1_options. */ + if (is_cpp_driver) + add_preprocessor_option ("--target-help", 13); + add_assembler_option ("--target-help", 13); + add_linker_option ("--target-help", 13); + break; + + case OPT_pass_exit_codes: + case OPT_print_search_dirs: + case OPT_print_file_name_: + case OPT_print_prog_name_: + case OPT_print_multi_lib: + case OPT_print_multi_directory: + case OPT_print_sysroot: + case OPT_print_multi_os_directory: + case OPT_print_sysroot_headers_suffix: + case OPT_time: + case OPT_wrapper: + /* These options set the variables specified in common.opt + automatically, and do not need to be saved for spec + processing. */ + do_save = false; + break; + + case OPT_print_libgcc_file_name: + print_file_name = "libgcc.a"; + do_save = false; + break; + + case OPT_fcompare_debug_second: + compare_debug_second = 1; + break; + + case OPT_fcompare_debug: + switch (value) + { + case 0: + compare_debug_replacement_opt = "-fcompare-debug="; + arg = ""; + goto compare_debug_with_arg; + + case 1: + compare_debug_replacement_opt = "-fcompare-debug=-gtoggle"; + arg = "-gtoggle"; + goto compare_debug_with_arg; + + default: + gcc_unreachable (); + } + break; + + case OPT_fcompare_debug_: + compare_debug_replacement_opt = decoded->canonical_option[0]; + compare_debug_with_arg: + gcc_assert (decoded->canonical_option_num_elements == 1); + gcc_assert (arg != NULL); + if (arg) + compare_debug = 1; + else + compare_debug = -1; + if (compare_debug < 0) + compare_debug_opt = NULL; + else + compare_debug_opt = arg; + save_switch (compare_debug_replacement_opt, 0, NULL, validated); + return true; + + case OPT_Wa_: + { + int prev, j; + /* Pass the rest of this option to the assembler. */ + + /* Split the argument at commas. */ + prev = 0; + for (j = 0; arg[j]; j++) + if (arg[j] == ',') + { + add_assembler_option (arg + prev, j - prev); + prev = j + 1; + } + + /* Record the part after the last comma. */ + add_assembler_option (arg + prev, j - prev); + } + do_save = false; + break; + + case OPT_Wp_: + { + int prev, j; + /* Pass the rest of this option to the preprocessor. */ + + /* Split the argument at commas. */ + prev = 0; + for (j = 0; arg[j]; j++) + if (arg[j] == ',') + { + add_preprocessor_option (arg + prev, j - prev); + prev = j + 1; + } + + /* Record the part after the last comma. */ + add_preprocessor_option (arg + prev, j - prev); + } + do_save = false; + break; + + case OPT_Wl_: + { + int prev, j; + /* Split the argument at commas. */ + prev = 0; + for (j = 0; arg[j]; j++) + if (arg[j] == ',') + { + add_infile (save_string (arg + prev, j - prev), "*"); + prev = j + 1; + } + /* Record the part after the last comma. */ + add_infile (arg + prev, "*"); + } + do_save = false; + break; + + case OPT_Xlinker: + add_infile (arg, "*"); + do_save = false; + break; + + case OPT_Xpreprocessor: + add_preprocessor_option (arg, strlen (arg)); + do_save = false; + break; + + case OPT_Xassembler: + add_assembler_option (arg, strlen (arg)); + do_save = false; + break; + + case OPT_l: + /* POSIX allows separation of -l and the lib arg; canonicalize + by concatenating -l with its arg */ + add_infile (concat ("-l", arg, NULL), "*"); + do_save = false; + break; + + case OPT_save_temps: + save_temps_flag = SAVE_TEMPS_CWD; + validated = true; + break; + + case OPT_save_temps_: + if (strcmp (arg, "cwd") == 0) + save_temps_flag = SAVE_TEMPS_CWD; + else if (strcmp (arg, "obj") == 0 + || strcmp (arg, "object") == 0) + save_temps_flag = SAVE_TEMPS_OBJ; + else + fatal_error ("%qs is an unknown -save-temps option", + decoded->orig_option_with_args_text); + break; + + case OPT_no_canonical_prefixes: + /* Already handled as a special case, so ignored here. */ + do_save = false; + break; + + case OPT_pipe: + validated = true; + /* Fall through. */ + case OPT_combine: + /* These options set the variables specified in common.opt + automatically, but do need to be saved for spec + processing. */ + break; + + case OPT_specs: + case OPT_specs_: + { + struct user_specs *user = XNEW (struct user_specs); + + user->next = (struct user_specs *) 0; + user->filename = arg; + if (user_specs_tail) + user_specs_tail->next = user; + else + user_specs_head = user; + user_specs_tail = user; + } + do_save = false; + break; + + case OPT__sysroot_: + target_system_root = arg; + target_system_root_changed = 1; + do_save = false; + break; + + case OPT_time_: + if (report_times_to_file) + fclose (report_times_to_file); + report_times_to_file = fopen (arg, "a"); + do_save = false; + break; + + case OPT____: + /* "-###" + This is similar to -v except that there is no execution + of the commands and the echoed arguments are quoted. It + is intended for use in shell scripts to capture the + driver-generated command line. */ + verbose_only_flag++; + verbose_flag++; + do_save = false; + break; + + case OPT_B: + { + size_t len = strlen (arg); + + /* Catch the case where the user has forgotten to append a + directory separator to the path. Note, they may be using + -B to add an executable name prefix, eg "i386-elf-", in + order to distinguish between multiple installations of + GCC in the same directory. Hence we must check to see + if appending a directory separator actually makes a + valid directory name. */ + if (!IS_DIR_SEPARATOR (arg[len - 1]) + && is_directory (arg, false)) + { + char *tmp = XNEWVEC (char, len + 2); + strcpy (tmp, arg); + tmp[len] = DIR_SEPARATOR; + tmp[++len] = 0; + arg = tmp; + } + + add_prefix (&exec_prefixes, arg, NULL, + PREFIX_PRIORITY_B_OPT, 0, 0); + add_prefix (&startfile_prefixes, arg, NULL, + PREFIX_PRIORITY_B_OPT, 0, 0); + add_prefix (&include_prefixes, arg, NULL, + PREFIX_PRIORITY_B_OPT, 0, 0); + } + validated = true; + break; + + case OPT_v: /* Print our subcommands and print versions. */ + verbose_flag++; + break; + + case OPT_x: + spec_lang = arg; + if (!strcmp (spec_lang, "none")) + /* Suppress the warning if -xnone comes after the last input + file, because alternate command interfaces like g++ might + find it useful to place -xnone after each input file. */ + spec_lang = 0; + else + last_language_n_infiles = n_infiles; + do_save = false; + break; + + case OPT_S: + case OPT_c: + case OPT_E: + /* have_c already set in a prescan above. */ + break; + + case OPT_o: + have_o = 1; +#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) + arg = convert_filename (arg, ! have_c, 0); +#endif + /* Save the output name in case -save-temps=obj was used. */ + save_temps_prefix = xstrdup (arg); + /* On some systems, ld cannot handle "-o" without a space. So + split the option from its argument. */ + save_switch ("-o", 1, &arg, validated); + return true; + + case OPT_static_libgcc: + case OPT_shared_libgcc: + case OPT_static_libgfortran: + case OPT_static_libstdc__: + /* These are always valid, since gcc.c itself understands the + first two, gfortranspec.c understands -static-libgfortran and + g++spec.c understands -static-libstdc++ */ + validated = true; + break; + + default: + gcc_unreachable (); + } + + if (do_save) + save_switch (decoded->canonical_option[0], + decoded->canonical_option_num_elements - 1, + &decoded->canonical_option[1], validated); + return true; +} + /* Create the vector `switches' and its contents. Store its length in `n_switches'. */ @@ -3515,11 +3895,12 @@ process_command (int argc, const char ** int i; const char *temp; char *temp1; - const char *spec_lang = 0; - int last_language_n_infiles; const char *tooldir_prefix; char *(*get_relative_prefix) (const char *, const char *, const char *) = NULL; + struct cl_option_handlers handlers; + struct cl_decoded_option *decoded_options; + unsigned int decoded_options_count, j; GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); @@ -3735,538 +4116,74 @@ process_command (int argc, const char ** last_language_n_infiles = -1; - for (i = 1; i < argc; i++) - { - const char *p = NULL; - int c = 0; - - if (argv[i][0] == '-' && argv[i][1] != 0) - { - p = &argv[i][1]; - c = *p; - } - - if (! strcmp (argv[i], "-dumpspecs")) - { - struct spec_list *sl; - init_spec (); - for (sl = specs; sl; sl = sl->next) - printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); - if (link_command_spec) - printf ("*link_command:\n%s\n\n", link_command_spec); - exit (0); - } - else if (! strcmp (argv[i], "-dumpversion")) - { - printf ("%s\n", spec_version); - exit (0); - } - else if (! strcmp (argv[i], "-dumpmachine")) - { - printf ("%s\n", spec_machine); - exit (0); - } - else if (strcmp (argv[i], "-fversion") == 0) - { - /* translate_options () has turned --version into -fversion. */ - print_version = 1; - - /* CPP driver cannot obtain switch from cc1_options. */ - if (is_cpp_driver) - add_preprocessor_option ("--version", strlen ("--version")); - add_assembler_option ("--version", strlen ("--version")); - add_linker_option ("--version", strlen ("--version")); - - goto normal_switch; - } - else if (strcmp (argv[i], "-fhelp") == 0) - { - /* translate_options () has turned --help into -fhelp. */ - print_help_list = 1; + decode_cmdline_options_to_array (argc, argv, CL_DRIVER, + &decoded_options, &decoded_options_count); - /* CPP driver cannot obtain switch from cc1_options. */ - if (is_cpp_driver) - add_preprocessor_option ("--help", 6); - add_assembler_option ("--help", 6); - add_linker_option ("--help", 6); - - goto normal_switch; - } - else if (strncmp (argv[i], "-fhelp=", 7) == 0) - { - /* translate_options () has turned --help into -fhelp. */ - print_subprocess_help = 2; - - goto normal_switch; - } - else if (strcmp (argv[i], "-ftarget-help") == 0) - { - /* translate_options() has turned --target-help into -ftarget-help. */ - print_subprocess_help = 1; - - /* CPP driver cannot obtain switch from cc1_options. */ - if (is_cpp_driver) - add_preprocessor_option ("--target-help", 13); - add_assembler_option ("--target-help", 13); - add_linker_option ("--target-help", 13); - - goto normal_switch; - } - else if (! strcmp (argv[i], "-pass-exit-codes")) - { - pass_exit_codes = 1; - } - else if (! strcmp (argv[i], "-print-search-dirs")) - print_search_dirs = 1; - else if (! strcmp (argv[i], "-print-libgcc-file-name")) - print_file_name = "libgcc.a"; - else if (! strncmp (argv[i], "-print-file-name=", 17)) - print_file_name = argv[i] + 17; - else if (! strncmp (argv[i], "-print-prog-name=", 17)) - print_prog_name = argv[i] + 17; - else if (! strcmp (argv[i], "-print-multi-lib")) - print_multi_lib = 1; - else if (! strcmp (argv[i], "-print-multi-directory")) - print_multi_directory = 1; - else if (! strcmp (argv[i], "-print-sysroot")) - print_sysroot = 1; - else if (! strcmp (argv[i], "-print-multi-os-directory")) - print_multi_os_directory = 1; - else if (! strcmp (argv[i], "-print-sysroot-headers-suffix")) - print_sysroot_headers_suffix = 1; - else if (! strcmp (argv[i], "-fcompare-debug-second")) - { - compare_debug_second = 1; - goto normal_switch; - } - else if (! strcmp (argv[i], "-fno-compare-debug")) - { - argv[i] = "-fcompare-debug="; - p = &argv[i][1]; - goto compare_debug_with_arg; - } - else if (! strcmp (argv[i], "-fcompare-debug")) - { - argv[i] = "-fcompare-debug=-gtoggle"; - p = &argv[i][1]; - goto compare_debug_with_arg; - } -#define OPT "-fcompare-debug=" - else if (! strncmp (argv[i], OPT, sizeof (OPT) - 1)) - { - const char *opt; - compare_debug_with_arg: - opt = argv[i] + sizeof (OPT) - 1; -#undef OPT - if (*opt) - compare_debug = 1; - else - compare_debug = -1; - if (compare_debug < 0) - compare_debug_opt = NULL; - else - compare_debug_opt = opt; - goto normal_switch; - } - else if (! strncmp (argv[i], "-Wa,", 4)) - { - int prev, j; - /* Pass the rest of this option to the assembler. */ - - /* Split the argument at commas. */ - prev = 4; - for (j = 4; argv[i][j]; j++) - if (argv[i][j] == ',') - { - add_assembler_option (argv[i] + prev, j - prev); - prev = j + 1; - } - - /* Record the part after the last comma. */ - add_assembler_option (argv[i] + prev, j - prev); - } - else if (! strncmp (argv[i], "-Wp,", 4)) - { - int prev, j; - /* Pass the rest of this option to the preprocessor. */ - - /* Split the argument at commas. */ - prev = 4; - for (j = 4; argv[i][j]; j++) - if (argv[i][j] == ',') - { - add_preprocessor_option (argv[i] + prev, j - prev); - prev = j + 1; - } - - /* Record the part after the last comma. */ - add_preprocessor_option (argv[i] + prev, j - prev); - } - else if (strncmp (argv[i], "-Wl,", 4) == 0) - { - int prev, j; - /* Split the argument at commas. */ - prev = 4; - for (j = 4; argv[i][j]; j++) - if (argv[i][j] == ',') - { - add_infile (save_string (argv[i] + prev, j - prev), "*"); - prev = j + 1; - } - /* Record the part after the last comma. */ - add_infile (argv[i] + prev, "*"); - } - else if (strcmp (argv[i], "-Xlinker") == 0) - { - if (i + 1 == argc) - fatal_error ("argument to %<-Xlinker%> is missing"); - - add_infile (argv[i+1], "*"); - i++; - } - else if (strcmp (argv[i], "-Xpreprocessor") == 0) - { - if (i + 1 == argc) - fatal_error ("argument to %<-Xpreprocessor%> is missing"); - - add_preprocessor_option (argv[i+1], strlen (argv[i+1])); - i++; - } - else if (strcmp (argv[i], "-Xassembler") == 0) - { - if (i + 1 == argc) - fatal_error ("argument to %<-Xassembler%> is missing"); - - add_assembler_option (argv[i+1], strlen (argv[i+1])); - i++; - } - else if (strcmp (argv[i], "-l") == 0) - { - if (i + 1 == argc) - fatal_error ("argument to %<-l%> is missing"); - - /* POSIX allows separation of -l and the lib arg; - canonicalize by concatenating -l with its arg */ - add_infile (concat ("-l", argv[i + 1], NULL), "*"); - i++; - } - else if (strncmp (argv[i], "-l", 2) == 0) - { - add_infile (argv[i], "*"); - } - else if (strcmp (argv[i], "-save-temps") == 0) - { - save_temps_flag = SAVE_TEMPS_CWD; - goto normal_switch; - } - else if (strncmp (argv[i], "-save-temps=", 12) == 0) - { - if (strcmp (argv[i]+12, "cwd") == 0) - save_temps_flag = SAVE_TEMPS_CWD; - else if (strcmp (argv[i]+12, "obj") == 0 - || strcmp (argv[i]+12, "object") == 0) - save_temps_flag = SAVE_TEMPS_OBJ; - else - fatal_error ("%qs is an unknown -save-temps option", argv[i]); - goto normal_switch; - } - else if (strcmp (argv[i], "-no-canonical-prefixes") == 0) - /* Already handled as a special case, so ignored here. */ - ; - else if (strcmp (argv[i], "-combine") == 0) - { - combine_flag = 1; - goto normal_switch; - } - else if (strcmp (argv[i], "-specs") == 0) - { - struct user_specs *user = XNEW (struct user_specs); - if (++i >= argc) - fatal_error ("argument to %<-specs%> is missing"); - - user->next = (struct user_specs *) 0; - user->filename = argv[i]; - if (user_specs_tail) - user_specs_tail->next = user; - else - user_specs_head = user; - user_specs_tail = user; - } - else if (strncmp (argv[i], "-specs=", 7) == 0) - { - struct user_specs *user = XNEW (struct user_specs); - if (strlen (argv[i]) == 7) - fatal_error ("argument to %<-specs=%> is missing"); - - user->next = (struct user_specs *) 0; - user->filename = argv[i] + 7; - if (user_specs_tail) - user_specs_tail->next = user; - else - user_specs_head = user; - user_specs_tail = user; - } - else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot="))) - { - target_system_root = argv[i] + strlen ("--sysroot="); - target_system_root_changed = 1; - } - else if (strcmp (argv[i], "-time") == 0) - report_times = 1; - else if (strncmp (argv[i], "-time=", sizeof ("-time=") - 1) == 0) - { - if (report_times_to_file) - fclose (report_times_to_file); - report_times_to_file = fopen (argv[i] + sizeof ("-time=") - 1, "a"); - } - else if (strcmp (argv[i], "-pipe") == 0) - { - /* -pipe has to go into the switches array as well as - setting a flag. */ - use_pipes = 1; - goto normal_switch; - } - else if (strcmp (argv[i], "-wrapper") == 0) - { - if (++i >= argc) - fatal_error ("argument to %<-wrapper%> is missing"); - - wrapper_string = argv[i]; - } - else if (strcmp (argv[i], "-###") == 0) - { - /* This is similar to -v except that there is no execution - of the commands and the echoed arguments are quoted. It - is intended for use in shell scripts to capture the - driver-generated command line. */ - verbose_only_flag++; - verbose_flag++; + handlers.unknown_option_callback = driver_unknown_option_callback; + handlers.wrong_lang_callback = driver_wrong_lang_callback; + handlers.post_handling_callback = driver_post_handling_callback; + handlers.num_handlers = 1; + handlers.handlers[0].handler = driver_handle_option; + handlers.handlers[0].mask = CL_DRIVER; + + for (j = 1; j < decoded_options_count; j++) + { + switch (decoded_options[j].opt_index) + { + case OPT_S: + case OPT_c: + case OPT_E: + have_c = 1; + break; } - else if (argv[i][0] == '-' && argv[i][1] != 0) - { - switch (c) - { - case 'B': - { - const char *value; - int len; - - if (p[1] == 0 && i + 1 == argc) - fatal_error ("argument to %<-B%> is missing"); - if (p[1] == 0) - value = argv[i + 1]; - else - value = p + 1; - - len = strlen (value); - - /* Catch the case where the user has forgotten to append a - directory separator to the path. Note, they may be using - -B to add an executable name prefix, eg "i386-elf-", in - order to distinguish between multiple installations of - GCC in the same directory. Hence we must check to see - if appending a directory separator actually makes a - valid directory name. */ - if (! IS_DIR_SEPARATOR (value [len - 1]) - && is_directory (value, false)) - { - char *tmp = XNEWVEC (char, len + 2); - strcpy (tmp, value); - tmp[len] = DIR_SEPARATOR; - tmp[++ len] = 0; - value = tmp; - } - - add_prefix (&exec_prefixes, value, NULL, - PREFIX_PRIORITY_B_OPT, 0, 0); - add_prefix (&startfile_prefixes, value, NULL, - PREFIX_PRIORITY_B_OPT, 0, 0); - add_prefix (&include_prefixes, value, NULL, - PREFIX_PRIORITY_B_OPT, 0, 0); - } - goto normal_switch; - - case 'v': /* Print our subcommands and print versions. */ - /* If they do anything other than exactly `-v', don't set - verbose_flag; rather, continue on to give the error. */ - if (p[1] != 0) - break; - verbose_flag++; - goto normal_switch; - - case 'x': - if (p[1] == 0 && i + 1 == argc) - fatal_error ("argument to %<-x%> is missing"); - if (p[1] == 0) - spec_lang = argv[++i]; - else - spec_lang = p + 1; - if (! strcmp (spec_lang, "none")) - /* Suppress the warning if -xnone comes after the last input - file, because alternate command interfaces like g++ might - find it useful to place -xnone after each input file. */ - spec_lang = 0; - else - last_language_n_infiles = n_infiles; - break; - - case 'S': - case 'c': - case 'E': - if (p[1] == 0) - have_c = 1; - goto normal_switch; - - case 'o': - have_o = 1; -#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) - if (! have_c) - { - int skip; - - /* Forward scan, just in case -S, -E or -c is specified - after -o. */ - int j = i + 1; - if (p[1] == 0) - ++j; - while (j < argc) - { - if (argv[j][0] == '-') - { - if (SWITCH_CURTAILS_COMPILATION (argv[j][1]) - && argv[j][2] == 0) - { - have_c = 1; - break; - } - else if ((skip = SWITCH_TAKES_ARG (argv[j][1]))) - j += skip - (argv[j][2] != 0); - else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))) - j += skip; - } - j++; - } - } -#endif -#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) - if (p[1] == 0) - argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0); - else - { - argv[i] = convert_filename (argv[i], ! have_c, 0); - p = &argv[i][1]; - } -#endif - /* Save the output name in case -save-temps=obj was used. */ - if ((p[1] == 0) && argv[i + 1]) - save_temps_prefix = xstrdup(argv[i + 1]); - else - save_temps_prefix = xstrdup(argv[i] + 1); - goto normal_switch; - - default: - normal_switch: - - alloc_switch (); - switches[n_switches].part1 = p; - /* Deal with option arguments in separate argv elements. */ - if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) - || WORD_SWITCH_TAKES_ARG (p)) - { - int j = 0; - int n_args = WORD_SWITCH_TAKES_ARG (p); - - if (n_args == 0) - { - /* Count only the option arguments in separate - argv elements. */ - n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); - } - if (i + n_args >= argc) - fatal_error ("argument to %<-%s%> is missing", p); - switches[n_switches].args - = XNEWVEC (const char *, n_args + 1); - while (j < n_args) - switches[n_switches].args[j++] = argv[++i]; - /* Null-terminate the vector. */ - switches[n_switches].args[j] = 0; - } - else if (c == 'o') - { - /* On some systems, ld cannot handle "-o" without - a space. So split the option from its argument. */ - char *part1 = XNEWVEC (char, 2); - part1[0] = c; - part1[1] = '\0'; - - switches[n_switches].part1 = part1; - switches[n_switches].args = XNEWVEC (const char *, 2); - switches[n_switches].args[0] = xstrdup (p+1); - switches[n_switches].args[1] = 0; - } - else - switches[n_switches].args = 0; + if (have_c) + break; + } - switches[n_switches].live_cond = 0; - switches[n_switches].validated = 0; - switches[n_switches].ordering = 0; - /* These are always valid, since gcc.c itself understands the - first four, gfortranspec.c understands -static-libgfortran - and g++spec.c understands -static-libstdc++ */ - if (!strcmp (p, "save-temps") - || !strcmp (p, "static-libgcc") - || !strcmp (p, "shared-libgcc") - || !strcmp (p, "pipe") - || !strcmp (p, "static-libgfortran") - || !strcmp (p, "static-libstdc++")) - switches[n_switches].validated = 1; - else - { - char ch = switches[n_switches].part1[0]; - if (ch == 'B') - switches[n_switches].validated = 1; - } - n_switches++; - } - } - else + for (j = 1; j < decoded_options_count; j++) + { + if (decoded_options[j].opt_index == OPT_SPECIAL_input_file) { - const char *p = strrchr (argv[i], '@'); + const char *arg = decoded_options[j].arg; + const char *p = strrchr (arg, '@'); char *fname; long offset; int consumed; #ifdef HAVE_TARGET_OBJECT_SUFFIX - argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK)); + arg = convert_filename (arg, 0, access (arg, F_OK)); #endif /* For LTO static archive support we handle input file specifications that are composed of a filename and an offset like FNAME@OFFSET. */ if (p - && p != argv[i] + && p != arg && sscanf (p, "@%li%n", &offset, &consumed) >= 1 && strlen (p) == (unsigned int)consumed) { - fname = (char *)xmalloc (p - argv[i] + 1); - memcpy (fname, argv[i], p - argv[i]); - fname[p - argv[i]] = '\0'; + fname = (char *)xmalloc (p - arg + 1); + memcpy (fname, arg, p - arg); + fname[p - arg] = '\0'; /* Only accept non-stdin and existing FNAME parts, otherwise try with the full name. */ if (strcmp (fname, "-") == 0 || access (fname, F_OK) < 0) { free (fname); - fname = xstrdup (argv[i]); + fname = xstrdup (arg); } } else - fname = xstrdup (argv[i]); + fname = xstrdup (arg); if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0) perror_with_name (fname); else - add_infile (argv[i], spec_lang); + add_infile (arg, spec_lang); free (fname); + continue; } + + read_cmdline_option (decoded_options + j, CL_DRIVER, &handlers); } /* If -save-temps=obj and -o name, create the prefix to use for %b. diff -rupN --exclude=.svn gcc-mainline-MD/gcc/java/lang.opt gcc-mainline/gcc/java/lang.opt --- gcc-mainline-MD/gcc/java/lang.opt 2010-08-11 15:25:31.000000000 -0700 +++ gcc-mainline/gcc/java/lang.opt 2010-08-12 02:47:21.000000000 -0700 @@ -33,7 +33,7 @@ Java ; Documented for C MD_ -Java Undocumented +Java Undocumented RejectDriver ; Documented for C MF @@ -45,7 +45,7 @@ Java ; Documented for C MMD_ -Java Undocumented +Java Undocumented RejectDriver ; Documented for C MP @@ -209,7 +209,7 @@ Java Joined Set the target VM version version -Java +Java RejectDriver ; ; Warnings handled by ecj. diff -rupN --exclude=.svn gcc-mainline-MD/gcc/opt-functions.awk gcc-mainline/gcc/opt-functions.awk --- gcc-mainline-MD/gcc/opt-functions.awk 2010-08-11 16:00:36.000000000 -0700 +++ gcc-mainline/gcc/opt-functions.awk 2010-08-12 02:47:21.000000000 -0700 @@ -78,6 +78,8 @@ function switch_flags (flags) result = result \ test_flag("Common", flags, " | CL_COMMON") \ test_flag("Target", flags, " | CL_TARGET") \ + test_flag("Driver", flags, " | CL_DRIVER") \ + test_flag("RejectDriver", flags, " | CL_REJECT_DRIVER") \ test_flag("Save", flags, " | CL_SAVE") \ test_flag("Joined", flags, " | CL_JOINED") \ test_flag("JoinedOrMissing", flags, " | CL_JOINED | CL_MISSING_OK") \ @@ -128,7 +130,7 @@ function static_var(name, flags) # Return the type of variable that should be associated with the given flags. function var_type(flags) { - if (!flag_set_p("Joined.*", flags)) + if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) return "int " else if (flag_set_p("UInteger", flags)) return "int " @@ -143,7 +145,7 @@ function var_type_struct(flags) { if (flag_set_p("UInteger", flags)) return "int " - else if (!flag_set_p("Joined.*", flags)) { + else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) { if (flag_set_p(".*Mask.*", flags)) return "int " else diff -rupN --exclude=.svn gcc-mainline-MD/gcc/opts-common.c gcc-mainline/gcc/opts-common.c --- gcc-mainline-MD/gcc/opts-common.c 2010-08-11 15:25:31.000000000 -0700 +++ gcc-mainline/gcc/opts-common.c 2010-08-12 04:31:59.000000000 -0700 @@ -128,8 +128,9 @@ integral_argument (const char *arg) } /* Decode the switch beginning at ARGV for the language indicated by - LANG_MASK, into the structure *DECODED. Returns the number of - switches consumed. */ + LANG_MASK (including CL_COMMON and CL_TARGET if applicable), into + the structure *DECODED. Returns the number of switches + consumed. */ static unsigned int decode_cmdline_option (const char **argv, unsigned int lang_mask, @@ -147,7 +148,7 @@ decode_cmdline_option (const char **argv opt = argv[0]; - opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET); + opt_index = find_opt (opt + 1, lang_mask); if (opt_index == OPT_SPECIAL_unknown && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm') && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') @@ -161,7 +162,7 @@ decode_cmdline_option (const char **argv memcpy (dup + 2, opt + 5, len - 2 + 1); opt = dup; value = 0; - opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET); + opt_index = find_opt (opt + 1, lang_mask); } if (opt_index == OPT_SPECIAL_unknown) @@ -218,11 +219,11 @@ decode_cmdline_option (const char **argv } /* Check if this is a switch for a different front end. */ - if (!(option->flags & (lang_mask | CL_COMMON | CL_TARGET))) + if (!(option->flags & lang_mask)) errors |= CL_ERR_WRONG_LANG; else if ((option->flags & CL_TARGET) - && (option->flags & CL_LANG_ALL) - && !(option->flags & lang_mask)) + && (option->flags & (CL_LANG_ALL | CL_DRIVER)) + && !(option->flags & (lang_mask & ~CL_COMMON & ~CL_TARGET))) /* Complain for target flag language mismatches if any languages are specified. */ errors |= CL_ERR_WRONG_LANG; @@ -301,8 +302,9 @@ decode_cmdline_option (const char **argv array and *DECODED_OPTIONS_COUNT to the number of entries in the array. The first entry in the array is always one for the program name (OPT_SPECIAL_program_name). LANG_MASK indicates the language - applicable for decoding. Do not produce any diagnostics or set - state outside of these variables. */ + flags applicable for decoding (including CL_COMMON and CL_TARGET if + those options should be considered applicable). Do not produce any + diagnostics or set state outside of these variables. */ void decode_cmdline_options_to_array (unsigned int argc, const char **argv, diff -rupN --exclude=.svn gcc-mainline-MD/gcc/opts.c gcc-mainline/gcc/opts.c --- gcc-mainline-MD/gcc/opts.c 2010-08-11 15:25:33.000000000 -0700 +++ gcc-mainline/gcc/opts.c 2010-08-12 12:21:14.000000000 -0700 @@ -418,17 +418,27 @@ complain_wrong_lang (const struct cl_dec { const struct cl_option *option = &cl_options[decoded->opt_index]; const char *text = decoded->orig_option_with_args_text; - char *ok_langs, *bad_lang; + char *ok_langs = NULL, *bad_lang = NULL; + unsigned int opt_flags = option->flags; if (!lang_hooks.complain_wrong_lang_p (option)) return; - ok_langs = write_langs (option->flags); - bad_lang = write_langs (lang_mask); - - /* Eventually this should become a hard error IMO. */ - warning (0, "command line option \"%s\" is valid for %s but not for %s", - text, ok_langs, bad_lang); + opt_flags &= ((1U << cl_lang_count) - 1) | CL_DRIVER; + if (opt_flags != CL_DRIVER) + ok_langs = write_langs (opt_flags); + if (lang_mask != CL_DRIVER) + bad_lang = write_langs (lang_mask); + + if (opt_flags == CL_DRIVER) + error ("command line option %qs is valid for the driver but not for %s", + text, bad_lang); + else if (lang_mask == CL_DRIVER) + gcc_unreachable (); + else + /* Eventually this should become a hard error IMO. */ + warning (0, "command line option %qs is valid for %s but not for %s", + text, ok_langs, bad_lang); free (ok_langs); free (bad_lang); @@ -681,7 +691,8 @@ decode_options (unsigned int argc, const else lang_mask = initial_lang_mask; - decode_cmdline_options_to_array (argc, argv, lang_mask, + decode_cmdline_options_to_array (argc, argv, + lang_mask | CL_COMMON | CL_TARGET, decoded_options, decoded_options_count); if (first_time_p) /* Perform language-specific options initialization. */ @@ -1193,6 +1204,12 @@ print_filtered_help (unsigned int includ if ((option->flags & exclude_flags) != 0) continue; + /* The driver currently prints its own help text. */ + if ((option->flags & CL_DRIVER) != 0 + && (option->flags & (((1U << cl_lang_count) - 1) + | CL_COMMON | CL_TARGET)) == 0) + continue; + found = true; /* Skip switches that have already been printed. */ if (printed[i]) @@ -1333,6 +1350,7 @@ print_specific_help (unsigned int includ switch (flag & include_flags) { case 0: + case CL_DRIVER: break; case CL_TARGET: @@ -1436,7 +1454,8 @@ common_handle_option (const struct cl_de print_specific_help (0, undoc_mask, all_langs_mask); /* Then display any remaining, non-language options. */ for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1) - print_specific_help (i, undoc_mask, 0); + if (i != CL_DRIVER) + print_specific_help (i, undoc_mask, 0); exit_after_options = true; break; } diff -rupN --exclude=.svn gcc-mainline-MD/gcc/opts.h gcc-mainline/gcc/opts.h --- gcc-mainline-MD/gcc/opts.h 2010-08-11 15:25:33.000000000 -0700 +++ gcc-mainline/gcc/opts.h 2010-08-12 02:47:21.000000000 -0700 @@ -67,11 +67,12 @@ extern const unsigned int cl_options_cou extern const char *const lang_names[]; extern const unsigned int cl_lang_count; -#define CL_PARAMS (1 << 17) /* Fake entry. Used to display --param info with --help. */ -#define CL_WARNING (1 << 18) /* Enables an (optional) warning message. */ -#define CL_OPTIMIZATION (1 << 19) /* Enables an (optional) optimization. */ -#define CL_TARGET (1 << 20) /* Target-specific option. */ -#define CL_COMMON (1 << 21) /* Language-independent. */ +#define CL_PARAMS (1 << 15) /* Fake entry. Used to display --param info with --help. */ +#define CL_WARNING (1 << 16) /* Enables an (optional) warning message. */ +#define CL_OPTIMIZATION (1 << 17) /* Enables an (optional) optimization. */ +#define CL_DRIVER (1 << 18) /* Driver option. */ +#define CL_TARGET (1 << 19) /* Target-specific option. */ +#define CL_COMMON (1 << 20) /* Language-independent. */ #define CL_MIN_OPTION_CLASS CL_PARAMS #define CL_MAX_OPTION_CLASS CL_COMMON @@ -81,6 +82,7 @@ extern const unsigned int cl_lang_count; This distinction is important because --help will not list options which only have these higher bits set. */ +#define CL_REJECT_DRIVER (1 << 21) /* Reject this option in the driver. */ #define CL_SAVE (1 << 22) /* Target-specific option for attribute. */ #define CL_DISABLED (1 << 23) /* Disabled in this configuration. */ #define CL_REPORT (1 << 24) /* Report argument with -fverbose-asm */