# DP: Fix PR lto/95604, proposed patch

	PR lto/95604
	* lto-wrapper.c (merge_and_complain): Add decoded options as parameter,
	error on different values for -fcf-protection.
	(append_compiler_options): Pass -fcf-protection option.
	(find_and_merge_options): Add decoded options as parameter,
	pass decoded_options to merge_and_complain.
	(run_gcc): Pass decoded options to find_and_merge_options.
	* lto-opts.c (lto_write_options): Pass -fcf-protection option.

--- a/src/gcc/lto-opts.c
+++ b/src/gcc/lto-opts.c
@@ -94,6 +94,21 @@ lto_write_options (void)
 				      : "-fno-pie");
     }
 
+  if (!global_options_set.x_flag_cf_protection)
+    {
+      append_to_collect_gcc_options (
+        &temporary_obstack, &first_p,
+	global_options.x_flag_cf_protection == CF_NONE
+	? "-fcf-protection=none"
+	: global_options.x_flag_cf_protection == CF_FULL
+	? "-fcf-protection=full"
+	: global_options.x_flag_cf_protection == CF_BRANCH
+	? "-fcf-protection=branch"
+	: global_options.x_flag_cf_protection == CF_RETURN
+	? "-fcf-protection=return"
+	: "");
+    }
+
   /* If debug info is enabled append -g.  */
   if (debug_info_level > DINFO_LEVEL_NONE)
     append_to_collect_gcc_options (&temporary_obstack, &first_p, "-g");
--- a/src/gcc/lto-wrapper.c
+++ b/src/gcc/lto-wrapper.c
@@ -193,11 +193,14 @@ 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)
+		    unsigned int fdecoded_options_count,
+		    struct cl_decoded_option *decoded_cl_options,
+		    unsigned int decoded_cl_options_count)
 {
   unsigned int i, j;
   struct cl_decoded_option *pic_option = NULL;
   struct cl_decoded_option *pie_option = NULL;
+  struct cl_decoded_option *cf_protection_option = NULL;
 
   /* ???  Merge options from files.  Most cases can be
      handled by either unioning or intersecting
@@ -212,6 +215,17 @@ merge_and_complain (struct cl_decoded_op
      In absence of that it's unclear what a good default is.
      It's also difficult to get positional handling correct.  */
 
+  /* Look for a -fcf-protection option in the link-time options
+     which overrides any -fcf-protection from the lto sections.  */
+  for (i = 0; i < decoded_cl_options_count; ++i)
+    {
+      struct cl_decoded_option *foption = &decoded_cl_options[i];
+      if (foption->opt_index == OPT_fcf_protection_)
+	{
+	  cf_protection_option = foption;
+	}
+    }
+  
   /* 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)
@@ -288,6 +302,23 @@ merge_and_complain (struct cl_decoded_op
 			 foption->orig_option_with_args_text);
 	  break;
 
+	case OPT_fcf_protection_:
+	  /* Default to link-time option, else append or check identical.  */
+	  if (!cf_protection_option)
+	    {
+	      for (j = 0; j < *decoded_options_count; ++j)
+		if ((*decoded_options)[j].opt_index == foption->opt_index)
+		  break;
+	      if (j == *decoded_options_count)
+		append_option (decoded_options, decoded_options_count, foption);
+	      else if (strcmp ((*decoded_options)[j].arg, foption->arg))
+		fatal_error (input_location,
+			     "option -fcf-protection with mismatching values"
+			     " (%s, %s)",
+			     (*decoded_options)[j].arg, foption->arg);
+	    }
+	    break;
+
 	case OPT_O:
 	case OPT_Ofast:
 	case OPT_Og:
@@ -631,6 +662,7 @@ append_compiler_options (obstack *argv_o
 	case OPT_fopenacc:
 	case OPT_fopenacc_dim_:
 	case OPT_foffload_abi_:
+	case OPT_fcf_protection_:
 	case OPT_g:
 	case OPT_O:
 	case OPT_Ofast:
@@ -1004,12 +1036,14 @@ find_crtoffloadtable (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
+   and OPT_COUNT.  Return true if we found a matching 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 *decoded_cl_options,
+			unsigned int decoded_cl_options_count,
 			struct cl_decoded_option **opts,
 			unsigned int *opt_count, const char *collect_gcc)
 {
@@ -1056,7 +1090,9 @@ find_and_merge_options (int fd, off_t fi
       else
 	merge_and_complain (&fdecoded_options,
 			    &fdecoded_options_count,
-			    f2decoded_options, f2decoded_options_count);
+			    f2decoded_options, f2decoded_options_count,
+			    decoded_cl_options,
+			    decoded_cl_options_count);
 
       fopts += strlen (fopts) + 1;
     }
@@ -1388,6 +1424,7 @@ run_gcc (unsigned argc, char *argv[])
 	}
 
       if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX,
+				  decoded_options, decoded_options_count,
 				  &fdecoded_options, &fdecoded_options_count,
 				  collect_gcc))
 	{
@@ -1591,6 +1628,7 @@ cont1:
 	    fatal_error (input_location, "cannot open %s: %m", filename);
 	  if (!find_and_merge_options (fd, file_offset,
 				       OFFLOAD_SECTION_NAME_PREFIX,
+				       decoded_options, decoded_options_count,
 				       &offload_fdecoded_options,
 				       &offload_fdecoded_options_count,
 				       collect_gcc))
