+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
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; \
if (fn_fields)
{
+ TYPE_METHODS (t) = fn_fields;
method_vec = finish_struct_methods (t, fn_fields, nonprivate_method);
if (TYPE_HAS_CONSTRUCTOR (t)
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);
|| (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))
{
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);
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,
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:
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);
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);
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. */
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);