X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgcc.c;h=ddec8db706b77d0f27aa2627414424e7088870f1;hb=229c2354d5315ae45932c64ce51fa35e7ad3436a;hp=cd201f53b95abef3c3a6bf330f619937a3ab4168;hpb=48b14f5076a521887a2286eb84e6b51de6c50fd8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gcc.c b/gcc/gcc.c index cd201f53b95..ddec8db706b 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -1,7 +1,7 @@ /* Compiler driver program that can handle many languages. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010 + 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -35,10 +35,6 @@ compilation is specified by a string called a "spec". */ #include "coretypes.h" #include "multilib.h" /* before tm.h */ #include "tm.h" -#include -#if ! defined( SIGCHLD ) && defined( SIGCLD ) -# define SIGCHLD SIGCLD -#endif #include "xregex.h" #include "obstack.h" #include "intl.h" @@ -47,18 +43,9 @@ compilation is specified by a string called a "spec". */ #include "diagnostic.h" #include "flags.h" #include "opts.h" - -#ifdef HAVE_MMAP_FILE -# include -# ifdef HAVE_MINCORE -/* This is on Solaris. */ -# include -# endif -#endif - -#ifndef MAP_FAILED -# define MAP_FAILED ((void *)-1) -#endif +#include "params.h" +#include "vec.h" +#include "filenames.h" /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -87,10 +74,6 @@ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; #define LIBRARY_PATH_ENV "LIBRARY_PATH" #endif -#ifndef HAVE_KILL -#define kill(p,s) raise(s) -#endif - /* If a stage of compilation returns an exit status >= 1, compilation of that file ceases. */ @@ -114,10 +97,6 @@ static int print_help_list; static int print_version; -/* Flag indicating whether we should print the command and arguments */ - -static int verbose_flag; - /* Flag indicating whether we should ONLY print the command and arguments (like verbose_flag) without executing the command. Displayed arguments are quoted so that the generated command @@ -287,6 +266,7 @@ static const char *print_asm_header_spec_function (int, const char **); static const char *compare_debug_dump_opt_spec_function (int, const char **); static const char *compare_debug_self_opt_spec_function (int, const char **); static const char *compare_debug_auxbase_opt_spec_function (int, const char **); +static const char *pass_through_libs_spec_func (int, const char **); /* The Specs Language @@ -412,6 +392,7 @@ or with constant text in a single argument. Note - this command is position dependent. % commands in the spec string before this one will see -S, % commands in the spec string after this one will not. + %>S Similar to "% 0 +/* The linker used has full plugin support, use LTO plugin by default. */ +#if HAVE_LTO_PLUGIN == 2 +#define PLUGIN_COND "!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin" +#define PLUGIN_COND_CLOSE "}" +#else +/* The linker used has limited plugin support, use LTO plugin with explicit + -fuse-linker-plugin. */ +#define PLUGIN_COND "fuse-linker-plugin" +#define PLUGIN_COND_CLOSE "" +#endif +#define LINK_PLUGIN_SPEC \ + "%{"PLUGIN_COND": \ + -plugin %(linker_plugin_file) \ + -plugin-opt=%(lto_wrapper) \ + -plugin-opt=-fresolution=%u.res \ + %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \ + }"PLUGIN_COND_CLOSE +#else +/* The linker used doesn't support -plugin, reject -fuse-linker-plugin. */ +#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\ + %e-fuse-linker-plugin is not supported in this configuration}" +#endif + /* -u* was put back because both BSD and SysV seem to support it. */ /* %{static:} simply prevents an error message if the target machine @@ -649,29 +661,24 @@ proper position among the other output files. */ /* We want %{T*} after %{L*} and %D so that it can be used to specify linker scripts which exist in user specified directories, or in standard directories. */ -/* We pass any -flto and -fwhopr flags on to the linker, which is expected +/* We pass any -flto flags on to the linker, which is expected to understand them. In practice, this means it had better be collect2. */ +/* %{e*} includes -export-dynamic; see comment in common.opt. */ #ifndef LINK_COMMAND_SPEC #define LINK_COMMAND_SPEC "\ %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ - %(linker) \ - %{fuse-linker-plugin: \ - -plugin %(linker_plugin_file) \ - -plugin-opt=%(lto_wrapper) \ - -plugin-opt=-fresolution=%u.res \ - %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \ - %{static:-plugin-opt=-pass-through=-lc} \ - } \ - %{flto:%next) - if (! strcmp (name, temp->name)) + if (! filename_cmp (name, temp->name)) goto already1; temp = XNEW (struct temp_file); @@ -1976,7 +1978,7 @@ record_temp_file (const char *filename, int always_delete, int fail_delete) { struct temp_file *temp; for (temp = failure_delete_queue; temp; temp = temp->next) - if (! strcmp (name, temp->name)) + if (! filename_cmp (name, temp->name)) goto already2; temp = XNEW (struct temp_file); @@ -2474,6 +2476,7 @@ execute (void) const char *prog; /* program name. */ const char **argv; /* vector of args. */ }; + const char *arg; struct command *commands; /* each command buffer with above info. */ @@ -2481,14 +2484,16 @@ execute (void) if (wrapper_string) { - string = find_a_file (&exec_prefixes, argbuf[0], X_OK, false); - argbuf[0] = (string) ? string : argbuf[0]; + string = find_a_file (&exec_prefixes, + VEC_index (const_char_p, argbuf, 0), X_OK, false); + if (string) + VEC_replace (const_char_p, argbuf, 0, string); insert_wrapper (wrapper_string); } /* Count # of piped commands. */ - for (n_commands = 1, i = 0; i < argbuf_index; i++) - if (strcmp (argbuf[i], "|") == 0) + for (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++) + if (strcmp (arg, "|") == 0) n_commands++; /* Get storage for each command. */ @@ -2498,8 +2503,10 @@ execute (void) and record info about each one. Also search for the programs that are to be run. */ - commands[0].prog = argbuf[0]; /* first command. */ - commands[0].argv = &argbuf[0]; + VEC_safe_push (const_char_p, heap, argbuf, 0); + + commands[0].prog = VEC_index (const_char_p, argbuf, 0); /* first command. */ + commands[0].argv = VEC_address (const_char_p, argbuf); if (!wrapper_string) { @@ -2507,15 +2514,17 @@ execute (void) commands[0].argv[0] = (string) ? string : commands[0].argv[0]; } - for (n_commands = 1, i = 0; i < argbuf_index; i++) - if (strcmp (argbuf[i], "|") == 0) + for (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++) + if (arg && strcmp (arg, "|") == 0) { /* each command. */ #if defined (__MSDOS__) || defined (OS2) || defined (VMS) fatal_error ("-pipe not supported"); #endif - argbuf[i] = 0; /* termination of command args. */ - commands[n_commands].prog = argbuf[i + 1]; - commands[n_commands].argv = &argbuf[i + 1]; + VEC_replace (const_char_p, argbuf, i, 0); /* Termination of + command args. */ + commands[n_commands].prog = VEC_index (const_char_p, argbuf, i + 1); + commands[n_commands].argv + = &(VEC_address (const_char_p, argbuf))[i + 1]; string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK, false); if (string) @@ -2523,8 +2532,6 @@ execute (void) n_commands++; } - argbuf[argbuf_index] = 0; - /* If -v, print what we are about to do, and maybe query. */ if (verbose_flag) @@ -2558,13 +2565,20 @@ execute (void) } fputc ('"', stderr); } + /* If it's empty, print "". */ + else if (!**j) + fprintf (stderr, " \"\""); else fprintf (stderr, " %s", *j); } } else for (j = commands[i].argv; *j; j++) - fprintf (stderr, " %s", *j); + /* If it's empty, print "". */ + if (!**j) + fprintf (stderr, " \"\""); + else + fprintf (stderr, " %s", *j); /* Print a pipe symbol after all but the last command. */ if (i + 1 != n_commands) @@ -2780,10 +2794,11 @@ execute (void) The `validated' field is nonzero if any spec has looked at this switch; if it remains zero at the end of the run, it must be meaningless. */ -#define SWITCH_LIVE 0x1 -#define SWITCH_FALSE 0x2 -#define SWITCH_IGNORE 0x4 -#define SWITCH_IGNORE_PERMANENTLY 0x8 +#define SWITCH_LIVE (1 << 0) +#define SWITCH_FALSE (1 << 1) +#define SWITCH_IGNORE (1 << 2) +#define SWITCH_IGNORE_PERMANENTLY (1 << 3) +#define SWITCH_KEEP_FOR_GCC (1 << 4) struct switchstr { @@ -2821,6 +2836,8 @@ static struct switchstr *switches_debug_check[2]; static int n_switches_debug_check[2]; +static int n_switches_alloc_debug_check[2]; + static char *debug_check_temp_file[2]; /* Language is one of three things: @@ -2991,43 +3008,20 @@ display_help (void) static void add_preprocessor_option (const char *option, int len) { - n_preprocessor_options++; - - if (! preprocessor_options) - preprocessor_options = XNEWVEC (char *, n_preprocessor_options); - else - preprocessor_options = XRESIZEVEC (char *, preprocessor_options, - n_preprocessor_options); - - preprocessor_options [n_preprocessor_options - 1] = - save_string (option, len); + VEC_safe_push (char_p, heap, preprocessor_options, + save_string (option, len)); } static void add_assembler_option (const char *option, int len) { - n_assembler_options++; - - if (! assembler_options) - assembler_options = XNEWVEC (char *, n_assembler_options); - else - assembler_options = XRESIZEVEC (char *, assembler_options, - n_assembler_options); - - assembler_options [n_assembler_options - 1] = save_string (option, len); + VEC_safe_push (char_p, heap, assembler_options, save_string (option, len)); } static void add_linker_option (const char *option, int len) { - n_linker_options++; - - if (! linker_options) - linker_options = XNEWVEC (char *, n_linker_options); - else - linker_options = XRESIZEVEC (char *, linker_options, n_linker_options); - - linker_options [n_linker_options - 1] = save_string (option, len); + VEC_safe_push (char_p, heap, linker_options, save_string (option, len)); } /* Allocate space for an input file in infiles. */ @@ -3100,16 +3094,24 @@ save_switch (const char *opt, size_t n_args, const char *const *args, } /* Handle an option DECODED that is unknown to the option-processing - machinery, but may be known to specs. */ + machinery. */ 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; + const char *opt = decoded->arg; + if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-' + && !(decoded->errors & CL_ERR_NEGATIVE)) + { + /* Leave unknown -Wno-* options for the compiler proper, to be + diagnosed only if there are warnings. */ + save_switch (decoded->canonical_option[0], + decoded->canonical_option_num_elements - 1, + &decoded->canonical_option[1], false); + return false; + } + else + return true; } /* Handle an option DECODED that is not marked as CL_DRIVER. @@ -3126,11 +3128,13 @@ driver_wrong_lang_callback (const struct cl_decoded_option *decoded, options. */ const struct cl_option *option = &cl_options[decoded->opt_index]; - if (option->flags & CL_REJECT_DRIVER) + if (option->cl_reject_driver) error ("unrecognized command line option %qs", decoded->orig_option_with_args_text); else - driver_unknown_option_callback (decoded); + save_switch (decoded->canonical_option[0], + decoded->canonical_option_num_elements - 1, + &decoded->canonical_option[1], false); } /* Note that an option (index OPT_INDEX, argument ARG, value VALUE) @@ -3150,9 +3154,13 @@ static int last_language_n_infiles; handle_option. */ static bool -driver_handle_option (const struct cl_decoded_option *decoded, +driver_handle_option (struct gcc_options *opts, + struct gcc_options *opts_set, + const struct cl_decoded_option *decoded, unsigned int lang_mask ATTRIBUTE_UNUSED, int kind, - const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) + location_t loc, + const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED, + diagnostic_context *dc) { size_t opt_index = decoded->opt_index; const char *arg = decoded->arg; @@ -3161,7 +3169,11 @@ driver_handle_option (const struct cl_decoded_option *decoded, bool validated = false; bool do_save = true; + gcc_assert (opts == &global_options); + gcc_assert (opts_set == &global_options_set); gcc_assert (kind == DK_UNSPECIFIED); + gcc_assert (loc == UNKNOWN_LOCATION); + gcc_assert (dc == global_dc); switch (opt_index) { @@ -3267,7 +3279,7 @@ driver_handle_option (const struct cl_decoded_option *decoded, compare_debug_with_arg: gcc_assert (decoded->canonical_option_num_elements == 1); gcc_assert (arg != NULL); - if (arg) + if (*arg) compare_debug = 1; else compare_debug = -1; @@ -3363,6 +3375,11 @@ driver_handle_option (const struct cl_decoded_option *decoded, save_switch (concat ("-L", arg, NULL), 0, NULL, validated); return true; + case OPT_F: + /* Likewise -F. */ + save_switch (concat ("-F", arg, NULL), 0, NULL, validated); + return true; + case OPT_save_temps: save_temps_flag = SAVE_TEMPS_CWD; validated = true; @@ -3426,7 +3443,7 @@ driver_handle_option (const struct cl_decoded_option *decoded, is intended for use in shell scripts to capture the driver-generated command line. */ verbose_only_flag++; - verbose_flag++; + verbose_flag = 1; do_save = false; break; @@ -3461,10 +3478,6 @@ driver_handle_option (const struct cl_decoded_option *decoded, 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")) @@ -3513,6 +3526,23 @@ driver_handle_option (const struct cl_decoded_option *decoded, return true; } +/* Put the driver's standard set of option handlers in *HANDLERS. */ + +static void +set_option_handlers (struct cl_option_handlers *handlers) +{ + 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 = 3; + handlers->handlers[0].handler = driver_handle_option; + handlers->handlers[0].mask = CL_DRIVER; + handlers->handlers[1].handler = common_handle_option; + handlers->handlers[1].mask = CL_COMMON; + handlers->handlers[2].handler = target_handle_option; + handlers->handlers[2].mask = CL_TARGET; +} + /* Create the vector `switches' and its contents. Store its length in `n_switches'. */ @@ -3528,7 +3558,7 @@ process_command (unsigned int decoded_options_count, struct cl_option_handlers handlers; unsigned int j; - GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); + gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX"); n_switches = 0; n_infiles = 0; @@ -3617,9 +3647,9 @@ process_command (unsigned int decoded_options_count, { temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1; if (IS_DIR_SEPARATOR (*temp) - && strncmp (temp + 1, "lib", 3) == 0 + && filename_ncmp (temp + 1, "lib", 3) == 0 && IS_DIR_SEPARATOR (temp[4]) - && strncmp (temp + 5, "gcc", 3) == 0) + && filename_ncmp (temp + 5, "gcc", 3) == 0) len -= sizeof ("/lib/gcc/") - 1; } @@ -3633,7 +3663,7 @@ process_command (unsigned int decoded_options_count, /* COMPILER_PATH and LIBRARY_PATH have values that are lists of directory names with colons. */ - GET_ENVIRONMENT (temp, "COMPILER_PATH"); + temp = getenv ("COMPILER_PATH"); if (temp) { const char *startp, *endp; @@ -3667,7 +3697,7 @@ process_command (unsigned int decoded_options_count, } } - GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV); + temp = getenv (LIBRARY_PATH_ENV); if (temp && *cross_compile == '0') { const char *startp, *endp; @@ -3700,7 +3730,7 @@ process_command (unsigned int decoded_options_count, } /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ - GET_ENVIRONMENT (temp, "LPATH"); + temp = getenv ("LPATH"); if (temp && *cross_compile == '0') { const char *startp, *endp; @@ -3737,12 +3767,7 @@ process_command (unsigned int decoded_options_count, last_language_n_infiles = -1; - 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; + set_option_handlers (&handlers); for (j = 1; j < decoded_options_count; j++) { @@ -3801,7 +3826,9 @@ process_command (unsigned int decoded_options_count, continue; } - read_cmdline_option (decoded_options + j, CL_DRIVER, &handlers); + read_cmdline_option (&global_options, &global_options_set, + decoded_options + j, UNKNOWN_LOCATION, + CL_DRIVER, &handlers, global_dc); } /* If -save-temps=obj and -o name, create the prefix to use for %b. @@ -3970,7 +3997,9 @@ set_collect_gcc_options (void) first_time = FALSE; /* Ignore elided switches. */ - if ((switches[i].live_cond & SWITCH_IGNORE) != 0) + if ((switches[i].live_cond + & (SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC)) + == SWITCH_IGNORE) continue; obstack_grow (&collect_obstack, "'-", 2); @@ -4103,6 +4132,7 @@ insert_wrapper (const char *wrapper) int i; char *buf = xstrdup (wrapper); char *p = buf; + unsigned int old_length = VEC_length (const_char_p, argbuf); do { @@ -4112,15 +4142,10 @@ insert_wrapper (const char *wrapper) } while ((p = strchr (p, ',')) != NULL); - if (argbuf_index + n >= argbuf_length) - { - argbuf_length = argbuf_length * 2; - while (argbuf_length < argbuf_index + n) - argbuf_length *= 2; - argbuf = XRESIZEVEC (const char *, argbuf, argbuf_length); - } - for (i = argbuf_index - 1; i >= 0; i--) - argbuf[i + n] = argbuf[i]; + VEC_safe_grow (const_char_p, heap, argbuf, old_length + n); + memmove (VEC_address (const_char_p, argbuf) + n, + VEC_address (const_char_p, argbuf), + old_length * sizeof (const_char_p)); i = 0; p = buf; @@ -4131,11 +4156,11 @@ insert_wrapper (const char *wrapper) *p = 0; p++; } - argbuf[i++] = p; + VEC_replace (const_char_p, argbuf, i, p); + i++; } while ((p = strchr (p, ',')) != NULL); gcc_assert (i == n); - argbuf_index += n; } /* Process the spec SPEC and run the commands specified therein. @@ -4152,12 +4177,13 @@ do_spec (const char *spec) If -pipe, this forces out the last command if it ended in `|'. */ if (value == 0) { - if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) - argbuf_index--; + if (VEC_length (const_char_p, argbuf) > 0 + && !strcmp (VEC_last (const_char_p, argbuf), "|")) + VEC_pop (const_char_p, argbuf); set_collect_gcc_options (); - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) value = execute (); } @@ -4253,68 +4279,64 @@ do_self_spec (const char *spec) if ((switches[i].live_cond & SWITCH_IGNORE)) switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY; - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) { - switches = XRESIZEVEC (struct switchstr, switches, - n_switches + argbuf_index + 1); - - for (i = 0; i < argbuf_index; i++) + const char **argbuf_copy; + struct cl_decoded_option *decoded_options; + struct cl_option_handlers handlers; + unsigned int decoded_options_count; + unsigned int j; + + /* Create a copy of argbuf with a dummy argv[0] entry for + decode_cmdline_options_to_array. */ + argbuf_copy = XNEWVEC (const char *, + VEC_length (const_char_p, argbuf) + 1); + argbuf_copy[0] = ""; + memcpy (argbuf_copy + 1, VEC_address (const_char_p, argbuf), + VEC_length (const_char_p, argbuf) * sizeof (const char *)); + + decode_cmdline_options_to_array (VEC_length (const_char_p, argbuf) + 1, + argbuf_copy, + CL_DRIVER, &decoded_options, + &decoded_options_count); + + set_option_handlers (&handlers); + + for (j = 1; j < decoded_options_count; j++) { - struct switchstr *sw; - const char *p = argbuf[i]; - int c = *p; - - /* Each switch should start with '-'. */ - if (c != '-') - fatal_error ("switch %qs does not start with %<-%>", argbuf[i]); - - p++; - c = *p; - - sw = &switches[n_switches++]; - sw->part1 = p; - sw->live_cond = 0; - sw->validated = 0; - sw->ordering = 0; - - /* Deal with option arguments in separate argv elements. */ - if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) - || WORD_SWITCH_TAKES_ARG (p)) + switch (decoded_options[j].opt_index) { - int j = 0; - int n_args = WORD_SWITCH_TAKES_ARG (p); + case OPT_SPECIAL_input_file: + /* Specs should only generate options, not input + files. */ + if (strcmp (decoded_options[j].arg, "-") != 0) + fatal_error ("switch %qs does not start with %<-%>", + decoded_options[j].arg); + else + fatal_error ("spec-generated switch is just %<-%>"); + break; - 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 >= argbuf_index) - fatal_error ("argument to %<-%s%> is missing", p); - sw->args - = XNEWVEC (const char *, n_args + 1); - while (j < n_args) - sw->args[j++] = argbuf[++i]; - /* Null-terminate the vector. */ - sw->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'; - - sw->part1 = part1; - sw->args = XNEWVEC (const char *, 2); - sw->args[0] = xstrdup (p+1); - sw->args[1] = 0; + case OPT_fcompare_debug_second: + case OPT_fcompare_debug: + case OPT_fcompare_debug_: + case OPT_o: + /* Avoid duplicate processing of some options from + compare-debug specs; just save them here. */ + save_switch (decoded_options[j].canonical_option[0], + (decoded_options[j].canonical_option_num_elements + - 1), + &decoded_options[j].canonical_option[1], false); + break; + + default: + read_cmdline_option (&global_options, &global_options_set, + decoded_options + j, UNKNOWN_LOCATION, + CL_DRIVER, &handlers, global_dc); + break; } - else - sw->args = 0; } + alloc_switch (); switches[n_switches].part1 = 0; } } @@ -4413,6 +4435,22 @@ compile_input_file_p (struct infile *infile) return false; } +/* Process each member of VEC as a spec. */ + +static void +do_specs_vec (VEC(char_p,heap) *vec) +{ + unsigned ix; + char *opt; + + FOR_EACH_VEC_ELT (char_p, vec, ix, opt) + { + do_spec_1 (opt, 1, NULL); + /* Make each accumulated option a separate argument. */ + do_spec_1 (" ", 0, NULL); + } +} + /* Process the sub-spec SPEC as a portion of a larger spec. This is like processing a whole spec except that we do not initialize at the beginning and we do not supply a @@ -4433,6 +4471,10 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) int i; int value; + /* If it's an empty string argument to a switch, keep it as is. */ + if (inswitch && !*p) + arg_going = 1; + while ((c = *p++)) /* If substituting a switch, treat all chars like letters. Otherwise, NL, SPC, TAB and % are special. */ @@ -4441,7 +4483,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) case '\n': end_going_arg (); - if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) + if (VEC_length (const_char_p, argbuf) > 0 + && !strcmp (VEC_last (const_char_p, argbuf), "|")) { /* A `|' before the newline means use a pipe here, but only if -pipe was specified. @@ -4452,12 +4495,12 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) break; } else - argbuf_index--; + VEC_pop (const_char_p, argbuf); } set_collect_gcc_options (); - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) { value = execute (); if (value) @@ -4704,7 +4747,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) tmp[basename_length + suffix_length] = '\0'; temp_filename = tmp; - if (strcmp (temp_filename, gcc_input_filename) != 0) + if (filename_cmp (temp_filename, gcc_input_filename) != 0) { #ifndef HOST_LACKS_INODE_NUMBERS struct stat st_temp; @@ -4730,7 +4773,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* Just compare canonical pathnames. */ char* input_realname = lrealpath (gcc_input_filename); char* temp_realname = lrealpath (temp_filename); - bool files_differ = strcmp (input_realname, temp_realname); + bool files_differ = filename_cmp (input_realname, temp_realname); free (input_realname); free (temp_realname); if (files_differ) @@ -4780,8 +4823,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) t->filename_length = temp_filename_length; } - if (saved_suffix) - free (saved_suffix); + free (saved_suffix); obstack_grow (&obstack, t->filename, t->filename_length); delete_this_arg = 1; @@ -4953,7 +4995,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) case 'W': { - int cur_index = argbuf_index; + unsigned int cur_index = VEC_length (const_char_p, argbuf); /* Handle the {...} following the %W. */ if (*p != '{') fatal_error ("spec %qs has invalid %<%%W%c%>", spec, *p); @@ -4963,8 +5005,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) end_going_arg (); /* If any args were output, mark the last one for deletion on failure. */ - if (argbuf_index != cur_index) - record_temp_file (argbuf[argbuf_index - 1], 0, 1); + if (VEC_length (const_char_p, argbuf) != cur_index) + record_temp_file (VEC_last (const_char_p, argbuf), 0, 1); break; } @@ -4973,6 +5015,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) { const char *p1 = p; char *string; + char *opt; + unsigned ix; /* Skip past the option value and make a copy. */ if (*p != '{') @@ -4982,8 +5026,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) string = save_string (p1 + 1, p - p1 - 2); /* See if we already recorded this option. */ - for (i = 0; i < n_linker_options; i++) - if (! strcmp (string, linker_options[i])) + FOR_EACH_VEC_ELT (char_p, linker_options, ix, opt) + if (! strcmp (string, opt)) { free (string); return 0; @@ -4996,32 +5040,17 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* Dump out the options accumulated previously using %x. */ case 'X': - for (i = 0; i < n_linker_options; i++) - { - do_spec_1 (linker_options[i], 1, NULL); - /* Make each accumulated option a separate argument. */ - do_spec_1 (" ", 0, NULL); - } + do_specs_vec (linker_options); break; /* Dump out the options accumulated previously using -Wa,. */ case 'Y': - for (i = 0; i < n_assembler_options; i++) - { - do_spec_1 (assembler_options[i], 1, NULL); - /* Make each accumulated option a separate argument. */ - do_spec_1 (" ", 0, NULL); - } + do_specs_vec (assembler_options); break; /* Dump out the options accumulated previously using -Wp,. */ case 'Z': - for (i = 0; i < n_preprocessor_options; i++) - { - do_spec_1 (preprocessor_options[i], 1, NULL); - /* Make each accumulated option a separate argument. */ - do_spec_1 (" ", 0, NULL); - } + do_specs_vec (preprocessor_options); break; /* Here are digits and numbers that just process @@ -5138,10 +5167,17 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* Henceforth ignore the option(s) matching the pattern after the %<. */ case '<': + case '>': { unsigned len = 0; int have_wildcard = 0; int i; + int switch_option; + + if (c == '>') + switch_option = SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC; + else + switch_option = SWITCH_IGNORE; while (p[len] && p[len] != ' ' && p[len] != '\t') len++; @@ -5153,7 +5189,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) if (!strncmp (switches[i].part1, p, len - have_wildcard) && (have_wildcard || switches[i].part1[len] == '\0')) { - switches[i].live_cond |= SWITCH_IGNORE; + switches[i].live_cond |= switch_option; switches[i].validated = 1; } @@ -5164,7 +5200,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) case '*': if (soft_matched_part) { - do_spec_1 (soft_matched_part, 1, NULL); + if (soft_matched_part[0]) + do_spec_1 (soft_matched_part, 1, NULL); do_spec_1 (" ", 0, NULL); } else @@ -5176,11 +5213,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* Process a string found as the value of a spec given by name. This feature allows individual machine descriptions - to add and use their own specs. - %[...] modifies -D options the way %P does; - %(...) uses the spec unmodified. */ - case '[': - warning (0, "use of obsolete %%[ operator in specs"); + to add and use their own specs. */ case '(': { const char *name = p; @@ -5189,7 +5222,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* The string after the S/P is the name of a spec that is to be processed. */ - while (*p && *p != ')' && *p != ']') + while (*p && *p != ')') p++; /* See if it's in the list. */ @@ -5198,63 +5231,20 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) { name = *(sl->ptr_spec); #ifdef DEBUG_SPECS - fnotice (stderr, "Processing spec %c%s%c, which is '%s'\n", - c, sl->name, (c == '(') ? ')' : ']', name); + fnotice (stderr, "Processing spec (%s), which is '%s'\n", + sl->name, name); #endif break; } if (sl) { - if (c == '(') - { - value = do_spec_1 (name, 0, NULL); - if (value != 0) - return value; - } - else - { - char *x = (char *) alloca (strlen (name) * 2 + 1); - char *buf = x; - const char *y = name; - int flag = 0; - - /* Copy all of NAME into BUF, but put __ after - every -D and at the end of each arg. */ - while (1) - { - if (! strncmp (y, "-D", 2)) - { - *x++ = '-'; - *x++ = 'D'; - *x++ = '_'; - *x++ = '_'; - y += 2; - flag = 1; - continue; - } - else if (flag - && (*y == ' ' || *y == '\t' || *y == '=' - || *y == '}' || *y == 0)) - { - *x++ = '_'; - *x++ = '_'; - flag = 0; - } - if (*y == 0) - break; - else - *x++ = *y++; - } - *x = 0; - - value = do_spec_1 (buf, 0, NULL); - if (value != 0) - return value; - } + value = do_spec_1 (name, 0, NULL); + if (value != 0) + return value; } - /* Discard the closing paren or bracket. */ + /* Discard the closing paren. */ if (*p) p++; } @@ -5308,9 +5298,7 @@ eval_spec_function (const char *func, const char *args) const char *funcval; /* Saved spec processing context. */ - int save_argbuf_index; - int save_argbuf_length; - const char **save_argbuf; + VEC(const_char_p,heap) *save_argbuf; int save_arg_going; int save_delete_this_arg; @@ -5326,8 +5314,6 @@ eval_spec_function (const char *func, const char *args) fatal_error ("unknown spec function %qs", func); /* Push the spec processing context. */ - save_argbuf_index = argbuf_index; - save_argbuf_length = argbuf_length; save_argbuf = argbuf; save_arg_going = arg_going; @@ -5348,12 +5334,11 @@ eval_spec_function (const char *func, const char *args) /* argbuf_index is an index for the next argument to be inserted, and so contains the count of the args already inserted. */ - funcval = (*sf->func) (argbuf_index, argbuf); + funcval = (*sf->func) (VEC_length (const_char_p, argbuf), + VEC_address (const_char_p, argbuf)); /* Pop the spec processing context. */ - argbuf_index = save_argbuf_index; - argbuf_length = save_argbuf_length; - free (argbuf); + VEC_free (const_char_p, heap, argbuf); argbuf = save_argbuf; arg_going = save_arg_going; @@ -5919,11 +5904,11 @@ is_directory (const char *path1, bool linker) if (linker && IS_DIR_SEPARATOR (path[0]) && ((cp - path == 6 - && strncmp (path + 1, "lib", 3) == 0) + && filename_ncmp (path + 1, "lib", 3) == 0) || (cp - path == 10 - && strncmp (path + 1, "usr", 3) == 0 + && filename_ncmp (path + 1, "usr", 3) == 0 && IS_DIR_SEPARATOR (path[4]) - && strncmp (path + 5, "lib", 3) == 0))) + && filename_ncmp (path + 5, "lib", 3) == 0))) return 0; return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); @@ -6106,6 +6091,7 @@ main (int argc, char **argv) int num_linker_inputs = 0; char *explicit_link_files; char *specs_file; + char *lto_wrapper_file; const char *p; struct user_specs *uptr; char **old_argv = argv; @@ -6129,6 +6115,12 @@ main (int argc, char **argv) if (argv != old_argv) at_file_supplied = true; + /* Register the language-independent parameters. */ + global_init_params (); + finish_params (); + + init_options_struct (&global_options, &global_options_set); + decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **, argv), CL_DRIVER, @@ -6166,6 +6158,10 @@ main (int argc, char **argv) signal (SIGCHLD, SIG_DFL); #endif + /* Parsing and gimplification sometimes need quite large stack. + Increase stack size limits if possible. */ + stack_limit_increase (64 * 1024 * 1024); + /* Allocate the argument vector. */ alloc_args (); @@ -6267,43 +6263,6 @@ main (int argc, char **argv) for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++) do_self_spec (driver_self_specs[i]); - if (compare_debug) - { - enum save_temps save; - - if (!compare_debug_second) - { - n_switches_debug_check[1] = n_switches; - switches_debug_check[1] = XDUPVEC (struct switchstr, switches, - n_switches + 1); - - do_self_spec ("%:compare-debug-self-opt()"); - n_switches_debug_check[0] = n_switches; - switches_debug_check[0] = switches; - - n_switches = n_switches_debug_check[1]; - switches = switches_debug_check[1]; - } - - /* Avoid crash when computing %j in this early. */ - save = save_temps_flag; - save_temps_flag = SAVE_TEMPS_NONE; - - compare_debug = -compare_debug; - do_self_spec ("%:compare-debug-self-opt()"); - - save_temps_flag = save; - - if (!compare_debug_second) - { - n_switches_debug_check[1] = n_switches; - switches_debug_check[1] = switches; - compare_debug = -compare_debug; - n_switches = n_switches_debug_check[0]; - switches = switches_debug_check[0]; - } - } - /* If not cross-compiling, look for executables in the standard places. */ if (*cross_compile == '0') @@ -6319,10 +6278,10 @@ main (int argc, char **argv) if (*sysroot_suffix_spec != 0 && do_spec_2 (sysroot_suffix_spec) == 0) { - if (argbuf_index > 1) + if (VEC_length (const_char_p, argbuf) > 1) error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC"); - else if (argbuf_index == 1) - target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]); + else if (VEC_length (const_char_p, argbuf) == 1) + target_sysroot_suffix = xstrdup (VEC_last (const_char_p, argbuf)); } #ifdef HAVE_LD_SYSROOT @@ -6342,10 +6301,10 @@ main (int argc, char **argv) if (*sysroot_hdrs_suffix_spec != 0 && do_spec_2 (sysroot_hdrs_suffix_spec) == 0) { - if (argbuf_index > 1) + if (VEC_length (const_char_p, argbuf) > 1) error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC"); - else if (argbuf_index == 1) - target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]); + else if (VEC_length (const_char_p, argbuf) == 1) + target_sysroot_hdrs_suffix = xstrdup (VEC_last (const_char_p, argbuf)); } /* Look for startfiles in the standard places. */ @@ -6353,9 +6312,10 @@ main (int argc, char **argv) && do_spec_2 (startfile_prefix_spec) == 0 && do_spec_1 (" ", 0, NULL) == 0) { + const char *arg; int ndx; - for (ndx = 0; ndx < argbuf_index; ndx++) - add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS", + FOR_EACH_VEC_ELT (const_char_p, argbuf, ndx, arg) + add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1); } /* We should eventually get rid of all these and stick to @@ -6412,6 +6372,58 @@ main (int argc, char **argv) read_specs (filename ? filename : uptr->filename, FALSE); } + /* Process any user self specs. */ + { + struct spec_list *sl; + for (sl = specs; sl; sl = sl->next) + if (sl->name_len == sizeof "self_spec" - 1 + && !strcmp (sl->name, "self_spec")) + do_self_spec (*sl->ptr_spec); + } + + if (compare_debug) + { + enum save_temps save; + + if (!compare_debug_second) + { + n_switches_debug_check[1] = n_switches; + n_switches_alloc_debug_check[1] = n_switches_alloc; + switches_debug_check[1] = XDUPVEC (struct switchstr, switches, + n_switches_alloc); + + do_self_spec ("%:compare-debug-self-opt()"); + n_switches_debug_check[0] = n_switches; + n_switches_alloc_debug_check[0] = n_switches_alloc; + switches_debug_check[0] = switches; + + n_switches = n_switches_debug_check[1]; + n_switches_alloc = n_switches_alloc_debug_check[1]; + switches = switches_debug_check[1]; + } + + /* Avoid crash when computing %j in this early. */ + save = save_temps_flag; + save_temps_flag = SAVE_TEMPS_NONE; + + compare_debug = -compare_debug; + do_self_spec ("%:compare-debug-self-opt()"); + + save_temps_flag = save; + + if (!compare_debug_second) + { + n_switches_debug_check[1] = n_switches; + n_switches_alloc_debug_check[1] = n_switches_alloc; + switches_debug_check[1] = switches; + compare_debug = -compare_debug; + n_switches = n_switches_debug_check[0]; + n_switches_alloc = n_switches_debug_check[0]; + switches = switches_debug_check[0]; + } + } + + /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ if (gcc_exec_prefix) gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str, @@ -6436,9 +6448,10 @@ main (int argc, char **argv) /* Set up to remember the pathname of the lto wrapper. */ - lto_wrapper_spec = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false); - if (lto_wrapper_spec) + lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false); + if (lto_wrapper_file) { + lto_wrapper_spec = lto_wrapper_file; obstack_init (&collect_obstack); obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=", sizeof ("COLLECT_LTO_WRAPPER=") - 1); @@ -6555,7 +6568,7 @@ main (int argc, char **argv) { printf (_("%s %s%s\n"), progname, pkgversion_string, version_string); - printf ("Copyright %s 2010 Free Software Foundation, Inc.\n", + printf ("Copyright %s 2011 Free Software Foundation, Inc.\n", _("(C)")); fputs (_("This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), @@ -6613,6 +6626,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (n_infiles == added_libraries) fatal_error ("no input files"); + if (seen_error ()) + goto out; + /* Make a place to record the compiler output file names that correspond to the input files. */ @@ -6695,12 +6711,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" { if (compare_debug) { - if (debug_check_temp_file[0]) - free (debug_check_temp_file[0]); + free (debug_check_temp_file[0]); debug_check_temp_file[0] = NULL; - if (debug_check_temp_file[1]) - free (debug_check_temp_file[1]); + free (debug_check_temp_file[1]); debug_check_temp_file[1] = NULL; } @@ -6715,12 +6729,14 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" compare_debug = -compare_debug; n_switches = n_switches_debug_check[1]; + n_switches_alloc = n_switches_alloc_debug_check[1]; switches = switches_debug_check[1]; value = do_spec (input_file_compiler->spec); compare_debug = -compare_debug; n_switches = n_switches_debug_check[0]; + n_switches_alloc = n_switches_alloc_debug_check[0]; switches = switches_debug_check[0]; if (value < 0) @@ -6730,8 +6746,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" } gcc_assert (debug_check_temp_file[1] - && strcmp (debug_check_temp_file[0], - debug_check_temp_file[1])); + && filename_cmp (debug_check_temp_file[0], + debug_check_temp_file[1])); if (verbose_flag) inform (0, "comparing final insns dumps"); @@ -6742,12 +6758,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (compare_debug) { - if (debug_check_temp_file[0]) - free (debug_check_temp_file[0]); + free (debug_check_temp_file[0]); debug_check_temp_file[0] = NULL; - if (debug_check_temp_file[1]) - free (debug_check_temp_file[1]); + free (debug_check_temp_file[1]); debug_check_temp_file[1] = NULL; } } @@ -6780,7 +6794,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" int i; for (i = 0; i < n_infiles ; i++) - if (infiles[i].language && infiles[i].language[0] != '*') + if (infiles[i].incompiler + || (infiles[i].language && infiles[i].language[0] != '*')) { set_input (infiles[i].name); break; @@ -6807,7 +6822,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2) { int tmp = execution_count; +#if HAVE_LTO_PLUGIN > 0 +#if HAVE_LTO_PLUGIN == 2 + const char *fno_use_linker_plugin = "fno-use-linker-plugin"; +#else const char *fuse_linker_plugin = "fuse-linker-plugin"; +#endif +#endif /* We'll use ld if we can't find collect2. */ if (! strcmp (linker_name_spec, "collect2")) @@ -6817,20 +6838,22 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" linker_name_spec = "ld"; } +#if HAVE_LTO_PLUGIN > 0 +#if HAVE_LTO_PLUGIN == 2 + if (!switch_matches (fno_use_linker_plugin, + fno_use_linker_plugin + strlen (fno_use_linker_plugin), 0)) +#else if (switch_matches (fuse_linker_plugin, fuse_linker_plugin + strlen (fuse_linker_plugin), 0)) +#endif { linker_plugin_file_spec = find_a_file (&exec_prefixes, - "liblto_plugin.so", R_OK, + LTOPLUGINSONAME, R_OK, false); if (!linker_plugin_file_spec) - fatal_error ("-fuse-linker-plugin, but liblto_plugin.so not found"); - - lto_libgcc_spec = find_a_file (&startfile_prefixes, "libgcc.a", - R_OK, true); - if (!lto_libgcc_spec) - fatal_error ("could not find libgcc.a"); + fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found"); } +#endif lto_gcc_spec = argv[0]; /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables @@ -6873,6 +6896,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" printf ("%s\n", bug_report_url); } + out: return (signal_count != 0 ? 2 : seen_error () ? (pass_exit_codes ? greatest_status : 1) : 0); @@ -7625,7 +7649,7 @@ print_multilib_info (void) /* If this is a duplicate, skip it. */ skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len - && ! strncmp (last_path, this_path, last_path_len)); + && ! filename_ncmp (last_path, this_path, last_path_len)); last_path = this_path; last_path_len = p - this_path; @@ -7829,7 +7853,7 @@ replace_outfile_spec_function (int argc, const char **argv) for (i = 0; i < n_infiles; i++) { - if (outfiles[i] && !strcmp (outfiles[i], argv[0])) + if (outfiles[i] && !filename_cmp (outfiles[i], argv[0])) outfiles[i] = xstrdup (argv[1]); } return NULL; @@ -7850,7 +7874,7 @@ remove_outfile_spec_function (int argc, const char **argv) for (i = 0; i < n_infiles; i++) { - if (outfiles[i] && !strcmp (outfiles[i], argv[0])) + if (outfiles[i] && !filename_cmp (outfiles[i], argv[0])) outfiles[i] = NULL; } return NULL; @@ -8084,19 +8108,20 @@ compare_debug_dump_opt_spec_function (int arg, do_spec_2 ("%{fdump-final-insns=*:%*}"); do_spec_1 (" ", 0, NULL); - if (argbuf_index > 0 && strcmp (argv[argbuf_index - 1], ".")) + if (VEC_length (const_char_p, argbuf) > 0 + && strcmp (argv[VEC_length (const_char_p, argbuf) - 1], ".")) { if (!compare_debug) return NULL; - name = xstrdup (argv[argbuf_index - 1]); + name = xstrdup (argv[VEC_length (const_char_p, argbuf) - 1]); ret = NULL; } else { const char *ext = NULL; - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) { do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}"); ext = ".gkd"; @@ -8108,9 +8133,9 @@ compare_debug_dump_opt_spec_function (int arg, do_spec_1 (" ", 0, NULL); - gcc_assert (argbuf_index > 0); + gcc_assert (VEC_length (const_char_p, argbuf) > 0); - name = concat (argbuf[argbuf_index - 1], ext, NULL); + name = concat (VEC_last (const_char_p, argbuf), ext, NULL); ret = concat ("-fdump-final-insns=", name, NULL); } @@ -8154,9 +8179,9 @@ compare_debug_self_opt_spec_function (int arg, do_spec_2 ("%{c|S:%{o*:%*}}"); do_spec_1 (" ", 0, NULL); - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) debug_auxbase_opt = concat ("-auxbase-strip ", - argbuf[argbuf_index - 1], + VEC_last (const_char_p, argbuf), NULL); else debug_auxbase_opt = NULL; @@ -8209,3 +8234,46 @@ compare_debug_auxbase_opt_spec_function (int arg, return name; } + +/* %:pass-through-libs spec function. Finds all -l options and input + file names in the lib spec passed to it, and makes a list of them + prepended with the plugin option to cause them to be passed through + to the final link after all the new object files have been added. */ + +const char * +pass_through_libs_spec_func (int argc, const char **argv) +{ + char *prepended = xstrdup (" "); + int n; + /* Shlemiel the painter's algorithm. Innately horrible, but at least + we know that there will never be more than a handful of strings to + concat, and it's only once per run, so it's not worth optimising. */ + for (n = 0; n < argc; n++) + { + char *old = prepended; + /* Anything that isn't an option is a full path to an output + file; pass it through if it ends in '.a'. Among options, + pass only -l. */ + if (argv[n][0] == '-' && argv[n][1] == 'l') + { + const char *lopt = argv[n] + 2; + /* Handle both joined and non-joined -l options. If for any + reason there's a trailing -l with no joined or following + arg just discard it. */ + if (!*lopt && ++n >= argc) + break; + else if (!*lopt) + lopt = argv[n]; + prepended = concat (prepended, "-plugin-opt=-pass-through=-l", + lopt, " ", NULL); + } + else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2)) + { + prepended = concat (prepended, "-plugin-opt=-pass-through=", + argv[n], " ", NULL); + } + if (prepended != old) + free (old); + } + return prepended; +}