OSDN Git Service

PR c++/27292
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 56f1290..f23b5f3 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,6 +1,6 @@
 /* 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 Free Software Foundation,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
    Inc.
 
 This file is part of GCC.
@@ -330,6 +330,7 @@ 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 fatal_ice (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
 static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
 static void display_help (void);
 static void add_preprocessor_option (const char *, int);
@@ -352,6 +353,7 @@ static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
 static const char *replace_outfile_spec_function (int, const char **);
 static const char *version_compare_spec_function (int, const char **);
+static const char *include_spec_function (int, const char **);
 \f
 /* The Specs Language
 
@@ -440,8 +442,8 @@ or with constant text in a single argument.
        SUFFIX characters following %O as they would following, for
        example, `.o'.
  %I    Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
-       (made from TARGET_SYSTEM_ROOT), and -isystem (made from COMPILER_PATH
-       and -B options) as necessary.
+       (made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH
+       and -B options) and -imultilib as necessary.
  %s     current argument is the name of a library or startup file of some sort.
         Search for that file in a standard list of directories
        and substitute the full name found.
@@ -679,6 +681,10 @@ proper position among the other output files.  */
 #endif
 #endif
 
+#ifndef LINK_GCC_MATH_SPEC
+#define LINK_GCC_MATH_SPEC ""
+#endif
+
 #ifndef LINK_PIE_SPEC
 #ifdef HAVE_LD_PIE
 #define LINK_PIE_SPEC "%{pie:-pie} "
@@ -698,9 +704,10 @@ proper position among the other output files.  */
 %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
     %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
     %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
-    %{static:} %{L*} %(mfwrap) %(link_libgcc) %o %(mflib)\
+    %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
+    %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
     %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
-    %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
+    %{!nostdlib:%{!nodefaultlibs:%(link_gcc_math) %(link_ssp) %(link_gcc_c_sequence)}}\
     %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
 #endif
 
@@ -731,12 +738,14 @@ static const char *cc1_spec = CC1_SPEC;
 static const char *cc1plus_spec = CC1PLUS_SPEC;
 static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
 static const char *link_ssp_spec = LINK_SSP_SPEC;
+static const char *link_gcc_math_spec = LINK_GCC_MATH_SPEC;
 static const char *asm_spec = ASM_SPEC;
 static const char *asm_final_spec = ASM_FINAL_SPEC;
 static const char *link_spec = LINK_SPEC;
 static const char *lib_spec = LIB_SPEC;
 static const char *mfwrap_spec = MFWRAP_SPEC;
 static const char *mflib_spec = MFLIB_SPEC;
+static const char *link_gomp_spec = "";
 static const char *libgcc_spec = LIBGCC_SPEC;
 static const char *endfile_spec = ENDFILE_SPEC;
 static const char *startfile_spec = STARTFILE_SPEC;
@@ -835,7 +844,15 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 #define DRIVER_SELF_SPECS ""
 #endif
 
-static const char *const driver_self_specs[] = { DRIVER_SELF_SPECS };
+/* Adding -fopenmp should imply pthreads.  This is particularly important
+   for targets that use different start files and suchlike.  */
+#ifndef GOMP_SELF_SPECS
+#define GOMP_SELF_SPECS "%{fopenmp: -pthread}"
+#endif
+
+static const char *const driver_self_specs[] = {
+  DRIVER_SELF_SPECS, GOMP_SELF_SPECS
+};
 
 #ifndef OPTION_DEFAULT_SPECS
 #define OPTION_DEFAULT_SPECS { "", "" }
@@ -1529,11 +1546,13 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("cc1plus",                 &cc1plus_spec),
   INIT_STATIC_SPEC ("link_gcc_c_sequence",     &link_gcc_c_sequence_spec),
   INIT_STATIC_SPEC ("link_ssp",                        &link_ssp_spec),
