OSDN Git Service

Fix ICE on invalid input, and eliminate confusing error message.
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 04ed068..a815e2f 100644 (file)
@@ -44,6 +44,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-iterator.h"
 #include "tree-gimple.h"
 
+/* 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.  */
@@ -157,7 +165,7 @@ c_incomplete_type_error (tree value, tree type)
          return;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
@@ -240,8 +248,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 +268,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 +418,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 +476,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
@@ -744,7 +747,7 @@ same_translation_unit_p (tree t1, tree t2)
       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 ();
+      default: gcc_unreachable ();
       }
 
   while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
@@ -753,7 +756,7 @@ same_translation_unit_p (tree t1, tree 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 ();
+      default: gcc_unreachable ();
       }
 
   return t1 == t2;
@@ -935,7 +938,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
       }
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -958,9 +961,9 @@ function_types_compatible_p (tree f1, tree f2)
   ret1 = TREE_TYPE (f1);
   ret2 = TREE_TYPE (f2);
 
-  /* 'volatile' qualifiers on a function's return type mean the function
-     is noreturn.  */
-  if (pedantic && TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
+  /* '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'");
   if (TYPE_VOLATILE (ret1))
     ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
@@ -1217,8 +1220,8 @@ default_function_array_conversion (tree exp)
       if (TREE_CODE (exp) == COMPOUND_EXPR)
        {
          tree op1 = default_conversion (TREE_OPERAND (exp, 1));
-         return build (COMPOUND_EXPR, TREE_TYPE (op1),
-                       TREE_OPERAND (exp, 0), op1);
+         return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
+                        TREE_OPERAND (exp, 0), op1);
        }
 
       lvalue_array_p = !not_lvalue && lvalue_p (exp);
@@ -1456,8 +1459,8 @@ build_component_ref (tree datum, tree component)
     case COMPOUND_EXPR:
       {
        tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
-       return build (COMPOUND_EXPR, TREE_TYPE (value),
-                     TREE_OPERAND (datum, 0), non_lvalue (value));
+       return build2 (COMPOUND_EXPR, TREE_TYPE (value),
+                      TREE_OPERAND (datum, 0), non_lvalue (value));
       }
     default:
       break;
@@ -1495,8 +1498,8 @@ build_component_ref (tree datum, tree component)
          if (TREE_TYPE (subdatum) == error_mark_node)
            return error_mark_node;
 
-         ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum,
-                      NULL_TREE);
+         ref = build3 (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum,
+                       NULL_TREE);
          if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
          if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
@@ -1649,7 +1652,7 @@ build_array_ref (tree array, tree index)
        }
 
       type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
-      rval = build (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
+      rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
          or if the array is.  */
       TREE_READONLY (rval)
@@ -1715,7 +1718,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)
     {
@@ -1756,6 +1759,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 +1790,86 @@ 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;
+  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.
@@ -1869,7 +1962,7 @@ build_function_call (tree function, tree params)
          else
            rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node));
 
-         return build (COMPOUND_EXPR, return_type, trap, rhs);
+         return build2 (COMPOUND_EXPR, return_type, trap, rhs);
        }
     }
 
@@ -1883,8 +1976,8 @@ build_function_call (tree function, tree params)
 
   check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
 
-  result = build (CALL_EXPR, TREE_TYPE (fntype),
-                 function, coerced_params, NULL_TREE);
+  result = build3 (CALL_EXPR, TREE_TYPE (fntype),
+                  function, coerced_params, NULL_TREE);
   TREE_SIDE_EFFECTS (result) = 1;
 
   if (require_constant_value)
@@ -1975,7 +2068,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                 differ from the default conversions.  */
              if (warn_conversion || warn_traditional)
                {
-                 int formal_prec = TYPE_PRECISION (type);
+                 unsigned int formal_prec = TYPE_PRECISION (type);
 
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
@@ -2246,7 +2339,7 @@ pointer_diff (tree op0, tree op1)
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
-  return fold (build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)));
+  return fold (build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)));
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -2395,8 +2488,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          arg = stabilize_reference (arg);
          real = build_unary_op (REALPART_EXPR, arg, 1);
          imag = build_unary_op (IMAGPART_EXPR, arg, 1);
