Message ID | Pine.LNX.4.64.1006261304040.28910@digraph.polyomino.org.uk |
---|---|
State | New |
Headers | show |
On Sat, Jun 26, 2010 at 3:05 PM, Joseph S. Myers <joseph@codesourcery.com> wrote: > 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? Ok. Thanks, Richard. > 2010-06-26 Joseph Myers <joseph@codesourcery.com> > > * 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 <joseph@codesourcery.com> > > * 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" } */ > > -- > Joseph S. Myers > joseph@codesourcery.com >
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" } */