OSDN Git Service

[gcc/ChangeLog]
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 905ad93..4c0ce27 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines shared by all languages that are variants of C.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -346,7 +346,25 @@ int warn_format_nonliteral;
 
 int warn_format_security;
 
-
+/* Zero means that faster, ...NonNil variants of objc_msgSend...
+   calls will be used in ObjC; passing nil receivers to such calls
+   will most likely result in crashes.  */
+int flag_nil_receivers = 1;
+
+/* Nonzero means that we will allow new ObjC exception syntax (@throw,
+   @try, etc.) in source code.  */
+int flag_objc_exceptions = 0;
+
+/* Nonzero means that code generation will be altered to support
+   "zero-link" execution.  This currently affects ObjC only, but may
+   affect other languages in the future.  */
+int flag_zero_link = 0;
+
+/* Nonzero means emit an '__OBJC, __image_info' for the current translation
+   unit.  It will inform the ObjC runtime that class definition(s) herein
+   contained are to replace one(s) previously loaded.  */
+int flag_replace_objc_classes = 0;
+   
 /* C/ObjC language option variables.  */
 
 
@@ -368,7 +386,7 @@ int flag_isoc94;
 
 int flag_isoc99;
 
-/* Nonzero means that we have builtin functions, and main is an int */
+/* Nonzero means that we have builtin functions, and main is an int */
 
 int flag_hosted = 1;
 
@@ -492,17 +510,6 @@ int flag_no_gnu_keywords;
 
 int flag_implement_inlines = 1;
 
-/* Nonzero means do emit exported implementations of templates, instead of
-   multiple static copies in each file that needs a definition.  */
-
-int flag_external_templates;
-
-/* Nonzero means that the decision to emit or not emit the implementation of a
-   template depends on where the template is instantiated, rather than where
-   it is defined.  */
-
-int flag_alt_external_templates;
-
 /* Nonzero means that implicit instantiations will be emitted if needed.  */
 
 int flag_implicit_templates = 1;
@@ -592,21 +599,6 @@ int flag_permissive;
 
 int flag_enforce_eh_specs = 1;
 
-/*  The version of the C++ ABI in use.  The following values are
-    allowed:
-
-    0: The version of the ABI believed most conformant with the
-       C++ ABI specification.  This ABI may change as bugs are
-       discovered and fixed.  Therefore, 0 will not necessarily
-       indicate the same ABI in different versions of G++.
-
-    1: The version of the ABI first used in G++ 3.2.
-
-    Additional positive integers will be assigned as new versions of
-    the ABI become the default version of the ABI.  */
-
-int flag_abi_version = 1;
-
 /* Nonzero means warn about things that will change when compiling
    with an ABI-compliant compiler.  */
 
@@ -775,7 +767,6 @@ static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
 static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
                                                 bool *);
-static tree vector_size_helper (tree, tree);
 
 static void check_function_nonnull (tree, tree);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -1044,7 +1035,13 @@ finish_fname_decls (void)
       tree *p = &DECL_SAVED_TREE (current_function_decl);
       /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK.  */
       while (TREE_CODE (*p) != COMPOUND_STMT)
-       p = &TREE_CHAIN (*p);
+       {
+         if (TREE_CODE (*p) == EXPR_STMT)
+           p = &TREE_CHAIN (*p);
+         else
+           p = &TREE_OPERAND(*p, 0);
+       }
+
       p = &COMPOUND_BODY (*p);
       if (TREE_CODE (*p) == SCOPE_STMT)
        p = &TREE_CHAIN (*p);
@@ -1167,7 +1164,7 @@ fix_string_type (tree value)
      -Wwrite-strings says make the string constant an array of const char
      so that copying it to a non-const pointer will get a warning.
      For C++, this is the standard behavior.  */
-  if (flag_const_strings && ! flag_writable_strings)
+  if (flag_const_strings)
     {
       tree elements
        = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
@@ -1182,7 +1179,7 @@ fix_string_type (tree value)
                          build_index_type (build_int_2 (nchars - 1, 0)));
 
   TREE_CONSTANT (value) = 1;
-  TREE_READONLY (value) = ! flag_writable_strings;
+  TREE_READONLY (value) = 1;
   TREE_STATIC (value) = 1;
   return value;
 }
@@ -1810,6 +1807,10 @@ c_common_type_for_size (unsigned int bits, int unsignedp)
   return 0;
 }
 
+/* Used for communication between c_common_type_for_mode and
+   c_register_builtin_type.  */
+static GTY(()) tree registered_builtin_types;
+
 /* Return a data type that has machine mode MODE.
    If the mode is an integer,
    then UNSIGNEDP selects between signed and unsigned types.  */
