aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey Keating <geoffk@redhat.com>2001-05-04 06:28:54 +0000
committerGeoffrey Keating <geoffk@gcc.gnu.org>2001-05-04 06:28:54 +0000
commit8e9eff6bc04068f44def72f44a5f11027d7eb3dc (patch)
treed868f5fe0152e84a5178c7af2fe9301e56e71e30
parent02d208ff0f057f9b15414f15fd2ece8eef5f49e5 (diff)
downloadgcc-8e9eff6bc04068f44def72f44a5f11027d7eb3dc.zip
gcc-8e9eff6bc04068f44def72f44a5f11027d7eb3dc.tar.gz
gcc-8e9eff6bc04068f44def72f44a5f11027d7eb3dc.tar.bz2
cp-tree.h (enum cp_tree_index): Add CPTI_PFN_VFLAG_IDENTIFIER.
* cp-tree.h (enum cp_tree_index): Add CPTI_PFN_VFLAG_IDENTIFIER. (pfn_vflag_identifier): Define. Update comment about layout of pointer functions. (build_ptrmemfunc1): Update prototype. (expand_ptrmemfunc_cst): Update prototype. * decl.c (initialize_predefined_identifiers): Initialize pfn_vflag_identifier. (build_ptrmemfunc_type): When FUNCTION_BOUNDARY < 16, add an extra field to the type. * expr.c (cplus_expand_constant): Pass 'flag' between expand_ptrmemfunc_cst and build_ptrmemfunc1. * typeck.c (get_member_function_from_ptrfunc): When FUNCTION_BOUNDARY < 16, look at additional field to determine if a pointer-to-member is a real pointer or a vtable offset. (build_ptrmemfunc1): Add new parameter to contain extra field. (build_ptrmemfunc): Pass the extra field around. (expand_ptrmemfunc_cst): Add new parameter to return extra field. (pfn_from_ptrmemfunc): Ignore the extra field. From-SVN: r41824
-rw-r--r--gcc/cp/ChangeLog21
-rw-r--r--gcc/cp/cp-tree.h64
-rw-r--r--gcc/cp/decl.c10
-rw-r--r--gcc/cp/expr.c5
-rw-r--r--gcc/cp/typeck.c63
5 files changed, 106 insertions, 57 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0acfdb9..9030ae6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,24 @@
+2001-05-03 Geoffrey Keating <geoffk@redhat.com>
+
+ * cp-tree.h (enum cp_tree_index): Add CPTI_PFN_VFLAG_IDENTIFIER.
+ (pfn_vflag_identifier): Define.
+ Update comment about layout of pointer functions.
+ (build_ptrmemfunc1): Update prototype.
+ (expand_ptrmemfunc_cst): Update prototype.
+ * decl.c (initialize_predefined_identifiers): Initialize
+ pfn_vflag_identifier.
+ (build_ptrmemfunc_type): When FUNCTION_BOUNDARY < 16, add
+ an extra field to the type.
+ * expr.c (cplus_expand_constant): Pass 'flag' between
+ expand_ptrmemfunc_cst and build_ptrmemfunc1.
+ * typeck.c (get_member_function_from_ptrfunc): When
+ FUNCTION_BOUNDARY < 16, look at additional field to determine
+ if a pointer-to-member is a real pointer or a vtable offset.
+ (build_ptrmemfunc1): Add new parameter to contain extra field.
+ (build_ptrmemfunc): Pass the extra field around.
+ (expand_ptrmemfunc_cst): Add new parameter to return extra field.
+ (pfn_from_ptrmemfunc): Ignore the extra field.
+
2001-05-03 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (flag_inline_trees): Update documentation.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 05a0d0f..e1b9361 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -611,6 +611,7 @@ enum cp_tree_index
CPTI_NELTS_IDENTIFIER,
CPTI_THIS_IDENTIFIER,
CPTI_PFN_IDENTIFIER,
+ CPTI_PFN_VFLAG_IDENTIFIER,
CPTI_PFN_OR_DELTA2_IDENTIFIER,
CPTI_VPTR_IDENTIFIER,
CPTI_STD_IDENTIFIER,
@@ -735,6 +736,7 @@ extern tree cp_global_trees[CPTI_MAX];
#define nelts_identifier cp_global_trees[CPTI_NELTS_IDENTIFIER]
#define this_identifier cp_global_trees[CPTI_THIS_IDENTIFIER]
#define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER]
+#define pfn_vflag_identifier cp_global_trees[CPTI_PFN_VFLAG_IDENTIFIER]
#define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER]
#define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER]
/* The name of the std namespace. */
@@ -2618,29 +2620,27 @@ extern int flag_new_for_scope;
/* A pointer-to-function member type looks like:
struct {
- short __delta;
- short __index;
- union {
- P __pfn;
- short __delta2;
- } __pfn_or_delta2;
+ __P __pfn;
+ ptrdiff_t __delta;
};
- where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the
- pointer to member. The fields are used as follows:
+ where P is either a POINTER_TYPE to a METHOD_TYPE appropriate for
+ the pointer to member, or one plus twice the index into the vtable;
+ the two cases are distinguished by looking at the least significant
+ bit of P. When FUNCTION_BOUNDARY is less than 16 (and so it might
+ happen that the function pointer might naturally have the low bit
+ set), the type is instead
- If __INDEX is -1, then the function to call is non-virtual, and
- is located at the address given by __PFN.
-
- If __INDEX is zero, then this a NULL pointer-to-member.
+ struct {
+ __P __pfn;
+ ptrdiff_t __delta;
+ char __vflag;
+ };
- Otherwise, the function to call is virtual. Then, __DELTA2 gives
- the offset from an instance of the object to the virtual function
- table, and __INDEX - 1 is the index into the vtable to use to
- find the function.
+ and __pfn is a pointer to a method when __vflag is zero.
- The value to use for the THIS parameter is the address of the
- object plus __DELTA.
+ In all cases, the value to use for the THIS parameter is the
+ address of the object plus __DELTA / 2 .
For example, given:
@@ -2657,27 +2657,9 @@ extern int flag_new_for_scope;
the pointer-to-member for `&S::f' looks like:
- { 4, -1, { &f__2B2 } };
-
- The `4' means that given an `S*' you have to add 4 bytes to get to
- the address of the `B2*'. Then, the -1 indicates that this is a
- non-virtual function. Of course, `&f__2B2' is the name of that
- function.
-
- (Of course, the exact values may differ depending on the mangling
- scheme, sizes of types, and such.).
-
- Under the new ABI, we do:
-
- struct {
- __P __pfn;
- ptrdiff_t __delta;
- };
+ { &f__2B2, 4, 0 };
- (We don't need DELTA2, because the vtable is always the first thing
- in the object.) If the function is virtual, then PFN is one plus
- twice the index into the vtable; otherwise, it is just a pointer to
- the function. */
+*/
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
@@ -4469,8 +4451,10 @@ extern int cp_type_quals PARAMS ((tree));
extern int cp_has_mutable_p PARAMS ((tree));
extern int at_least_as_qualified_p PARAMS ((tree, tree));
extern int more_qualified_p PARAMS ((tree, tree));
-extern tree build_ptrmemfunc1 PARAMS ((tree, tree, tree));
-extern void expand_ptrmemfunc_cst PARAMS ((tree, tree *, tree *));
+extern tree build_ptrmemfunc1 PARAMS ((tree, tree, tree,
+ tree));
+extern void expand_ptrmemfunc_cst PARAMS ((tree, tree *,
+ tree *, tree *));
extern tree pfn_from_ptrmemfunc PARAMS ((tree));
extern tree type_after_usual_arithmetic_conversions PARAMS ((tree, tree));
extern tree composite_pointer_type PARAMS ((tree, tree, tree, tree,
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 54d84f4..b04206d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6303,6 +6303,7 @@ initialize_predefined_identifiers ()
{ "nelts", &nelts_identifier, 0 },
{ THIS_NAME, &this_identifier, 0 },
{ VTABLE_PFN_NAME, &pfn_identifier, 0 },
+ { "__vflag", &pfn_vflag_identifier, 0 },
{ "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
{ "_vptr", &vptr_identifier, 0 },
{ "__vtt_parm", &vtt_parm_identifier, 0 },
@@ -9156,7 +9157,14 @@ build_ptrmemfunc_type (type)
fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_decl (FIELD_DECL, delta_identifier,
delta_type_node);
- finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
+ if (FUNCTION_BOUNDARY < 16)
+ {
+ fields[2] = build_decl (FIELD_DECL, pfn_vflag_identifier,
+ char_type_node);
+ finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
+ } else {
+ finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
+ }
/* Zap out the name so that the back-end will give us the debugging
information for this anonymous RECORD_TYPE. */
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 6855160f..7163a5b 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -62,9 +62,10 @@ cplus_expand_constant (cst)
{
tree delta;
tree pfn;
+ tree flag;
- expand_ptrmemfunc_cst (cst, &delta, &pfn);
- cst = build_ptrmemfunc1 (type, delta, pfn);
+ expand_ptrmemfunc_cst (cst, &delta, &pfn, &flag);
+ cst = build_ptrmemfunc1 (type, delta, pfn, flag);
}
}
break;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 440955d..6d010d8 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2909,9 +2909,22 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
idx = cp_build_binary_op (TRUNC_DIV_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3),
TYPE_SIZE_UNIT (vtable_entry_type));
- e1 = cp_build_binary_op (BIT_AND_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- integer_one_node);
+ if (FUNCTION_BOUNDARY < 16)
+ {
+ tree delta;
+ tree pfn;
+ if (TREE_CODE (function) == PTRMEM_CST)
+ expand_ptrmemfunc_cst (function, &delta, &pfn, &e1);
+ else
+ e1 = build_component_ref (function, pfn_vflag_identifier,
+ NULL_TREE, 0);
+ }
+ else
+ {
+ e1 = cp_build_binary_op (BIT_AND_EXPR,
+ build1 (NOP_EXPR, vtable_index_type, e3),
+ integer_one_node);
+ }
vtbl = convert_pointer_to (ptr_type_node, instance);
delta = cp_convert (ptrdiff_type_node,
@@ -5995,23 +6008,34 @@ get_delta_difference (from, to, force)
the other components as specified. */
tree
-build_ptrmemfunc1 (type, delta, pfn)
- tree type, delta, pfn;
+build_ptrmemfunc1 (type, delta, pfn, flag)
+ tree type, delta, pfn, flag;
{
tree u = NULL_TREE;
tree delta_field;
tree pfn_field;
+ tree vflag_field;
/* Pull the FIELD_DECLs out of the type. */
pfn_field = TYPE_FIELDS (type);
delta_field = TREE_CHAIN (pfn_field);
+ vflag_field = TREE_CHAIN (delta_field); /* NULL if no such field. */
/* Make sure DELTA has the type we want. */
delta = convert_and_check (delta_type_node, delta);
/* Finish creating the initializer. */
- u = tree_cons (pfn_field, pfn,
- build_tree_list (delta_field, delta));
+ if (FUNCTION_BOUNDARY < 16)
+ {
+ u = tree_cons (pfn_field, pfn,
+ tree_cons (delta_field, delta,
+ build_tree_list (vflag_field, flag)));
+ }
+ else
+ {
+ u = tree_cons (pfn_field, pfn,
+ build_tree_list (delta_field, delta));
+ }
u = build (CONSTRUCTOR, type, NULL_TREE, u);
TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta);
TREE_STATIC (u) = (TREE_CONSTANT (u)
@@ -6047,6 +6071,7 @@ build_ptrmemfunc (type, pfn, force)
{
tree delta = NULL_TREE;
tree npfn = NULL_TREE;
+ tree flag = NULL_TREE;
tree n;
if (!force
@@ -6075,18 +6100,21 @@ build_ptrmemfunc (type, pfn, force)
/* Obtain the function pointer and the current DELTA. */
if (TREE_CODE (pfn) == PTRMEM_CST)
- expand_ptrmemfunc_cst (pfn, &delta, &npfn);
+ expand_ptrmemfunc_cst (pfn, &delta, &npfn, &flag);
else
{
npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0);
delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0);
+ if (FUNCTION_BOUNDARY < 16)
+ flag = build_component_ref (pfn, pfn_vflag_identifier,
+ NULL_TREE, 0);
}
/* Under the new ABI, the conversion is easy. Just adjust
the DELTA field. */
delta = cp_convert (ptrdiff_type_node, delta);
delta = cp_build_binary_op (PLUS_EXPR, delta, n);
- return build_ptrmemfunc1 (to_type, delta, npfn);
+ return build_ptrmemfunc1 (to_type, delta, npfn, flag);
}
/* Handle null pointer to member function conversions. */
@@ -6095,7 +6123,8 @@ build_ptrmemfunc (type, pfn, force)
pfn = build_c_cast (type, integer_zero_node);
return build_ptrmemfunc1 (to_type,
integer_zero_node,
- pfn);
+ pfn,
+ integer_zero_node);
}
if (type_unknown_p (pfn))
@@ -6106,7 +6135,7 @@ build_ptrmemfunc (type, pfn, force)
return make_ptrmem_cst (to_type, fn);
}
-/* Return the DELTA, IDX, PFN, and DELTA2 values for the PTRMEM_CST
+/* Return the DELTA, PFN, and FLAG values for the PTRMEM_CST
given by CST.
??? There is no consistency as to the types returned for the above
@@ -6114,10 +6143,11 @@ build_ptrmemfunc (type, pfn, force)
integer_type_node. */
void
-expand_ptrmemfunc_cst (cst, delta, pfn)
+expand_ptrmemfunc_cst (cst, delta, pfn, flag)
tree cst;
tree *delta;
tree *pfn;
+ tree *flag;
{
tree type = TREE_TYPE (cst);
tree fn = PTRMEM_CST_MEMBER (cst);
@@ -6135,7 +6165,10 @@ expand_ptrmemfunc_cst (cst, delta, pfn)
*delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
if (!DECL_VIRTUAL_P (fn))
- *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
+ {
+ *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
+ *flag = integer_zero_node;
+ }
else
{
/* If we're dealing with a virtual function, we have to adjust 'this'
@@ -6155,6 +6188,7 @@ expand_ptrmemfunc_cst (cst, delta, pfn)
integer_one_node));
*pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
*pfn));
+ *flag = integer_one_node;
}
}
@@ -6169,8 +6203,9 @@ pfn_from_ptrmemfunc (t)
{
tree delta;
tree pfn;
+ tree flag;
- expand_ptrmemfunc_cst (t, &delta, &pfn);
+ expand_ptrmemfunc_cst (t, &delta, &pfn, &flag);
if (pfn)
return pfn;
}