Commit f49422da by Mike Stump

89th Cygnus<->FSF quick merge

From-SVN: r12978
parent 170e0690
Thu Oct 17 11:31:59 1996 Mike Stump <mrs@cygnus.com>
* cvt.c (convert_to_pointer_force): Add code to support pointer to
member function to pointer to function conversions.
* init.c (resolve_offset_ref): Add code to allow faked up objects,
ignoring them if they are not used, and giving an error, if they
are needed.
* typeck.c (get_member_function_from_ptrfunc): Fold e1 to improve
code, and so that we can give an error, if we needed an object,
and one was not provided.
(build_c_cast): Don't call default_conversion when we want to
convert to pointer to function from a METHOD_TYPE.
Mon Oct 14 00:28:51 1996 Jason Merrill <jason@yorick.cygnus.com>
* Make-lang.in (cplib2.ready): Fix logic.
* decl.c (shadow_tag): Only complain about non-artificial function
members.
* class.c (finish_struct_1): Add synthesized methods to TYPE_METHODS.
Fri Oct 11 16:12:40 1996 Jason Merrill <jason@yorick.cygnus.com>
* expr.c (cplus_expand_expr): Pre-tweak call_target like
expand_inline_function would.
* pt.c (mark_decl_instantiated): If extern_p, call
mark_inline_for_output.
Thu Oct 10 15:58:08 1996 Mike Stump <mrs@cygnus.com>
* typeck.c (unary_complex_lvalue): Add code to handle intermediate
......
......@@ -146,7 +146,7 @@ cplib2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs
else \
echo "" > cplib2.new; \
fi; \
if cmp -s cplib2.new cplib2.txt; then \
if cmp -s cplib2.new cplib2.txt; then true; else \
touch cplib2.ready; \
fi; \
rm -f cplib2.new; \
......
......@@ -3635,6 +3635,7 @@ finish_struct_1 (t, warn_anon)
if (fn_fields)
{
TYPE_METHODS (t) = fn_fields;
method_vec = finish_struct_methods (t, fn_fields, nonprivate_method);
if (TYPE_HAS_CONSTRUCTOR (t)
......
......@@ -282,6 +282,44 @@ convert_to_pointer_force (type, expr)
form = TREE_CODE (intype);
}
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
/* Allow an implicit this pointer for pointer to member
functions. */
if (TYPE_PTRMEMFUNC_P (intype))
{
tree decl, basebinfo;
tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
tree t = TYPE_METHOD_BASETYPE (fntype);
if (current_class_type == 0
|| get_base_distance (t, current_class_type, 0, &basebinfo) == -1)
{
decl = build1 (NOP_EXPR, t, error_mark_node);
}
else if (current_class_ptr == 0)
decl = build1 (NOP_EXPR, t, error_mark_node);
else
decl = current_class_ref;
expr = build (OFFSET_REF, fntype, decl, expr);
intype = TREE_TYPE (expr);
}
if (TREE_CODE (expr) == OFFSET_REF && TREE_CODE (intype) == METHOD_TYPE)
expr = resolve_offset_ref (expr);
if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
expr = build_addr_func (expr);
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
{
if (pedantic
&& TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE)
cp_pedwarn ("cannot convert `%T' to `%T'", intype, type);
return build1 (NOP_EXPR, type, expr);
}
}
if (form == POINTER_TYPE)
{
intype = TYPE_MAIN_VARIANT (intype);
......
......@@ -5647,10 +5647,16 @@ shadow_tag (declspecs)
|| (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
{
tree fn;
/* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
function members. */
if (TYPE_METHODS (t))
error ("an anonymous union cannot have function members");
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
if (! DECL_ARTIFICIAL (fn))
{
error ("an anonymous union cannot have function members");
break;
}
if (TYPE_FIELDS (t))
{
......
......@@ -137,6 +137,18 @@ cplus_expand_expr (exp, target, tmode, modifier)
result. The assumptions are true only if the address was
valid to begin with. */
call_target = validize_mem (call_target);
/* If this is a reference to a symbol, expand_inline_function
will do this transformation and return a different target
than the one we gave it, though functionally equivalent. Do
the transformation here to avoid confusion. */
if (! cse_not_expected && GET_CODE (call_target) == MEM
&& GET_CODE (XEXP (call_target, 0)) == SYMBOL_REF)
{
call_target = gen_rtx
(MEM, mode, memory_address (mode, XEXP (call_target, 0)));
MEM_IN_STRUCT_P (call_target) = 1;
}
}
call_exp = build (CALL_EXPR, type, func, args, NULL_TREE);
......
......@@ -2082,14 +2082,27 @@ resolve_offset_ref (exp)
my_friendly_abort (55);
}
/* If this is a reference to a member function, then return
the address of the member function (which may involve going
through the object's vtable), otherwise, return an expression
for the dereferenced pointer-to-member construct. */
addr = build_unary_op (ADDR_EXPR, base, 0);
/* Ensure that we have an object. */
if (TREE_CODE (base) == NOP_EXPR
&& TREE_OPERAND (base, 0) == error_mark_node)
addr = error_mark_node;
else
{
/* If this is a reference to a member function, then return the
address of the member function (which may involve going
through the object's vtable), otherwise, return an expression
for the dereferenced pointer-to-member construct. */
addr = build_unary_op (ADDR_EXPR, base, 0);
}
if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
{
if (addr == error_mark_node)
{
cp_error ("object missing in `%E'", exp);
return error_mark_node;
}
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
addr = convert_pointer_to (basetype, addr);
member = convert (ptrdiff_type_node,
......
......@@ -2858,6 +2858,8 @@ mark_decl_instantiated (result, extern_p)
DECL_INTERFACE_KNOWN (result) = 1;
DECL_NOT_REALLY_EXTERN (result) = 1;
}
else if (TREE_CODE (result) == FUNCTION_DECL)
mark_inline_for_output (result);
}
/* Given two function templates PAT1 and PAT2, return:
......
......@@ -2463,8 +2463,8 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
idx = save_expr (build_component_ref (function,
index_identifier,
NULL_TREE, 0));
e1 = build (GT_EXPR, boolean_type_node, idx,
convert (delta_type_node, integer_zero_node));
e1 = fold (build (GT_EXPR, boolean_type_node, idx,
convert (delta_type_node, integer_zero_node)));
delta = convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier, NULL_TREE, 0));
delta2 = DELTA2_FROM_PTRMEMFUNC (function);
......@@ -2473,7 +2473,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
instance
= convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
instance_ptr);
if (instance == error_mark_node)
if (instance == error_mark_node && instance_ptr != error_mark_node)
return instance;
vtbl = convert_pointer_to (ptr_type_node, instance);
......@@ -2503,7 +2503,14 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (e3);
function = build_conditional_expr (e1, e2, e3);
e1 = build_conditional_expr (e1, e2, e3);
if (instance_ptr == error_mark_node
&& TREE_CODE (e1) != ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
cp_error ("object missing in `%E'", function);
function = e1;
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
......@@ -5408,7 +5415,11 @@ build_c_cast (type, expr, allow_nonconverting)
convert references to their expanded types,
but don't convert any other types. */
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
|| (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
/* Don't do the default conversion if we want a
pointer to a function. */
&& TREE_CODE (type) != POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
|| TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
value = default_conversion (value);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment