Makefile.in (parse.o, decl.o): Also depend on $(srcdir)/../except.h $(srcdir)/.....
[gcc.git] / gcc / cp / expr.c
index 0c549c34954e33c613da2be0163993cc18e51927..a14695ddd51ff03fbc4c2e829d88f9b526fbc967 100644 (file)
@@ -21,18 +21,21 @@ Boston, MA 02111-1307, USA.  */
 
 
 #include "config.h"
+#include <stdio.h>
 #include "rtl.h"
 #include "tree.h"
 #include "flags.h"
 #include "expr.h"
 #include "cp-tree.h"
 
-#undef NULL
-#define NULL 0
+static tree extract_aggr_init PROTO((tree, tree));
+static tree extract_scalar_init PROTO((tree, tree));
+static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode,
+                                   enum expand_modifier));
 
 /* Hook used by expand_expr to expand language-specific tree codes.  */
 
-rtx
+static rtx
 cplus_expand_expr (exp, target, tmode, modifier)
      tree exp;
      rtx target;
@@ -42,11 +45,10 @@ cplus_expand_expr (exp, target, tmode, modifier)
   tree type = TREE_TYPE (exp);
   register enum machine_mode mode = TYPE_MODE (type);
   register enum tree_code code = TREE_CODE (exp);
-  rtx original_target = target;
   int ignore = target == const0_rtx;
 
   if (ignore)
-    target = 0, original_target = 0;
+    target = 0;
 
   /* No sense saving up arithmetic to be done
      if it's all in the wrong mode to form part of an address.
@@ -105,7 +107,7 @@ 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);
@@ -137,9 +139,21 @@ 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, 0);
+       call_exp = build (CALL_EXPR, type, func, args, NULL_TREE);
        TREE_SIDE_EFFECTS (call_exp) = 1;
        return_target = expand_call (call_exp, call_target, ignore);
        if (call_target == 0)
@@ -165,7 +179,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
 
                    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);
              }
@@ -226,6 +240,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;
     }
@@ -270,19 +292,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.  */
 
@@ -325,8 +334,8 @@ extract_scalar_init (decl, init)
 
       to = XEXP (r, 0);
 
-      if (! (to == value ||
-            (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
+      if (! (to == value
+            || (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
        return 0;
 
       r = XEXP (r, 1);
@@ -350,6 +359,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);
@@ -361,4 +371,93 @@ 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 if (! start)
+           error ("`default' 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);
 }