tiemann@YAHI.STANFORD.EDU (Michael Tiemann) (05/23/89)
These diffs fix bugs reported with MI, configuration file problems, and other minor problems. I will release 1.35.1 when that seems appropriate. Changes to fold-const.c provide a performance improvement over previous versions of the compiler. After profiling, it appears that the parser itself is the major hog of CPU cycles. I suspect that this is due to epsilon rules needed to parse C++ with an LALR parser. yahi% diff -rc2H g++-1.35.0+ src-g++ diff -rc2H g++-1.35.0+/ChangeLog src-g++/ChangeLog *** g++-1.35.0+/ChangeLog Fri May 19 14:22:31 1989 --- src-g++/ChangeLog Tue May 23 01:12:46 1989 *************** *** 1,28 **** 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 --- 1,71 ---- + Tue May 23 01:10:51 1989 Michael Tiemann (tiemann at yahi) + + * cplus-cvt.c: (convert_to_pointer) convert to virtual baseclasses + through virtual baseclass pointers. Also, give error if + converting up from a virtual baseclass type. + + Mon May 22 22:03:24 1989 Michael Tiemann (tiemann at yahi) + + * cplus-class.c: (finish_struct) remember to give dynamic classes + a vfield even if they don't define virtual functions (-fSOS). + + * cplus-decl.c: (init_decl_processing) fixed typo: TYPE_POINTER_TO + does not build a pointer type, but build_pointer_type does. + + * cplus-decl.c, cplus-init.c: allow builtin functions to be + declared friends. + + * cplus-class.c: (ideal_candidate) if the best candidates require + user-defined type conversions, don't reject as ambiguous the + case where one candidate comes from one class, and the other + candidates come from base classes of that class. + + * stor-layout.c: (layout_type) after laying out a type, make sure + that all type variants get the type's size. + Fri May 19 13:20:07 1989 Michael Tiemann (tiemann at yahi) ! * cplus-class.c: (popclass) don't kill out prev_class_type's decls ! if not at the global binding level. ! * cplus-decl.c: added new field `class_shadowed', which may some ! day be used to implement nested clases. ! ! * newld.c: (various places) round up size to double word boundary ! if defined(sparc) || defined(sun). ! ! * tree.c: (lvalue_p) A CALL_EXPR is an lvalue if the return type ! is an addressable type. ! ! * cplus-init.c: (make_friend_class) fix typo in error message. ! ! * cplus-class.c: (finish_struct) Don't give error message if class ! is does not define virtual functions which must be defined if ! that class has some of its own. ! ! * cplus-class.c: (instantiate_type) 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: (layout_basetypes) language dependent code ! removed, put in cplus-class.c ! ! * stmt.c: (expand_goto_internal, expand_end_bindings, ! fixup_cleanups) if cleanups were called on leaving a binding ! contour, and EXIT_IGNORE_STACK is not defined, call ! do_pending_stack_adjust. * 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) recognize 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) 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 *************** *** 31,37 **** * 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 --- 74,80 ---- * cplus-parse.y: call build_vbase_delete if appropriate. ! * cplus-init.c: (expand_delete) call build_vbase_delete if ! appropriate. No longer deletes parts of objects via virtual ! base classes. * cplus-init.c: new function build_vbase_delete, performs *************** *** 40,44 **** 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. --- 83,87 ---- running destructors. ! * cplus-decl.c: (pushdecl, shadow_tag, and xref_tag) implement C-like behavior in "C" language scope vis a vis type declarations. *************** *** 56,61 **** to cplus-class.c. ! * cplus-class.c: changed `finish_struct' to call ! `propagate_basetype_offsets'. * cplus-class.c: new function `propagate_basetype_offsets' gives --- 99,103 ---- to cplus-class.c. ! * cplus-class.c: (finish_struct) call `propagate_basetype_offsets'. * cplus-class.c: new function `propagate_basetype_offsets' gives diff -rc2H g++-1.35.0+/config.g++ src-g++/config.g++ *** g++-1.35.0+/config.g++ Fri May 19 14:22:32 1989 --- src-g++/config.g++ Fri May 19 16:02:24 1989 *************** *** 134,138 **** 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 ;; --- 134,137 ---- diff -rc2H g++-1.35.0+/cplus-class.c src-g++/cplus-class.c *** g++-1.35.0+/cplus-class.c Fri May 19 14:22:33 1989 --- src-g++/cplus-class.c Tue May 23 08:14:38 1989 *************** *** 918,921 **** --- 918,922 ---- tree friend_list = 0; int nonprivate_method = 0; + int uninheritable_virtuals = 0; if (TREE_CODE (name) == TYPE_DECL) *************** *** 998,1002 **** 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) --- 999,1003 ---- TYPE_USES_VIRTUAL_BASECLASSES (t) |= (TYPE_USES_VIRTUAL_BASECLASSES (basetype) | CLASSTYPE_VIA_VIRTUAL (t, i)); ! uninheritable_virtuals |= CLASSTYPE_HAS_UNINHERITABLE_VIRTUALS (basetype) | (CLASSTYPE_UNINHERITED_VIRTUALS (basetype) != 0); CLASSTYPE_ALTERS_VISIBILITIES_P (t) *************** *** 1774,1777 **** --- 1775,1792 ---- has_virtual = has_absolute; CLASSTYPE_VSIZE (t) = has_virtual; + if (vfield == 0) + { + /* We build this decl with ptr_type_node, and + change the type when we know what it should be. */ + vfield = build_lang_decl (FIELD_DECL, get_vfield_name (t), ptr_type_node); + DECL_FIELD_CONTEXT (vfield) = t; + DECL_VCONTEXT (vfield) = t; + DECL_SIZE_UNIT (vfield) = 0; + y = tree_last (fields); + if (y) + TREE_CHAIN (y) = vfield; + else + fields = vfield; + } } #endif *************** *** 1821,1829 **** } /* Now that we know all virtual functions defined for this class, make sure we don't inherit any from a base class we are not ! supposed to inherit. */ ! if (CLASSTYPE_HAS_UNINHERITABLE_VIRTUALS (t)) { x = TREE_CHAIN (CLASSTYPE_VIRTUALS (t)); while (x != NULL_TREE) --- 1836,1851 ---- } + CLASSTYPE_HAS_UNINHERITABLE_VIRTUALS (t) + = (uninheritable_virtuals || CLASSTYPE_UNINHERITED_VIRTUALS (t)); + /* Now that we know all virtual functions defined for this class, make sure we don't inherit any from a base class we are not ! supposed to inherit, but only if we don't define any such ! virtual functions ourself. */ ! ! if (uninheritable_virtuals ! && ! CLASSTYPE_UNINHERITED_VIRTUALS (t)) { + int errors = 0; x = TREE_CHAIN (CLASSTYPE_VIRTUALS (t)); while (x != NULL_TREE) *************** *** 1835,1840 **** && value_member (decl, CLASSTYPE_UNINHERITED_VIRTUALS (context))) { ! error_with_decl (decl, "Virtual function `%s' cannot be inherited from base class"); ! error ("at this point in file"); } x = TREE_CHAIN (x); --- 1857,1866 ---- && value_member (decl, CLASSTYPE_UNINHERITED_VIRTUALS (context))) { ! if (errors == 0) ! { ! errors = 1; ! error ("at this point in file, "); ! } ! error_with_decl (decl, "virtual function `%s' cannot be inherited from base class"); } x = TREE_CHAIN (x); *************** *** 1934,1940 **** if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t)) { ! TYPE_MODE (t) = BLKmode; DECL_MODE (TYPE_NAME (t)) = BLKmode; ! TREE_ADDRESSABLE (t) = 1; } --- 1960,1972 ---- if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t)) { ! tree variants = t; ! DECL_MODE (TYPE_NAME (t)) = BLKmode; ! while (variants) ! { ! TYPE_MODE (variants) = BLKmode; ! TREE_ADDRESSABLE (variants) = 1; ! variants = TYPE_NEXT_VARIANT (variants); ! } } *************** *** 2610,2613 **** --- 2642,2646 ---- tree tta = parms; tree ttf; + tree f1, p1; #if AMBIGUOUS_WORKING *************** *** 2664,2670 **** { if (best == 0) ! best = i; else ! return 0; } } while (cp + i != candidates); --- 2697,2724 ---- { if (best == 0) ! { ! best = i; ! f1 = cp[best].function; ! p1 = TYPE_ARG_TYPES (TREE_TYPE (f1)); ! } else ! { ! /* Don't complain if next best is from base class. */ ! tree f2 = cp[i].function; ! tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2)); ! ! if (TREE_CODE (TREE_TYPE (f1)) == METHOD_TYPE ! && TREE_CODE (TREE_TYPE (f2)) == METHOD_TYPE ! && (cp[i].harshness[0] & 4) != 0 ! && cp[best].harshness[0] < cp[i].harshness[0]) ! { ! if (! compparms (TREE_CHAIN (p1), TREE_CHAIN (p2), 1)) ! return 0; ! else ! continue; ! } ! else ! return 0; ! } } } while (cp + i != candidates); *************** *** 3585,3589 **** IDENTIFIER_POINTER (name)); else ! error_with_aggr_type (save_basetype, "no member function `%s' defined within type `%s'", IDENTIFIER_POINTER (name)); return error_mark_node; --- 3639,3643 ---- IDENTIFIER_POINTER (name)); else ! error_with_aggr_type (save_basetype, "no member function `%s::%s'", IDENTIFIER_POINTER (name)); return error_mark_node; *************** *** 4045,4049 **** current_class_type = type; ! if (type != prev_class_type && prev_class_type != NULL_TREE) { popclass (-1); --- 4099,4104 ---- current_class_type = type; ! if (type != prev_class_type && prev_class_type != NULL_TREE ! && current_class_stack == current_class_base + 1) { popclass (-1); diff -rc2H g++-1.35.0+/cplus-cvt.c src-g++/cplus-cvt.c *** g++-1.35.0+/cplus-cvt.c Fri May 19 14:22:33 1989 --- src-g++/cplus-cvt.c Tue May 23 06:08:22 1989 *************** *** 86,89 **** --- 86,90 ---- && IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))) { + enum tree_code code = PLUS_EXPR; tree basetype = get_base_type (TREE_TYPE (TYPE_MAIN_VARIANT (type)), TREE_TYPE (intype), 1); *************** *** 90,119 **** if (basetype == error_mark_node) return error_mark_node; ! if (basetype && DECL_OFFSET (TYPE_NAME (basetype)) != 0) { ! tree addr = TREE_CODE (expr) == ADDR_EXPR ! ? expr : save_expr (expr); ! tree temp = build (NOP_EXPR, string_type_node, addr); ! ! return build (COND_EXPR, type, ! build (EQ_EXPR, integer_type_node, temp, integer_zero_node), ! build (NOP_EXPR, type, temp), ! build (PLUS_EXPR, type, temp, CLASSTYPE_OFFSET (basetype))); } ! basetype = get_base_type (TREE_TYPE (intype), ! TREE_TYPE (TYPE_MAIN_VARIANT (type)), 1); ! if (basetype == error_mark_node) ! return error_mark_node; ! if (basetype && DECL_OFFSET (TYPE_NAME (basetype)) != 0) { ! tree addr = TREE_CODE (expr) == ADDR_EXPR ! ? expr : save_expr (expr); ! tree temp = build (NOP_EXPR, string_type_node, addr); ! return build (COND_EXPR, type, ! build (EQ_EXPR, integer_type_node, temp, integer_zero_node), ! build (NOP_EXPR, type, temp), ! build (MINUS_EXPR, type, temp, ! CLASSTYPE_OFFSET (basetype))); } } --- 91,141 ---- if (basetype == error_mark_node) return error_mark_node; ! if (basetype == NULL_TREE) { ! basetype = get_base_type (TREE_TYPE (intype), ! TREE_TYPE (TYPE_MAIN_VARIANT (type)), 1); ! if (basetype == error_mark_node) ! return error_mark_node; ! code = MINUS_EXPR; } ! if (basetype) { ! if (TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (type)) ! || TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (intype))) ! { ! /* Need to get the path we took. */ ! tree path; ! if (code == PLUS_EXPR) ! get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), 0, &path); ! else ! get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), 0, &path); ! while (path) ! { ! if (TREE_VIA_VIRTUAL (path)) ! { ! if (code == PLUS_EXPR) ! expr = build_vbase_pointer (build_indirect_ref (expr), TREE_VALUE (path)); ! else ! { ! error_with_aggr_type (TREE_VALUE (path), "cannot cast up from virtual baseclass `%s'"); ! return error_mark_node; ! } ! } ! path = TREE_CHAIN (path); ! } ! return build (NOP_EXPR, type, expr); ! } ! if (basetype && DECL_OFFSET (TYPE_NAME (basetype)) != 0) ! { ! tree addr = TREE_CODE (expr) == ADDR_EXPR ! ? expr : save_expr (expr); ! tree temp = build (NOP_EXPR, string_type_node, addr); ! return build (COND_EXPR, type, ! build (EQ_EXPR, integer_type_node, temp, integer_zero_node), ! build (NOP_EXPR, type, temp), ! build (code, type, ! temp, CLASSTYPE_OFFSET (basetype))); ! } } } diff -rc2H g++-1.35.0+/cplus-decl.c src-g++/cplus-decl.c *** g++-1.35.0+/cplus-decl.c Fri May 19 14:22:35 1989 --- src-g++/cplus-decl.c Tue May 23 06:07:52 1989 *************** *** 99,103 **** --- 99,105 ---- multiple error messages from one error in the input. */ + #undef error_mark_node tree error_mark_node; + #define error_mark_node (&ERROR_MARK_NODE) /* Erroneous argument lists can use this *IFF* they do not modify it. */ *************** *** 543,546 **** --- 545,551 ---- tree shadowed; + /* Same, for IDENTIFIER_CLASS_VALUE. */ + tree class_shadowed; + /* For each level (except not the global one), a chain of LET_STMT nodes for all the levels *************** *** 593,597 **** static struct binding_level clear_binding_level ! = {NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0}; #define PUSH_BINDING_LEVEL(NEWLEVEL, TAG_TRANSPARENT, TEMPORARY) \ --- 598,602 ---- static struct binding_level clear_binding_level ! = {NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0}; #define PUSH_BINDING_LEVEL(NEWLEVEL, TAG_TRANSPARENT, TEMPORARY) \ *************** *** 809,812 **** --- 814,821 ---- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + for (link = current_binding_level->class_shadowed; + link; + link = TREE_CHAIN (link)) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); /* If the level being exited is the top level of a function, *************** *** 2405,2408 **** --- 2414,2419 ---- Make definitions for built-in primitive functions. */ + union tree_node ERROR_MARK_NODE; + void init_decl_processing () *************** *** 2416,2420 **** --- 2427,2438 ---- /* Must lay these out before anything else gets laid out. */ + #if 0 error_mark_node = make_node (ERROR_MARK); + #else + #undef error_mark_node + error_mark_node = &ERROR_MARK_NODE; + #define error_mark_node (&ERROR_MARK_NODE) + TREE_PERMANENT (error_mark_node) = 1; + #endif TREE_TYPE (error_mark_node) = error_mark_node; error_mark_list = build_tree_list (error_mark_node, error_mark_node); *************** *** 2553,2557 **** default_function_type = build_function_type (integer_type_node, NULL_TREE); ! TYPE_POINTER_TO (default_function_type); ptr_type_node = build_pointer_type (void_type_node); --- 2571,2575 ---- default_function_type = build_function_type (integer_type_node, NULL_TREE); ! build_pointer_type (default_function_type); ptr_type_node = build_pointer_type (void_type_node); *************** *** 6375,6379 **** init = decl_constant_value (init); assert (TREE_PERMANENT (init)); ! if (! TREE_LITERAL (init)) { /* We can allow references to things that are effectively --- 6393,6398 ---- init = decl_constant_value (init); assert (TREE_PERMANENT (init)); ! if (init != error_mark_node ! && ! TREE_LITERAL (init)) { /* We can allow references to things that are effectively *************** *** 8072,8075 **** --- 8091,8098 ---- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + for (link = current_binding_level->class_shadowed; + link; + link = TREE_CHAIN (link)) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); POP_BINDING_LEVEL; diff -rc2H g++-1.35.0+/cplus-init.c src-g++/cplus-init.c *** g++-1.35.0+/cplus-init.c Fri May 19 14:22:36 1989 --- src-g++/cplus-init.c Tue May 23 06:08:49 1989 *************** *** 436,439 **** --- 436,440 ---- { tree vtbl, vtbl_ptr; + tree vtype; if (for_type != type) *************** *** 450,457 **** vtbl = build (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl); } - decl = convert_to_nonzero_pointer (TYPE_POINTER_TO (type), decl); - vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, 0), type); - return build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl); } --- 451,458 ---- vtbl = build (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl); } + vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type)); + decl = convert_to_nonzero_pointer (TYPE_POINTER_TO (vtype), decl); + vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, 0), vtype); return build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl); } *************** *** 1859,1863 **** if (classes) warning ("class `%s' is already friends with class `%s'", ! TYPE_NAME_STRING (type), TYPE_NAME_STRING (type)); else { --- 1860,1864 ---- if (classes) warning ("class `%s' is already friends with class `%s'", ! TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type)); else { *************** *** 1936,1944 **** } else if (TREE_CODE (decl) == FUNCTION_DECL ! && IDENTIFIER_LENGTH (declarator) == 4 ! && IDENTIFIER_POINTER (declarator)[0] == 'm' ! && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) { ! /* raw "main" never gets overloaded, but it can become a friend. */ add_friend (current_class_type, decl); DECL_FRIEND_P (decl) = 1; --- 1937,1951 ---- } else if (TREE_CODE (decl) == FUNCTION_DECL ! && ((IDENTIFIER_LENGTH (declarator) == 4 ! && IDENTIFIER_POINTER (declarator)[0] == 'm' ! && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) ! || (IDENTIFIER_LENGTH (declarator) > 10 ! && IDENTIFIER_POINTER (declarator)[0] == '_' ! && IDENTIFIER_POINTER (declarator)[1] == '_' ! && strncmp (IDENTIFIER_POINTER (declarator)+2, ! "builtin_", 8) == 0))) { ! /* raw "main", and builtin functions never gets overloaded, ! but they can become friends. */ add_friend (current_class_type, decl); DECL_FRIEND_P (decl) = 1; *************** *** 2659,2667 **** else { ! ref = addr; ! if (ref == C_C_D) ! addr = current_class_decl; else ! addr = build (ADDR_EXPR, build_pointer_type (type), addr); ptr = 0; } --- 2666,2676 ---- else { ! addr = convert (build_pointer_type (type), ! build_unary_op (ADDR_EXPR, addr, 0)); ! if (TREE_CODE (addr) == NOP_EXPR ! && TREE_OPERAND (addr, 0) == current_class_decl) ! ref = C_C_D; else ! ref = build_indirect_ref (addr, 0); ptr = 0; } diff -rc2H g++-1.35.0+/cplus-lex.c src-g++/cplus-lex.c *** g++-1.35.0+/cplus-lex.c Fri May 19 14:22:37 1989 --- src-g++/cplus-lex.c Tue May 23 07:31:22 1989 *************** *** 1468,1473 **** --- 1468,1478 ---- } + #if 0 #define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0) #define isdigit(char) (char >= '0' && char <= '9') + #else + #include <ctype.h> + #endif + #define ENDFILE -1 /* token that represents end-of-file */ *************** *** 1904,1909 **** || ANON_AGGRNAME_P (tmp) || ANON_PARMNAME_P (tmp))) ! fatal ("identifier name `%s' conflicts with GNU C++ internal naming strategy", ! token_buffer); /* Come into here if we must reprocess an identifier. */ --- 1909,1914 ---- || ANON_AGGRNAME_P (tmp) || ANON_PARMNAME_P (tmp))) ! warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy", ! token_buffer); /* Come into here if we must reprocess an identifier. */ *************** *** 2595,2601 **** } /* Go down for a (X::*) or (X::&). */ ! else if (nextchar >= 'a' && nextchar <= 'z' ! || nextchar >= 'A' && nextchar <= 'Z' ! || nextchar == '_' || nextchar == '$') { YYSTYPE this_yylval = yylval; --- 2600,2604 ---- } /* Go down for a (X::*) or (X::&). */ ! else if (isalpha (nextchar) || nextchar == '_' || nextchar == '$') { YYSTYPE this_yylval = yylval; diff -rc2H g++-1.35.0+/cplus-tree.h src-g++/cplus-tree.h *** g++-1.35.0+/cplus-tree.h Fri May 19 14:22:40 1989 --- src-g++/cplus-tree.h Tue May 23 06:05:31 1989 *************** *** 1086,1092 **** #define PRINT_LANG_TYPE - /* -- end of C++ */ - #define UNKNOWN_TYPE LANG_TYPE #define NO_AUTO_OVERLOAD --- 1086,1096 ---- #define PRINT_LANG_TYPE #define UNKNOWN_TYPE LANG_TYPE #define NO_AUTO_OVERLOAD + + extern union tree_node ERROR_MARK_NODE; + + #define error_mark_node (&ERROR_MARK_NODE) + + /* -- end of C++ */ diff -rc2H g++-1.35.0+/cplus-typeck.c src-g++/cplus-typeck.c *** g++-1.35.0+/cplus-typeck.c Fri May 19 14:22:41 1989 --- src-g++/cplus-typeck.c Tue May 23 08:14:44 1989 *************** *** 4069,4073 **** value get promoted if necessary. */ ! if (type1 == type2 && TREE_CODE (type2) != ARRAY_TYPE && TREE_CODE (type2) != ENUMERAL_TYPE --- 4069,4073 ---- value get promoted if necessary. */ ! if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2) && TREE_CODE (type2) != ARRAY_TYPE && TREE_CODE (type2) != ENUMERAL_TYPE *************** *** 4084,4087 **** --- 4084,4093 ---- if (TREE_READONLY (op2) && TREE_CODE (op2) == VAR_DECL) op2 = decl_constant_value (op2); + if (type1 != type2) + { + int constp = TREE_READONLY (type1) || TREE_READONLY (type2); + int volatilep = TREE_VOLATILE (type1) || TREE_VOLATILE (type2); + type1 = build_type_variant (type1, constp, volatilep); + } return build (COND_EXPR, type1, ifexp, op1, op2); } *************** *** 4104,4109 **** /* Quickly detect the usual case where op1 and op2 have the same type after promotion. */ ! if (type1 == type2) ! result_type = type1; else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE) && (code2 == INTEGER_TYPE || code2 == REAL_TYPE)) --- 4110,4123 ---- /* Quickly detect the usual case where op1 and op2 have the same type after promotion. */ ! if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) ! { ! if (type1 != type2) ! { ! int constp = TREE_READONLY (type1) || TREE_READONLY (type2); ! int volatilep = TREE_VOLATILE (type1) || TREE_VOLATILE (type2); ! type1 = build_type_variant (type1, constp, volatilep); ! } ! result_type = type1; ! } else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE) && (code2 == INTEGER_TYPE || code2 == REAL_TYPE)) diff -rc2H g++-1.35.0+/flags.h src-g++/flags.h *** g++-1.35.0+/flags.h Fri May 19 14:22:43 1989 --- src-g++/flags.h Mon May 22 21:02:57 1989 *************** *** 184,187 **** --- 184,191 ---- extern int flag_delayed_branch; + /* Nonzero means do basic-block instruction scheduling. */ + + extern int flag_schedule_insns; + /* 1 means write out virtual function tables and give them (C) public visibility. diff -rc2H g++-1.35.0+/fold-const.c src-g++/fold-const.c *** g++-1.35.0+/fold-const.c Fri May 19 14:22:44 1989 --- src-g++/fold-const.c Fri May 19 22:55:12 1989 *************** *** 208,211 **** --- 208,242 ---- register int i, j, k; + /* These two cases are used extensively, arising from pointer + combinations. */ + if (h2 == 0) + { + if (l2 == 4) + { + unsigned temp = l1 + l1; + h1 = (temp < l1) << 1; + l1 = temp; + temp += temp; + h1 += (temp < l1); + *lv = temp; + *hv = h1; + return; + } + if (l2 == 8) + { + unsigned temp = l1 + l1; + h1 += (temp < l1) << 2; + l1 = temp; + temp += temp; + h1 += (temp < l1) << 1; + l1 = temp; + temp += temp; + h1 += (temp < l1); + *lv = temp; + *hv = h1; + return; + } + } + encode (arg1, l1, h1); encode (arg2, l2, h2); *************** *** 606,614 **** /* get absolute values */ ! if (*hrem < 0) neg_double(*lrem, *hrem, &labs_rem, &habs_rem); ! if (hden < 0) neg_double(lden, hden, &labs_den, &habs_den); /* if (2 * abs (lrem) >= abs (lden)) */ ! mul_double(2, 0, labs_rem, habs_rem, <wice, &htwice); if (((unsigned) habs_den < (unsigned) htwice) || (((unsigned) habs_den == (unsigned) htwice) --- 637,645 ---- /* get absolute values */ ! if (*hrem < 0) neg_double (*lrem, *hrem, &labs_rem, &habs_rem); ! if (hden < 0) neg_double (lden, hden, &labs_den, &habs_den); /* if (2 * abs (lrem) >= abs (lden)) */ ! mul_double (2, 0, labs_rem, habs_rem, <wice, &htwice); if (((unsigned) habs_den < (unsigned) htwice) || (((unsigned) habs_den == (unsigned) htwice) *************** *** 784,787 **** --- 815,834 ---- case PLUS_EXPR: + if (int1h == 0) + { + int2l += int1l; + if ((unsigned) int2l < int1l) + int2h += 1; + t = build_int_2 (int2l, int2h); + break; + } + if (int2h == 0) + { + int1l += int2l; + if ((unsigned) int1l < int2l) + int1h += 1; + t = build_int_2 (int1l, int1h); + break; + } add_double (int1l, int1h, int2l, int2h, &low, &hi); t = build_int_2 (low, hi); *************** *** 789,792 **** --- 836,849 ---- case MINUS_EXPR: + if (int1h == 0 && int1l == 0) + { + t = build_int_2 (- int2l, - int2h); + break; + } + if (int2h == 0 && int2l == 0) + { + t = build_int_2 (int1l, int1h); + break; + } neg_double (int2l, int2h, &int2l, &int2h); add_double (int1l, int1h, int2l, int2h, &low, &hi); *************** *** 795,798 **** --- 852,921 ---- case MULT_EXPR: + /* Optimize simple cases. */ + if (int1h == 0) + { + unsigned temp; + + switch (int1l) + { + case 0: + t = build_int_2 (0, 0); + goto got_it; + case 1: + t = build_int_2 (int2l, int2h); + goto got_it; + case 2: + temp = int2l + int2l; + int2h += (temp < int2l); + t = build_int_2 (temp, int2h); + goto got_it; + case 3: + temp = int2l + int2l + int2l; + int2h += (temp < int2l); + t = build_int_2 (temp, int2h); + goto got_it; + case 4: + temp = int2l + int2l; + int2h += (temp < int2l) << 1; + int2l = temp; + temp += temp; + int2h += (temp < int2l); + t = build_int_2 (temp, int2h); + goto got_it; + case 5: + case 6: + case 7: + /* Don't bother with these. */ + break; + case 8: + temp = int2l + int2l; + int2h += (temp < int2l) << 2; + int2l = temp; + temp += temp; + int2h += (temp < int2l) << 1; + int2l = temp; + temp += temp; + int2h += (temp < int2l); + t = build_int_2 (temp, int2h); + goto got_it; + default: + break; + } + } + + if (int2h == 0) + { + if (int2l == 0) + { + t = build_int_2 (0, 0); + break; + } + if (int2l == 1) + { + t = build_int_2 (int1l, int1h); + break; + } + } + mul_double (int1l, int1h, int2l, int2h, &low, &hi); t = build_int_2 (low, hi); *************** *** 802,805 **** --- 925,941 ---- case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR: case EXACT_DIV_EXPR: + if (int2h == 0 && int2l == 1) + { + t = build_int_2 (int1l, int1h); + break; + } + if (int1l == int2l && int1h == int2h) + { + if ((int1l | int1h) == 0) + abort (); + t = build_int_2 (1, 0); + TREE_UNSIGNED (t) = uns; + break; + } div_and_round_double (code, uns, int1l, int1h, int2l, int2h, &low, &hi, &garbagel, &garbageh); *************** *** 837,840 **** --- 973,977 ---- abort (); } + got_it: TREE_TYPE (t) = TREE_TYPE (arg1); force_fit_type (t); diff -rc2H g++-1.35.0+/g++.texinfo src-g++/g++.texinfo *** g++-1.35.0+/g++.texinfo Fri May 19 14:22:45 1989 --- src-g++/g++.texinfo Mon May 22 23:56:39 1989 *************** *** 1120,1128 **** @item -flabels-ok ! Allow labels to be found in name-space. The compiler will allow a variable ! to be assigned to the value of a label, thus making complex jump tables ! constructible within GNU C++. Note that labels are not lvalues, and cannot ! be assigned to variables. @item -d@var{letters} Says to make debugging dumps at times specified by @var{letters}. --- 1120,1171 ---- @item -flabels-ok ! Allow labels to be found in name-space. The compiler will allow a ! variable to be assigned to the value of a label, thus making complex ! jump tables constructible within GNU C++. Note that labels are not ! lvalues, and cannot be assigned to variables. (This option is not ! currently implemented...) ! ! @item -felide-constructors ! Using this option instructs the compiler to be smarter about when it can ! elide constructors. With out this flag, GNU C++ and cfront both ! generate effectively the same code for: + @group + @example + A foo (); + A x (foo ()); // x is initialized by `foo ()', no ctor called here + A y = foo (); // call to `foo ()' heads to temporary, + // y is initialized from the temporary. + @end @example + @end @group + + Note the difference! With this flag, GNU C++ initializes `y' directly + from the call to `foo ()' without going through a temporary. + + @item -fall-virtual + When the -fall-virtual option is used, all member functions (except for + constructor functions and new/delete member operators) declared in the + same class with a ``method-call'' operator method have entries made for + them in the vtable for the given class. In effect, all of these methods + become ``implicitly virtual.'' + + This does @emph{not} mean that all calls to these methods will be made + through the vtable. There are some circumstances under which it is + obvious that a call to a given virtual function can be made directly, + and in these cases the calls still go direct. + + The effect of making all methods of a class with a declared + `operator->()()' implicitly virtual using -fall-virtual extends also to + all non-constructor methods of any class derived from such a class. + + @item -fsave-memoized + TBA + + @item -fmemoize-lookups + TBA + + @item -fSOS + TBA + @item -d@var{letters} Says to make debugging dumps at times specified by @var{letters}. *************** *** 2051,2073 **** @item The design of the C++ programming language did not take into account the ! usefulness of being able to specify that language using an LALR(1) grammar. ! As a result, in order to correctly parse it, one needs a look-ahead lexical ! analyzer (with infinite lookahead), and a recursive descent parser, guided ! by some good heuristics. This approach was not taken in GNU C++, because ! it is considered archaic, notoriously difficult to extend syntactically, ! and generally offensive. GNU C++ uses an LALR(1) grammar so that users can ! easily understand, and readily modify the compiler to suit their needs. ! Free software is useless if it becomes captive to an inaccessible or ! undesirable technology. However, in providing such a grammar, some ! syntactic forms were lost, most notably old-style C function declarations ! and occasionally function parameters which are declared longhand to be ! pointers to functions are not recognized properly. The first problem is ! solved by converting old-style C code to the ANSI-standard function ! prototype form. The second problem can always be solved by using a ! @code{typedef} for the pointer to function, and working from there. ! Another hack which can be used, if the parameter can legitimately be ! declared with a storage class (such as `register', or `auto') is to make ! that storage class explicit: @w{@code{int f (register int (*pf)(int,int)) ! @{...@}}}. @end itemize --- 2094,2119 ---- @item The design of the C++ programming language did not take into account the ! usefulness of being able to specify that language using an LALR(1) ! grammar. As a result, in order to correctly parse C++, one needs a ! look-ahead lexical analyzer (with infinite lookahead), and a recursive ! descent parser, guided by some good heuristics. This approach was not ! taken in GNU C++, because it is considered archaic, notoriously ! difficult to extend syntactically, and generally offensive. GNU C++ ! uses an LALR(1) grammar so that users can easily understand, and readily ! modify the compiler to suit their needs. Free software is useless if it ! becomes captive to an inaccessible or undesirable technology. ! ! Some syntactic forms were lost by utilizing an LALR(1) grammar, however. ! Most notably old-style C function declarations and function parameters ! and local variables that are declared longhand to be pointers to ! functions are not recognized properly (note that GNU C++ @emph{can} grok ! pointer-to-function casts, for example, (void (*)())0 is parsed ! correctly). The first problem is solved by converting old-style C code ! to the ANSI-standard function prototype form. The second problem can ! always be solved by using a @code{typedef} for the pointer to function, ! and working from there. Another hack which can be used, if the ! parameter can legitimately be declared with a storage class (such as ! `register', or `auto') is to make that storage class explicit: ! @w{@code{int f (register int (*pf)(int,int)) @{...@}}}. @end itemize *************** *** 3177,3181 **** @section Static Member Functions ! Could someone please write about this? @node Features, Bugs, Extensions, Top --- 3223,3313 ---- @section Static Member Functions ! Programmers familiar with Ada packages, Pascal units, or Modula-2 ! modules recognize the benefits of hiding functions within an ! encapsulation unit. GNU G++ further augments C++'s data abstraction ! capability with @dfn{static member functions}. Static member functions ! are subject to the same inlining and visibility features available with ! regular member functions. The major differences between static and ! non-static member functions are that: ! ! @itemize @bullet ! @item ! It is possible to call any visible static class member function ! regardless of whether a class instance exists. ! ! @item ! Static member functions may only access global variables and static ! class data elements. ! ! @item ! Static member functions may not be declared virtual. ! ! @end itemize ! ! Since static member functions exist independently of any class ! instances they lack an implicit `this' pointer. Therefore, they have ! no access to any @emph{non}-static class member functions or data. ! ! Here's an familiar Abstract Data Type application demonstrating static ! member functions: ! ! @group ! @example ! #include <stream.h> ! ! static const int MAX_STACK = 100; ! ! class Stack ! @{ ! private: ! static int stack[MAX_STACK]; ! static int top; ! ! public: ! static void push (int item) @{ stack[top++] = item; @} ! static int pop () @{ return stack[--top]; @} ! static int is_empty () @{ return top == 0; @} ! static int is_full () @{ return top >= MAX_STACK; @} ! @}; ! ! main () ! @{ ! for (srandom (time (0L)); !Stack::is_full (); Stack::push (random ())) ! ; ! ! while (!Stack::is_empty ()) ! cout << Stack::pop () << "\n"; ! @} ! @end example ! @end group ! ! This example is similar in spirit to how an Ada or Modula-2 programmer ! might design a bounded-stack abstraction. Note how there is only ! @strong{one} @var{stack} array for all instances of class Stack. ! Naturally, in this particular case it isn't very useful to declare ! multiple instances of class Stack, since the data would be shared ! between all class instances. ! ! Several benefits accrue from the use of static member functions: ! ! @itemize @bullet ! @item ! Static member functions have no access to the class instance pointer ! `this'. Thus, there is no need to pass an extra hidden parameter for ! each static member function call, thereby decreasing parameter passing ! overhead. ! ! @item ! Static member functions provide an encapsulation mechanism for ! manipulating static data objects. ! ! @end itemize ! ! Another important use of static member functions is writing type-safe ! handler routines. Doug Lea can explain how this works with the Fix{xx} ! classes in libg++. ! ! Note that it is possible to mix static and non-static member functions ! in the same class. @node Features, Bugs, Extensions, Top *************** *** 4133,4138 **** declarations. ! GNU C++ does not yet handle local class declarations. I.e., a local class ! declaration will permanently shadow a previous declaration. The @samp{-p} and @samp{-pg} options are not yet supported. The reason for --- 4265,4274 ---- declarations. ! GNU C++ does not yet handle local class declarations. A local class ! declaration permanently shadows a previous declaration. GNU C++ does ! however support local enum declarations. Access to class-level enum ! values are checked the same way that access is checked for class ! members and member functions, so it is possible to have private and ! protected enum values. The @samp{-p} and @samp{-pg} options are not yet supported. The reason for *************** *** 4158,4164 **** containing class objects with constructors and destructors. ! Work on supporting multiple inheritance is underway, but it is not yet ! fully operational in the current implementation. You help with testing ! and debugging multiple inheritance in GNU C++ would be very useful. @node Articles, Bibliography, BugList, Top --- 4294,4300 ---- containing class objects with constructors and destructors. ! Work on supporting multiple inheritance is underway, and appears almost ! fully operational in the current implementation. Your help with testing ! and debugging multiple inheritance in GNU C++ is very useful. @node Articles, Bibliography, BugList, Top diff -rc2H g++-1.35.0+/make-links.g++ src-g++/make-links.g++ *** g++-1.35.0+/make-links.g++ Fri May 19 14:22:47 1989 --- src-g++/make-links.g++ Sun May 21 14:24:11 1989 *************** *** 34,38 **** then DIR="../gcc" - else fi CDIR="../${DIR}/config" --- 34,37 ---- diff -rc2H g++-1.35.0+/newld.c src-g++/newld.c *** g++-1.35.0+/newld.c Fri May 19 14:22:49 1989 --- src-g++/newld.c Fri May 19 15:33:24 1989 *************** *** 2873,2877 **** #endif ! #ifdef sparc data_size = (data_size + sizeof(double) - 1) & ~(sizeof(double)-1); #endif --- 2873,2877 ---- #endif ! #if defined(sun) || defined(sparc) data_size = (data_size + sizeof(double) - 1) & ~(sizeof(double)-1); #endif *************** *** 2994,2997 **** --- 2994,3001 ---- } } + + #if defined(sun) || defined(sparc) + bss_size = (bss_size + sizeof(double) - 1) & ~(sizeof(double)-1); + #endif if (end_symbol) /* These are null if -r. */ diff -rc2H g++-1.35.0+/stor-layout.c src-g++/stor-layout.c *** g++-1.35.0+/stor-layout.c Fri May 19 14:22:51 1989 --- src-g++/stor-layout.c Tue May 23 07:40:21 1989 *************** *** 468,475 **** else { CLASSTYPE_THIS_BASECLASS (rec, i) = basetype ! = build_classtype_variant (basetype, ! convert_units (build_int (const_size), 1, BITS_PER_UNIT), ! 0); if (const_size != 0) --- 468,480 ---- else { + tree class_offset; + + if (const_size == 0) + class_offset = integer_zero_node; + else + class_offset = convert_units (build_int (const_size), 1, BITS_PER_UNIT); + CLASSTYPE_THIS_BASECLASS (rec, i) = basetype ! = build_classtype_variant (basetype, class_offset, 0); if (const_size != 0) *************** *** 1067,1070 **** --- 1072,1094 ---- if (TYPE_SIZE (type) != 0 && ! TREE_LITERAL (TYPE_SIZE (type))) TYPE_SIZE (type) = variable_size (TYPE_SIZE (type)); + + if (TYPE_NEXT_VARIANT (type) + || type != TYPE_MAIN_VARIANT (type)) + { + /* Lay out this type for all variants as well. */ + tree size = TYPE_SIZE (type); + int size_unit = TYPE_SIZE_UNIT (type); + int align = TYPE_ALIGN (type); + enum machine_mode mode = TYPE_MODE (type); + type = TYPE_MAIN_VARIANT (type); + while (type) + { + TYPE_SIZE (type) = size; + TYPE_SIZE_UNIT (type) = size_unit; + TYPE_ALIGN (type) = align; + TYPE_MODE (type) = mode; + type = TYPE_NEXT_VARIANT (type); + } + } if (temporary) diff -rc2H g++-1.35.0+/toplev.c src-g++/toplev.c *** g++-1.35.0+/toplev.c Fri May 19 14:22:52 1989 --- src-g++/toplev.c Mon May 22 21:03:37 1989 *************** *** 285,288 **** --- 285,292 ---- int flag_delayed_branch; + /* Nonzero means schedule instructions within basic blocks. */ + + int flag_schedule_insns = 0; + /* Name for output file of assembly code, specified with -o. */ *************** *** 318,322 **** {"caller-saves", &flag_caller_saves, 1}, {"pcc-struct-return", &flag_pcc_struct_return, 1}, ! {"delayed-branch", &flag_delayed_branch, 1} }; --- 322,327 ---- {"caller-saves", &flag_caller_saves, 1}, {"pcc-struct-return", &flag_pcc_struct_return, 1}, ! {"delayed-branch", &flag_delayed_branch, 1}, ! {"schedule-insns", &flag_schedule_insns, 1} }; diff -rc2H g++-1.35.0+/tree.c src-g++/tree.c *** g++-1.35.0+/tree.c Fri May 19 14:22:53 1989 --- src-g++/tree.c Fri May 19 15:30:37 1989 *************** *** 1104,1108 **** case CALL_EXPR: ! if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) return 1; break; --- 1104,1110 ---- case CALL_EXPR: ! if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE ! /* unary_complex_lvalue knows how to deal with this case. */ ! || TREE_ADDRESSABLE (TREE_TYPE (ref))) return 1; break; diff -rc2H g++-1.35.0+/version.c src-g++/version.c *** g++-1.35.0+/version.c Fri May 19 14:22:54 1989 --- src-g++/version.c Tue May 23 07:14:12 1989 *************** *** 1,1 **** ! char *version_string = "1.35.0+"; --- 1,1 ---- ! char *version_string = "1.35.1-"; yahi% Michael