[gnu.g++.bug] g++ 1.35 virtual base class bug.

tiemann@YAHI.STANFORD.EDU (Michael Tiemann) (05/20/89)

I fixed some minor glitches in GNU C++ 1.35.0, mostly relating to
error recovery and multiple inheritance.  There are other, harder bugs
which I am fixing now, but I don't want to tie everyone up waiting for
those.  Also, if `#pragma once' bites you (there was a bug in the GCC
1.35 release of cccp.c which failed to close files after processing
#pragma once), you can get a copy of the fixed file in
yahi:~ftp/pub/cccp.c.Z .

yahi% diff -rc2H g++-1.35.0 g++-1.35.0+
diff -rc2H g++-1.35.0/ChangeLog g++-1.35.0+/ChangeLog
*** g++-1.35.0/ChangeLog	Tue May 16 23:45:39 1989
--- g++-1.35.0+/ChangeLog	Fri May 19 14:22:31 1989
***************
*** 1,2 ****
--- 1,66 ----
+ Fri May 19 13:20:07 1989  Michael Tiemann  (tiemann at yahi)
+ 
+ 	* cplus-class.c: handle case where user requests member function
+ 	  using object, i.e., `x.f'.  If f is virtual, return the function
+ 	  found in the virtual function table.
+ 
+ 	* stor-layout.c: language dependent code removed from
+ 	layout_basetypes, put in cplus-class.c
+ 
+ 	* stmt.c: if cleanups were called on leaving a binding contour,
+ 	  and EXIT_IGNORE_STACK is not defined, call
+ 	  do_pending_stack_adjust (expand_goto_internal,
+ 	  expand_end_bindings, fixup_cleanups).
+ 
+ 	* gcc.c: recognize ".cxx" as a C++ file name extension.
+ 
+ 	* cplus-typeck.c: convert_for_initialization,
+ 	  convert_for_assignment convert MEMBER_REFs, if possible, to
+ 	  members or component refs as appropriate.
+ 
+ 	* cplus-typeck.c: build_member_ref recognizes member refs which
+ 	  are not associated with any object in particular (i.e., could
+ 	  be, but need not be `this').
+ 
+ 	* cplus-search.c: get_vbase_types now orders the virtual
+ 	  base classes so that initialization and anti-initialization are
+ 	  performed in correct order.  A virtual baseclass is not
+ 	  destroyed until all parts of the object which could be using
+ 	  that virtual base class are destroyed.
+ 
+ 	* cplus-parse.y: call build_vbase_delete if appropriate.
+ 
+ 	* cplus-init.c: expand_delete now calls build_vbase_delete if
+ 	  appropriate.  build_delete no longer deletes parts of objects
+ 	  via virtual base classes.
+ 
+ 	* cplus-init.c: new function build_vbase_delete, performs
+ 	  destructors on objects with virtual base classes.  new function
+ 	  build_x_delete calls free-store deallocator on objects without
+ 	  running destructors.
+ 
+ 	* cplus-decl.c: make pushdecl, shadow_tag, and xref_tag have
+ 	  C-like behavior in "C" language scope vis a vis type
+ 	  declarations.
+ 
+ 	* cplus-decl.c: define macros PUSH_BINDING_LEVEL and
+ 	  POP_BINDING_LEVEL.  Use these macros where appropriate.  Fixed
+ 	  bug in popping binding contours in the presence of syntax
+ 	  errors.
+ 
+ 	* README, config.g++, make-links.g++: fixed minor glitches
+ 
+ Wed May 17 20:34:29 1989  Michael Tiemann  (tiemann at yahi)
+ 
+ 	* stor-layout.c: move code which deletes an incomplete base type
+ 	  to cplus-class.c.
+ 
+ 	* cplus-class.c: changed `finish_struct' to call
+ 	  `propagate_basetype_offsets'.
+ 
+ 	* cplus-class.c: new function `propagate_basetype_offsets' gives
+ 	  correct offsets to base types which are not immediate base types
+ 	  in a multiple inheritance lattice.
+ 
  Tue May 16 09:40:00 1989  Michael Tiemann  (tiemann at yahi)
  
diff -rc2H g++-1.35.0/HINTS g++-1.35.0+/HINTS
*** g++-1.35.0/HINTS	Tue May 16 23:45:38 1989
--- g++-1.35.0+/HINTS	Fri May 19 14:22:31 1989
***************
*** 73,74 ****
--- 73,87 ----
  tiemann@lurch.stanford.edu
  ----------------------------------------------------------------
+ The default LINK_SPEC in gcc.c tells the linker to link
+ with crt0+.o.  Many machine-specific files define their own
+ LINK_SPECs.  A strategy which worked until tm-sun?-nfp-os? came along
+ was to edit the tm-*.h file into tm-*+.h, and replace the string
+ "crt0.o" with "crt0+.o".  This strategy is defeated with one tm-*.h
+ file includes a file defining LINK_SPEC.  I will fix this in release
+ 1.35.1.  In the mean time, copy LINK_SPEC from the file that is being
+ included, #undef it and redef it in the top level tm-*.h file.
+ 
+ 
+ Michael Tieman
+ tieman@lurch.stanford.edu
+ ----------------------------------------------------------------
diff -rc2H g++-1.35.0/Makefile g++-1.35.0+/Makefile
*** g++-1.35.0/Makefile	Tue May 16 23:45:19 1989
--- g++-1.35.0+/Makefile	Fri May 19 14:22:31 1989
***************
*** 53,59 ****
  # Variables that exist for you to override.
  
! CFLAGS = -g -DSOS -DESKIT
  # CFLAGS = -g -O
! CC = ../gcc/gcc -B../gcc/
  BISON = bison
  BISONFLAGS = -v -d
--- 53,59 ----
  # Variables that exist for you to override.
  
! CFLAGS = -g -DSOS -DESKIT -O
  # CFLAGS = -g -O
! CC = gcc
  BISON = bison
  BISONFLAGS = -v -d
***************
*** 555,559 ****
  	-ln -s $(DIR)/move-if-change .
  	$(MAKE) clean
! 	make-links.g++
  	-ln -s $(DIR)/gen*.c .
  	-ln -s $(TDIR)/obstack.o $(TDIR)/rtl.o $(TDIR)/emit-rtl.o \
--- 555,559 ----
  	-ln -s $(DIR)/move-if-change .
  	$(MAKE) clean
! 	./make-links.g++
  	-ln -s $(DIR)/gen*.c .
  	-ln -s $(TDIR)/obstack.o $(TDIR)/rtl.o $(TDIR)/emit-rtl.o \
diff -rc2H g++-1.35.0/README g++-1.35.0+/README
*** g++-1.35.0/README	Tue May 16 23:45:20 1989
--- g++-1.35.0+/README	Fri May 19 14:22:31 1989
***************
*** 137,141 ****
  
  	install% pwd
! 	install% ./g++
  
  *Very Important*: Because GNU C++ now uses its own crt0.c, borrowed
--- 137,142 ----
  
  	install% pwd
! 	./g++
! 	install% 
  
  *Very Important*: Because GNU C++ now uses its own crt0.c, borrowed
***************
*** 144,153 ****
  have GNU Emacs, and you are not compiling to a SUN, consult your local
  GNU Emacs guru, to see what sort of #defines are required for proper
! operation.  Then, just type `make'.  If you are not using a SUN, you
! will need to use the appropriate machine dependent files, as per GNU
! CC.  If you do not provide a proper crt0.c, any executable produced
! by GNU C++ may fail to run at all.  Conversely, if you have a program
! which does not make it as far as the first line in main (), you have
! probably failed to provide the correct flags to crt0.c.
  
  You have now just made GNU C++.  Having done that, you should now
--- 145,158 ----
  have GNU Emacs, and you are not compiling to a SUN, consult your local
  GNU Emacs guru, to see what sort of #defines are required for proper
! operation.  Then, just type `make':
! 
! 	install% make
! 
! If you are not using a SUN, you will need to use the appropriate
! machine dependent files, as per GNU CC.  If you do not provide a
! proper crt0.c, any executable produced by GNU C++ may fail to run at
! all.  Conversely, if you have a program which does not make it as far
! as the first line in main (), you have probably failed to provide the
! correct flags to crt0.c.
  
  You have now just made GNU C++.  Having done that, you should now
diff -rc2H g++-1.35.0/config.g++ g++-1.35.0+/config.g++
*** g++-1.35.0/config.g++	Tue May 16 23:45:32 1989
--- g++-1.35.0+/config.g++	Fri May 19 14:22:32 1989
***************
*** 126,130 ****
  	sun3-os4 | sun-3-os4)
  		cpu_type=m68k
! 		sed 's/-e start//' < config/xm-sunos4.h > config/xm-sunos4+.h
  		configuration_file=xm-sunos4+.h
  		machine_type=sun3
--- 126,130 ----
  	sun3-os4 | sun-3-os4)
  		cpu_type=m68k
! 		sed 's/-e start/-e __start/' < config/xm-sunos4.h > config/xm-sunos4+.h
  		configuration_file=xm-sunos4+.h
  		machine_type=sun3
***************
*** 132,136 ****
  	sun3-nfp-os4 | sun-3-nfp-os4)
  		cpu_type=m68k
! 		sed 's/-e start//' < config/xm-sunos4.h > config/xm-sunos4+.h
  		configuration_file=xm-sunos4.h
  		machine_type=sun3-nfp
--- 132,137 ----
  	sun3-nfp-os4 | sun-3-nfp-os4)
  		cpu_type=m68k
! 		sed 's/-e start/-e __start/' < config/xm-sunos4.h > config/xm-sunos4+.h
! 		configuration_file=xm-sunos4+.h
  		configuration_file=xm-sunos4.h
  		machine_type=sun3-nfp
diff -rc2H g++-1.35.0/cplus-class.c g++-1.35.0+/cplus-class.c
*** g++-1.35.0/cplus-class.c	Tue May 16 23:45:21 1989
--- g++-1.35.0+/cplus-class.c	Fri May 19 14:22:33 1989
***************
*** 645,648 ****
--- 645,689 ----
  }
  
+ /* Add OFFSET to all child types of T.
+ 
+    OFFSET, which is a type offset, is number of bytes.
+ 
+    Note that we don't have to worry about having two paths to the
+    same base type, since virtual baseclasses are avoided,
+    and basetypes become unique.  */
+ static void
+ propagate_basetype_offsets (t, offset)
+      tree t;
+      tree offset;
+ {
+   int i, n_baselinks = CLASSTYPE_N_BASECLASSES (t);
+ 
+   for (i = 1; i <= n_baselinks; i++)
+     if (! CLASSTYPE_VIA_VIRTUAL (t, i))
+       {
+ 	tree basetype = CLASSTYPE_THIS_BASECLASS (t, i);
+ 
+ 	if (CLASSTYPE_OFFSET (basetype) == integer_zero_node)
+ 	  basetype = build_classtype_variant (basetype, offset, 0);
+ 	else
+ 	  basetype = build_classtype_variant (basetype,
+ 					      genop (PLUS_EXPR, CLASSTYPE_OFFSET (basetype), offset), 0);
+ 	/* Now make our own copy of this base type we can munge.  */
+ 	basetype = copy_node (basetype);
+ 	CLASSTYPE_THIS_BASECLASS (t, i) = basetype;
+ 	copy_type_lang_specific (basetype);
+ 	TYPE_NAME (basetype) = copy_node (TYPE_NAME (basetype));
+ 	TREE_TYPE (TYPE_NAME (basetype)) = basetype;
+ 	DECL_OFFSET (TYPE_NAME (basetype))
+ 	  = TREE_INT_CST_LOW (convert_units (CLASSTYPE_OFFSET (basetype), BITS_PER_UNIT, 1));
+ 	propagate_basetype_offsets (basetype, offset);
+ 	if (i < n_baselinks)
+ 	  {
+ 	    offset = genop (PLUS_EXPR,
+ 			    convert_units (TYPE_SIZE (basetype), TYPE_SIZE_UNIT (basetype), BITS_PER_UNIT), offset);
+ 	  }
+       }
+ }
+ 
  /* Change the visibility of T::FDECL to VISIBILITY.
     Return 1 if change was legit, otherwise return 0.  */
***************
*** 934,997 ****
  
        /* If the type of basetype is incomplete, then
! 	 we already complained about that fact.  */
!       if (TYPE_SIZE (basetype))
  	{
! 	  TYPE_USES_VIRTUAL_BASECLASSES (t)
! 	    |= (TYPE_USES_VIRTUAL_BASECLASSES (basetype) | CLASSTYPE_VIA_VIRTUAL (t, i));
! 	  CLASSTYPE_HAS_UNINHERITABLE_VIRTUALS (t)
! 	    |= CLASSTYPE_HAS_UNINHERITABLE_VIRTUALS (basetype) | (CLASSTYPE_UNINHERITED_VIRTUALS (basetype) != 0);
! 	  CLASSTYPE_ALTERS_VISIBILITIES_P (t)
! 	    |= CLASSTYPE_ALTERS_VISIBILITIES_P (basetype);
! 
! 	  /* This does not work if the MI lattice has
! 	     virtual baseclasses.  Must use a bfs or dfs
! 	     routine instead.  */
! 	  n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
! 	  needs_ctor |= TYPE_NEEDS_CONSTRUCTOR (basetype);
! 	  needs_dtor |= TYPE_NEEDS_DESTRUCTOR (basetype);
! 	  needs_wrapper |= TYPE_NEEDS_WRAPPER (basetype) | TYPE_HAS_WRAPPER (basetype);
! 	  any_assigns_this |= TREE_ANY_ASSIGNS_THIS (basetype);
! 	  gets_assignment |= TREE_GETS_ASSIGNMENT (basetype);
! 
! 	  TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
! 	  TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
! 	  if (TYPE_VIRTUAL_P (basetype))
! 	    {
! 	      /* We cannot share virtual information for any node
! 		 which has a non-zero offset.  This is because for
! 		 such nodes, we rewrite that node's virtual information
! 		 in place--mostly.  */
! 	      if (CLASSTYPE_OFFSET (basetype) != integer_zero_node
! 		  || CLASSTYPE_VIA_VIRTUAL (t, i))
! 		{
! 		  CLASSTYPE_THIS_BASECLASS (t, i) = basetype = copy_node (basetype);
! 		  TREE_VIA_VIRTUAL (basetype) = CLASSTYPE_VIA_VIRTUAL (t, i);
! 		  copy_type_lang_specific (basetype);
! 		}
! 	      if (first_vfn_base_index == 0)
! 		{
! 		  first_vfn_base_index = i;
! 
! 		  /* The size of the virtual function table we get
! 		     from the base class is this.  */
! 		  max_has_virtual = has_virtual = CLASSTYPE_VSIZE (basetype);
! 
! 		  /* Don't borrow vfields from virtual baseclasses,
! 		     but do borrow everything else.  */
! 		  if (! TREE_VIA_VIRTUAL (basetype))
! 		    {
! 		      vfield = CLASSTYPE_VFIELD (basetype);
! 		      CLASSTYPE_VFIELD (t) = vfield;
! 		      static_vfield_name = DECL_NAME (vfield);
! 		    }
! 		}
! 	      else
! 		{
! 		  if (CLASSTYPE_VSIZE (basetype) > max_has_virtual)
! 		    max_has_virtual = CLASSTYPE_VSIZE (basetype);
! 		}
  	    }
  	}
-       else continue;
      }
  
--- 975,1060 ----
  
        /* If the type of basetype is incomplete, then
! 	 we already complained about that fact
! 	 (and we should have fixed it up as well).  */
!       if (TYPE_SIZE (basetype) == 0)
! 	{
! 	  int j;
! 	  /* The base type is of incomplete type.  It is
! 	     probably best to pretend that it does not
! 	     exist.  */
! 	  if (i == n_baseclasses)
! 	    CLASSTYPE_THIS_BASECLASS (t, i) = NULL_TREE;
! 	  CLASSTYPE_N_BASECLASSES (t) -= 1;
! 	  n_baseclasses -= 1;
! 	  for (j = i; j < n_baseclasses; j++)
! 	    {
! 	      CLASSTYPE_THIS_BASECLASS (t, j) = CLASSTYPE_THIS_BASECLASS (t, j+1);
! 	      SET_CLASSTYPE_VIAS (t, j,
! 				 CLASSTYPE_VIA_PUBLIC (t, j+1),
! 				 CLASSTYPE_VIA_VIRTUAL (t, j+1));
! 	    }
! 	}
! 
!       TYPE_USES_VIRTUAL_BASECLASSES (t)
! 	|= (TYPE_USES_VIRTUAL_BASECLASSES (basetype) | CLASSTYPE_VIA_VIRTUAL (t, i));
!       CLASSTYPE_HAS_UNINHERITABLE_VIRTUALS (t)
! 	|= CLASSTYPE_HAS_UNINHERITABLE_VIRTUALS (basetype) | (CLASSTYPE_UNINHERITED_VIRTUALS (basetype) != 0);
!       CLASSTYPE_ALTERS_VISIBILITIES_P (t)
! 	|= CLASSTYPE_ALTERS_VISIBILITIES_P (basetype);
! 
!       /* This does not work if the MI lattice has
! 	 virtual baseclasses.  Must use a bfs or dfs
! 	 routine instead.  */
!       n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
!       needs_ctor |= TYPE_NEEDS_CONSTRUCTOR (basetype);
!       needs_dtor |= TYPE_NEEDS_DESTRUCTOR (basetype);
!       needs_wrapper |= TYPE_NEEDS_WRAPPER (basetype) | TYPE_HAS_WRAPPER (basetype);
!       any_assigns_this |= TREE_ANY_ASSIGNS_THIS (basetype);
!       gets_assignment |= TREE_GETS_ASSIGNMENT (basetype);
! 
!       TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
!       TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
! 
!       if (CLASSTYPE_OFFSET (basetype) != integer_zero_node)
! 	/* Propagate this offset through all the children.  Do this
! 	   before uniquizing baseclasses for virtual functions.  */
! 	propagate_basetype_offsets (basetype, CLASSTYPE_OFFSET (basetype));
! 
!       if (TYPE_VIRTUAL_P (basetype))
  	{
! 	  /* We cannot share virtual information for any node
! 	     which has a non-zero offset.  This is because for
! 	     such nodes, we rewrite that node's virtual information
! 	     in place--mostly.  */
! 	  if (CLASSTYPE_OFFSET (basetype) != integer_zero_node
! 	      || CLASSTYPE_VIA_VIRTUAL (t, i))
! 	    {
! 	      CLASSTYPE_THIS_BASECLASS (t, i) = basetype = copy_node (basetype);
! 	      TREE_VIA_VIRTUAL (basetype) = CLASSTYPE_VIA_VIRTUAL (t, i);
! 	      copy_type_lang_specific (basetype);
! 	    }
! 	  if (first_vfn_base_index == 0)
! 	    {
! 	      first_vfn_base_index = i;
! 
! 	      /* The size of the virtual function table we get
! 		 from the base class is this.  */
! 	      max_has_virtual = has_virtual = CLASSTYPE_VSIZE (basetype);
! 
! 	      /* Don't borrow vfields from virtual baseclasses,
! 		 but do borrow everything else.  */
! 	      if (! TREE_VIA_VIRTUAL (basetype))
! 		{
! 		  vfield = CLASSTYPE_VFIELD (basetype);
! 		  CLASSTYPE_VFIELD (t) = vfield;
! 		  static_vfield_name = DECL_NAME (vfield);
! 		}
! 	    }
! 	  else
! 	    {
! 	      if (CLASSTYPE_VSIZE (basetype) > max_has_virtual)
! 		max_has_virtual = CLASSTYPE_VSIZE (basetype);
  	    }
  	}
      }
  
