Intermodule patch

Geoffrey Keating gkeating@apple.com
Wed Jul 9 18:59:00 GMT 2003


This is the current version of my intermodule optimization patch.  I
plan to commit this just as soon as the tree can bootstrap again on
Darwin (grrr).

It still doesn't have a testsuite.  That's being worked on, but it
turns out to be hard.  However, it can be tested, by bootstrapping GCC
with the new --enable-intermodule configure option; although to really
enjoy a debugging session, you want to add 'CFLAGS=-O3' as well (I
hope that one day this will actually work).

New features in this version:

- --enable-intermodule
- struct cgraph needs chain_next and chain_prev options to make GCC
  bootstrap with --enable-intermodule, or it'll run out of stack
  space due to having (tens of?) thousands of entries in the chain.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/imi-7.patch===============================
2003-07-09  Geoffrey Keating  <geoffk@apple.com>

	* configure.in (onstep): Support --enable-intermodule.
	* Makefile.in (OBJS-common): New.
	(OBJS-md): New.
	(OBJS-archive): New.
	(OBJS): Build from OBJS-common, OBJS-md, OBJS-archive.
	(OBJS-onestep): New.
	(libbackend.a): Support @onestep@.
	(libbackend.o): New.
	* configure: Regenerate.
	
	* c-common.h (c_reset_state): New prototype.
	(c_parse_file): New prototype.
	(finish_file): Move prototype from c-tree.h.
	* c-decl.c: Include <hashtab.h>.
	(builtin_decls): New.
	(current_file_decl): New.
	(duplicate_decls): Add extra parameter. Change all callers.  Don't
	output duplicate common symbols.
	(link_hash_hash): New.
	(link_hash_eq): New.
	(poplevel): Handle popping of the top level.
	(warn_if_shadowing): Handle TRANSLATION_UNIT_DECL.
	(pushdecl): Set DECL_CONTEXT to TRANSLATION_UNIT_DECL if appropriate.
	(pushdecl_top_level): Likewise.
	(redeclaration_error_message): Handle TRANSLATION_UNIT_DECL.
	(c_init_decl_processing): Create TRANSLATION_UNIT_DECL.
	(finish_decl): Handle TRANSLATION_UNIT_DECL.
	(merge_translation_unit_decls): New.
	(c_write_global_declarations): New.
	(c_reset_state): New.
	* c-lang.c (LANG_HOOKS_WRITE_GLOBALS): New.
	* c-objc-common.c (c_cannot_inline_tree_fn): Handle
	TRANSLATION_UNIT_DECL.
	(c_objc_common_finish_file): Call merge_translation_unit_decls.
	* c-opts.c (in_fnames): Rename from in_fname.
	(c_common_decode_option): Handle multiple input filenames.
	(c_common_post_options): Likewise.
	(c_common_parse_file): Likewise; also, call c_parse_file rather than
	yyparse.
	* c-parse.in: Move cleanup code to c_parse_file.
	(free_parser_stacks): Move contents to c_parse_file.
	(c_parse_file): New.
	* c-tree.h (union lang_tree_node): Chain along TYPE_NEXT_VARIANT
	for integer types.
	(finish_file): Move prototype to c-common.h.
	(merge_translation_unit_decls): New prototype.
	(comptypes): Add extra parameter to prototype.
	(c_write_global_declarations): New prototype.
	* c-typeck.c (tagged_types_tu_compatible_p): New.
	(function_types_compatible_p): Add extra parameter, change all callers.
	(type_lists_compatible_p): Likewise.
	(comptypes): Likewise.
	(struct tagged_tu_seen): New.
	(tagged_tu_seen_base): New.
	(build_unary_op): Handle TRANSLATION_UNIT_DECL.
	(c_mark_addressable): Remove #if 0 code.
	* calls.c (special_function_p): Handle TRANSLATION_UNIT_DECL, add
	comment explaining why it shouldn't have to.
	* cppinit.c (cpp_read_next_file): New.
	(cpp_read_main_file): Use it.
	* cpplib.c (undefine_macros): New.
	(cpp_undef_all): New.
	* cpplib.h (cpp_read_next_file): Prototype.
	(cpp_undef_all): Prototype.
	* langhooks-def.h (write_global_declarations): Remove prototype.
	* toplev.h (write_global_declarations): Add prototype.
	* tree.c (decl_type_context): Use switch statement, handle
	TRANSLATION_UNIT_DECL.
	* tree.def: Update documentation for TRANSLATION_UNIT_DECL.
	(TRANSLATION_UNIT_DECL): New kind of tree.
	* tree.h: Update documentation for TRANSLATION_UNIT_DECL.
	* Makefile.in (c-decl.o): Add $(HASHTAB_H) to dependencies.
	* doc/invoke.texi: Make attempt to document new functionality.

	2003-05-19  Per Bothner <bothner@apple.com>

	* gcc.c (combine_inputs): New.
	(process_command): Set combine_inputs.
	(do_spec_1): Handle combine_inputs.
	(main): Likewise.

Index: cp/ChangeLog
2003-07-09  Geoffrey Keating  <geoffk@apple.com>

	* cp-lang.c (c_reset_state): New dummy routine.
	* cp-tree.h (finish_file): Move prototype to c-common.h.
	* parser.c (c_parse_file): Rename from yyparse; don't call finish_file.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1110
diff -u -p -u -p -r1.1110 Makefile.in
--- Makefile.in	9 Jul 2003 12:12:27 -0000	1.1110
+++ Makefile.in	9 Jul 2003 18:43:51 -0000
@@ -801,7 +801,8 @@ C_OBJS = c-parse.o c-lang.o c-pretty-pri
 
 # Language-independent object files.
 
-OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	   \
+OBJS-common = \
+ alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	  	   \
  cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o		   \
  cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o	   \
  cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o 	   \
@@ -809,7 +810,7 @@ OBJS = alias.o bb-reorder.o bitmap.o bui
  dwarf2asm.o dwarf2out.o dwarfout.o emit-rtl.o except.o explow.o	   \
  expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o		   \
  genrtl.o ggc-common.o global.o graph.o gtype-desc.o			   \
- haifa-sched.o hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o	   \
+ haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.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  	   \
  loop.o optabs.o options.o opts.o params.o postreload.o predict.o	   \
@@ -820,9 +821,16 @@ OBJS = alias.o bb-reorder.o bitmap.o bui
  sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o	   \
  sibcall.o simplify-rtx.o sreal.o ssa.o ssa-ccp.o ssa-dce.o stmt.o	   \
  stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
- tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
- alloc-pool.o et-forest.o cgraph.o cgraphunit.o cfghooks.o bt-load.o	   \
- $(GGC) $(out_object_file) $(EXTRA_OBJS) $(host_hook_obj)
+ unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o		   \
+ alloc-pool.o et-forest.o cfghooks.o bt-load.o $(GGC)
+
+OBJS-md = $(out_object_file)
+OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) hashtable.o tree-inline.o	   \
+  cgraph.o cgraphunit.o
+
+OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
+
+OBJS-onestep = libbackend.o $(OBJS-archive)
 
 BACKEND = main.o libbackend.a
 
@@ -1026,9 +1034,9 @@ rest.cross: $(LIBGCC) specs
 compilations: $(BACKEND)
 
 # Like libcpp.a, this archive is strictly for the host.
-libbackend.a: $(OBJS)
+libbackend.a: $(OBJS@onestep@)
 	-rm -rf libbackend.a
-	$(AR) $(AR_FLAGS) libbackend.a $(OBJS)
+	$(AR) $(AR_FLAGS) libbackend.a $(OBJS@onestep@)
 	-$(RANLIB) libbackend.a
 
 # We call this executable `xgcc' rather than `gcc'
