summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-23 00:26:04 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-23 00:26:04 +0000
commit215e2f1d86a587308fdbde512bb2f228ba224ae9 (patch)
tree0be6b0f8e11f86590d8a53628df5d2776497a29c /gcc/cp
parentf09f2d78d2d06c18635dec7e3cc6c103fd174eee (diff)
downloadgcc-215e2f1d86a587308fdbde512bb2f228ba224ae9.tar.gz
* tree.def (VTABLE_REF): Remove.
(OBJ_TYPE_REF): New. (TRY_CATCH_EXPR, TRY_FINALLY_EXPR): Set type 's'. * expr.c (expand_expr_real_1): Replace VTABLE_REF with OBJ_TYPE_REF. * fold-const.c (non_lvalue): Likewise. * gimplify.c (gimplify_expr): Likewise. (gimplify_call_expr): Use is_gimple_call_addr. * langhooks-def.h (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New. * langhooks.h (fold_obj_type_ref): New. * tree-gimple.c (is_gimple_call_addr): New. * tree-gimple.h (is_gimple_call_addr): Declare. * tree-inline.c (inlinable_function_p): Fix merge error. (estimate_num_insns_1): Replace VTABLE_REF with OBJ_TYPE_REF. * tree-pretty-print.c (dump_generic_node): Likewise. (print_call_name): Handle OBJ_TYPE_REF. * tree-ssa-ccp.c (fold_stmt): Fold OBJ_TYPE_REF. * tree-ssa-operands.c (get_expr_operands): Handle OBJ_TYPE_REF. * tree.h (OBJ_TYPE_REF_EXPR): New. (OBJ_TYPE_REF_OBJECT, OBJ_TYPE_REF_TOKEN): New. * doc/c-tree.texi (VTABLE_REF): Remove. * objc/objc-act.c (build_objc_method_call): Build an OBJ_TYPE_REF. cp/ * class.c (build_vfn_ref): Take a pointer not object. Build an OBJ_TYPE_REF. (cp_fold_obj_type_ref): New. * call.c (build_over_call): Update build_vfn_ref call. * cp-lang.c (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New. * cp-tree.h (cp_fold_obj_type_ref): Declare. testsuite/ * g++.dg/opt/devirt1.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83531 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/class.c41
-rw-r--r--gcc/cp/cp-lang.c2
-rw-r--r--gcc/cp/cp-tree.h1
5 files changed, 50 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1f2eda9b6a0..f67eb221408 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2004-06-22 Richard Henderson <rth@redhat.com>
+
+ * class.c (build_vfn_ref): Take a pointer not object. Build
+ an OBJ_TYPE_REF.
+ (cp_fold_obj_type_ref): New.
+ * call.c (build_over_call): Update build_vfn_ref call.
+ * cp-lang.c (LANG_HOOKS_FOLD_OBJ_TYPE_REF): New.
+ * cp-tree.h (cp_fold_obj_type_ref): Declare.
+
2004-06-21 Jason Merrill <jason@redhat.com>
PR c++/16112
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 0c247b8127a..2a659cce1ef 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4835,7 +4835,7 @@ build_over_call (struct z_candidate *cand, int flags)
if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
fn = build_java_interface_fn_ref (fn, *p);
else
- fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
+ fn = build_vfn_ref (*p, DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
}
else if (DECL_INLINE (fn))
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1853d4faadf..d58577f496f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -542,13 +542,15 @@ build_vtbl_ref (tree instance, tree idx)
return aref;
}
-/* Given an object INSTANCE, return an expression which yields a
- function pointer corresponding to vtable element INDEX. */
+/* Given a stable object pointer INSTANCE_PTR, return an expression which
+ yields a function pointer corresponding to vtable element INDEX. */
tree
-build_vfn_ref (tree instance, tree idx)
+build_vfn_ref (tree instance_ptr, tree idx)
{
- tree aref = build_vtbl_ref_1 (instance, idx);
+ tree aref;
+
+ aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx);
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
@@ -556,6 +558,9 @@ build_vfn_ref (tree instance, tree idx)
aref = build1 (NOP_EXPR, TREE_TYPE (aref),
build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
+ /* Remember this as a method reference, for later devirtualization. */
+ aref = build (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
+
return aref;
}
@@ -7912,3 +7917,31 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}
+
+/* Fold a OBJ_TYPE_REF expression to the address of a function.
+ KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF). */
+
+tree
+cp_fold_obj_type_ref (tree ref, tree known_type)
+{
+ HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+ HOST_WIDE_INT i = 0;
+ tree v = TYPE_BINFO_VIRTUALS (known_type);
+ tree fndecl;
+
+ while (i != index)
+ {
+ i += (TARGET_VTABLE_USES_DESCRIPTORS
+ ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
+ v = TREE_CHAIN (v);
+ }
+
+ fndecl = BV_FN (v);
+
+#ifdef ENABLE_CHECKING
+ if (!tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), DECL_VINDEX (fndecl)))
+ abort ();
+#endif
+
+ return build_address (fndecl);
+}
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 757ca08e845..5af5b97333d 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -182,6 +182,8 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
+#undef LANG_HOOKS_FOLD_OBJ_TYPE_REF
+#define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref
/* Each front end provides its own hooks, for toplev.c. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e29e084e0bb..36d98c60195 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3678,6 +3678,7 @@ extern tree get_vtt_name (tree);
extern tree get_primary_binfo (tree);
extern void debug_class (tree);
extern void debug_thunks (tree);
+extern tree cp_fold_obj_type_ref (tree, tree);
/* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree);