OSDN Git Service

PR optimization/13424 (hppa), bootstrap/14462, c/14828
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index b5d6651..a3904ca 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.
 
@@ -100,9 +100,9 @@ cpp_reader *parse_in;               /* Declared in c-pragma.h.  */
        tree long_unsigned_type_node;
        tree long_long_unsigned_type_node;
 
-       tree boolean_type_node;
-       tree boolean_false_node;
-       tree boolean_true_node;
+       tree truthvalue_type_node;
+       tree truthvalue_false_node;
+       tree truthvalue_true_node;
 
        tree ptrdiff_type_node;
 
@@ -187,10 +187,6 @@ tree c_global_trees[CTI_MAX];
    langhook should take care of initialization of this array.  */
 
 bool statement_code_p[MAX_TREE_CODES];
-
-/* Nonzero if we can read a PCH file now.  */
-
-int allow_pch = 1;
 \f
 /* Switches common to the C front ends.  */
 
@@ -350,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.  */
 
 
@@ -372,15 +386,10 @@ 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;
 
-/* Nonzero means add default format_arg attributes for functions not
-   in ISO C.  */
-
-int flag_noniso_default_format_attributes = 1;
-
 /* Nonzero means warn when casting a function call to a type that does
    not match the return type (e.g. (float)sqrt() or (anything*)malloc()
    when there is no previous declaration of sqrt or malloc.  */
@@ -391,6 +400,10 @@ int warn_bad_function_cast;
 
 int warn_traditional;
 
+/* Nonzero means warn for a declaration found after a statement.  */
+
+int warn_declaration_after_statement;
+
 /* Nonzero means warn for non-prototype function decls
    or non-prototyped defs without previous prototype.  */
 
@@ -417,6 +430,11 @@ int warn_main;
 
 int warn_sequence_point;
 
+/* Nonzero means warn about uninitialized variable when it is initialized with itself.
+   For example: int i = i;, GCC will not warn about this when warn_init_self is nonzero.  */
+
+int warn_init_self;
+
 /* Nonzero means to warn about compile-time division by zero.  */
 int warn_div_by_zero = 1;
 
@@ -429,6 +447,10 @@ int warn_implicit_int;
 
 int warn_nonnull;
 
+/* Warn about old-style parameter declaration.  */
+
+int warn_old_style_definition;
+
 
 /* ObjC language option variables.  */
 
@@ -488,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;
@@ -564,15 +575,18 @@ int flag_new_for_scope = 1;
 
 int flag_weak = 1;
 
+/* 0 means we want the preprocessor to not emit line directives for
+   the current working directory.  1 means we want it to do it.  -1
+   means we should decide depending on whether debugging information
+   is being emitted or not.  */
+
+int flag_working_directory = -1;
+
 /* Nonzero to use __cxa_atexit, rather than atexit, to register
    destructors for local statics and global objects.  */
 
 int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
 
-/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc.  */
-
-int flag_vtable_gc;
-
 /* Nonzero means make the default pedwarns warnings instead of errors.
    The value of this flag is ignored if -pedantic is specified.  */
 
@@ -585,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.  */
 
@@ -766,7 +765,8 @@ static tree handle_vector_size_attribute (tree *, tree, tree, int,
 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
 static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
-static tree vector_size_helper (tree, tree);
+static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
+                                                bool *);
 
 static void check_function_nonnull (tree, tree);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -843,6 +843,8 @@ const struct attribute_spec c_common_attribute_table[] =
   { "may_alias",             0, 0, false, true, false, NULL },
   { "cleanup",               1, 1, true, false, false,
                              handle_cleanup_attribute },
+  { "warn_unused_result",     0, 0, false, true, true,
+                             handle_warn_unused_result_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -1033,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);
@@ -1068,16 +1076,18 @@ finish_fname_decls (void)
 const char *
 fname_as_string (int pretty_p)
 {
-  const char *name = NULL;
-
-  if (pretty_p)
-    name = (current_function_decl
-           ? (*lang_hooks.decl_printable_name) (current_function_decl, 2)
-           : "top level");
-  else if (current_function_decl && DECL_NAME (current_function_decl))
-    name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
-  else
-    name = "";
+  const char *name = "top level";
+  int vrb = 2;
+
+  if (! pretty_p)
+    {
+      name = "";
+      vrb = 0;
+    }
+
+  if (current_function_decl)
+    name = lang_hooks.decl_printable_name (current_function_decl, vrb);
+
   return name;
 }
 
@@ -1127,8 +1137,7 @@ fname_decl (unsigned int rid, tree id)
       input_line = saved_lineno;
     }
   if (!ix && !current_function_decl)
-    pedwarn ("%H'%D' is not defined outside of function scope",
-             &DECL_SOURCE_LOCATION (decl), decl);
+    pedwarn ("%J'%D' is not defined outside of function scope", decl, decl);
 
   return decl;
 }
@@ -1155,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,
@@ -1170,19 +1179,11 @@ 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;
 }
 \f
-static int is_valid_printf_arglist (tree);
-static rtx c_expand_builtin (tree, rtx, enum machine_mode,
-                            enum expand_modifier);
-static rtx c_expand_builtin_printf (tree, rtx, enum machine_mode,
-                                   enum expand_modifier, int, int);
-static rtx c_expand_builtin_fprintf (tree, rtx, enum machine_mode,
-                                    enum expand_modifier, int, int);
-\f
 /* Print a warning if a constant expression had overflow in folding.
    Invoke this function on every expression that the language
    requires to be a constant expression.
@@ -1247,7 +1248,7 @@ unsigned_conversion_warning (tree result, tree operand)
 
   if (TREE_CODE (operand) == INTEGER_CST
       && TREE_CODE (type) == INTEGER_TYPE
-      && TREE_UNSIGNED (type)
+      && TYPE_UNSIGNED (type)
       && skip_evaluation == 0
       && !int_fits_type_p (operand, type))
     {
@@ -1291,13 +1292,13 @@ convert_and_check (tree type, tree expr)
          TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (expr);
 
          /* No warning for converting 0x80000000 to int.  */
-         if (!(TREE_UNSIGNED (type) < TREE_UNSIGNED (TREE_TYPE (expr))
+         if (!(TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (expr))
                && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
                && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr))))
            /* If EXPR fits in the unsigned version of TYPE,
               don't warn unless pedantic.  */
            if ((pedantic
-                || TREE_UNSIGNED (type)
+                || TYPE_UNSIGNED (type)
                 || ! constant_fits_type_p (expr,
                                            c_common_unsigned_type (type)))
                && skip_evaluation == 0)