@@ -1815,6 +1823,15 @@ mips-tdump: mips-tdump.o version.o $(LIB
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tdump.o version.o $(LIBS)
 
 mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h $(TM_H) version.h
+
+# FIXME: writing proper dependencies for this is a *LOT* of work.
+libbackend.o : $(OBJS-common:.o=.c) $(out_file) \
+  insn-config.h insn-flags.h insn-codes.h insn-constants.h \
+  insn-attr.h options_.h
+	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	  -DTARGET_NAME=\"$(target_alias)\" \
+	  -DLOCALEDIR=\"$(localedir)\" \
+	  -c $(filter %.c,$^) -o $@
 
 #
 # Generate header and source files from the machine description,
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.189
diff -u -p -u -p -r1.189 c-common.h
--- c-common.h	9 Jul 2003 00:31:10 -0000	1.189
+++ c-common.h	9 Jul 2003 18:43:51 -0000
@@ -963,6 +963,14 @@ extern bool c_promoting_integer_type_p (
 extern int self_promoting_args_p (tree);
 extern tree strip_array_types (tree);
 
+/* This function resets the parsers' state in preparation for parsing
+   a new file.  */
+extern void c_reset_state			PARAMS ((void));
+/* This is the basic parsing function.  */
+extern void c_parse_file			PARAMS ((void));
+/* This is misnamed, it actually performs end-of-compilation processing.  */
+extern void finish_file				PARAMS ((void));
+
 /* These macros provide convenient access to the various _STMT nodes.  */
 
 /* Nonzero if this statement should be considered a full-expression,
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.403
diff -u -p -u -p -r1.403 c-decl.c
--- c-decl.c	9 Jul 2003 00:31:13 -0000	1.403
+++ c-decl.c	9 Jul 2003 18:43:52 -0000
@@ -127,6 +127,14 @@ static GTY(()) tree shadowed_labels;
    some other global meaning for that identifier.  */
 static GTY(()) tree truly_local_externals;
 
+/* A list of the builtin file-scope DECLs.  */
+
+static GTY(()) tree builtin_decls;
+
+/* A DECL for the current file-scope context.  */
+
+static GTY(()) tree current_file_decl;
+
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
@@ -265,7 +273,7 @@ tree static_ctors, static_dtors;
 
 static struct binding_level *make_binding_level (void);
 static void pop_binding_level (struct binding_level **);
-static int duplicate_decls (tree, tree, int);
+static int duplicate_decls (tree, tree, int, int);
 static int redeclaration_error_message (tree, tree);
 static void implicit_decl_warning (tree);
 static void storedecls (tree);
@@ -282,6 +290,8 @@ static void record_external_decl (tree);
 static void warn_if_shadowing (tree, tree);
 static void clone_underlying_type (tree);
 static bool flexible_array_type_p (tree);
+static hashval_t link_hash_hash	(const void *);
+static int link_hash_eq (const void *, const void *);
 
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
@@ -482,8 +492,12 @@ poplevel (int keep, int reverse, int fun
   /* We used to warn about unused variables in expand_end_bindings,
      i.e. while generating RTL.  But in function-at-a-time mode we may
      choose to never expand a function at all (e.g. auto inlining), so
-     we do this explicitly now.  */
-  warn_about_unused_variables (decls);
+     we do this explicitly now.
+     No warnings when the global scope is popped because the global
+     scope isn't popped for the last translation unit, so the warnings
+     are done in c_write_global_declaration.  */
+  if (current_binding_level != global_binding_level)
+    warn_about_unused_variables (decls);
 
   /* Clear out the name-meanings declared on this level.
      Propagate TREE_ADDRESSABLE from nested functions to their
@@ -492,7 +506,8 @@ poplevel (int keep, int reverse, int fun
     {
       if (DECL_NAME (link) != 0)
 	{
-	  if (DECL_EXTERNAL (link))
+	  if (DECL_EXTERNAL (link) 
+	      && current_binding_level != global_binding_level)
 	    /* External decls stay in the symbol-value slot but are
 	       inaccessible.  */
 	    C_DECL_INVISIBLE (link) = 1;
@@ -626,7 +641,7 @@ poplevel (int keep, int reverse, int fun
   /* Dispose of the block that we just made inside some higher level.  */
   if (functionbody)
     DECL_INITIAL (current_function_decl) = block;
-  else if (block)
+  else if (block && current_binding_level)
     current_binding_level->blocks
       = chainon (current_binding_level->blocks, block);
   /* If we did not make a block for the level just exited,
@@ -634,7 +649,7 @@ poplevel (int keep, int reverse, int fun
      (since they cannot be recorded as subblocks in that level)
      must be carried forward so they will later become subblocks
      of something else.  */
-  else if (subblocks)
+  else if (! block && subblocks)
     current_binding_level->blocks
       = chainon (current_binding_level->blocks, subblocks);
 
@@ -784,9 +799,13 @@ pushtag (tree name, tree type)
    and OLDDECL is in an outer binding level and should thus not be changed.  */
 
 static int
-duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
+duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
+		 int different_tu)
 {
-  int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+  int comptype_flags = (different_tu ? COMPARE_DIFFERENT_TU
+			: COMPARE_STRICT);
+  int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl),
+			       comptype_flags);
   int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
 			   && DECL_INITIAL (newdecl) != 0);
   tree oldtype = TREE_TYPE (olddecl);
@@ -908,7 +927,7 @@ duplicate_decls (tree newdecl, tree oldd
 	      trytype = build_type_attribute_variant (trytype,
 						      TYPE_ATTRIBUTES (oldtype));
 
-              types_match = comptypes (newtype, trytype);
+              types_match = comptypes (newtype, trytype, comptype_flags);
 	      if (types_match)
 		oldtype = trytype;
 	    }
@@ -931,7 +950,7 @@ duplicate_decls (tree newdecl, tree oldd
 	      trytype = build_type_attribute_variant (trytype,
 						      TYPE_ATTRIBUTES (oldtype));
 
-	      types_match = comptypes (newtype, trytype);
+	      types_match = comptypes (newtype, trytype, comptype_flags);
 	      if (types_match)
 		oldtype = trytype;
 	    }
@@ -1030,7 +1049,7 @@ duplicate_decls (tree newdecl, tree oldd
 		 && ! pedantic
 		 /* Return types must still match.  */
 		 && comptypes (TREE_TYPE (oldtype),
-			       TREE_TYPE (newtype))
+			       TREE_TYPE (newtype), comptype_flags)
 		 && TYPE_ARG_TYPES (newtype) == 0))
     {
       error_with_decl (newdecl, "conflicting types for `%s'");
@@ -1038,7 +1057,7 @@ duplicate_decls (tree newdecl, tree oldd
 	 involving an empty arglist vs a nonempty one.  */
       if (TREE_CODE (olddecl) == FUNCTION_DECL
 	  && comptypes (TREE_TYPE (oldtype),
-			TREE_TYPE (newtype))
+			TREE_TYPE (newtype), comptype_flags)
 	  && ((TYPE_ARG_TYPES (oldtype) == 0
 	       && DECL_INITIAL (olddecl) == 0)
 	      ||
@@ -1166,7 +1185,8 @@ duplicate_decls (tree newdecl, tree oldd
 		}
 	      /* Type for passing arg must be consistent
 		 with that declared for the arg.  */
-	      if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
+	      if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type),
+			       comptype_flags))
 		{
 		  error_with_decl (newdecl,
 				   "prototype for `%s' follows and argument %d doesn't match",
@@ -1393,7 +1413,7 @@ duplicate_decls (tree newdecl, tree oldd
     }
   if (DECL_EXTERNAL (newdecl))
     {
-      if (! different_binding_level)
+      if (! different_binding_level || different_tu)
 	{
 	  /* Don't mess with these flags on local externs; they remain
 	     external even if there's a declaration at file scope which
@@ -1404,7 +1424,13 @@ duplicate_decls (tree newdecl, tree oldd
       /* An extern decl does not override previous storage class.  */
       TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
       if (! DECL_EXTERNAL (newdecl))
-	DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
+	{
+	  DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
+	  /* If we have two non-EXTERNAL file-scope decls that are
+	     the same, only one of them should be written out.  */
+	  if (different_tu)
+	    TREE_ASM_WRITTEN (newdecl) = 1;
+	}
     }
   else
     {
@@ -1586,7 +1612,8 @@ warn_if_shadowing (tree x, tree old)
 
   if (TREE_CODE (old) == PARM_DECL)
     shadow_warning (SW_PARAM, name, old);
-  else if (DECL_CONTEXT (old) == 0)
+  else if (DECL_CONTEXT (old) == 0
+	   || TREE_CODE (DECL_CONTEXT (old)) == TRANSLATION_UNIT_DECL)
     shadow_warning (SW_GLOBAL, name, old);
   else
     shadow_warning (SW_LOCAL, name, old);
@@ -1685,12 +1712,13 @@ pushdecl (tree x)
   /* A local extern declaration for a function doesn't constitute nesting.
      A local auto declaration does, since it's a forward decl
      for a nested function coming later.  */
-  if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
-      && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
-    DECL_CONTEXT (x) = 0;
+  if (current_function_decl == NULL
+      || ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+	  && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x)))
+    DECL_CONTEXT (x) = current_file_decl;
   else
     DECL_CONTEXT (x) = current_function_decl;
-
+  
   if (name)
     {
       tree old;
@@ -1703,7 +1731,7 @@ pushdecl (tree x)
 		 IDENTIFIER_POINTER (name));
 
       old = lookup_name_current_level (name);
-      if (old && duplicate_decls (x, old, 0))
+      if (old && duplicate_decls (x, old, 0, false))
 	return old;
       if (DECL_EXTERNAL (x) || scope == global_binding_level)
 	{
@@ -1714,7 +1742,8 @@ pushdecl (tree x)
 	  tree ext = any_external_decl (name);
 	  if (ext)
 	    {
-	      if (duplicate_decls (x, ext, scope != global_binding_level))
+	      if (duplicate_decls (x, ext, scope != global_binding_level, 
+				   false))
 		x = copy_node (ext);
 	    }
 	  else
@@ -1788,13 +1817,13 @@ pushdecl_top_level (tree x)
       if (DECL_CONTEXT (old))
 	abort ();
 
-      if (!duplicate_decls (x, old, 0))
+      if (!duplicate_decls (x, old, 0, false))
 	abort ();
 
       return old;
     }
 
-  DECL_CONTEXT (x) = 0;
+  DECL_CONTEXT (x) = current_file_decl;
   IDENTIFIER_SYMBOL_VALUE (name) = x;
   TREE_CHAIN (x) = global_binding_level->names;
   global_binding_level->names = x;
@@ -1935,7 +1964,8 @@ redeclaration_error_message (tree newdec
 	return 1;
       return 0;
     }
-  else if (DECL_CONTEXT (newdecl) == NULL_TREE)
+  else if (DECL_CONTEXT (newdecl) == NULL_TREE
+	   || TREE_CODE (DECL_CONTEXT (newdecl)) == TRANSLATION_UNIT_DECL)
     {
       /* Objects declared at top level:  */
       /* If at least one is a reference, it's ok.  */
@@ -2245,6 +2275,9 @@ c_init_decl_processing (void)
   input_location.file = "<internal>";
   input_location.line = 0;
 
+  /* Make the DECL for the toplevel file scope.  */
+  current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
+
   build_common_tree_nodes (flag_signed_char);
 
   c_common_nodes_and_builtins ();
@@ -2277,6 +2310,8 @@ c_init_decl_processing (void)
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
+
+  builtin_decls = global_binding_level->names;
 }
 
 /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -2860,7 +2895,8 @@ finish_decl (tree decl, tree init, tree 
       if (c_dialect_objc ())
 	objc_check_decl (decl);
 
-      if (!DECL_CONTEXT (decl))
+      if (!DECL_CONTEXT (decl) 
+	  || TREE_CODE (DECL_CONTEXT (decl)) == TRANSLATION_UNIT_DECL)
 	{
 	  if (DECL_INITIAL (decl) == NULL_TREE
 	      || DECL_INITIAL (decl) == error_mark_node)
@@ -5970,7 +6006,8 @@ store_parm_decls (void)
 		 declared for the arg.  ISO C says we take the unqualified
 		 type for parameters declared with qualified type.  */
 	      if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
-			       TYPE_MAIN_VARIANT (TREE_VALUE (type))))
+			       TYPE_MAIN_VARIANT (TREE_VALUE (type)),
+			       COMPARE_STRICT))
 		{
 		  if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
 		      == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
@@ -6749,6 +6786,181 @@ make_pointer_declarator (tree type_quals
   if (attrs != NULL_TREE)
     itarget = tree_cons (attrs, target, NULL_TREE);
   return build1 (INDIRECT_REF, quals, itarget);
+}
+
+/* Hash and equality functions for link_hash_table: key off
+   DECL_ASSEMBLER_NAME.  */
+
+static hashval_t
+link_hash_hash (x_p)
+     const void *x_p;
+{
+  tree x = (tree)x_p;
+  return (hashval_t) DECL_ASSEMBLER_NAME (x);
+}
+
+static int
+link_hash_eq (x1_p, x2_p)
+     const void *x1_p;
+     const void *x2_p;
+{
+  tree x1 = (tree)x1_p;
+  tree x2 = (tree)x2_p;
+  return DECL_ASSEMBLER_NAME (x1) == DECL_ASSEMBLER_NAME (x2);
+}
+
+/* Propagate information between definitions and uses between multiple
+   translation units in TU_LIST based on linkage rules.  */
+
+void
+merge_translation_unit_decls PARAMS((void))
+{
+  const tree tu_list = current_file_decl;
+  tree tu;
+  tree decl;
+  htab_t link_hash_table;
+  tree block;
+  
+  /* Create the BLOCK that poplevel would have created, but don't
+     actually call poplevel since that's expensive.  */
+  block = make_node (BLOCK);
+  BLOCK_VARS (block) = current_binding_level->names;
+  TREE_USED (block) = 1;
+  DECL_INITIAL (current_file_decl) = block;
+
+  /* If only one translation unit seen, no copying necessary.  */
+  if (TREE_CHAIN (tu_list) == NULL_TREE)
+    return;
+
+  link_hash_table = htab_create (1021, link_hash_hash, link_hash_eq, NULL);
+
+  /* Enter any actual definitions into the hash table.  */
+  for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
+    for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
+      if (TREE_PUBLIC (decl) && ! DECL_EXTERNAL (decl))
+	{
+	  PTR *slot;
+	  slot = htab_find_slot (link_hash_table, decl, INSERT);
+
+	  /* If we've already got a definition, work out which one is
+	     the real one, put it into the hash table, and make the
+	     other one DECL_EXTERNAL.  This is important to avoid
+	     putting out two definitions of the same symbol in the
+	     assembly output.  */
+	  if (*slot != NULL)
+	    {
+	      tree old_decl = (tree) *slot;
+
+	      /* If this is weak or common or whatever, suppress it
+		 in favour of the other definition.  */
+	      if (DECL_WEAK (decl))
+		DECL_EXTERNAL (decl) = 1;
+	      else if (DECL_WEAK (old_decl) && ! DECL_WEAK (decl))
+		DECL_EXTERNAL (old_decl) = 1;
+	      else if (DECL_COMMON (decl) || DECL_ONE_ONLY (decl))
+		DECL_EXTERNAL (decl) = 1;
+	      else if (DECL_COMMON (old_decl) || DECL_ONE_ONLY (old_decl))
+		DECL_EXTERNAL (old_decl) = 1;
+	      
+	      if (DECL_EXTERNAL (decl))
+		{
+		  DECL_INITIAL (decl) = NULL_TREE;
+		  DECL_COMMON (decl) = 0;
+		  DECL_ONE_ONLY (decl) = 0;
+		  DECL_WEAK (decl) = 0;
+		}
+	      else if (DECL_EXTERNAL (old_decl))
+		{
+		  DECL_INITIAL (old_decl) = NULL_TREE;
+		  DECL_COMMON (old_decl) = 0;
+		  DECL_ONE_ONLY (old_decl) = 0;
+		  DECL_WEAK (old_decl) = 0;
+		  *slot = decl;
+		}
+	      else
+		{
+		  error_with_decl (decl, "redefinition of global `%s'");
+		  error_with_decl (old_decl, "`%s' previously defined here");
+		}
+	    }
+	  else
+	    *slot = decl;
+	}
+
+  /* Now insert the desired information from all the definitions
+     into any plain declarations.  */
+  for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
+    for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
+      if (TREE_PUBLIC (decl) && DECL_EXTERNAL (decl))
+	{
+	  tree global_decl;
+	  global_decl = (tree) htab_find (link_hash_table, decl);
+	  
+	  if (! global_decl)
+	    continue;
+	  
+	  /* Print any appropriate error messages, and partially merge
+	     the decls.  */
+	  (void) duplicate_decls (decl, global_decl, true, true);
+	}
+
+  htab_delete (link_hash_table);
+}
+
+/* Perform final processing on file-scope data.  */
+
+void
+c_write_global_declarations()
+{
+  tree link;
+  
+  for (link = current_file_decl; link; link = TREE_CHAIN (link))
+    {
+      tree globals = BLOCK_VARS (DECL_INITIAL (link));
+      int len = list_length (globals);
+      tree *vec = (tree *) xmalloc (sizeof (tree) * len);
+      int i;
+      tree decl;
+      
+      /* Process the decls in reverse order--earliest first.
+	 Put them into VEC from back to front, then take out from front.  */
+      
+      for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+	vec[len - i - 1] = decl;
+      
+      wrapup_global_declarations (vec, len);
+      
+      check_global_declarations (vec, len);
+      
+      /* Clean up.  */
+      free (vec);
+    }
+}
+
+/* Reset the parser's state in preparation for a new file.  */
+
+void
+c_reset_state ()
+{
+  tree link;
+  tree file_scope_decl;
+  
+  /* Pop the global binding level.  */
+  if (current_binding_level != global_binding_level)
+      current_binding_level = global_binding_level;
+  file_scope_decl = current_file_decl;
+  DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0);
+  truly_local_externals = NULL_TREE;
+
+  /* Start a new global binding level.  */
+  pushlevel (0);
+  global_binding_level = current_binding_level;
+  current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
+  TREE_CHAIN (current_file_decl) = file_scope_decl;
+
+  /* Reintroduce the global declarations.  */
+  for (link = builtin_decls; link; link = TREE_CHAIN (link))
+    pushdecl (copy_node (link));
 }
 
 #include "gt-c-decl.h"
