OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 978e95c..abd7880 100644 (file)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
+#include "c-lang.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "output.h"
@@ -70,9 +71,6 @@ int in_sizeof;
 /* The level of nesting inside "typeof".  */
 int in_typeof;
 
-struct c_label_context_se *label_context_stack_se;
-struct c_label_context_vm *label_context_stack_vm;
-
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
 static int missing_braces_mentioned;
@@ -89,7 +87,7 @@ static int type_lists_compatible_p (const_tree, const_tree, bool *);
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
-static tree pointer_diff (tree, tree);
+static tree pointer_diff (location_t, tree, tree);
 static tree convert_for_assignment (location_t, tree, tree, tree,
                                    enum impl_conv, bool, tree, tree, int);
 static tree valid_compound_expr_initializer (tree, tree);
@@ -1628,9 +1626,9 @@ c_size_in_bytes (const_tree type)
     }
 
   /* Convert in case a char is more than one unit.  */
-  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
-                    size_int (TYPE_PRECISION (char_type_node)
-                              / BITS_PER_UNIT));
+  return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                        size_int (TYPE_PRECISION (char_type_node)
+                                  / BITS_PER_UNIT));
 }
 \f
 /* Return either DECL or its known constant value (if it has one).  */
@@ -2082,7 +2080,7 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
              error_at (loc, "dereferencing pointer to incomplete type");
              return error_mark_node;
            }
-         if (VOID_TYPE_P (t) && skip_evaluation == 0)
+         if (VOID_TYPE_P (t) && c_inhibit_evaluation_warnings == 0)
            warning_at (loc, 0, "dereferencing %<void *%> pointer");
 
          /* We *must* set TREE_READONLY when dereferencing a pointer to const,
@@ -2589,7 +2587,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
       if (VOID_TYPE_P (return_type))
        {
          if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
-           pedwarn (input_location, 0,
+           pedwarn (loc, 0,
                     "function with qualified void return type called");
          return trap;
        }
@@ -2602,7 +2600,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
                                          build_constructor (return_type, 0),
                                          false);
          else
-           rhs = fold_convert (return_type, integer_zero_node);
+           rhs = fold_convert_loc (loc, return_type, integer_zero_node);
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
@@ -2626,23 +2624,24 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
     {
       if (require_constant_value)
-       result = fold_build_call_array_initializer (TREE_TYPE (fntype),
-                                                   function, nargs, argarray);
+       result = 
+         fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
+                                                function, nargs, argarray);
       else
-       result = fold_build_call_array (TREE_TYPE (fntype),
-                                       function, nargs, argarray);
+       result = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
+                                           function, nargs, argarray);
       if (TREE_CODE (result) == NOP_EXPR
          && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST)
        STRIP_TYPE_NOPS (result);
     }
   else
-    result = build_call_array (TREE_TYPE (fntype),
-                              function, nargs, argarray);
+    result = build_call_array_loc (loc, TREE_TYPE (fntype),
+                                  function, nargs, argarray);
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     {
       if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
-       pedwarn (input_location, 0,
+       pedwarn (loc, 0,
                 "function with qualified void return type called");
       return result;
     }
@@ -3061,7 +3060,7 @@ parser_build_binary_op (location_t location, enum tree_code code,
    The resulting tree has type int.  */
 
 static tree
-pointer_diff (tree op0, tree op1)
+pointer_diff (location_t loc, tree op0, tree op1)
 {
   tree restype = ptrdiff_type_node;
 
@@ -3070,10 +3069,10 @@ pointer_diff (tree op0, tree op1)
   tree orig_op1 = op1;
 
   if (TREE_CODE (target_type) == VOID_TYPE)
-    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+    pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
             "pointer of type %<void *%> used in subtraction");
   if (TREE_CODE (target_type) == FUNCTION_TYPE)
-    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+    pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
             "pointer to a function used in subtraction");
 
   /* If the conversion to ptrdiff_type does anything like widening or
@@ -3125,18 +3124,19 @@ pointer_diff (tree op0, tree op1)
      Do not do default conversions on the minus operator
      in case restype is a short type.  */
 
