OSDN Git Service

(struct function): Make frame_offset be HOST_WIDE_INT.
[pf3gnuchains/gcc-fork.git] / gcc / cp / expr.c
index 338065b..3351ccb 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert language-specific tree expression to rtl instructions,
    for GNU compiler.
-   Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -16,7 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include "config.h"
@@ -104,9 +105,10 @@ cplus_expand_expr (exp, target, tmode, modifier)
            && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
            && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
          {
-           type = TYPE_POINTER_TO (type);
+           type = build_pointer_type (type);
            /* Don't clobber a value that might be part of a default
               parameter value.  */
+           mark_addressable (slot);
            if (TREE_PERMANENT (args))
              args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
                                TREE_CHAIN (args));
@@ -130,20 +132,28 @@ cplus_expand_expr (exp, target, tmode, modifier)
          }
        if (call_target)
          {
-           preserve_temp_slots (call_target);
-
            /* Make this a valid memory address now.  The code below assumes
               that it can compare rtx and make assumptions based on the
               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;
+             }
          }
 
-       preserve_temp_slots (DECL_RTL (slot));
-       call_exp = build (CALL_EXPR, type, func, args, 0);
+       call_exp = build (CALL_EXPR, type, func, args, NULL_TREE);
        TREE_SIDE_EFFECTS (call_exp) = 1;
-       return_target = expand_expr (call_exp, call_target, mode, 0);
-       free_temp_slots ();
+       return_target = expand_call (call_exp, call_target, ignore);
        if (call_target == 0)
          {
            if (pcc_struct_return)
@@ -151,8 +161,9 @@ cplus_expand_expr (exp, target, tmode, modifier)
                extern int flag_access_control;
                int old_ac = flag_access_control;
 
-               tree init = build (RTL_EXPR, type, 0, return_target);
+               tree init = build_decl (VAR_DECL, 0, type);
                TREE_ADDRESSABLE (init) = 1;
+               DECL_RTL (init) = return_target;
 
                flag_access_control = 0;
                expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
@@ -160,11 +171,13 @@ cplus_expand_expr (exp, target, tmode, modifier)
 
                if (TYPE_NEEDS_DESTRUCTOR (type))
                  {
-                   init = build (RTL_EXPR, build_reference_type (type), 0,
-                                 XEXP (return_target, 0));
+                   init = build_decl (VAR_DECL, 0,
+                                      build_reference_type (type));
+                   DECL_RTL (init) = XEXP (return_target, 0);
+
                    init = maybe_build_cleanup (convert_from_reference (init));
                    if (init != NULL_TREE)
-                     expand_expr (init, 0, 0, 0);
+                     expand_expr (init, const0_rtx, VOIDmode, 0);
                  }
                call_target = return_target = DECL_RTL (slot);
              }
@@ -174,7 +187,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
 
        if (call_target != return_target)
          {
-           my_friendly_assert (! TYPE_NEEDS_CONSTRUCTING (type), 317);
+           my_friendly_assert (TYPE_HAS_TRIVIAL_INIT_REF (type), 317);
            if (GET_MODE (return_target) == BLKmode)
              emit_block_move (call_target, return_target, expr_size (exp),
                               TYPE_ALIGN (type) / BITS_PER_UNIT);
@@ -225,6 +238,14 @@ cplus_expand_expr (exp, target, tmode, modifier)
       expand_throw (TREE_OPERAND (exp, 0));
       return NULL;
 
+    case VEC_INIT_EXPR:
+      return expand_expr
+       (expand_vec_init
+        (NULL_TREE, TREE_OPERAND (exp, 0),
+         build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
+                          integer_one_node, 1),
+         TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
+
     default:
       break;
     }
@@ -269,19 +290,6 @@ fixup_result_decl (decl, result)
     }
 }
 
-/* Return nonzero iff DECL is memory-based.  The DECL_RTL of
-   certain const variables might be a CONST_INT, or a REG
-   in some cases.  We cannot use `memory_operand' as a test
-   here because on most RISC machines, a variable's address
-   is not, by itself, a legitimate address.  */
-
-int
-decl_in_memory_p (decl)
-     tree decl;
-{
-  return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
-}
-
 /* Expand this initialization inline and see if it's simple enough that
    it can be done at compile-time.  */
 
@@ -349,6 +357,7 @@ extract_init (decl, init)
 {
   return 0;
 
+#if 0
   if (IS_AGGR_TYPE (TREE_TYPE (decl))
       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
     init = extract_aggr_init (decl, init);
@@ -360,4 +369,91 @@ extract_init (decl, init)
 
   DECL_INITIAL (decl) = init;
   return 1;
+#endif
+}
+
+void
+do_case (start, end)
+     tree start, end;
+{
+  tree value1 = NULL_TREE, value2 = NULL_TREE, label;
+
+  if (start != NULL_TREE && TREE_TYPE (start) != NULL_TREE 
+      && POINTER_TYPE_P (TREE_TYPE (start)))
+    error ("pointers are not permitted as case values");
+
+  if (end && pedantic)
+    pedwarn ("ANSI C++ forbids range expressions in switch statement");
+
+  if (processing_template_decl)
+    {
+      add_tree (build_min_nt (CASE_LABEL, start, end));
+      return;
+    }
+
+  if (start)
+    value1 = check_cp_case_value (start);
+  if (end)
+    value2 = check_cp_case_value (end);
+  
+  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+
+  if (value1 != error_mark_node
+      && value2 != error_mark_node)
+    {
+      tree duplicate;
+      int success;
+
+      if (end)
+       success = pushcase_range (value1, value2, convert_and_check,
+                                 label, &duplicate);
+      else if (start)
+       success = pushcase (value1, convert_and_check, label, &duplicate);
+      else
+       success = pushcase (NULL_TREE, 0, label, &duplicate);
+
+      if (success == 1)
+       {
+         if (end)
+           error ("case label not within a switch statement");
+         else if (start)
+           cp_error ("case label `%E' not within a switch statement", start);
+         else
+           error ("default label not within a switch statement");
+       }
+      else if (success == 2)
+       {
+         if (end)
+           {
+             error ("duplicate (or overlapping) case value");
+             cp_error_at ("this is the first entry overlapping that value",
+                          duplicate);
+           }
+         else if (start)
+           {
+             cp_error ("duplicate case value `%E'", start);
+             cp_error_at ("previously used here", duplicate);
+           }
+         else
+           {
+             error ("multiple default labels in one switch");
+             cp_error_at ("this is the first default label", duplicate);
+           }
+       }
+      else if (success == 3)
+       warning ("case value out of range");
+      else if (success == 4)
+       warning ("empty range specified");
+      else if (success == 5)
+       {
+         if (end)
+           error ("case label within scope of cleanup or variable array");
+         else
+           cp_error ("case label `%E' within scope of cleanup or variable array", start);
+       }
+    }
+  if (start)
+    define_case_label (label);
+  else
+    define_case_label (NULL_TREE);
 }