From: Mike Stump Date: Fri, 18 Oct 1996 18:33:44 +0000 (+0000) Subject: 89th Cygnus<->FSF quick merge X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f49422dada8bd589fdee875cda13cc6aa1cfa402;p=gcc.git 89th Cygnus<->FSF quick merge From-SVN: r12978 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 136247a678b..1c95b3b45c3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,33 @@ +Thu Oct 17 11:31:59 1996 Mike Stump + + * 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 + + * 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 + + * 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 * typeck.c (unary_complex_lvalue): Add code to handle intermediate diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index f7265c96124..b6b0105857c 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -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; \ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 304531586eb..60b2cffea73 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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) diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 84196a6b65f..cd40b9a0cec 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 469b529ff58..7c8c28bda78 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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)) { diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 506d64c7284..3351ccba770 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -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); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index af629caf051..84fd6a22365 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 99943e22f0b..f5f502dbfd0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index dfcc28f2b3e..1e09c28e0aa 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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);