-  op0 = build_binary_op (input_location,
+  op0 = build_binary_op (loc,
                         MINUS_EXPR, convert (restype, op0),
                         convert (restype, op1), 0);
   /* This generates an error if op1 is pointer to incomplete type.  */
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
-    error ("arithmetic on pointer to an incomplete type");
+    error_at (loc, "arithmetic on pointer to an incomplete type");
 
   /* This generates an error if op0 is pointer to incomplete type.  */
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
-  return fold_build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
+  return fold_build2_loc (loc, EXACT_DIV_EXPR, restype,
+                         op0, convert (restype, op1));
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -3206,7 +3206,7 @@ build_unary_op (location_t location,
        }
       else if (!noconvert)
        arg = default_conversion (arg);
-      arg = non_lvalue (arg);
+      arg = non_lvalue_loc (location, arg);
       break;
 
     case NEGATE_EXPR:
@@ -3277,7 +3277,7 @@ build_unary_op (location_t location,
          return error_mark_node;
        }
       arg = c_objc_common_truthvalue_conversion (location, arg);
-      ret = invert_truthvalue (arg);
+      ret = invert_truthvalue_loc (location, arg);
       /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
       if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
        location = EXPR_LOCATION (ret);
@@ -3287,7 +3287,8 @@ build_unary_op (location_t location,
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1_loc (location,
+                              REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
        ret = arg;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
@@ -3298,9 +3299,11 @@ build_unary_op (location_t location,
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1_loc (location,
+                              IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
-       ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg);
+       ret = omit_one_operand_loc (location, TREE_TYPE (arg),
+                               integer_zero_node, arg);
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
@@ -3408,7 +3411,7 @@ build_unary_op (location_t location,
              }
 
            inc = c_size_in_bytes (TREE_TYPE (argtype));
-           inc = fold_convert (sizetype, inc);
+           inc = fold_convert_loc (location, sizetype, inc);
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
@@ -3478,7 +3481,7 @@ build_unary_op (location_t location,
        {
          /* Don't let this be an lvalue.  */
          if (lvalue_p (TREE_OPERAND (arg, 0)))
-           return non_lvalue (TREE_OPERAND (arg, 0));
+           return non_lvalue_loc (location, TREE_OPERAND (arg, 0));
          ret = TREE_OPERAND (arg, 0);
          goto return_build_unary_op;
        }
@@ -3544,10 +3547,11 @@ build_unary_op (location_t location,
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
-         tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
+         tree op0 = fold_convert_loc (location, sizetype,
+                                      fold_offsetof (arg, val)), op1;
 
-         op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
-         ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+         op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0));
+         ret = fold_build2_loc (location, POINTER_PLUS_EXPR, argtype, op1, op0);
          goto return_build_unary_op;
        }
 
@@ -3564,8 +3568,8 @@ build_unary_op (location_t location,
     argtype = TREE_TYPE (arg);
   if (TREE_CODE (arg) == INTEGER_CST)
     ret = (require_constant_value
-          ? fold_build1_initializer (code, argtype, arg)
-          : fold_build1 (code, argtype, arg));
+          ? fold_build1_initializer_loc (location, code, argtype, arg)
+          : fold_build1_loc (location, code, argtype, arg));
   else
     ret = build1 (code, argtype, arg);
  return_build_unary_op:
@@ -3773,7 +3777,8 @@ c_mark_addressable (tree exp)
 
 tree
 build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
-                       tree op1, tree op2)
+                       tree op1, tree op1_original_type, tree op2,
+                       tree op2_original_type)
 {
   tree type1;
   tree type2;
@@ -3846,6 +3851,20 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
        }
     }
 