Index: c-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-lang.c,v
retrieving revision 1.108
diff -u -p -u -p -r1.108 c-lang.c
--- c-lang.c	9 Jul 2003 00:31:13 -0000	1.108
+++ c-lang.c	9 Jul 2003 18:43:52 -0000
@@ -125,6 +125,9 @@ enum c_language_kind c_language = clk_c;
 #undef LANG_HOOKS_TYPE_PROMOTES_TO
 #define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
 
+#undef LANG_HOOKS_WRITE_GLOBALS
+#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
+
 /* ### When changing hooks, consider if ObjC needs changing too!! ### */
 
 /* Each front end provides its own.  */
Index: c-objc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.27
diff -u -p -u -p -r1.27 c-objc-common.c
--- c-objc-common.c	9 Jul 2003 00:31:13 -0000	1.27
+++ c-objc-common.c	9 Jul 2003 18:43:52 -0000
@@ -184,7 +184,8 @@ c_cannot_inline_tree_fn (tree *fnp)
 	goto cannot_inline;
     }
 
-  if (DECL_CONTEXT (fn))
+  if (DECL_CONTEXT (fn) 
+      && TREE_CODE (DECL_CONTEXT (fn)) != TRANSLATION_UNIT_DECL)
     {
       /* If a nested function has pending sizes, we may have already
          saved them.  */
@@ -356,6 +357,10 @@ c_objc_common_finish_file (void)
 {
   if (pch_file)
     c_common_write_pch ();
+
+  /* If multiple translation units were built, copy information between
+     them based on linkage rules.  */
+  merge_translation_unit_decls ();
 
   if (flag_unit_at_a_time)
     {
Index: c-opts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-opts.c,v
retrieving revision 1.71
diff -u -p -u -p -r1.71 c-opts.c
--- c-opts.c	8 Jul 2003 05:25:39 -0000	1.71
+++ c-opts.c	9 Jul 2003 18:43:52 -0000
@@ -52,7 +52,8 @@ static int saved_lineno;
 static cpp_options *cpp_opts;
 
 /* Input filename.  */
-static const char *in_fname;
+static const char **in_fnames;
+static unsigned num_in_fnames;
 
 /* Filename and stream for preprocessed output.  */
 static const char *out_fname;
@@ -1039,12 +1040,9 @@ c_common_handle_option (size_t scode, co
 void
 c_common_handle_filename (const char *filename)
 {
-  if (!in_fname)
-    in_fname = filename;
-  else if (!out_fname)
-    out_fname = filename;
-  else
-    error ("output filename specified twice");
+  num_in_fnames++;
+  in_fnames = xrealloc (in_fnames, num_in_fnames * sizeof (in_fnames[0]));
+  in_fnames[num_in_fnames - 1] = filename;
 }
 
 /* Post-switch processing.  */
@@ -1052,8 +1050,13 @@ bool
 c_common_post_options (const char **pfilename)
 {
   /* Canonicalize the input and output filenames.  */
-  if (in_fname == NULL || !strcmp (in_fname, "-"))
-    in_fname = "";
+  if (in_fnames == NULL)
+    {
+      in_fnames = xmalloc (sizeof (in_fnames[0]));
+      in_fnames[0] = "";
+    }
+  else if (strcmp (in_fnames[0], "-") == 0)
+    in_fnames[0] = "";
 
   if (out_fname == NULL || !strcmp (out_fname, "-"))
     out_fname = "";
@@ -1119,6 +1122,10 @@ c_common_post_options (const char **pfil
 	  return false;
 	}
 
+      if (num_in_fnames > 1)
+	error ("too many filenames given.  Type %s --help for usage",
+	       progname);
+
       init_pp_output (out_stream);
     }
   else
@@ -1132,7 +1139,7 @@ c_common_post_options (const char **pfil
   cpp_get_callbacks (parse_in)->file_change = cb_file_change;
 
   /* NOTE: we use in_fname here, not the one supplied.  */
-  *pfilename = cpp_read_main_file (parse_in, in_fname);
+  *pfilename = cpp_read_main_file (parse_in, in_fnames[0]);
 
   saved_lineno = input_line;
   input_line = 0;
@@ -1176,23 +1183,45 @@ c_common_init (void)
   return true;
 }
 
-/* A thin wrapper around the real parser that initializes the
-   integrated preprocessor after debug output has been initialized.
-   Also, make sure the start_source_file debug hook gets called for
-   the primary source file.  */
+/* Initialize the integrated preprocessor after debug output has been
+   initialized;  make sure the start_source_file debug hook gets
+   called for each primary source file; loop over each input file.  */
 void
 c_common_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
 {
+  unsigned file_index;
+  
 #if YYDEBUG != 0
   yydebug = set_yydebug;
 #else
   warning ("YYDEBUG not defined");
 #endif
 
-  finish_options();
-  pch_init();
-  yyparse ();
+  file_index = 0;
+  
+  do
+    {
+      if (file_index > 0)
+	{
+	  /* Reset the state of the parser.  */
+	  c_reset_state();
+
+	  /* Reset cpplib's macros and start a new file.  */
+	  cpp_undef_all (parse_in);
+	  cpp_read_next_file (parse_in, in_fnames[file_index]);
+	}
+
+      (*debug_hooks->start_source_file) (input_line, input_filename);
+      finish_options();
+      if (file_index == 0)
+	pch_init();
+      c_parse_file ();
+
+      file_index++;
+    } while (file_index < num_in_fnames);
+  
   free_parser_stacks ();
+  finish_file ();
 }
 
 /* Common finish hook for the C, ObjC and C++ front ends.  */
Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.170
diff -u -p -u -p -r1.170 c-parse.in
--- c-parse.in	7 Jul 2003 17:57:12 -0000	1.170
+++ c-parse.in	9 Jul 2003 18:43:52 -0000
@@ -352,20 +352,8 @@ c_parse_init (void)
 program: /* empty */
 		{ if (pedantic)
 		    pedwarn ("ISO C forbids an empty source file");
-		  finish_file ();
 		}
 	| extdefs
-		{
-		  /* In case there were missing closebraces,
-		     get us back to the global binding level.  */
-		  while (! global_bindings_p ())
-		    poplevel (0, 0, 0);
-		  /* __FUNCTION__ is defined at file scope ("").  This
-		     call may not be necessary as my tests indicate it
-		     still works without it.  */
-		  finish_fname_decls ();
-                  finish_file ();
-		}
 	;
 
 /* the reason for the strange actions in this rule
@@ -718,7 +706,7 @@ primary:
 		  e1 = TYPE_MAIN_VARIANT (groktypename ($3));
 		  e2 = TYPE_MAIN_VARIANT (groktypename ($5));
 
-		  $$ = comptypes (e1, e2)
+		  $$ = comptypes (e1, e2, COMPARE_STRICT)
 		    ? build_int_2 (1, 0) : build_int_2 (0, 0);
 		}
 	| primary '[' expr ']'   %prec '.'
@@ -3795,10 +3783,27 @@ yyprint (FILE *file, int yychar, YYSTYPE
 void
 free_parser_stacks (void)
 {
+}
+
+/* Parse the file.  */
+void
+c_parse_file ()
+{
+  yyparse ();
+  /* In case there were missing closebraces, get us back to the global
+     binding level.  */
+  while (! global_bindings_p ())
+    poplevel (0, 0, 0);
+  /* __FUNCTION__ is defined at file scope ("").  This
+     call may not be necessary as my tests indicate it
+     still works without it.  */
+  finish_fname_decls ();
+
   if (malloced_yyss)
     {
       free (malloced_yyss);
       free (malloced_yyvs);
+      malloced_yyss = 0;
     }
 }
 
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.118
diff -u -p -u -p -r1.118 c-tree.h
--- c-tree.h	4 Jul 2003 01:55:47 -0000	1.118
+++ c-tree.h	9 Jul 2003 18:43:52 -0000
@@ -46,7 +46,7 @@ struct lang_identifier GTY(())
 
 union lang_tree_node 
   GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-       chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
 {
   union tree_node GTY ((tag ("0"), 
 			desc ("tree_node_structure (&%h)"))) 
@@ -157,7 +157,6 @@ extern tree lookup_interface (tree);
 extern tree is_class_name (tree);
 extern tree objc_is_id (tree);
 extern void objc_check_decl (tree);
-extern void finish_file (void);
 extern int objc_comptypes (tree, tree, int);
 extern tree objc_message_selector (void);
 extern tree lookup_objc_ivar (tree);
@@ -226,6 +225,7 @@ extern tree c_begin_compound_stmt (void)
 extern void c_expand_deferred_function (tree);
 extern void c_expand_decl_stmt (tree);
 extern tree make_pointer_declarator (tree, tree);
+extern void merge_translation_unit_decls (void);
 
 /* in c-objc-common.c */
 extern int c_disregard_inline_limits (tree);
@@ -242,9 +242,17 @@ extern bool c_warn_unused_global_decl (t
 			  ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
 
 #define c_sizeof_nowarn(T)  c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 0)
+
 /* in c-typeck.c */
+
+/* For use with comptypes.  */
+enum {
+  COMPARE_STRICT = 0,
+  COMPARE_DIFFERENT_TU = 1
+};
+
 extern tree require_complete_type (tree);
-extern int comptypes (tree, tree);
+extern int comptypes (tree, tree, int);
 extern tree c_size_in_bytes (tree);
 extern bool c_mark_addressable (tree);
 extern void c_incomplete_type_error (tree, tree);
@@ -301,6 +309,7 @@ extern int system_header_p;
 
 /* In c-decl.c */
 extern void c_finish_incomplete_decl (tree);
+extern void c_write_global_declarations (void);
 
 extern GTY(()) tree static_ctors;
 extern GTY(()) tree static_dtors;
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.242
diff -u -p -u -p -r1.242 c-typeck.c
--- c-typeck.c	6 Jul 2003 18:59:38 -0000	1.242
+++ c-typeck.c	9 Jul 2003 18:43:53 -0000
@@ -53,9 +53,10 @@ static int missing_braces_mentioned;
 static int undeclared_variable_notice;
 
 static tree qualify_type (tree, tree);
+static int tagged_types_tu_compatible_p	(tree, tree, int);
 static int comp_target_types (tree, tree, int);
-static int function_types_compatible_p (tree, tree);
-static int type_lists_compatible_p (tree, tree);
+static int function_types_compatible_p (tree, tree, int);
+static int type_lists_compatible_p (tree, tree, int);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
@@ -409,7 +410,8 @@ common_type (tree t1, tree t2)
 		tree memb;
 		for (memb = TYPE_FIELDS (TREE_VALUE (p1));
 		     memb; memb = TREE_CHAIN (memb))
-		  if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2)))
+		  if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2), 
+				 COMPARE_STRICT))
 		    {
 		      TREE_VALUE (n) = TREE_VALUE (p2);
 		      if (pedantic)
@@ -423,7 +425,8 @@ common_type (tree t1, tree t2)
 		tree memb;
 		for (memb = TYPE_FIELDS (TREE_VALUE (p2));
 		     memb; memb = TREE_CHAIN (memb))
-		  if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1)))
+		  if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1), 
+				 COMPARE_STRICT))
 		    {
 		      TREE_VALUE (n) = TREE_VALUE (p1);
 		      if (pedantic)
@@ -452,7 +455,7 @@ common_type (tree t1, tree t2)
    but a warning may be needed if you use them together.  */
 
 int
-comptypes (tree type1, tree type2)
+comptypes (tree type1, tree type2, int flags)
 {
   tree t1 = type1;
   tree t2 = type2;
@@ -512,11 +515,11 @@ comptypes (tree type1, tree type2)
     {
     case POINTER_TYPE:
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-	      ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
+	      ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags));
       break;
 
     case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2);
