79th Cygnus<->FSF merge

From-SVN: r11082
This commit is contained in:
Mike Stump 1996-01-22 19:49:02 +00:00
parent f589b741f9
commit 455376771f
11 changed files with 236 additions and 115 deletions

View File

@ -1,3 +1,60 @@
Fri Jan 19 18:03:14 1996 Mike Stump <mrs@cygnus.com>
* typeck.c (build_component_ref): Handle getting vbase pointers
out of complex multiple inheritance better.
Fri Jan 19 16:27:40 1996 Mike Stump <mrs@cygnus.com>
* typeck.c (build_object_ref): Make sure we use the real type, not
any reference type.
Fri Jan 19 16:01:47 1996 Mike Stump <mrs@cygnus.com>
* tree.c (build_exception_variant): Don't create new types if we
don't have to, also build new types on the right obstack.
Fri Jan 19 14:09:44 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (store_bindings): Split out from push_to_top_level.
(push_to_top_level): Call it for b->type_shadowed on class binding
levels.
Fri Jan 19 13:53:14 1996 Mike Stump <mrs@cygnus.com>
* search.c (expand_upcast_fixups): Fix so that offsets stored in
vbase_offsets are always right. Fixes a problem where virtual base
upcasting and downcasting could be wrong during conversions on this
during virtual function dispatch at ctor/dtor time when dynamic
vtable fixups for deltas are needed. This only sounds easier than
it is. :-)
(fixup_virtual_upcast_offsets): Change to reflect new calling
convention for expand_upcast_fixups.
Fri Jan 19 12:23:08 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* decl2.c (grokbitfield): Strip the NOPs from WIDTH before we
check that it's usable as the bitfield width.
Wed Jan 17 21:22:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* decl2.c (grokfield): Call cplus_decl_attributes with the attrlist.
Pass a null tree to grokdeclarator for its ATTRLIST arg, since it's
only ever used for functions in it.
Wed Jan 17 12:10:38 1996 Jason Merrill <jason@yorick.cygnus.com>
* parse.y (qualified_type_name): Use the TYPE_DECL, not the type.
(nested_type): Ditto.
(nested_name_specifier): Use lastiddecl.
* decl.c (grokdeclarator): Adjust accordingly.
* init.c (expand_member_init): Ditto.
* parse.y (base_class): Ditto.
* typeck2.c (build_functional_cast): Ditto.
* typeck2.c (build_functional_cast): Fill in name after we've
checked for non-aggr type.
Wed Jan 17 10:18:01 1996 Mike Stump <mrs@cygnus.com>
* decl2.c (warn_pointer_arith): Default to on.
@ -53,9 +110,6 @@ Mon Jan 15 16:19:32 1996 Jason Merrill <jason@yorick.cygnus.com>
* init.c (sort_base_init): Ditto.
(expand_member_init): Ditto.
* init.c (is_aggr_type): New function, like is_aggr_typedef.
* class.c (pushclass): If !modify and
CLASSTYPE_LOCAL_TYPEDECLS (type)), do set up IDENTIFIER_TYPE_VALUE
for inherited types.
Mon Jan 15 08:45:01 1996 Jeffrey A Law (law@cygnus.com)

View File

@ -4416,7 +4416,7 @@ pushclass (type, modify)
else if (type != previous_class_type || current_class_depth > 1)
{
build_mi_matrix (type);
push_class_decls (type, !modify);
push_class_decls (type);
free_mi_matrix ();
if (current_class_depth == 1)
previous_class_type = type;
@ -4453,12 +4453,6 @@ pushclass (type, modify)
current_function_decl = this_fndecl;
}
else if (CLASSTYPE_LOCAL_TYPEDECLS (type))
{
build_mi_matrix (type);
push_class_decls (type, !modify);
free_mi_matrix ();
}
if (flag_cadillac)
cadillac_push_class (type);

View File