+  if (warn_cxx_compat)
+    {
+      tree t1 = op1_original_type ? op1_original_type : TREE_TYPE (orig_op1);
+      tree t2 = op2_original_type ? op2_original_type : TREE_TYPE (orig_op2);
+
+      if (TREE_CODE (t1) == ENUMERAL_TYPE
+         && TREE_CODE (t2) == ENUMERAL_TYPE
+         && TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
+       warning_at (colon_loc, OPT_Wc___compat,
+                   ("different enum types in conditional is "
+                    "invalid in C++: %qT vs %qT"),
+                   t1, t2);
+    }
+
   /* Quickly detect the usual case where op1 and op2 have the same type
      after promotion.  */
   if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
@@ -3867,7 +3886,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
         and later code won't know it used to be different.
         Do this check on the original types, so that explicit casts
         will be considered, but default promotions won't.  */
-      if (!skip_evaluation)
+      if (c_inhibit_evaluation_warnings == 0)
        {
          int unsigned_op1 = TYPE_UNSIGNED (TREE_TYPE (orig_op1));
          int unsigned_op2 = TYPE_UNSIGNED (TREE_TYPE (orig_op2));
@@ -3894,10 +3913,19 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                     that folding in this case even without
                     warn_sign_compare to avoid warning options
                     possibly affecting code generation.  */
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_false_node);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_false_node);
+
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_true_node);
                  op2 = c_fully_fold (op2, require_constant_value,
                                      &op2_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_true_node);
 
                  if (warn_sign_compare)
                    {
@@ -4036,7 +4064,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                       && !TREE_OVERFLOW (orig_op2)));
     }
   if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
-    ret = fold_build3 (COND_EXPR, result_type, ifexp, op1, op2);
+    ret = fold_build3_loc (colon_loc, COND_EXPR, result_type, ifexp, op1, op2);
   else
     {
       ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
@@ -4390,7 +4418,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 
   /* Don't let a cast be an lvalue.  */
   if (value == expr)
-    value = non_lvalue (value);
+    value = non_lvalue_loc (loc, value);
 
   /* Don't allow the results of casting to floating-point or complex
      types be confused with actual constants, or casts involving
@@ -4927,7 +4955,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
            pedwarn (location, OPT_pedantic, 
                     "ISO C prohibits argument conversion to union type");
 
-         rhs = fold_convert (TREE_TYPE (memb), rhs);
+         rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
          return build_constructor_single (type, memb, rhs);
        }
     }
@@ -5549,16 +5577,26 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
              && TYPE_SIZE (type) != 0
-             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+           {
+             unsigned HOST_WIDE_INT len = TREE_STRING_LENGTH (inside_init);
+
              /* Subtract the size of a single (possibly wide) character
                 because it's ok to ignore the terminating null char
                 that is counted in the length of the constant.  */
-             && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
-                                      TREE_STRING_LENGTH (inside_init)
-                                      - (TYPE_PRECISION (typ1)
-                                         / BITS_PER_UNIT)))
-           pedwarn_init (init_loc, 0, 
-                         "initializer-string for array of chars is too long");
+             if (0 > compare_tree_int (TYPE_SIZE_UNIT (type),
+                                       (len
+                                        - (TYPE_PRECISION (typ1)
+                                           / BITS_PER_UNIT))))
+               pedwarn_init (init_loc, 0,
+                             ("initializer-string for array of chars "
+                              "is too long"));
+             else if (warn_cxx_compat
+                      && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), len))
+               warning_at (init_loc, OPT_Wc___compat,
+                           ("initializer-string for array chars "
+                            "is too long for C++"));
+           }
 
          return inside_init;
        }
@@ -7294,8 +7332,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
   /* Advance the variable that indicates sequential elements output.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     constructor_unfilled_index
-      = size_binop (PLUS_EXPR, constructor_unfilled_index,
-                   bitsize_one_node);
+      = size_binop_loc (input_location, PLUS_EXPR, constructor_unfilled_index,
+                       bitsize_one_node);
   else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
       constructor_unfilled_fields
@@ -7610,9 +7648,9 @@ process_init_element (struct c_expr value, bool implicit)
              /* For a record, keep track of end position of last field.  */
              if (DECL_SIZE (constructor_fields))
                constructor_bit_index
-                 = size_binop (PLUS_EXPR,
-                               bit_position (constructor_fields),
-                               DECL_SIZE (constructor_fields));
+                 = size_binop_loc (input_location, PLUS_EXPR,
+                                   bit_position (constructor_fields),
+                                   DECL_SIZE (constructor_fields));
 
              /* If the current field was the first one not yet written out,
                 it isn't now, so update.  */
@@ -7747,7 +7785,8 @@ process_init_element (struct c_expr value, bool implicit)
            }
 
          constructor_index
-           = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
+           = size_binop_loc (input_location, PLUS_EXPR,
+                             constructor_index, bitsize_one_node);
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
@@ -7779,7 +7818,8 @@ process_init_element (struct c_expr value, bool implicit)
            }
 
          constructor_index