@@ -1806,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.  */
@@ -1813,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;
 
@@ -1858,46 +1865,27 @@ 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);
 
   if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
     return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
 
-  switch (mode)
-    {
-    case V16QImode:
-      return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
-    case V8HImode:
-      return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
-    case V4SImode:
-      return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
-    case V2DImode:
-      return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
-    case V2SImode:
-      return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
-    case V2HImode:
-      return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
-    case V4HImode:
-      return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
-    case V8QImode:
-      return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
-    case V1DImode:
-      return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
-    case V16SFmode:
-      return V16SF_type_node;
-    case V4SFmode:
-      return V4SF_type_node;
-    case V2SFmode:
-      return V2SF_type_node;
-    case V2DFmode:
-      return V2DF_type_node;
-    case V4DFmode:
-      return V4DF_type_node;
-    default:
-      break;
+  if (VECTOR_MODE_P (mode))
+    {
+      enum machine_mode inner_mode = GET_MODE_INNER (mode);
+      tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+      if (inner_type != NULL_TREE)
+       return build_vector_type_for_mode (inner_type, mode);
     }
 
+  for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
+    if (TYPE_MODE (TREE_VALUE (t)) == mode)
+      return TREE_VALUE (t);
+
   return 0;
 }
 
@@ -1975,39 +1963,61 @@ tree
 c_common_signed_or_unsigned_type (int unsignedp, tree type)
 {
   if (! INTEGRAL_TYPE_P (type)
-      || TREE_UNSIGNED (type) == unsignedp)
+      || TYPE_UNSIGNED (type) == unsignedp)
     return type;
 
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
+  /* Must check the mode of the types, not the precision.  Enumeral types
+     in C++ have precision set to match their range, but may use a wider
+     mode to match an ABI.  If we change modes, we may wind up with bad
+     conversions.  */
+
+  if (TYPE_MODE (type) == TYPE_MODE (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (short_integer_type_node))
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
            : long_long_integer_type_node);
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (widest_integer_literal_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
            : widest_integer_literal_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (intTI_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (intDI_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (intDI_type_node))
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (intSI_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (intSI_type_node))
     return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (intHI_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (intHI_type_node))
     return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node))
+  if (TYPE_MODE (type) == TYPE_MODE (intQI_type_node))
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
 
   return type;
 }
+
+/* The C version of the register_builtin_type langhook.  */
+
+void
+c_register_builtin_type (tree type, const char* name)
+{
+  tree decl;
+
+  decl = build_decl (TYPE_DECL, get_identifier (name), type);
+  DECL_ARTIFICIAL (decl) = 1;
+  if (!TYPE_NAME (type))
+    TYPE_NAME (type) = decl;
+  pushdecl (decl);
+
+  registered_builtin_types = tree_cons (0, type, registered_builtin_types);
+}
+
 \f
 /* Return the minimum number of bits needed to represent VALUE in a
    signed or unsigned type, UNSIGNEDP says which.  */
@@ -2138,9 +2148,9 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
      but it *requires* conversion to FINAL_TYPE.  */
 
   if (op0 == primop0 && TREE_TYPE (op0) != *restype_ptr)
-    unsignedp0 = TREE_UNSIGNED (TREE_TYPE (op0));
+    unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (op0));
   if (op1 == primop1 && TREE_TYPE (op1) != *restype_ptr)
-    unsignedp1 = TREE_UNSIGNED (TREE_TYPE (op1));
+    unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (op1));
 
   /* If one of the operands must be floated, we cannot optimize.  */
   real1 = TREE_CODE (TREE_TYPE (primop0)) == REAL_TYPE;
@@ -2212,16 +2222,18 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       int min_gt, max_gt, min_lt, max_lt;
       tree maxval, minval;
       /* 1 if comparison is nominally unsigned.  */
-      int unsignedp = TREE_UNSIGNED (*restype_ptr);
+      int unsignedp = TYPE_UNSIGNED (*restype_ptr);
       tree val;
 
       type = c_common_signed_or_unsigned_type (unsignedp0,
                                               TREE_TYPE (primop0));
 
-      /* If TYPE is an enumeration, then we need to get its min/max
-        values from it's underlying integral type, not the enumerated
-        type itself.  */
-      if (TREE_CODE (type) == ENUMERAL_TYPE)
+      /* In C, if TYPE is an enumeration, then we need to get its
+        min/max values from its underlying integral type, not the
+        enumerated type itself.  In C++, TYPE_MAX_VALUE and
+        TYPE_MIN_VALUE have already been set correctly on the
+        enumeration type.  */
+      if (!c_dialect_cxx() && TREE_CODE (type) == ENUMERAL_TYPE)
        type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
 
       maxval = TYPE_MAX_VALUE (type);
@@ -2258,40 +2270,40 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       if (code == NE_EXPR)
        {
          if (max_lt || min_gt)
-           val = boolean_true_node;
+           val = truthvalue_true_node;
        }
       else if (code == EQ_EXPR)
        {
          if (max_lt || min_gt)
-           val = boolean_false_node;
+           val = truthvalue_false_node;
        }
       else if (code == LT_EXPR)
        {
          if (max_lt)
-           val = boolean_true_node;
+           val = truthvalue_true_node;
          if (!min_lt)
-           val = boolean_false_node;
+           val = truthvalue_false_node;
        }
       else if (code == GT_EXPR)
        {
          if (min_gt)
-           val = boolean_true_node;
+           val = truthvalue_true_node;
          if (!max_gt)
-           val = boolean_false_node;
+           val = truthvalue_false_node;
        }
       else if (code == LE_EXPR)
        {
          if (!max_gt)
-           val = boolean_true_node;
+           val = truthvalue_true_node;
          if (min_gt)
-           val = boolean_false_node;
+           val = truthvalue_false_node;
        }
       else if (code == GE_EXPR)
        {
          if (!min_lt)
-           val = boolean_true_node;
+           val = truthvalue_true_node;
          if (max_lt)
-           val = boolean_false_node;
+           val = truthvalue_false_node;
        }
 
       /* If primop0 was sign-extended and unsigned comparison specd,
@@ -2330,9 +2342,9 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
 
       if (TREE_CODE (primop0) != INTEGER_CST)
        {
-         if (val == boolean_false_node)
+         if (val == truthvalue_false_node)
            warning ("comparison is always false due to limited range of data type");
-         if (val == boolean_true_node)
+         if (val == truthvalue_true_node)
            warning ("comparison is always true due to limited range of data type");
        }
 
@@ -2367,7 +2379,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
     {
       type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
       type = c_common_signed_or_unsigned_type (unsignedp0
-                                              || TREE_UNSIGNED (*restype_ptr),
+                                              || TYPE_UNSIGNED (*restype_ptr),
                                               type);
       /* Make sure shorter operand is extended the right way
         to match the longer operand.  */