-         return build (COMPLEX_EXPR, TREE_TYPE (arg),
-                       build_unary_op (code, real, 1), imag);
+         return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+                        build_unary_op (code, real, 1), imag);
        }
 
       /* Report invalid types.  */
@@ -2466,7 +2559,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
        else
-         val = build (code, TREE_TYPE (arg), arg, inc);
+         val = build2 (code, TREE_TYPE (arg), arg, inc);
        TREE_SIDE_EFFECTS (val) = 1;
        val = convert (result_type, val);
        if (TREE_CODE (val) != code)
@@ -2514,39 +2607,24 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
                                          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);
-
-           addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
-
-           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;
-             }
+      if (TREE_CODE (arg) == COMPONENT_REF
+         && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+       {
+         error ("attempt to take address of bit-field structure member `%D'",
+                TREE_OPERAND (arg, 1));
+         return error_mark_node;
+       }
 
-           addr = fold (build (PLUS_EXPR, argtype,
-                               convert (argtype, addr),
-                               convert (argtype, byte_position (field))));
-         }
-       else
-         addr = build1 (code, argtype, arg);
+      argtype = build_pointer_type (argtype);
+      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;
@@ -2867,7 +2945,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   if (TREE_CODE (ifexp) == INTEGER_CST)
     return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
 
-  return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
+  return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2));
 }
 \f
 /* Return a compound expression that performs two expressions and
@@ -2901,7 +2979,7 @@ build_compound_expr (tree expr1, tree expr2)
   else if (warn_unused_value)
     warn_if_unused_value (expr1, input_location);
 
-  return build (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
+  return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
 }
 
 /* Build an expression representing a cast to type TYPE of expression EXPR.  */
@@ -2917,8 +2995,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)
     {
@@ -3108,9 +3188,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 (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 (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c')
+           /* Similarly, constant_overflow cannot have become
+              cleared.  */
            TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
        }
     }
@@ -3130,15 +3217,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);
@@ -3223,7 +3311,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   /* Scan operands */
 
-  result = build (MODIFY_EXPR, lhstype, lhs, newrhs);
+  result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
 
   /* If we got the LHS in a different type for storing in,
@@ -3319,7 +3407,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.  */
@@ -3472,7 +3560,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                       || target_cmp)
                ;
              /* If there is a mismatch, do warn.  */
-             else if (pedantic)
+             else
                warn_for_assignment ("pointer targets in %s differ in signedness",
                                     errtype, funname, parmnum);
            }
@@ -3598,7 +3686,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
            {
              /* Function name is known; supply it.  */
              const char *const argstring = _("passing arg of `%s'");
-             new_opname = alloca (IDENTIFIER_LENGTH (function)
+             new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
                                   + strlen (argstring) + 1 + 1);
              sprintf (new_opname, argstring,
                       IDENTIFIER_POINTER (function));
@@ -3607,7 +3695,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
            {
              /* Function name unknown (call through ptr).  */
              const char *const argnofun = _("passing arg of pointer to function");
-             new_opname = alloca (strlen (argnofun) + 1 + 1);
+             new_opname = (char *) alloca (strlen (argnofun) + 1 + 1);
              sprintf (new_opname, argnofun);
            }
        }