-           = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
+           = size_binop_loc (input_location,
+                             PLUS_EXPR, constructor_index, bitsize_one_node);
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
@@ -7828,7 +7868,8 @@ process_init_element (struct c_expr value, bool implicit)
              process_init_element (pop_init_level (1), true);
            }
 
-         p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
+         p->index = size_binop_loc (input_location,
+                                    PLUS_EXPR, p->index, bitsize_one_node);
          if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
            finish = 1;
 
@@ -7979,46 +8020,9 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
 tree
 c_finish_goto_label (location_t loc, tree label)
 {
-  tree decl = lookup_label (label);
+  tree decl = lookup_label_for_goto (loc, label);
   if (!decl)
     return NULL_TREE;
-
-  if (C_DECL_UNJUMPABLE_STMT_EXPR (decl))
-    {
-      error_at (loc, "jump into statement expression");
-      return NULL_TREE;
-    }
-
-  if (C_DECL_UNJUMPABLE_VM (decl))
-    {
-      error_at (loc,
-               "jump into scope of identifier with variably modified type");
-      return NULL_TREE;
-    }
-
-  if (!C_DECL_UNDEFINABLE_STMT_EXPR (decl))
-    {
-      /* No jump from outside this statement expression context, so
-        record that there is a jump from within this context.  */
-      struct c_label_list *nlist;
-      nlist = XOBNEW (&parser_obstack, struct c_label_list);
-      nlist->next = label_context_stack_se->labels_used;
-      nlist->label = decl;
-      label_context_stack_se->labels_used = nlist;
-    }
-
-  if (!C_DECL_UNDEFINABLE_VM (decl))
-    {
-      /* No jump from outside this context context of identifiers with
-        variably modified type, so record that there is a jump from
-        within this context.  */
-      struct c_label_list *nlist;
-      nlist = XOBNEW (&parser_obstack, struct c_label_list);
-      nlist->next = label_context_stack_vm->labels_used;
-      nlist->label = decl;
-      label_context_stack_vm->labels_used = nlist;
-    }
-
   TREE_USED (decl) = 1;
   {
     tree t = build1 (GOTO_EXPR, void_type_node, decl);
@@ -8189,15 +8193,9 @@ struct c_switch {
      of the GNU case range extension.  */
   splay_tree cases;
 
-  /* Number of nested statement expressions within this switch
-     statement; if nonzero, case and default labels may not
-     appear.  */
-  unsigned int blocked_stmt_expr;
-
-  /* Scope of outermost declarations of identifiers with variably
-     modified type within this switch statement; if nonzero, case and
-     default labels may not appear.  */
-  unsigned int blocked_vm;
+  /* The bindings at the point of the switch.  This is used for
+     warnings crossing decls when branching to a case label.  */
+  struct c_spot_bindings *bindings;
 
   /* The next node on the stack.  */
   struct c_switch *next;
@@ -8261,8 +8259,7 @@ c_start_case (location_t switch_loc,
   SET_EXPR_LOCATION (cs->switch_expr, switch_loc);
   cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
-  cs->blocked_stmt_expr = 0;
-  cs->blocked_vm = 0;
+  cs->bindings = c_get_switch_bindings ();
   cs->next = c_switch_stack;
   c_switch_stack = cs;
 
@@ -8292,40 +8289,26 @@ do_case (location_t loc, tree low_value, tree high_value)
                 "case label is not an integer constant expression");
     }
 
-  if (c_switch_stack && !c_switch_stack->blocked_stmt_expr
-      && !c_switch_stack->blocked_vm)
-    {
-      label = c_add_case_label (loc, c_switch_stack->cases,
-                               SWITCH_COND (c_switch_stack->switch_expr),
-                               c_switch_stack->orig_type,
-                               low_value, high_value);
-      if (label == error_mark_node)
-       label = NULL_TREE;
-    }
-  else if (c_switch_stack && c_switch_stack->blocked_stmt_expr)
+  if (c_switch_stack == NULL)
     {
       if (low_value)
-       error_at (loc, "case label in statement expression not containing "
-                 "enclosing switch statement");
+       error_at (loc, "case label not within a switch statement");
       else
-       error_at (loc, "%<default%> label in statement expression not containing "
-                 "enclosing switch statement");
-    }
-  else if (c_switch_stack && c_switch_stack->blocked_vm)
-    {
-      if (low_value)
-       error_at (loc, "case label in scope of identifier with variably "
-                 "modified type not containing enclosing switch statement");
-      else
-       error_at (loc, "%<default%> label in scope of identifier with "
-                 "variably modified type not containing enclosing switch "
-                 "statement");
+       error_at (loc, "%<default%> label not within a switch statement");
+      return NULL_TREE;
     }
-  else if (low_value)
-    error_at (loc, "case label not within a switch statement");
-  else
-    error_at (loc, "%<default%> label not within a switch statement");
 
+  if (c_check_switch_jump_warnings (c_switch_stack->bindings,
+                                   EXPR_LOCATION (c_switch_stack->switch_expr),
+                                   loc))
+    return NULL_TREE;
+
+  label = c_add_case_label (loc, c_switch_stack->cases,
+                           SWITCH_COND (c_switch_stack->switch_expr),
+                           c_switch_stack->orig_type,
+                           low_value, high_value);
+  if (label == error_mark_node)
+    label = NULL_TREE;
   return label;
 }
 
@@ -8339,11 +8322,6 @@ c_finish_case (tree body)
 
   SWITCH_BODY (cs->switch_expr) = body;
 
-  /* We must not be within a statement expression nested in the switch
-     at this point; we might, however, be within the scope of an
-     identifier with variably modified type nested in the switch.  */
-  gcc_assert (!cs->blocked_stmt_expr);
-
   /* Emit warnings as needed.  */
   switch_location = EXPR_LOCATION (cs->switch_expr);
   c_do_switch_warnings (cs->cases, switch_location,
@@ -8353,6 +8331,7 @@ c_finish_case (tree body)
   /* Pop the stack.  */
   c_switch_stack = cs->next;
   splay_tree_delete (cs->cases);
+  c_release_switch_bindings (cs->bindings);
   XDELETE (cs);
 }
 \f
@@ -8397,9 +8376,8 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
     found:
 
       if (COND_EXPR_ELSE (inner_if))
-        warning (OPT_Wparentheses,
-                 "%Hsuggest explicit braces to avoid ambiguous %<else%>",
-                 &if_locus);
+        warning_at (if_locus, OPT_Wparentheses,
+                    "suggest explicit braces to avoid ambiguous %<else%>");
     }
 
   stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
