summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/init.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
committerobrien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
commitc8f5fc7032940ad6633f932ac40cade82ec4d0cc (patch)
tree29a0f0a6c79a69ecc64f612947a0fe5904311713 /contrib/gcc/cp/init.c
parentc9ab9ae440a8066b2c2b85b157b1fdadcf09916a (diff)
downloadFreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.zip
FreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.tar.gz
Gcc 3.1.0 pre-release from the FSF anoncvs repo on 9-May-2002 15:57:15 EDT.
Diffstat (limited to 'contrib/gcc/cp/init.c')
-rw-r--r--contrib/gcc/cp/init.c196
1 files changed, 105 insertions, 91 deletions
diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c
index 017b894..4cb0dab 100644
--- a/contrib/gcc/cp/init.c
+++ b/contrib/gcc/cp/init.c
@@ -97,10 +97,6 @@ begin_init_stmts (stmt_expr_p, compound_stmt_p)
if (building_stmt_tree ())
*compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
- /*
- else
- *compound_stmt_p = genrtl_begin_compound_stmt (has_no_scope=1);
- */
}
/* Finish out the statement-expression begun by the previous call to
@@ -116,7 +112,10 @@ finish_init_stmts (stmt_expr, compound_stmt)
finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
if (building_stmt_tree ())
- stmt_expr = finish_stmt_expr (stmt_expr);
+ {
+ stmt_expr = finish_stmt_expr (stmt_expr);
+ STMT_EXPR_NO_SCOPE (stmt_expr) = true;
+ }
else
stmt_expr = finish_global_stmt_expr (stmt_expr);
@@ -1496,10 +1495,8 @@ build_member_call (type, name, parmlist)
decl = maybe_dummy_object (type, &basetype_path);
/* Convert 'this' to the specified type to disambiguate conversion
- to the function's context. Apparently Standard C++ says that we
- shouldn't do this. */
+ to the function's context. */
if (decl == current_class_ref
- && ! pedantic
&& ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
{
tree olddecl = current_class_ptr;
@@ -1819,9 +1816,7 @@ resolve_offset_ref (exp)
if (TREE_CODE (member) == FIELD_DECL
&& (base == current_class_ref || is_dummy_object (base)))
{
- tree expr;
-
- basetype = DECL_CONTEXT (member);
+ tree binfo = TYPE_BINFO (current_class_type);
/* Try to get to basetype from 'this'; if that doesn't work,
nothing will. */
@@ -1829,30 +1824,15 @@ resolve_offset_ref (exp)
/* First convert to the intermediate base specified, if appropriate. */
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
- base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
-
- /* Don't check access on the conversion; we might be after a member
- promoted by an access- or using-declaration, and we have already
- checked access for the member itself. */
- basetype = lookup_base (TREE_TYPE (base), basetype, ba_ignore, NULL);
- expr = build_base_path (PLUS_EXPR, base, basetype, 1);
-
- if (expr == error_mark_node)
- return error_mark_node;
-
- type = TREE_TYPE (member);
- if (TREE_CODE (type) != REFERENCE_TYPE)
{
- int quals = cp_type_quals (type) | cp_type_quals (TREE_TYPE (expr));
-
- if (DECL_MUTABLE_P (member))
- quals &= ~TYPE_QUAL_CONST;
-
- type = cp_build_qualified_type (type, quals);
+ binfo = binfo_or_else (TYPE_OFFSET_BASETYPE (type),
+ current_class_type);
+ if (!binfo)
+ return error_mark_node;
+ base = build_base_path (PLUS_EXPR, base, binfo, 1);
}
-
- expr = build (COMPONENT_REF, type, expr, member);
- return convert_from_reference (expr);
+
+ return build_component_ref (base, member, binfo, 1);
}
/* Ensure that we have an object. */
@@ -2206,6 +2186,7 @@ build_new_1 (exp)
tree full_type;
tree nelts = NULL_TREE;
tree alloc_call, alloc_expr, alloc_node;
+ tree alloc_fn;
tree cookie_expr, init_expr;
int has_array = 0;
enum tree_code code;
@@ -2260,7 +2241,7 @@ build_new_1 (exp)
size = size_in_bytes (true_type);
if (has_array)
- size = fold (cp_build_binary_op (MULT_EXPR, size, nelts));
+ size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
if (TREE_CODE (true_type) == VOID_TYPE)
{
@@ -2288,7 +2269,7 @@ build_new_1 (exp)
use_cookie = 0;
/* When using placement new, users may not realize that they need
the extra storage. We require that the operator called be
- the global placement operator delete[]. */
+ the global placement operator new[]. */
else if (placement && !TREE_CHAIN (placement)
&& same_type_p (TREE_TYPE (TREE_VALUE (placement)),
ptr_type_node))
@@ -2346,13 +2327,14 @@ build_new_1 (exp)
if (alloc_call == error_mark_node)
return error_mark_node;
- /* The ALLOC_CALL should be a CALL_EXPR, and the first operand
- should be the address of a known FUNCTION_DECL. */
- my_friendly_assert (TREE_CODE (alloc_call) == CALL_EXPR, 20000521);
- t = TREE_OPERAND (alloc_call, 0);
- my_friendly_assert (TREE_CODE (t) == ADDR_EXPR, 20000521);
- t = TREE_OPERAND (t, 0);
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL, 20000521);
+ /* The ALLOC_CALL should be a CALL_EXPR -- or a COMPOUND_EXPR whose
+ right-hand-side is ultimately a CALL_EXPR -- and the first
+ operand should be the address of a known FUNCTION_DECL. */
+ t = alloc_call;
+ while (TREE_CODE (t) == COMPOUND_EXPR)
+ t = TREE_OPERAND (t, 1);
+ alloc_fn = get_callee_fndecl (t);
+ my_friendly_assert (alloc_fn != NULL_TREE, 20020325);
/* Now, check to see if this function is actually a placement
allocation function. This can happen even when PLACEMENT is NULL
because we might have something like:
@@ -2364,7 +2346,8 @@ build_new_1 (exp)
one argument, or there are variable arguments, then this is a
placement allocation function. */
placement_allocation_fn_p
- = (type_num_arguments (TREE_TYPE (t)) > 1 || varargs_function_p (t));
+ = (type_num_arguments (TREE_TYPE (alloc_fn)) > 1
+ || varargs_function_p (alloc_fn));
/* unless an allocation function is declared with an empty excep-
tion-specification (_except.spec_), throw(), it indicates failure to
@@ -2376,11 +2359,7 @@ build_new_1 (exp)
So check for a null exception spec on the op new we just called. */
- /* The ADDR_EXPR. */
- t = TREE_OPERAND (alloc_call, 0);
- /* The function. */
- t = TREE_OPERAND (t, 0);
- nothrow = TYPE_NOTHROW_P (TREE_TYPE (t));
+ nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
check_new = (flag_check_new || nothrow) && ! use_java_new;
alloc_expr = alloc_call;
@@ -2473,13 +2452,22 @@ build_new_1 (exp)
tree cleanup;
int flags = (LOOKUP_NORMAL
| (globally_qualified_p * LOOKUP_GLOBAL));
+ tree delete_node;
+
+ if (use_cookie)
+ /* Subtract the padding back out to get to the pointer returned
+ from operator new. */
+ delete_node = fold (build (MINUS_EXPR, TREE_TYPE (alloc_node),
+ alloc_node, cookie_size));
+ else
+ delete_node = alloc_node;
/* The Standard is unclear here, but the right thing to do
is to use the same method for finding deallocation
functions that we use for finding allocation functions. */
flags |= LOOKUP_SPECULATIVELY;
- cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
+ cleanup = build_op_delete_call (dcode, delete_node, size, flags,
(placement_allocation_fn_p
? alloc_call : NULL_TREE));
@@ -3200,6 +3188,14 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* Call the complete object destructor. */
auto_delete = sfk_complete_destructor;
}
+ else if (auto_delete == sfk_deleting_destructor
+ && TYPE_GETS_REG_DELETE (type))
+ {
+ /* Make sure we have access to the member op delete, even though
+ we'll actually be calling it from the destructor. */
+ build_op_delete_call (DELETE_EXPR, addr, c_sizeof_nowarn (type),
+ LOOKUP_NORMAL, NULL_TREE);
+ }
expr = build_dtor_call (build_indirect_ref (addr, NULL),
auto_delete, flags);
@@ -3221,18 +3217,65 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
}
}
-/* At the beginning of a destructor, push cleanups that will call the
- destructors for our base classes and members.
+/* At the end of a destructor, call the destructors for our base classes
+ and members.
- Called from setup_vtbl_ptr. */
+ Called from finish_destructor_body. */
void
-push_base_cleanups ()
+perform_base_cleanups ()
{
tree binfos;
int i, n_baseclasses;
tree member;
tree expr;
+ tree member_destructions = NULL;
+ tree vbase_destructions = NULL;
+
+ for (member = TYPE_FIELDS (current_class_type); member;
+ member = TREE_CHAIN (member))
+ {
+ if (TREE_CODE (member) != FIELD_DECL)
+ continue;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+ {
+ tree this_member = (build_component_ref
+ (current_class_ref, member,
+ NULL_TREE, 0));
+ tree this_type = TREE_TYPE (member);
+ expr = build_delete (this_type, this_member,
+ sfk_complete_destructor,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
+ 0);
+ if (!member_destructions)
+ member_destructions = expr;
+ else
+ member_destructions = build (COMPOUND_EXPR,
+ TREE_TYPE (member_destructions),
+ expr,
+ member_destructions);
+ }
+ }
+ if (member_destructions)
+ finish_expr_stmt (member_destructions);
+
+ binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
+ n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+
+ /* Take care of the remaining baseclasses. */
+ for (i = n_baseclasses - 1; i >= 0; i--)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
+ || TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+
+ expr = build_scoped_method_call (current_class_ref, base_binfo,
+ base_dtor_identifier,
+ NULL_TREE);
+
+ finish_expr_stmt (expr);
+ }
/* Run destructors for all virtual baseclasses. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
@@ -3271,47 +3314,18 @@ push_base_cleanups ()
LOOKUP_NORMAL);
expr = build (COND_EXPR, void_type_node, cond,
expr, void_zero_node);
- finish_decl_cleanup (NULL_TREE, expr);
+ if (!vbase_destructions)
+ vbase_destructions = expr;
+ else
+ vbase_destructions = build (COMPOUND_EXPR,
+ TREE_TYPE (vbase_destructions),
+ expr,
+ vbase_destructions);
}
}
}
-
- binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
- n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
-
- /* Take care of the remaining baseclasses. */
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
- || TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- expr = build_scoped_method_call (current_class_ref, base_binfo,
- base_dtor_identifier,
- NULL_TREE);
-
- finish_decl_cleanup (NULL_TREE, expr);
- }
-
- for (member = TYPE_FIELDS (current_class_type); member;
- member = TREE_CHAIN (member))
- {
- if (TREE_CODE (member) != FIELD_DECL)
- continue;
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
- {
- tree this_member = (build_component_ref
- (current_class_ref, DECL_NAME (member),
- NULL_TREE, 0));
- tree this_type = TREE_TYPE (member);
- expr = build_delete (this_type, this_member,
- sfk_complete_destructor,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
- 0);
- finish_decl_cleanup (NULL_TREE, expr);
- }
- }
+ if (vbase_destructions)
+ finish_expr_stmt (vbase_destructions);
}
/* For type TYPE, delete the virtual baseclass objects of DECL. */
OpenPOWER on IntegriCloud