aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/typeck.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/typeck.c')
-rw-r--r--gcc/cp/typeck.c325
1 files changed, 306 insertions, 19 deletions
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e0dc1ebdb49..ccb8d771e28 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -530,10 +530,16 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
class1 = TREE_TYPE (t1);
class2 = TREE_TYPE (t2);
- if (DERIVED_FROM_P (class1, class2))
+ /* APPLE LOCAL begin Objective-C++ */
+ if (DERIVED_FROM_P (class1, class2) ||
+ (c_dialect_objc () && objc_comptypes (class1, class2, 0) == 1))
+ /* APPLE LOCAL end Objective-C++ */
t2 = (build_pointer_type
(cp_build_qualified_type (class1, TYPE_QUALS (class2))));
- else if (DERIVED_FROM_P (class2, class1))
+ /* APPLE LOCAL begin Objective-C++ */
+ else if (DERIVED_FROM_P (class2, class1) ||
+ (c_dialect_objc () && objc_comptypes (class2, class1, 0) == 1))
+ /* APPLE LOCAL end Objective-C++ */
t1 = (build_pointer_type
(cp_build_qualified_type (class2, TYPE_QUALS (class1))));
else
@@ -1847,6 +1853,12 @@ finish_class_member_access_expr (tree object, tree name)
if (object == error_mark_node || name == error_mark_node)
return error_mark_node;
+ /* APPLE LOCAL begin Objective-C++ */
+ /* If OBJECT is an ObjC class instance, we must obey ObjC access rules. */
+ if (!objc_is_public (object, name))
+ return error_mark_node;
+ /* APPLE LOCAL end Objective-C++ */
+
object_type = TREE_TYPE (object);
if (processing_template_decl)
@@ -2006,6 +2018,8 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
routine directly because it expects the object to be of class
type. */
ptrmem_type = TREE_TYPE (ptrmem);
+ /* APPLE LOCAL KEXT 2.95-ptmf-compatibility --turly */
+ if (!flag_apple_kext)
gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type));
member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
/*want_type=*/false);
@@ -2289,7 +2303,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
- tree idx, delta, e1, e2, e3, vtbl, basetype;
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ tree idx, delta, e1, e2, e3, vtbl = vtbl, basetype;
+ tree delta2 = delta2;
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree instance_ptr = *instance_ptrptr;
@@ -2321,6 +2338,17 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* Start by extracting all the information from the PMF itself. */
e3 = pfn_from_ptrmemfunc (function);
delta = build_ptrmemfunc_access_expr (function, delta_identifier);
+
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ idx = build_ptrmemfunc_access_expr (function, index_identifier);
+ idx = save_expr (default_conversion (idx));
+ e1 = cp_build_binary_op (GE_EXPR, idx, integer_zero_node);
+ }
+ else
+ {
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
@@ -2338,6 +2366,19 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
gcc_unreachable ();
}
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ }
+ /* DELTA2 is the amount by which to adjust the `this' pointer
+ to find the vtbl. */
+ if (flag_apple_kext)
+ {
+ delta2 = build_ptrmemfunc_access_expr (function,
+ pfn_or_delta2_identifier);
+ delta2 = build_ptrmemfunc_access_expr (delta2,
+ delta2_identifier);
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* Convert down to the right base before using the instance. First
use the type... */
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
@@ -2346,6 +2387,14 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, 1);
if (instance_ptr == error_mark_node)
return error_mark_node;
+
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ /* Next extract the vtable pointer from the object. */
+ vtbl = build (PLUS_EXPR,build_pointer_type (vtbl_ptr_type_node),
+ instance_ptr, cp_convert (ptrdiff_type_node, delta2));
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* ...and then the delta in the PMF. */
instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
@@ -2353,11 +2402,22 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* Hand back the adjusted 'this' argument to our caller. */
*instance_ptrptr = instance_ptr;
+ /* APPLE LOCAL KEXT 2.95-ptmf-compatibility --turly */
+ if (!flag_apple_kext)
/* Next extract the vtable pointer from the object. */
vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
instance_ptr);
vtbl = build_indirect_ref (vtbl, NULL);
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ /* 2.95-style indices are off by one. */
+ if (flag_apple_kext)
+ {
+ idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node);
+ idx = cp_build_binary_op (LSHIFT_EXPR, idx, integer_two_node);
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* Finally, extract the function pointer from the vtable. */
e2 = fold (build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
e2 = build_indirect_ref (e2, NULL);
@@ -2393,6 +2453,12 @@ build_function_call (tree function, tree params)
int is_method;
tree original = function;
+ /* APPLE LOCAL begin Radar 4055183 */
+ /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
+ expressions, like those used for ObjC messenger dispatches. */
+ function = objc_rewrite_function_call (function, params);
+
+ /* APPLE LOCAL end Radar 4055183 */
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context. */
if (TREE_CODE (function) == NOP_EXPR
@@ -2653,6 +2719,13 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2,
tree orig_arg2;
tree expr;
+ /* APPLE LOCAL begin CW asm blocks */
+ if (inside_cw_asm_block
+ && (TREE_CODE (arg1) == IDENTIFIER_NODE
+ || TREE_CODE (arg2) == IDENTIFIER_NODE))
+ return error_mark_node;
+ /* APPLE LOCAL end CW asm blocks */
+
orig_arg1 = arg1;
orig_arg2 = arg2;
@@ -3016,6 +3089,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
}
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ /* Shouldn't we use INDEX here rather than PFN? This seems to
+ work fine, though... */
+ if (flag_apple_kext)
+ op0 = build_ptrmemfunc_access_expr (op0, index_identifier);
+ else
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
result_type = TREE_TYPE (op0);
@@ -3910,9 +3990,12 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
}
/* Complain about anything else that is not a true lvalue. */
- if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? lv_increment : lv_decrement)))
+ /* APPLE LOCAL begin non-lvalue assign */
+ if (!lvalue_or_else (&arg, ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? lv_increment
+ : lv_decrement)))
+ /* APPLE LOCAL end non-lvalue assign */
return error_mark_node;
/* Forbid using -- on `bool'. */
@@ -4056,7 +4139,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
is an error. */
else if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE
- && !lvalue_or_else (arg, lv_addressof))
+ /* APPLE LOCAL non-lvalue assign */
+ && !lvalue_or_else (&arg, lv_addressof))
return error_mark_node;
if (argtype != error_mark_node)
@@ -4429,8 +4513,12 @@ build_x_compound_expr (tree op1, tree op2)
tree
build_compound_expr (tree lhs, tree rhs)
{
- lhs = convert_to_void (lhs, "left-hand operand of comma");
-
+ /* APPLE LOCAL begin AltiVec */
+ lhs = convert_to_void (lhs, targetm.cast_expr_as_vector_init
+ ? NULL
+ : "left-hand operand of comma");
+ /* APPLE LOCAL end AltiVec */
+
if (lhs == error_mark_node || rhs == error_mark_node)
return error_mark_node;
@@ -4636,13 +4724,17 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
promotions, floating point promotion, integral conversions,
floating point conversions, floating-integral conversions,
pointer conversions, and pointer to member conversions. */
- if ((ARITHMETIC_TYPE_P (type) && ARITHMETIC_TYPE_P (intype))
- /* DR 128
-
- A value of integral _or enumeration_ type can be explicitly
- converted to an enumeration type. */
- || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
- && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
+/* APPLE LOCAL begin mainline 4.0 2005-03-25 */
+ /* DR 128
+
+ A value of integral _or enumeration_ type can be explicitly
+ converted to an enumeration type. */
+ /* The effect of all that is that any conversion between any two
+ types which are integral, floating, or enumeration types can be
+ performed. */
+ if ((INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type))
+ && (INTEGRAL_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype)))
+/* APPLE LOCAL end mainline 4.0 2005-03-25 */
{
expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
@@ -4747,6 +4839,13 @@ build_static_cast (tree type, tree expr)
return convert_from_reference (expr);
}
+ /* APPLE LOCAL begin AltiVec */
+ /* If we are casting to a vector type, treat the expression as a vector
+ initializer if this target supports it. */
+ if (TREE_CODE (type) == VECTOR_TYPE && targetm.cast_expr_as_vector_init)
+ return vector_constructor_from_expr (expr, type);
+ /* APPLE LOCAL end AltiVec */
+
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
if (TREE_CODE (type) != REFERENCE_TYPE
@@ -4779,6 +4878,20 @@ convert_member_func_to_ptr (tree type, tree expr)
gcc_assert (TYPE_PTRMEMFUNC_P (intype)
|| TREE_CODE (intype) == METHOD_TYPE);
+ /* APPLE LOCAL begin kext ptmf casts --bowdidge*/
+ /* Beginning in gcc-4.0, casts from pointer-to-member-function to pointer-to-
+ function should always be done with the OSMemberFunctionCast() to guarantee
+ the 2.95 behavior. Casts the "old fashioned way" should be flagged as
+ errors so developers won't have kexts that silently use the new
+ ptmf->pmf behavior and get a different function than 3.3. */
+
+ if (flag_apple_kext)
+ {
+ error ("converting from `%T' to `%T' in a kext. Use OSMemberFunctionCast() instead.", intype, type);
+ return error_mark_node;
+ }
+ /* APPLE LOCAL end kext ptmf casts */
+
if (pedantic || warn_pmf2ptr)
pedwarn ("converting from %qT to %qT", intype, type);
@@ -4937,6 +5050,14 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
error ("invalid cast from type %qT to type %qT", intype, type);
return error_mark_node;
}
+
+ /* APPLE LOCAL begin don't sign-extend pointers cast to integers */
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TREE_CODE (intype) == POINTER_TYPE
+ && TYPE_PRECISION (type) > TYPE_PRECISION (intype)
+ && TYPE_UNSIGNED (type))
+ expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 1), expr);
+ /* APPLE LOCAL end don't sign-extend pointers cast to integers */
return cp_convert (type, expr);
}
@@ -4958,6 +5079,13 @@ build_reinterpret_cast (tree type, tree expr)
return convert_from_reference (t);
}
+ /* APPLE LOCAL begin AltiVec */
+ /* If we are casting to a vector type, treat the expression as a vector
+ initializer if this target supports it. */
+ if (TREE_CODE (type) == VECTOR_TYPE && targetm.cast_expr_as_vector_init)
+ return vector_constructor_from_expr (expr, type);
+ /* APPLE LOCAL end AltiVec */
+
return build_reinterpret_cast_1 (type, expr, /*c_cast_p=*/false,
/*valid_p=*/NULL);
}
@@ -5112,6 +5240,15 @@ build_c_cast (tree type, tree expr)
return convert_from_reference (t);
}
+ /* APPLE LOCAL begin AltiVec */
+ /* If we are casting to a vector type, treat the expression as a vector
+ initializer if this target supports it. */
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && targetm.cast_expr_as_vector_init
+ && !IS_AGGR_TYPE (TREE_TYPE(expr)))
+ return vector_constructor_from_expr (expr, type);
+ /* APPLE LOCAL end AltiVec */
+
/* Casts to a (pointer to a) specific ObjC class (or 'id' or
'Class') should always be retained, because this information aids
in method lookup. */
@@ -5252,7 +5389,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
case MAX_EXPR:
/* MIN_EXPR and MAX_EXPR are currently only permitted as lvalues,
when neither operand has side-effects. */
- if (!lvalue_or_else (lhs, lv_assign))
+ /* APPLE LOCAL non-lvalue assign */
+ if (!lvalue_or_else (&lhs, lv_assign))
return error_mark_node;
gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))
@@ -5280,7 +5418,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
/* Check this here to avoid odd errors when trying to convert
a throw to the type of the COND_EXPR. */
- if (!lvalue_or_else (lhs, lv_assign))
+ /* APPLE LOCAL non-lvalue assign */
+ if (!lvalue_or_else (&lhs, lv_assign))
return error_mark_node;
cond = build_conditional_expr
@@ -5374,7 +5513,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
}
/* The left-hand side must be an lvalue. */
- if (!lvalue_or_else (lhs, lv_assign))
+ /* APPLE LOCAL non-lvalue assign */
+ if (!lvalue_or_else (&lhs, lv_assign))
return error_mark_node;
/* Warn about modifying something that is `const'. Don't warn if
@@ -5476,6 +5616,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
if (newrhs == error_mark_node)
return error_mark_node;
+ /* APPLE LOCAL begin ObjC GC */
+ if (c_dialect_objc () && flag_objc_gc)
+ {
+ result = objc_generate_write_barrier (lhs, modifycode, newrhs);
+
+ if (result)
+ return result;
+ }
+ /* APPLE LOCAL end ObjC GC */
+
result = build2 (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
lhstype, lhs, newrhs);
@@ -5603,6 +5753,114 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
tree delta_field;
tree pfn_field;
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ /* Ooo-err, Missus. Cons up a 2.95-style ptmf struct given
+ gcc3-style inputs! Recall:
+
+ struct ptmf2 { struct ptmf3 {
+ short __delta; __P __pfn;
+ short __index; ptrdiff_t __delta;
+ union { }
+ __P __pfn;
+ short __delta2;
+ }
+ }
+
+ Won't this be fun. Much of this is snarfed from 2.95.
+ Note that the __delta2 val, if required, will always be __delta. */
+
+ tree subtype, pfn_or_delta2_field, idx, idx_field, delta2_field;
+ tree delta2 = integer_zero_node;
+ int ixval = 0;
+ int allconstant = 0, allsimple = 0, allinvariant = 0;
+
+ delta_field = TYPE_FIELDS (type);
+ idx_field = TREE_CHAIN (delta_field);
+ pfn_or_delta2_field = TREE_CHAIN (idx_field);
+ subtype = TREE_TYPE (pfn_or_delta2_field);
+ pfn_field = TYPE_FIELDS (subtype);
+ delta2_field = TREE_CHAIN (pfn_field);
+
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
+ {
+ /* If the low bit of PFN is set, the virtual index is PFN >> 1.
+ Else it's nonvirtual. */
+ allconstant = TREE_CONSTANT (pfn);
+ allinvariant = TREE_INVARIANT (pfn);
+ allsimple = !! initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
+ if (TREE_CODE (pfn) == INTEGER_CST && (TREE_INT_CST_LOW (pfn) & 1))
+ {
+ /* It's a virtual function. PFN is the vt offset + 1. */
+
+ int vt_entry_sz = 4;
+ tree vt_entry_sz_tree = TYPE_SIZE_UNIT (vtable_entry_type);
+ if (TREE_CODE (vt_entry_sz_tree) == INTEGER_CST)
+ vt_entry_sz = TREE_INT_CST_LOW (vt_entry_sz_tree);
+
+ ixval = (TREE_INT_CST_LOW (pfn) - 1);
+ ixval /= vt_entry_sz;
+
+ /* Now add 2 for that spadgey VPTR index hack, plus one because
+ 2.95 indices are offset by 1. */
+ ixval += 2 + 1;
+
+ /* __delta2 is the same as __delta. */
+ u = tree_cons (delta2_field, delta, NULL_TREE);
+ }
+ else
+ if (TREE_CODE (pfn) == INTEGER_CST && TREE_INT_CST_LOW (pfn) == 0)
+ {
+ /* NULL pfn. Just zero out everything. */
+ ixval = 0;
+ pfn = integer_zero_node;
+ delta = integer_zero_node;
+ u = tree_cons (pfn_field, pfn, NULL_TREE);
+ }
+ else
+ {
+ ixval = -1; /* -1 ==> PFN is the pointer */
+ u = tree_cons (pfn_field, pfn, NULL_TREE);
+ }
+ }
+ else /* Low bit of DELTA is set if we're virtual. */
+ {
+ /* Don't know how to do this yet. Much like the above, probably. */
+ abort ();
+ allconstant = TREE_CONSTANT (delta);
+ allinvariant = TREE_INVARIANT (delta);
+ allsimple = !! initializer_constant_valid_p (delta,
+ TREE_TYPE (delta));
+
+ u = tree_cons (delta2_field, delta2, NULL_TREE);
+ }
+
+ delta = convert_and_check (delta_type_node, delta);
+ idx = convert_and_check (delta_type_node, ssize_int (ixval));
+
+ u = build_constructor (subtype, u);
+ TREE_CONSTANT (u) = allconstant;
+ TREE_INVARIANT (u) = allinvariant;
+ TREE_STATIC (u) = allconstant && allsimple;
+
+ allconstant = allconstant && TREE_CONSTANT (delta) && TREE_CONSTANT (idx);
+ allinvariant = allinvariant && TREE_INVARIANT (delta) && TREE_INVARIANT (idx);
+ allsimple = allsimple
+ && initializer_constant_valid_p (delta, TREE_TYPE (delta))
+ && initializer_constant_valid_p (idx, TREE_TYPE (idx));
+
+ u = tree_cons (delta_field, delta,
+ tree_cons (idx_field, idx,
+ tree_cons (pfn_or_delta2_field, u, NULL_TREE)));
+ u = build_constructor (type, u);
+ TREE_CONSTANT (u) = allconstant;
+ TREE_INVARIANT (u) = allinvariant;
+ TREE_STATIC (u) = allconstant && allsimple;
+ return u;
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* Pull the FIELD_DECLs out of the type. */
pfn_field = TYPE_FIELDS (type);
delta_field = TREE_CHAIN (pfn_field);
@@ -5794,6 +6052,22 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
tree
pfn_from_ptrmemfunc (tree t)
{
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree fn = PTRMEM_CST_MEMBER (t);
+ if (!DECL_VIRTUAL_P (fn))
+ return convert (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)),
+ build_addr_func (fn));
+ }
+
+ t = build_ptrmemfunc_access_expr (t, pfn_or_delta2_identifier);
+ return build_ptrmemfunc_access_expr (t, pfn_identifier);
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
if (TREE_CODE (t) == PTRMEM_CST)
{
tree delta;
@@ -6500,3 +6774,16 @@ non_reference (tree t)
t = TREE_TYPE (t);
return t;
}
+
+/* APPLE LOCAL begin CW asm blocks */
+tree
+cw_asm_cp_build_component_ref (tree datum, tree component)
+{
+ tree expr = finish_class_member_access_expr (datum, component);
+ /* If this is not a real component reference, extract the field
+ decl, which includes the numeric offset we'll use later. */
+ if (TREE_CODE (datum) == TYPE_DECL)
+ expr = TREE_OPERAND (expr, 1);
+ return expr;
+}
+/* APPLE LOCAL end CW asm blocks */