@@ -8457,11 +8435,12 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
            }
 
          t = build_and_jump (&blab);
-         exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
          if (cond_is_first)
-           SET_EXPR_LOCATION (exit, start_locus);
+           exit = fold_build3_loc (start_locus,
+                               COND_EXPR, void_type_node, cond, exit, t);
          else
-           SET_EXPR_LOCATION (exit, input_location);
+           exit = fold_build3_loc (input_location,
+                               COND_EXPR, void_type_node, cond, exit, t);
        }
 
       add_stmt (top);
@@ -8603,30 +8582,16 @@ tree
 c_begin_stmt_expr (void)
 {
   tree ret;
-  struct c_label_context_se *nstack;
-  struct c_label_list *glist;
 
   /* We must force a BLOCK for this level so that, if it is not expanded
      later, there is a way to turn off the entire subtree of blocks that
      are contained in it.  */
   keep_next_level ();
   ret = c_begin_compound_stmt (true);
-  if (c_switch_stack)
-    {
-      c_switch_stack->blocked_stmt_expr++;
-      gcc_assert (c_switch_stack->blocked_stmt_expr != 0);
-    }
-  for (glist = label_context_stack_se->labels_used;
-       glist != NULL;
-       glist = glist->next)
-    {
-      C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 1;
-    }
-  nstack = XOBNEW (&parser_obstack, struct c_label_context_se);
-  nstack->labels_def = NULL;
-  nstack->labels_used = NULL;
-  nstack->next = label_context_stack_se;
-  label_context_stack_se = nstack;
+
+  c_bindings_start_stmt_expr (c_switch_stack == NULL
+                             ? NULL
+                             : c_switch_stack->bindings);
 
   /* Mark the current statement list as belonging to a statement list.  */
   STATEMENT_LIST_STMT_EXPR (ret) = 1;
@@ -8642,37 +8607,12 @@ c_finish_stmt_expr (location_t loc, tree body)
 {
   tree last, type, tmp, val;
   tree *last_p;
-  struct c_label_list *dlist, *glist, *glist_prev = NULL;
 
   body = c_end_compound_stmt (loc, body, true);
-  if (c_switch_stack)
-    {
-      gcc_assert (c_switch_stack->blocked_stmt_expr != 0);
-      c_switch_stack->blocked_stmt_expr--;
-    }
-  /* It is no longer possible to jump to labels defined within this
-     statement expression.  */
-  for (dlist = label_context_stack_se->labels_def;
-       dlist != NULL;
-       dlist = dlist->next)
-    {
-      C_DECL_UNJUMPABLE_STMT_EXPR (dlist->label) = 1;
-    }
-  /* It is again possible to define labels with a goto just outside
-     this statement expression.  */
-  for (glist = label_context_stack_se->next->labels_used;
-       glist != NULL;
-       glist = glist->next)
-    {
-      C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 0;
-      glist_prev = glist;
-    }
-  if (glist_prev != NULL)
-    glist_prev->next = label_context_stack_se->labels_used;
-  else
-    label_context_stack_se->next->labels_used
-      = label_context_stack_se->labels_used;
-  label_context_stack_se = label_context_stack_se->next;
+
+  c_bindings_end_stmt_expr (c_switch_stack == NULL
+                           ? NULL
+                           : c_switch_stack->bindings);
 
   /* Locate the last statement in BODY.  See c_end_compound_stmt
      about always returning a BIND_EXPR.  */
@@ -8754,7 +8694,7 @@ c_finish_stmt_expr (location_t loc, tree body)
     val = TREE_OPERAND (val, 0);
 
   *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
-  SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last));
+  SET_EXPR_LOCATION (*last_p, EXPR_LOCATION (last));
 
   {
     tree t = build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
@@ -8762,80 +8702,6 @@ c_finish_stmt_expr (location_t loc, tree body)
     return t;
   }
 }
