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