@@ -1817,6 +1818,8 @@ c_common_type_for_size (unsigned int bits, int unsignedp)
 tree
 c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 {
+  tree t;
+
   if (mode == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
@@ -1862,6 +1865,9 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
   if (mode == TYPE_MODE (long_double_type_node))
     return long_double_type_node;
 
+  if (mode == TYPE_MODE (void_type_node))
+    return void_type_node;
+  
   if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
     return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
 
@@ -1902,6 +1908,10 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
       break;
     }
 
+  for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
+    if (TYPE_MODE (TREE_VALUE (t)) == mode)
+      return TREE_VALUE (t);
+
   return 0;
 }
 
@@ -2030,6 +2040,8 @@ c_register_builtin_type (tree type, const char* name)
   if (!TYPE_NAME (type))
     TYPE_NAME (type) = decl;
   pushdecl (decl);
+
+  registered_builtin_types = tree_cons (0, type, registered_builtin_types);
 }
 
 \f
@@ -2581,27 +2593,8 @@ c_common_truthvalue_conversion (tree expr)
   if (TREE_CODE (expr) == ERROR_MARK)
     return expr;
 
-#if 0 /* This appears to be wrong for C++.  */
-  /* These really should return error_mark_node after 2.4 is stable.
-     But not all callers handle ERROR_MARK properly.  */
-  switch (TREE_CODE (TREE_TYPE (expr)))
-    {
-    case RECORD_TYPE:
-      error ("struct type value used where scalar is required");
-      return truthvalue_false_node;
-
-    case UNION_TYPE:
-      error ("union type value used where scalar is required");
-      return truthvalue_false_node;
-
-    case ARRAY_TYPE:
-      error ("array type value used where scalar is required");
-      return truthvalue_false_node;
-
-    default:
-      break;
-    }
-#endif /* 0 */
+  if (TREE_CODE (expr) == FUNCTION_DECL)
+    expr = build_unary_op (ADDR_EXPR, expr, 0);
 
   switch (TREE_CODE (expr))
     {
@@ -2626,30 +2619,42 @@ c_common_truthvalue_conversion (tree expr)
       return real_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
 
     case ADDR_EXPR:
-      /* If we are taking the address of an external decl, it might be zero
-        if it is weak, so we cannot optimize.  */
-      if (DECL_P (TREE_OPERAND (expr, 0))
-         && DECL_EXTERNAL (TREE_OPERAND (expr, 0)))
-       break;
+      {
+       if (TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL
+           && ! DECL_WEAK (TREE_OPERAND (expr, 0)))
+         {
+           /* Common Ada/Pascal programmer's mistake.  We always warn
+              about this since it is so bad.  */
+           warning ("the address of `%D', will always evaluate as `true'",
+                    TREE_OPERAND (expr, 0));
+           return truthvalue_true_node;
+         }
 
-      if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
-       return build (COMPOUND_EXPR, truthvalue_type_node,
-                     TREE_OPERAND (expr, 0), truthvalue_true_node);
-      else
-       return truthvalue_true_node;
+       /* If we are taking the address of an external decl, it might be
+          zero if it is weak, so we cannot optimize.  */
+       if (DECL_P (TREE_OPERAND (expr, 0))
+           && DECL_EXTERNAL (TREE_OPERAND (expr, 0)))
+         break;
+
+       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
+         return build (COMPOUND_EXPR, truthvalue_type_node,
+                       TREE_OPERAND (expr, 0), truthvalue_true_node);
+       else
+         return truthvalue_true_node;
+      }
 
     case COMPLEX_EXPR:
       return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)),
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)),
                              0);
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
-      return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+      return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -2657,15 +2662,15 @@ c_common_truthvalue_conversion (tree expr)
         we can't ignore them if their second arg has side-effects.  */
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
        return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1),