@@ -3615,7 +3703,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
        {
          /* Function name is known; supply it.  */
          const char *const argstring = _("passing arg %d of `%s'");
-         new_opname = alloca (IDENTIFIER_LENGTH (function)
+         new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
                               + strlen (argstring) + 1 + 25 /*%d*/ + 1);
          sprintf (new_opname, argstring, argnum,
                   IDENTIFIER_POINTER (function));
@@ -3624,7 +3712,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
        {
          /* Function name unknown (call through ptr); just give arg number.  */
          const char *const argnofun = _("passing arg %d of pointer to function");
-         new_opname = alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
+         new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
          sprintf (new_opname, argnofun, argnum);
        }
       opname = new_opname;
@@ -3649,8 +3737,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;
@@ -3755,11 +3842,8 @@ static int spelling_size;                /* Size of the spelling stack.  */
   if (depth >= spelling_size)                                          \
     {                                                                  \
       spelling_size += 10;                                             \
-      if (spelling_base == 0)                                          \
-       spelling_base = xmalloc (spelling_size * sizeof (struct spelling)); \
-      else                                                             \
-        spelling_base = xrealloc (spelling_base,               \
-                                 spelling_size * sizeof (struct spelling)); \
+      spelling_base = XRESIZEVEC (struct spelling, spelling_base,      \
+                                 spelling_size);                       \
       RESTORE_SPELLING_DEPTH (depth);                                  \
     }                                                                  \
                                                                        \
@@ -3849,7 +3933,7 @@ error_init (const char *msgid)
   char *ofwhat;
 
   error ("%s", _(msgid));
-  ofwhat = print_spelling (alloca (spelling_length () + 1));
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     error ("(near initialization for `%s')", ofwhat);
 }
@@ -3864,7 +3948,7 @@ pedwarn_init (const char *msgid)
   char *ofwhat;
 
   pedwarn ("%s", _(msgid));
-  ofwhat = print_spelling (alloca (spelling_length () + 1));
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     pedwarn ("(near initialization for `%s')", ofwhat);
 }
@@ -3879,7 +3963,7 @@ warning_init (const char *msgid)
   char *ofwhat;
 
   warning ("%s", _(msgid));
-  ofwhat = print_spelling (alloca (spelling_length () + 1));
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     warning ("(near initialization for `%s')", ofwhat);
 }
@@ -3930,37 +4014,41 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
   /* Initialization of an array of chars from a string constant
      optionally enclosed in braces.  */
 
-  if (code == ARRAY_TYPE)
+  if (code == ARRAY_TYPE && inside_init
+      && TREE_CODE (inside_init) == STRING_CST)
     {
       tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      if ((typ1 == char_type_node
-          || typ1 == signed_char_type_node
-          || typ1 == unsigned_char_type_node
-          || typ1 == unsigned_wchar_type_node
-          || typ1 == signed_wchar_type_node)
-         && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
+      /* Note that an array could be both an array of character type
+        and an array of wchar_t if wchar_t is signed char or unsigned
+        char.  */
+      bool char_array = (typ1 == char_type_node
+                        || typ1 == signed_char_type_node
+                        || typ1 == unsigned_char_type_node);
+      bool wchar_array = !!comptypes (typ1, wchar_type_node);
+      if (char_array || wchar_array)
        {
          struct c_expr expr;
+         bool char_string;
          expr.value = inside_init;
          expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
          maybe_warn_string_init (type, expr);
 
+         char_string
+           = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
+              == char_type_node);
+
          if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
                         TYPE_MAIN_VARIANT (type)))
            return inside_init;
 
-         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
-              != char_type_node)
-             && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
+         if (!wchar_array && !char_string)
            {
              error_init ("char-array initialized from wide string");
              return error_mark_node;
            }
-         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
-              == char_type_node)
-             && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
+         if (char_string && !char_array)
            {
-             error_init ("int-array initialized from non-wide string");
+             error_init ("wchar_t-array initialized from non-wide string");
              return error_mark_node;
            }
 
@@ -3982,12 +4070,19 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
          return inside_init;
        }
