OSDN Git Service

2004-10-02 James A. Morrison <phython@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 2c89c73..08b5953 100644 (file)
@@ -44,6 +44,25 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-iterator.h"
 #include "tree-gimple.h"
 
+/* Places where an lvalue, or modifiable lvalue, may be required.
+   Used to select diagnostic messages in lvalue_or_else and
+   readonly_error.  */
+enum lvalue_use {
+  lv_assign,
+  lv_increment,
+  lv_decrement,
+  lv_addressof,
+  lv_asm
+};
+
+/* The level of nesting inside "__alignof__".  */
+int in_alignof;
+
+/* The level of nesting inside "sizeof".  */
+int in_sizeof;
+
+/* The level of nesting inside "typeof".  */
+int in_typeof;
 
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
@@ -81,7 +100,8 @@ static void add_pending_init (tree, tree);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
-static int lvalue_or_else (tree, const char *);
+static int lvalue_or_else (tree, enum lvalue_use);
+static void readonly_error (tree, enum lvalue_use);
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
@@ -117,7 +137,7 @@ c_incomplete_type_error (tree value, tree type)
 
   if (value != 0 && (TREE_CODE (value) == VAR_DECL
                     || TREE_CODE (value) == PARM_DECL))
-    error ("`%s' has an incomplete type",
+    error ("%qs has an incomplete type",
           IDENTIFIER_POINTER (DECL_NAME (value)));
   else
     {
@@ -157,15 +177,15 @@ c_incomplete_type_error (tree value, tree type)
          return;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-       error ("invalid use of undefined type `%s %s'",
+       error ("invalid use of undefined type %<%s %s%>",
               type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type)));
       else
        /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
-       error ("invalid use of incomplete typedef `%s'",
+       error ("invalid use of incomplete typedef %qs",
               IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
     }
 }
@@ -240,8 +260,7 @@ composite_type (tree t1, tree t2)
   if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
     return t2;
 
-  if (code1 != code2)
-    abort ();
+  gcc_assert (code1 == code2);
 
   switch (code1)
     {
@@ -261,8 +280,7 @@ composite_type (tree t1, tree t2)
        tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
        
        /* We should not have any type quals on arrays at all.  */
-       if (TYPE_QUALS (t1) || TYPE_QUALS (t2))
-         abort ();
+       gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
        
        /* Save space: see if the result is identical to one of the args.  */
        if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
@@ -412,8 +430,8 @@ common_pointer_type (tree t1, tree t2)
   if (t2 == error_mark_node)
     return t1;
 
-  if (TREE_CODE (t1) != POINTER_TYPE || TREE_CODE (t2) != POINTER_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (t1) == POINTER_TYPE
+             && TREE_CODE (t2) == POINTER_TYPE);
 
   /* Merge the attributes.  */
   attributes = targetm.merge_type_attributes (t1, t2);
@@ -470,13 +488,10 @@ common_type (tree t1, tree t2)
   code1 = TREE_CODE (t1);
   code2 = TREE_CODE (t2);
 
-  if (code1 != VECTOR_TYPE && code1 != COMPLEX_TYPE
-      && code1 != REAL_TYPE && code1 != INTEGER_TYPE)
-    abort ();
-
-  if (code2 != VECTOR_TYPE && code2 != COMPLEX_TYPE
-      && code2 != REAL_TYPE && code2 != INTEGER_TYPE)
-    abort ();
+  gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
+             || code1 == REAL_TYPE || code1 == INTEGER_TYPE);
+  gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
+             || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
 
   /* If one type is a vector type, return that type.  (How the usual
      arithmetic conversions apply to the vector types extension is not
@@ -741,19 +756,25 @@ same_translation_unit_p (tree t1, tree t2)
   while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t1)))
       {
-      case 'd': t1 = DECL_CONTEXT (t1); break;
-      case 't': t1 = TYPE_CONTEXT (t1); break;
-      case 'x': t1 = BLOCK_SUPERCONTEXT (t1); break;  /* assume block */
-      default: abort ();
+      case tcc_declaration:
+       t1 = DECL_CONTEXT (t1); break;
+      case tcc_type:
+       t1 = TYPE_CONTEXT (t1); break;
+      case tcc_exceptional:
+       t1 = BLOCK_SUPERCONTEXT (t1); break;  /* assume block */
+      default: gcc_unreachable ();
       }
 
   while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t2)))
       {
-      case 'd': t2 = DECL_CONTEXT (t2); break;
-      case 't': t2 = TYPE_CONTEXT (t2); break;
-      case 'x': t2 = BLOCK_SUPERCONTEXT (t2); break;  /* assume block */
-      default: abort ();
+      case tcc_declaration:
+       t2 = DECL_CONTEXT (t2); break;
+      case tcc_type:
+       t2 = TYPE_CONTEXT (t2); break;
+      case tcc_exceptional:
+       t2 = BLOCK_SUPERCONTEXT (t2); break;  /* assume block */
+      default: gcc_unreachable ();
       }
 
   return t1 == t2;
@@ -935,7 +956,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
       }
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -961,7 +982,7 @@ function_types_compatible_p (tree f1, tree f2)
   /* 'volatile' qualifiers on a function's return type used to mean
      the function is noreturn.  */
   if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
-    pedwarn ("function return types not compatible due to `volatile'");
+    pedwarn ("function return types not compatible due to %<volatile%>");
   if (TYPE_VOLATILE (ret1))
     ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
                                 TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE);
@@ -1197,7 +1218,7 @@ default_function_array_conversion (tree exp)
       int volatilep = 0;
       int lvalue_array_p;
 
-      if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
+      if (REFERENCE_CLASS_P (exp) || DECL_P (exp))
        {
          constp = TREE_READONLY (exp);
          volatilep = TREE_THIS_VOLATILE (exp);
@@ -1443,26 +1464,6 @@ build_component_ref (tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
-  /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
-     Ensure that the arguments are not lvalues; otherwise,
-     if the component is an array, it would wrongly decay to a pointer in
-     C89 mode.
-     We cannot do this with a COND_EXPR, because in a conditional expression
-     the default promotions are applied to both sides, and this would yield
-     the wrong type of the result; for example, if the components have
-     type "char".  */
-  switch (TREE_CODE (datum))
-    {
-    case COMPOUND_EXPR:
-      {
-       tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
-       return build2 (COMPOUND_EXPR, TREE_TYPE (value),
-                      TREE_OPERAND (datum, 0), non_lvalue (value));
-      }
-    default:
-      break;
-    }
-
   /* See if there is a field or component with name COMPONENT.  */
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
@@ -1477,8 +1478,7 @@ build_component_ref (tree datum, tree component)
 
       if (!field)
        {
-         error ("%s has no member named `%s'",
-                code == RECORD_TYPE ? "structure" : "union",
+         error ("%qT has no member named %qs", type,
                 IDENTIFIER_POINTER (component));
          return error_mark_node;
        }
@@ -1514,7 +1514,7 @@ build_component_ref (tree datum, tree component)
       return ref;
     }
   else if (code != ERROR_MARK)
-    error ("request for member `%s' in something not a structure or union",
+    error ("request for member %qs in something not a structure or union",
            IDENTIFIER_POINTER (component));
 
   return error_mark_node;
@@ -1547,7 +1547,7 @@ build_indirect_ref (tree ptr, const char *errorstring)
              return error_mark_node;
            }
          if (VOID_TYPE_P (t) && skip_evaluation == 0)
-           warning ("dereferencing `void *' pointer");
+           warning ("dereferencing %<void *%> pointer");
 
          /* We *must* set TREE_READONLY when dereferencing a pointer to const,
             so that we get the proper error message if the result is used
@@ -1564,7 +1564,7 @@ build_indirect_ref (tree ptr, const char *errorstring)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    error ("invalid type argument of `%s'", errorstring);
+    error ("invalid type argument of %qs", errorstring);
   return error_mark_node;
 }
 
@@ -1602,7 +1602,7 @@ build_array_ref (tree array, tree index)
         must have done so deliberately.  */
       if (warn_char_subscripts
          && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-       warning ("array subscript has type `char'");
+       warning ("array subscript has type %<char%>");
 
       /* Apply default promotions *after* noticing character types.  */
       index = default_conversion (index);
@@ -1643,7 +1643,7 @@ build_array_ref (tree array, tree index)
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
-           pedwarn ("ISO C forbids subscripting `register' array");
+           pedwarn ("ISO C forbids subscripting %<register%> array");
          else if (! flag_isoc99 && ! lvalue_p (foo))
            pedwarn ("ISO C90 forbids subscripting non-lvalue array");
        }
@@ -1678,7 +1678,7 @@ build_array_ref (tree array, tree index)
     if (warn_char_subscripts
        && TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE
        && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-      warning ("subscript has type `char'");
+      warning ("subscript has type %<char%>");
 
     /* Put the integer in IND to simplify error checking.  */
     if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
@@ -1715,7 +1715,7 @@ build_external_ref (tree id, int fun)
 {
   tree ref;
   tree decl = lookup_name (id);
-  tree objc_ivar = lookup_objc_ivar (id);
+  tree objc_ivar = objc_lookup_ivar (id);
 
   if (decl && decl != error_mark_node)
     {
@@ -1724,7 +1724,7 @@ build_external_ref (tree id, int fun)
        ref = decl;
       else if (decl != objc_ivar && !DECL_FILE_SCOPE_P (decl))
        {
-         warning ("local declaration of `%s' hides instance variable",
+         warning ("local declaration of %qs hides instance variable",
                   IDENTIFIER_POINTER (id));
          ref = decl;
        }
@@ -1756,6 +1756,16 @@ build_external_ref (tree id, int fun)
     assemble_external (ref);
   TREE_USED (ref) = 1;
 
+  if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
+    {
+      if (!in_sizeof && !in_typeof)
+       C_DECL_USED (ref) = 1;
+      else if (DECL_INITIAL (ref) == 0
+              && DECL_EXTERNAL (ref)
+              && !TREE_PUBLIC (ref))
+       record_maybe_used_decl (ref);
+    }
+
   if (TREE_CODE (ref) == CONST_DECL)
     {
       ref = DECL_INITIAL (ref);
@@ -1777,6 +1787,95 @@ build_external_ref (tree id, int fun)
   return ref;
 }
 
+/* Record details of decls possibly used inside sizeof or typeof.  */
+struct maybe_used_decl
+{
+  /* The decl.  */
+  tree decl;
+  /* The level seen at (in_sizeof + in_typeof).  */
+  int level;
+  /* The next one at this level or above, or NULL.  */
+  struct maybe_used_decl *next;
+};
+
+static struct maybe_used_decl *maybe_used_decls;
+
+/* Record that DECL, an undefined static function reference seen
+   inside sizeof or typeof, might be used if the operand of sizeof is
+   a VLA type or the operand of typeof is a variably modified
+   type.  */
+
+void
+record_maybe_used_decl (tree decl)
+{
+  struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
+  t->decl = decl;
+  t->level = in_sizeof + in_typeof;
+  t->next = maybe_used_decls;
+  maybe_used_decls = t;
+}
+
+/* Pop the stack of decls possibly used inside sizeof or typeof.  If
+   USED is false, just discard them.  If it is true, mark them used
+   (if no longer inside sizeof or typeof) or move them to the next
+   level up (if still inside sizeof or typeof).  */
+
+void
+pop_maybe_used (bool used)
+{
+  struct maybe_used_decl *p = maybe_used_decls;
+  int cur_level = in_sizeof + in_typeof;
+  while (p && p->level > cur_level)
+    {
+      if (used)
+       {
+         if (cur_level == 0)
+           C_DECL_USED (p->decl) = 1;
+         else
+           p->level = cur_level;
+       }
+      p = p->next;
+    }
+  if (!used || cur_level == 0)
+    maybe_used_decls = p;
+}
+
+/* Return the result of sizeof applied to EXPR.  */
+
+struct c_expr
+c_expr_sizeof_expr (struct c_expr expr)
+{
+  struct c_expr ret;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = c_sizeof (TREE_TYPE (expr.value));
+      ret.original_code = ERROR_MARK;
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
+  return ret;
+}
+
+/* Return the result of sizeof applied to T, a structure for the type
+   name passed to sizeof (rather than the type itself).  */
+
+struct c_expr
+c_expr_sizeof_type (struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  type = groktypename (t);
+  ret.value = c_sizeof (type);
+  ret.original_code = ERROR_MARK;
+  pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+  return ret;
+}
+
 /* Build a function call to function FUNCTION with parameters PARAMS.
    PARAMS is a list--a chain of TREE_LIST nodes--in which the
    TREE_VALUE of each node is a parameter-expression.
@@ -1818,7 +1917,7 @@ build_function_call (tree function, tree params)
   if (!(TREE_CODE (fntype) == POINTER_TYPE
        && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
     {
-      error ("called object is not a function");
+      error ("called object %qE is not a function", function);
       return error_mark_node;
     }
 
@@ -1942,7 +2041,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
       if (type == void_type_node)
        {
          if (name)
-           error ("too many arguments to function `%s'",
+           error ("too many arguments to function %qs",
                   IDENTIFIER_POINTER (name));
          else
            error ("too many arguments to function");
@@ -2004,7 +2103,9 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
                      if (formal_prec == TYPE_PRECISION (float_type_node))
-                       warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);
+                       warn_for_assignment ("%s as %<float%> rather than "
+                                            "%<double%> due to prototype",
+                                            (char *) 0, name, parmnum + 1);
                    }
                  /* Detect integer changing in width or signedness.
                     These warnings are only activated with
@@ -2081,7 +2182,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
       if (name)
-       error ("too few arguments to function `%s'",
+       error ("too few arguments to function %qs",
               IDENTIFIER_POINTER (name));
       else
        error ("too few arguments to function");
@@ -2137,7 +2238,8 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of |");
          /* Check cases like x|y==z */
-         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+         if (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison)
            warning ("suggest parentheses around comparison in operand of |");
        }
 
@@ -2149,7 +2251,8 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of ^");
          /* Check cases like x^y==z */
-         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+         if (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison)
            warning ("suggest parentheses around comparison in operand of ^");
        }
 
@@ -2159,13 +2262,14 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around + or - in operand of &");
          /* Check cases like x&y==z */
-         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+         if (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison)
            warning ("suggest parentheses around comparison in operand of &");
        }
       /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
-      if (TREE_CODE_CLASS (code) == '<'
-         && (TREE_CODE_CLASS (code1) == '<'
-             || TREE_CODE_CLASS (code2) == '<'))
+      if (TREE_CODE_CLASS (code) == tcc_comparison
+         && (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison))
        warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");
 
     }
@@ -2192,7 +2296,7 @@ pointer_diff (tree op0, tree op1)
   if (pedantic || warn_pointer_arith)
     {
       if (TREE_CODE (target_type) == VOID_TYPE)
-       pedwarn ("pointer of type `void *' used in subtraction");
+       pedwarn ("pointer of type %<void *%> used in subtraction");
       if (TREE_CODE (target_type) == FUNCTION_TYPE)
        pedwarn ("pointer to a function used in subtraction");
     }
@@ -2313,7 +2417,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
        {
          code = CONJ_EXPR;
          if (pedantic)
-           pedwarn ("ISO C does not support `~' for complex conjugation");
+           pedwarn ("ISO C does not support %<~%> for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
        }
@@ -2390,7 +2494,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          tree real, imag;
 
          if (pedantic)
-           pedwarn ("ISO C does not support `++' and `--' on complex types");
+           pedwarn ("ISO C does not support %<++%> and %<--%>"
+                    " on complex types");
 
          arg = stabilize_reference (arg);
          real = build_unary_op (REALPART_EXPR, arg, 1);
@@ -2452,8 +2557,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
-                                  ? "invalid lvalue in increment"
-                                  : "invalid lvalue in decrement")))
+                                  ? lv_increment
+                                  : lv_decrement)))
          return error_mark_node;
 
        /* Report a read-only lvalue.  */
