Commit 45537677 by Mike Stump

79th Cygnus<->FSF merge

From-SVN: r11082
parent f589b741
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> Wed Jan 17 10:18:01 1996 Mike Stump <mrs@cygnus.com>
* decl2.c (warn_pointer_arith): Default to on. * 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> ...@@ -53,9 +110,6 @@ Mon Jan 15 16:19:32 1996 Jason Merrill <jason@yorick.cygnus.com>
* init.c (sort_base_init): Ditto. * init.c (sort_base_init): Ditto.
(expand_member_init): Ditto. (expand_member_init): Ditto.
* init.c (is_aggr_type): New function, like is_aggr_typedef. * 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) Mon Jan 15 08:45:01 1996 Jeffrey A Law (law@cygnus.com)
......
...@@ -4416,7 +4416,7 @@ pushclass (type, modify) ...@@ -4416,7 +4416,7 @@ pushclass (type, modify)
else if (type != previous_class_type || current_class_depth > 1) else if (type != previous_class_type || current_class_depth > 1)
{ {
build_mi_matrix (type); build_mi_matrix (type);
push_class_decls (type, !modify); push_class_decls (type);
free_mi_matrix (); free_mi_matrix ();
if (current_class_depth == 1) if (current_class_depth == 1)
previous_class_type = type; previous_class_type = type;
...@@ -4453,12 +4453,6 @@ pushclass (type, modify) ...@@ -4453,12 +4453,6 @@ pushclass (type, modify)
current_function_decl = this_fndecl; 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) if (flag_cadillac)
cadillac_push_class (type); cadillac_push_class (type);
......
...@@ -2332,7 +2332,7 @@ extern void build_mi_virtuals PROTO((int, int)); ...@@ -2332,7 +2332,7 @@ extern void build_mi_virtuals PROTO((int, int));
extern void add_mi_virtuals PROTO((int, tree)); extern void add_mi_virtuals PROTO((int, tree));
extern void report_ambiguous_mi_virtuals PROTO((int, tree)); extern void report_ambiguous_mi_virtuals PROTO((int, tree));
extern void note_debug_info_needed PROTO((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 pop_class_decls PROTO((tree));
extern void unuse_fields PROTO((tree)); extern void unuse_fields PROTO((tree));
extern void unmark_finished_struct PROTO((tree)); extern void unmark_finished_struct PROTO((tree));
......
...@@ -1832,6 +1832,48 @@ struct saved_scope { ...@@ -1832,6 +1832,48 @@ struct saved_scope {
static struct saved_scope *current_saved_scope; static struct saved_scope *current_saved_scope;
extern tree prev_class_type; 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 void
push_to_top_level () push_to_top_level ()
{ {
...@@ -1849,37 +1891,13 @@ push_to_top_level () ...@@ -1849,37 +1891,13 @@ push_to_top_level ()
if (b == global_binding_level) if (b == global_binding_level)
continue; continue;
for (t = b->names; t; t = TREE_CHAIN (t))
{
tree binding, t1, t2 = t;
tree id = DECL_ASSEMBLER_NAME (t2);
if (!id old_bindings = store_bindings (b->names, old_bindings);
|| (!IDENTIFIER_LOCAL_VALUE (id) /* We also need to check type_shadowed to save class-level type
&& !IDENTIFIER_CLASS_VALUE (id))) bindings, since pushclass doesn't fill in b->names. */
continue; 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. */ /* Unwind type-value slots back to top level. */
for (t = b->type_shadowed; t; t = TREE_CHAIN (t)) for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t)); SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
...@@ -7783,7 +7801,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli ...@@ -7783,7 +7801,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
innermost_code = TREE_CODE (decl); innermost_code = TREE_CODE (decl);
if (decl_context == FIELD && ctype == NULL_TREE) if (decl_context == FIELD && ctype == NULL_TREE)
ctype = current_class_type; 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); TREE_OPERAND (decl, 0) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 0); next = &TREE_OPERAND (decl, 0);
decl = *next; decl = *next;
...@@ -7886,23 +7909,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli ...@@ -7886,23 +7909,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
next = 0; next = 0;
break; 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: 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); cp_compiler_error ("`%D' as declarator", decl);
return 0; /* We used to do a 155 abort here. */ return 0; /* We used to do a 155 abort here. */
} }
...@@ -8031,6 +8057,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli ...@@ -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) if (type)
error ("two or more data types in declaration of `%s'", name); error ("two or more data types in declaration of `%s'", name);
else if (TREE_CODE (id) == IDENTIFIER_NODE) else if (TREE_CODE (id) == IDENTIFIER_NODE)
......
...@@ -1362,7 +1362,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) ...@@ -1362,7 +1362,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
init = NULL_TREE; init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, value = grokdeclarator (declarator, declspecs, FIELD, init != 0,
raises, attrlist); raises, NULL_TREE);
if (! value) if (! value)
return value; /* friend or constructor went bad. */ return value; /* friend or constructor went bad. */
...@@ -1476,6 +1476,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) ...@@ -1476,6 +1476,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
/* The corresponding pop_obstacks is in cp_finish_decl. */ /* The corresponding pop_obstacks is in cp_finish_decl. */
push_obstacks_nochange (); push_obstacks_nochange ();
if (attrlist)
cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
TREE_VALUE (attrlist));
if (TREE_CODE (value) == VAR_DECL) if (TREE_CODE (value) == VAR_DECL)
{ {
/* We cannot call pushdecl here, because that would /* We cannot call pushdecl here, because that would
...@@ -1616,6 +1620,9 @@ grokbitfield (declarator, declspecs, width) ...@@ -1616,6 +1620,9 @@ grokbitfield (declarator, declspecs, width)
if (width != error_mark_node) if (width != error_mark_node)
{ {
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (width);
/* detect invalid field size. */ /* detect invalid field size. */
if (TREE_CODE (width) == CONST_DECL) if (TREE_CODE (width) == CONST_DECL)
width = DECL_INITIAL (width); width = DECL_INITIAL (width);
......
...@@ -930,10 +930,10 @@ expand_member_init (exp, name, init) ...@@ -930,10 +930,10 @@ expand_member_init (exp, name, init)
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') if (TREE_CODE (name) == TYPE_DECL)
{ {
basetype = name; basetype = TREE_TYPE (name);
name = TYPE_IDENTIFIER (name); name = DECL_NAME (name);
} }
if (name == NULL_TREE && IS_AGGR_TYPE (type)) if (name == NULL_TREE && IS_AGGR_TYPE (type))
......
...@@ -2349,7 +2349,7 @@ base_class_list: ...@@ -2349,7 +2349,7 @@ base_class_list:
base_class: base_class:
base_class.1 base_class.1
{ {
tree type = $1; tree type = TREE_TYPE ($1);
if (! is_aggr_type (type, 1)) if (! is_aggr_type (type, 1))
$$ = NULL_TREE; $$ = NULL_TREE;
else if (current_aggr == signature_type_node else if (current_aggr == signature_type_node
...@@ -2362,7 +2362,7 @@ base_class: ...@@ -2362,7 +2362,7 @@ base_class:
{ {
sorry ("signature inheritance, base type `%s' ignored", sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER ($$)); IDENTIFIER_POINTER ($$));
$$ = build_tree_list (access_public_node, $$); $$ = build_tree_list (access_public_node, type);
} }
else if (type && IS_SIGNATURE (type)) else if (type && IS_SIGNATURE (type))
{ {
...@@ -2370,11 +2370,11 @@ base_class: ...@@ -2370,11 +2370,11 @@ base_class:
$$ = NULL_TREE; $$ = NULL_TREE;
} }
else else
$$ = build_tree_list (access_default_node, $$); $$ = build_tree_list (access_default_node, type);
} }
| base_class_access_list see_typename base_class.1 | base_class_access_list see_typename base_class.1
{ {
tree type = $3; tree type = TREE_TYPE ($3);
if (current_aggr == signature_type_node) if (current_aggr == signature_type_node)
error ("access and source specifiers not allowed in signature"); error ("access and source specifiers not allowed in signature");
if (! IS_AGGR_TYPE (type)) if (! IS_AGGR_TYPE (type))
...@@ -2389,7 +2389,7 @@ base_class: ...@@ -2389,7 +2389,7 @@ base_class:
{ {
sorry ("signature inheritance, base type `%s' ignored", sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER ($$)); IDENTIFIER_POINTER ($$));
$$ = build_tree_list (access_public_node, $3); $$ = build_tree_list (access_public_node, type);
} }
else if (type && IS_SIGNATURE (type)) else if (type && IS_SIGNATURE (type))
{ {
...@@ -2397,7 +2397,7 @@ base_class: ...@@ -2397,7 +2397,7 @@ base_class:
$$ = NULL_TREE; $$ = NULL_TREE;
} }
else else
$$ = build_tree_list ($$, $3); $$ = build_tree_list ($$, type);
} }
; ;
...@@ -2857,20 +2857,25 @@ after_type_declarator: ...@@ -2857,20 +2857,25 @@ after_type_declarator:
qualified_type_name: qualified_type_name:
type_name %prec EMPTY type_name %prec EMPTY
{ {
$$ = TREE_TYPE ($1); $$ = identifier_typedecl_value ($1);
/* Remember that this name has been used in the class /* Remember that this name has been used in the class
definition, as per [class.scope0] */ definition, as per [class.scope0] */
if (current_class_type if (current_class_type
&& TYPE_BEING_DEFINED (current_class_type) && TYPE_BEING_DEFINED (current_class_type)
&& ! IDENTIFIER_TEMPLATE ($1)
&& ! IDENTIFIER_CLASS_VALUE ($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_type: nested_type:
nested_name_specifier type_name %prec EMPTY nested_name_specifier type_name %prec EMPTY
{ $$ = TREE_TYPE ($2); } { $$ = identifier_typedecl_value ($2); }
; ;
direct_after_type_declarator: direct_after_type_declarator:
...@@ -2984,7 +2989,17 @@ nested_name_specifier: ...@@ -2984,7 +2989,17 @@ nested_name_specifier:
inline here?!? (jason) */ inline here?!? (jason) */
nested_name_specifier_1: nested_name_specifier_1:
TYPENAME SCOPE 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 | NSNAME SCOPE
{ got_scope = $$ = $1; } { got_scope = $$ = $1; }
| template_type SCOPE | template_type SCOPE
......
...@@ -2663,7 +2663,10 @@ virtual_context (fndecl, t, vbase) ...@@ -2663,7 +2663,10 @@ virtual_context (fndecl, t, vbase)
they may upcast into a direct base, or they may upcast into a direct base, or
they may upcast into a different vbase. 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 routine mirrors fixup_vtable_deltas in functionality, though
this one is runtime based, and the other is compile time based. this one is runtime based, and the other is compile time based.
...@@ -2671,10 +2674,14 @@ virtual_context (fndecl, t, vbase) ...@@ -2671,10 +2674,14 @@ virtual_context (fndecl, t, vbase)
done at runtime. done at runtime.
VBASE_OFFSETS is an association list of virtual bases that contains 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 static void
expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets) expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
tree binfo, addr, orig_addr, vbase, t, *vbase_offsets; vbase_offsets)
tree binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets;
{ {
tree virtuals = BINFO_VIRTUALS (binfo); tree virtuals = BINFO_VIRTUALS (binfo);
tree vc; tree vc;
...@@ -2685,7 +2692,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets) ...@@ -2685,7 +2692,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
if (! delta) if (! delta)
{ {
delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbase)); 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 = save_expr (delta);
delta = tree_cons (vbase, delta, *vbase_offsets); delta = tree_cons (vbase, delta, *vbase_offsets);
*vbase_offsets = delta; *vbase_offsets = delta;
...@@ -2739,26 +2746,32 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets) ...@@ -2739,26 +2746,32 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
naref = build_array_ref (nvtbl, idx); naref = build_array_ref (nvtbl, idx);
old_delta = build_component_ref (aref, delta_identifier, 0, 0); old_delta = build_component_ref (aref, delta_identifier, 0, 0);
new_delta = build_component_ref (naref, 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, old_delta = build_binary_op (PLUS_EXPR, old_delta,
TREE_VALUE (delta), 0); TREE_VALUE (delta), 0);
if (vc) if (vc)
{ {
/* If this is set, we need to add in delta adjustments for /* If this is set, we need to subtract out the delta
the other virtual base. */ adjustments for the other virtual base that we
downcast into. */
tree vc_delta = purpose_member (vc, *vbase_offsets); tree vc_delta = purpose_member (vc, *vbase_offsets);
if (! vc_delta) if (! vc_delta)
{ {
tree vc_addr = convert_pointer_to_real (vc, orig_addr); tree vc_addr = convert_pointer_to_real (vc, orig_addr);
vc_delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc)); vc_delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc));
vc_delta = build (MINUS_EXPR, ptrdiff_type_node, vc_delta = build (MINUS_EXPR, ptrdiff_type_node,
vc_addr, vc_delta); vc_delta, vc_addr);
vc_delta = save_expr (vc_delta); vc_delta = save_expr (vc_delta);
*vbase_offsets = tree_cons (vc, vc_delta, *vbase_offsets); *vbase_offsets = tree_cons (vc, vc_delta, *vbase_offsets);
} }
else else
vc_delta = TREE_VALUE (vc_delta); 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; TREE_READONLY (new_delta) = 0;
...@@ -2800,8 +2813,9 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori ...@@ -2800,8 +2813,9 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
/* Should we use something besides CLASSTYPE_VFIELDS? */ /* Should we use something besides CLASSTYPE_VFIELDS? */
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo))) if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
{ {
addr = convert_pointer_to_real (binfo, addr); tree new_addr = convert_pointer_to_real (binfo, addr);
expand_upcast_fixups (real_binfo, addr, orig_addr, vbase, type, vbase_offsets); expand_upcast_fixups (real_binfo, new_addr, orig_addr, vbase, addr,
type, vbase_offsets);
} }
} }
...@@ -3334,14 +3348,10 @@ dfs_compress_decls (binfo) ...@@ -3334,14 +3348,10 @@ dfs_compress_decls (binfo)
lattice. Where ambiguities result, we mark them lattice. Where ambiguities result, we mark them
with `error_mark_node' so that if they are encountered with `error_mark_node' so that if they are encountered
without explicit qualification, we can emit an error without explicit qualification, we can emit an error
message. message. */
ONLY_TYPES is set when defining TYPE so that inherited types are visible
in the derived class. */
void void
push_class_decls (type, only_types) push_class_decls (type)
tree type; tree type;
int only_types;
{ {
tree id; tree id;
struct obstack *ambient_obstack = current_obstack; struct obstack *ambient_obstack = current_obstack;
...@@ -3396,12 +3406,7 @@ push_class_decls (type, only_types) ...@@ -3396,12 +3406,7 @@ push_class_decls (type, only_types)
/* Install the original class value in order to make /* Install the original class value in order to make
pushdecl_class_level work correctly. */ pushdecl_class_level work correctly. */
IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes); IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes);
if (only_types) if (TREE_CODE (new) == TREE_LIST)
{
if (TREE_CODE (new) == TYPE_DECL)
set_identifier_type_value (id, TREE_TYPE (new));
}
else if (TREE_CODE (new) == TREE_LIST)
push_class_level_binding (id, new); push_class_level_binding (id, new);
else else
pushdecl_class_level (new); pushdecl_class_level (new);
......
...@@ -1579,7 +1579,7 @@ build_exception_variant (type, raises) ...@@ -1579,7 +1579,7 @@ build_exception_variant (type, raises)
int constp = TYPE_READONLY (type); int constp = TYPE_READONLY (type);
int volatilep = TYPE_VOLATILE (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 if (TYPE_READONLY (v) != constp
|| TYPE_VOLATILE (v) != volatilep) || TYPE_VOLATILE (v) != volatilep)
...@@ -1595,9 +1595,8 @@ build_exception_variant (type, raises) ...@@ -1595,9 +1595,8 @@ build_exception_variant (type, raises)
} }
/* Need to build a new variant. */ /* Need to build a new variant. */
v = copy_node (type); v = build_type_copy (type);
TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
TYPE_NEXT_VARIANT (type) = v;
if (raises && ! TREE_PERMANENT (raises)) if (raises && ! TREE_PERMANENT (raises))
{ {
push_obstacks_nochange (); push_obstacks_nochange ();
......
...@@ -1539,7 +1539,7 @@ build_object_ref (datum, basetype, field) ...@@ -1539,7 +1539,7 @@ build_object_ref (datum, basetype, field)
} }
else if (is_aggr_type (basetype, 1)) 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) if (binfo)
return build_component_ref (build_scoped_ref (datum, basetype), return build_component_ref (build_scoped_ref (datum, basetype),
field, binfo, 1); field, binfo, 1);
...@@ -1825,7 +1825,16 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -1825,7 +1825,16 @@ build_component_ref (datum, component, basetype_path, protect)
error ("invalid reference to NULL ptr, use ptr-to-member instead"); error ("invalid reference to NULL ptr, use ptr-to-member instead");
return error_mark_node; 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); datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 311); my_friendly_assert (datum != error_mark_node, 311);
} }
...@@ -5831,7 +5840,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5831,7 +5840,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (build_default_binary_type_conversion (modifycode, &lhs_tmp, &rhs_tmp)) if (build_default_binary_type_conversion (modifycode, &lhs_tmp, &rhs_tmp))
{ {
lhs = stabilize_reference (lhs_tmp); lhs = stabilize_reference (lhs_tmp);
/* Forget is was ever anything else. */ /* Forget it was ever anything else. */
olhstype = lhstype = TREE_TYPE (lhs); olhstype = lhstype = TREE_TYPE (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1); newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
} }
......
...@@ -1440,6 +1440,8 @@ build_functional_cast (exp, parms) ...@@ -1440,6 +1440,8 @@ build_functional_cast (exp, parms)
type = TREE_TYPE (type); type = TREE_TYPE (type);
} }
} }
else if (TREE_CODE (exp) == TYPE_DECL)
type = TREE_TYPE (exp);
else else
type = exp; type = exp;
...@@ -1449,20 +1451,6 @@ build_functional_cast (exp, parms) ...@@ -1449,20 +1451,6 @@ build_functional_cast (exp, parms)
return error_mark_node; 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)) if (! IS_AGGR_TYPE (type))
{ {
/* this must build a C cast */ /* this must build a C cast */
...@@ -1478,6 +1466,20 @@ build_functional_cast (exp, parms) ...@@ -1478,6 +1466,20 @@ build_functional_cast (exp, parms)
return build_c_cast (type, parms, 1); 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) if (TYPE_SIZE (type) == NULL_TREE)
{ {
cp_error ("type `%T' is not yet defined", type); cp_error ("type `%T' is not yet defined", type);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment