From 691c003dccd336c1350119b2f7d4b54c46e2a5fb Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 31 Oct 1996 17:08:58 +0000 Subject: [PATCH] 90th Cygnus<->FSF quick merge From-SVN: r13082 --- gcc/cp/ChangeLog | 28 ++++++++ gcc/cp/call.c | 4 +- gcc/cp/class.c | 21 ++++-- gcc/cp/decl2.c | 3 + gcc/cp/typeck.c | 182 ++++++++++++++--------------------------------- 5 files changed, 101 insertions(+), 137 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1c95b3b45c3..b5cf22ac60b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,31 @@ +Mon Oct 28 12:45:05 1996 Jeffrey A Law (law@cygnus.com) + + * typeck.c (signed_or_unsigned_type): If the given type already + as the correct signedness, then just return it. + + * typeck.c ({un,}signed_type): If can't do anything, call + signed_or_unsigned_type. + +Thu Oct 24 14:21:59 1996 Bob Manson + + * decl2.c (copy_assignment_arg_p): Don't buy the farm if + current_class_type is NULL. + +Wed Oct 23 00:43:10 1996 Jason Merrill + + * class.c (finish_struct_1): Avoid empty structs by adding a field + so layout_type gets the mode right. + + * typeck.c (c_expand_return): Drastically simplify. + +Mon Oct 21 22:34:02 1996 Jason Merrill + + * typeck.c (decay_conversion): Handle overloaded methods. + +Fri Oct 18 16:03:48 1996 Jason Merrill + + * call.c (build_over_call): A TARGET_EXPR has side-effects. + Thu Oct 17 11:31:59 1996 Mike Stump * cvt.c (convert_to_pointer_force): Add code to support pointer to diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9ae201c9313..80258c0fc61 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5099,7 +5099,9 @@ build_over_call (fn, convs, args, flags) { val = build (VAR_DECL, DECL_CONTEXT (fn)); layout_decl (val, 0); - return build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0); + val = build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0); + TREE_SIDE_EFFECTS (val) = 1; + return val; } } else if (! real_lvalue_p (arg) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 60b2cffea73..28391dc7cb2 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3051,6 +3051,7 @@ finish_struct_1 (t, warn_anon) tree t_binfo = TYPE_BINFO (t); tree access_decls = NULL_TREE; int aggregate = 1; + int empty = 1; if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) pedwarn ("anonymous class type not used to declare any objects"); @@ -3215,7 +3216,10 @@ finish_struct_1 (t, warn_anon) GNU_xref_member (current_class_name, x); if (TREE_CODE (x) == FIELD_DECL) - DECL_PACKED (x) |= TYPE_PACKED (t); + { + DECL_PACKED (x) |= TYPE_PACKED (t); + empty = 0; + } /* Handle access declarations. */ if (TREE_CODE (x) == USING_DECL) @@ -3767,6 +3771,7 @@ finish_struct_1 (t, warn_anon) else fields = vfield; #endif + empty = 0; vfields = chainon (vfields, CLASSTYPE_AS_LIST (t)); } @@ -3836,18 +3841,22 @@ finish_struct_1 (t, warn_anon) /* Don't re-use old size. */ DECL_SIZE (base_layout_decl) = NULL_TREE; } + else if (empty) + { + /* C++: do not let empty structures exist. */ + tree decl = build_lang_field_decl + (FIELD_DECL, NULL_TREE, char_type_node); + TREE_CHAIN (decl) = TYPE_FIELDS (t); + TYPE_FIELDS (t) = decl; + } layout_type (t); finish_struct_anon (t); - if (n_baseclasses) + if (n_baseclasses || empty) TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t)); - /* C++: do not let empty structures exist. */ - if (integer_zerop (TYPE_SIZE (t))) - TYPE_SIZE (t) = TYPE_SIZE (char_type_node); - /* Set the TYPE_DECL for this type to contain the right value for DECL_OFFSET, so that we can use it as part of a COMPONENT_REF for multiple inheritance. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0775bb2bba0..4bd06a36fdc 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1672,6 +1672,9 @@ copy_assignment_arg_p (parmtype, virtualp) tree parmtype; int virtualp; { + if (current_class_type == NULL_TREE) + return 0; + if (TREE_CODE (parmtype) == REFERENCE_TYPE) parmtype = TREE_TYPE (parmtype); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 1e09c28e0aa..4c876f6304a 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1210,7 +1210,8 @@ unsigned_type (type) return unsigned_intHI_type_node; if (type1 == intQI_type_node) return unsigned_intQI_type_node; - return type; + + return signed_or_unsigned_type (1, type); } /* Return a signed type the same as TYPE in other respects. */ @@ -1238,7 +1239,8 @@ signed_type (type) return intHI_type_node; if (type1 == unsigned_intQI_type_node) return intQI_type_node; - return type; + + return signed_or_unsigned_type (0, type); } /* Return a type the same as TYPE except unsigned or @@ -1249,8 +1251,10 @@ signed_or_unsigned_type (unsignedp, type) int unsignedp; tree type; { - if (! INTEGRAL_TYPE_P (type)) + if (! INTEGRAL_TYPE_P (type) + || TREE_UNSIGNED (type) == unsignedp) return type; + if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) @@ -1445,6 +1449,12 @@ decay_conversion (exp) type = TREE_TYPE (type); code = TREE_CODE (type); + + if (type == unknown_type_node) + { + cp_pedwarn ("assuming & on overloaded member function"); + return build_unary_op (ADDR_EXPR, exp, 0); + } } if (code == REFERENCE_TYPE) @@ -7018,7 +7028,6 @@ c_expand_return (retval) extern tree dtor_label, ctor_label; tree result = DECL_RESULT (current_function_decl); tree valtype = TREE_TYPE (result); - int returns_value = 1; if (TREE_THIS_VOLATILE (current_function_decl)) warning ("function declared `noreturn' has a `return' statement"); @@ -7074,20 +7083,20 @@ c_expand_return (retval) else if (DECL_CONSTRUCTOR_P (current_function_decl) && retval != current_class_ptr) { - error ("return from a constructor: use `this = ...' instead"); + if (flag_this_is_variable) + error ("return from a constructor: use `this = ...' instead"); + else + error ("return from a constructor"); retval = current_class_ptr; } if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE) { current_function_returns_null = 1; - /* We do this here so we'll avoid a warning about how the function - "may or may not return a value" in finish_function. */ - returns_value = 0; - - if (retval) + if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) pedwarn ("`return' with a value, in function returning void"); expand_return (retval); + return; } /* Add some useful error checking for C++. */ else if (TREE_CODE (valtype) == REFERENCE_TYPE) @@ -7168,143 +7177,56 @@ c_expand_return (retval) (3) If an X(X&) constructor is defined, the return value must be returned via that. */ - /* If we're returning in a register, we can't initialize the - return value from a TARGET_EXPR. */ - if (TREE_CODE (retval) == TARGET_EXPR - && TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype) - && ! current_function_returns_struct) - retval = expand_target_expr (retval); - if (retval == result - /* Watch out for constructors, which "return" aggregates - via initialization, but which otherwise "return" a pointer. */ || DECL_CONSTRUCTOR_P (current_function_decl)) + /* It's already done for us. */; + else if (TYPE_MODE (TREE_TYPE (retval)) == VOIDmode) { - /* This is just an error--it's already been reported. */ - if (TYPE_SIZE (valtype) == NULL_TREE) - return; - - if (TYPE_MODE (valtype) != BLKmode - && any_pending_cleanups (1)) - retval = get_temp_regvar (valtype, retval); - } - else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct) - { - expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING); - expand_cleanups_to (NULL_TREE); - DECL_INITIAL (result) = NULL_TREE; + pedwarn ("return of void value in function returning non-void"); + expand_expr_stmt (retval); retval = 0; } else { - if (TYPE_MODE (valtype) == VOIDmode) - { - if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode - && warn_return_type) - warning ("return of void value in function returning non-void"); - expand_expr_stmt (retval); - retval = 0; - result = 0; - } - else if (TYPE_MODE (valtype) != BLKmode - && any_pending_cleanups (1)) - { - retval = get_temp_regvar (valtype, retval); - expand_cleanups_to (NULL_TREE); - result = 0; - } - else - { - /* We already did this above, don't do it again. */ - if (TREE_CODE (valtype) != REFERENCE_TYPE) - retval = convert_for_initialization (result, valtype, retval, - LOOKUP_NORMAL, - "return", NULL_TREE, 0); - DECL_INITIAL (result) = NULL_TREE; - } - if (retval == error_mark_node) - return; - } + /* We already did this above for refs, don't do it again. */ + if (TREE_CODE (valtype) != REFERENCE_TYPE) + retval = convert_for_initialization (NULL_TREE, valtype, retval, + LOOKUP_NORMAL, + "return", NULL_TREE, 0); - emit_queue (); + /* We can't initialize a register from a NEW_EXPR. */ + if (! current_function_returns_struct + && TREE_CODE (retval) == TARGET_EXPR + && TREE_CODE (TREE_OPERAND (retval, 0)) == NEW_EXPR) + retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval, + TREE_OPERAND (retval, 0)); + + if (retval == error_mark_node) + { + /* Avoid warning about control reaching end of function. */ + expand_null_return (); + return; + } + } if (retval != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (retval)) == 'd' && cond_stack == 0 && loop_stack == 0 && case_stack == 0) current_function_return_value = retval; - if (result) + if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) { - /* Everything's great--RETVAL is in RESULT. */ - if (original_result_rtx) - { - store_expr (result, original_result_rtx, 0); - expand_cleanups_to (NULL_TREE); - use_variable (DECL_RTL (result)); - if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) - expand_goto (ctor_label); - else - expand_null_return (); - } - else if (retval && retval != result) - { - /* Clear this out so the later call to decl_function_context - won't end up bombing on us. */ - if (DECL_CONTEXT (result) == error_mark_node) - DECL_CONTEXT (result) = NULL_TREE; - /* Here is where we finally get RETVAL into RESULT. - `expand_return' does the magic of protecting - RESULT from cleanups. */ - retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), - retval)); - /* This part _must_ come second, because expand_return looks for - the INIT_EXPR as the toplevel node only. :-( */ - retval = build (INIT_EXPR, TREE_TYPE (result), result, retval); - TREE_SIDE_EFFECTS (retval) = 1; - expand_return (retval); - } - else - expand_return (result); - } - else - { - /* We may still need to put RETVAL into RESULT. */ - result = DECL_RESULT (current_function_decl); - if (original_result_rtx) - { - /* Here we have a named return value that went - into memory. We can compute RETVAL into that. */ - if (retval) - expand_assignment (result, retval, 0, 0); - else - store_expr (result, original_result_rtx, 0); - result = make_tree (TREE_TYPE (result), original_result_rtx); - } - else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) - { - /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */ - expand_goto (ctor_label); - } - else if (retval) - { - /* Here is where we finally get RETVAL into RESULT. - `expand_return' does the magic of protecting - RESULT from cleanups. */ - result = build (INIT_EXPR, TREE_TYPE (result), result, retval); - TREE_SIDE_EFFECTS (result) = 1; - expand_return (result); - } - else if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode) - expand_return (result); + /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */ + expand_goto (ctor_label); } - current_function_returns_value = returns_value; - - /* One way to clear out cleanups that EXPR might - generate. Note that this code will really be - dead code, but that is ok--cleanups that were - needed were handled by the magic of `return'. */ - expand_cleanups_to (NULL_TREE); + if (retval && retval != result) + { + result = build (INIT_EXPR, TREE_TYPE (result), result, retval); + TREE_SIDE_EFFECTS (result) = 1; + } + expand_return (result); + current_function_returns_value = 1; } /* Start a C switch statement, testing expression EXP.