+      else if (INTEGRAL_TYPE_P (typ1))
+       {
+         error_init ("array of inappropriate type initialized "
+                     "from string constant");
+         return error_mark_node;
+       }
     }
 
   /* Build a VECTOR_CST from a *constant* vector constructor.  If the
      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))
       {
@@ -4071,16 +4166,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;
@@ -4102,13 +4189,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;
@@ -4299,7 +4390,7 @@ void
 start_init (tree decl, tree asmspec_tree, int top_level)
 {
   const char *locus;
-  struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
+  struct initializer_stack *p = XNEW (struct initializer_stack);
   const char *asmspec = 0;
 
   if (asmspec_tree)
@@ -4370,8 +4461,7 @@ 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);
@@ -4401,7 +4491,7 @@ finish_init (void)
 void
 really_start_incremental_init (tree type)
 {
-  struct constructor_stack *p = xmalloc (sizeof (struct constructor_stack));
+  struct constructor_stack *p = XNEW (struct constructor_stack);
 
   if (type == 0)
     type = TREE_TYPE (constructor_decl);
@@ -4465,14 +4555,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_2 (-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_2 (-1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          constructor_index
            = convert (bitsizetype,
@@ -4487,7 +4577,7 @@ really_start_incremental_init (tree type)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_2 (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;
     }
@@ -4538,7 +4628,7 @@ push_init_level (int implicit)
        value = find_init_member (constructor_index);
     }
 
-  p = xmalloc (sizeof (struct constructor_stack));
+  p = XNEW (struct constructor_stack);
   p->type = constructor_type;
   p->fields = constructor_fields;
   p->index = constructor_index;
@@ -4642,7 +4732,7 @@ push_init_level (int implicit)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_2 (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;
     }
@@ -4656,14 +4746,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_2 (-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_2 (-1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          constructor_index
            = convert (bitsizetype,
@@ -4715,8 +4805,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.  */
@@ -4736,8 +4825,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)
@@ -4749,14 +4840,10 @@ 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.  */
-  if (extra_warnings
+  if (warn_missing_field_initializers
       && constructor_type
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
@@ -4868,14 +4955,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.  */
@@ -4891,19 +4978,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)
@@ -4931,7 +5019,7 @@ push_range_stack (tree range_end)
 {
   struct constructor_range_stack *p;
 
-  p = ggc_alloc (sizeof (struct constructor_range_stack));
+  p = GGC_NEW (struct constructor_range_stack);
   p->prev = constructor_range_stack;
   p->next = 0;
   p->fields = constructor_fields;
@@ -5112,7 +5200,7 @@ add_pending_init (tree purpose, tree value)
        }
     }
 
-  r = ggc_alloc (sizeof (struct init_node));
+  r = GGC_NEW (struct init_node);
   r->purpose = purpose;
   r->value = value;
 
@@ -5323,18 +5411,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);
@@ -5387,8 +5474,7 @@ set_nonincremental_init_from_string (tree str)
                      << (bitpos - HOST_BITS_PER_WIDE_INT);
        }
 
-      value = build_int_2 (val[1], val[0]);
-      TREE_TYPE (value) = type;
+      value = build_int_cst_wide (type, val[1], val[0]);
       add_pending_init (purpose, value);
     }
 
@@ -5476,7 +5562,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
       || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
          && !(TREE_CODE (value) == STRING_CST
               && TREE_CODE (type) == ARRAY_TYPE
-              && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+              && INTEGRAL_TYPE_P (TREE_TYPE (type)))
          && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
                         TYPE_MAIN_VARIANT (type))))
     value = default_conversion (value);
@@ -5495,21 +5581,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.  */
@@ -5776,7 +5864,7 @@ process_init_element (struct c_expr value)
   if (string_flag
       && constructor_type
       && TREE_CODE (constructor_type) == ARRAY_TYPE
-      && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
+      && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type))
       && integer_zerop (constructor_unfilled_index))
     {
       if (constructor_stack->replacement_value.value)
@@ -5855,7 +5943,7 @@ process_init_element (struct c_expr value)
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
              && fieldcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
              && string_flag)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
@@ -5943,7 +6031,7 @@ process_init_element (struct c_expr value)
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
              && fieldcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
              && string_flag)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
@@ -5983,7 +6071,7 @@ process_init_element (struct c_expr value)
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
              && eltcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (elttype))
              && string_flag)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
@@ -6077,16 +6165,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));
            }
 
@@ -6210,7 +6296,7 @@ c_finish_goto_label (tree label)
     return NULL_TREE;
 
   TREE_USED (decl) = 1;
-  return add_stmt (build (GOTO_EXPR, void_type_node, decl));
+  return add_stmt (build1 (GOTO_EXPR, void_type_node, decl));
 }
 
 /* Generate a computed goto statement to EXPR.  */