***************
*** 4189,4192 ****
--- 4252,4275 ----
        {
  	tree field = TREE_OPERAND (rhs, 1);
+ 	if (TREE_CODE (field) == TREE_LIST)
+ 	  {
+ 	    tree function = instantiate_type (lhstype, field, complain);
+ 	    if (function == error_mark_node)
+ 	      return error_mark_node;
+ 	    assert (TREE_CODE (function) == FUNCTION_DECL);
+ 	    if (DECL_VIRTUAL_P (function))
+ 	      {
+ 		tree base = TREE_OPERAND (rhs, 0);
+ 		tree base_ptr = build_unary_op (ADDR_EXPR, base, 0);
+ 		if (base_ptr == error_mark_node)
+ 		  return error_mark_node;
+ 		base_ptr = convert_to_nonzero_pointer (TYPE_POINTER_TO (DECL_VCONTEXT (function)), base_ptr);
+ 		if (base_ptr == error_mark_node)
+ 		  return error_mark_node;
+ 		return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
+ 	      }
+ 	    return function;
+ 	  }
+ 
  	assert (TREE_CODE (field) == FIELD_DECL);
  	assert (!(TREE_CODE (TREE_TYPE (field)) == FUNCTION_TYPE
***************
*** 4245,4249 ****
  	    {
  	      if (complain)
! 		error ("invalid type combination in `instantiate_type'");
  	      return error_mark_node;
  	    }
--- 4328,4332 ----
  	    {
  	      if (complain)
! 		error ("invalid type combination type instantiation");
  	      return error_mark_node;
  	    }
***************
*** 4295,4299 ****
  	else if (TREE_CODE (TREE_VALUE (rhs)) == TREE_LIST)
  	  {
! 	    char *name = IDENTIFIER_POINTER (TREE_PURPOSE (rhs));
  	    /* rhs is a BASELINK from derived downto base types.  */
  	    while (rhs)
--- 4378,4382 ----
  	else if (TREE_CODE (TREE_VALUE (rhs)) == TREE_LIST)
  	  {
! 	    char *name = IDENTIFIER_POINTER (TREE_PURPOSE (TREE_VALUE (rhs)));
  	    /* rhs is a BASELINK from derived downto base types.  */
  	    while (rhs)
diff -rc2H g++-1.35.0/cplus-decl.c g++-1.35.0+/cplus-decl.c
*** g++-1.35.0/cplus-decl.c	Tue May 16 23:45:22 1989
--- g++-1.35.0+/cplus-decl.c	Fri May 19 14:22:35 1989
***************
*** 594,597 ****
--- 594,637 ----
  static struct binding_level clear_binding_level
    = {NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0};
+ 
+ #define PUSH_BINDING_LEVEL(NEWLEVEL, TAG_TRANSPARENT, TEMPORARY) \
+ do {									\
+   /* Add this level to the front of the chain (stack) of levels that	\
+      are active.  */							\
+   *NEWLEVEL = clear_binding_level;					\
+   if (class_binding_level)						\
+     {									\
+       NEWLEVEL->level_chain = class_binding_level;			\
+       class_binding_level = 0;						\
+     }									\
+   else									\
+     {									\
+       NEWLEVEL->level_chain = current_binding_level;			\
+     }									\
+   current_binding_level = NEWLEVEL;					\
+   NEWLEVEL->tag_transparent = TAG_TRANSPARENT;				\
+   NEWLEVEL->more_cleanups_ok = 1;					\
+   NEWLEVEL->temporary = TEMPORARY;					\
+ } while (0)
+ 
+ #define POP_BINDING_LEVEL \
+ do {									\
+   /* Pop the current level, and free the structure for reuse.  */	\
+   {									\
+     register struct binding_level *level = current_binding_level;	\
+     current_binding_level = current_binding_level->level_chain;		\
+     level->level_chain = free_binding_level;				\
+     free_binding_level = level;						\
+     if (current_binding_level->parm_flag < 0)				\
+       {									\
+ 	class_binding_level = current_binding_level;			\
+ 	do								\
+ 	  {								\
+ 	    current_binding_level = current_binding_level->level_chain;	\
+ 	  }								\
+ 	while (current_binding_level->parm_flag < 0);			\
+       }									\
+   }									\
+ } while (0)
  
  /* Create a new `struct binding_level'.  */
***************
*** 644,665 ****
        newlevel = make_binding_level ();
      }
! 
!   /* Add this level to the front of the chain (stack) of levels that
!      are active.  */
! 
!   *newlevel = clear_binding_level;
!   if (class_binding_level)
!     {
!       newlevel->level_chain = class_binding_level;
!       class_binding_level = 0;
!     }
!   else
!     {
!       newlevel->level_chain = current_binding_level;
!     }
!   current_binding_level = newlevel;
!   newlevel->tag_transparent = tag_transparent;
!   newlevel->more_cleanups_ok = 1;
!   newlevel->temporary = 0;
  }
  
--- 684,688 ----
        newlevel = make_binding_level ();
      }
!   PUSH_BINDING_LEVEL (newlevel, tag_transparent, 0);
  }
  
***************
*** 813,835 ****
      }
  
-   /* Pop the current level, and free the structure for reuse.  */
    tmp = current_binding_level->temporary;
!   {
!     register struct binding_level *level = current_binding_level;
!     current_binding_level = current_binding_level->level_chain;
! 
!     level->level_chain = free_binding_level;
!     free_binding_level = level;
!     if (current_binding_level->parm_flag < 0)
!       {
! 	class_binding_level = current_binding_level;
! 	do
! 	  {
! 	    current_binding_level = current_binding_level->level_chain;
! 	  }
! 	while (current_binding_level->parm_flag < 0);
!       }
!   }
! 
    if (functionbody > 0)
      {
--- 836,841 ----
      }
  
    tmp = current_binding_level->temporary;
