90th Cygnus<->FSF quick merge
authorMike Stump <mrs@gcc.gnu.org>
Thu, 31 Oct 1996 17:08:58 +0000 (17:08 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Thu, 31 Oct 1996 17:08:58 +0000 (17:08 +0000)
From-SVN: r13082

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/decl2.c
gcc/cp/typeck.c

index 1c95b3b..b5cf22a 100644 (file)
@@ -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  <manson@charmed.cygnus.com>
+
+       * 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  <jason@gerbil.cygnus.com>
+
+       * 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  <jason@yorick.cygnus.com>
+
+       * typeck.c (decay_conversion): Handle overloaded methods.
+
+Fri Oct 18 16:03:48 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * call.c (build_over_call): A TARGET_EXPR has side-effects.
+
 Thu Oct 17 11:31:59 1996  Mike Stump  <mrs@cygnus.com>
 
        * cvt.c (convert_to_pointer_force): Add code to support pointer to
index 9ae201c..80258c0 100644 (file)
@@ -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)
index 60b2cff..28391dc 100644 (file)
@@ -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.  */
index 0775bb2..4bd06a3 100644 (file)
@@ -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);
 
index 1e09c28..4c876f6 100644 (file)
@@ -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 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);
+
+      /* 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)
        {
-         /* 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;
+         /* Avoid warning about control reaching end of function.  */
+         expand_null_return ();
+         return;
        }
-      if (retval == error_mark_node)
-       return;
     }
 
-  emit_queue ();
-
   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);
+      /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do.  */
+      expand_goto (ctor_label);
     }
-  else
+
+  if (retval && retval != result)
     {
-      /* 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);
+      result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
+      TREE_SIDE_EFFECTS (result) = 1;
     }
-
-  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);
+  expand_return (result);
+  current_function_returns_value = 1;
 }
 \f
 /* Start a C switch statement, testing expression EXP.