+  INIT_STATIC_SPEC ("link_gcc_math",           &link_gcc_math_spec),
   INIT_STATIC_SPEC ("endfile",                 &endfile_spec),
   INIT_STATIC_SPEC ("link",                    &link_spec),
   INIT_STATIC_SPEC ("lib",                     &lib_spec),
   INIT_STATIC_SPEC ("mfwrap",                  &mfwrap_spec),
   INIT_STATIC_SPEC ("mflib",                   &mflib_spec),
+  INIT_STATIC_SPEC ("link_gomp",               &link_gomp_spec),
   INIT_STATIC_SPEC ("libgcc",                  &libgcc_spec),
   INIT_STATIC_SPEC ("startfile",               &startfile_spec),
   INIT_STATIC_SPEC ("switches_need_spaces",    &switches_need_spaces),
@@ -1581,6 +1600,7 @@ static const struct spec_function static_spec_functions[] =
   { "if-exists-else",          if_exists_else_spec_function },
   { "replace-outfile",         replace_outfile_spec_function },
   { "version-compare",         version_compare_spec_function },
+  { "include",                 include_spec_function },
   { 0, 0 }
 };
 
@@ -1810,7 +1830,7 @@ set_spec (const char *name, const char *spec)
   if (!sl)
     {
       /* Not found - make it.  */
-      sl = xmalloc (sizeof (struct spec_list));
+      sl = XNEW (struct spec_list);
       sl->name = xstrdup (name);
       sl->name_len = name_len;
       sl->ptr_spec = &sl->ptr;
@@ -1893,7 +1913,7 @@ static void
 alloc_args (void)
 {
   argbuf_length = 10;
-  argbuf = xmalloc (argbuf_length * sizeof (const char *));
+  argbuf = XNEWVEC (const char *, argbuf_length);
 }
 
 /* Clear out the vector of arguments (after a command is executed).  */
@@ -1952,14 +1972,14 @@ load_specs (const char *filename)
     pfatal_with_name (filename);
 
   /* Read contents of file into BUFFER.  */
-  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
+  buffer = XNEWVEC (char, statbuf.st_size + 1);
   readlen = read (desc, buffer, (unsigned) statbuf.st_size);
   if (readlen < 0)
     pfatal_with_name (filename);
   buffer[readlen] = 0;
   close (desc);
 
-  specs = xmalloc (readlen + 1);
+  specs = XNEWVEC (char, readlen + 1);
   specs_p = specs;
   for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
     {
@@ -2275,7 +2295,7 @@ record_temp_file (const char *filename, int always_delete, int fail_delete)
        if (! strcmp (name, temp->name))
          goto already1;
 
-      temp = xmalloc (sizeof (struct temp_file));
+      temp = XNEW (struct temp_file);
       temp->next = always_delete_queue;
       temp->name = name;
       always_delete_queue = temp;
@@ -2290,7 +2310,7 @@ record_temp_file (const char *filename, int always_delete, int fail_delete)
        if (! strcmp (name, temp->name))
          goto already2;
 
-      temp = xmalloc (sizeof (struct temp_file));
+      temp = XNEW (struct temp_file);
       temp->next = failure_delete_queue;
       temp->name = name;
       failure_delete_queue = temp;
@@ -2421,7 +2441,7 @@ for_each_path (const struct path_prefix *paths,
            len += suffix_len;
          else
            len += multi_os_dir_len;
-         path = xmalloc (len);
+         path = XNEWVEC (char, len);
        }
 
       for (pl = paths->plist; pl != 0; pl = pl->next)
@@ -2719,7 +2739,7 @@ add_prefix (struct path_prefix *pprefix, const char *prefix,
   if (len > pprefix->max_len)
     pprefix->max_len = len;
 
-  pl = xmalloc (sizeof (struct prefix_list));
+  pl = XNEW (struct prefix_list);
   pl->prefix = prefix;
   pl->require_machine_suffix = require_machine_suffix;
   pl->priority = priority;
@@ -2978,12 +2998,12 @@ execute (void)
              }
            else
 #endif
-             fatal ("\
+             fatal_ice ("\
 Internal error: %s (program %s)\n\
 Please submit a full bug report.\n\
 See %s for instructions.",
-                    strsignal (WTERMSIG (status)), commands[i].prog,
-                    bug_report_url);
+                       strsignal (WTERMSIG (status)), commands[i].prog,
+                       bug_report_url);
          }
        else if (WIFEXITED (status)
                 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
@@ -3207,7 +3227,7 @@ add_preprocessor_option (const char *option, int len)
   n_preprocessor_options++;
 
   if (! preprocessor_options)
-    preprocessor_options = xmalloc (n_preprocessor_options * sizeof (char *));
+    preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
   else
     preprocessor_options = xrealloc (preprocessor_options,
                                     n_preprocessor_options * sizeof (char *));
@@ -3222,7 +3242,7 @@ add_assembler_option (const char *option, int len)
   n_assembler_options++;
 
   if (! assembler_options)
-    assembler_options = xmalloc (n_assembler_options * sizeof (char *));
+    assembler_options = XNEWVEC (char *, n_assembler_options);
   else
     assembler_options = xrealloc (assembler_options,
                                  n_assembler_options * sizeof (char *));
@@ -3236,7 +3256,7 @@ add_linker_option (const char *option, int len)
   n_linker_options++;
 
   if (! linker_options)
-    linker_options = xmalloc (n_linker_options * sizeof (char *));
+    linker_options = XNEWVEC (char *, n_linker_options);
   else
     linker_options = xrealloc (linker_options,
                               n_linker_options * sizeof (char *));
@@ -3258,7 +3278,7 @@ process_command (int argc, const char **argv)
   int lang_n_infiles = 0;
 #ifdef MODIFY_TARGET_NAME
   int is_modify_target_name;
-  int j;
+  unsigned int j;
 #endif
 
   GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
@@ -3281,11 +3301,11 @@ process_command (int argc, const char **argv)
     }
 
   /* If there is a -V or -b option (or both), process it now, before
-     trying to interpret the rest of the command line. 
+     trying to interpret the rest of the command line.
      Use heuristic that all configuration names must have at least
      one dash '-'. This allows us to pass options starting with -b.  */
   if (argc > 1 && argv[1][0] == '-'
-      && (argv[1][1] == 'V' || 
+      && (argv[1][1] == 'V' ||
         ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
     {
       const char *new_version = DEFAULT_TARGET_VERSION;
@@ -3522,7 +3542,7 @@ process_command (int argc, const char **argv)
        {
          /* translate_options () has turned --version into -fversion.  */
          printf (_("%s (GCC) %s\n"), programname, version_string);
-         printf ("Copyright %s 2005 Free Software Foundation, Inc.\n",
+         printf ("Copyright %s 2006 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"),
@@ -3666,7 +3686,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        }
       else if (strcmp (argv[i], "-specs") == 0)
        {
-         struct user_specs *user = xmalloc (sizeof (struct user_specs));
+         struct user_specs *user = XNEW (struct user_specs);
          if (++i >= argc)
            fatal ("argument to '-specs' is missing");
 
@@ -3680,7 +3700,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        }
       else if (strncmp (argv[i], "-specs=", 7) == 0)
        {
-         struct user_specs *user = xmalloc (sizeof (struct user_specs));
+         struct user_specs *user = XNEW (struct user_specs);
          if (strlen (argv[i]) == 7)
            fatal ("argument to '-specs=' is missing");
 
@@ -3747,7 +3767,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
                if (! IS_DIR_SEPARATOR (value [len - 1])
                    && is_directory (value, false))
                  {
-                   char *tmp = xmalloc (len + 2);
+                   char *tmp = XNEWVEC (char, len + 2);
                    strcpy (tmp, value);
                    tmp[len] = DIR_SEPARATOR;
                    tmp[++ len] = 0;
@@ -3994,8 +4014,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   /* Then create the space for the vectors and scan again.  */
 
-  switches = xmalloc ((n_switches + 1) * sizeof (struct switchstr));
-  infiles = xmalloc ((n_infiles + 1) * sizeof (struct infile));
+  switches = XNEWVEC (struct switchstr, n_switches + 1);
+  infiles = XNEWVEC (struct infile, n_infiles + 1);
   n_switches = 0;
   n_infiles = 0;
   last_language_n_infiles = -1;
@@ -4145,7 +4165,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
              if (i + n_args >= argc)
                fatal ("argument to '-%s' is missing", p);
              switches[n_switches].args
-               = xmalloc ((n_args + 1) * sizeof(const char *));
+               = XNEWVEC (const char *, n_args + 1);
              while (j < n_args)
                switches[n_switches].args[j++] = argv[++i];
              /* Null-terminate the vector.  */
@@ -4155,12 +4175,12 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
            {
              /* On some systems, ld cannot handle some options without
                 a space.  So split the option from its argument.  */
-             char *part1 = xmalloc (2);
+             char *part1 = XNEWVEC (char, 2);
              part1[0] = c;
              part1[1] = '\0';
 
              switches[n_switches].part1 = part1;
-             switches[n_switches].args = xmalloc (2 * sizeof (const char *));
+             switches[n_switches].args = XNEWVEC (const char *, 2);
              switches[n_switches].args[0] = xstrdup (p+1);
              switches[n_switches].args[1] = 0;
            }
@@ -4803,7 +4823,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    else
                      {
                        saved_suffix
-                         = xmalloc (suffix_length
+                         = XNEWVEC (char, suffix_length
                                     + strlen (TARGET_OBJECT_SUFFIX));
                        strncpy (saved_suffix, suffix, suffix_length);
                        strcpy (saved_suffix + suffix_length,
@@ -4934,6 +4954,15 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
            {
              struct spec_path_info info;
 
+             if (multilib_dir)
+               {
+                 do_spec_1 ("-imultilib", 1, NULL);
+                 /* Make this a separate argument.  */
+                 do_spec_1 (" ", 0, NULL);
+                 do_spec_1 (multilib_dir, 1, NULL);
+                 do_spec_1 (" ", 0, NULL);
+               }
+
              if (gcc_exec_prefix)
                {
                  do_spec_1 ("-iprefix", 1, NULL);
@@ -5353,20 +5382,11 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 static const struct spec_function *
 lookup_spec_function (const char *name)
 {
-  static const struct spec_function * const spec_function_tables[] =
-  {
-    static_spec_functions,
-    lang_specific_spec_functions,
-  };
   const struct spec_function *sf;
-  unsigned int i;
 
-  for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++)
-    {
-      for (sf = spec_function_tables[i]; sf->name != NULL; sf++)
-       if (strcmp (sf->name, name) == 0)
-         return sf;
-    }
+  for (sf = static_spec_functions; sf->name != NULL; sf++)
+    if (strcmp (sf->name, name) == 0)
+      return sf;
 
   return NULL;
 }
@@ -5527,10 +5547,10 @@ input_suffix_matches (const char *atom, const char *end_atom)
          && input_suffix[end_atom - atom] == '\0');
 }
 
-/* Inline subroutine of handle_braces.  Returns true if a switch
+/* Subroutine of handle_braces.  Returns true if a switch
    matching the atom bracketed by ATOM and END_ATOM appeared on the
    command line.  */
-static inline bool
+static bool
 switch_matches (const char *atom, const char *end_atom, int starred)
 {
   int i;
@@ -6458,16 +6478,16 @@ main (int argc, char **argv)
 
   i = n_infiles;
   i += lang_specific_extra_outfiles;
-  outfiles = xcalloc (i, sizeof (char *));
+  outfiles = XCNEWVEC (const char *, i);
 
   /* Record which files were specified explicitly as link input.  */
 
-  explicit_link_files = xcalloc (1, n_infiles);
+  explicit_link_files = XCNEWVEC (char, n_infiles);
 
   if (combine_flag)
     combine_inputs = true;
   else
-    combine_inputs = false;  
+    combine_inputs = false;
 
   for (i = 0; (int) i < n_infiles; i++)
     {
@@ -6498,7 +6518,7 @@ main (int argc, char **argv)
       infiles[i].compiled = false;
       infiles[i].preprocessed = false;
     }
-    
+
   if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
    fatal ("cannot specify -o with -c or -S with multiple files");
 
@@ -6773,7 +6793,7 @@ lookup_compiler (const char *name, size_t length, const char *language)
 static char *
 save_string (const char *s, int len)
 {
-  char *result = xmalloc (len + 1);
+  char *result = XNEWVEC (char, len + 1);
 
   memcpy (result, s, len);
   result[len] = 0;
@@ -6799,12 +6819,27 @@ perror_with_name (const char *name)
 void
 fancy_abort (const char *file, int line, const char *func)
 {
-  fatal ("internal gcc abort in %s, at %s:%d", func, file, line);
+  fatal_ice ("internal gcc abort in %s, at %s:%d", func, file, line);
 }
 \f
 /* Output an error message and exit.  */
 
 void
+fatal_ice (const char *cmsgid, ...)
+{
+  va_list ap;
+
+  va_start (ap, cmsgid);
+
+  fprintf (stderr, "%s: ", programname);
+  vfprintf (stderr, _(cmsgid), ap);
+  va_end (ap);
+  fprintf (stderr, "\n");
+  delete_temp_files ();
+  exit (pass_exit_codes ? ICE_EXIT_CODE : 1);
+}
+
+void
 fatal (const char *cmsgid, ...)
 {
   va_list ap;
@@ -7023,8 +7058,7 @@ used_arg (const char *p, int len)
         xmalloc from calling fatal, and prevents us from re-executing this
         block of code.  */
       mswitches
-       = xmalloc (sizeof (struct mswitchstr)
-                  * (n_mdswitches + (n_switches ? n_switches : 1)));
+       = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
       for (i = 0; i < n_switches; i++)
        if (switches[i].live_cond != SWITCH_IGNORE)
          {
@@ -7151,7 +7185,7 @@ set_multilib_dir (void)
     {
       int i = 0;
 
-      mdswitches = xmalloc (sizeof (struct mdswitchstr) * n_mdswitches);
+      mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches);
       for (start = multilib_defaults; *start != '\0'; start = end + 1)
        {
          while (*start == ' ' || *start == '\t')
@@ -7313,7 +7347,7 @@ set_multilib_dir (void)
          if (this_path_len != 1
              || this_path[0] != '.')
            {
-             char *new_multilib_dir = xmalloc (this_path_len + 1);
+             char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
              char *q;
 
              strncpy (new_multilib_dir, this_path, this_path_len);
@@ -7334,7 +7368,7 @@ set_multilib_dir (void)
            q++;
          if (q < end)
            {
-             char *new_multilib_os_dir = xmalloc (end - q);
+             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;
@@ -7789,3 +7823,22 @@ version_compare_spec_function (int argc, const char **argv)
 
   return argv[nargs + 2];
 }
+
+/* %:include builtin spec function.  This differs from %include in that it
+   can be nested inside a spec, and thus be conditionalized.  It takes
+   one argument, the filename, and looks for it in the startfile path.
+   The result is always NULL, i.e. an empty expansion.  */
+
+static const char *
+include_spec_function (int argc, const char **argv)
+{
+  char *file;
+
+  if (argc != 1)
+    abort ();
+
+  file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
+  read_specs (file ? file : argv[0], FALSE);
+
+  return NULL;
+}