On Tue, Jan 26, 2016 at 03:06:43PM +0100, Richard Biener wrote:
> I'm somewhat confused about that you drop -fsanitize options from
> the LTO options section writing in lto-opts.c but then add code to
> parse it from there in lto-wrapper.c.  The code there also looks

Sorry, as I said to Bernd, that has been just thinko in the comment change,
the code was doing what I meant to.

> somewhat duplicated - why not just canonicalize any -fsanitize=
> option coming in to the first in merge_and_complain
> and special-case it in append_compiler_options again by say
> 
>   case OPT_fsanitize_:
>      obstack_ptr_grow (argv_obstack, "-fsanitize=shift");

It is certainly much easier to just propagate around a bool flag
whether we need to add -fsanitize=shift after the linker options.
The reason I haven't done that because I didn't want to pass around
yet another argument, furthermore so specific to a particular option.

But looking around, it seems we are already passing around pairs,
the pointer to array of struct cl_decoded_option and pointer to the count of
elements in that array.  By sticking the two into a structure and adding
the sanitize_undefined flag for now, if in the future we need to handle
some other option similarly, we can just handle it in 3-4 spots and not
everywhere among so many different functions.

So, what do you think about the untested patch below (the test with
-c -flto -fsanitize=undefined
-flto -fno-sanitize=undefined
passes)?  The patch is large, because it changed many places from
a pair of pointer and unsigned int (or a pair of pointer to pointer and
pointer to unsigned int) to pointer to this new struct.

2016-01-26  Jakub Jelinek  <ja...@redhat.com>

        PR lto/69254
        * lto-opts.c (lto_write_options): Write also -f{,no-}sanitize=
        options.
        * lto-wrapper.c (struct lto_decoded_options): New type.
        (append_option, merge_and_complain, append_compiler_options,
        append_linker_options, append_offload_options,
        compile_offload_image, compile_images_for_offload_targets,
        find_and_merge_options): Pass around options
        in struct lto_decoded_options instead of struct cl_decoded_option
        pointer and count pair.
        (get_options_from_collect_gcc_options): Likewise.  Parse -fsanitize=
        options and if in the end any ub sanitizers are enabled, set
        decoded_opts->sanitize_undefined to true.
        (run_gcc): Adjust callers of these functions.  If
        fdecoded_options.sanitize_undefined is true, append
        -fsanitize=shift after the linker options.

--- gcc/lto-opts.c.jj   2016-01-25 22:33:11.477029666 +0100
+++ gcc/lto-opts.c      2016-01-26 15:41:02.937040062 +0100
@@ -198,10 +198,13 @@ lto_write_options (void)
 
       /* Also drop all options that are handled by the driver as well,
         which includes things like -o and -v or -fhelp for example.
-        We do not need those.  The only exception is -foffload option, if we
-        write it in offload_lto section.  Also drop all diagnostic options.  */
+        We do not need those.  The only exceptions are:
+        1) -foffload option, if we write it in offload_lto section
+        2) -f{,no-}sanitize=
+        Also drop all diagnostic options.  */
       if ((cl_options[option->opt_index].flags & (CL_DRIVER|CL_WARNING))
-         && (!lto_stream_offload_p || option->opt_index != OPT_foffload_))
+         && (!lto_stream_offload_p || option->opt_index != OPT_foffload_)
+         && option->opt_index != OPT_fsanitize_)
        continue;
 
       for (j = 0; j < option->canonical_option_num_elements; ++j)
--- gcc/lto-wrapper.c.jj        2016-01-26 15:24:10.457845617 +0100
+++ gcc/lto-wrapper.c   2016-01-26 16:38:16.784303735 +0100
@@ -118,6 +118,16 @@ maybe_unlink (const char *file)
 /* Template of LTRANS dumpbase suffix.  */
 #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
 
+/* Structure containing decoded options, number of them and auxiliary
+   state from the options handling.  */
+
+struct lto_decoded_options
+{
+  struct cl_decoded_option *opt;
+  unsigned int count;
+  bool sanitize_undefined;
+};
+
 /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
    environment according to LANG_MASK.  */
 