@@ -6221,7 +6307,7 @@ c_finish_goto_ptr (tree expr)
   if (pedantic)
     pedwarn ("ISO C forbids `goto *expr;'");
   expr = convert (ptr_type_node, expr);
-  return add_stmt (build (GOTO_EXPR, void_type_node, expr));
+  return add_stmt (build1 (GOTO_EXPR, void_type_node, expr));
 }
 
 /* Generate a C `return' statement.  RETVAL is the expression for what
@@ -6295,7 +6381,8 @@ c_finish_return (tree retval)
            case ADDR_EXPR:
              inner = TREE_OPERAND (inner, 0);
 
-             while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
+             while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r'
+                    && TREE_CODE (inner) != INDIRECT_REF)
                inner = TREE_OPERAND (inner, 0);
 
              if (DECL_P (inner)
@@ -6312,7 +6399,7 @@ c_finish_return (tree retval)
          break;
        }
 
-      retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
+      retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
     }
 
   return add_stmt (build_stmt (RETURN_EXPR, retval));
@@ -6381,8 +6468,9 @@ c_start_case (tree exp)
     }
 
   /* Add this new SWITCH_STMT to the stack.  */
-  cs = xmalloc (sizeof (*cs));
-  cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type);
+  cs = XNEW (struct c_switch);
+  cs->switch_stmt = build_stmt ((enum tree_code) SWITCH_STMT, exp, NULL_TREE,
+                               orig_type);
   cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
   cs->next = c_switch_stack;
@@ -6430,7 +6518,7 @@ c_finish_case (tree body)
   /* Pop the stack.  */
   c_switch_stack = cs->next;
   splay_tree_delete (cs->cases);
-  free (cs);
+  XDELETE (cs);
 }
 \f
 /* Emit an if statement.  IF_LOCUS is the location of the 'if'.  COND,
@@ -6469,7 +6557,7 @@ 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:
 
@@ -6546,7 +6634,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
             }
  
          t = build_and_jump (&blab);
-          exit = build (COND_EXPR, void_type_node, cond, exit, t);
+          exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
           exit = fold (exit);
          if (cond_is_first)
             SET_EXPR_LOCATION (exit, start_locus);
@@ -6587,7 +6675,7 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
       return NULL_TREE;
     }
 
-  return add_stmt (build (GOTO_EXPR, void_type_node, label));
+  return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
 }
 
 /* A helper routine for c_process_expr_stmt and c_finish_stmt_expr.  */
@@ -6752,10 +6840,10 @@ c_finish_stmt_expr (tree body)
       && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
     val = TREE_OPERAND (val, 0);
 
-  *last_p = build (MODIFY_EXPR, void_type_node, tmp, val);
+  *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
   SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last));
 
-  return build (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
+  return build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
 }
 \f
 /* Begin and end compound statements.  This is as simple as pushing
@@ -6794,7 +6882,7 @@ c_end_compound_stmt (tree stmt, bool do_scope)
       && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
       && TREE_CODE (stmt) != BIND_EXPR)
     {
-      stmt = build (BIND_EXPR, void_type_node, NULL, stmt, NULL);
+      stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL);
       TREE_SIDE_EFFECTS (stmt) = 1;
     }
 
@@ -6806,7 +6894,7 @@ c_end_compound_stmt (tree stmt, bool do_scope)
    meant to apply to normal control flow transfer.  */
 
 void
-push_cleanup (tree decl ATTRIBUTE_UNUSED, tree cleanup, bool eh_only)
+push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only)
 {
   enum tree_code code;
   tree stmt, list;
@@ -7539,13 +7627,18 @@ 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)
     build_type = result_type;
 
   {
-    tree result = build (resultcode, build_type, op0, op1);
+    tree result = build2 (resultcode, build_type, op0, op1);
 
     /* Treat expressions in initializers specially as they can't trap.  */
     result = require_constant_value ? fold_initializer (result)
@@ -7556,31 +7649,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);
-}