I have been fixing a bug. It involved the Negative property of options, and I have some confusion about it.
gcc/optc-gen.awk: 383 neg = opt_args("Negative", flags[i]); if (neg != "") idx = indices[neg] else { if (flag_set_p("RejectNegative", flags[i])) idx = -1; else { if (opts[i] ~ "^[Wfgm]") idx = indices[opts[i]]; else idx = -1; } } Above is the code that handles the ‘Nagetive’ property. I don't see why the 'idx' should be set -1 when 'RejectNegative'. As I understand it, ‘Negative’ and ‘RejectNegative’ are similar name, but not related in implementation. The following is my implementation about it: --- a/gcc/doc/options.texi +++ b/gcc/doc/options.texi @@ -220,11 +220,7 @@ property is used. The option will turn off another option @var{othername}, which is the option name with the leading ``-'' removed. This chain action will propagate through the @code{Negative} property of the option to be -turned off. The driver will prune options, removing those that are -turned off by some later option. This pruning is not done for options -with @code{Joined} or @code{JoinedOrMissing} properties, unless the -options have either @code{RejectNegative} property or the @code{Negative} -property mentions an option other than itself. +turned off. As a consequence, if you have a group of mutually-exclusive options, their @code{Negative} properties should form a circular chain. diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk index 880ac77..d32354c 100644 --- a/gcc/optc-gen.awk +++ b/gcc/optc-gen.awk @@ -383,7 +383,9 @@ for (i = 0; i < n_opts; i++) { if (neg != "") idx = indices[neg] else { - if (flag_set_p("RejectNegative", flags[i])) + if (flag_set_p("Joined", flags[i]) \ + || flag_set_p("JoinedOrMissing", flags[i]) \ + || flag_set_p("Separate", flags[i])) idx = -1; else { if (opts[i] ~ "^[Wfgm]") diff --git a/gcc/opts-common.c b/gcc/opts-common.c index 5e10ede..898e8d8 100644 --- a/gcc/opts-common.c +++ b/gcc/opts-common.c @@ -1039,11 +1039,12 @@ cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx) if (cl_options [next_opt_idx].neg_index == opt_idx) return true; - if (cl_options [next_opt_idx].neg_index != orig_next_opt_idx) - return cancel_option (opt_idx, cl_options [next_opt_idx].neg_index, - orig_next_opt_idx); + if (cl_options [next_opt_idx].neg_index == orig_next_opt_idx + || cl_options [next_opt_idx].neg_index < 0) + return false; - return false; + return cancel_option (opt_idx, cl_options [next_opt_idx].neg_index, + orig_next_opt_idx); } /* Filter out options canceled by the ones after them. */ @@ -1088,14 +1089,6 @@ prune_options (struct cl_decoded_option **decoded_options, default: gcc_assert (opt_idx < cl_options_count); option = &cl_options[opt_idx]; - if (option->neg_index < 0) - goto keep; - - /* Skip joined switches. */ - if ((option->flags & CL_JOINED) - && (!option->cl_reject_negative - || (unsigned int) option->neg_index != opt_idx)) - goto keep; for (j = i + 1; j < old_decoded_options_count; j++) { @@ -1104,13 +1097,6 @@ prune_options (struct cl_decoded_option **decoded_options, next_opt_idx = old_decoded_options[j].opt_index; if (next_opt_idx >= cl_options_count) continue; - if (cl_options[next_opt_idx].neg_index < 0) - continue; - if ((cl_options[next_opt_idx].flags & CL_JOINED) - && (!cl_options[next_opt_idx].cl_reject_negative - || ((unsigned int) cl_options[next_opt_idx].neg_index - != next_opt_idx))) - continue; if (cancel_option (opt_idx, next_opt_idx, next_opt_idx)) break; } -- 2.7.4