From patchwork Sat Jun 26 13:05:11 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 57057 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 8C93EB6EE8 for ; Sat, 26 Jun 2010 23:05:28 +1000 (EST) Received: (qmail 2536 invoked by alias); 26 Jun 2010 13:05:26 -0000 Received: (qmail 2521 invoked by uid 22791); 26 Jun 2010 13:05:22 -0000 X-SWARE-Spam-Status: No, hits=-0.8 required=5.0 tests=AWL, BAYES_20, 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; Sat, 26 Jun 2010 13:05:14 +0000 Received: (qmail 20594 invoked from network); 26 Jun 2010 13:05:12 -0000 Received: from unknown (HELO digraph.polyomino.org.uk) (joseph@127.0.0.2) by mail.codesourcery.com with ESMTPA; 26 Jun 2010 13:05:12 -0000 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.69) (envelope-from ) id 1OSV4J-0007dX-26 for gcc-patches@gcc.gnu.org; Sat, 26 Jun 2010 13:05:11 +0000 Date: Sat, 26 Jun 2010 13:05:11 +0000 (UTC) From: "Joseph S. Myers" To: gcc-patches@gcc.gnu.org Subject: Merge two passes over options in gcc.c 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 Continuing preparation for making the driver share option processing machinery with the compiler proper, this patch replaces two passes over options in the driver with a single pass, which fits more naturally with the option processing model used elsewhere of a pass over options that calls appropriate handlers for each option in turn. (There are several other passes to assimilate to the model of first decoding options then working with decoded options, but these two passes are the main ones that will need converting to use decoded options as part of the initial integration of shared option processing machinery in the driver; the others can follow later.) Previously, the first pass would act on some options and work out how much memory to allocate for other options and input files, while the second pass would act on other options and store options for use of specs as well as storing a list of input files. By making the code increase the size of the relevant arrays as needed (size doubling like this is already used elsewhere in the driver), the two passes can be integrated. The two passes were in fact out of sync as regards -Xpreprocessor and -Xassembler; the second pass would skip their operands when looking for the next option, but the first pass would not, resulting in such operands being wrongly interpreted as driver options. Bootstrapped with no regressions on x86_64-unknown-linux-gnu. OK to commit? 2010-06-26 Joseph Myers * gcc.c (n_switches_alloc, n_infiles_alloc, alloc_infile, add_infile, alloc_switch): New. (process_command): Remove variable lang_n_infiles. Process options in a single pass. Use new functions for allocating infiles and switches arrays. Properly skip operands of -Xpreprocessor and -Xassembler. testsuite: 2010-06-26 Joseph Myers * gcc.dg/opts-3.c: New test. diff -rupN --exclude=.svn gcc-mainline-opt4-takes-arg/gcc/gcc.c gcc-mainline/gcc/gcc.c --- gcc-mainline-opt4-takes-arg/gcc/gcc.c 2010-06-25 08:11:25.000000000 -0700 +++ gcc-mainline/gcc/gcc.c 2010-06-26 03:36:56.000000000 -0700 @@ -3244,6 +3244,8 @@ static struct switchstr *switches; static int n_switches; +static int n_switches_alloc; + /* Set to zero if -fcompare-debug is disabled, positive if it's enabled and we're running the first compilation, negative if it's enabled and we're running the second compilation. For most of the @@ -3289,6 +3291,8 @@ static struct infile *infiles; int n_infiles; +static int n_infiles_alloc; + /* True if multiple input files are being compiled to a single assembly file. */ @@ -3473,6 +3477,51 @@ add_linker_option (const char *option, i linker_options [n_linker_options - 1] = save_string (option, len); } +/* Allocate space for an input file in infiles. */ + +static void +alloc_infile (void) +{ + if (n_infiles_alloc == 0) + { + n_infiles_alloc = 16; + infiles = XNEWVEC (struct infile, n_infiles_alloc); + } + else if (n_infiles_alloc == n_infiles) + { + n_infiles_alloc *= 2; + infiles = XRESIZEVEC (struct infile, infiles, n_infiles_alloc); + } +} + +/* Store an input file with the given NAME and LANGUAGE in + infiles. */ + +static void +add_infile (const char *name, const char *language) +{ + alloc_infile (); + infiles[n_infiles].name = name; + infiles[n_infiles++].language = language; +} + +/* Allocate space for a switch in switches. */ + +static void +alloc_switch (void) +{ + if (n_switches_alloc == 0) + { + n_switches_alloc = 16; + switches = XNEWVEC (struct switchstr, n_switches_alloc); + } + else if (n_switches_alloc == n_switches) + { + n_switches_alloc *= 2; + switches = XRESIZEVEC (struct switchstr, switches, n_switches_alloc); + } +} + /* Create the vector `switches' and its contents. Store its length in `n_switches'. */ @@ -3484,7 +3533,6 @@ process_command (int argc, const char ** char *temp1; const char *spec_lang = 0; int last_language_n_infiles; - int lang_n_infiles = 0; const char *tooldir_prefix; char *(*get_relative_prefix) (const char *, const char *, const char *) = NULL; @@ -3698,12 +3746,22 @@ process_command (int argc, const char ** } } - /* Scan argv twice. Here, the first time, just count how many switches - there will be in their vector, and how many input files in theirs. - Here we also parse the switches that cc itself uses (e.g. -v). */ + /* Process the options and store input files and switches in their + vectors. */ + + 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; @@ -3729,59 +3787,50 @@ process_command (int argc, const char ** /* translate_options () has turned --version into -fversion. */ print_version = 1; - /* We will be passing a dummy file on to the sub-processes. */ - n_infiles++; - n_switches++; - /* 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; - /* We will be passing a dummy file on to the sub-processes. */ - n_infiles++; - n_switches++; - /* 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; - /* We will be passing a dummy file on to the sub-processes. */ - n_infiles++; - n_switches++; + goto normal_switch; } else if (strcmp (argv[i], "-ftarget-help") == 0) { /* translate_options() has turned --target-help into -ftarget-help. */ print_subprocess_help = 1; - /* We will be passing a dummy file on to the sub-processes. */ - n_infiles++; - n_switches++; - /* 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; - n_switches++; } else if (! strcmp (argv[i], "-print-search-dirs")) print_search_dirs = 1; @@ -3804,16 +3853,18 @@ process_command (int argc, const char ** else if (! strcmp (argv[i], "-fcompare-debug-second")) { compare_debug_second = 1; - n_switches++; + 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=" @@ -3831,7 +3882,7 @@ process_command (int argc, const char ** compare_debug_opt = NULL; else compare_debug_opt = opt; - n_switches++; + goto normal_switch; } else if (! strncmp (argv[i], "-Wa,", 4)) { @@ -3869,17 +3920,24 @@ process_command (int argc, const char ** } else if (strncmp (argv[i], "-Wl,", 4) == 0) { - int j; + int prev, j; /* Split the argument at commas. */ - for (j = 3; argv[i][j]; j++) - n_infiles += (argv[i][j] == ','); + 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"); - n_infiles++; + add_infile (argv[i+1], "*"); i++; } else if (strcmp (argv[i], "-Xpreprocessor") == 0) @@ -3888,6 +3946,7 @@ process_command (int argc, const char ** 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) { @@ -3895,25 +3954,29 @@ process_command (int argc, const char ** 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"); - n_infiles++; + /* 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) - n_infiles++; + { + add_infile (argv[i], "*"); + } else if (strcmp (argv[i], "-save-temps") == 0) { save_temps_flag = SAVE_TEMPS_CWD; - n_switches++; + goto normal_switch; } else if (strncmp (argv[i], "-save-temps=", 12) == 0) { - n_switches++; if (strcmp (argv[i]+12, "cwd") == 0) save_temps_flag = SAVE_TEMPS_CWD; else if (strcmp (argv[i]+12, "obj") == 0 @@ -3921,6 +3984,7 @@ process_command (int argc, const char ** 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. */ @@ -3928,7 +3992,7 @@ process_command (int argc, const char ** else if (strcmp (argv[i], "-combine") == 0) { combine_flag = 1; - n_switches++; + goto normal_switch; } else if (strcmp (argv[i], "-specs") == 0) { @@ -3958,6 +4022,11 @@ process_command (int argc, const char ** 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) @@ -3971,7 +4040,7 @@ process_command (int argc, const char ** /* -pipe has to go into the switches array as well as setting a flag. */ use_pipes = 1; - n_switches++; + goto normal_switch; } else if (strcmp (argv[i], "-wrapper") == 0) { @@ -3979,8 +4048,6 @@ process_command (int argc, const char ** fatal_error ("argument to %<-wrapper%> is missing"); wrapper_string = argv[i]; - n_switches++; - n_switches++; } else if (strcmp (argv[i], "-###") == 0) { @@ -3993,9 +4060,6 @@ process_command (int argc, const char ** } else if (argv[i][0] == '-' && argv[i][1] != 0) { - const char *p = &argv[i][1]; - int c = *p; - switch (c) { case 'B': @@ -4006,7 +4070,7 @@ process_command (int argc, const char ** if (p[1] == 0 && i + 1 == argc) fatal_error ("argument to %<-B%> is missing"); if (p[1] == 0) - value = argv[++i]; + value = argv[i + 1]; else value = p + 1; @@ -4035,28 +4099,38 @@ process_command (int argc, const char ** PREFIX_PRIORITY_B_OPT, 0, 0); add_prefix (&include_prefixes, value, NULL, PREFIX_PRIORITY_B_OPT, 0, 0); - n_switches++; } - break; + goto normal_switch; case 'v': /* Print our subcommands and print versions. */ - n_switches++; /* 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; - n_switches++; - break; - } + have_c = 1; goto normal_switch; case 'o': @@ -4094,7 +4168,10 @@ process_command (int argc, const char ** 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); + { + 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]) @@ -4106,18 +4183,105 @@ process_command (int argc, const char ** default: normal_switch: - n_switches++; + 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 (SWITCH_TAKES_ARG (c) > (p[1] != 0)) - i += SWITCH_TAKES_ARG (c) - (p[1] != 0); - else if (WORD_SWITCH_TAKES_ARG (p)) - i += 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 (strchr (switches_need_spaces, c)) + { + /* On some systems, ld cannot handle some options 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; + + 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 { - n_infiles++; - lang_n_infiles++; + const char *p = strrchr (argv[i], '@'); + char *fname; + long offset; + int consumed; +#ifdef HAVE_TARGET_OBJECT_SUFFIX + argv[i] = convert_filename (argv[i], 0, access (argv[i], 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] + && 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'; + /* 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]); + } + } + else + fname = xstrdup (argv[i]); + + if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0) + perror_with_name (fname); + else + add_infile (argv[i], spec_lang); + + free (fname); } } @@ -4156,13 +4320,11 @@ process_command (int argc, const char ** { compare_debug = 2; compare_debug_opt = gcd; - n_switches++; } else if (gcd && *gcd && strcmp (gcd, "0")) { compare_debug = 3; compare_debug_opt = "-gtoggle"; - n_switches++; } } else if (compare_debug < 0) @@ -4215,7 +4377,7 @@ process_command (int argc, const char ** then consider it to relocate with the rest of the GCC installation if GCC_EXEC_PREFIX is set. ``make_relative_prefix'' is not compiled for VMS, so don't call it. */ - if (target_system_root && gcc_exec_prefix) + if (target_system_root && !target_system_root_changed && gcc_exec_prefix) { char *tmp_prefix = get_relative_prefix (argv[0], standard_bindir_prefix, @@ -4231,232 +4393,12 @@ process_command (int argc, const char ** /* More prefixes are enabled in main, after we read the specs file and determine whether this is cross-compilation or not. */ - /* Then create the space for the vectors and scan again. */ - - switches = XNEWVEC (struct switchstr, n_switches + 1); - infiles = XNEWVEC (struct infile, n_infiles + 1); - n_switches = 0; - n_infiles = 0; - last_language_n_infiles = -1; - - /* This, time, copy the text of each switch and store a pointer - to the copy in the vector of switches. - Store all the infiles in their vector. */ - - for (i = 1; i < argc; i++) - { - /* Just skip the switches that were handled by the preceding loop. */ - if (! strncmp (argv[i], "-Wa,", 4)) - ; - else if (! strncmp (argv[i], "-Wp,", 4)) - ; - else if (! strcmp (argv[i], "-no-canonical-prefixes")) - ; - else if (! strcmp (argv[i], "-pass-exit-codes")) - ; - else if (! strcmp (argv[i], "-print-search-dirs")) - ; - else if (! strcmp (argv[i], "-print-libgcc-file-name")) - ; - else if (! strncmp (argv[i], "-print-file-name=", 17)) - ; - else if (! strncmp (argv[i], "-print-prog-name=", 17)) - ; - else if (! strcmp (argv[i], "-print-multi-lib")) - ; - else if (! strcmp (argv[i], "-print-multi-directory")) - ; - else if (! strcmp (argv[i], "-print-sysroot")) - ; - else if (! strcmp (argv[i], "-print-multi-os-directory")) - ; - else if (! strcmp (argv[i], "-print-sysroot-headers-suffix")) - ; - else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot="))) - { - target_system_root = argv[i] + strlen ("--sysroot="); - target_system_root_changed = 1; - } - 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] == ',') - { - infiles[n_infiles].language = "*"; - infiles[n_infiles++].name - = save_string (argv[i] + prev, j - prev); - prev = j + 1; - } - /* Record the part after the last comma. */ - infiles[n_infiles].language = "*"; - infiles[n_infiles++].name = argv[i] + prev; - } - else if (strcmp (argv[i], "-Xlinker") == 0) - { - infiles[n_infiles].language = "*"; - infiles[n_infiles++].name = argv[++i]; - } - /* Xassembler and Xpreprocessor were already handled in the first argv - scan, so all we need to do here is ignore them and their argument. */ - else if (strcmp (argv[i], "-Xassembler") == 0) - i++; - else if (strcmp (argv[i], "-Xpreprocessor") == 0) - i++; - else if (strcmp (argv[i], "-l") == 0) - { /* POSIX allows separation of -l and the lib arg; - canonicalize by concatenating -l with its arg */ - infiles[n_infiles].language = "*"; - infiles[n_infiles++].name = concat ("-l", argv[++i], NULL); - } - else if (strncmp (argv[i], "-l", 2) == 0) - { - infiles[n_infiles].language = "*"; - infiles[n_infiles++].name = argv[i]; - } - else if (strcmp (argv[i], "-wrapper") == 0) - i++; - else if (strcmp (argv[i], "-specs") == 0) - i++; - else if (strncmp (argv[i], "-specs=", 7) == 0) - ; - else if (strcmp (argv[i], "-time") == 0) - ; - else if (strncmp (argv[i], "-time=", sizeof ("-time=") - 1) == 0) - ; - else if (strcmp (argv[i], "-###") == 0) - ; - else if (argv[i][0] == '-' && argv[i][1] != 0) - { - const char *p = &argv[i][1]; - int c = *p; - - if (c == '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; - continue; - } - 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 (strchr (switches_need_spaces, c)) - { - /* On some systems, ld cannot handle some options 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; - - 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 - { - const char *p = strrchr (argv[i], '@'); - char *fname; - long offset; - int consumed; -#ifdef HAVE_TARGET_OBJECT_SUFFIX - argv[i] = convert_filename (argv[i], 0, access (argv[i], 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] - && 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'; - /* 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]); - } - } - else - fname = xstrdup (argv[i]); - - if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0) - perror_with_name (fname); - else - { - infiles[n_infiles].language = spec_lang; - infiles[n_infiles++].name = argv[i]; - } - - free (fname); - } - } - if (n_infiles == last_language_n_infiles && spec_lang != 0) warning (0, "%<-x %s%> after last input file has no effect", spec_lang); if (compare_debug == 2 || compare_debug == 3) { + alloc_switch (); switches[n_switches].part1 = concat ("fcompare-debug=", compare_debug_opt, NULL); @@ -4471,15 +4413,16 @@ process_command (int argc, const char ** /* Ensure we only invoke each subprocess once. */ if (print_subprocess_help || print_help_list || print_version) { - n_infiles = 1; + n_infiles = 0; /* Create a dummy input file, so that we can pass the help option on to the various sub-processes. */ - infiles[0].language = "c"; - infiles[0].name = "help-dummy"; + add_infile ("help-dummy", "c"); } + alloc_switch (); switches[n_switches].part1 = 0; + alloc_infile (); infiles[n_infiles].name = 0; } diff -rupN --exclude=.svn gcc-mainline-opt4-takes-arg/gcc/testsuite/gcc.dg/opts-3.c gcc-mainline/gcc/testsuite/gcc.dg/opts-3.c --- gcc-mainline-opt4-takes-arg/gcc/testsuite/gcc.dg/opts-3.c 1969-12-31 16:00:00.000000000 -0800 +++ gcc-mainline/gcc/testsuite/gcc.dg/opts-3.c 2010-06-25 17:37:27.000000000 -0700 @@ -0,0 +1,7 @@ +/* Parameters of -Xassembler should not be interpreted as driver + options (and so cause the driver to exit prematurely, as in this + testcase, or have other unintended effects). */ +/* { dg-do compile } */ +/* { dg-options "-Xassembler -dumpmachine" } */ + +int int x; /* { dg-error "two or more data types" } */