/* 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, 2011
+ 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC.
#include "diagnostic.h"
#include "flags.h"
#include "opts.h"
+#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 */
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 **);
+static char *convert_white_space (char *);
\f
/* The Specs Language
This may be combined with '.', '!', ',', '|', and '*' as above.
%(Spec) processes a specification defined in a specs file as *Spec:
- %[Spec] as above, but put __ around -D arguments
The conditional text X in a %{S:X} or similar construct may contain
other nested % constructs or spaces, or even newlines. They are
/* XXX: should exactly match hooks provided by libmudflap.a */
#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
--wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
- --wrap=mmap --wrap=munmap --wrap=alloca\
+ --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca\
} %{fmudflapth: --wrap=pthread_create\
}} %{fmudflap|fmudflapth: --wrap=main}"
#endif
# endif
#endif
-/* Conditional to test whether plugin is used or not.
+/* Conditional to test whether the LTO plugin is used or not.
FIXME: For slim LTO we will need to enable plugin unconditionally. This
still cause problems with PLUGIN_LD != LD and when plugin is built but
not useable. For GCC 4.6 we don't support slim LTO and thus we can enable
plugin only when LTO is enabled. We still honor explicit
- -fuse-linker-plugin. */
-#ifdef HAVE_LTO_PLUGIN
+ -fuse-linker-plugin if the linker used understands -plugin. */
+
+/* The linker has some plugin support. */
+#if HAVE_LTO_PLUGIN > 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. */
directories. */
/* 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) \
- %{"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" \
- %{flto|flto=*:%<fcompare-debug*} \
+ %(linker) " \
+ LINK_PLUGIN_SPEC \
+ "%{flto|flto=*:%<fcompare-debug*} \
%{flto} %{flto=*} %l " LINK_PIE_SPEC \
"%X %{o*} %{e*} %{N} %{n} %{r}\
%{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
%{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
%{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+ %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
%(mflib) " STACK_SPLIT_SPEC "\
%{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
%{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
static const char *sysroot_spec = SYSROOT_SPEC;
static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
+static const char *self_spec = "";
/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
There should be no need to override these in target dependent files,
%{coverage:-fprofile-arcs -ftest-coverage}";
static const char *asm_options =
-"%{--target-help:%:print-asm-header()} "
+"%{-target-help:%:print-asm-header()} "
#if HAVE_GNU_AS
/* If GNU AS is used, then convert -w (no warnings), -I, and -v
to the assembler equivalents. */
#define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
#endif
+/* Likewise for -fgnu-tm. */
+#ifndef GTM_SELF_SPECS
+#define GTM_SELF_SPECS "%{fgnu-tm: -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
+ DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS
};
#ifndef OPTION_DEFAULT_SPECS
%W{o*:--output-pch=%*}}%V}}}}}}", 0, 0, 0},
{".i", "@cpp-output", 0, 0, 0},
{"@cpp-output",
- "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
+ "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
{".s", "@assembler", 0, 0, 0},
{"@assembler",
"%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0},
set_multilib_dir based on the compilation options. */
static const char *multilib_os_dir;
+
+/* Subdirectory to use for locating libraries in multiarch conventions. Set by
+ set_multilib_dir based on the compilation options. */
+
+static const char *multiarch_dir;
\f
/* Structure to keep track of the specs that have been defined so far.
- These are accessed using %(specname) or %[specname] in a compiler
- or link spec. */
+ These are accessed using %(specname) in a compiler or link
+ spec. */
struct spec_list
{
INIT_STATIC_SPEC ("sysroot_spec", &sysroot_spec),
INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec),
INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec),
+ INIT_STATIC_SPEC ("self_spec", &self_spec),
};
#ifdef EXTRA_SPECS /* additional specs needed */
}
#endif
-#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC
+#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC || \
+ defined LINKER_HASH_STYLE
# ifdef LINK_BUILDID_SPEC
/* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before. */
obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof(LINK_BUILDID_SPEC) - 1);
/* Prepend LINK_EH_SPEC to whatever link_spec we had before. */
obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
# endif
+# ifdef LINKER_HASH_STYLE
+ /* Prepend --hash-style=LINKER_HASH_STYLE to whatever link_spec we had
+ before. */
+ {
+ static const char hash_style[] = "--hash-style=";
+ obstack_grow (&obstack, hash_style, sizeof(hash_style) - 1);
+ obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof(LINKER_HASH_STYLE) - 1);
+ obstack_1grow (&obstack, ' ');
+ }
+# endif
obstack_grow0 (&obstack, link_spec, strlen (link_spec));
link_spec = XOBFINISH (&obstack, const char *);
#endif
{
struct temp_file *temp;
for (temp = always_delete_queue; temp; temp = temp->next)
- if (! strcmp (name, temp->name))
+ if (! filename_cmp (name, temp->name))
goto already1;
temp = XNEW (struct temp_file);
{
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);
struct prefix_list *pl;
const char *multi_dir = NULL;
const char *multi_os_dir = NULL;
+ const char *multiarch_suffix = NULL;
const char *multi_suffix;
const char *just_multi_suffix;
char *path = NULL;
}
if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+ if (multiarch_dir)
+ multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
while (1)
{
size_t multi_dir_len = 0;
size_t multi_os_dir_len = 0;
+ size_t multiarch_len = 0;
size_t suffix_len;
size_t just_suffix_len;
size_t len;
multi_dir_len = strlen (multi_dir);
if (multi_os_dir)
multi_os_dir_len = strlen (multi_os_dir);
+ if (multiarch_suffix)
+ multiarch_len = strlen (multiarch_suffix);
suffix_len = strlen (multi_suffix);
just_suffix_len = strlen (just_multi_suffix);
if (path == NULL)
{
len = paths->max_len + extra_space + 1;
- if (suffix_len > multi_os_dir_len)
- len += suffix_len;
- else
- len += multi_os_dir_len;
+ len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
path = XNEWVEC (char, len);
}
break;
}
+ /* Now try the multiarch path. */
+ if (!skip_multi_dir
+ && !pl->require_machine_suffix && multiarch_dir)
+ {
+ memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
+
/* Now try the base path. */
if (!pl->require_machine_suffix
&& !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
if (target_system_root)
{
+ char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
+ size_t sysroot_len = strlen (target_system_root);
+
+ if (sysroot_len > 0
+ && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
+ sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
+
if (target_sysroot_suffix)
prefix = concat (target_sysroot_suffix, prefix, NULL);
- prefix = concat (target_system_root, prefix, NULL);
+ prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
+ free (sysroot_no_trailing_dir_separator);
/* We have to override this because GCC's notion of sysroot
moves along with GCC. */
}
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)
fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout);
fputs (_(" --help Display this information\n"), stdout);
fputs (_(" --target-help Display target specific command line options\n"), stdout);
- fputs (_(" --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
+ fputs (_(" --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
fputs (_(" Display specific types of command line options\n"), stdout);
if (! verbose_flag)
fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout);
fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout);
fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout);
+ fputs (_("\
+ -print-multiarch Display the target's normalized GNU triplet, used as\n\
+ a component in the library path\n"), stdout);
fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout);
fputs (_("\
-print-multi-lib Display the mapping between command line options and\n\
fputs (_(" -S Compile only; do not assemble or link\n"), stdout);
fputs (_(" -c Compile and assemble, but do not link\n"), stdout);
fputs (_(" -o <file> Place the output into <file>\n"), stdout);
+ fputs (_(" -pie Create a position independent executable\n"), stdout);
+ fputs (_(" -shared Create a shared library\n"), stdout);
fputs (_("\
-x <language> Specify the language of the following input files\n\
Permissible languages include: c c++ assembler none\n\
}
/* 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.
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);
-}
-
-/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
- has been successfully handled with a handler for mask MASK. */
-
-static void
-driver_post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
- unsigned int mask ATTRIBUTE_UNUSED)
-{
- /* Nothing to do here. */
+ save_switch (decoded->canonical_option[0],
+ decoded->canonical_option_num_elements - 1,
+ &decoded->canonical_option[1], false);
}
static const char *spec_lang = 0;
case OPT_print_multi_directory:
case OPT_print_sysroot:
case OPT_print_multi_os_directory:
+ case OPT_print_multiarch:
case OPT_print_sysroot_headers_suffix:
case OPT_time:
case OPT_wrapper:
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;
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;
{
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->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.
{
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;
}
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. */
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;
/* 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)
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;
do_spec_1 (" ", 0, NULL);
}
+ if (multiarch_dir)
+ {
+ do_spec_1 ("-imultiarch", 1, NULL);
+ /* Make this a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ do_spec_1 (multiarch_dir, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+ }
+
if (gcc_exec_prefix)
{
do_spec_1 ("-iprefix", 1, NULL);
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
/* 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;
/* 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. */
{
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++;
}
&& check_live_switch (i, plen))
return true;
+ /* Check if a switch with separated form matching the atom.
+ We check -D and -U switches. */
+ else if (switches[i].args != 0)
+ {
+ if ((*switches[i].part1 == 'D' || *switches[i].part1 == 'U')
+ && *switches[i].part1 == atom[0])
+ {
+ if (!strncmp (switches[i].args[0], &atom[1], len - 1)
+ && (starred || (switches[i].part1[1] == '\0'
+ && switches[i].args[0][len - 1] == '\0'))
+ && check_live_switch (i, (starred ? 1 : -1)))
+ return true;
+ }
+ }
+
return false;
}
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));
if (argv != old_argv)
at_file_supplied = true;
- global_options = global_options_init;
+ /* 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),
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 ();
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;
- 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 not cross-compiling, look for executables in the standard
places. */
if (*cross_compile == '0')
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,
/* Set up to remember the pathname of the lto wrapper. */
- lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
+ if (have_c)
+ lto_wrapper_file = NULL;
+ else
+ lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper",
+ X_OK, false);
if (lto_wrapper_file)
{
+ lto_wrapper_file = convert_white_space (lto_wrapper_file);
lto_wrapper_spec = lto_wrapper_file;
obstack_init (&collect_obstack);
obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
return (0);
}
+ if (print_multiarch)
+ {
+ if (multiarch_dir == NULL)
+ printf ("\n");
+ else
+ printf ("%s\n", multiarch_dir);
+ return (0);
+ }
+
if (print_sysroot)
{
if (target_system_root)
{
printf (_("%s %s%s\n"), progname, pkgversion_string,
version_string);
- printf ("Copyright %s 2011 Free Software Foundation, Inc.\n",
+ printf ("Copyright %s 2012 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"),
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. */
{
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;
}
}
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");
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;
}
}
if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
{
int tmp = execution_count;
-#ifdef HAVE_LTO_PLUGIN
- const char *fno_use_linker_plugin = "fno-use-linker-plugin";
+
+ if (! have_c)
+ {
+#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";
+ 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"))
- {
- char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
- if (s == NULL)
- linker_name_spec = "ld";
- }
+ /* We'll use ld if we can't find collect2. */
+ if (! strcmp (linker_name_spec, "collect2"))
+ {
+ char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
+ if (s == NULL)
+ linker_name_spec = "ld";
+ }
-#ifdef HAVE_LTO_PLUGIN
- if (!switch_matches (fno_use_linker_plugin,
- fno_use_linker_plugin + strlen (fno_use_linker_plugin), 0))
+#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))
+ if (switch_matches (fuse_linker_plugin,
+ fuse_linker_plugin
+ + strlen (fuse_linker_plugin), 0))
#endif
- {
- linker_plugin_file_spec = find_a_file (&exec_prefixes,
- LTOPLUGINSONAME, R_OK,
- false);
- if (!linker_plugin_file_spec)
- fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found");
+ {
+ char *temp_spec = find_a_file (&exec_prefixes,
+ LTOPLUGINSONAME, R_OK,
+ false);
+ if (!temp_spec)
+ fatal_error ("-fuse-linker-plugin, but %s not found",
+ LTOPLUGINSONAME);
+ linker_plugin_file_spec = convert_white_space (temp_spec);
+ }
+#endif
+ lto_gcc_spec = argv[0];
}
- lto_gcc_spec = argv[0];
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
printf ("%s\n", bug_report_url);
}
+ out:
return (signal_count != 0 ? 2
: seen_error () ? (pass_exit_codes ? greatest_status : 1)
: 0);
options are present, then we will ignore this completely. Passing
that, gcc will consider each multilib_select in turn using the same
rules for matching the options. If a match is found, that subdirectory
- will be used. */
+ will be used.
+ A subdirectory name is optionally followed by a colon and the corresponding
+ multiarch name. */
static void
set_multilib_dir (void)
q++;
if (q < end)
{
- char *new_multilib_os_dir = XNEWVEC (char, end - q);
- memcpy (new_multilib_os_dir, q + 1, end - q - 1);
- new_multilib_os_dir[end - q - 1] = '\0';
- multilib_os_dir = new_multilib_os_dir;
+ const char *q2 = q + 1, *ml_end = end;
+ char *new_multilib_os_dir;
+
+ while (q2 < end && *q2 != ':')
+ q2++;
+ if (*q2 == ':')
+ ml_end = q2;
+ new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+ memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+ new_multilib_os_dir[ml_end - q - 1] = '\0';
+ multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+
+ if (q2 < end && *q2 == ':')
+ {
+ char *new_multiarch_dir = XNEWVEC (char, end - q2);
+ memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+ new_multiarch_dir[end - q2 - 1] = '\0';
+ multiarch_dir = new_multiarch_dir;
+ }
break;
}
}
}
/* When --disable-multilib was used but target defines
- MULTILIB_OSDIRNAMES, entries starting with .: are there just
- to find multilib_os_dir, so skip them from output. */
- if (this_path[0] == '.' && this_path[1] == ':')
+ MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
+ with .:: for multiarch configurations) are there just to find
+ multilib_os_dir, so skip them from output. */
+ if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
skip = 1;
/* Check for matches with the multilib_exclusions. We don't bother
/* 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;
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;
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;
return NULL;
}
-/* Compute a timestamp to initialize flag_random_seed. */
+/* Get a random number for -frandom-seed */
-static unsigned
-get_local_tick (void)
+static unsigned HOST_WIDE_INT
+get_random_number (void)
{
- unsigned ret = 0;
+ unsigned HOST_WIDE_INT ret = 0;
+ int fd;
+
+ fd = open ("/dev/urandom", O_RDONLY);
+ if (fd >= 0)
+ {
+ read (fd, &ret, sizeof (HOST_WIDE_INT));
+ close (fd);
+ if (ret)
+ return ret;
+ }
/* Get some more or less random data. */
#ifdef HAVE_GETTIMEOFDAY
}
#endif
- return ret;
+ return ret ^ getpid();
}
/* %:compare-debug-dump-opt spec function. Save the last argument,
if (!which)
{
- unsigned HOST_WIDE_INT value = get_local_tick () ^ getpid ();
+ unsigned HOST_WIDE_INT value = get_random_number ();
sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
}
}
return prepended;
}
+
+/* Insert backslash before spaces in ORIG (usually a file path), to
+ avoid being broken by spec parser.
+
+ This function is needed as do_spec_1 treats white space (' ' and '\t')
+ as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
+ the file name should be treated as a single argument rather than being
+ broken into multiple. Solution is to insert '\\' before the space in a
+ file name.
+
+ This function converts and only converts all occurrence of ' '
+ to '\\' + ' ' and '\t' to '\\' + '\t'. For example:
+ "a b" -> "a\\ b"
+ "a b" -> "a\\ \\ b"
+ "a\tb" -> "a\\\tb"
+ "a\\ b" -> "a\\\\ b"
+
+ orig: input null-terminating string that was allocated by xalloc. The
+ memory it points to might be freed in this function. Behavior undefined
+ if ORIG wasn't xalloced or was freed already at entry.
+
+ Return: ORIG if no conversion needed. Otherwise a newly allocated string
+ that was converted from ORIG. */
+
+static char *
+convert_white_space (char *orig)
+{
+ int len, number_of_space = 0;
+
+ for (len = 0; orig[len]; len++)
+ if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
+
+ if (number_of_space)
+ {
+ char *new_spec = (char *) xmalloc (len + number_of_space + 1);
+ int j, k;
+ for (j = 0, k = 0; j <= len; j++, k++)
+ {
+ if (orig[j] == ' ' || orig[j] == '\t')
+ new_spec[k++] = '\\';
+ new_spec[k] = orig[j];
+ }
+ free (orig);
+ return new_spec;
+ }
+ else
+ return orig;
+}