+      val = function_types_compatible_p (t1, t2, flags);
       break;
 
     case ARRAY_TYPE:
@@ -529,7 +532,8 @@ comptypes (tree type1, tree type2)
 
 	/* Target types must match incl. qualifiers.  */
 	if (TREE_TYPE (t1) != TREE_TYPE (t2)
-	    && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))
+	    && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2),
+				      flags)))
 	  return 0;
 
 	/* Sizes must match unless one is missing or variable.  */
@@ -561,6 +565,11 @@ comptypes (tree type1, tree type2)
     case RECORD_TYPE:
       if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1)
 	val = 1;
+
+    case ENUMERAL_TYPE:
+    case UNION_TYPE:
+      if (val != 1 && (flags & COMPARE_DIFFERENT_TU))
+	val = tagged_types_tu_compatible_p (t1, t2, flags);
       break;
 
     case VECTOR_TYPE:
@@ -592,7 +601,7 @@ comp_target_types (tree ttl, tree ttr, i
     return val;
 
   val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
-		   TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
+		   TYPE_MAIN_VARIANT (TREE_TYPE (ttr)), COMPARE_STRICT);
 
   if (val == 2 && pedantic)
     pedwarn ("types are not quite compatible");
@@ -601,6 +610,159 @@ comp_target_types (tree ttl, tree ttr, i
 
 /* Subroutines of `comptypes'.  */
 
+/* The C standard says that two structures in different translation
+   units are compatible with each other only if the types of their
+   fields are compatible (among other things).  So, consider two copies
+   of this structure:  */
+
+struct tagged_tu_seen {
+  const struct tagged_tu_seen * next;
+  tree t1;
+  tree t2;
+};
+
+/* Can they be compatible with each other?  We choose to break the
+   recursion by allowing those types to be compatible.  */
+
+static const struct tagged_tu_seen * tagged_tu_seen_base;
+
+/* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are
+   compatible.  If the two types are not the same (which has been
+   checked earlier), this can only happen when multiple translation
+   units are being compiled.  See C99 6.2.7 paragraph 1 for the exact
+   rules.  */
+
+static int
+tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
+{
+  tree s1, s2;
+  bool needs_warning = false;
+  
+  /* We have to verify that the tags of the types are the same.  This
+     is harder than it looks because this may be a typedef, so we have
+     to go look at the original type.  It may even be a typedef of a
+     typedef... */
+  while (TYPE_NAME (t1) && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL)
+    t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
+
+  while (TYPE_NAME (t2) && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL)
+    t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
+
+  /* C90 didn't have the requirement that the two tags be the same.  */
+  if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2))
+    return 0;
+  
+  /* C90 didn't say what happened if one or both of the types were
+     incomplete; we choose to follow C99 rules here, which is that they
+     are compatible.  */
+  if (TYPE_SIZE (t1) == NULL
+      || TYPE_SIZE (t2) == NULL)
+    return 1;
+  
+  {
+    const struct tagged_tu_seen * tts_i;
+    for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
+      if (tts_i->t1 == t1 && tts_i->t2 == t2)
+	return 1;
+  }
+  
+  switch (TREE_CODE (t1))
+    {
+    case ENUMERAL_TYPE:
+      {
+	if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
+	  return 0;
+	
+	for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
+	  {
+	    s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
+	    if (s2 == NULL
+		|| simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
+	      return 0;
+	  }
+	return 1;
+      }
+
+    case UNION_TYPE:
+      {
+	if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
+	  return 0;
+
+	for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
+	  {
+	    bool ok = false;
+	    struct tagged_tu_seen tts;
+
+	    tts.next = tagged_tu_seen_base;
+	    tts.t1 = t1;
+	    tts.t2 = t2;
+	    tagged_tu_seen_base = &tts;
+	
+	    if (DECL_NAME (s1) != NULL)
+	      for (s2 = TYPE_VALUES (t2); s2; s2 = TREE_CHAIN (s2))
+		if (DECL_NAME (s1) == DECL_NAME (s2))
+		  {
+		    int result;
+		    result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags);
+		    if (result == 0)
+		      break;
+		    if (result == 2)
+		      needs_warning = true;
+		    
+		    if (TREE_CODE (s1) == FIELD_DECL
+			&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+					     DECL_FIELD_BIT_OFFSET (s2)) != 1)
+		      break;
+
+		    ok = true;
+		    break;
+		  }
+	    tagged_tu_seen_base = tts.next;
+	    if (! ok)
+	      return 0;
+	  }
+	return needs_warning ? 2 : 1;
+      }
+
+    case RECORD_TYPE:
+      {
+	struct tagged_tu_seen tts;
+	
+	tts.next = tagged_tu_seen_base;
+	tts.t1 = t1;
+	tts.t2 = t2;
+	tagged_tu_seen_base = &tts;
+	  
+	for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); 
+	     s1 && s2;
+	     s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+	  {
+	    int result;
+	    if (TREE_CODE (s1) != TREE_CODE (s2)
+		|| DECL_NAME (s1) != DECL_NAME (s2))
+	      break;
+	    result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags);
+	    if (result == 0)
+	      break;
+	    if (result == 2)
+	      needs_warning = true;
+	    
+	    if (TREE_CODE (s1) == FIELD_DECL
+		&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+				     DECL_FIELD_BIT_OFFSET (s2)) != 1)
+	      break;
+	  }
+	tagged_tu_seen_base = tts.next;
+	if (s1 && s2)
+	  return 0;
+	return needs_warning ? 2 : 1;
+      }
+
+    default:
+      abort ();
+    }
+}
+
 /* Return 1 if two function types F1 and F2 are compatible.
    If either type specifies no argument types,
    the other must specify a fixed number of self-promoting arg types.
@@ -609,7 +771,7 @@ comp_target_types (tree ttl, tree ttr, i
    Otherwise, the argument types must match.  */
 
 static int