@@ -125,13 +135,14 @@ static void
 get_options_from_collect_gcc_options (const char *collect_gcc,
                                      const char *collect_gcc_options,
                                      unsigned int lang_mask,
-                                     struct cl_decoded_option 
**decoded_options,
-                                     unsigned int *decoded_options_count)
+                                     struct lto_decoded_options *decoded_opts)
 {
   struct obstack argv_obstack;
   char *argv_storage;
   const char **argv;
   int j, k, argc;
+  unsigned int i;
+  int sanitize = 0;
 
   argv_storage = xstrdup (collect_gcc_options);
   obstack_init (&argv_obstack);
@@ -166,9 +177,30 @@ get_options_from_collect_gcc_options (co
   argc = obstack_object_size (&argv_obstack) / sizeof (void *) - 1;
   argv = XOBFINISH (&argv_obstack, const char **);
 
+  memset (decoded_opts, 0, sizeof (*decoded_opts));
   decode_cmdline_options_to_array (argc, (const char **)argv,
                                   lang_mask,
-                                  decoded_options, decoded_options_count);
+                                  &decoded_opts->opt, &decoded_opts->count);
+
+  for (i = 0; i < decoded_opts->count; ++i)
+    {
+      struct cl_decoded_option *foption = &decoded_opts->opt[i];
+      switch (foption->opt_index)
+       {
+       case OPT_fsanitize_:
+         sanitize = parse_sanitizer_options (foption->arg, input_location,
+                                             OPT_fsanitize_, sanitize,
+                                             foption->value, false);
+         break;
+       default:
+         break;
+       }
+    }
+  /* If DECODED_OPTS->OPT requested any ubsan sanitization, collect
+     that info for later handling.  */
+  if (sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+    decoded_opts->sanitize_undefined = true;
+
   obstack_free (&argv_obstack, NULL);
 }
 
@@ -176,17 +208,16 @@ get_options_from_collect_gcc_options (co
    DECODED_OPTIONS_COUNT.  */
 
 static void
-append_option (struct cl_decoded_option **decoded_options,
-              unsigned int *decoded_options_count,
+append_option (struct lto_decoded_options *decoded_options,
               struct cl_decoded_option *option)
 {
-  ++*decoded_options_count;
-  *decoded_options
+  ++decoded_options->count;
+  decoded_options->opt
     = (struct cl_decoded_option *)
-       xrealloc (*decoded_options,
-                 (*decoded_options_count
+       xrealloc (decoded_options->opt,
+                 (decoded_options->count
                   * sizeof (struct cl_decoded_option)));
-  memcpy (&(*decoded_options)[*decoded_options_count - 1], option,
+  memcpy (&decoded_options->opt[decoded_options->count - 1], option,
          sizeof (struct cl_decoded_option));
 }
 
@@ -194,13 +225,13 @@ append_option (struct cl_decoded_option
    ontop of DECODED_OPTIONS.  */
 
 static void
-merge_and_complain (struct cl_decoded_option **decoded_options,
-                   unsigned int *decoded_options_count,
-                   struct cl_decoded_option *fdecoded_options,
-                   unsigned int fdecoded_options_count)
+merge_and_complain (struct lto_decoded_options *decoded_options,
+                   struct lto_decoded_options *fdecoded_options)
 {
   unsigned int i, j;
 
+  decoded_options->sanitize_undefined |= fdecoded_options->sanitize_undefined;
+
   /* ???  Merge options from files.  Most cases can be
      handled by either unioning or intersecting
      (for example -fwrapv is a case for unioning,
@@ -216,9 +247,9 @@ merge_and_complain (struct cl_decoded_op
 
   /* The following does what the old LTO option code did,
      union all target and a selected set of common options.  */
-  for (i = 0; i < fdecoded_options_count; ++i)
+  for (i = 0; i < fdecoded_options->count; ++i)
     {
-      struct cl_decoded_option *foption = &fdecoded_options[i];
+      struct cl_decoded_option *foption = &fdecoded_options->opt[i];
       switch (foption->opt_index)
        {
        case OPT_SPECIAL_unknown:
@@ -248,27 +279,27 @@ merge_and_complain (struct cl_decoded_op
             setting per OPT code, we pick the first we encounter.
             ???  This doesn't make too much sense, but when it doesn't
             then we should complain.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
+         for (j = 0; j < decoded_options->count; ++j)
+           if (decoded_options->opt[j].opt_index == foption->opt_index)
              break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
+         if (j == decoded_options->count)
+           append_option (decoded_options, foption);
          break;
 
        case OPT_ftrapv:
        case OPT_fstrict_overflow:
        case OPT_ffp_contract_:
          /* For selected options we can merge conservatively.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
+         for (j = 0; j < decoded_options->count; ++j)
+           if (decoded_options->opt[j].opt_index == foption->opt_index)
              break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
+         if (j == decoded_options->count)
+           append_option (decoded_options, foption);
          /* FP_CONTRACT_OFF < FP_CONTRACT_ON < FP_CONTRACT_FAST,
             -fno-trapv < -ftrapv,
             -fno-strict-overflow < -fstrict-overflow  */
-         else if (foption->value < (*decoded_options)[j].value)
-           (*decoded_options)[j] = *foption;
+         else if (foption->value < decoded_options->opt[j].value)
+           decoded_options->opt[j] = *foption;
          break;
 
        case OPT_fmath_errno:
@@ -280,38 +311,38 @@ merge_and_complain (struct cl_decoded_op
        case OPT_fcilkplus:
        case OPT_fcheck_pointer_bounds:
          /* For selected options we can merge conservatively.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
+         for (j = 0; j < decoded_options->count; ++j)
+           if (decoded_options->opt[j].opt_index == foption->opt_index)
              break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
+         if (j == decoded_options->count)
+           append_option (decoded_options, foption);
          /* -fmath-errno > -fno-math-errno,
             -fsigned-zeros > -fno-signed-zeros,
             -ftrapping-math -> -fno-trapping-math,
             -fwrapv > -fno-wrapv.  */
-         else if (foption->value > (*decoded_options)[j].value)
-           (*decoded_options)[j] = *foption;
+         else if (foption->value > decoded_options->opt[j].value)
+           decoded_options->opt[j] = *foption;
          break;
 
        case OPT_freg_struct_return:
        case OPT_fpcc_struct_return:
        case OPT_fshort_double:
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
+         for (j = 0; j < decoded_options->count; ++j)
+           if (decoded_options->opt[j].opt_index == foption->opt_index)
              break;
-         if (j == *decoded_options_count)
+         if (j == decoded_options->count)
            fatal_error (input_location,
                         "Option %s not used consistently in all LTO input"
                         " files", foption->orig_option_with_args_text);
          break;
 
        case OPT_foffload_abi_:
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
+         for (j = 0; j < decoded_options->count; ++j)
+           if (decoded_options->opt[j].opt_index == foption->opt_index)
              break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if (foption->value != (*decoded_options)[j].value)
+         if (j == decoded_options->count)
+           append_option (decoded_options, foption);
+         else if (foption->value != decoded_options->opt[j].value)
            fatal_error (input_location,
                         "Option %s not used consistently in all LTO input"
                         " files", foption->orig_option_with_args_text);
@@ -321,15 +352,15 @@ merge_and_complain (struct cl_decoded_op
        case OPT_Ofast:
        case OPT_Og:
        case OPT_Os:
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == OPT_O
-               || (*decoded_options)[j].opt_index == OPT_Ofast
-               || (*decoded_options)[j].opt_index == OPT_Og
-               || (*decoded_options)[j].opt_index == OPT_Os)
+         for (j = 0; j < decoded_options->count; ++j)
+           if (decoded_options->opt[j].opt_index == OPT_O
+               || decoded_options->opt[j].opt_index == OPT_Ofast
+               || decoded_options->opt[j].opt_index == OPT_Og
+               || decoded_options->opt[j].opt_index == OPT_Os)
              break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if ((*decoded_options)[j].opt_index == foption->opt_index
+         if (j == decoded_options->count)
+           append_option (decoded_options, foption);
+         else if (decoded_options->opt[j].opt_index == foption->opt_index
                   && foption->opt_index != OPT_O)
            /* Exact same options get merged.  */
            ;
@@ -359,13 +390,13 @@ merge_and_complain (struct cl_decoded_op
                default:
                  gcc_unreachable ();
                }
-             switch ((*decoded_options)[j].opt_index)
+             switch (decoded_options->opt[j].opt_index)
                {
                case OPT_O:
-                 if ((*decoded_options)[j].arg[0] == '\0')
+                 if (decoded_options->opt[j].arg[0] == '\0')
                    level = MAX (level, 1);
                  else
-                   level = MAX (level, atoi ((*decoded_options)[j].arg));
+                   level = MAX (level, atoi (decoded_options->opt[j].arg));
                  break;
                case OPT_Ofast:
                  level = MAX (level, 3);
@@ -379,17 +410,17 @@ merge_and_complain (struct cl_decoded_op
                default:
                  gcc_unreachable ();
                }
-             (*decoded_options)[j].opt_index = OPT_O;
+             decoded_options->opt[j].opt_index = OPT_O;
              char *tem;
              tem = xasprintf ("-O%d", level);
-             (*decoded_options)[j].arg = &tem[2];
-             (*decoded_options)[j].canonical_option[0] = tem;
-             (*decoded_options)[j].value = 1;
+             decoded_options->opt[j].arg = &tem[2];
+             decoded_options->opt[j].canonical_option[0] = tem;
+             decoded_options->opt[j].value = 1;
            }
          break;
 
        case OPT_foffload_:
-         append_option (decoded_options, decoded_options_count, foption);
+         append_option (decoded_options, foption);
          break;
        }
     }
@@ -459,13 +490,13 @@ parse_env_var (const char *str, char ***
 /* Append options OPTS from lto or offload_lto sections to ARGV_OBSTACK.  */
 
 static void
-append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                        unsigned int count)
+append_compiler_options (obstack *argv_obstack,
+                        struct lto_decoded_options *opts)
 {
   /* Append compiler driver arguments as far as they were merged.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts->count; ++j)
     {
-      struct cl_decoded_option *option = &opts[j];
+      struct cl_decoded_option *option = &opts->opt[j];
 
       /* File options have been properly filtered by lto-opts.c.  */
       switch (option->opt_index)
@@ -531,14 +562,13 @@ append_compiler_options (obstack *argv_o
 /* Append linker options OPTS to ARGV_OBSTACK.  */
 
 static void
-append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                      unsigned int count)
+append_linker_options (obstack *argv_obstack, struct lto_decoded_options *opts)
 {
   /* Append linker driver arguments.  Compiler options from the linker
      driver arguments will override / merge with those from the compiler.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts->count; ++j)
     {
-      struct cl_decoded_option *option = &opts[j];
+      struct cl_decoded_option *option = &opts->opt[j];
 
       /* Do not pass on frontend specific flags not suitable for lto.  */
       if (!(cl_options[option->opt_index].flags
@@ -584,15 +614,14 @@ append_linker_options (obstack *argv_obs
 
 static void
 append_offload_options (obstack *argv_obstack, const char *target,
-                       struct cl_decoded_option *options,
-                       unsigned int options_count)
+                       struct lto_decoded_options *options)
 {
-  for (unsigned i = 0; i < options_count; i++)
+  for (unsigned i = 0; i < options->count; i++)
     {
       const char *cur, *next, *opts;
       char **argv;
       unsigned argc;
-      struct cl_decoded_option *option = &options[i];
+      struct cl_decoded_option *option = &options->opt[i];
 
       if (option->opt_index != OPT_foffload_)
        continue;
@@ -664,10 +693,8 @@ access_check (const char *name, int mode
 static char *
 compile_offload_image (const char *target, const char *compiler_path,
                       unsigned in_argc, char *in_argv[],
-                      struct cl_decoded_option *compiler_opts,
-                      unsigned int compiler_opt_count,
-                      struct cl_decoded_option *linker_opts,
-                      unsigned int linker_opt_count)
+                      struct lto_decoded_options *compiler_opts,
+                      struct lto_decoded_options *linker_opts)
 {
   char *filename = NULL;
   char **argv;
@@ -708,15 +735,12 @@ compile_offload_image (const char *targe
        obstack_ptr_grow (&argv_obstack, in_argv[i]);
 
       /* Append options from offload_lto sections.  */
-      append_compiler_options (&argv_obstack, compiler_opts,
-                              compiler_opt_count);
+      append_compiler_options (&argv_obstack, compiler_opts);
 
       /* Append options specified by -foffload last.  In case of conflicting
         options we expect offload compiler to choose the latest.  */
-      append_offload_options (&argv_obstack, target, compiler_opts,
-                             compiler_opt_count);
-      append_offload_options (&argv_obstack, target, linker_opts,
-                             linker_opt_count);
+      append_offload_options (&argv_obstack, target, compiler_opts);
+      append_offload_options (&argv_obstack, target, linker_opts);
 
       obstack_ptr_grow (&argv_obstack, NULL);
       argv = XOBFINISH (&argv_obstack, char **);
@@ -736,10 +760,8 @@ compile_offload_image (const char *targe
 
 static void
 compile_images_for_offload_targets (unsigned in_argc, char *in_argv[],
-                                   struct cl_decoded_option *compiler_opts,
-                                   unsigned int compiler_opt_count,
-                                   struct cl_decoded_option *linker_opts,
-                                   unsigned int linker_opt_count)
+                                   struct lto_decoded_options *compiler_opts,
+                                   struct lto_decoded_options *linker_opts)
 {
   char **names = NULL;
   const char *target_names = getenv (OFFLOAD_TARGET_NAMES_ENV);
@@ -764,8 +786,7 @@ compile_images_for_offload_targets (unsi
 
       offload_names[next_name_entry]
        = compile_offload_image (names[i], compiler_path, in_argc, in_argv,
-                                compiler_opts, compiler_opt_count,
-                                linker_opts, linker_opt_count);
+                                compiler_opts, linker_opts);
       if (!offload_names[next_name_entry])
        fatal_error (input_location,
                     "problem with building target image for %s\n", names[i]);
@@ -837,23 +858,20 @@ find_offloadbeginend (void)
 }
 
 /* A subroutine of run_gcc.  Examine the open file FD for lto sections with
-   name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS
-   and OPT_COUNT.  Return true if we found a matchingn section, false
-   otherwise.  COLLECT_GCC holds the value of the environment variable with
-   the same name.  */
+   name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS.
+   Return true if we found a matchingn section, false otherwise.  COLLECT_GCC
+   holds the value of the environment variable with the same name.  */
 
 static bool
 find_and_merge_options (int fd, off_t file_offset, const char *prefix,
-                       struct cl_decoded_option **opts,
-                       unsigned int *opt_count, const char *collect_gcc)
+                       struct lto_decoded_options *opts,
+                       const char *collect_gcc)
 {
   off_t offset, length;
   char *data;
   char *fopts;
   const char *errmsg;
   int err;
-  struct cl_decoded_option *fdecoded_options = *opts;
-  unsigned int fdecoded_options_count = *opt_count;
 
   simple_object_read *sobj;
   sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO",
@@ -877,21 +895,14 @@ find_and_merge_options (int fd, off_t fi
   fopts = data;
   do
     {
-      struct cl_decoded_option *f2decoded_options;
-      unsigned int f2decoded_options_count;
+      struct lto_decoded_options fdecoded_options;
       get_options_from_collect_gcc_options (collect_gcc,
                                            fopts, CL_LANG_ALL,
-                                           &f2decoded_options,
-                                           &f2decoded_options_count);
-      if (!fdecoded_options)
-       {
-        fdecoded_options = f2decoded_options;
-        fdecoded_options_count = f2decoded_options_count;
-       }
+                                           &fdecoded_options);
+      if (opts->opt == NULL)
+       *opts = fdecoded_options;
       else
-       merge_and_complain (&fdecoded_options,
-                           &fdecoded_options_count,
-                           f2decoded_options, f2decoded_options_count);
+       merge_and_complain (opts, &fdecoded_options);
 
       fopts += strlen (fopts) + 1;
     }
@@ -899,8 +910,6 @@ find_and_merge_options (int fd, off_t fi
 
   free (data);
   simple_object_release_read (sobj);
-  *opts = fdecoded_options;
-  *opt_count = fdecoded_options_count;
   return true;
 }
 
@@ -918,12 +927,9 @@ run_gcc (unsigned argc, char *argv[])
   int parallel = 0;
   int jobserver = 0;
   bool no_partition = false;
-  struct cl_decoded_option *fdecoded_options = NULL;
-  struct cl_decoded_option *offload_fdecoded_options = NULL;
-  unsigned int fdecoded_options_count = 0;
-  unsigned int offload_fdecoded_options_count = 0;
-  struct cl_decoded_option *decoded_options;
-  unsigned int decoded_options_count;
+  struct lto_decoded_options fdecoded_options;
+  struct lto_decoded_options offload_fdecoded_options;
+  struct lto_decoded_options decoded_options;
   struct obstack argv_obstack;
   int new_head_argc;
   bool have_lto = false;
@@ -931,6 +937,8 @@ run_gcc (unsigned argc, char *argv[])
   unsigned lto_argc = 0, offload_argc = 0;
   char **lto_argv, **offload_argv;
 
+  memset (&fdecoded_options, 0, sizeof fdecoded_options);
+  memset (&offload_fdecoded_options, 0, sizeof offload_fdecoded_options);
   /* Get the driver and options.  */
   collect_gcc = getenv ("COLLECT_GCC");
   if (!collect_gcc)
@@ -942,8 +950,7 @@ run_gcc (unsigned argc, char *argv[])
                 "environment variable COLLECT_GCC_OPTIONS must be set");
   get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
                                        CL_LANG_ALL,
-                                       &decoded_options,
-                                       &decoded_options_count);
+                                       &decoded_options);
 
   /* Allocate arrays for input object files with LTO or offload IL,
      and for possible preceding arguments.  */
@@ -978,16 +985,14 @@ run_gcc (unsigned argc, char *argv[])
        }
 
       if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX,
-                                 &fdecoded_options, &fdecoded_options_count,
-                                 collect_gcc))
+                                 &fdecoded_options, collect_gcc))
        {
          have_lto = true;
          lto_argv[lto_argc++] = argv[i];
        }
 
       if (find_and_merge_options (fd, file_offset, OFFLOAD_SECTION_NAME_PREFIX,
-                                 &offload_fdecoded_options,
-                                 &offload_fdecoded_options_count, collect_gcc))
+                                 &offload_fdecoded_options, collect_gcc))
        {
          have_offload = true;
          offload_argv[offload_argc++] = argv[i];
@@ -1002,14 +1007,22 @@ run_gcc (unsigned argc, char *argv[])
   obstack_ptr_grow (&argv_obstack, "-xlto");
   obstack_ptr_grow (&argv_obstack, "-c");
 
-  append_compiler_options (&argv_obstack, fdecoded_options,
-                          fdecoded_options_count);
-  append_linker_options (&argv_obstack, decoded_options, 
decoded_options_count);
+  append_compiler_options (&argv_obstack, &fdecoded_options);
+  append_linker_options (&argv_obstack, &decoded_options);
+  /* If any of the TUs have enabled any undefined behavior sanitizer
+     options, make sure one of them is enabled in lto1, no matter what
+     the linker options say.  It doesn't matter much which undefined
+     behavior sanitizer it is, as long as it is handled only in the FEs
+     or before IPA, and afterwards the instrumentation is present only
+     in the form of builtin functions.  Adding this option makes sure
+     the builtins are initialized in lto1.  */
+  if (fdecoded_options.sanitize_undefined)
+    obstack_ptr_grow (&argv_obstack, "-fsanitize=shift");
 
   /* Scan linker driver arguments for things that are of relevance to us.  */
-  for (j = 1; j < decoded_options_count; ++j)
+  for (j = 1; j < decoded_options.count; ++j)
     {
-      struct cl_decoded_option *option = &decoded_options[j];
+      struct cl_decoded_option *option = &decoded_options.opt[j];
       switch (option->opt_index)
        {
        case OPT_o:
@@ -1092,10 +1105,8 @@ run_gcc (unsigned argc, char *argv[])
   if (have_offload)
     {
       compile_images_for_offload_targets (offload_argc, offload_argv,
-                                         offload_fdecoded_options,
-                                         offload_fdecoded_options_count,
-                                         decoded_options,
-                                         decoded_options_count);
+                                         &offload_fdecoded_options,
+                                         &decoded_options);
       if (offload_names)
        {
          find_offloadbeginend ();

        Jakub

Reply via email to