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.c245
1 files changed, 141 insertions, 104 deletions
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index 5bb555d..16682af 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
-#include "obstack.h"
#include "rtl.h"
#include "expr.h"
#include "output.h"
@@ -35,6 +34,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "ggc.h"
#include "tm_p.h"
+#include "target.h"
/* Various flags to control the mangling process. */
@@ -54,9 +54,6 @@ enum mangling_flags
typedef enum mangling_flags mangling_flags;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
static void do_build_assign_ref PARAMS ((tree));
static void do_build_copy_constructor PARAMS ((tree));
static tree synthesize_exception_spec PARAMS ((tree, tree (*) (tree, void *), void *));
@@ -165,12 +162,26 @@ hack_identifier (value, name)
return error_mark_node;
}
TREE_USED (current_class_ptr) = 1;
+ if (processing_template_decl)
+ value = build_min_nt (COMPONENT_REF, current_class_ref, name);
+ else
+ {
+ tree access_type = current_class_type;
+
+ while (!DERIVED_FROM_P (context_for_name_lookup (value),
+ access_type))
+ {
+ access_type = TYPE_CONTEXT (access_type);
+ while (DECL_P (access_type))
+ access_type = DECL_CONTEXT (access_type);
+ }
- /* Mark so that if we are in a constructor, and then find that
- this field was initialized by a base initializer,
- we can emit an error message. */
- TREE_USED (value) = 1;
- value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
+ enforce_access (access_type, value);
+ value
+ = build_class_member_access_expr (current_class_ref, value,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
+ }
}
else if ((TREE_CODE (value) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (value))
@@ -183,7 +194,7 @@ hack_identifier (value, name)
value = OVL_CURRENT (value);
decl = maybe_dummy_object (DECL_CONTEXT (value), 0);
- value = build_component_ref (decl, name, NULL_TREE, 1);
+ value = finish_class_member_access_expr (decl, name);
}
else if (really_overloaded_fn (value))
;
@@ -267,10 +278,11 @@ make_thunk (function, delta, vcall_index)
{
tree thunk_id;
tree thunk;
- tree func_decl;
tree vcall_offset;
HOST_WIDE_INT d;
+ my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
+
/* Scale the VCALL_INDEX to be in terms of bytes. */
if (vcall_index)
vcall_offset
@@ -283,64 +295,66 @@ make_thunk (function, delta, vcall_index)
d = tree_low_cst (delta, 0);
- if (TREE_CODE (function) != ADDR_EXPR)
- abort ();
- func_decl = TREE_OPERAND (function, 0);
- if (TREE_CODE (func_decl) != FUNCTION_DECL)
- abort ();
+ /* See if we already have the thunk in question. */
+ for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
+ if (THUNK_DELTA (thunk) == d
+ && ((THUNK_VCALL_OFFSET (thunk) != NULL_TREE)
+ == (vcall_offset != NULL_TREE))
+ && (THUNK_VCALL_OFFSET (thunk)
+ ? tree_int_cst_equal (THUNK_VCALL_OFFSET (thunk),
+ vcall_offset)
+ : true))
+ return thunk;
+
+ /* All thunks must be created before FUNCTION is actually emitted;
+ the ABI requires that all thunks be emitted together with the
+ function to which they transfer control. */
+ my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025);
+
+ thunk_id = mangle_thunk (function, delta, vcall_offset);
+ thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (function));
+ DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
+ cxx_dup_lang_specific_decl (function);
+ SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
+ DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
+ TREE_READONLY (thunk) = TREE_READONLY (function);
+ TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
+ TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
+ if (flag_weak)
+ comdat_linkage (thunk);
+ SET_DECL_THUNK_P (thunk);
+ DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function);
+ THUNK_DELTA (thunk) = d;
+ THUNK_VCALL_OFFSET (thunk) = vcall_offset;
+ /* The thunk itself is not a constructor or destructor, even if
+ the thing it is thunking to is. */
+ DECL_INTERFACE_KNOWN (thunk) = 1;
+ DECL_NOT_REALLY_EXTERN (thunk) = 1;
+ DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
+ DECL_DESTRUCTOR_P (thunk) = 0;
+ DECL_CONSTRUCTOR_P (thunk) = 0;
+ /* And neither is it a clone. */
+ DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
+ DECL_EXTERNAL (thunk) = 1;
+ DECL_ARTIFICIAL (thunk) = 1;
+ /* Even if this thunk is a member of a local class, we don't
+ need a static chain. */
+ DECL_NO_STATIC_CHAIN (thunk) = 1;
+ /* The THUNK is not a pending inline, even if the FUNCTION is. */
+ DECL_PENDING_INLINE_P (thunk) = 0;
+ DECL_INLINE (thunk) = 0;
+ DECL_DECLARED_INLINE_P (thunk) = 0;
+ /* Nor has it been deferred. */
+ DECL_DEFERRED_FN (thunk) = 0;
+ /* Add it to the list of thunks associated with FUNCTION. */
+ TREE_CHAIN (thunk) = DECL_THUNKS (function);
+ DECL_THUNKS (function) = thunk;
- thunk_id = mangle_thunk (TREE_OPERAND (function, 0),
- delta, vcall_offset);
- thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
- if (thunk && !DECL_THUNK_P (thunk))
- {
- error ("implementation-reserved name `%D' used", thunk_id);
- thunk = NULL_TREE;
- SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
- }
- if (thunk == NULL_TREE)
- {
- thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
- DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl);
- copy_lang_decl (func_decl);
- SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
- DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
- TREE_READONLY (thunk) = TREE_READONLY (func_decl);
- TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
- TREE_PUBLIC (thunk) = TREE_PUBLIC (func_decl);
- if (flag_weak)
- comdat_linkage (thunk);
- SET_DECL_THUNK_P (thunk);
- DECL_INITIAL (thunk) = function;
- THUNK_DELTA (thunk) = d;
- THUNK_VCALL_OFFSET (thunk) = vcall_offset;
- /* The thunk itself is not a constructor or destructor, even if
- the thing it is thunking to is. */
- DECL_INTERFACE_KNOWN (thunk) = 1;
- DECL_NOT_REALLY_EXTERN (thunk) = 1;
- DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
- DECL_DESTRUCTOR_P (thunk) = 0;
- DECL_CONSTRUCTOR_P (thunk) = 0;
- /* And neither is it a clone. */
- DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
- DECL_EXTERNAL (thunk) = 1;
- DECL_ARTIFICIAL (thunk) = 1;
- /* Even if this thunk is a member of a local class, we don't
- need a static chain. */
- DECL_NO_STATIC_CHAIN (thunk) = 1;
- /* The THUNK is not a pending inline, even if the FUNC_DECL is. */
- DECL_PENDING_INLINE_P (thunk) = 0;
- /* Nor has it been deferred. */
- DECL_DEFERRED_FN (thunk) = 0;
- /* So that finish_file can write out any thunks that need to be: */
- pushdecl_top_level (thunk);
- SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
- }
return thunk;
}
/* Emit the definition of a C++ multiple inheritance vtable thunk. If
- EMIT_P is non-zero, the thunk is emitted immediately. */
+ EMIT_P is nonzero, the thunk is emitted immediately. */
void
use_thunk (thunk_fndecl, emit_p)
@@ -350,7 +364,7 @@ use_thunk (thunk_fndecl, emit_p)
tree fnaddr;
tree function;
tree vcall_offset;
- HOST_WIDE_INT delta;
+ HOST_WIDE_INT delta, vcall_value;
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
@@ -376,6 +390,17 @@ use_thunk (thunk_fndecl, emit_p)
delta = THUNK_DELTA (thunk_fndecl);
vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
+ if (vcall_offset)
+ {
+ vcall_value = tree_low_cst (vcall_offset, /*pos=*/0);
+
+ /* It is expected that a value of zero means no vcall. */
+ if (!vcall_value)
+ abort ();
+ }
+ else
+ vcall_value = 0;
+
/* And, if we need to emit the thunk, it's used. */
mark_used (thunk_fndecl);
/* This thunk is actually defined. */
@@ -398,8 +423,8 @@ use_thunk (thunk_fndecl, emit_p)
BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
= DECL_ARGUMENTS (thunk_fndecl);
-#ifdef ASM_OUTPUT_MI_THUNK
- if (!vcall_offset)
+ if (targetm.asm_out.can_output_mi_thunk (thunk_fndecl, delta,
+ vcall_value, function))
{
const char *fnname;
current_function_decl = thunk_fndecl;
@@ -409,18 +434,23 @@ use_thunk (thunk_fndecl, emit_p)
init_function_start (thunk_fndecl, input_filename, lineno);
current_function_is_thunk = 1;
assemble_start_function (thunk_fndecl, fnname);
- ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
+
+ targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, delta,
+ vcall_value, function);
+
assemble_end_function (thunk_fndecl, fnname);
current_function_decl = 0;
cfun = 0;
+ /* Because init_function_start increments this, we must
+ decrement it. */
+ immediate_size_expand--;
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
}
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. */
+ /* If we don't have the necessary code 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;
@@ -526,7 +556,6 @@ do_build_copy_constructor (fndecl)
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
tree member_init_list = NULL_TREE;
- tree base_init_list = NULL_TREE;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
@@ -540,10 +569,12 @@ do_build_copy_constructor (fndecl)
{
tree binfo = TREE_VALUE (t);
- base_init_list = tree_cons (binfo,
- build_base_path (PLUS_EXPR, parm,
- binfo, 1),
- base_init_list);
+ member_init_list
+ = tree_cons (binfo,
+ build_tree_list (NULL_TREE,
+ build_base_path (PLUS_EXPR, parm,
+ binfo, 1)),
+ member_init_list);
}
for (i = 0; i < n_bases; ++i)
@@ -552,10 +583,12 @@ do_build_copy_constructor (fndecl)
if (TREE_VIA_VIRTUAL (binfo))
continue;
- base_init_list = tree_cons (binfo,
- build_base_path (PLUS_EXPR, parm,
- binfo, 1),
- base_init_list);
+ member_init_list
+ = tree_cons (binfo,
+ build_tree_list (NULL_TREE,
+ build_base_path (PLUS_EXPR, parm,
+ binfo, 1)),
+ member_init_list);
}
for (; fields; fields = TREE_CHAIN (fields))
@@ -599,9 +632,7 @@ do_build_copy_constructor (fndecl)
member_init_list
= tree_cons (field, init, member_init_list);
}
- member_init_list = nreverse (member_init_list);
- base_init_list = nreverse (base_init_list);
- emit_base_init (member_init_list, base_init_list);
+ finish_mem_initializers (member_init_list);
}
}
@@ -626,33 +657,39 @@ do_build_assign_ref (fndecl)
}
else
{
- tree fields = TYPE_FIELDS (current_class_type);
- int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
- tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
+ tree fields;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
- for (i = 0; i < n_bases; ++i)
+ /* Assign to each of thedirect base classes. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i)
{
- /* We must deal with the binfo's directly as a direct base
- might be inaccessible due to ambiguity. */
- tree binfo = TREE_VEC_ELT (binfos, i);
- tree src = build_base_path (PLUS_EXPR, parm, binfo, 1);
- tree dst = build_base_path (PLUS_EXPR, current_class_ref, binfo, 1);
-
- tree expr = build_method_call (dst,
- ansi_assopname (NOP_EXPR),
- build_tree_list (NULL_TREE, src),
- binfo,
- LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
- finish_expr_stmt (expr);
+ tree binfo;
+ tree converted_parm;
+
+ binfo = BINFO_BASETYPE (TYPE_BINFO (current_class_type), i);
+ /* We must convert PARM directly to the base class
+ explicitly since the base class may be ambiguous. */
+ converted_parm = build_base_path (PLUS_EXPR, parm, binfo, 1);
+ /* Call the base class assignment operator. */
+ finish_expr_stmt
+ (build_special_member_call (current_class_ref,
+ ansi_assopname (NOP_EXPR),
+ build_tree_list (NULL_TREE,
+ converted_parm),
+ binfo,
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
}
- for (; fields; fields = TREE_CHAIN (fields))
+
+ /* Assign to each of the non-static data members. */
+ for (fields = TYPE_FIELDS (current_class_type);
+ fields;
+ fields = TREE_CHAIN (fields))
{
tree comp, init, t;
tree field = fields;
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (CP_TYPE_CONST_P (TREE_TYPE (field)))
@@ -733,7 +770,7 @@ synthesize_method (fndecl)
during the generation of the implicit body points at the place
where the attempt to generate the function occurs, giving the
user a hint as to why we are attempting to generate the
- function. */
+ function. */
DECL_SOURCE_LINE (fndecl) = lineno;
DECL_SOURCE_FILE (fndecl) = input_filename;
@@ -808,7 +845,7 @@ synthesize_exception_spec (type, extractor, client)
tree type = TREE_TYPE (fields);
tree fn;
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
OpenPOWER on IntegriCloud