-function_types_compatible_p (tree f1, tree f2)
+function_types_compatible_p (tree f1, tree f2, int flags)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -630,7 +792,7 @@ function_types_compatible_p (tree f1, tr
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
 				 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes (ret1, ret2);
+  val = comptypes (ret1, ret2, flags);
   if (val == 0)
     return 0;
 
@@ -648,7 +810,8 @@ function_types_compatible_p (tree f1, tr
 	 compare that with the other type's arglist.
 	 If they don't match, ask for a warning (but no error).  */
       if (TYPE_ACTUAL_ARG_TYPES (f1)
-	  && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1)))
+	  && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
+					   flags))
 	val = 2;
       return val;
     }
@@ -657,13 +820,14 @@ function_types_compatible_p (tree f1, tr
       if (!self_promoting_args_p (args1))
 	return 0;
       if (TYPE_ACTUAL_ARG_TYPES (f2)
-	  && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2)))
+	  && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
+					   flags))
 	val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2);
+  val1 = type_lists_compatible_p (args1, args2, flags);
   return val1 != 1 ? val1 : val;
 }
 
@@ -672,7 +836,7 @@ function_types_compatible_p (tree f1, tr
    or 2 for compatible with warning.  */
 
 static int
-type_lists_compatible_p (tree args1, tree args2)
+type_lists_compatible_p (tree args1, tree args2, int flags)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -701,7 +865,8 @@ type_lists_compatible_p (tree args1, tre
 	    return 0;
 	}
       else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
-				      TYPE_MAIN_VARIANT (TREE_VALUE (args2)))))
+				      TYPE_MAIN_VARIANT (TREE_VALUE (args2)),
+				      flags)))
 	{
 	  /* Allow  wait (union {union wait *u; int *i} *)
 	     and  wait (union wait *)  to be compatible.  */
@@ -715,7 +880,8 @@ type_lists_compatible_p (tree args1, tre
 	      tree memb;
 	      for (memb = TYPE_FIELDS (TREE_VALUE (args1));
 		   memb; memb = TREE_CHAIN (memb))
-		if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2)))
+		if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2),
+			       flags))
 		  break;
 	      if (memb == 0)
 		return 0;
@@ -730,7 +896,8 @@ type_lists_compatible_p (tree args1, tre
 	      tree memb;
 	      for (memb = TYPE_FIELDS (TREE_VALUE (args2));
 		   memb; memb = TREE_CHAIN (memb))
-		if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1)))
+		if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1),
+			       flags))
 		  break;
 	      if (memb == 0)
 		return 0;
@@ -3031,7 +3198,8 @@ build_unary_op (enum tree_code code, tre
 	   file-scope function counts as a constant.  */
 	if (staticp (arg)
 	    && ! (TREE_CODE (arg) == FUNCTION_DECL
-		  && DECL_CONTEXT (arg) != 0))
+		  && DECL_CONTEXT (arg) != 0
+		  && TREE_CODE (DECL_CONTEXT (arg)) != TRANSLATION_UNIT_DECL))
 	  TREE_CONSTANT (addr) = 1;
 	return addr;
       }
@@ -3258,6 +3426,7 @@ c_mark_addressable (tree exp)
 	/* drops in */
       case FUNCTION_DECL:
 	TREE_ADDRESSABLE (x) = 1;
+	/* drops out */
       default:
 	return true;
     }
@@ -3523,7 +3692,7 @@ build_c_cast (tree type, tree expr)
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
 	if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
-		       TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+		       TYPE_MAIN_VARIANT (TREE_TYPE (value)), COMPARE_STRICT))
 	  break;
 
       if (field)
@@ -3917,7 +4086,7 @@ convert_for_assignment (tree type, tree 
      This code doesn't fully support references, it's just for the
      special case of va_start and va_copy.  */
   if (codel == REFERENCE_TYPE
-      && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
+      && comptypes (TREE_TYPE (type), TREE_TYPE (rhs), COMPARE_STRICT) == 1)
     {
       if (!lvalue_p (rhs))
 	{
@@ -3966,7 +4135,7 @@ convert_for_assignment (tree type, tree 
 	  tree memb_type = TREE_TYPE (memb_types);
 
 	  if (comptypes (TYPE_MAIN_VARIANT (memb_type),
-			 TYPE_MAIN_VARIANT (rhstype)))
+			 TYPE_MAIN_VARIANT (rhstype), COMPARE_STRICT))
 	    break;
 
 	  if (TREE_CODE (memb_type) != POINTER_TYPE)
@@ -4543,7 +4712,7 @@ digest_init (tree type, tree init, int r
 	  && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
 	{
 	  if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-			 TYPE_MAIN_VARIANT (type)))
+			 TYPE_MAIN_VARIANT (type), COMPARE_STRICT))
 	    return inside_init;
 
 	  if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
@@ -4585,12 +4754,13 @@ digest_init (tree type, tree init, int r
      vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
      below and handle as a constructor.  */
     if (code == VECTOR_TYPE
-        && comptypes (TREE_TYPE (inside_init), type)
+        && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)
         && TREE_CONSTANT (inside_init))
       {
 	if (TREE_CODE (inside_init) == VECTOR_CST
 	    && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-			  TYPE_MAIN_VARIANT (type)))
+			  TYPE_MAIN_VARIANT (type),
+			  COMPARE_STRICT))
 	  return inside_init;
 	else
 	  return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
@@ -4601,16 +4771,16 @@ digest_init (tree type, tree init, int r
 
   if (inside_init && TREE_TYPE (inside_init) != 0
       && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-		     TYPE_MAIN_VARIANT (type))
+		     TYPE_MAIN_VARIANT (type), COMPARE_STRICT)
 	  || (code == ARRAY_TYPE
-	      && comptypes (TREE_TYPE (inside_init), type))
+	      && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
 	  || (code == VECTOR_TYPE
-	      && comptypes (TREE_TYPE (inside_init), type))
+	      && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
 	  || (code == POINTER_TYPE
 	      && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
 		  || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)
 	      && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
-			    TREE_TYPE (type)))))
+			    TREE_TYPE (type), COMPARE_STRICT))))
     {
       if (code == POINTER_TYPE)
 	inside_init = default_function_array_conversion (inside_init);
@@ -6039,7 +6209,7 @@ output_init_element (tree value, tree ty
 	       && TREE_CODE (type) == ARRAY_TYPE
 	       && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
 	  && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
-			 TYPE_MAIN_VARIANT (type))))
+			 TYPE_MAIN_VARIANT (type), COMPARE_STRICT)))
     value = default_conversion (value);
 
   if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.285
diff -u -p -u -p -r1.285 calls.c
--- calls.c	9 Jul 2003 01:17:26 -0000	1.285
+++ calls.c	9 Jul 2003 18:43:53 -0000
@@ -600,8 +600,14 @@ special_function_p (tree fndecl, int fla
       && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
       /* Exclude functions not at the file scope, or not `extern',
 	 since they are not the magic functions we would otherwise
-	 think they are.  */
-      && DECL_CONTEXT (fndecl) == NULL_TREE && TREE_PUBLIC (fndecl))
+	 think they are.
+         FIXME: this should be handled with attributes, not with this
+         hacky imitation of DECL_ASSEMBLER_NAME.  It's (also) wrong
+         because you can declare fork() inside a function if you
+         wish.  */
+      && (DECL_CONTEXT (fndecl) == NULL_TREE 
+	  || TREE_CODE (DECL_CONTEXT (fndecl)) == TRANSLATION_UNIT_DECL)
+      && TREE_PUBLIC (fndecl))
     {
       const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
       const char *tname = name;
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.11
diff -u -p -u -p -r1.11 cgraph.h
--- cgraph.h	9 Jul 2003 01:20:22 -0000	1.11
+++ cgraph.h	9 Jul 2003 18:43:53 -0000
@@ -62,7 +62,7 @@ struct cgraph_rtl_info GTY(())
 /* The cgraph data strutcture.
    Each function decl has assigned cgraph_node listing callees and callers.  */
 
-struct cgraph_node GTY(())
+struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
 {
   tree decl;
   struct cgraph_edge *callees;
Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.701
diff -u -p -u -p -r1.701 configure.in
--- configure.in	9 Jul 2003 11:48:18 -0000	1.701
+++ configure.in	9 Jul 2003 18:43:54 -0000
@@ -569,6 +569,16 @@ AC_SUBST(TARGET_SYSTEM_ROOT)
 AC_SUBST(TARGET_SYSTEM_ROOT_DEFINE)
 AC_SUBST(CROSS_SYSTEM_HEADER_DIR)
 
+# Build with intermodule optimisations
+local_prefix=
+AC_ARG_ENABLE(intermodule,
+[  --enable-intermodule    build the compiler in one step],
+[case "${enable_intermodule}" in
+  yes) onestep=-onestep : ;;
+  *) onestep= : ;;
+esac])
+AC_SUBST(onestep)
+
 # -------------------------
 # Checks for other programs
 # -------------------------
Index: cppinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppinit.c,v
retrieving revision 1.285
diff -u -p -u -p -r1.285 cppinit.c
--- cppinit.c	5 Jul 2003 00:23:48 -0000	1.285
+++ cppinit.c	9 Jul 2003 18:43:54 -0000
@@ -427,6 +427,17 @@ cpp_add_dependency_target (cpp_reader *p
   deps_add_target (pfile->deps, target, quote);
 }
 
+/* This sets up for processing input from the file FNAME.  
+   It returns false on error.  */
+bool
+cpp_read_next_file (pfile, fname)
+     cpp_reader *pfile;
+     const char *fname;
+{
+  /* Open the main input file.  */
+  return _cpp_read_file (pfile, fname);
+}
+
 /* This is called after options have been parsed, and partially
    processed.  Setup for processing input from the file named FNAME,
    or stdin if it is the empty string.  Return the original filename
@@ -451,9 +462,8 @@ cpp_read_main_file (cpp_reader *pfile, c
       deps_add_default_target (pfile->deps, fname);
     }
 
-  /* Open the main input file.  */
   pfile->line = 1;
-  if (!_cpp_read_file (pfile, fname))
+  if (!cpp_read_next_file (pfile, fname))
     return NULL;
 
   /* Set this here so the client can change the option if it wishes,
Index: cpplib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.c,v
retrieving revision 1.341
diff -u -p -u -p -r1.341 cpplib.c
--- cpplib.c	5 Jul 2003 00:23:52 -0000	1.341
+++ cpplib.c	9 Jul 2003 18:43:54 -0000
@@ -109,6 +109,7 @@ static unsigned int read_flag (cpp_reade
 static int strtoul_for_line (const uchar *, unsigned int, unsigned long *);
 static void do_diagnostic (cpp_reader *, int, int);
 static cpp_hashnode *lex_macro_node (cpp_reader *);
+static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
 static void do_include_common (cpp_reader *, enum include_type);
 static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *,
                                                  const cpp_hashnode *);
@@ -539,6 +540,48 @@ do_undef (cpp_reader *pfile)
     }
   check_eol (pfile);
 }
+
+/* Undefine a single macro/assertion/whatever.  */
+
+static int
+undefine_macros (pfile, h, data_p)
+     cpp_reader *pfile;
+     cpp_hashnode *h;
+     void *data_p ATTRIBUTE_UNUSED;
+{
+  switch (h->type)
+    {
+    case NT_VOID:
+      break;
+      
+    case NT_MACRO:
+      if (pfile->cb.undef)
+        (*pfile->cb.undef) (pfile, pfile->directive_line, h);
+
+      if (CPP_OPTION (pfile, warn_unused_macros))
+        _cpp_warn_if_unused_macro (pfile, h, NULL);
+
+      /* and fall through... */
+    case NT_ASSERTION:
+      _cpp_free_definition (h);
+      break;
+
+    default:
+      abort ();
+    }
+  h->flags &= ~NODE_POISONED;
+  return 1;
+}
+
+/* Undefine all macros and assertions.  */
+
+void
+cpp_undef_all (pfile)
+     cpp_reader *pfile;
+{
+  cpp_forall_identifiers (pfile, undefine_macros, NULL);
+}
+
 
 /* Helper routine used by parse_include.  Reinterpret the current line
    as an h-char-sequence (< ... >); we are looking at the first token
Index: cpplib.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.h,v
retrieving revision 1.259
diff -u -p -u -p -r1.259 cpplib.h
--- cpplib.h	5 Jul 2003 00:23:52 -0000	1.259
+++ cpplib.h	9 Jul 2003 18:43:54 -0000
@@ -535,6 +535,10 @@ extern void cpp_set_callbacks (cpp_reade
    too.  If there was an error opening the file, it returns NULL.  */
 extern const char *cpp_read_main_file (cpp_reader *, const char *);
 
