aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r--gcc/cp/call.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b8d72f4f348..2ab061426da 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4061,6 +4061,36 @@ enforce_access (tree basetype_path, tree decl)
return true;
}
+/* APPLE LOCAL begin direct-binding-refs turly 20020224 */
+
+/* Should we *really* call a constructor for the object whose reference type
+ we want? If we have a user conversion function which returns the ref
+ type directly, there's no need to call the object's constructor as we
+ can bind directly (dcl.init.ref.)
+
+ These must be exactly the same types. */
+
+static int really_call_constructor_p (tree, tree, tree);
+static int
+really_call_constructor_p (tree expr, tree convfn, tree totype)
+{
+ /* TEMPORARILY DISABLING THIS "FIX" NOW WE HAVE A SOURCE WORKAROUND. */
+ /* However, we'll leave the code here pending input from the FSF
+ on this issue. */
+
+ if (0 /* && ! NEED_TEMPORARY_P (convfn) Watch out! this macro is undefined */
+ && TREE_CODE (expr) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (convfn)) == METHOD_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (convfn))) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_TYPE (convfn)))) == RECORD_TYPE
+ && TREE_TYPE (TREE_TYPE (TREE_TYPE (convfn))) == totype
+ && TREE_TYPE (expr) == totype)
+ return 0;
+
+ return 1;
+}
+/* APPLE LOCAL end direct-binding-refs turly 20020224 */
+
/* Initialize a temporary of type TYPE with EXPR. The FLAGS are a
bitwise or of LOOKUP_* values. If any errors are warnings are
generated, set *DIAGNOSTIC_FN to "error" or "warning",
@@ -4172,6 +4202,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
If the target is a class, that means call a ctor. */
if (IS_AGGR_TYPE (totype)
+ /* APPLE LOCAL direct-binding-refs turly 20020224 */
+ && really_call_constructor_p (expr, convfn, totype)
&& (inner >= 0 || !lvalue_p (expr)))
{
expr = (build_temp
@@ -4812,7 +4844,11 @@ build_over_call (struct z_candidate *cand, int flags)
mark_used (fn);
- if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
+ /* APPLE LOCAL begin -findirect-virtual-calls 2001-10-30 sts */
+ if (DECL_VINDEX (fn)
+ && (flag_indirect_virtual_calls
+ || (flags & LOOKUP_NONVIRTUAL) == 0))
+ /* APPLE LOCAL end -findirect-virtual-calls 2001-10-30 sts */
{
tree t, *p = &TREE_VALUE (converted_args);
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
@@ -4826,6 +4862,33 @@ build_over_call (struct z_candidate *cand, int flags)
t = build_pointer_type (TREE_TYPE (fn));
if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
fn = build_java_interface_fn_ref (fn, *p);
+ /* APPLE LOCAL begin -findirect-virtual-calls 2001-10-30 sts */
+ /* If this is not really supposed to be a virtual call, find the
+ vtable corresponding to the correct type, and use it. */
+ else if (flags & LOOKUP_NONVIRTUAL) {
+ tree call_site_type = TREE_TYPE (cand->access_path);
+ tree fn_class_type = DECL_CLASS_CONTEXT (fn);
+
+ my_friendly_assert (call_site_type != NULL &&
+ fn_class_type != NULL &&
+ AGGREGATE_TYPE_P (call_site_type) &&
+ AGGREGATE_TYPE_P (fn_class_type),
+ 20020717);
+ my_friendly_assert(lookup_base(TYPE_MAIN_VARIANT (call_site_type),
+ TYPE_MAIN_VARIANT (fn_class_type),
+ ba_any | ba_quiet,
+ NULL) != NULL,
+ 20020719);
+
+ if (TYPE_USES_MULTIPLE_INHERITANCE (call_site_type)
+ || TYPE_USES_VIRTUAL_BASECLASSES (call_site_type))
+ error ("indirect virtual calls are invalid for a type that uses multiple or virtual inheritance");
+
+ fn = (build_vfn_ref_using_vtable
+ (BINFO_VTABLE (TYPE_BINFO (call_site_type)),
+ DECL_VINDEX (fn)));
+ }
+ /* APPLE LOCAL end -findirect-virtual-calls 2001-10-30 sts */
else
fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
TREE_TYPE (fn) = t;