PATCH: driver/26885: [4.1/4.2 regression] -m64 -m32 no longer creates 32-bit object

H. J. Lu hjl@lucon.org
Sat Apr 22 23:08:00 GMT 2006


The gcc driver has a generic problem that is if an option is canceled
by another one, gcc stills passes everything down to other programs.
When the order of all options are passed down unmodified, it isn't
a problem. But sometimes spec processing gets into our way, in which
case, the order of options processed by spec is diffeerent from the
command line. This patch implements Negative(XXX) to cancel -XXX in
the gcc driver, as suggested in PR 26885.


H.J.
---
gcc/

2006-04-22  H.J. Lu  <hongjiu.lu@intel.com>

	PR driver/26885
	* Makefile.in (GCC_OBJS): New.
	(OBJS-common): Add opts-common.o.
	(xgcc$(exeext)): Replace gcc.o with $(GCC_OBJS).
	(cpp$(exeext)): Likewise.
	(gcc.o): Also depend on opts.h.
	(opts-common.o): New.

	* common.opt (gcoff): Add Negative(gdwarf-2).
	(gdwarf-2): Add Negative(gstabs).
	(gstabs): Add Negative(gstabs+).
	(gstabs+): Add Negative(gvms).
	(gvms): Add Negative(gxcoff).
	(gxcoff): Add Negative(gxcoff+).
	(gxcoff+): Add Negative(gcoff).
	* config/i386/i386.opt (m32): Add Negative(m64).
	(m64): Add Negative(m32).

	* gcc.c: Include "opts.h".
	(main): Call prune_options after expandargv.

	* optc-gen.awk: Generate common declarations for all flag
	variables in options.c. Output the neg_index field.

	* opts.c (find_opt): Moved to ...
	* opts-common.c: Here. New file.

	* opts.h (cl_option): Add a neg_index field.
	(find_opt): New.
	(prune_options): Likewise.

gcc/cp/

2006-04-22  H.J. Lu  <hongjiu.lu@intel.com>

	PR driver/26885
	* Make-lang.in (GXX_OBJS): Replace gcc.o with $(GCC_OBJS).

gcc/fortran/

2006-04-22  H.J. Lu  <hongjiu.lu@intel.com>

	PR driver/26885
	* Make-lang.in (GFORTRAN_D_OBJS): Replace gcc.o with
	$(GCC_OBJS).

gcc/java/

2006-04-22  H.J. Lu  <hongjiu.lu@intel.com>

	PR driver/26885
	* Make-lang.in ($(GCJ)$(exeext)): Replace gcc.o with
	$(GCC_OBJS).

gcc/treelang/

2006-04-22  H.J. Lu  <hongjiu.lu@intel.com>

	PR driver/26885
	* Make-lang.in (gtreelang$(exeext)): Replace gcc.o with
	$(GCC_OBJS).

--- gcc/Makefile.in.negative	2006-04-21 06:23:55.000000000 -0700
+++ gcc/Makefile.in	2006-04-22 15:51:07.000000000 -0700
@@ -960,6 +960,9 @@ C_TARGET_OBJS=@c_target_objs@
 # Target specific, C++ specific object file
 CXX_TARGET_OBJS=@cxx_target_objs@
 
+# Object files for gcc driver.
+GCC_OBJS = gcc.o opts-common.o options.o
+
 # Language-specific object files for C and Objective C.
 C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
   c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
@@ -1001,7 +1004,7 @@ OBJS-common = \
  haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o insn-modes.o	   \
  insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o	   \
  integrate.o intl.o jump.o  langhooks.o lcm.o lists.o local-alloc.o  	   \
- mode-switching.o modulo-sched.o optabs.o options.o opts.o	   \
+ mode-switching.o modulo-sched.o optabs.o options.o opts.o opts-common.o \
  params.o postreload.o postreload-gcse.o predict.o			   \
  insn-preds.o insn-automata.o pointer-set.o 			   	   \
  print-rtl.o print-tree.o profile.o value-prof.o var-tracking.o		   \
@@ -1305,18 +1308,18 @@ libbackend.a: $(OBJS@onestep@)
 # We call this executable `xgcc' rather than `gcc'
 # to avoid confusion if the current directory is in the path
 # and CC is `gcc'.  It is renamed to `gcc' when it is installed.
-xgcc$(exeext): gcc.o gccspec.o version.o intl.o prefix.o \
+xgcc$(exeext): $(GCC_OBJS) gccspec.o version.o intl.o prefix.o \
    version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