+/* This continues processing to a new file.  It will return false if
+   there was an error opening the file.  */
+extern bool cpp_read_next_file (cpp_reader *, const char *);
+
 /* Set up built-ins like __FILE__.  */
 extern void cpp_init_builtins (cpp_reader *, int);
 
@@ -583,6 +587,9 @@ extern void cpp_define (cpp_reader *, co
 extern void cpp_assert (cpp_reader *, const char *);
 extern void cpp_undef (cpp_reader *, const char *);
 extern void cpp_unassert (cpp_reader *, const char *);
+
+/* Undefine all macros and assertions.  */
+extern void cpp_undef_all (cpp_reader *);
 
 extern cpp_buffer *cpp_push_buffer (cpp_reader *, const unsigned char *,
 				    size_t, int, int);
Index: gcc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.386
diff -u -p -u -p -r1.386 gcc.c
--- gcc.c	6 Jul 2003 20:42:55 -0000	1.386
+++ gcc.c	9 Jul 2003 18:43:55 -0000
@@ -2891,6 +2891,11 @@ static struct infile *infiles;
 
 int n_infiles;
 
+/* True if multiple input files are being compiled to a single
+   assembly file.  */
+
+static bool combine_inputs;
+
 /* This counts the number of libraries added by lang_specific_driver, so that
    we can tell if there were any user supplied any files or libraries.  */
 
@@ -3715,8 +3720,7 @@ warranty; not even for MERCHANTABILITY o
 	}
     }
 