-
-/* Begin the scope of an identifier of variably modified type, scope
-   number SCOPE.  Jumping from outside this scope to inside it is not
-   permitted.  */
-
-void
-c_begin_vm_scope (unsigned int scope)
-{
-  struct c_label_context_vm *nstack;
-  struct c_label_list *glist;
-
-  gcc_assert (scope > 0);
-
-  /* At file_scope, we don't have to do any processing.  */
-  if (label_context_stack_vm == NULL)
-    return;
-
-  if (c_switch_stack && !c_switch_stack->blocked_vm)
-    c_switch_stack->blocked_vm = scope;
-  for (glist = label_context_stack_vm->labels_used;
-       glist != NULL;
-       glist = glist->next)
-    {
-      C_DECL_UNDEFINABLE_VM (glist->label) = 1;
-    }
-  nstack = XOBNEW (&parser_obstack, struct c_label_context_vm);
-  nstack->labels_def = NULL;
-  nstack->labels_used = NULL;
-  nstack->scope = scope;
-  nstack->next = label_context_stack_vm;
-  label_context_stack_vm = nstack;
-}
-
-/* End a scope which may contain identifiers of variably modified
-   type, scope number SCOPE.  */
-
-void
-c_end_vm_scope (unsigned int scope)
-{
-  if (label_context_stack_vm == NULL)
-    return;
-  if (c_switch_stack && c_switch_stack->blocked_vm == scope)
-    c_switch_stack->blocked_vm = 0;
-  /* We may have a number of nested scopes of identifiers with
-     variably modified type, all at this depth.  Pop each in turn.  */
-  while (label_context_stack_vm->scope == scope)
-    {
-      struct c_label_list *dlist, *glist, *glist_prev = NULL;
-
-      /* It is no longer possible to jump to labels defined within this
-        scope.  */
-      for (dlist = label_context_stack_vm->labels_def;
-          dlist != NULL;
-          dlist = dlist->next)
-       {
-         C_DECL_UNJUMPABLE_VM (dlist->label) = 1;
-       }
-      /* It is again possible to define labels with a goto just outside
-        this scope.  */
-      for (glist = label_context_stack_vm->next->labels_used;
-          glist != NULL;
-          glist = glist->next)
-       {
-         C_DECL_UNDEFINABLE_VM (glist->label) = 0;
-         glist_prev = glist;
-       }
-      if (glist_prev != NULL)
-       glist_prev->next = label_context_stack_vm->labels_used;
-      else
-       label_context_stack_vm->next->labels_used
-         = label_context_stack_vm->labels_used;
-      label_context_stack_vm = label_context_stack_vm->next;
-    }
-}
 \f
 /* Begin and end compound statements.  This is as simple as pushing
    and popping new statement lists from the tree.  */