-	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o gccspec.o intl.o \
-	  prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) gccspec.o \
+	  intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
 
 # cpp is to cpp0 as gcc is to cc1.
 # The only difference from xgcc is that it's linked with cppspec.o
 # instead of gccspec.o.
-cpp$(exeext): gcc.o cppspec.o version.o intl.o prefix.o \
+cpp$(exeext): $(GCC_OBJS) cppspec.o version.o intl.o prefix.o \
    version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
-	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o cppspec.o intl.o \
-	  prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) cppspec.o \
+	  intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
 
 # Create links to binutils, especially for in-tree builds, to make -B.
 # use them.  We need hard links so that directories can be shuffled
@@ -1713,7 +1716,7 @@ DRIVER_DEFINES = \
 
 gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h multilib.h \
     Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H) $(FLAGS_H) \
-    configargs.h $(OBSTACK_H)
+    configargs.h $(OBSTACK_H) opts.h
 	(SHLIB_LINK='$(SHLIB_LINK)' \
 	SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
 	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
@@ -2131,6 +2134,8 @@ opts.o : opts.c opts.h options.h toplev.
    coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(RTL_H) \
    output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
    $(FLAGS_H) $(PARAMS_H) tree-pass.h
+opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
+   coretypes.h intl.h
 targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
    $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h toplev.h \
    $(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h
--- gcc/common.opt.negative	2006-03-27 08:37:13.000000000 -0800
+++ gcc/common.opt	2006-04-22 15:05:46.000000000 -0700
@@ -1080,11 +1080,11 @@ Common JoinedOrMissing
 Generate debug information in default format
 
 gcoff
-Common JoinedOrMissing
+Common JoinedOrMissing Negative(gdwarf-2)
 Generate debug information in COFF format
 
 gdwarf-2
-Common JoinedOrMissing
+Common JoinedOrMissing Negative(gstabs)
 Generate debug information in DWARF v2 format
 
 ggdb
@@ -1092,23 +1092,23 @@ Common JoinedOrMissing
 Generate debug information in default extended format
 
 gstabs
-Common JoinedOrMissing
+Common JoinedOrMissing Negative(gstabs+)
 Generate debug information in STABS format
 
 gstabs+
-Common JoinedOrMissing
+Common JoinedOrMissing Negative(gvms)
 Generate debug information in extended STABS format
 
 gvms
-Common JoinedOrMissing
+Common JoinedOrMissing Negative(gxcoff)
 Generate debug information in VMS format
 
 gxcoff
-Common JoinedOrMissing
+Common JoinedOrMissing Negative(gxcoff+)
 Generate debug information in XCOFF format
 
 gxcoff+
-Common JoinedOrMissing
+Common JoinedOrMissing Negative(gcoff)
 Generate debug information in extended XCOFF format
 
 o
--- gcc/config/i386/i386.opt.negative	2006-04-21 06:23:57.000000000 -0700
+++ gcc/config/i386/i386.opt	2006-04-22 14:52:10.000000000 -0700
@@ -24,7 +24,7 @@ Target RejectNegative Report Mask(128BIT
 sizeof(long double) is 16
 
 m32
-Target RejectNegative Report InverseMask(64BIT)
+Target RejectNegative Negative(m64) Report InverseMask(64BIT)
 Generate 32bit i386 code
 
 m386
@@ -40,7 +40,7 @@ Target RejectNegative Undocumented
 ;; Deprecated
 
 m64
-Target RejectNegative Report Mask(64BIT)
+Target RejectNegative Negative(m32) Report Mask(64BIT)
 Generate 64bit x86-64 code
 
 m80387
--- gcc/cp/Make-lang.in.negative	2006-04-16 11:18:32.000000000 -0700
+++ gcc/cp/Make-lang.in	2006-04-22 14:32:30.000000000 -0700
@@ -60,7 +60,7 @@ g++spec.o: $(srcdir)/cp/g++spec.c $(SYST
 		$(INCLUDES) $(srcdir)/cp/g++spec.c)
 
 # Create the compiler driver for g++.
-GXX_OBJS = gcc.o g++spec.o intl.o prefix.o version.o
+GXX_OBJS = $(GCC_OBJS) g++spec.o intl.o prefix.o version.o
 g++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS)
 	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
 	  $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBS)
--- gcc/fortran/Make-lang.in.negative	2006-03-31 07:24:48.000000000 -0800
+++ gcc/fortran/Make-lang.in	2006-04-22 14:32:40.000000000 -0700
@@ -93,7 +93,7 @@ gfortranspec.o: $(srcdir)/fortran/gfortr
 		$(INCLUDES) $(srcdir)/fortran/gfortranspec.c)
 
 # Create the compiler driver gfortran.