@@ -2389,7 +2401,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       primop1 = op1;
 
       if (!real1 && !real2 && integer_zerop (primop1)
-         && TREE_UNSIGNED (*restype_ptr))
+         && TYPE_UNSIGNED (*restype_ptr))
        {
          tree value = 0;
          switch (code)
@@ -2404,7 +2416,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                        && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                     primop0))))
                warning ("comparison of unsigned expression >= 0 is always true");
-             value = boolean_true_node;
+             value = truthvalue_true_node;
              break;
 
            case LT_EXPR:
@@ -2413,7 +2425,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                        && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                     primop0))))
                warning ("comparison of unsigned expression < 0 is always false");
-             value = boolean_false_node;
+             value = truthvalue_false_node;
              break;
 
            default:
@@ -2434,7 +2446,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
   *op0_ptr = convert (type, primop0);
   *op1_ptr = convert (type, primop1);
 
-  *restype_ptr = boolean_type_node;
+  *restype_ptr = truthvalue_type_node;
 
   return 0;
 }
@@ -2472,12 +2484,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
        pedwarn ("pointer to member function used in arithmetic");
       size_exp = integer_one_node;
     }
-  else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE)
-    {
-      if (pedantic || warn_pointer_arith)
-       pedwarn ("pointer to a member used in arithmetic");
-      size_exp = integer_one_node;
-    }
   else
     size_exp = size_in_bytes (TREE_TYPE (result_type));
 
@@ -2496,7 +2502,7 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
       /* If the constant is unsigned, and smaller than the pointer size,
         then we must skip this optimization.  This is because it could cause
         an overflow error if the constant is negative but INTOP is not.  */