-  if (have_c && have_o && lang_n_infiles > 1)
-    fatal ("cannot specify -o with -c or -S and multiple compilations");
+  combine_inputs = (have_c && have_o && lang_n_infiles > 1);
 
   if ((save_temps_flag || report_times) && use_pipes)
     {
@@ -4760,8 +4764,16 @@ do_spec_1 (const char *spec, int inswitc
 	    break;
 
 	  case 'i':
-	    obstack_grow (&obstack, input_filename, input_filename_length);
-	    arg_going = 1;
+	    if (combine_inputs)
+	      {
+		for (i = 0; (int) i < n_infiles; i++)
+		  store_arg (infiles[i].name, 0, 0);
+	      }
+	    else
+	      {
+		obstack_grow (&obstack, input_filename, input_filename_length);
+		arg_going = 1;
+	      }
 	    break;
 
 	  case 'I':
@@ -6291,7 +6303,28 @@ main (int argc, const char *const *argv)
 
   explicit_link_files = xcalloc (1, n_infiles);
 
-  for (i = 0; (int) i < n_infiles; i++)
+  if (combine_inputs)
+    {
+       int lang_n_infiles = 0;
+       for (i = 0; (int) i < n_infiles; i++)
+	 {
+	   const char *name = infiles[i].name;
+	   struct compiler *compiler
+	     = lookup_compiler (name, strlen (name), infiles[i].language);
+	   if (compiler == NULL)
+	     error ("%s: linker input file unused because linking not done",
+		    name);
+	   else if (lang_n_infiles > 0 && compiler != input_file_compiler)
+	     fatal ("cannot specify -o with -c or -S and multiple languages");
+	   else
+	     {
+	       lang_n_infiles++;
+	       input_file_compiler = compiler;
+	     }
+	 }
+    }
+  
+  for (i = 0; (int) i < (combine_inputs ? 1 : n_infiles); i++)
     {
       int this_file_error = 0;
 
@@ -6306,9 +6339,10 @@ main (int argc, const char *const *argv)
 
       /* Figure out which compiler from the file's suffix.  */
 
-      input_file_compiler
-	= lookup_compiler (infiles[i].name, input_filename_length,
-			   infiles[i].language);
+      if (! combine_inputs)
+	input_file_compiler
+	  = lookup_compiler (infiles[i].name, input_filename_length,
+			     infiles[i].language);
 
       if (input_file_compiler)
 	{
Index: langhooks-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks-def.h,v
retrieving revision 1.56
diff -u -p -u -p -r1.56 langhooks-def.h
--- langhooks-def.h	9 Jul 2003 00:31:13 -0000	1.56
+++ langhooks-def.h	9 Jul 2003 18:43:55 -0000
@@ -80,8 +80,6 @@ extern int lhd_tree_inlining_start_inlin
 extern void lhd_tree_inlining_end_inlining (tree);
 extern tree lhd_tree_inlining_convert_parm_for_inlining (tree, tree, tree);
 
-extern void write_global_declarations (void);
-
 #define LANG_HOOKS_NAME			"GNU unknown"
 #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
 #define LANG_HOOKS_INIT			hook_bool_void_false
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.h,v
retrieving revision 1.106
diff -u -p -u -p -r1.106 toplev.h
--- toplev.h	6 Jul 2003 14:48:56 -0000	1.106
+++ toplev.h	9 Jul 2003 18:43:55 -0000
@@ -101,8 +101,9 @@ extern void fnotice			(FILE *, const cha
      ATTRIBUTE_PRINTF_2;
 #endif
 
-extern int wrapup_global_declarations   (union tree_node **, int);
-extern void check_global_declarations   (union tree_node **, int);
+extern int wrapup_global_declarations (union tree_node **, int);
+extern void check_global_declarations (union tree_node **, int);
+extern void write_global_declarations (void);
 
 /* A unique local time stamp, might be zero if none is available.  */
 extern unsigned local_tick;
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.314
diff -u -p -u -p -r1.314 tree.c
--- tree.c	6 Jul 2003 14:48:56 -0000	1.314
+++ tree.c	9 Jul 2003 18:43:55 -0000
@@ -4370,26 +4370,30 @@ decl_type_context (tree decl)
   tree context = DECL_CONTEXT (decl);
 
   while (context)
-    {
-      if (TREE_CODE (context) == NAMESPACE_DECL)
+    switch (TREE_CODE (context))
+      {
+      case NAMESPACE_DECL:
+      case TRANSLATION_UNIT_DECL:
 	return NULL_TREE;
 
-      if (TREE_CODE (context) == RECORD_TYPE
-	  || TREE_CODE (context) == UNION_TYPE
-	  || TREE_CODE (context) == QUAL_UNION_TYPE)
+      case RECORD_TYPE:
+      case UNION_TYPE:
+      case QUAL_UNION_TYPE:
 	return context;
-
-      if (TREE_CODE (context) == TYPE_DECL
-	  || TREE_CODE (context) == FUNCTION_DECL)
+	
+      case TYPE_DECL:
+      case FUNCTION_DECL:
 	context = DECL_CONTEXT (context);
-
-      else if (TREE_CODE (context) == BLOCK)
+	break;
+	
+      case BLOCK:
 	context = BLOCK_SUPERCONTEXT (context);
-
-      else
-	/* Unhandled CONTEXT!?  */
+	break;
+	
+      default:
 	abort ();
-    }
+      }
+
   return NULL_TREE;
 }
 
Index: tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.60
diff -u -p -u -p -r1.60 tree.def
--- tree.def	16 Jun 2003 11:30:25 -0000	1.60
+++ tree.def	9 Jul 2003 18:43:55 -0000
@@ -277,17 +277,18 @@ DEFTREECODE (VECTOR_CST, "vector_cst", '
 /* Contents are TREE_STRING_LENGTH and TREE_STRING_POINTER fields. */
 DEFTREECODE (STRING_CST, "string_cst", 'c', 0)
 
-/* Declarations.  All references to names are represented as ..._DECL nodes.
-   The decls in one binding context are chained through the TREE_CHAIN field.
-   Each DECL has a DECL_NAME field which contains an IDENTIFIER_NODE.
-    (Some decls, most often labels, may have zero as the DECL_NAME).
-   DECL_CONTEXT points to the node representing the context in which
-    this declaration has its scope.  For FIELD_DECLs, this is the
-    RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node that the field
-    is a member of.  For VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL,
-    and CONST_DECL nodes, this points to either the FUNCTION_DECL for the
-    containing function, the RECORD_TYPE or UNION_TYPE for the containing
-    type, or NULL_TREE if the given decl has "file scope".
+/* Declarations.  All references to names are represented as ..._DECL
+   nodes.  The decls in one binding context are chained through the
+   TREE_CHAIN field.  Each DECL has a DECL_NAME field which contains
+   an IDENTIFIER_NODE.  (Some decls, most often labels, may have zero
+   as the DECL_NAME).  DECL_CONTEXT points to the node representing
+   the context in which this declaration has its scope.  For
+   FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
+   QUAL_UNION_TYPE node that the field is a member of.  For VAR_DECL,
+   PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, this
+   points to either the FUNCTION_DECL for the containing function, the
+   RECORD_TYPE or UNION_TYPE for the containing type, or NULL_TREE or
+   a TRANSLATION_UNIT_DECL if the given decl has "file scope".
    DECL_ABSTRACT_ORIGIN, if non-NULL, points to the original (abstract)
     ..._DECL node of which this decl is an (inlined or template expanded)
     instance.
@@ -298,9 +299,9 @@ DEFTREECODE (STRING_CST, "string_cst", '
     and DECL_MODE fields exist in decl nodes just as in type nodes.
     They are unused in LABEL_DECL, TYPE_DECL and CONST_DECL nodes.
 
-   DECL_OFFSET holds an integer number of bits offset for the location.
-   DECL_VOFFSET holds an expression for a variable offset; it is
-   to be multiplied by DECL_VOFFSET_UNIT (an integer).
+   DECL_FIELD_BIT_OFFSET holds an integer number of bits offset for
+   the location.  DECL_VOFFSET holds an expression for a variable
+   offset; it is to be multiplied by DECL_VOFFSET_UNIT (an integer).
    These fields are relevant only in FIELD_DECLs and PARM_DECLs.
 
    DECL_INITIAL holds the value to initialize a variable to,
@@ -346,6 +347,10 @@ DEFTREECODE (FIELD_DECL, "field_decl", '
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", 'd', 0)
+
+/* A translation unit.  This is not technically a declaration, since it
+   can't be looked up, but it's close enough.  */
+DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl", 'd', 0)
 
 /* References to storage.  */
 
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.424
diff -u -p -u -p -r1.424 tree.h
--- tree.h	7 Jul 2003 17:57:22 -0000	1.424
+++ tree.h	9 Jul 2003 18:43:56 -0000
@@ -1253,12 +1253,13 @@ struct tree_type GTY(())
    the name from decl_attributes to make_function_rtl and make_decl_rtl.  */
 #define DECL_SECTION_NAME(NODE) (DECL_CHECK (NODE)->decl.section_name)
 
-/*  For FIELD_DECLs, this is the
-    RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node that the field is
-    a member of.  For VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL,
-    and CONST_DECL nodes, this points to either the FUNCTION_DECL for the
-    containing function, the RECORD_TYPE or UNION_TYPE for the containing
-    type, or NULL_TREE if the given decl has "file scope".  */
+/*  For FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
+    QUAL_UNION_TYPE node that the field is a member of.  For VAR_DECL,
+    PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, this
+    points to either the FUNCTION_DECL for the containing function,
+    the RECORD_TYPE or UNION_TYPE for the containing type, or
+    NULL_TREE or a TRANSLATION_UNIT_DECL if the given decl has "file
+    scope".  */
 #define DECL_CONTEXT(NODE) (DECL_CHECK (NODE)->decl.context)
 #define DECL_FIELD_CONTEXT(NODE) (FIELD_DECL_CHECK (NODE)->decl.context)
 /* In a DECL this is the field where attributes are stored.  */
@@ -1287,6 +1288,7 @@ struct tree_type GTY(())
 /* In PARM_DECL, holds the type as written (perhaps a function or array).  */
 #define DECL_ARG_TYPE_AS_WRITTEN(NODE) (PARM_DECL_CHECK (NODE)->decl.result)
 /* For a FUNCTION_DECL, holds the tree of BINDINGs.
+   For a TRANSLATION_UNIT_DECL, holds the namespace's BLOCK.
    For a VAR_DECL, holds the initial value.
    For a PARM_DECL, not used--default
    values for parameters are encoded in the type of the function,
Index: cp/cp-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-lang.c,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 cp-lang.c
--- cp/cp-lang.c	9 Jul 2003 00:31:14 -0000	1.55
+++ cp/cp-lang.c	9 Jul 2003 18:44:00 -0000
@@ -372,3 +372,9 @@ cp_var_mod_type_p (tree type)
   return false;
 }
 
+/* Stub routine to tell people that this doesn't work yet.  */
+void
+c_reset_state ()
+{
+  sorry ("inter-module optimisations not implemented yet");
+}
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.871
diff -u -p -u -p -r1.871 cp-tree.h
--- cp/cp-tree.h	9 Jul 2003 08:47:58 -0000	1.871
+++ cp/cp-tree.h	9 Jul 2003 18:44:01 -0000
@@ -3773,7 +3773,6 @@ extern void comdat_linkage (tree);
 extern void import_export_vtable (tree, tree, int);
 extern void import_export_decl (tree);
 extern void import_export_tinfo	(tree, tree, bool);
-extern void finish_file				(void);
 extern tree build_cleanup			(tree);
 extern tree build_offset_ref_call_from_tree     (tree, tree);
 extern void set_decl_namespace (tree, tree, bool);
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.77
diff -u -p -u -p -r1.77 parser.c
--- cp/parser.c	9 Jul 2003 08:48:00 -0000	1.77
+++ cp/parser.c	9 Jul 2003 18:44:02 -0000
@@ -14605,10 +14605,10 @@ static GTY (()) cp_parser *the_parser;
 
 /* External interface.  */
 
-/* Parse the entire translation unit.  */
+/* Parse one entire translation unit.  */
 
-int
-yyparse (void)
+void
+c_parse_file (void)
 {
   bool error_occurred;
 
@@ -14617,10 +14617,6 @@ yyparse (void)
 				? dk_no_deferred : dk_no_check);
   error_occurred = cp_parser_translation_unit (the_parser);
   the_parser = NULL;
-  
-  finish_file ();
-
-  return error_occurred;
 }
 
 /* Clean up after parsing the entire translation unit.  */
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.314
diff -u -p -u -p -r1.314 invoke.texi
--- doc/invoke.texi	9 Jul 2003 04:07:44 -0000	1.314
+++ doc/invoke.texi	9 Jul 2003 18:44:03 -0000
@@ -709,10 +709,12 @@ in the following sections.
 @section Options Controlling the Kind of Output
 
 Compilation can involve up to four stages: preprocessing, compilation
-proper, assembly and linking, always in that order.  The first three
-stages apply to an individual source file, and end by producing an
-object file; linking combines all the object files (those newly
-compiled, and those specified as input) into an executable file.
+proper, assembly and linking, always in that order.  GCC is capable of
+preprocessing and compiling several files either into several
+assembler input files, or into one assembler input file; then each
+assembler input file produces an object file, and linking combines all
+the object files (those newly compiled, and those specified as input)
+into an executable file.
 
 @cindex file name suffix
 For any given input file, the file name suffix determines what kind of
@@ -884,9 +886,9 @@ Place output in file @var{file}.  This a
 sort of output is being produced, whether it be an executable file,
 an object file, an assembler file or preprocessed C code.
 
-Since only one output file can be specified, it does not make sense to
-use @option{-o} when compiling more than one input file, unless you are
-producing an executable file as output.
+If you specify @option{-o} when compiling more than one input file, or
+you are producing an executable file as output, all the source files
+on the command line will be compiled at once.
 
 If @option{-o} is not specified, the default is to put an executable file
 in @file{a.out}, the object file for @file{@var{source}.@var{suffix}} in
@@ -3471,6 +3473,14 @@ Turning on optimization flags makes the 
 the performance and/or code size at the expense of compilation time
 and possibly the ability to debug the program.
 
+The compiler performs optimisation based on the knowledge it has of
+the program.  Using the @option{-funit-at-a-time} flag will allow the
+compiler to consider information gained from later functions in the
+file when compiling a function.  Compiling multiple files at once to a
+single output file (and using @option{-funit-at-a-time}) will allow
+the compiler to use information gained from all of the files when
+compiling each of them.
+
 Not all optimizations are controlled directly by a flag.  Only
 optimizations that have a flag are listed.
 
@@ -4362,8 +4372,9 @@ better job.
 
 @item -funit-at-a-time
 @opindex funit-at-a-time
-Parse the whole compilation unit before starting to produce code.  This allows some
-extra optimizations to take place but consumes more memory.
+Parse the whole compilation unit before starting to produce code.
+This allows some extra optimizations to take place but consumes more
+memory.
 
 @item -funroll-loops
 @opindex funroll-loops
Index: objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.179
diff -u -p -u -p -r1.179 objc-act.c
--- objc/objc-act.c	5 Jul 2003 00:23:53 -0000	1.179
+++ objc/objc-act.c	9 Jul 2003 18:44:04 -0000
@@ -3521,7 +3521,7 @@ check_ivars (inter, imp)
 
       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
 
-      if (!comptypes (t1, t2))
+      if (!comptypes (t1, t2, false))
 	{
 	  if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
 	    {
@@ -4905,7 +4905,7 @@ finish_message_expr (receiver, sel_name,
 	;
       else if (! IS_ID (rtype)
 	       /* Allow any type that matches objc_class_type.  */
-	       && ! comptypes (rtype, objc_class_type))
+	       && ! comptypes (rtype, objc_class_type, false))
 	{
 	  warning ("invalid receiver type `%s'",
 		   gen_declaration (rtype, errbuf));
@@ -7064,7 +7064,8 @@ comp_method_with_proto (method, proto)
   /* install return type */
   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
 
-  return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
+  return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
+		    false);
 }
 
 /* Return 1 if PROTO1 is consistent with PROTO2.  */
@@ -7087,7 +7088,7 @@ comp_proto_with_proto (proto0, proto1)
   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
   TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
 
-  return comptypes (function1_template, function2_template);
+  return comptypes (function1_template, function2_template, false);
 }
 
 /* - Generate an identifier for the function. the format is "_n_cls",
============================================================



More information about the Gcc-patches mailing list