@@ -9089,12 +8955,12 @@ build_binary_op (location_t location, enum tree_code code,
       /* Handle the pointer + int case.  */
       if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (PLUS_EXPR, op0, op1);
+         ret = pointer_int_sum (location, PLUS_EXPR, op0, op1);
          goto return_build_binary_op;
        }
       else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (PLUS_EXPR, op1, op0);
+         ret = pointer_int_sum (location, PLUS_EXPR, op1, op0);
          goto return_build_binary_op;
        }
       else
@@ -9107,13 +8973,13 @@ build_binary_op (location_t location, enum tree_code code,
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
          && comp_target_types (location, type0, type1))
        {
-         ret = pointer_diff (op0, op1);
+         ret = pointer_diff (location, op0, op1);
          goto return_build_binary_op;
        }
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (MINUS_EXPR, op0, op1);
+         ret = pointer_int_sum (location, MINUS_EXPR, op0, op1);
          goto return_build_binary_op;
        }
       else
@@ -9252,7 +9118,7 @@ build_binary_op (location_t location, enum tree_code code,
              if (tree_int_cst_sgn (op1) < 0)
                {
                  int_const = false;
-                 if (skip_evaluation == 0)
+                 if (c_inhibit_evaluation_warnings == 0)
                    warning (0, "right shift count is negative");
                }
              else
@@ -9263,7 +9129,7 @@ build_binary_op (location_t location, enum tree_code code,
                  if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                    {
                      int_const = false;
-                     if (skip_evaluation == 0)
+                     if (c_inhibit_evaluation_warnings == 0)
                        warning (0, "right shift count >= width of type");
                    }
                }
@@ -9289,14 +9155,14 @@ build_binary_op (location_t location, enum tree_code code,
              if (tree_int_cst_sgn (op1) < 0)
                {
                  int_const = false;
-                 if (skip_evaluation == 0)
+                 if (c_inhibit_evaluation_warnings == 0)
                    warning (0, "left shift count is negative");
                }
 
              else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                {
                  int_const = false;
-                 if (skip_evaluation == 0)
+                 if (c_inhibit_evaluation_warnings == 0)
                    warning (0, "left shift count >= width of type");
                }
            }
@@ -9636,7 +9502,7 @@ build_binary_op (location_t location, enum tree_code code,
          converted = 1;
          resultcode = xresultcode;
 
-         if (!skip_evaluation)
+         if (c_inhibit_evaluation_warnings == 0)
            {
              bool op0_maybe_const = true;
              bool op1_maybe_const = true;
@@ -9653,10 +9519,12 @@ build_binary_op (location_t location, enum tree_code code,
                     build_conditional_expr.  This requires the
                     "original" values to be folded, not just op0 and
                     op1.  */
+                 c_inhibit_evaluation_warnings++;
                  op0 = c_fully_fold (op0, require_constant_value,
                                      &op0_maybe_const);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings--;
                  orig_op0_folded = c_fully_fold (orig_op0,
                                                  require_constant_value,
                                                  NULL);
@@ -9726,8 +9594,9 @@ build_binary_op (location_t location, enum tree_code code,
   /* Treat expressions in initializers specially as they can't trap.  */
   if (int_const_or_overflow)
     ret = (require_constant_value
-          ? fold_build2_initializer (resultcode, build_type, op0, op1)
-          : fold_build2 (resultcode, build_type, op0, op1));
+          ? fold_build2_initializer_loc (location, resultcode, build_type,
+                                         op0, op1)
+          : fold_build2_loc (location, resultcode, build_type, op0, op1));
   else
     ret = build2 (resultcode, build_type, op0, op1);
   if (final_type != 0)