re PR fortran/48889 (f951: internal compiler error: in gfc_is_constant_expr, at fortr...
[gcc.git] / gcc / gcc.c
index 9532d7efd8bbd488a8b5320220d5d93a8161cce7..c43e45ab427add091f0917cdb39cd05c4a0c9a5f 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -44,6 +44,7 @@ compilation is specified by a string called a "spec".  */
 #include "flags.h"
 #include "opts.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 */
@@ -621,11 +622,36 @@ proper position among the other output files.  */
 # endif
 #endif
 
-/* Conditional to test whether plugin is used or not.  */
-#ifdef HAVE_LTO_PLUGIN
-#define PLUGIN_COND "!fno-use-linker-plugin"
+/* 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 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
 
 
@@ -637,18 +663,14 @@ proper position among the other output files.  */
    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))}} \
-    } \
-    %{flto*:%<fcompare-debug*} \
-    %{flto*} %l " LINK_PIE_SPEC \
+    %(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\
@@ -768,7 +790,7 @@ static const char *cc1_options =
  %{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.  */
@@ -942,7 +964,7 @@ static const struct compiler default_compilers[] =
                     %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},
@@ -1368,7 +1390,8 @@ init_spec (void)
                            "-lgcc_eh"
 #ifdef USE_LIBUNWIND_EXCEPTIONS
 # ifdef HAVE_LD_STATIC_DYNAMIC
-                           " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}"
+                           " %{!static:" LD_STATIC_OPTION "} -lunwind"
+                           " %{!static:" LD_DYNAMIC_OPTION "}"
 # else
                            " -lunwind"
 # endif
@@ -1415,7 +1438,8 @@ init_spec (void)
   }
 #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);
@@ -1423,6 +1447,16 @@ init_spec (void)
 # ifdef LINK_EH_SPEC
   /* 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 *);
@@ -1927,7 +1961,7 @@ record_temp_file (const char *filename, int always_delete, int fail_delete)
     {
       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);
@@ -1942,7 +1976,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);
@@ -2529,13 +2563,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)
@@ -3051,16 +3092,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.
@@ -3077,11 +3126,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)
@@ -3322,6 +3373,11 @@ driver_handle_option (struct gcc_options *opts,
       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;
@@ -3585,9 +3641,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;
        }
 
@@ -4409,6 +4465,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.  */
@@ -4681,7 +4741,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;
@@ -4707,7 +4767,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)
@@ -4757,8 +4817,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;
@@ -5135,7 +5194,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
@@ -5885,11 +5945,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));
@@ -6589,6 +6649,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.  */
 
@@ -6671,12 +6734,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;
                }
 
@@ -6708,8 +6769,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");
@@ -6720,12 +6781,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;
                }
            }
@@ -6786,10 +6845,12 @@ 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;
-#ifdef HAVE_LTO_PLUGIN
+#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.  */
@@ -6800,7 +6861,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
            linker_name_spec = "ld";
        }
 
-#ifdef HAVE_LTO_PLUGIN
+#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
@@ -6814,6 +6876,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          if (!linker_plugin_file_spec)
            fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found");
        }
+#endif
       lto_gcc_spec = argv[0];
 
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
@@ -6856,6 +6919,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);
@@ -7608,7 +7672,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;
@@ -7812,7 +7876,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;
@@ -7833,7 +7897,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;