Mercurial > hg > CbC > CbC_gcc
diff gcc/gcc.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | d34655255c78 1830386684a0 |
line wrap: on
line diff
--- a/gcc/gcc.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/gcc.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Compiler driver program that can handle many languages. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -36,6 +36,7 @@ #include "obstack.h" #include "intl.h" #include "prefix.h" +#include "opt-suggestions.h" #include "gcc.h" #include "diagnostic.h" #include "flags.h" @@ -170,9 +171,10 @@ /* By default there is no special suffix for target executables. */ -/* FIXME: when autoconf is fixed, remove the host check - dj */ -#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX) +#ifdef TARGET_EXECUTABLE_SUFFIX #define HAVE_TARGET_EXECUTABLE_SUFFIX +#else +#define TARGET_EXECUTABLE_SUFFIX "" #endif /* By default there is no special suffix for host executables. */ @@ -219,6 +221,10 @@ static int print_version; +/* Flag that stores string prefix for which we provide bash completion. */ + +static const char *completion = NULL; + /* 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 @@ -349,12 +355,12 @@ static inline void process_marked_switches (void); static const char *process_brace_body (const char *, const char *, const char *, int, int); static const struct spec_function *lookup_spec_function (const char *); -static const char *eval_spec_function (const char *, const char *); -static const char *handle_spec_function (const char *, bool *); +static const char *eval_spec_function (const char *, const char *, const char *); +static const char *handle_spec_function (const char *, bool *, const char *); static char *save_string (const char *, int); static void set_collect_gcc_options (void); static int do_spec_1 (const char *, int, const char *); -static int do_spec_2 (const char *); +static int do_spec_2 (const char *, const char *); static void do_option_spec (const char *, const char *); static void do_self_spec (const char *); static const char *find_file (const char *); @@ -366,7 +372,6 @@ static int default_arg (const char *, int); static void set_multilib_dir (void); static void print_multilib_info (void); -static void perror_with_name (const char *); static void display_help (void); static void add_preprocessor_option (const char *, int); static void add_assembler_option (const char *, int); @@ -475,8 +480,11 @@ into the sequence of arguments that %o will substitute later. %V indicates that this compilation produces no "output file". %W{...} - like %{...} but mark last argument supplied within - as a file to be deleted on failure. + like %{...} but marks the last argument supplied within as a file + to be deleted on failure. + %@{...} + like %{...} but puts the result into a FILE and substitutes @FILE + if an @file argument has been supplied. %o substitutes the names of all the output files, with spaces automatically placed around them. You should write spaces around the %o as well or the results are undefined. @@ -683,7 +691,7 @@ #ifndef LIBASAN_SPEC #define STATIC_LIBASAN_LIBS \ - " %{static-libasan:%:include(libsanitizer.spec)%(link_libasan)}" + " %{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)}" #ifdef LIBASAN_EARLY_SPEC #define LIBASAN_SPEC STATIC_LIBASAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) @@ -701,7 +709,7 @@ #ifndef LIBTSAN_SPEC #define STATIC_LIBTSAN_LIBS \ - " %{static-libtsan:%:include(libsanitizer.spec)%(link_libtsan)}" + " %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}" #ifdef LIBTSAN_EARLY_SPEC #define LIBTSAN_SPEC STATIC_LIBTSAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) @@ -719,7 +727,7 @@ #ifndef LIBLSAN_SPEC #define STATIC_LIBLSAN_LIBS \ - " %{static-liblsan:%:include(libsanitizer.spec)%(link_liblsan)}" + " %{static-liblsan|static:%:include(libsanitizer.spec)%(link_liblsan)}" #ifdef LIBLSAN_EARLY_SPEC #define LIBLSAN_SPEC STATIC_LIBLSAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) @@ -737,7 +745,7 @@ #ifndef LIBUBSAN_SPEC #define STATIC_LIBUBSAN_LIBS \ - " %{static-libubsan:%:include(libsanitizer.spec)%(link_libubsan)}" + " %{static-libubsan|static:%:include(libsanitizer.spec)%(link_libubsan)}" #ifdef HAVE_LD_STATIC_DYNAMIC #define LIBUBSAN_SPEC "%{static-libubsan:" LD_STATIC_OPTION \ "} -lubsan %{static-libubsan:" LD_DYNAMIC_OPTION "}" \ @@ -863,7 +871,7 @@ -lgcc and -lc order specially, yet not require them to override all of LINK_COMMAND_SPEC. */ #ifndef LINK_GCC_C_SEQUENCE_SPEC -#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G" +#define LINK_GCC_C_SEQUENCE_SPEC "%G %{!nolibc:%L %G}" #endif #ifndef LINK_SSP_SPEC @@ -960,6 +968,7 @@ -plugin %(linker_plugin_file) \ -plugin-opt=%(lto_wrapper) \ -plugin-opt=-fresolution=%u.res \ + %{flinker-output=*:-plugin-opt=-linker-output-known} \ %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \ }" PLUGIN_COND_CLOSE #else @@ -971,20 +980,20 @@ /* Linker command line options for -fsanitize= early on the command line. */ #ifndef SANITIZER_EARLY_SPEC #define SANITIZER_EARLY_SPEC "\ -%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \ +%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \ %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \ - %{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}" + %{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}}" #endif /* Linker command line options for -fsanitize= late on the command line. */ #ifndef SANITIZER_SPEC #define SANITIZER_SPEC "\ -%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\ +%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\ %{static:%ecannot specify -static with -fsanitize=address}}\ %{%:sanitize(thread):" LIBTSAN_SPEC "\ %{static:%ecannot specify -static with -fsanitize=thread}}\ %{%:sanitize(undefined):" LIBUBSAN_SPEC "}\ - %{%:sanitize(leak):" LIBLSAN_SPEC "}}}" + %{%:sanitize(leak):" LIBLSAN_SPEC "}}}}" #endif #ifndef POST_LINK_SPEC @@ -998,8 +1007,8 @@ #ifndef VTABLE_VERIFICATION_SPEC #if ENABLE_VTABLE_VERIFY #define VTABLE_VERIFICATION_SPEC "\ -%{!nostdlib:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}\ - %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}" +%{!nostdlib:%{!r:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}\ + %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}}" #else #define VTABLE_VERIFICATION_SPEC "\ %{fvtable-verify=none:} \ @@ -1010,10 +1019,6 @@ #endif #endif -#ifndef CHKP_SPEC -#define CHKP_SPEC "" -#endif - /* -u* was put back because both BSD and SysV seem to support it. */ /* %{static|no-pie|static-pie:} simply prevents an error message: 1. If the target machine doesn't handle -static. @@ -1035,17 +1040,16 @@ %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \ "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \ "%X %{o*} %{e*} %{N} %{n} %{r}\ - %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} \ - %{static|no-pie|static-pie:} %{L*} %(mfwrap) %(link_libgcc) " \ - VTABLE_VERIFICATION_SPEC " " SANITIZER_EARLY_SPEC " %o " CHKP_SPEC " \ + %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!r:%{!nostartfiles:%S}}} \ + %{static|no-pie|static-pie:} %@{L*} %(mfwrap) %(link_libgcc) " \ + VTABLE_VERIFICATION_SPEC " " SANITIZER_EARLY_SPEC " %o "" \ %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\ %:include(libgomp.spec)%(link_gomp)}\ - %{fcilkplus:%:include(libcilkrts.spec)%(link_cilkrts)}\ %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\ %(mflib) " STACK_SPLIT_SPEC "\ %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} " SANITIZER_SPEC " \ - %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\ - %{!nostdlib:%{!nostartfiles:%E}} %{T*} \n%(post_link) }}}}}}" + %{!nostdlib:%{!r:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}}\ + %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} \n%(post_link) }}}}}}" #endif #ifndef LINK_LIBGCC_SPEC @@ -1112,12 +1116,12 @@ therefore no dependency entry, confuses make into thinking a .o file that happens to exist is up-to-date. */ static const char *cpp_unique_options = -"%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\ +"%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %@{I*&F*} %{P} %I\ %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\ %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\ %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\ %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\ - %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\ + %{remap} %{g3|ggdb3|gstabs3|gxcoff3|gvms3:-dD}\ %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\ %{H} %C %{D*&U*&A*} %{i*} %Z %i\ %{E|M|MM:%W{o*}}"; @@ -1215,15 +1219,9 @@ #define GTM_SELF_SPECS "%{fgnu-tm: -pthread}" #endif -/* Likewise for -fcilkplus. */ -#ifndef CILK_SELF_SPECS -#define CILK_SELF_SPECS "%{fcilkplus: -pthread}" -#endif - static const char *const driver_self_specs[] = { "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns", - DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS, - CILK_SELF_SPECS + DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS }; #ifndef OPTION_DEFAULT_SPECS @@ -1933,9 +1931,14 @@ typedef const char *const_char_p; /* For DEF_VEC_P. */ /* Vector of pointers to arguments in the current line of specifications. */ - static vec<const_char_p> argbuf; +/* Likewise, but for the current @file. */ +static vec<const_char_p> at_file_argbuf; + +/* Whether an @file is currently open. */ +static bool in_at_file = false; + /* Were the options -c, -S or -E passed. */ static int have_c = 0; @@ -1975,6 +1978,7 @@ alloc_args (void) { argbuf.create (10); + at_file_argbuf.create (10); } /* Clear out the vector of arguments (after a command is executed). */ @@ -1983,6 +1987,7 @@ clear_args (void) { argbuf.truncate (0); + at_file_argbuf.truncate (0); } /* Add one argument to the vector at the end. @@ -1995,7 +2000,10 @@ static void store_arg (const char *arg, int delete_always, int delete_failure) { - argbuf.safe_push (arg); + if (in_at_file) + at_file_argbuf.safe_push (arg); + else + argbuf.safe_push (arg); if (delete_always || delete_failure) { @@ -2008,6 +2016,67 @@ record_temp_file (arg, delete_always, delete_failure); } } + +/* Open a temporary @file into which subsequent arguments will be stored. */ + +static void +open_at_file (void) +{ + if (in_at_file) + fatal_error (input_location, "cannot open nested response file"); + else + in_at_file = true; +} + +/* Close the temporary @file and add @file to the argument list. */ + +static void +close_at_file (void) +{ + if (!in_at_file) + fatal_error (input_location, "cannot close nonexistent response file"); + + in_at_file = false; + + const unsigned int n_args = at_file_argbuf.length (); + if (n_args == 0) + return; + + char **argv = (char **) alloca (sizeof (char *) * (n_args + 1)); + char *temp_file = make_temp_file (""); + char *at_argument = concat ("@", temp_file, NULL); + FILE *f = fopen (temp_file, "w"); + int status; + unsigned int i; + + /* Copy the strings over. */ + for (i = 0; i < n_args; i++) + argv[i] = CONST_CAST (char *, at_file_argbuf[i]); + argv[i] = NULL; + + at_file_argbuf.truncate (0); + + if (f == NULL) + fatal_error (input_location, "could not open temporary response file %s", + temp_file); + + status = writeargv (argv, f); + + if (status) + fatal_error (input_location, + "could not write to temporary response file %s", + temp_file); + + status = fclose (f); + + if (status == EOF) + fatal_error (input_location, "could not close temporary response file %s", + temp_file); + + store_arg (at_argument, 0, 0); + + record_temp_file (temp_file, !save_temps_flag, !save_temps_flag); +} /* Load specs from a file name named FILENAME, replacing occurrences of various different types of line-endings, \r\n, \n\r and just \r, with @@ -2030,15 +2099,20 @@ /* Open and stat the file. */ desc = open (filename, O_RDONLY, 0); if (desc < 0) - pfatal_with_name (filename); + { + failed: + /* This leaves DESC open, but the OS will save us. */ + fatal_error (input_location, "cannot read spec file %qs: %m", filename); + } + if (stat (filename, &statbuf) < 0) - pfatal_with_name (filename); + goto failed; /* Read contents of file into BUFFER. */ buffer = XNEWVEC (char, statbuf.st_size + 1); readlen = read (desc, buffer, (unsigned) statbuf.st_size); if (readlen < 0) - pfatal_with_name (filename); + goto failed; buffer[readlen] = 0; close (desc); @@ -2419,7 +2493,7 @@ if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode)) \ if (unlink (NAME) < 0) \ if (VERBOSE_FLAG) \ - perror_with_name (NAME); \ + error ("%s: %m", (NAME)); \ } while (0) #endif @@ -3098,13 +3172,11 @@ NULL, NULL, &err); if (errmsg != NULL) { - if (err == 0) - fatal_error (input_location, errmsg); - else - { - errno = err; - pfatal_with_name (errmsg); - } + errno = err; + fatal_error (input_location, + err ? G_("cannot execute %qs: %s: %m") + : G_("cannot execute %qs: %s"), + string, errmsg); } if (i && string != commands[i].prog) @@ -3824,6 +3896,11 @@ add_linker_option ("--version", strlen ("--version")); break; + case OPT__completion_: + validated = true; + completion = decoded->arg; + break; + case OPT__help: print_help_list = 1; @@ -4469,10 +4546,8 @@ if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0) { - if (fname[0] == '@' && access (fname + 1, F_OK) < 0) - perror_with_name (fname + 1); - else - perror_with_name (fname); + bool resp = fname[0] == '@' && access (fname + 1, F_OK) < 0; + error ("%s: %m", fname + resp); } else add_infile (arg, spec_lang); @@ -4864,7 +4939,7 @@ { int value; - value = do_spec_2 (spec); + value = do_spec_2 (spec, NULL); /* Force out any unfinished command. If -pipe, this forces out the last command if it ended in `|'. */ @@ -4883,8 +4958,11 @@ return value; } +/* Process the spec SPEC, with SOFT_MATCHED_PART designating the current value + of a matched * pattern which may be re-injected by way of %*. */ + static int -do_spec_2 (const char *spec) +do_spec_2 (const char *spec, const char *soft_matched_part) { int result; @@ -4897,14 +4975,13 @@ input_from_pipe = 0; suffix_subst = NULL; - result = do_spec_1 (spec, 0, NULL); + result = do_spec_1 (spec, 0, soft_matched_part); end_going_arg (); return result; } - /* Process the given spec string and add any new options to the end of the switches/n_switches array. */ @@ -4962,7 +5039,7 @@ { int i; - do_spec_2 (spec); + do_spec_2 (spec, NULL); do_spec_1 (" ", 0, NULL); /* Mark %<S switches processed by do_self_spec to be ignored permanently. @@ -5090,39 +5167,6 @@ return NULL; } -/* Create a temporary FILE with the contents of ARGV. Add @FILE to the - argument list. */ - -static void -create_at_file (char **argv) -{ - char *temp_file = make_temp_file (""); - char *at_argument = concat ("@", temp_file, NULL); - FILE *f = fopen (temp_file, "w"); - int status; - - if (f == NULL) - fatal_error (input_location, "could not open temporary response file %s", - temp_file); - - status = writeargv (argv, f); - - if (status) - fatal_error (input_location, - "could not write to temporary response file %s", - temp_file); - - status = fclose (f); - - if (EOF == status) - fatal_error (input_location, "could not close temporary response file %s", - temp_file); - - store_arg (at_argument, 0, 0); - - record_temp_file (temp_file, !save_temps_flag, !save_temps_flag); -} - /* True if we should compile INFILE. */ static bool @@ -5314,7 +5358,7 @@ buf = (char *) alloca (p - q + 1); strncpy (buf, q, p - q); buf[p - q] = 0; - inform (0, "%s", _(buf)); + inform (UNKNOWN_LOCATION, "%s", _(buf)); if (*p) p++; } @@ -5535,41 +5579,22 @@ case 'i': if (combine_inputs) { + /* We are going to expand `%i' into `@FILE', where FILE + is a newly-created temporary filename. The filenames + that would usually be expanded in place of %o will be + written to the temporary file. */ if (at_file_supplied) - { - /* We are going to expand `%i' to `@FILE', where FILE - is a newly-created temporary filename. The filenames - that would usually be expanded in place of %o will be - written to the temporary file. */ - char **argv; - int n_files = 0; - int j; - - for (i = 0; i < n_infiles; i++) - if (compile_input_file_p (&infiles[i])) - n_files++; - - argv = (char **) alloca (sizeof (char *) * (n_files + 1)); - - /* Copy the strings over. */ - for (i = 0, j = 0; i < n_infiles; i++) - if (compile_input_file_p (&infiles[i])) - { - argv[j] = CONST_CAST (char *, infiles[i].name); - infiles[i].compiled = true; - j++; - } - argv[j] = NULL; - - create_at_file (argv); - } - else - for (i = 0; (int) i < n_infiles; i++) - if (compile_input_file_p (&infiles[i])) - { - store_arg (infiles[i].name, 0, 0); - infiles[i].compiled = true; - } + open_at_file (); + + for (i = 0; (int) i < n_infiles; i++) + if (compile_input_file_p (&infiles[i])) + { + store_arg (infiles[i].name, 0, 0); + infiles[i].compiled = true; + } + + if (at_file_supplied) + close_at_file (); } else { @@ -5642,45 +5667,20 @@ break; case 'o': - { - int max = n_infiles; - max += lang_specific_extra_outfiles; - - if (HAVE_GNU_LD && at_file_supplied) - { - /* We are going to expand `%o' to `@FILE', where FILE - is a newly-created temporary filename. The filenames - that would usually be expanded in place of %o will be - written to the temporary file. */ - - char **argv; - int n_files, j; - - /* Convert OUTFILES into a form suitable for writeargv. */ - - /* Determine how many are non-NULL. */ - for (n_files = 0, i = 0; i < max; i++) - n_files += outfiles[i] != NULL; - - argv = (char **) alloca (sizeof (char *) * (n_files + 1)); - - /* Copy the strings over. */ - for (i = 0, j = 0; i < max; i++) - if (outfiles[i]) - { - argv[j] = CONST_CAST (char *, outfiles[i]); - j++; - } - argv[j] = NULL; - - create_at_file (argv); - } - else - for (i = 0; i < max; i++) - if (outfiles[i]) - store_arg (outfiles[i], 0, 0); - break; - } + /* We are going to expand `%o' into `@FILE', where FILE + is a newly-created temporary filename. The filenames + that would usually be expanded in place of %o will be + written to the temporary file. */ + if (at_file_supplied) + open_at_file (); + + for (i = 0; i < n_infiles + lang_specific_extra_outfiles; i++) + if (outfiles[i]) + store_arg (outfiles[i], 0, 0); + + if (at_file_supplied) + close_at_file (); + break; case 'O': obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); @@ -5721,6 +5721,20 @@ break; } + case '@': + /* Handle the {...} following the %@. */ + if (*p != '{') + fatal_error (input_location, + "spec %qs has invalid %<%%@%c%>", spec, *p); + if (at_file_supplied) + open_at_file (); + p = handle_braces (p + 1); + if (at_file_supplied) + close_at_file (); + if (p == 0) + return -1; + break; + /* %x{OPTION} records OPTION for %X to output. */ case 'x': { @@ -5865,7 +5879,7 @@ break; case ':': - p = handle_spec_function (p, NULL); + p = handle_spec_function (p, NULL, soft_matched_part); if (p == 0) return -1; break; @@ -6027,7 +6041,8 @@ /* Evaluate a spec function. */ static const char * -eval_spec_function (const char *func, const char *args) +eval_spec_function (const char *func, const char *args, + const char *soft_matched_part) { const struct spec_function *sf; const char *funcval; @@ -6077,7 +6092,7 @@ arguments. */ alloc_args (); - if (do_spec_2 (args) < 0) + if (do_spec_2 (args, soft_matched_part) < 0) fatal_error (input_location, "error in args to spec function %qs", func); /* argbuf_index is an index for the next argument to be inserted, and @@ -6114,10 +6129,14 @@ NULL if no processing is required. If RETVAL_NONNULL is not NULL, then store a bool whether function - returned non-NULL. */ + returned non-NULL. + + SOFT_MATCHED_PART holds the current value of a matched * pattern, which + may be re-expanded with a %* as part of the function arguments. */ static const char * -handle_spec_function (const char *p, bool *retval_nonnull) +handle_spec_function (const char *p, bool *retval_nonnull, + const char *soft_matched_part) { char *func, *args; const char *endp, *funcval; @@ -6160,7 +6179,7 @@ /* p now points to just past the end of the spec function expression. */ - funcval = eval_spec_function (func, args); + funcval = eval_spec_function (func, args, soft_matched_part); if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0) p = NULL; if (retval_nonnull) @@ -6314,7 +6333,7 @@ { atom = NULL; end_atom = NULL; - p = handle_spec_function (p + 2, &a_matched); + p = handle_spec_function (p + 2, &a_matched, NULL); } else { @@ -6866,13 +6885,11 @@ err_temp, &err); if (errmsg != NULL) { - if (err == 0) - fatal_error (input_location, errmsg); - else - { - errno = err; - pfatal_with_name (errmsg); - } + errno = err; + fatal_error (input_location, + err ? G_ ("cannot execute %qs: %s: %m") + : G_ ("cannot execute %qs: %s"), + new_argv[0], errmsg); } if (!pex_get_status (pex, 1, &exit_status)) @@ -7041,8 +7058,8 @@ /* In final attempt we append compiler options and preprocesssed code to last generated .out file with configuration and backtrace. */ - char **output = &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]; - do_report_bug (new_argv, nargs, stderr_commented, output); + char **err = &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1]; + do_report_bug (new_argv, nargs, stderr_commented, err); } out: @@ -7268,8 +7285,7 @@ driver::driver (bool can_finalize, bool debug) : explicit_link_files (NULL), - decoded_options (NULL), - m_option_suggestions (NULL) + decoded_options (NULL) { env.init (can_finalize, debug); } @@ -7278,14 +7294,6 @@ { XDELETEVEC (explicit_link_files); XDELETEVEC (decoded_options); - if (m_option_suggestions) - { - int i; - char *str; - FOR_EACH_VEC_ELT (*m_option_suggestions, i, str) - free (str); - delete m_option_suggestions; - } } /* driver::main is implemented as a series of driver:: method calls. */ @@ -7306,6 +7314,12 @@ maybe_putenv_OFFLOAD_TARGETS (); handle_unrecognized_options (); + if (completion) + { + m_option_proposer.suggest_completion (completion); + return 0; + } + if (!maybe_print_and_exit ()) return 0; @@ -7552,7 +7566,7 @@ /* Process sysroot_suffix_spec. */ if (*sysroot_suffix_spec != 0 && !no_sysroot_suffix - && do_spec_2 (sysroot_suffix_spec) == 0) + && do_spec_2 (sysroot_suffix_spec, NULL) == 0) { if (argbuf.length () > 1) error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC"); @@ -7576,7 +7590,7 @@ /* Process sysroot_hdrs_suffix_spec. */ if (*sysroot_hdrs_suffix_spec != 0 && !no_sysroot_suffix - && do_spec_2 (sysroot_hdrs_suffix_spec) == 0) + && do_spec_2 (sysroot_hdrs_suffix_spec, NULL) == 0) { if (argbuf.length () > 1) error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC"); @@ -7586,7 +7600,7 @@ /* Look for startfiles in the standard places. */ if (*startfile_prefix_spec != 0 - && do_spec_2 (startfile_prefix_spec) == 0 + && do_spec_2 (startfile_prefix_spec, NULL) == 0 && do_spec_1 (" ", 0, NULL) == 0) { const char *arg; @@ -7774,106 +7788,6 @@ offload_targets = NULL; } -/* Helper function for driver::suggest_option. Populate - m_option_suggestions with candidate strings for misspelled options. - The strings will be freed by the driver's dtor. */ - -void -driver::build_option_suggestions (void) -{ - gcc_assert (m_option_suggestions == NULL); - m_option_suggestions = new auto_vec <char *> (); - - /* We build a vec of m_option_suggestions, using add_misspelling_candidates - to add copies of strings, without a leading dash. */ - - for (unsigned int i = 0; i < cl_options_count; i++) - { - const struct cl_option *option = &cl_options[i]; - const char *opt_text = option->opt_text; - switch (i) - { - default: - if (option->var_type == CLVC_ENUM) - { - const struct cl_enum *e = &cl_enums[option->var_enum]; - for (unsigned j = 0; e->values[j].arg != NULL; j++) - { - char *with_arg = concat (opt_text, e->values[j].arg, NULL); - add_misspelling_candidates (m_option_suggestions, option, - with_arg); - free (with_arg); - } - } - else - add_misspelling_candidates (m_option_suggestions, option, - opt_text); - break; - - case OPT_fsanitize_: - case OPT_fsanitize_recover_: - /* -fsanitize= and -fsanitize-recover= can take - a comma-separated list of arguments. Given that combinations - are supported, we can't add all potential candidates to the - vec, but if we at least add them individually without commas, - we should do a better job e.g. correcting - "-sanitize=address" - to - "-fsanitize=address" - rather than to "-Wframe-address" (PR driver/69265). */ - { - for (int j = 0; sanitizer_opts[j].name != NULL; ++j) - { - struct cl_option optb; - /* -fsanitize=all is not valid, only -fno-sanitize=all. - So don't register the positive misspelling candidates - for it. */ - if (sanitizer_opts[j].flag == ~0U && i == OPT_fsanitize_) - { - optb = *option; - optb.opt_text = opt_text = "-fno-sanitize="; - optb.cl_reject_negative = true; - option = &optb; - } - /* Get one arg at a time e.g. "-fsanitize=address". */ - char *with_arg = concat (opt_text, - sanitizer_opts[j].name, - NULL); - /* Add with_arg and all of its variant spellings e.g. - "-fno-sanitize=address" to candidates (albeit without - leading dashes). */ - add_misspelling_candidates (m_option_suggestions, option, - with_arg); - free (with_arg); - } - } - break; - } - } -} - -/* Helper function for driver::handle_unrecognized_options. - - Given an unrecognized option BAD_OPT (without the leading dash), - locate the closest reasonable matching option (again, without the - leading dash), or NULL. - - The returned string is owned by the driver instance. */ - -const char * -driver::suggest_option (const char *bad_opt) -{ - /* Lazily populate m_option_suggestions. */ - if (!m_option_suggestions) - build_option_suggestions (); - gcc_assert (m_option_suggestions); - - /* "m_option_suggestions" is now populated. Use it. */ - return find_closest_string - (bad_opt, - (auto_vec <const char *> *) m_option_suggestions); -} - /* Reject switches that no pass was interested in. */ void @@ -7882,7 +7796,7 @@ for (size_t i = 0; (int) i < n_switches; i++) if (! switches[i].validated) { - const char *hint = suggest_option (switches[i].part1); + const char *hint = m_option_proposer.suggest_option (switches[i].part1); if (hint) error ("unrecognized command line option %<-%s%>;" " did you mean %<-%s%>?", @@ -8041,7 +7955,7 @@ { printf (_("%s %s%s\n"), progname, pkgversion_string, version_string); - printf ("Copyright %s 2017 Free Software Foundation, Inc.\n", + printf ("Copyright %s 2018 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"), @@ -8191,7 +8105,8 @@ else if (compare_debug && debug_check_temp_file[0]) { if (verbose_flag) - inform (0, "recompiling with -fcompare-debug"); + inform (UNKNOWN_LOCATION, + "recompiling with -fcompare-debug"); compare_debug = -compare_debug; n_switches = n_switches_debug_check[1]; @@ -8216,7 +8131,7 @@ debug_check_temp_file[1])); if (verbose_flag) - inform (0, "comparing final insns dumps"); + inform (UNKNOWN_LOCATION, "comparing final insns dumps"); if (compare_files (debug_check_temp_file)) this_file_error = 1; @@ -8489,19 +8404,6 @@ return result; } -void -pfatal_with_name (const char *name) -{ - perror_with_name (name); - delete_temp_files (); - exit (1); -} - -static void -perror_with_name (const char *name) -{ - error ("%s: %m", name); -} static inline void validate_switches_from_spec (const char *spec, bool user) @@ -8509,7 +8411,11 @@ const char *p = spec; char c; while ((c = *p++)) - if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{'))) + if (c == '%' + && (*p == '{' + || *p == '<' + || (*p == 'W' && *++p == '{') + || (*p == '@' && *++p == '{'))) /* We have a switch spec. */ p = validate_switches (p + 1, user); } @@ -8591,6 +8497,8 @@ p = validate_switches (p+1, user_spec); else if (p[0] == 'W' && p[1] == '{') p = validate_switches (p+2, user_spec); + else if (p[0] == '@' && p[1] == '{') + p = validate_switches (p+2, user_spec); } else p++; @@ -9328,7 +9236,11 @@ Returns the value of the environment variable given by its first argument, concatenated with the second argument. If the variable is not defined, a fatal error is issued unless such undefs are internally allowed, in which - case the variable name is used as the variable value. */ + case the variable name prefixed by a '/' is used as the variable value. + + The leading '/' allows using the result at a spot where a full path would + normally be expected and when the actual value doesn't really matter since + undef vars are allowed. */ static const char * getenv_spec_function (int argc, const char **argv) @@ -9346,8 +9258,15 @@ varname = argv[0]; value = env.get (varname); + /* If the variable isn't defined and this is allowed, craft our expected + return value. Assume variable names used in specs strings don't contain + any active spec character so don't need escaping. */ if (!value && spec_undefvar_allowed) - value = varname; + { + result = XNEWVAR (char, strlen(varname) + 2); + sprintf (result, "/%s", varname); + return result; + } if (!value) fatal_error (input_location, @@ -9713,7 +9632,7 @@ fatal_error (input_location, "too many arguments to %%:compare-debug-dump-opt"); - do_spec_2 ("%{fdump-final-insns=*:%*}"); + do_spec_2 ("%{fdump-final-insns=*:%*}", NULL); do_spec_1 (" ", 0, NULL); if (argbuf.length () > 0 @@ -9731,13 +9650,13 @@ if (argbuf.length () > 0) { - do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}"); + do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}", NULL); ext = ".gkd"; } else if (!compare_debug) return NULL; else - do_spec_2 ("%g.gkd"); + do_spec_2 ("%g.gkd", NULL); do_spec_1 (" ", 0, NULL); @@ -9789,7 +9708,7 @@ if (compare_debug >= 0) return NULL; - do_spec_2 ("%{c|S:%{o*:%*}}"); + do_spec_2 ("%{c|S:%{o*:%*}}", NULL); do_spec_1 (" ", 0, NULL); if (argbuf.length () > 0) @@ -10149,7 +10068,7 @@ processing_spec_function = 0; - argbuf.truncate (0); + clear_args (); have_c = 0; have_o = 0;