https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86517
--- Comment #7 from Jan Hubicka <hubicka at ucw dot cz> --- Hi, I am attaching patch I am testing and also table generated by a script that walks through individual combinations of options. The combination rules are as follows. I tried to take into account that targets may default to some form of PIC or PIE. That is why, for example combining -fpic and empty options results in empty options and no no-pic. Note that in addition to lto-wrapper option merging we now have logic that disables PIC/PIE when final binary is built based on lto-plugion output (it knows if it builds binary, relocatable binary, library or incrementally links). Still we rely on the merging to choose particular form of PIC/PIE and we need it right in incremental link where linker does not help us. -fpic + -fpic => -fpic -fpic + -fPIC => -fpic -fpic + -fpie => -fpie -fpic + -fPIE => -fpie -fpic + -fno-pic => -fno-pic -fpic + -fno-pie => -fpic + => -fPIC + -fpic => -fpic -fPIC + -fPIC => -fPIC -fPIC + -fpie => -fpie -fPIC + -fPIE => -fPIE -fPIC + -fno-pic => -fno-pic -fPIC + -fno-pie => -fPIC + => -fpie + -fpic => -fpie -fpie + -fPIC => -fpie -fpie + -fpie => -fpie -fpie + -fPIE => -fpie -fpie + -fno-pic => -fpie + -fno-pie => -fpie + => -fPIE + -fpic => -fpie -fPIE + -fPIC => -fPIE -fPIE + -fpie => -fpie -fPIE + -fPIE => -fPIE -fPIE + -fno-pic => -fPIE + -fno-pie => -fPIE + => -fno-pic + -fpic => -fno-pic -fno-pic + -fPIC => -fno-pic -fno-pic + -fpie => -fno-pic -fno-pic + -fPIE => -fno-pic -fno-pic + -fno-pic => -fno-pic -fno-pic + -fno-pie => -fno-pic -fno-pic + => -fno-pic -fno-pie + -fpic => -fno-pie -fno-pie + -fPIC => -fno-pie -fno-pie + -fpie => -fno-pie -fno-pie + -fPIE => -fno-pie -fno-pie + -fno-pic => -fno-pie -fno-pie + -fno-pie => -fno-pie -fno-pie + => -fno-pie -fpic + => -fPIC + => -fpie + => -fPIE + => -fno-pic + => -fno-pie + => + => Index: lto-wrapper.c =================================================================== --- lto-wrapper.c (revision 262682) +++ lto-wrapper.c (working copy) @@ -408,6 +408,11 @@ merge_and_complain (struct cl_decoded_op It is a common mistake to mix few -fPIC compiled objects into otherwise non-PIC code. We do not want to build everything with PIC then. + Similarly we merge PIE options, however in addition we keep + -fPIC + -fPIE = -fPIE + -fpic + -fPIE = -fpie + -fPIC/-fpic + -fpie = -fpie + It would be good to warn on mismatches, but it is bit hard to do as we do not know what nothing translates to. */ @@ -415,11 +420,34 @@ merge_and_complain (struct cl_decoded_op if ((*decoded_options)[j].opt_index == OPT_fPIC || (*decoded_options)[j].opt_index == OPT_fpic) { - if (!pic_option - || (pic_option->value > 0) != ((*decoded_options)[j].value > 0)) - remove_option (decoded_options, j, decoded_options_count); - else if (pic_option->opt_index == OPT_fPIC - && (*decoded_options)[j].opt_index == OPT_fpic) + /* -fno-pic in one unit implies -fno-pic everywhere. */ + if ((*decoded_options)[j].value == 0) + j++; + /* If we have no pic option or merge in -fno-pic, we still may turn + existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present. */ + else if ((pic_option && pic_option->value == 0) + || !pic_option) + { + if (pie_option && pie_option->value > 0) + { + bool big = (*decoded_options)[j].opt_index == OPT_fPIC + && pie_option->opt_index == OPT_fPIE; + (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie; + (*decoded_options)[j].canonical_option[0] = big ? "-fPIE" : "-fpie"; + j++; + } + else if (pic_option) + { + (*decoded_options)[j] = *pic_option; + j++; + } + /* We do not know if target defaults to pic or not, so just remove + option if it is missing in one unit but enabled in other. */ + else + remove_option (decoded_options, j, decoded_options_count); + } + else if (pic_option->opt_index == OPT_fpic + && (*decoded_options)[j].opt_index == OPT_fPIC) { (*decoded_options)[j] = *pic_option; j++; @@ -430,11 +458,37 @@ merge_and_complain (struct cl_decoded_op else if ((*decoded_options)[j].opt_index == OPT_fPIE || (*decoded_options)[j].opt_index == OPT_fpie) { - if (!pie_option - || pie_option->value != (*decoded_options)[j].value) - remove_option (decoded_options, j, decoded_options_count); - else if (pie_option->opt_index == OPT_fPIE - && (*decoded_options)[j].opt_index == OPT_fpie) + /* -fno-pie in one unit implies -fno-pie everywhere. */ + if ((*decoded_options)[j].value == 0) + j++; + /* If we have no pie option or merge in -fno-pie, we still preserve + PIE/pie if pic/PIC is present. */ + else if ((pie_option && pie_option->value == 0) + || !pie_option) + { + /* If -fPIC/-fpic is given, merge it with -fPIE/-fpie. */ + if (pic_option && pic_option->value > 0) + { + if (pic_option->opt_index == OPT_fpic + && (*decoded_options)[j].opt_index == OPT_fPIE) + { + (*decoded_options)[j].opt_index = OPT_fpie; + (*decoded_options)[j].canonical_option[0] = "-fpie"; + } + j++; + } + /* Target may default to pic. */ + else if (pie_option && pic_option) + { + (*decoded_options)[j] = *pie_option; + j++; + } + /* Target may default to pie. */ + else + remove_option (decoded_options, j, decoded_options_count); + } + else if (pie_option->opt_index == OPT_fpie + && (*decoded_options)[j].opt_index == OPT_fPIE) { (*decoded_options)[j] = *pie_option; j++;