-      && (! TREE_UNSIGNED (TREE_TYPE (intop))
+      && (! TYPE_UNSIGNED (TREE_TYPE (intop))
          || (TYPE_PRECISION (TREE_TYPE (intop))
              == TYPE_PRECISION (TREE_TYPE (ptrop)))))
     {
@@ -2516,9 +2522,9 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
      so the multiply won't overflow spuriously.  */
 
   if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
-      || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
+      || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
     intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
-                                            TREE_UNSIGNED (sizetype)), intop);
+                                            TYPE_UNSIGNED (sizetype)), intop);
 
   /* Replace the integer argument with a suitable product by the object size.
      Do this multiplication as signed, then convert to the appropriate
@@ -2544,10 +2550,10 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
    This preparation consists of taking the ordinary
    representation of an expression expr and producing a valid tree
    boolean expression describing whether expr is nonzero.  We could
-   simply always do build_binary_op (NE_EXPR, expr, boolean_false_node, 1),
+   simply always do build_binary_op (NE_EXPR, expr, truthvalue_false_node, 1),
    but we optimize comparisons, &&, ||, and !.
 
-   The resulting type should always be `boolean_type_node'.  */
+   The resulting type should always be `truthvalue_type_node'.  */
 
 tree
 c_common_truthvalue_conversion (tree expr)
@@ -2555,27 +2561,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 boolean_false_node;
-
-    case UNION_TYPE:
-      error ("union type value used where scalar is required");
-      return boolean_false_node;
-
-    case ARRAY_TYPE:
-      error ("array type value used where scalar is required");
-      return boolean_false_node;
-
-    default:
-      break;
-    }
-#endif /* 0 */
+  if (TREE_CODE (expr) == FUNCTION_DECL)
+    expr = build_unary_op (ADDR_EXPR, expr, 0);
 
   switch (TREE_CODE (expr))
     {
@@ -2587,61 +2574,71 @@ c_common_truthvalue_conversion (tree expr)
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
     case TRUTH_NOT_EXPR:
-      TREE_TYPE (expr) = boolean_type_node;
+      TREE_TYPE (expr) = truthvalue_type_node;
       return expr;
 
     case ERROR_MARK:
       return expr;
 
     case INTEGER_CST:
-      return integer_zerop (expr) ? boolean_false_node : boolean_true_node;
+      return integer_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
 
     case REAL_CST:
-      return real_zerop (expr) ? boolean_false_node : boolean_true_node;
+      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, boolean_type_node,
-                     TREE_OPERAND (expr, 0), boolean_true_node);
-      else
-       return boolean_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:
-    case FFS_EXPR:
-    case POPCOUNT_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:
       /* These don't change whether an object is zero or nonzero, but
         we can't ignore them if their second arg has side-effects.  */
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
-       return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 1),
-                     c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+       return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1),
+                     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, boolean_type_node, TREE_OPERAND (expr, 0),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
+      return fold (build (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0),
+               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,
@@ -2649,12 +2646,12 @@ c_common_truthvalue_conversion (tree expr)
       if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
          || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
        break;
-      /* fall through...  */
+      /* Fall through....  */
     case NOP_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:
@@ -2668,7 +2665,7 @@ c_common_truthvalue_conversion (tree expr)
         be false.  */
       if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
        break;
-      /* fall through...  */
+      /* Fall through....  */
     case BIT_XOR_EXPR:
       /* This and MINUS_EXPR can be changed into a comparison of the
         two objects.  */
@@ -2683,9 +2680,9 @@ c_common_truthvalue_conversion (tree expr)
 
     case BIT_AND_EXPR:
       if (integer_onep (TREE_OPERAND (expr, 1))
-         && TREE_TYPE (expr) != boolean_type_node)
+         && TREE_TYPE (expr) != truthvalue_type_node)
        /* Using convert here would cause infinite recursion.  */
-       return build1 (NOP_EXPR, boolean_type_node, expr);
+       return build1 (NOP_EXPR, truthvalue_type_node, expr);
       break;
 
     case MODIFY_EXPR:
@@ -2703,8 +2700,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));
     }
 
@@ -2721,13 +2718,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))))
@@ -2736,10 +2737,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);
 }
 
@@ -2748,9 +2745,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)
     {
@@ -2759,11 +2766,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.  */
@@ -2810,7 +2821,7 @@ c_common_get_alias_set (tree t)
   /* The C standard specifically allows aliasing between signed and
      unsigned variants of the same type.  We treat the signed
      variant as canonical.  */
-  if (TREE_CODE (t) == INTEGER_TYPE && TREE_UNSIGNED (t))
+  if (TREE_CODE (t) == INTEGER_TYPE && TYPE_UNSIGNED (t))
     {
       tree t1 = c_common_signed_type (t);
 
@@ -2839,7 +2850,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
@@ -2967,20 +2978,16 @@ enum built_in_attribute
 #define DEF_ATTR_INT(ENUM, VALUE) ENUM,
 #define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
 #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum.  */
 #include "builtin-attrs.def"
 #undef DEF_ATTR_NULL_TREE
 #undef DEF_ATTR_INT
 #undef DEF_ATTR_IDENT
 #undef DEF_ATTR_TREE_LIST
-#undef DEF_FN_ATTR
   ATTR_LAST
 };
 
 static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
 
-static bool c_attrs_initialized = false;
-
 static void c_init_attributes (void);
 
 /* Build tree nodes and builtin functions common to both C and C++ language
@@ -3060,43 +3067,43 @@ c_common_nodes_and_builtins (void)
 
   /* These are types that c_common_type_for_size and
      c_common_type_for_mode use.  */
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intQI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intHI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intSI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intDI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intQI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intHI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intSI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("__int128_t"),
-                                           intTI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("__int128_t"),
+                                        intTI_type_node));
 #endif
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intQI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intHI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intSI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intDI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intQI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intHI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intSI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("__uint128_t"),
-                                           unsigned_intTI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("__uint128_t"),
+                                        unsigned_intTI_type_node));
 #endif
 
   /* Create the widest literal types.  */
   widest_integer_literal_type_node
     = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           widest_integer_literal_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        widest_integer_literal_type_node));
 
   widest_unsigned_literal_type_node
     = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           widest_unsigned_literal_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        widest_unsigned_literal_type_node));
 
   /* `unsigned long' is the standard type for sizeof.
      Note that stddef.h uses `unsigned long',
@@ -3112,16 +3119,16 @@ c_common_nodes_and_builtins (void)
   record_builtin_type (RID_DOUBLE, NULL, double_type_node);
   record_builtin_type (RID_MAX, "long double", long_double_type_node);
 
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("complex int"),
-                                           complex_integer_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("complex float"),
-                                           complex_float_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("complex double"),
-                                           complex_double_type_node));
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("complex int"),
+                                        complex_integer_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("complex float"),
+                                        complex_float_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("complex double"),
+                                        complex_double_type_node));
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("complex long double"),
                 complex_long_double_type_node));
 
@@ -3145,12 +3152,12 @@ c_common_nodes_and_builtins (void)
 
   if (g77_integer_type_node != NULL_TREE)
     {
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_integer"),
-                                               g77_integer_type_node));
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_uinteger"),
-                                               g77_uinteger_type_node));
+      lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                            get_identifier ("__g77_integer"),
+                                            g77_integer_type_node));
+      lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                            get_identifier ("__g77_uinteger"),
+                                            g77_uinteger_type_node));
     }
 
   if (TYPE_PRECISION (float_type_node) * 2
@@ -3170,12 +3177,12 @@ c_common_nodes_and_builtins (void)
 
   if (g77_longint_type_node != NULL_TREE)
     {
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_longint"),
-                                               g77_longint_type_node));
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_ulongint"),
-                                               g77_ulongint_type_node));
+      lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                            get_identifier ("__g77_longint"),
+                                            g77_longint_type_node));
+      lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                            get_identifier ("__g77_ulongint"),
+                                            g77_ulongint_type_node));
     }
 
   record_builtin_type (RID_VOID, NULL, void_type_node);
@@ -3213,7 +3220,7 @@ c_common_nodes_and_builtins (void)
   wchar_type_size = TYPE_PRECISION (wchar_type_node);
   if (c_dialect_cxx ())
     {
-      if (TREE_UNSIGNED (wchar_type_node))
+      if (TYPE_UNSIGNED (wchar_type_node))
        wchar_type_node = make_unsigned_type (wchar_type_size);
       else
        wchar_type_node = make_signed_type (wchar_type_size);
@@ -3242,15 +3249,15 @@ c_common_nodes_and_builtins (void)
     = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
   unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
 
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
                 va_list_type_node));
 
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),
                 ptrdiff_type_node));
 
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
                 sizetype));
 
@@ -3358,8 +3365,7 @@ c_common_nodes_and_builtins (void)
 #undef DEF_FUNCTION_TYPE_VAR_3
 #undef DEF_POINTER_TYPE
 
-  if (!c_attrs_initialized)
-    c_init_attributes ();
+  c_init_attributes ();
 
 #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE,                  \
                    BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT)     \
@@ -3395,7 +3401,7 @@ c_common_nodes_and_builtins (void)
 #include "builtins.def"
 #undef DEF_BUILTIN
 
-  (*targetm.init_builtins) ();
+  targetm.init_builtins ();
 
   main_identifier_node = get_identifier ("main");
 }
@@ -3555,6 +3561,15 @@ strip_array_types (tree type)
   return type;
 }
 
+/* Recursively remove any '*' or '&' operator from TYPE.  */
+tree
+strip_pointer_operator (tree t)
+{
+  while (POINTER_TYPE_P (t))
+    t = TREE_TYPE (t);
+  return t;
+}
+
 static tree expand_unordered_cmp (tree, tree, enum tree_code, enum tree_code);
 
 /* Expand a call to an unordered comparison function such as
@@ -3668,14 +3683,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);
@@ -3912,19 +3929,17 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
       if (high_value)
        {
          error ("duplicate (or overlapping) case value");
-         error ("%Hthis is the first entry overlapping that value",
-                 &DECL_SOURCE_LOCATION (duplicate));
+         error ("%Jthis is the first entry overlapping that value", duplicate);
        }
       else if (low_value)
        {
          error ("duplicate case value") ;
-         error ("%Hpreviously used here", &DECL_SOURCE_LOCATION (duplicate));
+         error ("%Jpreviously used here", duplicate);
        }
       else
        {
          error ("multiple default labels in one switch");
-         error ("%Hthis is the first default label",
-                 &DECL_SOURCE_LOCATION (duplicate));
+         error ("%Jthis is the first default label", duplicate);
        }
       if (!cases->root)
        add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
@@ -3973,8 +3988,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))
     {
@@ -3983,7 +3999,26 @@ 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)
+         {
+           tree stmt = STMT_EXPR_STMT (exp);
+           tree scope;
+
+           for (scope = COMPOUND_BODY (stmt);
+                scope && TREE_CODE (scope) != SCOPE_STMT;
+                scope = TREE_CHAIN (scope));
+
+           if (scope && SCOPE_STMT_BLOCK (scope))
+             warning ("%Hignoring return value of `%D', "
+                      "declared with attribute warn_unused_result",
+                      &expr_wfl_stack->location,
+                      BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope)));
+           else
+             warning ("%Hignoring return value of function "
+                      "declared with attribute warn_unused_result",
+                      &expr_wfl_stack->location);
+         }
 
        /* Since expand_expr_stmt calls free_temp_slots after every
           expression statement, we must call push_temp_slots here.
@@ -4011,30 +4046,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);
@@ -4053,27 +4076,13 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
       }
       break;
 
-    case CALL_EXPR:
-      {
-       if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
-           && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-               == FUNCTION_DECL)
-           && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-           && (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-               == BUILT_IN_FRONTEND))
-         return c_expand_builtin (exp, target, tmode, modifier);
-       else
-         abort ();
-      }
-      break;
-
     case COMPOUND_LITERAL_EXPR:
       {
        /* Initialize the anonymous variable declared in the compound
           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:
@@ -4135,280 +4144,6 @@ c_staticp (tree exp)
     return 1;
   return 0;
 }
-
-#define CALLED_AS_BUILT_IN(NODE) \
-   (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
-
-static rtx
-c_expand_builtin (tree exp, rtx target, enum machine_mode tmode,
-                 enum expand_modifier modifier)
-{
-  tree type = TREE_TYPE (exp);
-  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
-  tree arglist = TREE_OPERAND (exp, 1);
-  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
-  enum tree_code code = TREE_CODE (exp);
-  const int ignore = (target == const0_rtx
-                     || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
-                          || code == CONVERT_EXPR || code == REFERENCE_EXPR
-                          || code == COND_EXPR)
-                         && TREE_CODE (type) == VOID_TYPE));
-
-  if (! optimize && ! CALLED_AS_BUILT_IN (fndecl))
-    return expand_call (exp, target, ignore);
-
-  switch (fcode)
-    {
-    case BUILT_IN_PRINTF:
-      target = c_expand_builtin_printf (arglist, target, tmode,
-                                       modifier, ignore, /*unlocked=*/ 0);
-      if (target)
-       return target;
-      break;
-
-    case BUILT_IN_PRINTF_UNLOCKED:
-      target = c_expand_builtin_printf (arglist, target, tmode,
-                                       modifier, ignore, /*unlocked=*/ 1);
-      if (target)
-       return target;
-      break;
-
-    case BUILT_IN_FPRINTF:
-      target = c_expand_builtin_fprintf (arglist, target, tmode,
-                                        modifier, ignore, /*unlocked=*/ 0);
-      if (target)
-       return target;
-      break;
-
-    case BUILT_IN_FPRINTF_UNLOCKED:
-      target = c_expand_builtin_fprintf (arglist, target, tmode,
-                                        modifier, ignore, /*unlocked=*/ 1);
-      if (target)
-       return target;
-      break;
-
-    default:                   /* just do library call, if unknown builtin */
-      error ("built-in function `%s' not currently supported",
-            IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-    }
-
-  /* The switch statement above can drop through to cause the function
-     to be called normally.  */
-  return expand_call (exp, target, ignore);
-}
-
-/* Check an arglist to *printf for problems.  The arglist should start
-   at the format specifier, with the remaining arguments immediately
-   following it.  */
-static int
-is_valid_printf_arglist (tree arglist)
-{
-  /* Save this value so we can restore it later.  */
-  const int SAVE_pedantic = pedantic;
-  int diagnostic_occurred = 0;
-  tree attrs;
-
-  /* Set this to a known value so the user setting won't affect code
-     generation.  */
-  pedantic = 1;
-  /* Check to make sure there are no format specifier errors.  */
-  attrs = tree_cons (get_identifier ("format"),
-                    tree_cons (NULL_TREE,
-                               get_identifier ("printf"),
-                               tree_cons (NULL_TREE,
-                                          integer_one_node,
-                                          tree_cons (NULL_TREE,
-                                                     build_int_2 (2, 0),
-                                                     NULL_TREE))),
-                    NULL_TREE);
-  check_function_format (&diagnostic_occurred, attrs, arglist);
-
-  /* Restore the value of `pedantic'.  */
-  pedantic = SAVE_pedantic;
-
-  /* If calling `check_function_format_ptr' produces a warning, we
-     return false, otherwise we return true.  */
-  return ! diagnostic_occurred;
-}
-
-/* If the arguments passed to printf are suitable for optimizations,
-   we attempt to transform the call.  */
-static rtx
-c_expand_builtin_printf (tree arglist, rtx target, enum machine_mode tmode,
-                        enum expand_modifier modifier, int ignore,
-                        int unlocked)
-{
-  tree fn_putchar = unlocked ?
-    implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTCHAR];
-  tree fn_puts = unlocked ?
-    implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTS];
-  tree fn, format_arg, stripped_string;
-
-  /* If the return value is used, or the replacement _DECL isn't
-     initialized, don't do the transformation.  */
-  if (!ignore || !fn_putchar || !fn_puts)
-    return 0;
-
-  /* Verify the required arguments in the original call.  */
-  if (arglist == 0
-      || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE))
-    return 0;
-
-  /* Check the specifier vs. the parameters.  */
-  if (!is_valid_printf_arglist (arglist))
-    return 0;
-
-  format_arg = TREE_VALUE (arglist);
-  stripped_string = format_arg;
-  STRIP_NOPS (stripped_string);
-  if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
-    stripped_string = TREE_OPERAND (stripped_string, 0);
-
-  /* If the format specifier isn't a STRING_CST, punt.  */
-  if (TREE_CODE (stripped_string) != STRING_CST)
-    return 0;
-
-  /* OK!  We can attempt optimization.  */
-
-  /* If the format specifier was "%s\n", call __builtin_puts(arg2).  */
-  if (strcmp (TREE_STRING_POINTER (stripped_string), "%s\n") == 0)
-    {
-      arglist = TREE_CHAIN (arglist);
-      fn = fn_puts;
-    }
-  /* If the format specifier was "%c", call __builtin_putchar (arg2).  */
-  else if (strcmp (TREE_STRING_POINTER (stripped_string), "%c") == 0)
-    {
-      arglist = TREE_CHAIN (arglist);
-      fn = fn_putchar;
-    }
-  else
-    {
-      /* We can't handle anything else with % args or %% ... yet.  */
-      if (strchr (TREE_STRING_POINTER (stripped_string), '%'))
-       return 0;
-
-      /* If the resulting constant string has a length of 1, call
-         putchar.  Note, TREE_STRING_LENGTH includes the terminating
-         NULL in its count.  */
-      if (TREE_STRING_LENGTH (stripped_string) == 2)
-        {
-         /* Given printf("c"), (where c is any one character,)
-             convert "c"[0] to an int and pass that to the replacement
-             function.  */
-         arglist = build_int_2 (TREE_STRING_POINTER (stripped_string)[0], 0);
-         arglist = build_tree_list (NULL_TREE, arglist);
-
-         fn = fn_putchar;
-        }
-      /* If the resulting constant was "string\n", call
-         __builtin_puts("string").  Ensure "string" has at least one
-         character besides the trailing \n.  Note, TREE_STRING_LENGTH
-         includes the terminating NULL in its count.  */
-      else if (TREE_STRING_LENGTH (stripped_string) > 2
-              && TREE_STRING_POINTER (stripped_string)
-              [TREE_STRING_LENGTH (stripped_string) - 2] == '\n')
-        {
-         /* Create a NULL-terminated string that's one char shorter
-            than the original, stripping off the trailing '\n'.  */
-         const int newlen = TREE_STRING_LENGTH (stripped_string) - 1;
-         char *newstr = alloca (newlen);
-         memcpy (newstr, TREE_STRING_POINTER (stripped_string), newlen - 1);
-         newstr[newlen - 1] = 0;
-
-         arglist = fix_string_type (build_string (newlen, newstr));
-         arglist = build_tree_list (NULL_TREE, arglist);
-         fn = fn_puts;
-       }
-      else
-       /* We'd like to arrange to call fputs(string) here, but we
-           need stdout and don't have a way to get it ... yet.  */
-       return 0;
-    }
-
-  return expand_expr (build_function_call (fn, arglist),
-                     (ignore ? const0_rtx : target),
-                     tmode, modifier);
-}
-
-/* If the arguments passed to fprintf are suitable for optimizations,
-   we attempt to transform the call.  */
-static rtx
-c_expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode tmode,
-                         enum expand_modifier modifier, int ignore,
-                         int unlocked)
-{
-  tree fn_fputc = unlocked ?
-    implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTC];
-  tree fn_fputs = unlocked ?
-    implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTS];
-  tree fn, format_arg, stripped_string;
-
-  /* If the return value is used, or the replacement _DECL isn't
-     initialized, don't do the transformation.  */
-  if (!ignore || !fn_fputc || !fn_fputs)
-    return 0;
-
-  /* Verify the required arguments in the original call.  */
-  if (arglist == 0
-      || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
-      || (TREE_CHAIN (arglist) == 0)
-      || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) !=
-         POINTER_TYPE))
-    return 0;
-
-  /* Check the specifier vs. the parameters.  */
-  if (!is_valid_printf_arglist (TREE_CHAIN (arglist)))
-    return 0;
-
-  format_arg = TREE_VALUE (TREE_CHAIN (arglist));
-  stripped_string = format_arg;
-  STRIP_NOPS (stripped_string);
-  if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
-    stripped_string = TREE_OPERAND (stripped_string, 0);
-
-  /* If the format specifier isn't a STRING_CST, punt.  */
-  if (TREE_CODE (stripped_string) != STRING_CST)
-    return 0;
-
-  /* OK!  We can attempt optimization.  */
-
-  /* If the format specifier was "%s", call __builtin_fputs(arg3, arg1).  */
-  if (strcmp (TREE_STRING_POINTER (stripped_string), "%s") == 0)
-    {
-      tree newarglist = build_tree_list (NULL_TREE, TREE_VALUE (arglist));
-      arglist = tree_cons (NULL_TREE,
-                          TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))),
-                          newarglist);
-      fn = fn_fputs;
-    }
-  /* If the format specifier was "%c", call __builtin_fputc (arg3, arg1).  */
-  else if (strcmp (TREE_STRING_POINTER (stripped_string), "%c") == 0)
-    {
-      tree newarglist = build_tree_list (NULL_TREE, TREE_VALUE (arglist));
-      arglist = tree_cons (NULL_TREE,
-                          TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))),
-                          newarglist);
-      fn = fn_fputc;
-    }
-  else
-    {
-      /* We can't handle anything else with % args or %% ... yet.  */
-      if (strchr (TREE_STRING_POINTER (stripped_string), '%'))
-       return 0;
-
-      /* When "string" doesn't contain %, replace all cases of
-         fprintf(stream,string) with fputs(string,stream).  The fputs
-         builtin will take take of special cases like length==1.  */
-      arglist = tree_cons (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)),
-                          build_tree_list (NULL_TREE, TREE_VALUE (arglist)));
-      fn = fn_fputs;
-    }
-
-  return expand_expr (build_function_call (fn, arglist),
-                     (ignore ? const0_rtx : target),
-                     tmode, modifier);
-}
 \f
 
 /* Given a boolean expression ARG, return a tree representing an increment
@@ -4418,7 +4153,7 @@ tree
 boolean_increment (enum tree_code code, tree arg)
 {
   tree val;
-  tree true_res = (c_dialect_cxx () ? boolean_true_node : c_bool_true_node);
+  tree true_res = boolean_true_node;
 
   arg = stabilize_reference (arg);
   switch (code)
@@ -4474,55 +4209,11 @@ c_init_attributes (void)
     = tree_cons (built_in_attributes[(int) PURPOSE],   \
                 built_in_attributes[(int) VALUE],      \
                 built_in_attributes[(int) CHAIN]);
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No initialization needed.  */
-#include "builtin-attrs.def"
-#undef DEF_ATTR_NULL_TREE
-#undef DEF_ATTR_INT
-#undef DEF_ATTR_IDENT
-#undef DEF_ATTR_TREE_LIST
-#undef DEF_FN_ATTR
-  c_attrs_initialized = true;
-}
-
-/* Depending on the name of DECL, apply default attributes to it.  */
-
-void
-c_common_insert_default_attributes (tree decl)
-{
-  tree name = DECL_NAME (decl);
-
-  if (!c_attrs_initialized)
-    c_init_attributes ();
-
-#define DEF_ATTR_NULL_TREE(ENUM) /* Nothing needed after initialization.  */
-#define DEF_ATTR_INT(ENUM, VALUE)
-#define DEF_ATTR_IDENT(ENUM, STRING)
-#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE)                    \
-  if ((PREDICATE) && name == built_in_attributes[(int) NAME])  \
-    decl_attributes (&decl, built_in_attributes[(int) ATTRS],  \
-                    ATTR_FLAG_BUILT_IN);
 #include "builtin-attrs.def"
 #undef DEF_ATTR_NULL_TREE
 #undef DEF_ATTR_INT
 #undef DEF_ATTR_IDENT
 #undef DEF_ATTR_TREE_LIST
-#undef DEF_FN_ATTR
-}
-
-/* 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 ("%Hshadowed declaration is here", &DECL_SOURCE_LOCATION (decl));
 }
 
 /* Attribute handlers common to C front ends.  */