@@ -2461,7 +2566,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          readonly_error (arg,
                          ((code == PREINCREMENT_EXPR
                            || code == POSTINCREMENT_EXPR)
-                          ? "increment" : "decrement"));
+                          ? lv_increment : lv_decrement));
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
@@ -2498,7 +2603,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
-              && !lvalue_or_else (arg, "invalid lvalue in unary `&'"))
+              && !lvalue_or_else (arg, lv_addressof))
        return error_mark_node;
 
       /* Ordinary case; arg is a COMPONENT_REF or a decl.  */
@@ -2508,45 +2613,38 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          to which the address will point.  Note that you can't get a
         restricted pointer by taking the address of something, so we
         only have to deal with `const' and `volatile' here.  */
-      if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
+      if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
          && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
          argtype = c_build_type_variant (argtype,
                                          TREE_READONLY (arg),
                                          TREE_THIS_VOLATILE (arg));
 
-      argtype = build_pointer_type (argtype);
-
       if (!c_mark_addressable (arg))
        return error_mark_node;
 
-      {
-       tree addr;
-
-       if (TREE_CODE (arg) == COMPONENT_REF)
-         {
-           tree field = TREE_OPERAND (arg, 1);
+      if (TREE_CODE (arg) == COMPONENT_REF
+         && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+       {
+         error ("attempt to take address of bit-field structure member %qD",
+                TREE_OPERAND (arg, 1));
+         return error_mark_node;
+       }
 
-           addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
+      argtype = build_pointer_type (argtype);
 
-           if (DECL_C_BIT_FIELD (field))
-             {
-               error ("attempt to take address of bit-field structure member `%s'",
-                      IDENTIFIER_POINTER (DECL_NAME (field)));
-               return error_mark_node;
-             }
+      /* ??? Cope with user tricks that amount to offsetof.  Delete this
+        when we have proper support for integer constant expressions.  */
+      val = get_base_address (arg);
+      if (val && TREE_CODE (val) == INDIRECT_REF
+         && integer_zerop (TREE_OPERAND (val, 0)))
+       return fold_convert (argtype, fold_offsetof (arg));
 
-           addr = fold (build2 (PLUS_EXPR, argtype,
-                                convert (argtype, addr),
-                                convert (argtype, byte_position (field))));
-         }
-       else
-         addr = build1 (code, argtype, arg);
+      val = build1 (ADDR_EXPR, argtype, arg);
 
-       if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
-         TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1;
+      if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
+       TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
 
-       return addr;
-      }
+      return val;
 
     default:
       break;
@@ -2596,38 +2694,73 @@ lvalue_p (tree ref)
 }
 
 /* Return nonzero if REF is an lvalue valid for this language;
-   otherwise, print an error message and return zero.  */
+   otherwise, print an error message and return zero.  USE says
+   how the lvalue is being used and so selects the error message.  */
 
 static int