@ -2332,7 +2332,7 @@ extern void build_mi_virtuals PROTO((int, int));
extern void add_mi_virtuals PROTO((int, tree));
extern void report_ambiguous_mi_virtuals PROTO((int, tree));
extern void note_debug_info_needed PROTO((tree));
extern void push_class_decls PROTO((tree, int));
extern void push_class_decls PROTO((tree));
extern void pop_class_decls PROTO((tree));
extern void unuse_fields PROTO((tree));
extern void unmark_finished_struct PROTO((tree));

View File

@ -1832,6 +1832,48 @@ struct saved_scope {
static struct saved_scope *current_saved_scope;
extern tree prev_class_type;
tree
store_bindings (names, old_bindings)
tree names, old_bindings;
{
tree t;
for (t = names; t; t = TREE_CHAIN (t))
{
tree binding, t1, id;
if (TREE_CODE (t) == TREE_LIST)
id = TREE_PURPOSE (t);
else
id = DECL_NAME (t);
if (!id
|| (!IDENTIFIER_LOCAL_VALUE (id)
&& !IDENTIFIER_CLASS_VALUE (id)))
continue;
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
if (TREE_VEC_ELT (t1, 0) == id)
goto skip_it;
binding = make_tree_vec (4);
if (id)
{
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id;
TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id);
TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
TREE_CHAIN (binding) = old_bindings;
old_bindings = binding;
skip_it:
;
}
return old_bindings;
}
void
push_to_top_level ()
{
@ -1849,37 +1891,13 @@ push_to_top_level ()
if (b == global_binding_level)
continue;
for (t = b->names; t; t = TREE_CHAIN (t))
{
tree binding, t1, t2 = t;
tree id = DECL_ASSEMBLER_NAME (t2);
if (!id
|| (!IDENTIFIER_LOCAL_VALUE (id)
&& !IDENTIFIER_CLASS_VALUE (id)))
continue;
old_bindings = store_bindings (b->names, old_bindings);
/* We also need to check type_shadowed to save class-level type
bindings, since pushclass doesn't fill in b->names. */
if (b->parm_flag == 2)
old_bindings = store_bindings (b->type_shadowed, old_bindings);
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
if (TREE_VEC_ELT (t1, 0) == id)
goto skip_it;
binding = make_tree_vec (4);
if (id)
{
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id;
TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id);
TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
TREE_CHAIN (binding) = old_bindings;
old_bindings = binding;
skip_it:
;
}
/* Unwind type-value slots back to top level. */
for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
@ -7783,7 +7801,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
innermost_code = TREE_CODE (decl);
if (decl_context == FIELD && ctype == NULL_TREE)
ctype = current_class_type;
if (ctype && TREE_OPERAND (decl, 0) == ctype)
if (ctype
&& (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
&& ((DECL_NAME (TREE_OPERAND (decl, 0))
== constructor_name_full (ctype))
|| (DECL_NAME (TREE_OPERAND (decl, 0))
== constructor_name (ctype)))))
TREE_OPERAND (decl, 0) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 0);
decl = *next;
@ -7886,23 +7909,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
next = 0;
break;
case TYPE_DECL:
/* Parse error puts this typespec where
a declarator should go. */
cp_error ("`%T' specified as declarator-id", DECL_NAME (decl));
if (TREE_TYPE (decl) == current_class_type)
cp_error (" perhaps you want `%T' for a constructor",
current_class_name);
dname = DECL_NAME (decl);
name = IDENTIFIER_POINTER (dname);
/* Avoid giving two errors for this. */
IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
declspecs);
*next = dname;
next = 0;
break;
default:
if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
{
/* Parse error puts this typespec where
a declarator should go. */
error ("typename specified as declarator-id");
if (current_class_type)
cp_error (" perhaps you want `%T' for a constructor",
current_class_name);
dname = TYPE_IDENTIFIER (decl);
name = dname ? IDENTIFIER_POINTER (dname) : "<nameless>";
declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
declspecs);
*next = dname;
next = 0;
break;
}
cp_compiler_error ("`%D' as declarator", decl);
return 0; /* We used to do a 155 abort here. */
}
@ -8031,6 +8057,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
}
}
/* C++ aggregate types. */
else if (TREE_CODE (id) == TYPE_DECL)
{
if (type)
cp_error ("multiple declarations `%T' and `%T'", type,
TREE_TYPE (id));
else
type = TREE_TYPE (id);
goto found;
}
if (type)
error ("two or more data types in declaration of `%s'", name);
else if (TREE_CODE (id) == IDENTIFIER_NODE)