-GFORTRAN_D_OBJS = gcc.o gfortranspec.o version.o prefix.o intl.o
+GFORTRAN_D_OBJS = $(GCC_OBJS) gfortranspec.o version.o prefix.o intl.o
 gfortran$(exeext): $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS)
 	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
 	  $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) $(LIBS)
--- gcc/gcc.c.negative	2006-04-21 06:23:55.000000000 -0700
+++ gcc/gcc.c	2006-04-22 10:51:24.000000000 -0700
@@ -86,6 +86,7 @@ compilation is specified by a string cal
 #include "prefix.h"
 #include "gcc.h"
 #include "flags.h"
+#include "opts.h"
 
 /* By default there is no special suffix for target executables.  */
 /* FIXME: when autoconf is fixed, remove the host check - dj */
@@ -6089,6 +6090,8 @@ main (int argc, char **argv)
 
   expandargv (&argc, &argv);
 
+  prune_options (&argc, &argv);
+
 #ifdef GCC_DRIVER_HOST_INITIALIZATION
   /* Perform host dependent initialization when needed.  */
   GCC_DRIVER_HOST_INITIALIZATION;
--- gcc/java/Make-lang.in.negative	2006-03-31 07:24:37.000000000 -0800
+++ gcc/java/Make-lang.in	2006-04-22 14:33:03.000000000 -0700
@@ -67,10 +67,10 @@ jvspec.o: $(srcdir)/java/jvspec.c $(SYST
 		$(INCLUDES) $(srcdir)/java/jvspec.c $(OUTPUT_OPTION))
 
 # Create the compiler driver for $(GCJ).
-$(GCJ)$(exeext): gcc.o jvspec.o version.o \
+$(GCJ)$(exeext): $(GCC_OBJS) jvspec.o version.o \
 	   prefix.o intl.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
-	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o jvspec.o prefix.o intl.o \
-	  version.o $(EXTRA_GCC_OBJS) $(LIBS)
+	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) jvspec.o \
+	  prefix.o intl.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
 
 # Create a version of the $(GCJ) driver which calls the cross-compiler.
 $(GCJ)-cross$(exeext): $(GCJ)$(exeext)
--- gcc/optc-gen.awk.negative	2006-04-22 07:50:37.000000000 -0700
+++ gcc/optc-gen.awk	2006-04-22 14:52:00.000000000 -0700
@@ -62,20 +62,27 @@ for (i = 1; i <= n_headers; i++)
 print "#include " quote "opts.h" quote
 print "#include " quote "intl.h" quote
 print ""
+print "int target_flags;"
+print ""
 
 for (i = 0; i < n_opts; i++) {
 	name = var_name(flags[i]);
 	if (name == "")
 		continue;
 
-	if (flag_set_p("VarExists", flags[i]))
-		continue;
-
-	init = opt_args("Init", flags[i])
-	if (init != "")
-		init = " = " init;
-	else if (name in var_seen)
-		continue;
+	if (flag_set_p("VarExists", flags[i])) {
+		# Need it for the gcc driver.
+		if (name in var_seen)
+			continue;
+		init = ""
+	}
+	else {
+		init = opt_args("Init", flags[i])
+		if (init != "")
+			init = " = " init;
+		else if (name in var_seen)
+			continue;
+	}
 
 	print "/* Set by -" opts[i] "."
 	print "   " help[i] "  */"
@@ -107,8 +114,21 @@ print "const unsigned int cl_options_cou
 
 print "const struct cl_option cl_options[] =\n{"
 
-for (i = 0; i < n_opts; i++)
+j = 0
+for (i = 0; i < n_opts; i++) {
 	back_chain[i] = "N_OPTS";
+	indices[opts[i]] = j;
+	# Combine the flags of identical switches.  Switches
+	# appear many times if they are handled by many front
+	# ends, for example.
+	while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+		flags[i + 1] = flags[i] " " flags[i + 1];
+		i++;
+		back_chain[i] = "N_OPTS";
+		indices[opts[i]] = j;
+	}
+	j++;
+}
 
 for (i = 0; i < n_opts; i++) {
 	# Combine the flags of identical switches.  Switches
@@ -147,8 +167,21 @@ for (i = 0; i < n_opts; i++) {
 	else
 		hlp = quote help[i] quote;
 
-	printf("  { %c-%s%c,\n    %s,\n    %s, %u,\n",
-	       quote, opts[i], quote, hlp, back_chain[i], len)
+	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] ~ "^[Wfm]")
+				idx = indices[opts[i]];
+			else
+				idx = -1;
+		}
+	}
+	printf("  { %c-%s%c,\n    %s,\n    %s, %u, %d,\n",
+	       quote, opts[i], quote, hlp, back_chain[i], len, idx)
 	condition = opt_args("Condition", flags[i])
 	cl_flags = switch_flags(flags[i])
 	if (condition != "")
--- gcc/opts-common.c.negative	2006-04-22 14:52:03.000000000 -0700
+++ gcc/opts-common.c	2006-04-22 15:43:33.000000000 -0700
@@ -0,0 +1,248 @@
+/* Command line option handling.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "intl.h"
+#include "coretypes.h"
+#include "opts.h"
+
+/* Perform a binary search to find which option the command-line INPUT
+   matches.  Returns its index in the option array, and N_OPTS
+   (cl_options_count) on failure.
+
+   This routine is quite subtle.  A normal binary search is not good
+   enough because some options can be suffixed with an argument, and
+   multiple sub-matches can occur, e.g. input of "-pedantic" matching
+   the initial substring of "-pedantic-errors".
+
+   A more complicated example is -gstabs.  It should match "-g" with
+   an argument of "stabs".  Suppose, however, that the number and list
+   of switches are such that the binary search tests "-gen-decls"
+   before having tested "-g".  This doesn't match, and as "-gen-decls"
+   is less than "-gstabs", it will become the lower bound of the
+   binary search range, and "-g" will never be seen.  To resolve this
+   issue, opts.sh makes "-gen-decls" point, via the back_chain member,
+   to "-g" so that failed searches that end between "-gen-decls" and
+   the lexicographically subsequent switch know to go back and see if
+   "-g" causes a match (which it does in this example).
+
+   This search is done in such a way that the longest match for the
+   front end in question wins.  If there is no match for the current
+   front end, the longest match for a different front end is returned
+   (or N_OPTS if none) and the caller emits an error message.  */
+size_t
+find_opt (const char *input, int lang_mask)
+{
+  size_t mn, mx, md, opt_len;
+  size_t match_wrong_lang;
+  int comp;
+
+  mn = 0;
+  mx = cl_options_count;
+
+  /* Find mn such this lexicographical inequality holds:
+     cl_options[mn] <= input < cl_options[mn + 1].  */
+  while (mx - mn > 1)
+    {
+      md = (mn + mx) / 2;
+      opt_len = cl_options[md].opt_len;
+      comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
+
+      if (comp < 0)
+	mx = md;
+      else
+	mn = md;
+    }
+
+  /* This is the switch that is the best match but for a different
+     front end, or cl_options_count if there is no match at all.  */
+  match_wrong_lang = cl_options_count;
+
+  /* Backtrace the chain of possible matches, returning the longest
+     one, if any, that fits best.  With current GCC switches, this
+     loop executes at most twice.  */
+  do
+    {
+      const struct cl_option *opt = &cl_options[mn];
+
+      /* Is the input either an exact match or a prefix that takes a
+	 joined argument?  */
+      if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
+	  && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
+	{
+	  /* If language is OK, return it.  */
+	  if (opt->flags & lang_mask)
+	    return mn;
+
+	  /* If we haven't remembered a prior match, remember this
+	     one.  Any prior match is necessarily better.  */
+	  if (match_wrong_lang == cl_options_count)
+	    match_wrong_lang = mn;
+	}
+
+      /* Try the next possibility.  This is cl_options_count if there
+	 are no more.  */
+      mn = opt->back_chain;
+    }
+  while (mn != cl_options_count);
+
+  /* Return the best wrong match, or cl_options_count if none.  */
+  return match_wrong_lang;
+}
+
+struct gcc_options
+{
+  int idx;
+  int neg;
+};
+
+/* Return true if NEXT_OPT_IDX cancels OPT_IDX.  Return false if the
+   next one is the same ORIG_NEXT_OPT_IDX.  */
+
+static bool
+cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx)
+{
+  /* A negative option can only be canceled by a positive option. A
+     positive option can only be canceled by a negative option or an
+     option with Negative.  */
+  if ((opt_idx < 0
+       && (next_opt_idx > 0
+	   && cl_options [next_opt_idx].neg_index == next_opt_idx
+	   && cl_options [next_opt_idx].neg_index == -opt_idx))
+      || ((next_opt_idx > 0
+	   && cl_options [next_opt_idx].neg_index == opt_idx)
+	  || (next_opt_idx < 0
+	      && cl_options [-next_opt_idx].neg_index == opt_idx)))
+    return true;
+
+  if (opt_idx > 0
+      && next_opt_idx > 0
+      && cl_options [next_opt_idx].neg_index > 0
+      && 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);
+    
+  return false;
+}
+
+/* Filter out options canceled by the ones after them.  */
+
+void
+prune_options (int *argcp, char ***argvp)
+{
+  int argc = *argcp;
+  struct gcc_options *options = xmalloc (argc * sizeof (*options));
+  char **argv = xmalloc (argc * sizeof (char *));
+  int i, arg_count;
+  const struct cl_option *option;
+  size_t opt_index;
+
+  /* Scan all arguments.  */
+  for (i = 1; i < argc; i++)
+    {
+      int value = 1;
+      const char *opt = (*argvp) [i];
+
+      opt_index = find_opt (opt + 1, -1);
+      if (opt_index == cl_options_count
+	  && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
+	  && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
+	{
+	  char *dup;
+
+	  /* Drop the "no-" from negative switches.  */
+	  size_t len = strlen (opt) - 3;
+
+	  dup = XNEWVEC (char, len + 1);
+	  dup[0] = '-';
+	  dup[1] = opt[1];
+	  memcpy (dup + 2, opt + 5, len - 2 + 1);
+	  opt = dup;
+	  value = 0;
+	  opt_index = find_opt (opt + 1, -1);
+	  free (dup);
+	}
+
+      if (opt_index == cl_options_count)
+	{
+cont:
+	  options [i].idx = 0;
+	  options [i].neg = 0;
+	  continue;
+	}
+
+      option = &cl_options[opt_index];
+      if (option->neg_index < 0)
+	goto cont;
+
+      /* Reject negative form of switches that don't take negatives as
+	 unrecognized.  */
+      if (!value)
+	{
+	  if ((option->flags & CL_REJECT_NEGATIVE))
+	    goto cont;
+	  options [i].idx = -(option - cl_options);
+	  options [i].neg = option->neg_index;
+	}
+      else
+	{
+	  options [i].idx = option - cl_options;
+	  options [i].neg = option->neg_index;
+	}
+    }
+
+  /* Remove the argument which is negated by others after it.  */
+  argv [0] = (*argvp) [0];
+  arg_count = 1;
+  for (i = 1; i < argc; i++)
+    {
+      int j, opt_idx;
+
+      opt_idx = options [i].idx;
+      if (opt_idx != 0)
+	{
+	  for (j = i + 1; j < argc; j++)
+	    if (cancel_option (opt_idx, options [j].idx,
+			       options [j].idx))
+	      break;
+	}
+      else
+	goto keep;
+
+      if (j == argc)
+	{
+keep:
+	  argv [arg_count] = (*argvp) [i];
+	  arg_count++;
+	}
+    }
+
+  if (arg_count == argc)
+    free (argv);
+  else
+    {
+      *argcp = arg_count;
+      *argvp = argv;
+    }
+
+  free (options);
+}
+
--- gcc/opts.c.negative	2006-04-21 06:23:56.000000000 -0700
+++ gcc/opts.c	2006-04-22 10:50:23.000000000 -0700
@@ -108,7 +108,6 @@ static bool flag_peel_loops_set, flag_br
 const char **in_fnames;
 unsigned num_in_fnames;
 
-static size_t find_opt (const char *, int);
 static int common_handle_option (size_t scode, const char *arg, int value,
 				 unsigned int lang_mask);
 static void handle_param (const char *);
@@ -127,90 +126,6 @@ static unsigned int print_switch (const 
 static void set_debug_level (enum debug_info_type type, int extended,
 			     const char *arg);
 
-/* Perform a binary search to find which option the command-line INPUT
-   matches.  Returns its index in the option array, and N_OPTS
-   (cl_options_count) on failure.
-
-   This routine is quite subtle.  A normal binary search is not good
-   enough because some options can be suffixed with an argument, and
-   multiple sub-matches can occur, e.g. input of "-pedantic" matching
-   the initial substring of "-pedantic-errors".
-
-   A more complicated example is -gstabs.  It should match "-g" with
-   an argument of "stabs".  Suppose, however, that the number and list
-   of switches are such that the binary search tests "-gen-decls"
-   before having tested "-g".  This doesn't match, and as "-gen-decls"
-   is less than "-gstabs", it will become the lower bound of the
-   binary search range, and "-g" will never be seen.  To resolve this
-   issue, opts.sh makes "-gen-decls" point, via the back_chain member,
-   to "-g" so that failed searches that end between "-gen-decls" and
-   the lexicographically subsequent switch know to go back and see if
-   "-g" causes a match (which it does in this example).
-
-   This search is done in such a way that the longest match for the
-   front end in question wins.  If there is no match for the current
-   front end, the longest match for a different front end is returned
-   (or N_OPTS if none) and the caller emits an error message.  */
-static size_t
-find_opt (const char *input, int lang_mask)
-{
-  size_t mn, mx, md, opt_len;
-  size_t match_wrong_lang;
-  int comp;
-
-  mn = 0;
-  mx = cl_options_count;
-
-  /* Find mn such this lexicographical inequality holds:
-     cl_options[mn] <= input < cl_options[mn + 1].  */
-  while (mx - mn > 1)
-    {
-      md = (mn + mx) / 2;
-      opt_len = cl_options[md].opt_len;
-      comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
-
-      if (comp < 0)
-	mx = md;
-      else
-	mn = md;
-    }
-
-  /* This is the switch that is the best match but for a different
-     front end, or cl_options_count if there is no match at all.  */
-  match_wrong_lang = cl_options_count;
-
-  /* Backtrace the chain of possible matches, returning the longest
-     one, if any, that fits best.  With current GCC switches, this
-     loop executes at most twice.  */
-  do
-    {
-      const struct cl_option *opt = &cl_options[mn];
-
-      /* Is the input either an exact match or a prefix that takes a
-	 joined argument?  */
-      if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
-	  && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
-	{
-	  /* If language is OK, return it.  */
-	  if (opt->flags & lang_mask)
-	    return mn;
-
-	  /* If we haven't remembered a prior match, remember this
-	     one.  Any prior match is necessarily better.  */
-	  if (match_wrong_lang == cl_options_count)
-	    match_wrong_lang = mn;
-	}
-
-      /* Try the next possibility.  This is cl_options_count if there
-	 are no more.  */
-      mn = opt->back_chain;
-    }
-  while (mn != cl_options_count);
-
-  /* Return the best wrong match, or cl_options_count if none.  */
-  return match_wrong_lang;
-}
-
 /* If ARG is a non-negative integer made up solely of digits, return its
    value, otherwise return -1.  */
 static int
--- gcc/opts.h.negative	2006-02-01 16:55:37.000000000 -0800
+++ gcc/opts.h	2006-04-22 13:44:59.000000000 -0700
@@ -46,6 +46,7 @@ struct cl_option
   const char *help;
   unsigned short back_chain;
   unsigned char opt_len;
+  int neg_index;
   unsigned int flags;
   void *flag_var;
   enum cl_var_type var_type;
@@ -84,6 +85,8 @@ extern const char **in_fnames;
 
 extern unsigned num_in_fnames;
 
+size_t find_opt (const char *input, int lang_mask);
+extern void prune_options (int *argcp, char ***argvp);
 extern void decode_options (unsigned int argc, const char **argv);
 extern int option_enabled (int opt_idx);
 extern bool get_option_state (int, struct cl_option_state *);
--- gcc/treelang/Make-lang.in.negative	2006-03-31 07:24:50.000000000 -0800
+++ gcc/treelang/Make-lang.in	2006-04-22 14:33:47.000000000 -0700
@@ -87,10 +87,10 @@ tree1$(exeext): treelang/tree1.o treelan
 	$(BACKEND) $(LIBS) attribs.o
 
 # Create the compiler driver treelang.
-gtreelang$(exeext): gcc.o version.o prefix.o intl.o $(EXTRA_GCC_OBJS) \
+gtreelang$(exeext): $(GCC_OBJS) version.o prefix.o intl.o $(EXTRA_GCC_OBJS) \
   $(LIBDEPS) treelang/spec.o
 	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ treelang/spec.o \
-	  gcc.o version.o prefix.o intl.o $(EXTRA_GCC_OBJS) $(LIBS)
+	  $(GCC_OBJS) version.o prefix.o intl.o $(EXTRA_GCC_OBJS) $(LIBS)
 
 
 



More information about the Gcc-patches mailing list