@@ -4905,13 +4596,25 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
            mode = (enum machine_mode) j;
 
       if (mode == VOIDmode)
-       error ("unknown machine mode `%s'", p);
-      else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
-                    (mode, TREE_UNSIGNED (type))))
+       {
+         error ("unknown machine mode `%s'", p);
+         return NULL_TREE;
+       }
+
+      if (VECTOR_MODE_P (mode))
+       {
+         warning ("specifying vector types with __attribute__ ((mode)) "
+                  "is deprecated");
+         warning ("use __attribute__ ((vector_size)) instead");
+       }
+
+      typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
+      if (typefm == NULL_TREE)
        error ("no data type for mode `%s'", p);
+
       else if ((TREE_CODE (type) == POINTER_TYPE
                || TREE_CODE (type) == REFERENCE_TYPE)
-              && !(*targetm.valid_pointer_mode) (mode))
+              && !targetm.valid_pointer_mode (mode))
        error ("invalid pointer mode `%s'", p);
       else
        {
@@ -4926,17 +4629,17 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
          if (TREE_CODE (type) == POINTER_TYPE)
            {
              ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
-                                                     mode);
+                                                     mode, false);
              *node = ptr_type;
            }
          else if (TREE_CODE (type) == REFERENCE_TYPE)
            {
              ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
-                                                       mode);
+                                                       mode, false);
              *node = ptr_type;
            }
          else
-         *node = typefm;
+           *node = typefm;
          /* No need to layout the type here.  The caller should do this.  */
        }
     }
@@ -4963,8 +4666,8 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
              && current_function_decl != NULL_TREE
              && ! TREE_STATIC (decl))
            {
-             error ("%Hsection attribute cannot be specified for "
-                     "local variables", &DECL_SOURCE_LOCATION (decl));
+             error ("%Jsection attribute cannot be specified for "
+                     "local variables", decl);
              *no_add_attrs = true;
            }
 
@@ -4974,8 +4677,8 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
                   && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
                              TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
            {
-             error ("%Hsection of '%D' conflicts with previous declaration",
-                     &DECL_SOURCE_LOCATION (*node), *node);
+             error ("%Jsection of '%D' conflicts with previous declaration",
+                     *node, *node);
              *no_add_attrs = true;
            }
          else
@@ -4983,15 +4686,13 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
        }
       else
        {
-         error ("%Hsection attribute not allowed for '%D'",
-                 &DECL_SOURCE_LOCATION (*node), *node);
+         error ("%Jsection attribute not allowed for '%D'", *node, *node);
          *no_add_attrs = true;
        }
     }
   else
     {
-      error ("%Hsection attributes are not supported for this target",
-             &DECL_SOURCE_LOCATION (*node));
+      error ("%Jsection attributes are not supported for this target", *node);
       *no_add_attrs = true;
     }
 
@@ -5065,8 +4766,7 @@ handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
   else if (TREE_CODE (decl) != VAR_DECL
           && TREE_CODE (decl) != FIELD_DECL)
     {
-      error ("%Halignment may not be specified for '%D'",
-             &DECL_SOURCE_LOCATION (decl), decl);
+      error ("%Jalignment may not be specified for '%D'", decl, decl);
       *no_add_attrs = true;
     }
   else
@@ -5104,11 +4804,16 @@ handle_alias_attribute (tree *node, tree name, tree args,
   if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
       || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
     {
-      error ("%H'%D' defined both normally and as an alias",
-             &DECL_SOURCE_LOCATION (decl), decl);
+      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;
 
@@ -5146,34 +4851,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;
 }
 
@@ -5229,14 +4933,12 @@ handle_no_instrument_function_attribute (tree *node, tree name,
 
   if (TREE_CODE (decl) != FUNCTION_DECL)
     {
-      error ("%H'%E' attribute applies only to functions",
-             &DECL_SOURCE_LOCATION (decl), name);
+      error ("%J'%E' attribute applies only to functions", decl, name);
       *no_add_attrs = true;
     }
   else if (DECL_INITIAL (decl))
     {
-      error ("%Hcan't set '%E' attribute after definition",
-             &DECL_SOURCE_LOCATION (decl), name);
+      error ("%Jcan't set '%E' attribute after definition", decl, name);
       *no_add_attrs = true;
     }
   else
@@ -5277,14 +4979,12 @@ handle_no_limit_stack_attribute (tree *node, tree name,
 
   if (TREE_CODE (decl) != FUNCTION_DECL)
     {
-      error ("%H'%E' attribute applies only to functions",
-             &DECL_SOURCE_LOCATION (decl), name);
+      error ("%J'%E' attribute applies only to functions", decl, name);
       *no_add_attrs = true;
     }
   else if (DECL_INITIAL (decl))
     {
-      error ("%Hcan't set '%E' attribute after definition",
-             &DECL_SOURCE_LOCATION (decl), name);
+      error ("%Jcan't set '%E' attribute after definition", decl, name);
       *no_add_attrs = true;
     }
   else
@@ -5370,13 +5070,6 @@ handle_deprecated_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
-/* Keep a list of vector type nodes we created in handle_vector_size_attribute,
-   to prevent us from duplicating type nodes unnecessarily.
-   The normal mechanism to prevent duplicates is to use type_hash_canon, but
-   since we want to distinguish types that are essentially identical (except
-   for their debug representation), we use a local list here.  */
-static GTY(()) tree vector_type_node_list = 0;
-
 /* Handle a "vector_size" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -5387,19 +5080,24 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
 {
   unsigned HOST_WIDE_INT vecsize, nunits;
   enum machine_mode mode, orig_mode, new_mode;
-  tree type = *node, new_type = NULL_TREE;
-  tree type_list_node;
+  tree type = *node, new_type, size;
 
   *no_add_attrs = true;
 
-  if (! host_integerp (TREE_VALUE (args), 1))
+  /* Stripping NON_LVALUE_EXPR allows declarations such as
+     typedef short v4si __attribute__((vector_size (4 * sizeof(short)))).  */
+  size = TREE_VALUE (args);
+  if (TREE_CODE (size) == NON_LVALUE_EXPR)
+    size = TREE_OPERAND (size, 0);
+
+  if (! host_integerp (size, 1))
     {
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
       return NULL_TREE;
     }
 
   /* Get the vector size (in bytes).  */
-  vecsize = tree_low_cst (TREE_VALUE (args), 1);
+  vecsize = tree_low_cst (size, 1);
 
   /* We need to provide for vector pointers, vector arrays, and
      functions returning vectors.  For example:
@@ -5411,6 +5109,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
 
   while (POINTER_TYPE_P (type)
         || TREE_CODE (type) == FUNCTION_TYPE
+        || TREE_CODE (type) == METHOD_TYPE
         || TREE_CODE (type) == ARRAY_TYPE)
     type = TREE_TYPE (type);
 
@@ -5444,119 +5143,20 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
        break;
       }
 
-    if (new_mode == VOIDmode)
+  if (new_mode == VOIDmode)
     {
       error ("no vector mode with the size and type specified could be found");
       return NULL_TREE;
     }
 
-  for (type_list_node = vector_type_node_list; type_list_node;
-       type_list_node = TREE_CHAIN (type_list_node))
-    {
-      tree other_type = TREE_VALUE (type_list_node);
-      tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type);
-      tree fields = TYPE_FIELDS (record);
-      tree field_type = TREE_TYPE (fields);
-      tree array_type = TREE_TYPE (field_type);
-      if (TREE_CODE (fields) != FIELD_DECL
-         || TREE_CODE (field_type) != ARRAY_TYPE)
-       abort ();
-
-      if (TYPE_MODE (other_type) == mode && type == array_type)
-       {
-         new_type = other_type;
-         break;
-       }
-    }
-
-  if (new_type == NULL_TREE)
-    {
-      tree index, array, rt, list_node;
-
-      new_type = (*lang_hooks.types.type_for_mode) (new_mode,
-                                                   TREE_UNSIGNED (type));
-
-      if (!new_type)
-       {
-         error ("no vector mode with the size and type specified could be found");
-         return NULL_TREE;
-       }
-
-      new_type = build_type_copy (new_type);
-
-      /* If this is a vector, make sure we either have hardware
-         support, or we can emulate it.  */
-      if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
-          || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
-         && !vector_mode_valid_p (mode))
-       {
-         error ("unable to emulate '%s'", GET_MODE_NAME (mode));
-         return NULL_TREE;
-       }
-
-      /* Set the debug information here, because this is the only
-        place where we know the underlying type for a vector made
-        with vector_size.  For debugging purposes we pretend a vector
-        is an array within a structure.  */
-      index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
-      array = build_array_type (type, build_index_type (index));
-      rt = make_node (RECORD_TYPE);
-
-      TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
-      DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
-      layout_type (rt);
-      TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
-
-      list_node = build_tree_list (NULL, new_type);
-      TREE_CHAIN (list_node) = vector_type_node_list;
-      vector_type_node_list = list_node;
-    }
+  new_type = build_vector_type_for_mode (type, new_mode);
 
   /* 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_VALUES (type));
-    }
-  else if (TREE_CODE (type) == FUNCTION_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_function_type (inner, TYPE_VALUES (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,
@@ -5783,6 +5383,23 @@ handle_cleanup_attribute (tree *node, tree name, tree args,
 
   return NULL_TREE;
 }
+
+/* Handle a "warn_unused_result" attribute.  No special handling.  */
+
+static tree
+handle_warn_unused_result_attribute (tree *node, tree name,
+                              tree args ATTRIBUTE_UNUSED,
+                              int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+  /* Ignore the attribute for functions not returning any value.  */
+  if (VOID_TYPE_P (TREE_TYPE (*node)))
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
 \f
 /* Check for valid arguments being passed to a function.  */
 void
@@ -5964,28 +5581,47 @@ c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
       return NULL;
     }
   /* Assume that constants and references counts nothing.  These should
-     be majorized by amount of operations amoung them we count later
+     be majorized by amount of operations among them we count later
      and are common target of CSE and similar optimizations.  */
   if (TREE_CODE_CLASS (TREE_CODE (x)) == 'c'
       || TREE_CODE_CLASS (TREE_CODE (x)) == 'r')
     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:
@@ -5996,7 +5632,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.  */
@@ -6059,4 +5694,67 @@ c_estimate_num_insns (tree decl)
   return num;
 }
 
+/* Used by c_decl_uninit to find where expressions like x = x + 1; */
+
+static tree
+c_decl_uninit_1 (tree *t, int *walk_sub_trees, void *x)
+{
+  /* If x = EXP(&x)EXP, then do not warn about the use of x.  */
+  if (TREE_CODE (*t) == ADDR_EXPR && TREE_OPERAND (*t, 0) == x)
+    {
+      *walk_sub_trees = 0;
+      return NULL_TREE;
+    }
+  if (*t == x)
+    return *t;
+  return NULL_TREE;
+}
+
+/* Find out if a variable is uninitialized based on DECL_INITIAL.  */
+
+bool
+c_decl_uninit (tree t)
+{
+  /* int x = x; is GCC extension to turn off this warning, only if warn_init_self is zero.  */
+  if (DECL_INITIAL (t) == t)
+    return warn_init_self ? true : false;
+
+  /* Walk the trees looking for the variable itself.  */
+  if (walk_tree_without_duplicates (&DECL_INITIAL (t), c_decl_uninit_1, t))
+    return true;
+  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"