summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/method.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/method.c')
-rw-r--r--contrib/gcc/cp/method.c185
1 files changed, 97 insertions, 88 deletions
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index b0cc63a..e4af0ab 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -392,6 +392,12 @@ use_thunk (thunk_fndecl, emit_p)
push_to_top_level ();
+ /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
+ create one. */
+ DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
+ BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
+ = DECL_ARGUMENTS (thunk_fndecl);
+
#ifdef ASM_OUTPUT_MI_THUNK
if (!vcall_offset)
{
@@ -411,88 +417,83 @@ use_thunk (thunk_fndecl, emit_p)
}
else
#endif /* ASM_OUTPUT_MI_THUNK */
- {
- /* If we don't have the necessary macro for efficient thunks, generate a
- thunk function that just makes a call to the real function.
- Unfortunately, this doesn't work for varargs. */
-
- tree a, t;
-
- if (varargs_function_p (function))
- error ("generic thunk code fails for method `%#D' which uses `...'",
- function);
-
- /* Set up clone argument trees for the thunk. */
- t = NULL_TREE;
- for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
- {
- tree x = copy_node (a);
- TREE_CHAIN (x) = t;
- DECL_CONTEXT (x) = thunk_fndecl;
- t = x;
- }
- a = nreverse (t);
- DECL_ARGUMENTS (thunk_fndecl) = a;
- DECL_RESULT (thunk_fndecl) = NULL_TREE;
-
- start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
- /* We don't bother with a body block for thunks. */
-
- /* Adjust the this pointer by the constant. */
- t = ssize_int (delta);
- t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));
- /* If there's a vcall offset, look up that value in the vtable and
- adjust the `this' pointer again. */
- if (vcall_offset && !integer_zerop (vcall_offset))
- {
- tree orig_this;
-
- t = save_expr (t);
- orig_this = t;
- /* The vptr is always at offset zero in the object. */
- t = build1 (NOP_EXPR,
- build_pointer_type (build_pointer_type
- (vtable_entry_type)),
- t);
- /* Form the vtable address. */
- t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
- /* Find the entry with the vcall offset. */
- t = build (PLUS_EXPR, TREE_TYPE (t), t, vcall_offset);
- /* Calculate the offset itself. */
- t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
- /* Adjust the `this' pointer. */
- t = fold (build (PLUS_EXPR,
- TREE_TYPE (orig_this),
- orig_this,
- t));
- }
-
- /* Build up the call to the real function. */
- t = tree_cons (NULL_TREE, t, NULL_TREE);
- for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
- t = tree_cons (NULL_TREE, a, t);
- t = nreverse (t);
- t = build_call (function, t);
- if (VOID_TYPE_P (TREE_TYPE (t)))
- finish_expr_stmt (t);
- else
- finish_return_stmt (t);
+ {
+ /* If we don't have the necessary macro for efficient thunks, generate
+ a thunk function that just makes a call to the real function.
+ Unfortunately, this doesn't work for varargs. */
- /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
- create one. */
- DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
- BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
- = DECL_ARGUMENTS (thunk_fndecl);
+ tree a, t;
- /* Since we want to emit the thunk, we explicitly mark its name as
- referenced. */
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (thunk_fndecl)) = 1;
+ if (varargs_function_p (function))
+ error ("generic thunk code fails for method `%#D' which uses `...'",
+ function);
- /* But we don't want debugging information about it. */
- DECL_IGNORED_P (thunk_fndecl) = 1;
+ /* Set up clone argument trees for the thunk. */
+ t = NULL_TREE;
+ for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
+ {
+ tree x = copy_node (a);
+ TREE_CHAIN (x) = t;
+ DECL_CONTEXT (x) = thunk_fndecl;
+ t = x;
+ }
+ a = nreverse (t);
+ DECL_ARGUMENTS (thunk_fndecl) = a;
+ DECL_RESULT (thunk_fndecl) = NULL_TREE;
- expand_body (finish_function (0));
- }
+ start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
+ /* We don't bother with a body block for thunks. */
+
+ /* Adjust the this pointer by the constant. */
+ t = ssize_int (delta);
+ t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));
+
+ /* If there's a vcall offset, look up that value in the vtable and
+ adjust the `this' pointer again. */
+ if (vcall_offset && !integer_zerop (vcall_offset))
+ {
+ tree orig_this;
+
+ t = save_expr (t);
+ orig_this = t;
+ /* The vptr is always at offset zero in the object. */
+ t = build1 (NOP_EXPR,
+ build_pointer_type (build_pointer_type
+ (vtable_entry_type)),
+ t);
+ /* Form the vtable address. */
+ t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
+ /* Find the entry with the vcall offset. */
+ t = build (PLUS_EXPR, TREE_TYPE (t), t, vcall_offset);
+ /* Calculate the offset itself. */
+ t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
+ /* Adjust the `this' pointer. */
+ t = fold (build (PLUS_EXPR,
+ TREE_TYPE (orig_this),
+ orig_this,
+ t));
+ }
+
+ /* Build up the call to the real function. */
+ t = tree_cons (NULL_TREE, t, NULL_TREE);
+ for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
+ t = tree_cons (NULL_TREE, a, t);
+ t = nreverse (t);
+ t = build_call (function, t);
+ if (VOID_TYPE_P (TREE_TYPE (t)))
+ finish_expr_stmt (t);
+ else
+ finish_return_stmt (t);
+
+ /* Since we want to emit the thunk, we explicitly mark its name as
+ referenced. */
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (thunk_fndecl)) = 1;
+
+ /* But we don't want debugging information about it. */
+ DECL_IGNORED_P (thunk_fndecl) = 1;
+
+ expand_body (finish_function (0));
+ }
pop_from_top_level ();
}
@@ -561,6 +562,7 @@ do_build_copy_constructor (fndecl)
{
tree init;
tree field = fields;
+ tree expr_type;
if (TREE_CODE (field) != FIELD_DECL)
continue;
@@ -583,9 +585,15 @@ do_build_copy_constructor (fndecl)
else
continue;
- init = build (COMPONENT_REF,
- build_qualified_type (TREE_TYPE (field), cvquals),
- init, field);
+ /* Compute the type of "init->field". If the copy-constructor
+ parameter is, for example, "const S&", and the type of
+ the field is "T", then the type will usually be "const
+ T". (There are no cv-qualified variants of reference
+ types.) */
+ expr_type = TREE_TYPE (field);
+ if (TREE_CODE (expr_type) != REFERENCE_TYPE)
+ expr_type = cp_build_qualified_type (expr_type, cvquals);
+ init = build (COMPONENT_REF, expr_type, init, field);
init = build_tree_list (NULL_TREE, init);
member_init_list
@@ -635,7 +643,7 @@ do_build_assign_ref (fndecl)
tree expr = build_method_call (dst,
ansi_assopname (NOP_EXPR),
build_tree_list (NULL_TREE, src),
- NULL,
+ binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
finish_expr_stmt (expr);
}
@@ -769,8 +777,9 @@ synthesize_method (fndecl)
/* Use EXTRACTOR to locate the relevant function called for each base &
class field of TYPE. CLIENT allows additional information to be passed
- to EXTRACTOR. Generates the union of all exceptions generated by
- those functions. */
+ to EXTRACTOR. Generates the union of all exceptions generated by those
+ functions. Note that we haven't updated TYPE_FIELDS and such of any
+ variants yet, so we need to look at the main one. */
static tree
synthesize_exception_spec (type, extractor, client)
@@ -782,7 +791,7 @@ synthesize_exception_spec (type, extractor, client)
tree fields = TYPE_FIELDS (type);
int i, n_bases = CLASSTYPE_N_BASECLASSES (type);
tree binfos = TYPE_BINFO_BASETYPES (type);
-
+
for (i = 0; i != n_bases; i++)
{
tree base = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
@@ -961,7 +970,7 @@ implicitly_declare_fn (kind, type, const_p)
case sfk_assignment_operator:
{
struct copy_data data;
- tree argtype;
+ tree argtype = type;
has_parm = 1;
data.name = NULL;
@@ -977,10 +986,10 @@ implicitly_declare_fn (kind, type, const_p)
if (const_p)
{
data.quals = TYPE_QUAL_CONST;
- type = build_qualified_type (type, TYPE_QUAL_CONST);
+ argtype = build_qualified_type (argtype, TYPE_QUAL_CONST);
}
- argtype = build_reference_type (type);
+ argtype = build_reference_type (argtype);
args = build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg"));
args = tree_cons (NULL_TREE, args, void_list_node);
OpenPOWER on IntegriCloud