-lvalue_or_else (tree ref, const char *msgid)
+lvalue_or_else (tree ref, enum lvalue_use use)
 {
   int win = lvalue_p (ref);
 
-  if (! win)
-    error ("%s", msgid);
+  if (!win)
+    {
+      switch (use)
+       {
+       case lv_assign:
+         error ("invalid lvalue in assignment");
+         break;
+       case lv_increment:
+         error ("invalid lvalue in increment");
+         break;
+       case lv_decrement:
+         error ("invalid lvalue in decrement");
+         break;
+       case lv_addressof:
+         error ("invalid lvalue in unary %<&%>");
+         break;
+       case lv_asm:
+         error ("invalid lvalue in asm statement");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+    }
 
   return win;
 }
 
 \f
-/* Warn about storing in something that is `const'.  */
+/* Give an error for storing in something that is 'const'.  */
 
-void
-readonly_error (tree arg, const char *msgid)
+static void
+readonly_error (tree arg, enum lvalue_use use)
 {
+  gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement);
+  /* Using this macro rather than (for example) arrays of messages
+     ensures that all the format strings are checked at compile
+     time.  */
+#define READONLY_MSG(A, I, D) (use == lv_assign                                \
+                              ? (A)                                    \
+                              : (use == lv_increment ? (I) : (D)))
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       readonly_error (TREE_OPERAND (arg, 0), msgid);
+       readonly_error (TREE_OPERAND (arg, 0), use);
       else
