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