View File

@ -1362,7 +1362,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0,
raises, attrlist);
raises, NULL_TREE);
if (! value)
return value; /* friend or constructor went bad. */
@ -1476,6 +1476,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
/* The corresponding pop_obstacks is in cp_finish_decl. */
push_obstacks_nochange ();
if (attrlist)
cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
TREE_VALUE (attrlist));
if (TREE_CODE (value) == VAR_DECL)
{
/* We cannot call pushdecl here, because that would
@ -1616,6 +1620,9 @@ grokbitfield (declarator, declspecs, width)
if (width != error_mark_node)
{
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (width);
/* detect invalid field size. */
if (TREE_CODE (width) == CONST_DECL)
width = DECL_INITIAL (width);

View File

@ -930,10 +930,10 @@ expand_member_init (exp, name, init)
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
if (TREE_CODE (name) == TYPE_DECL)
{
basetype = name;
name = TYPE_IDENTIFIER (name);
basetype = TREE_TYPE (name);
name = DECL_NAME (name);
}
if (name == NULL_TREE && IS_AGGR_TYPE (type))

View File

@ -2349,7 +2349,7 @@ base_class_list:
base_class:
base_class.1
{
tree type = $1;
tree type = TREE_TYPE ($1);
if (! is_aggr_type (type, 1))
$$ = NULL_TREE;
else if (current_aggr == signature_type_node
@ -2362,7 +2362,7 @@ base_class:
{
sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER ($$));
$$ = build_tree_list (access_public_node, $$);
$$ = build_tree_list (access_public_node, type);
}
else if (type && IS_SIGNATURE (type))
{
@ -2370,11 +2370,11 @@ base_class:
$$ = NULL_TREE;
}
else
$$ = build_tree_list (access_default_node, $$);
$$ = build_tree_list (access_default_node, type);
}
| base_class_access_list see_typename base_class.1
{
tree type = $3;
tree type = TREE_TYPE ($3);
if (current_aggr == signature_type_node)
error ("access and source specifiers not allowed in signature");
if (! IS_AGGR_TYPE (type))
@ -2389,7 +2389,7 @@ base_class:
{
sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER ($$));
$$ = build_tree_list (access_public_node, $3);
$$ = build_tree_list (access_public_node, type);
}
else if (type && IS_SIGNATURE (type))
{
@ -2397,7 +2397,7 @@ base_class:
$$ = NULL_TREE;
}
else
$$ = build_tree_list ($$, $3);
$$ = build_tree_list ($$, type);
}
;
@ -2857,20 +2857,25 @@ after_type_declarator:
qualified_type_name:
type_name %prec EMPTY
{
$$ = TREE_TYPE ($1);
$$ = identifier_typedecl_value ($1);
/* Remember that this name has been used in the class
definition, as per [class.scope0] */
if (current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& ! IDENTIFIER_TEMPLATE ($1)
&& ! IDENTIFIER_CLASS_VALUE ($1))
pushdecl_class_level (lookup_name ($1, -2));
{
/* Be sure to get an inherited typedef. */
$$ = lookup_name ($1, 1);
pushdecl_class_level ($$);
}
}
| nested_type
;
nested_type:
nested_name_specifier type_name %prec EMPTY
{ $$ = TREE_TYPE ($2); }
{ $$ = identifier_typedecl_value ($2); }
;
direct_after_type_declarator:
@ -2984,7 +2989,17 @@ nested_name_specifier:
inline here?!? (jason) */
nested_name_specifier_1:
TYPENAME SCOPE
{ got_scope = $$ = TREE_TYPE ($1); }
{
$$ = lastiddecl;
/* Remember that this name has been used in the class
definition, as per [class.scope0] */
if (current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& ! TREE_MANGLED ($1)
&& ! IDENTIFIER_CLASS_VALUE ($1))
pushdecl_class_level ($$);
got_scope = $$ = TREE_TYPE ($$);
}
| NSNAME SCOPE
{ got_scope = $$ = $1; }
| template_type SCOPE

View File

@ -2663,7 +2663,10 @@ virtual_context (fndecl, t, vbase)
they may upcast into a direct base, or
they may upcast into a different vbase.
We only need to do fixups in case 2 and 3.
We only need to do fixups in case 2 and 3. In case 2, we add in
the virtual base offset to effect an upcast, in case 3, we add in
the virtual base offset to effect an upcast, then subtract out the
offset for the other virtual base, to effect a downcast into it.
This routine mirrors fixup_vtable_deltas in functionality, though
this one is runtime based, and the other is compile time based.
@ -2671,10 +2674,14 @@ virtual_context (fndecl, t, vbase)
done at runtime.
VBASE_OFFSETS is an association list of virtual bases that contains
offset information, so the offsets are only calculated once. */
offset information for the virtual bases, so the offsets are only
calculated once. The offsets are computed by where we think the
vbase should be (as noted by the CLASSTYPE_SEARCH_SLOT) minus where
the vbase really is. */
static void
expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
tree binfo, addr, orig_addr, vbase, t, *vbase_offsets;
expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
vbase_offsets)
tree binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets;
{
tree virtuals = BINFO_VIRTUALS (binfo);
tree vc;
@ -2685,7 +2692,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
if (! delta)
{
delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbase));
delta = build (MINUS_EXPR, ptrdiff_type_node, delta, addr);
delta = build (MINUS_EXPR, ptrdiff_type_node, delta, vbase_addr);
delta = save_expr (delta);
delta = tree_cons (vbase, delta, *vbase_offsets);
*vbase_offsets = delta;
@ -2739,26 +2746,32 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
naref = build_array_ref (nvtbl, idx);
old_delta = build_component_ref (aref, delta_identifier, 0, 0);
new_delta = build_component_ref (naref, delta_identifier, 0, 0);
/* This is a upcast, so we have to add the offset for the
virtual base. */
old_delta = build_binary_op (PLUS_EXPR, old_delta,
TREE_VALUE (delta), 0);
if (vc)
{
/* If this is set, we need to add in delta adjustments for
the other virtual base. */
/* If this is set, we need to subtract out the delta
adjustments for the other virtual base that we
downcast into. */
tree vc_delta = purpose_member (vc, *vbase_offsets);
if (! vc_delta)
{
tree vc_addr = convert_pointer_to_real (vc, orig_addr);
vc_delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc));
vc_delta = build (MINUS_EXPR, ptrdiff_type_node,
vc_addr, vc_delta);
vc_delta, vc_addr);
vc_delta = save_expr (vc_delta);
*vbase_offsets = tree_cons (vc, vc_delta, *vbase_offsets);
}
else
vc_delta = TREE_VALUE (vc_delta);
old_delta = build_binary_op (PLUS_EXPR, old_delta, vc_delta, 0);
/* This is a downcast, so we have to subtract the offset
for the virtual base. */
old_delta = build_binary_op (MINUS_EXPR, old_delta, vc_delta, 0);
}
TREE_READONLY (new_delta) = 0;
@ -2800,8 +2813,9 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
{
addr = convert_pointer_to_real (binfo, addr);
expand_upcast_fixups (real_binfo, addr, orig_addr, vbase, type, vbase_offsets);
tree new_addr = convert_pointer_to_real (binfo, addr);
expand_upcast_fixups (real_binfo, new_addr, orig_addr, vbase, addr,
type, vbase_offsets);
}
}
@ -3334,14 +3348,10 @@ dfs_compress_decls (binfo)
lattice. Where ambiguities result, we mark them
with `error_mark_node' so that if they are encountered
without explicit qualification, we can emit an error
message.
ONLY_TYPES is set when defining TYPE so that inherited types are visible
in the derived class. */
message. */
void
push_class_decls (type, only_types)
push_class_decls (type)
tree type;
int only_types;
{
tree id;
struct obstack *ambient_obstack = current_obstack;
@ -3396,12 +3406,7 @@ push_class_decls (type, only_types)
/* Install the original class value in order to make
pushdecl_class_level work correctly. */
IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes);
if (only_types)
{
if (TREE_CODE (new) == TYPE_DECL)
set_identifier_type_value (id, TREE_TYPE (new));
}
else if (TREE_CODE (new) == TREE_LIST)
if (TREE_CODE (new) == TREE_LIST)
push_class_level_binding (id, new);
else
pushdecl_class_level (new);

View File

@ -1579,7 +1579,7 @@ build_exception_variant (type, raises)
int constp = TYPE_READONLY (type);
int volatilep = TYPE_VOLATILE (type);
for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
for (; v; v = TYPE_NEXT_VARIANT (v))
{
if (TYPE_READONLY (v) != constp
|| TYPE_VOLATILE (v) != volatilep)
@ -1595,9 +1595,8 @@ build_exception_variant (type, raises)
}
/* Need to build a new variant. */
v = copy_node (type);
TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
TYPE_NEXT_VARIANT (type) = v;
v = build_type_copy (type);
if (raises && ! TREE_PERMANENT (raises))
{
push_obstacks_nochange ();

View File

@ -1539,7 +1539,7 @@ build_object_ref (datum, basetype, field)
}
else if (is_aggr_type (basetype, 1))
{
tree binfo = binfo_or_else (basetype, TREE_TYPE (datum));
tree binfo = binfo_or_else (basetype, dtype);
if (binfo)
return build_component_ref (build_scoped_ref (datum, basetype),
field, binfo, 1);
@ -1825,7 +1825,16 @@ build_component_ref (datum, component, basetype_path, protect)
error ("invalid reference to NULL ptr, use ptr-to-member instead");
return error_mark_node;
}
addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
if (VBASE_NAME_P (DECL_NAME (field)))
{
/* It doesn't matter which vbase pointer we grab, just
find one of them. */
tree binfo = get_binfo (DECL_FIELD_CONTEXT (field),
TREE_TYPE (TREE_TYPE (addr)), 0);
addr = convert_pointer_to_real (binfo, addr);
}
else
addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 311);
}
@ -5831,7 +5840,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (build_default_binary_type_conversion (modifycode, &lhs_tmp, &rhs_tmp))
{
lhs = stabilize_reference (lhs_tmp);
/* Forget is was ever anything else. */
/* Forget it was ever anything else. */
olhstype = lhstype = TREE_TYPE (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
}

View File

@ -1440,6 +1440,8 @@ build_functional_cast (exp, parms)
type = TREE_TYPE (type);
}
}
else if (TREE_CODE (exp) == TYPE_DECL)
type = TREE_TYPE (exp);
else
type = exp;
@ -1449,20 +1451,6 @@ build_functional_cast (exp, parms)
return error_mark_node;
}
/* Prepare to evaluate as a call to a constructor. If this expression
is actually used, for example,
return X (arg1, arg2, ...);
then the slot being initialized will be filled in. */
if (name == NULL_TREE)
{
name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NESTED_TYPENAME (name);
}
if (! IS_AGGR_TYPE (type))
{
/* this must build a C cast */
@ -1478,6 +1466,20 @@ build_functional_cast (exp, parms)
return build_c_cast (type, parms, 1);
}
/* Prepare to evaluate as a call to a constructor. If this expression
is actually used, for example,
return X (arg1, arg2, ...);
then the slot being initialized will be filled in. */
if (name == NULL_TREE)
{
name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NESTED_TYPENAME (name);
}
if (TYPE_SIZE (type) == NULL_TREE)
{
cp_error ("type `%T' is not yet defined", type);