diff options
Diffstat (limited to 'contrib/gcc/cp/method.c')
-rw-r--r-- | contrib/gcc/cp/method.c | 185 |
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); |