-                     c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                     (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)));
       else
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
       return fold (build (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)),
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 2))));
 
     case CONVERT_EXPR:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -2678,7 +2683,7 @@ c_common_truthvalue_conversion (tree expr)
       /* If this is widening the argument, we can ignore it.  */
       if (TYPE_PRECISION (TREE_TYPE (expr))
          >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
       break;
 
     case MINUS_EXPR:
@@ -2727,8 +2732,8 @@ c_common_truthvalue_conversion (tree expr)
       return (build_binary_op
              ((TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-       c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
-       c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+       (*lang_hooks.truthvalue_conversion) (build_unary_op (REALPART_EXPR, t, 0)),
+       (*lang_hooks.truthvalue_conversion) (build_unary_op (IMAGPART_EXPR, t, 0)),
               0));
     }
 
@@ -2745,13 +2750,17 @@ static tree builtin_function_2 (const char *, const char *, tree, tree,
 tree
 c_build_qualified_type (tree type, int type_quals)
 {
+  if (type == error_mark_node)
+    return type;
+  
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    return build_array_type (c_build_qualified_type (TREE_TYPE (type),
+                                                    type_quals),
+                            TYPE_DOMAIN (type));
+
   /* A restrict-qualified pointer type must be a pointer to object or
      incomplete type.  Note that the use of POINTER_TYPE_P also allows
-     REFERENCE_TYPEs, which is appropriate for C++.  Unfortunately,
-     the C++ front-end also use POINTER_TYPE for pointer-to-member
-     values, so even though it should be illegal to use `restrict'
-     with such an entity we don't flag that here.  Thus, special case
-     code for that case is required in the C++ front-end.  */
+     REFERENCE_TYPEs, which is appropriate for C++.  */
   if ((type_quals & TYPE_QUAL_RESTRICT)
       && (!POINTER_TYPE_P (type)
          || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
@@ -2760,10 +2769,6 @@ c_build_qualified_type (tree type, int type_quals)
       type_quals &= ~TYPE_QUAL_RESTRICT;
     }
 
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    return build_array_type (c_build_qualified_type (TREE_TYPE (type),
-                                                    type_quals),
-                            TYPE_DOMAIN (type));
   return build_qualified_type (type, type_quals);
 }
 
@@ -2772,9 +2777,19 @@ c_build_qualified_type (tree type, int type_quals)
 void
 c_apply_type_quals_to_decl (int type_quals, tree decl)
 {
-  if ((type_quals & TYPE_QUAL_CONST)
-      || (TREE_TYPE (decl)
-         && TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE))
+  tree type = TREE_TYPE (decl);
+  
+  if (type == error_mark_node)
+    return;
+
+  if (((type_quals & TYPE_QUAL_CONST)
+       || (type && TREE_CODE (type) == REFERENCE_TYPE))
+      /* An object declared 'const' is only readonly after it is
+        initialized.  We don't have any way of expressing this currently,
+        so we need to be conservative and unset TREE_READONLY for types
+        with constructors.  Otherwise aliasing code will ignore stores in
+        an inline constructor.  */
+      && !(type && TYPE_NEEDS_CONSTRUCTING (type)))
     TREE_READONLY (decl) = 1;
   if (type_quals & TYPE_QUAL_VOLATILE)
     {
@@ -2783,11 +2798,15 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
     }
   if (type_quals & TYPE_QUAL_RESTRICT)
     {
-      if (!TREE_TYPE (decl)
-         || !POINTER_TYPE_P (TREE_TYPE (decl))
-         || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl))))
+      while (type && TREE_CODE (type) == ARRAY_TYPE)
+       /* Allow 'restrict' on arrays of pointers.
+          FIXME currently we just ignore it.  */
+       type = TREE_TYPE (type);
+      if (!type
+         || !POINTER_TYPE_P (type)
+         || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
        error ("invalid use of `restrict'");
-      else if (flag_strict_aliasing)
+      else if (flag_strict_aliasing && type == TREE_TYPE (decl))
        /* Indicate we need to make a unique alias set for this pointer.
           We can't do it here because it might be pointing to an
           incomplete type.  */
@@ -2863,7 +2882,7 @@ c_common_get_alias_set (tree t)
 
             int *ip;
             int **ipp = &ip;
-            const int* const* cipp = &ipp;
+            const int* const* cipp = ipp;
 
          And, it doesn't make sense for that to be legal unless you
         can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
@@ -3696,14 +3715,16 @@ expand_tree_builtin (tree function, tree params, tree coerced_params)
     case BUILT_IN_CREALL:
       if (coerced_params == 0)
        return integer_zero_node;
-      return build_unary_op (REALPART_EXPR, TREE_VALUE (coerced_params), 0);
+      return non_lvalue (build_unary_op (REALPART_EXPR,
+                                        TREE_VALUE (coerced_params), 0));
 
     case BUILT_IN_CIMAG:
     case BUILT_IN_CIMAGF:
     case BUILT_IN_CIMAGL:
       if (coerced_params == 0)
        return integer_zero_node;
-      return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0);
+      return non_lvalue (build_unary_op (IMAGPART_EXPR,
+                                        TREE_VALUE (coerced_params), 0));
 
     case BUILT_IN_ISGREATER:
       return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR);
@@ -3999,8 +4020,9 @@ finish_label_address_expr (tree label)
 /* Hook used by expand_expr to expand language-specific tree codes.  */
 
 rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
-     /* Actually enum_modifier.  */
+c_expand_expr (tree exp, rtx target, enum machine_mode tmode, 
+              int modifier /* Actually enum_modifier.  */,
+              rtx *alt_rtl)
 {
   switch (TREE_CODE (exp))
     {
@@ -4009,7 +4031,6 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
        tree rtl_expr;
        rtx result;
        bool preserve_result = false;
-       bool return_target = false;
 
        if (STMT_EXPR_WARN_UNUSED_RESULT (exp) && target == const0_rtx)
          {
@@ -4057,30 +4078,18 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
            if (TREE_CODE (last) == SCOPE_STMT
                && TREE_CODE (expr) == EXPR_STMT)
              {
-               if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL
-                   && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target)
-                 /* If the last expression is a variable whose RTL is the
-                    same as our target, just return the target; if it
-                    isn't valid expanding the decl would produce different
-                    RTL, and store_expr would try to do a copy.  */
-                 return_target = true;
-               else
-                 {
-                   /* Otherwise, note that we want the value from the last
-                      expression.  */
-                   TREE_ADDRESSABLE (expr) = 1;
-                   preserve_result = true;
-                 }
+               /* Otherwise, note that we want the value from the last
+                  expression.  */
+               TREE_ADDRESSABLE (expr) = 1;
+               preserve_result = true;
              }
          }
 
        expand_stmt (STMT_EXPR_STMT (exp));
        expand_end_stmt_expr (rtl_expr);
 
-       result = expand_expr (rtl_expr, target, tmode, modifier);
-       if (return_target)
-         result = target;
-       else if (preserve_result && GET_CODE (result) == MEM)
+       result = expand_expr_real (rtl_expr, target, tmode, modifier, alt_rtl);
+       if (preserve_result && GET_CODE (result) == MEM)
          {
            if (GET_MODE (result) != BLKmode)
              result = copy_to_reg (result);
@@ -4105,7 +4114,7 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
           literal, then return the variable.  */
        tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
        emit_local_var (decl);
-       return expand_expr (decl, target, tmode, modifier);
+       return expand_expr_real (decl, target, tmode, modifier, alt_rtl);
       }
 
     default:
@@ -4239,21 +4248,6 @@ c_init_attributes (void)
 #undef DEF_ATTR_TREE_LIST
 }
 
-/* Output a -Wshadow warning MSGCODE about NAME, and give the location
-   of the previous declaration DECL.  */
-void
-shadow_warning (enum sw_kind msgcode, const char *name, tree decl)
-{
-  static const char *const msgs[] = {
-    /* SW_PARAM  */ N_("declaration of \"%s\" shadows a parameter"),
-    /* SW_LOCAL  */ N_("declaration of \"%s\" shadows a previous local"),
-    /* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration")
-  };
-
-  warning (msgs[msgcode], name);
-  warning ("%Jshadowed declaration is here", decl);
-}
-
 /* Attribute handlers common to C front ends.  */
 
 /* Handle a "packed" attribute; arguments as in
@@ -4833,7 +4827,13 @@ handle_alias_attribute (tree *node, tree name, tree args,
       error ("%J'%D' defined both normally and as an alias", decl, decl);
       *no_add_attrs = true;
     }
-  else if (decl_function_context (decl) == 0)
+
+  /* Note that the very first time we process a nested declaration,
+     decl_function_context will not be set.  Indeed, *would* never
+     be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
+     we do below.  After such frobbery, pushdecl would set the context.
+     In any case, this is never what we want.  */
+  else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
     {
       tree id;
 
@@ -4871,34 +4871,33 @@ handle_visibility_attribute (tree *node, tree name, tree args,
                             bool *no_add_attrs)
 {
   tree decl = *node;
+  tree id = TREE_VALUE (args);
+
+  *no_add_attrs = true;
 
   if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
     {
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
+      return NULL_TREE;
     }
-  else
-    {
-      tree id;
 
-      id = TREE_VALUE (args);
-      if (TREE_CODE (id) != STRING_CST)
-       {
-         error ("visibility arg not a string");
-         *no_add_attrs = true;
-         return NULL_TREE;
-       }
-      if (strcmp (TREE_STRING_POINTER (id), "hidden")
-         && strcmp (TREE_STRING_POINTER (id), "protected")
-         && strcmp (TREE_STRING_POINTER (id), "internal")
-         && strcmp (TREE_STRING_POINTER (id), "default"))
-       {
-         error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
-         *no_add_attrs = true;
-         return NULL_TREE;
-       }
+  if (TREE_CODE (id) != STRING_CST)
+    {
+      error ("visibility arg not a string");
+      return NULL_TREE;
     }
 
+  if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
+    DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+  else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
+    DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
+  else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
+    DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;  
+  else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
+    DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
+  else
+    error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+
   return NULL_TREE;
 }
 
@@ -5235,57 +5234,11 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
     }
 
   /* Build back pointers if needed.  */
-  *node = vector_size_helper (*node, new_type);
+  *node = reconstruct_complex_type (*node, new_type);
 
   return NULL_TREE;
 }
 
-/* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a
-   better way.
-
-   If we requested a pointer to a vector, build up the pointers that
-   we stripped off while looking for the inner type.  Similarly for
-   return values from functions.
-
-   The argument "type" is the top of the chain, and "bottom" is the
-   new type which we will point to.  */
-
-static tree
-vector_size_helper (tree type, tree bottom)
-{
-  tree inner, outer;
-
-  if (POINTER_TYPE_P (type))
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_pointer_type (inner);
-    }
-  else if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_array_type (inner, TYPE_DOMAIN (type));
-    }
-  else if (TREE_CODE (type) == FUNCTION_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_function_type (inner, TYPE_ARG_TYPES (type));
-    }
-  else if (TREE_CODE (type) == METHOD_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
-                                         inner, 
-                                         TYPE_ARG_TYPES (type));
-    }
-  else
-    return bottom;
-
-  TREE_READONLY (outer) = TREE_READONLY (type);
-  TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
-
-  return outer;
-}
-
 /* Handle the "nonnull" attribute.  */
 static tree
 handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
@@ -5717,21 +5670,40 @@ c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     return NULL;
   switch (TREE_CODE (x))
     { 
-    /* Reconginze assignments of large structures and constructors of
+    /* Recognize assignments of large structures and constructors of
        big arrays.  */
     case MODIFY_EXPR:
     case CONSTRUCTOR:
       {
-       int size = int_size_in_bytes (TREE_TYPE (x));
+       HOST_WIDE_INT size;
+
+       size = int_size_in_bytes (TREE_TYPE (x));
 
-       if (!size || size > MOVE_MAX_PIECES)
+       if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO)
          *count += 10;
        else
-         *count += 2 * (size + MOVE_MAX - 1) / MOVE_MAX;
-       return NULL;
+         *count += ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES);
       }
       break;
-    /* Few special cases of expensive operations.  This is usefull
+    case CALL_EXPR:
+      {
+       tree decl = get_callee_fndecl (x);
+
+       if (decl && DECL_BUILT_IN (decl))
+         switch (DECL_FUNCTION_CODE (decl))
+           {
+           case BUILT_IN_CONSTANT_P:
+             *walk_subtrees = 0;
+             return NULL_TREE;
+           case BUILT_IN_EXPECT:
+             return NULL_TREE;
+           default:
+             break;
+           }
+       *count += 10;
+       break;
+      }
+    /* Few special cases of expensive operations.  This is useful
        to avoid inlining on functions having too many of these.  */
     case TRUNC_DIV_EXPR:
     case CEIL_DIV_EXPR:
@@ -5742,7 +5714,6 @@ c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
     case RDIV_EXPR:
-    case CALL_EXPR:
       *count += 10;
       break;
     /* Various containers that will produce no code themselves.  */
@@ -5836,4 +5807,36 @@ c_decl_uninit (tree t)
   return false;
 }
 
+/* Issue the error given by MSGID, indicating that it occurred before
+   TOKEN, which had the associated VALUE.  */
+
+void
+c_parse_error (const char *msgid, enum cpp_ttype token, tree value)
+{
+  const char *string = _(msgid);
+
+  if (token == CPP_EOF)
+    error ("%s at end of input", string);
+  else if (token == CPP_CHAR || token == CPP_WCHAR)
+    {
+      unsigned int val = TREE_INT_CST_LOW (value);
+      const char *const ell = (token == CPP_CHAR) ? "" : "L";
+      if (val <= UCHAR_MAX && ISGRAPH (val))
+       error ("%s before %s'%c'", string, ell, val);
+      else
+       error ("%s before %s'\\x%x'", string, ell, val);
+    }
+  else if (token == CPP_STRING
+          || token == CPP_WSTRING)
+    error ("%s before string constant", string);
+  else if (token == CPP_NUMBER)
+    error ("%s before numeric constant", string);
+  else if (token == CPP_NAME)
+    error ("%s before \"%s\"", string, IDENTIFIER_POINTER (value));
+  else if (token < N_TTYPES)
+    error ("%s before '%s' token", string, cpp_type2name (token));
+  else
+    error ("%s", string);
+}
+
 #include "gt-c-common.h"