!   POP_BINDING_LEVEL;
    if (functionbody > 0)
      {
***************
*** 895,899 ****
  {
    register struct binding_level *level = class_binding_level;
!   class_binding_level = class_binding_level->level_chain;
  
    level->level_chain = free_binding_level;
--- 901,914 ----
  {
    register struct binding_level *level = class_binding_level;
! 
!   if (level == 0)
!     {
!       while (current_binding_level && class_binding_level == 0)
! 	poplevel (0, 0, 0);
!       if (current_binding_level == 0)
! 	fatal ("syntax error too serious");
!       level = class_binding_level;
!     }
!   class_binding_level = level->level_chain;
  
    level->level_chain = free_binding_level;
***************
*** 1325,1329 ****
      for (prev = 0, vars = global_binding_level->names;
           vars;
!          prev = vars, vars = TREE_CHAIN (vars))
        {
          if (TREE_CODE (vars) == TYPE_DECL
--- 1340,1344 ----
      for (prev = 0, vars = global_binding_level->names;
           vars;
!          vars = TREE_CHAIN (vars))
        {
          if (TREE_CODE (vars) == TYPE_DECL
***************
*** 1359,1362 ****
--- 1374,1379 ----
                global_binding_level->names = TREE_CHAIN (global_binding_level->names);
            }
+ 	else
+ 	  prev = vars;
        }
    }
***************
*** 1820,1836 ****
        if (TREE_CODE (x) == TYPE_DECL)
  	{
! 	  if (TYPE_NAME (TREE_TYPE (x)) == 0
! 	      || TREE_CODE (TYPE_NAME (TREE_TYPE (x))) != TYPE_DECL)
! 	    TYPE_NAME (TREE_TYPE (x)) = x;
! 	  else if (current_lang_name == lang_name_cplusplus
! 		   && IS_AGGR_TYPE (TREE_TYPE (x))
! 		   && ANON_AGGRNAME_P (DECL_NAME (TYPE_NAME (TREE_TYPE (x)))))
  	    {
! 	      /* do gratuitous C++ typedefing, and make sure that
! 		 we access this type either through TREE_TYPE field
! 		 or via the tags list.  */
! 	      TYPE_NAME (TREE_TYPE (x)) = x;
! 	      pushtag (DECL_NAME (x), TREE_TYPE (x));
  	    }
  	}
  
--- 1837,1861 ----
        if (TREE_CODE (x) == TYPE_DECL)
  	{
! 	  if (current_lang_name == lang_name_cplusplus)
  	    {
! 	      if (TYPE_NAME (TREE_TYPE (x)) == 0
! 		  || TREE_CODE (TYPE_NAME (TREE_TYPE (x))) != TYPE_DECL)
! 		{
! 		  /* If these are different names, make two equivalent
! 		     definitions.  */
! 		  TYPE_NAME (TREE_TYPE (x)) = x;
! 		}
! 	      else if (IS_AGGR_TYPE (TREE_TYPE (x))
! 		       && ANON_AGGRNAME_P (DECL_NAME (TYPE_NAME (TREE_TYPE (x)))))
! 		{
! 		  /* do gratuitous C++ typedefing, and make sure that
! 		     we access this type either through TREE_TYPE field
! 		     or via the tags list.  */
! 		  TYPE_NAME (TREE_TYPE (x)) = x;
! 		  pushtag (DECL_NAME (x), TREE_TYPE (x));
! 		}
  	    }
+ 	  else if (TYPE_NAME (TREE_TYPE (x)) == 0)
+ 	    TYPE_NAME (TREE_TYPE (x)) = x;
  	}
  
***************
*** 3050,3055 ****
  #endif
  
!     if (TREE_CODE (decl) == FUNCTION_DECL
! 	&& TREE_OVERLOADED (decl))
        /* @@ Also done in start_function.  */
        push_overloaded_decl (tem);
--- 3075,3079 ----
  #endif
  
!     if (TREE_CODE (decl) == FUNCTION_DECL && TREE_OVERLOADED (decl))
        /* @@ Also done in start_function.  */
        push_overloaded_decl (tem);
***************
*** 3134,3138 ****
  	  DECL_INITIAL (decl) = init = 0;
  	}
!       if (IS_AGGR_TYPE (TREE_TYPE (decl)))
  	{
  	  if (TREE_TYPE (DECL_NAME (decl)))
--- 3158,3163 ----
  	  DECL_INITIAL (decl) = init = 0;
  	}
!       if (current_lang_name == lang_name_cplusplus
! 	  && IS_AGGR_TYPE (TREE_TYPE (decl)))
  	{
  	  if (TREE_TYPE (DECL_NAME (decl)))
***************
*** 4961,4965 ****
  	 refer to it, so nothing needs know about the name change.
  	 The TYPE_NAME field was filled in by build_struct_xref.  */
!       if (IS_AGGR_TYPE (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
  	  && ANON_AGGRNAME_P (DECL_NAME (TYPE_NAME (type))))
--- 4986,4991 ----
  	 refer to it, so nothing needs know about the name change.
  	 The TYPE_NAME field was filled in by build_struct_xref.  */
!       if (current_lang_name == lang_name_cplusplus
! 	  && IS_AGGR_TYPE (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
  	  && ANON_AGGRNAME_P (DECL_NAME (TYPE_NAME (type))))
***************
*** 8047,8068 ****
        IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
  
!     /* Pop the current level, and free the structure for reuse.  */
! 
!     {
!       register struct binding_level *level = current_binding_level;
!       current_binding_level = current_binding_level->level_chain;
! 
!       level->level_chain = free_binding_level;
!       free_binding_level = level;
!       if (current_binding_level->parm_flag < 0)
! 	{
! 	  class_binding_level = current_binding_level;
! 	  do
! 	    {
! 	      current_binding_level = current_binding_level->level_chain;
! 	    }
! 	  while (current_binding_level->parm_flag < 0);
! 	}
!     }
    }
  
--- 8073,8077 ----
        IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
  
!     POP_BINDING_LEVEL;
    }
  
diff -rc2H g++-1.35.0/cplus-init.c g++-1.35.0+/cplus-init.c
*** g++-1.35.0/cplus-init.c	Tue May 16 23:45:23 1989
--- g++-1.35.0+/cplus-init.c	Fri May 19 14:22:36 1989
***************
*** 47,50 ****
--- 47,51 ----
  void expand_aggr_init ();
  tree build_virtual_init ();
+ tree build_vbase_delete ();
  
  static void expand_aggr_init_1 ();
***************
*** 191,195 ****
  	     an immediate base class, complain.  */
  	  for (i = n_baseclasses; i > 0; i--)
! 	    if (basetype == CLASSTYPE_BASECLASS (current_class_type, i))
  	      break;
  	  if (i == 0)
--- 192,196 ----
  	     an immediate base class, complain.  */
  	  for (i = n_baseclasses; i > 0; i--)
! 	    if (basetype == CLASSTYPE_THIS_BASECLASS (current_class_type, i))
  	      break;
  	  if (i == 0)
***************
*** 2533,2536 ****
--- 2534,2540 ----
  }
  
+ /* Delete an object at top level.  This means we delete both the
+    object and its virtual base classes.  */
+ 
  void
  expand_delete (type, addr, auto_delete, protect)
***************
*** 2563,2570 ****
    else
      {
        rval = build_delete (type, addr, auto_delete, protect);
!       if (rval != error_mark_node)
! 	expand_expr_stmt (rval);
!       else
  	/* Have to emit something, since it might be a cleanup.  */
  	emit_note (0, -1);
--- 2567,2580 ----
    else
      {
+       struct rtx_def *get_last_insn ();
+       struct rtx_def *last_insn = get_last_insn ();
+ 
        rval = build_delete (type, addr, auto_delete, protect);
!       expand_expr_stmt (rval);
!       if (TYPE_NEEDS_DESTRUCTOR (type)
! 	  && TYPE_USES_VIRTUAL_BASECLASSES (type))
! 	expand_expr_stmt (build_vbase_delete (type, addr));
! 
!       if (get_last_insn () == last_insn)
  	/* Have to emit something, since it might be a cleanup.  */
  	emit_note (0, -1);
***************
*** 2572,2578 ****
  }
  
  /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
     ADDR is an expression which yields the store to be destroyed.
!    AUTO_DELETE is nonzero if a call to DELETE should be made or not.  */
  tree
  build_delete (type, addr, auto_delete, protect)
--- 2582,2615 ----
  }
  
+ /* Free up storage of type TYPE, at address ADDR.
+    TYPE is a POINTER_TYPE.
+ 
+    This does not call any destructors.  */
+ tree
+ build_x_delete (type, addr)
+      tree type, addr;
+ {
+   tree rval;
+ 
+   if (TREE_GETS_DELETE (TREE_TYPE (type)))
+     rval = build_opfncall (DELETE_EXPR, addr, addr);
+   else
+     {
+       rval = build (CALL_EXPR, void_type_node, BID,
+ 		    build_tree_list (NULL_TREE, addr), 0);
+       TREE_VOLATILE (rval) = 1;
+     }
+   return rval;
+ }
+ 
  /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
     ADDR is an expression which yields the store to be destroyed.
!    AUTO_DELETE is nonzero if a call to DELETE should be made or not.
! 
!    PROTECT is nonzero if we protect access to the virtual baseclass
!    members.
! 
!    This function does not delete an object's virtual base classes.
!    Call `expand_delete' for that.  */
  tree
  build_delete (type, addr, auto_delete, protect)
***************
*** 2753,2757 ****
  	}
        else if (basetype == NULL_TREE
! 	       || ! TYPE_NEEDS_DESTRUCTOR (basetype))
  	{
  	  cond = build (COND_EXPR, void_type_node,
--- 2790,2795 ----
  	}
        else if (basetype == NULL_TREE
! 	       || (CLASSTYPE_VIA_VIRTUAL (type, 1) == 0
! 		   && ! TYPE_NEEDS_DESTRUCTOR (basetype)))
  	{
  	  cond = build (COND_EXPR, void_type_node,
***************
*** 2765,2769 ****
  	exprstmt = build_tree_list (NULL_TREE, cond);
  
!       if (basetype && TYPE_NEEDS_DESTRUCTOR (basetype))
  	{
  	  expr = build_delete (basetype, ref, parent_auto_delete, protect);
--- 2803,2809 ----
  	exprstmt = build_tree_list (NULL_TREE, cond);
  
!       if (basetype
! 	  && ! CLASSTYPE_VIA_VIRTUAL (type, 1)
! 	  && TYPE_NEEDS_DESTRUCTOR (basetype))
  	{
  	  expr = build_delete (basetype, ref, parent_auto_delete, protect);
***************
*** 2776,2780 ****
  	{
  	  basetype = CLASSTYPE_BASECLASS (type, i);
! 	  if (! TYPE_NEEDS_DESTRUCTOR (basetype))
  	    continue;
  
--- 2816,2821 ----
  	{
  	  basetype = CLASSTYPE_BASECLASS (type, i);
! 	  if (! TYPE_NEEDS_DESTRUCTOR (basetype)
! 	      || CLASSTYPE_VIA_VIRTUAL (type, i))
  	    continue;
  
***************
*** 2794,2799 ****
  	  if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member)))
  	    {
! 	      expr = build_delete (TREE_TYPE (member),
! 				   build_component_ref (ref, DECL_NAME (member), 0, 0),
  				   integer_zero_node, 1);
  	      if (expr == error_mark_node)
--- 2835,2840 ----
  	  if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member)))
  	    {
! 	      tree this_member = build_component_ref (ref, DECL_NAME (member), 0, 0);
! 	      expr = build_delete (TREE_TYPE (member), this_member,
  				   integer_zero_node, 1);
  	      if (expr == error_mark_node)
***************
*** 2800,2803 ****
--- 2841,2851 ----
  		return error_mark_node;
  	      exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+ 	      if (TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (member)))
+ 		{
+ 		  expr = build_vbase_delete (TREE_TYPE (member), this_member);
+ 		  if (expr == error_mark_node)
+ 		    return error_mark_node;
+ 		  exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+ 		}
  	    }
  	}
***************
*** 2805,2814 ****
        if (exprstmt)
  	return build_compound_expr (exprstmt);
!       else
! 	{
! 	  compiler_error ("build delete does nothing");
! 	  return error_mark_node;
! 	}
      }
  }
  
--- 2853,2880 ----
        if (exprstmt)
  	return build_compound_expr (exprstmt);
!       /* Virtual base classes make this function do nothing.  */
!       return build (NOP_EXPR, void_type_node, integer_zero_node);
!     }
! }
! 
! /* For type TYPE, delete the virtual baseclass objects of DECL.  */
! 
! tree
! build_vbase_delete (type, decl)
!      tree type, decl;
! {
!   tree vbases = CLASSTYPE_VBASECLASSES (type);
!   tree result = NULL_TREE;
!   tree addr = build_unary_op (ADDR_EXPR, decl, 0);
!   if (addr == error_mark_node)
!     return error_mark_node;
!   while (vbases)
!     {
!       result = tree_cons (NULL_TREE,
! 			  build_delete (TYPE_POINTER_TO (TREE_VALUE (vbases)),
! 					addr, integer_zero_node, 1), result);
!       vbases = TREE_CHAIN (vbases);
      }
+   return build_compound_expr (nreverse (result));
  }
  
***************
*** 2821,2825 ****
     This function expands (or synthesizes) these calls itself.
     AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
!    AUTO_DELETE say whether each item in the container should be deallocated.  */
  void
  expand_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete)
--- 2887,2893 ----
     This function expands (or synthesizes) these calls itself.
     AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
!    AUTO_DELETE say whether each item in the container should be deallocated.
! 
!    This also calls delete for virtual baseclasses of elements of the vector.  */
  void
  expand_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete)
***************
*** 2912,2916 ****
     This generates a call to the function BIVD, which passes the
     destructor across the vector.  This is needed only when
!    expanding such an action is unacceptable.  */
  tree
  build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete)
--- 2980,2986 ----
     This generates a call to the function BIVD, which passes the
     destructor across the vector.  This is needed only when
!    expanding such an action is unacceptable.
! 
!    This does not call delete on the elements' virtual baseclasses.  */
  tree
  build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete)
diff -rc2H g++-1.35.0/cplus-parse.y g++-1.35.0+/cplus-parse.y
*** g++-1.35.0/cplus-parse.y	Tue May 16 23:45:24 1989
--- g++-1.35.0+/cplus-parse.y	Fri May 19 14:22:38 1989
***************
*** 623,628 ****
  		      $$ = error_mark_node;
  		    }
! 		  else
  		    $$ = build_delete (type, expr, integer_one_node, 1);
  		}
  	| DELETE '[' expr ']' expr_no_commas  %prec UNARY
--- 623,637 ----
  		      $$ = error_mark_node;
  		    }
! 		  else if (! IS_AGGR_TYPE (TREE_TYPE (type))
! 			   || ! TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (type)))
  		    $$ = build_delete (type, expr, integer_one_node, 1);
+ 		  else
+ 		    {
+ 		      $$ = build (COMPOUND_EXPR, void_type_node,
+ 				  build (COMPOUND_EXPR, void_type_node,
+ 					 build_delete (type, expr, integer_zero_node, 1),
+ 					 build_vbase_delete (type, expr)),
+ 				  build_x_delete (type, expr));
+ 		    }
  		}
  	| DELETE '[' expr ']' expr_no_commas  %prec UNARY
diff -rc2H g++-1.35.0/cplus-search.c g++-1.35.0+/cplus-search.c
*** g++-1.35.0/cplus-search.c	Tue May 16 23:45:25 1989
--- g++-1.35.0+/cplus-search.c	Fri May 19 14:22:39 1989
***************
*** 2027,2030 ****
--- 2027,2036 ----
  }
  
+ /* Some virtual baseclasses might be virtual baseclasses for
+    other virtual baseclasses.  We sort the virtual baseclasses
+    topologically: in the list returned, the first virtual base
+    classes have no virtual baseclasses themselves, and any entry
+    on the list has no dependency on virtual base classes later in the
+    list.  */
  tree
  get_vbase_types (type)
***************
*** 2034,2038 ****
  
    dfs_walk (type, dfs_get_vbase_types, unmarkedp);
!   dfs_walk (type, dfs_unmark12, markedp);
  
    return vbase_types;
--- 2040,2081 ----
  
    dfs_walk (type, dfs_get_vbase_types, unmarkedp);
!   dfs_walk (type, dfs_unmark, markedp);
! 
!   if (vbase_types)
!     {
!       /* Now sort these types.  This is essentially a bubble sort.  */
!       tree vbases = vbase_types;
! 
!       while (vbases)
! 	{
! 	  tree prev = NULL_TREE;
! 	  while (vbases
! 		 && ! TYPE_USES_VIRTUAL_BASECLASSES (TREE_VALUE (vbases)))
! 	    {
! 	      CLASSTYPE_MARKED2 (TREE_VALUE (vbases)) = 0;
! 	      prev = vbases;
! 	      vbases = TREE_CHAIN (vbases);
! 	    }
! 	  if (vbases)
! 	    {
! 	      /* If all our virtual baseclasses are unmarked, ok.  */
! 	      tree t = CLASSTYPE_VBASECLASSES (TREE_VALUE (vbases));
! 	      while (t && CLASSTYPE_MARKED2 (TREE_VALUE (vbases)) == 0)
! 		t = TREE_CHAIN (t);
! 	      if (t != NULL_TREE)
! 		{
! 		  /* This virtual base class still depends on others.  */
! 		  tree next = TREE_CHAIN (vbases);
! 		  assert (prev != NULL_TREE);
! 		  TREE_CHAIN (prev) = next;
! 		  TREE_CHAIN (vbases) = TREE_CHAIN (next);
! 		  TREE_CHAIN (next) = vbases;
! 		  vbases = next;
! 		  continue;
! 		}
! 	    }
! 	  break;
! 	}
!     }
  
    return vbase_types;
diff -rc2H g++-1.35.0/cplus-typeck.c g++-1.35.0+/cplus-typeck.c
*** g++-1.35.0/cplus-typeck.c	Tue May 16 23:45:27 1989
--- g++-1.35.0+/cplus-typeck.c	Fri May 19 14:22:41 1989
***************
*** 3708,3712 ****
  
        t = TREE_OPERAND (arg, 1);
!       if (TREE_OPERAND (arg, 0))
  	{
  	  /* Don't know if this should return address to just
--- 3708,3714 ----
  
        t = TREE_OPERAND (arg, 1);
!       if (TREE_OPERAND (arg, 0)
! 	  && (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
! 	      || TREE_OPERAND (TREE_OPERAND (arg, 0), 0) != error_mark_node))
  	{
  	  /* Don't know if this should return address to just
***************
*** 4788,4791 ****
--- 4790,4802 ----
      rhs = TREE_OPERAND (rhs, 0);
  
+   if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
+     {
+       rhs = resolve_member_ref (rhs);
+       if (rhs == error_mark_node)
+ 	return error_mark_node;
+       rhstype = TREE_TYPE (rhs);
+       coder = TREE_CODE (rhstype);
+     }
+ 
    if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
        || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
***************
*** 5047,5050 ****
--- 5058,5070 ----
        && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0)))
      rhs = TREE_OPERAND (rhs, 0);
+ 
+   if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
+     {
+       rhs = resolve_member_ref (rhs);
+       if (rhs == error_mark_node)
+ 	return error_mark_node;
+       rhstype = TREE_TYPE (rhs);
+       coder = TREE_CODE (rhstype);
+     }
  
    if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
diff -rc2H g++-1.35.0/gcc.c g++-1.35.0+/gcc.c
*** g++-1.35.0/gcc.c	Tue May 16 23:45:31 1989
--- g++-1.35.0+/gcc.c	Fri May 19 14:22:45 1989
***************
*** 278,281 ****
--- 278,297 ----
                        %{!pipe:%g.s}\
  		      %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"},
+   {".cxx",
+    "cpp -+ %{nostdinc} %{C} %{v} %{D*} %{U*} %{I*} %{M*} %{T}\
+         -undef -D__GNU__ -D__GNUG__ -D__cplusplus %{ansi:-T -D__STRICT_ANSI__} %{!ansi:%p} %P\
+         %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic}\
+ 	%{Wcomment*} %{Wtrigraphs} %{Wall} %C\
+         %i %{!M*:%{!E:%{!pipe:%g.cpp}}}%{E:%{o*}}%{M*:%{o*}} |\n\
+     %{!M*:%{!E:cc1plus %{!pipe:%g.cpp} %1 \
+ 		   %{!Q:-quiet} -dumpbase %i %{Y*} %{d*} %{m*} %{f*} %{a}\
+ 		   %{W*} %{w} %{pedantic} %{ansi} %{traditional}\
+ 		   %{O:-opt}%{!O:-noreg}\
+ 		   %{v:-version} %{g:-G} %{g0:-G0} %{pg:-p} %{p}\
+ 		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ 		   %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
+ 	      %{!S:as %{R} %{j} %{J} %{h} %{d2} %a\
+                       %{!pipe:%g.s}\
+ 		      %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"},
    {".i",
     "cc1 %i %1 %{!Q:-quiet} %{Y*} %{d*} %{m*} %{f*} %{a}\
diff -rc2H g++-1.35.0/make-links.g++ g++-1.35.0+/make-links.g++
*** g++-1.35.0/make-links.g++	Tue May 16 23:45:38 1989
--- g++-1.35.0+/make-links.g++	Fri May 19 14:22:47 1989
***************
*** 34,41 ****
  then
  	DIR="../gcc"
- 	CDIR="../../gcc/config"
  else
- 	CDIR="${DIR}/config"
  fi
  
  progname=$0
--- 34,40 ----
  then
  	DIR="../gcc"
  else
  fi
+ CDIR="../${DIR}/config"
  
  progname=$0
***************
*** 61,65 ****
    insn-output.c insn-flags.h insn-config.h insn-codes.h"
  
! $remove -f config
  $make_directory config
  $change_directory config
--- 60,64 ----
    insn-output.c insn-flags.h insn-config.h insn-codes.h"
  
! $remove -rf config
  $make_directory config
  $change_directory config
diff -rc2H g++-1.35.0/stmt.c g++-1.35.0+/stmt.c
*** g++-1.35.0/stmt.c	Tue May 16 23:45:34 1989
--- g++-1.35.0+/stmt.c	Fri May 19 14:22:50 1989
***************
*** 511,514 ****
--- 511,518 ----
        if (stack_level)
  	emit_move_insn (stack_pointer_rtx, stack_level);
+ #ifndef EXIT_IGNORE_STACK
+       else
+ 	do_pending_stack_adjust ();
+ #endif
  
        if (body != 0 && TREE_PACKED (body))
***************
*** 1754,1757 ****
--- 1758,1765 ----
  			  thisblock->data.block.stack_level);
  	}
+ #ifndef EXIT_IGNORE_STACK
+       else
+ 	do_pending_stack_adjust ();
+ #endif
  
        /* Any gotos out of this block must also do these things.
***************
*** 2077,2080 ****
--- 2085,2092 ----
  
    expand_cleanups (list, 0);
+ #ifndef EXIT_IGNORE_STACK
+   do_pending_stack_adjust ();
+ #endif
+ 
    new_before_jump = get_last_insn ();
  
diff -rc2H g++-1.35.0/stor-layout.c g++-1.35.0+/stor-layout.c
*** g++-1.35.0/stor-layout.c	Tue May 16 23:45:35 1989
--- g++-1.35.0+/stor-layout.c	Fri May 19 14:22:51 1989
***************
*** 439,458 ****
        if (TYPE_SIZE (basetype) == 0)
  	{
! 	  int j;
! 	  /* The base type is of incomplete type.  It is
! 	     probably best to pretend that it does not
! 	     exist.  */
! 	  error ("base class `%s' has incomplete type", TYPE_NAME_STRING (basetype));
! 	  if (i == n_baseclasses)
! 	    CLASSTYPE_THIS_BASECLASS (rec, i) = NULL_TREE;
! 	  CLASSTYPE_N_BASECLASSES (rec) -= 1;
! 	  n_baseclasses -= 1;
! 	  for (j = i; j < n_baseclasses; j++)
! 	    {
! 	      CLASSTYPE_THIS_BASECLASS (rec, j) = CLASSTYPE_THIS_BASECLASS (rec, j+1);
! 	      SET_CLASSTYPE_VIAS (rec, j,
! 				 CLASSTYPE_VIA_PUBLIC (rec, j+1),
! 				 CLASSTYPE_VIA_VIRTUAL (rec, j+1));
! 	    }
  	  continue;
  	}
--- 439,443 ----
        if (TYPE_SIZE (basetype) == 0)
  	{
! 	  error_with_aggr_type (basetype, "base class `%s' has incomplete type");
  	  continue;
  	}
diff -rc2H g++-1.35.0/version.c g++-1.35.0+/version.c
*** g++-1.35.0/version.c	Tue May 16 23:45:37 1989
--- g++-1.35.0+/version.c	Fri May 19 14:22:54 1989
***************
*** 1,1 ****
! char *version_string = "1.35.0";
--- 1,1 ----
! char *version_string = "1.35.0+";
yahi% 

If these diffs make anything worse, I need to know.

Michael