-       error ("%s of read-only member `%s'", _(msgid),
+       error (READONLY_MSG (N_("assignment of read-only member %qs"),
+                            N_("increment of read-only member %qs"),
+                            N_("decrement of read-only member %qs")),
               IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    error ("%s of read-only variable `%s'", _(msgid),
+    error (READONLY_MSG (N_("assignment of read-only variable %qs"),
+                        N_("increment of read-only variable %qs"),
+                        N_("decrement of read-only variable %qs")),
           IDENTIFIER_POINTER (DECL_NAME (arg)));
   else
-    error ("%s of read-only location", _(msgid));
+    error (READONLY_MSG (N_("assignment of read-only location"),
+                        N_("increment of read-only location"),
+                        N_("decrement of read-only location")));
 }
 \f
 /* Mark EXP saying that we need to be able to take the
@@ -2645,7 +2778,7 @@ c_mark_addressable (tree exp)
       case COMPONENT_REF:
        if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
          {
-           error ("cannot take address of bit-field `%s'",
+           error ("cannot take address of bit-field %qs",
                   IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
            return false;
          }
@@ -2673,23 +2806,23 @@ c_mark_addressable (tree exp)
          {
            if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
              {
-               error ("global register variable `%s' used in nested function",
+               error ("global register variable %qs used in nested function",
                       IDENTIFIER_POINTER (DECL_NAME (x)));
                return false;
              }
-           pedwarn ("register variable `%s' used in nested function",
+           pedwarn ("register variable %qs used in nested function",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
        else if (C_DECL_REGISTER (x))
          {
            if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
              {
-               error ("address of global register variable `%s' requested",
+               error ("address of global register variable %qs requested",
                       IDENTIFIER_POINTER (DECL_NAME (x)));
                return false;
              }
 
-           pedwarn ("address of register variable `%s' requested",
+           pedwarn ("address of register variable %qs requested",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
 
@@ -2804,14 +2937,16 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
          if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
-           pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
+           pedwarn ("ISO C forbids conditional expr between "
+                    "%<void *%> and function pointer");
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
                                                          TREE_TYPE (type2)));
        }
       else if (VOID_TYPE_P (TREE_TYPE (type2)))
        {
          if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
-           pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
+           pedwarn ("ISO C forbids conditional expr between "
+                    "%<void *%> and function pointer");
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
                                                          TREE_TYPE (type1)));
        }
@@ -2917,8 +3052,10 @@ build_c_cast (tree type, tree expr)
   /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
      only in <protocol> qualifications.  But when constructing cast expressions,
      the protocols do matter and must be kept around.  */
-  if (!c_dialect_objc () || !objc_is_object_ptr (type))
-    type = TYPE_MAIN_VARIANT (type);
+  if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
+    return build1 (NOP_EXPR, type, expr);
+
+  type = TYPE_MAIN_VARIANT (type);
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -3047,7 +3184,8 @@ build_c_cast (tree type, tree expr)
       if (warn_bad_function_cast
          && TREE_CODE (value) == CALL_EXPR
          && TREE_CODE (type) != TREE_CODE (otype))
-       warning ("cast does not match function type");
+       warning ("cast from function call of type %qT to non-matching "
+                "type %qT", otype, type);
 
       if (TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == INTEGER_TYPE
@@ -3108,9 +3246,16 @@ build_c_cast (tree type, tree expr)
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST)
        {
-         TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
-
-         if (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c')
+         if (EXPR_P (ovalue))
+           /* If OVALUE had overflow set, then so will VALUE, so it
+              is safe to overwrite.  */
+           TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+         else
+           TREE_OVERFLOW (value) = 0;
+         
+         if (CONSTANT_CLASS_P (ovalue))
+           /* Similarly, constant_overflow cannot have become
+              cleared.  */
            TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
        }
     }
@@ -3130,15 +3275,16 @@ build_c_cast (tree type, tree expr)
 
 /* Interpret a cast of expression EXPR to type TYPE.  */
 tree
-c_cast_expr (tree type, tree expr)
+c_cast_expr (struct c_type_name *type_name, tree expr)
 {
+  tree type;
   int saved_wsp = warn_strict_prototypes;
 
   /* This avoids warnings about unprototyped casts on
      integers.  E.g. "#define SIG_DFL (void(*)())0".  */
   if (TREE_CODE (expr) == INTEGER_CST)
     warn_strict_prototypes = 0;
-  type = groktypename (type);
+  type = groktypename (type_name);
   warn_strict_prototypes = saved_wsp;
 
   return build_c_cast (type, expr);
@@ -3182,16 +3328,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
-  if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
+  if (!lvalue_or_else (lhs, lv_assign))
     return error_mark_node;
 
-  /* Warn about storing in something that is `const'.  */
+  /* Give an error for storing in something that is 'const'.  */
 
   if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
-    readonly_error (lhs, "assignment");
+    readonly_error (lhs, lv_assign);
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
@@ -3221,7 +3367,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
 
-  /* Scan operands */
+  /* Scan operands */
 
   result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
@@ -3319,7 +3465,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
       return rhs;
     }
   /* Some types can interconvert without explicit casts.  */
-  else if (codel == VECTOR_TYPE
+  else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
            && vector_types_convertible_p (type, TREE_TYPE (rhs)))
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
@@ -3456,7 +3602,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                      which are not ANSI null ptr constants.  */
                   && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           warn_for_assignment ("ISO C forbids %s between function pointer and `void *'",
+           warn_for_assignment ("ISO C forbids %s between function "
+                                "pointer and %<void *%>",
                                 errtype, funname, parmnum);
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
@@ -3530,10 +3677,10 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
          tree selector = objc_message_selector ();
 
          if (selector && parmnum > 2)
-           error ("incompatible type for argument %d of `%s'",
+           error ("incompatible type for argument %d of %qs",
                   parmnum - 2, IDENTIFIER_POINTER (selector));
          else
-           error ("incompatible type for argument %d of `%s'",
+           error ("incompatible type for argument %d of %qs",
                   parmnum, IDENTIFIER_POINTER (funname));
        }
       else
@@ -3573,8 +3720,7 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
 
 /* Print a warning using MSGID.
    It gets OPNAME as its one parameter.
-   if OPNAME is null and ARGNUM is 0, it is replaced by "passing arg of `FUNCTION'".
-   Otherwise if OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'".
+   If OPNAME is null, it is replaced by "passing arg ARGNUM of 'FUNCTION'".
    FUNCTION and ARGNUM are handled specially if we are building an
    Objective-C selector.  */
 
@@ -3592,29 +3738,11 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
          function = selector;
          argnum -= 2;
        }
-      if (argnum == 0)
-       {
-         if (function)
-           {
-             /* Function name is known; supply it.  */
-             const char *const argstring = _("passing arg of `%s'");
-             new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
-                                  + strlen (argstring) + 1 + 1);
-             sprintf (new_opname, argstring,
-                      IDENTIFIER_POINTER (function));
-           }
-         else
-           {
-             /* Function name unknown (call through ptr).  */
-             const char *const argnofun = _("passing arg of pointer to function");
-             new_opname = (char *) alloca (strlen (argnofun) + 1 + 1);
-             sprintf (new_opname, argnofun);
-           }
-       }
-      else if (function)
+      gcc_assert (argnum > 0);
+      if (function)
        {
          /* Function name is known; supply it.  */
-         const char *const argstring = _("passing arg %d of `%s'");
+         const char *const argstring = _("passing arg %d of '%s'");
          new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
                               + strlen (argstring) + 1 + 25 /*%d*/ + 1);
          sprintf (new_opname, argstring, argnum,
@@ -3649,8 +3777,7 @@ valid_compound_expr_initializer (tree value, tree endtype)
       return valid_compound_expr_initializer (TREE_OPERAND (value, 1),
                                              endtype);
     }
-  else if (! TREE_CONSTANT (value)
-          && ! initializer_constant_valid_p (value, endtype))
+  else if (!initializer_constant_valid_p (value, endtype))
     return error_mark_node;
   else
     return value;
@@ -3848,7 +3975,7 @@ error_init (const char *msgid)
   error ("%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    error ("(near initialization for `%s')", ofwhat);
+    error ("(near initialization for %qs)", ofwhat);
 }
 
 /* Issue a pedantic warning for a bad initializer component.
@@ -3863,7 +3990,7 @@ pedwarn_init (const char *msgid)
   pedwarn ("%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    pedwarn ("(near initialization for `%s')", ofwhat);
+    pedwarn ("(near initialization for %qs)", ofwhat);
 }
 
 /* Issue a warning for a bad initializer component.
@@ -3878,7 +4005,7 @@ warning_init (const char *msgid)
   warning ("%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    warning ("(near initialization for `%s')", ofwhat);
+    warning ("(near initialization for %qs)", ofwhat);
 }
 \f
 /* If TYPE is an array type and EXPR is a parenthesized string
@@ -3995,6 +4122,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
      vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
      below and handle as a constructor.  */
     if (code == VECTOR_TYPE
+       && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
         && vector_types_convertible_p (TREE_TYPE (inside_init), type)
         && TREE_CONSTANT (inside_init))
       {
@@ -4078,16 +4206,8 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
            inside_init = error_mark_node;
        }
       else if (require_constant
-              && (!TREE_CONSTANT (inside_init)
-                  /* This test catches things like `7 / 0' which
-                     result in an expression for which TREE_CONSTANT
-                     is true, but which is not actually something
-                     that is a legal constant.  We really should not
-                     be using this function, because it is a part of
-                     the back-end.  Instead, the expression should
-                     already have been turned into ERROR_MARK_NODE.  */
-                  || !initializer_constant_valid_p (inside_init,
-                                                    TREE_TYPE (inside_init))))
+              && !initializer_constant_valid_p (inside_init,
+                                                TREE_TYPE (inside_init)))
        {
          error_init ("initializer element is not constant");
          inside_init = error_mark_node;
@@ -4109,13 +4229,17 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
        = convert_for_assignment (type, init, _("initialization"),
                                  NULL_TREE, NULL_TREE, 0);
 
-      if (require_constant && ! TREE_CONSTANT (inside_init))
+      /* Check to see if we have already given an error message.  */
+      if (inside_init == error_mark_node)
+       ;
+      else if (require_constant && ! TREE_CONSTANT (inside_init))
        {
          error_init ("initializer element is not constant");
          inside_init = error_mark_node;
        }
       else if (require_constant
-              && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
+              && !initializer_constant_valid_p (inside_init,
+                                                TREE_TYPE (inside_init)))
        {
          error_init ("initializer element is not computable at load time");
          inside_init = error_mark_node;
@@ -4212,9 +4336,6 @@ int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages.  */
    such as (struct foo) {...}.  */
 static tree constructor_decl;
 
-/* start_init saves the ASMSPEC arg here for really_start_incremental_init.  */
-static const char *constructor_asmspec;
-
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
 
@@ -4286,7 +4407,6 @@ struct initializer_stack
 {
   struct initializer_stack *next;
   tree decl;
-  const char *asmspec;
   struct constructor_stack *constructor_stack;
   struct constructor_range_stack *constructor_range_stack;
   tree elements;
@@ -4303,17 +4423,12 @@ struct initializer_stack *initializer_stack;
 /* Prepare to parse and output the initializer for variable DECL.  */
 
 void
-start_init (tree decl, tree asmspec_tree, int top_level)
+start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
 {
   const char *locus;
-  struct initializer_stack *p = XNEW (struct initializer_stack);
-  const char *asmspec = 0;
-
-  if (asmspec_tree)
-    asmspec = TREE_STRING_POINTER (asmspec_tree);
+  struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
 
   p->decl = constructor_decl;
-  p->asmspec = constructor_asmspec;
   p->require_constant_value = require_constant_value;
   p->require_constant_elements = require_constant_elements;
   p->constructor_stack = constructor_stack;
@@ -4327,7 +4442,6 @@ start_init (tree decl, tree asmspec_tree, int top_level)
   initializer_stack = p;
 
   constructor_decl = decl;
-  constructor_asmspec = asmspec;
   constructor_designated = 0;
   constructor_top_level = top_level;
 
@@ -4377,14 +4491,12 @@ finish_init (void)
       free (q);
     }
 
-  if (constructor_range_stack)
-    abort ();
+  gcc_assert (!constructor_range_stack);
 
   /* Pop back to the data of the outer initializer (if any).  */
   free (spelling_base);
 
   constructor_decl = p->decl;
-  constructor_asmspec = p->asmspec;
   require_constant_value = p->require_constant_value;
   require_constant_elements = p->require_constant_elements;
   constructor_stack = p->constructor_stack;
@@ -4472,14 +4584,14 @@ really_start_incremental_init (tree type)
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
-           constructor_max_index = build_int_cst (NULL_TREE, -1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          constructor_index
            = convert (bitsizetype,
@@ -4494,8 +4606,7 @@ really_start_incremental_init (tree type)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_cst (NULL_TREE,
-                      TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0);
+       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       constructor_index = convert (bitsizetype, bitsize_zero_node);
       constructor_unfilled_index = constructor_index;
     }
@@ -4650,8 +4761,7 @@ push_init_level (int implicit)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_cst (NULL_TREE,
-                      TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0);
+       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       constructor_index = convert (bitsizetype, integer_zero_node);
       constructor_unfilled_index = constructor_index;
     }
@@ -4665,14 +4775,14 @@ push_init_level (int implicit)
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
-           constructor_max_index = build_int_cst (NULL_TREE, -1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          constructor_index
            = convert (bitsizetype,
@@ -4724,8 +4834,7 @@ pop_init_level (int implicit)
       while (constructor_stack->implicit)
        process_init_element (pop_init_level (1));
 
-      if (constructor_range_stack)
-       abort ();
+      gcc_assert (!constructor_range_stack);
     }
 
   /* Now output all pending elements.  */
@@ -4745,8 +4854,10 @@ pop_init_level (int implicit)
         already have pedwarned for empty brackets.  */
       if (integer_zerop (constructor_unfilled_index))
        constructor_type = NULL_TREE;
-      else if (! TYPE_SIZE (constructor_type))
+      else
        {
+         gcc_assert (!TYPE_SIZE (constructor_type));
+         
          if (constructor_depth > 2)
            error_init ("initialization of flexible array member in a nested context");
          else if (pedantic)
@@ -4758,10 +4869,6 @@ pop_init_level (int implicit)
          if (TREE_CHAIN (constructor_fields) != NULL_TREE)
            constructor_type = NULL_TREE;
        }
-      else
-       /* Zero-length arrays are no longer special, so we should no longer
-          get here.  */
-       abort ();
     }
 
   /* Warn when some struct elements are implicitly initialized to zero.  */
@@ -4877,14 +4984,14 @@ set_designator (int array)
   if (constructor_type == 0)
     return 1;
 
-  /* If there were errors in this designator list already, bail out silently.  */
+  /* If there were errors in this designator list already, bail out
+     silently.  */
   if (designator_errorneous)
     return 1;
 
   if (!designator_depth)
     {
-      if (constructor_range_stack)
-       abort ();
+      gcc_assert (!constructor_range_stack);
 
       /* Designator list starts at the level of closest explicit
         braces.  */
@@ -4900,19 +5007,20 @@ set_designator (int array)
       return 1;
     }
 
-  if (TREE_CODE (constructor_type) == RECORD_TYPE
-      || TREE_CODE (constructor_type) == UNION_TYPE)
+  switch (TREE_CODE (constructor_type))
     {
+    case  RECORD_TYPE:
+    case  UNION_TYPE:
       subtype = TREE_TYPE (constructor_fields);
       if (subtype != error_mark_node)
        subtype = TYPE_MAIN_VARIANT (subtype);
-    }
-  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    {
+      break;
+    case ARRAY_TYPE:
       subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+      break;
+    default:
+      gcc_unreachable ();
     }
-  else
-    abort ();
 
   subcode = TREE_CODE (subtype);
   if (array && subcode != ARRAY_TYPE)
@@ -5057,7 +5165,7 @@ set_init_label (tree fieldname)
     }
 
   if (tail == 0)
-    error ("unknown field `%s' specified in initializer",
+    error ("unknown field %qs specified in initializer",
           IDENTIFIER_POINTER (fieldname));
   else
     {
@@ -5332,18 +5440,17 @@ set_nonincremental_init_from_string (tree str)
   const char *p, *end;
   int byte, wchar_bytes, charwidth, bitpos;
 
-  if (TREE_CODE (constructor_type) != ARRAY_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE);
 
   if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
       == TYPE_PRECISION (char_type_node))
     wchar_bytes = 1;
-  else if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
-          == TYPE_PRECISION (wchar_type_node))
-    wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
   else
-    abort ();
-
+    {
+      gcc_assert (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
+                 == TYPE_PRECISION (wchar_type_node));
+      wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+    }
   charwidth = TYPE_PRECISION (char_type_node);
   type = TREE_TYPE (constructor_type);
   p = TREE_STRING_POINTER (str);
@@ -5396,7 +5503,7 @@ set_nonincremental_init_from_string (tree str)
                      << (bitpos - HOST_BITS_PER_WIDE_INT);
        }
 
-      value = build_int_cst (type, val[1], val[0]);
+      value = build_int_cst_wide (type, val[1], val[0]);
       add_pending_init (purpose, value);
     }
 
@@ -5503,21 +5610,23 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
     constructor_erroneous = 1;
   else if (!TREE_CONSTANT (value))
     constructor_constant = 0;
-  else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0
+  else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
           || ((TREE_CODE (constructor_type) == RECORD_TYPE
                || TREE_CODE (constructor_type) == UNION_TYPE)
               && DECL_C_BIT_FIELD (field)
               && TREE_CODE (value) != INTEGER_CST))
     constructor_simple = 0;
 
-  if (require_constant_value && ! TREE_CONSTANT (value))
+  if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
     {
-      error_init ("initializer element is not constant");
-      value = error_mark_node;
+      if (require_constant_value)
+       {
+         error_init ("initializer element is not constant");
+         value = error_mark_node;
+       }
+      else if (require_constant_elements)
+       pedwarn ("initializer element is not computable at load time");
     }
-  else if (require_constant_elements
-          && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
-    pedwarn ("initializer element is not computable at load time");
 
   /* If this field is empty (and not at the end of structure),
      don't do anything other than checking the initializer.  */
@@ -6085,16 +6194,14 @@ process_init_element (struct c_expr value)
          constructor_range_stack = 0;
          while (constructor_stack != range_stack->stack)
            {
-             if (!constructor_stack->implicit)
-               abort ();
+             gcc_assert (constructor_stack->implicit);
              process_init_element (pop_init_level (1));
            }
          for (p = range_stack;
               !p->range_end || tree_int_cst_equal (p->index, p->range_end);
               p = p->prev)
            {
-             if (!constructor_stack->implicit)
-               abort ();
+             gcc_assert (constructor_stack->implicit);
              process_init_element (pop_init_level (1));
            }
 
@@ -6168,7 +6275,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
       tree output = TREE_VALUE (tail);
       STRIP_NOPS (output);
       TREE_VALUE (tail) = output;
-      lvalue_or_else (output, "invalid lvalue in asm statement");
+      lvalue_or_else (output, lv_asm);
 
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
 
@@ -6227,7 +6334,7 @@ tree
 c_finish_goto_ptr (tree expr)
 {
   if (pedantic)
-    pedwarn ("ISO C forbids `goto *expr;'");
+    pedwarn ("ISO C forbids %<goto *expr;%>");
   expr = convert (ptr_type_node, expr);
   return add_stmt (build1 (GOTO_EXPR, void_type_node, expr));
 }
@@ -6241,20 +6348,21 @@ c_finish_return (tree retval)
   tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
 
   if (TREE_THIS_VOLATILE (current_function_decl))
-    warning ("function declared `noreturn' has a `return' statement");
+    warning ("function declared %<noreturn%> has a %<return%> statement");
 
   if (!retval)
     {
       current_function_returns_null = 1;
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
-       pedwarn_c99 ("`return' with no value, in function returning non-void");
+       pedwarn_c99 ("%<return%> with no value, in "
+                    "function returning non-void");
     }
   else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
     {
       current_function_returns_null = 1;
       if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
-       pedwarn ("`return' with a value, in function returning void");
+       pedwarn ("%<return%> with a value, in function returning void");
     }
   else
     {
@@ -6303,7 +6411,8 @@ c_finish_return (tree retval)
            case ADDR_EXPR:
              inner = TREE_OPERAND (inner, 0);
 
-             while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
+             while (REFERENCE_CLASS_P (inner)
+                    && TREE_CODE (inner) != INDIRECT_REF)
                inner = TREE_OPERAND (inner, 0);
 
              if (DECL_P (inner)
@@ -6330,7 +6439,7 @@ struct c_switch {
   /* The SWITCH_STMT being built.  */
   tree switch_stmt;
 
-  /* The original type of the testing expression, ie. before the
+  /* The original type of the testing expression, i.e. before the
      default conversion is applied.  */
   tree orig_type;
 
@@ -6381,7 +6490,8 @@ c_start_case (tree exp)
          if (warn_traditional && !in_system_header
              && (type == long_integer_type_node
                  || type == long_unsigned_type_node))
-           warning ("`long' switch expression not converted to `int' in ISO C");
+           warning ("%<long%> switch expression not converted to "
+                    "%<int%> in ISO C");
 
          exp = default_conversion (exp);
          type = TREE_TYPE (exp);
@@ -6419,7 +6529,7 @@ do_case (tree low_value, tree high_value)
   else if (low_value)
     error ("case label not within a switch statement");
   else
-    error ("`default' label not within a switch statement");
+    error ("%<default%> label not within a switch statement");
 
   return label;
 }
@@ -6478,12 +6588,12 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
            inner_if = TREE_OPERAND (inner_if, 0);
            break;
          default:
-           abort ();
+           gcc_unreachable ();
          }
     found:
 
       if (COND_EXPR_ELSE (inner_if))
-        warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
+        warning ("%Hsuggest explicit braces to avoid ambiguous %<else%>",
                  &if_locus);
     }
 
@@ -6649,7 +6759,7 @@ c_process_expr_stmt (tree expr)
 
   /* If the expression is not of a type to which we cannot assign a line
      number, wrap the thing in a no-op NOP_EXPR.  */
-  if (DECL_P (expr) || TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
+  if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
     expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
 
   if (EXPR_P (expr))
@@ -7140,13 +7250,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 whose value is 0 but which isn't a valid null ptr const.  */
              if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
                  && TREE_CODE (tt1) == FUNCTION_TYPE)
-               pedwarn ("ISO C forbids comparison of `void *' with function pointer");
+               pedwarn ("ISO C forbids comparison of %<void *%>"
+                        " with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
              if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
                  && TREE_CODE (tt0) == FUNCTION_TYPE)
-               pedwarn ("ISO C forbids comparison of `void *' with function pointer");
+               pedwarn ("ISO C forbids comparison of %<void *%>"
+                        " with function pointer");
            }
          else
            pedwarn ("comparison of distinct pointer types lacks a cast");
@@ -7548,6 +7660,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        op0 = convert (result_type, op0);
       if (TREE_TYPE (op1) != result_type)
        op1 = convert (result_type, op1);
+
+      /* This can happen if one operand has a vector type, and the other
+        has a different type.  */
+      if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+       return error_mark_node;
     }
 
   if (build_type == NULL_TREE)
@@ -7565,31 +7682,3 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     return result;
   }
 }
-
-/* Build the result of __builtin_offsetof.  TYPE is the first argument to
-   offsetof, i.e. a type.  LIST is a tree_list that encodes component and
-   array references; PURPOSE is set for the former and VALUE is set for
-   the later.  */
-
-tree
-build_offsetof (tree type, tree list)
-{
-  tree t;
-
-  /* Build "*(type *)0".  */
-  t = convert (build_pointer_type (type), null_pointer_node);
-  t = build_indirect_ref (t, "");
-
-  /* Build COMPONENT and ARRAY_REF expressions as needed.  */
-  for (list = nreverse (list); list ; list = TREE_CHAIN (list))
-    if (TREE_PURPOSE (list))
-      t = build_component_ref (t, TREE_PURPOSE (list));
-    else
-      t = build_array_ref (t, TREE_VALUE (list));
-
-  /* Finalize the offsetof expression.  For now all we need to do is take
-     the address of the expression we created, and cast that to an integer
-     type; this mirrors the traditional macro implementation of offsetof.  */
-  t = build_unary_op (ADDR_EXPR, t, 0);
-  return convert (size_type_node, t);
-}