OSDN Git Service

* c-common.c, c-decl.c, c-format.c, c-typeck.c: Use %D for
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index dd84285..6f2a6bc 100644 (file)
@@ -1,6 +1,6 @@
 /* Build expressions with type checking for C compiler.
 /* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -43,6 +43,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "target.h"
 #include "tree-iterator.h"
 #include "tree-gimple.h"
 #include "target.h"
 #include "tree-iterator.h"
 #include "tree-gimple.h"
+#include "tree-flow.h"
+
+/* Possible cases of implicit bad conversions.  Used to select
+   diagnostic messages in convert_for_assignment.  */
+enum impl_conv {
+  ic_argpass,
+  ic_argpass_nonproto,
+  ic_assign,
+  ic_init,
+  ic_return
+};
 
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
 
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
@@ -70,9 +81,8 @@ static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
-static tree convert_for_assignment (tree, tree, const char *, tree, tree,
+static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
                                    int);
                                    int);
-static void warn_for_assignment (const char *, const char *, tree, int);
 static tree valid_compound_expr_initializer (tree, tree);
 static void push_string (const char *);
 static void push_member_name (tree);
 static tree valid_compound_expr_initializer (tree, tree);
 static void push_string (const char *);
 static void push_member_name (tree);
@@ -89,7 +99,8 @@ static void add_pending_init (tree, tree);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
-static int lvalue_or_else (tree, const char *);
+static void readonly_error (tree, enum lvalue_use);
+static void record_maybe_used_decl (tree);
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
@@ -125,8 +136,7 @@ c_incomplete_type_error (tree value, tree type)
 
   if (value != 0 && (TREE_CODE (value) == VAR_DECL
                     || TREE_CODE (value) == PARM_DECL))
 
   if (value != 0 && (TREE_CODE (value) == VAR_DECL
                     || TREE_CODE (value) == PARM_DECL))
-    error ("%qs has an incomplete type",
-          IDENTIFIER_POINTER (DECL_NAME (value)));
+    error ("%qD has an incomplete type", value);
   else
     {
     retry:
   else
     {
     retry:
@@ -169,12 +179,11 @@ c_incomplete_type_error (tree value, tree type)
        }
 
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
        }
 
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-       error ("invalid use of undefined type %<%s %s%>",
-              type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type)));
+       error ("invalid use of undefined type %<%s %E%>",
+              type_code_string, TYPE_NAME (type));
       else
        /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
       else
        /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
-       error ("invalid use of incomplete typedef %qs",
-              IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+       error ("invalid use of incomplete typedef %qD", TYPE_NAME (type));
     }
 }
 
     }
 }
 
@@ -266,7 +275,9 @@ composite_type (tree t1, tree t2)
     case ARRAY_TYPE:
       {
        tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
     case ARRAY_TYPE:
       {
        tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
-       
+       int quals;
+       tree unqual_elt;
+
        /* We should not have any type quals on arrays at all.  */
        gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
        
        /* We should not have any type quals on arrays at all.  */
        gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
        
@@ -281,8 +292,16 @@ composite_type (tree t1, tree t2)
        if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t2, attributes);
        
        if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t2, attributes);
        
-       /* Merge the element types, and have a size if either arg has one.  */
-       t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+       /* Merge the element types, and have a size if either arg has
+          one.  We may have qualifiers on the element types.  To set
+          up TYPE_MAIN_VARIANT correctly, we need to form the
+          composite of the unqualified types and add the qualifiers
+          back at the end.  */
+       quals = TYPE_QUALS (strip_array_types (elt));
+       unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+       t1 = build_array_type (unqual_elt,
+                              TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+       t1 = c_build_qualified_type (t1, quals);
        return build_type_attribute_variant (t1, attributes);
       }
 
        return build_type_attribute_variant (t1, attributes);
       }
 
@@ -298,9 +317,9 @@ composite_type (tree t1, tree t2)
        int i;
 
        /* Save space: see if the result is identical to one of the args.  */
        int i;
 
        /* Save space: see if the result is identical to one of the args.  */
-       if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2))
+       if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2))
          return build_type_attribute_variant (t1, attributes);
          return build_type_attribute_variant (t1, attributes);
-       if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1))
+       if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1))
          return build_type_attribute_variant (t2, attributes);
 
        /* Simple way if one arg fails to specify argument types.  */
          return build_type_attribute_variant (t2, attributes);
 
        /* Simple way if one arg fails to specify argument types.  */
@@ -354,29 +373,51 @@ composite_type (tree t1, tree t2)
                && TREE_VALUE (p1) != TREE_VALUE (p2))
              {
                tree memb;
                && TREE_VALUE (p1) != TREE_VALUE (p2))
              {
                tree memb;
+               tree mv2 = TREE_VALUE (p2);
+               if (mv2 && mv2 != error_mark_node
+                   && TREE_CODE (mv2) != ARRAY_TYPE)
+                 mv2 = TYPE_MAIN_VARIANT (mv2);
                for (memb = TYPE_FIELDS (TREE_VALUE (p1));
                     memb; memb = TREE_CHAIN (memb))
                for (memb = TYPE_FIELDS (TREE_VALUE (p1));
                     memb; memb = TREE_CHAIN (memb))
-                 if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2)))
-                   {
-                     TREE_VALUE (n) = TREE_VALUE (p2);
-                     if (pedantic)
-                       pedwarn ("function types not truly compatible in ISO C");
-                     goto parm_done;
-                   }
+                 {
+                   tree mv3 = TREE_TYPE (memb);
+                   if (mv3 && mv3 != error_mark_node
+                       && TREE_CODE (mv3) != ARRAY_TYPE)
+                     mv3 = TYPE_MAIN_VARIANT (mv3);
+                   if (comptypes (mv3, mv2))
+                     {
+                       TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
+                                                        TREE_VALUE (p2));
+                       if (pedantic)
+                         pedwarn ("function types not truly compatible in ISO C");
+                       goto parm_done;
+                     }
+                 }
              }
            if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE
                && TREE_VALUE (p2) != TREE_VALUE (p1))
              {
                tree memb;
              }
            if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE
                && TREE_VALUE (p2) != TREE_VALUE (p1))
              {
                tree memb;
+               tree mv1 = TREE_VALUE (p1);
+               if (mv1 && mv1 != error_mark_node
+                   && TREE_CODE (mv1) != ARRAY_TYPE)
+                 mv1 = TYPE_MAIN_VARIANT (mv1);
                for (memb = TYPE_FIELDS (TREE_VALUE (p2));
                     memb; memb = TREE_CHAIN (memb))
                for (memb = TYPE_FIELDS (TREE_VALUE (p2));
                     memb; memb = TREE_CHAIN (memb))
-                 if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1)))
-                   {
-                     TREE_VALUE (n) = TREE_VALUE (p1);
-                     if (pedantic)
-                       pedwarn ("function types not truly compatible in ISO C");
-                     goto parm_done;
-                   }
+                 {
+                   tree mv3 = TREE_TYPE (memb);
+                   if (mv3 && mv3 != error_mark_node
+                       && TREE_CODE (mv3) != ARRAY_TYPE)
+                     mv3 = TYPE_MAIN_VARIANT (mv3);
+                   if (comptypes (mv3, mv1))
+                     {
+                       TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
+                                                        TREE_VALUE (p1));
+                       if (pedantic)
+                         pedwarn ("function types not truly compatible in ISO C");
+                       goto parm_done;
+                     }
+                 }
              }
            TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
          parm_done: ;
              }
            TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
          parm_done: ;
@@ -404,8 +445,8 @@ static tree
 common_pointer_type (tree t1, tree t2)
 {
   tree attributes;
 common_pointer_type (tree t1, tree t2)
 {
   tree attributes;
-  tree pointed_to_1;
-  tree pointed_to_2;
+  tree pointed_to_1, mv1;
+  tree pointed_to_2, mv2;
   tree target;
 
   /* Save time if the two types are the same.  */
   tree target;
 
   /* Save time if the two types are the same.  */
@@ -425,11 +466,15 @@ common_pointer_type (tree t1, tree t2)
   attributes = targetm.merge_type_attributes (t1, t2);
 
   /* Find the composite type of the target types, and combine the
   attributes = targetm.merge_type_attributes (t1, t2);
 
   /* Find the composite type of the target types, and combine the
-     qualifiers of the two types' targets.  */
-  pointed_to_1 = TREE_TYPE (t1);
-  pointed_to_2 = TREE_TYPE (t2);
-  target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
-                          TYPE_MAIN_VARIANT (pointed_to_2));
+     qualifiers of the two types' targets.  Do not lose qualifiers on
+     array element types by taking the TYPE_MAIN_VARIANT.  */
+  mv1 = pointed_to_1 = TREE_TYPE (t1);
+  mv2 = pointed_to_2 = TREE_TYPE (t2);
+  if (TREE_CODE (mv1) != ARRAY_TYPE)
+    mv1 = TYPE_MAIN_VARIANT (pointed_to_1);
+  if (TREE_CODE (mv2) != ARRAY_TYPE)
+    mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
+  target = composite_type (mv1, mv2);
   t1 = build_pointer_type (c_build_qualified_type
                           (target,
                            TYPE_QUALS (pointed_to_1) |
   t1 = build_pointer_type (c_build_qualified_type
                           (target,
                            TYPE_QUALS (pointed_to_1) |
@@ -445,8 +490,8 @@ common_pointer_type (tree t1, tree t2)
    This is the type for the result of most arithmetic operations
    if the operands have the given two types.  */
 
    This is the type for the result of most arithmetic operations
    if the operands have the given two types.  */
 
-tree
-common_type (tree t1, tree t2)
+static tree
+c_common_type (tree t1, tree t2)
 {
   enum tree_code code1;
   enum tree_code code2;
 {
   enum tree_code code1;
   enum tree_code code2;
@@ -497,7 +542,7 @@ common_type (tree t1, tree t2)
     {
       tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
       tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
     {
       tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
       tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
-      tree subtype = common_type (subtype1, subtype2);
+      tree subtype = c_common_type (subtype1, subtype2);
 
       if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
        return t1;
 
       if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
        return t1;
@@ -567,6 +612,18 @@ common_type (tree t1, tree t2)
     return t2;
 }
 \f
     return t2;
 }
 \f
+/* Wrapper around c_common_type that is used by c-common.c.  ENUMERAL_TYPEs
+   are allowed here and are converted to their compatible integer types.  */
+tree
+common_type (tree t1, tree t2)
+{
+  if (TREE_CODE (t1) == ENUMERAL_TYPE)
+    t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
+  if (TREE_CODE (t2) == ENUMERAL_TYPE)
+    t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
+  return c_common_type (t1, t2);
+}
+\f
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  */
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  */
@@ -621,11 +678,12 @@ comptypes (tree type1, tree type2)
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
 
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
 
-  if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+  if (TREE_CODE (t1) != ARRAY_TYPE
+      && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return 1;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
     return 1;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  if (! (attrval = targetm.comp_type_attributes (t1, t2)))
+  if (!(attrval = targetm.comp_type_attributes (t1, t2)))
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -638,6 +696,10 @@ comptypes (tree type1, tree type2)
           protocol qualifiers may be involved.  */
       if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0)
        break;
           protocol qualifiers may be involved.  */
       if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0)
        break;
+      /* Do not remove mode or aliasing information.  */
+      if (TYPE_MODE (t1) != TYPE_MODE (t2)
+         || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
+       break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
             ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
       break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
             ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
       break;
@@ -663,13 +725,13 @@ comptypes (tree type1, tree type2)
        if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
 
        if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
 
-       d1_zero = ! TYPE_MAX_VALUE (d1);
-       d2_zero = ! TYPE_MAX_VALUE (d2);
+       d1_zero = !TYPE_MAX_VALUE (d1);
+       d2_zero = !TYPE_MAX_VALUE (d2);
 
 
-       d1_variable = (! d1_zero
+       d1_variable = (!d1_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
                       && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
-       d2_variable = (! d2_zero
+       d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
 
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
 
@@ -678,8 +740,8 @@ comptypes (tree type1, tree type2)
        if (d1_zero && d2_zero)
          break;
        if (d1_zero || d2_zero
        if (d1_zero && d2_zero)
          break;
        if (d1_zero || d2_zero
-           || ! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
-           || ! tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
+           || !tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
+           || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
          val = 0;
 
         break;
          val = 0;
 
         break;
@@ -719,13 +781,21 @@ static int
 comp_target_types (tree ttl, tree ttr, int reflexive)
 {
   int val;
 comp_target_types (tree ttl, tree ttr, int reflexive)
 {
   int val;
+  tree mvl, mvr;
 
   /* Give objc_comptypes a crack at letting these types through.  */
   if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0)
     return val;
 
 
   /* Give objc_comptypes a crack at letting these types through.  */
   if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0)
     return val;
 
-  val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
-                  TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
+  /* Do not lose qualifiers on element types of array types that are
+     pointer targets by taking their TYPE_MAIN_VARIANT.  */
+  mvl = TREE_TYPE (ttl);
+  mvr = TREE_TYPE (ttr);
+  if (TREE_CODE (mvl) != ARRAY_TYPE)
+    mvl = TYPE_MAIN_VARIANT (mvl);
+  if (TREE_CODE (mvr) != ARRAY_TYPE)
+    mvr = TYPE_MAIN_VARIANT (mvr);
+  val = comptypes (mvl, mvr);
 
   if (val == 2 && pedantic)
     pedwarn ("types are not quite compatible");
 
   if (val == 2 && pedantic)
     pedwarn ("types are not quite compatible");
@@ -744,18 +814,24 @@ same_translation_unit_p (tree t1, tree t2)
   while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t1)))
       {
   while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t1)))
       {
-      case 'd': t1 = DECL_CONTEXT (t1); break;
-      case 't': t1 = TYPE_CONTEXT (t1); break;
-      case 'x': t1 = BLOCK_SUPERCONTEXT (t1); break;  /* assume block */
+      case tcc_declaration:
+       t1 = DECL_CONTEXT (t1); break;
+      case tcc_type:
+       t1 = TYPE_CONTEXT (t1); break;
+      case tcc_exceptional:
+       t1 = BLOCK_SUPERCONTEXT (t1); break;  /* assume block */
       default: gcc_unreachable ();
       }
 
   while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t2)))
       {
       default: gcc_unreachable ();
       }
 
   while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t2)))
       {
-      case 'd': t2 = DECL_CONTEXT (t2); break;
-      case 't': t2 = TYPE_CONTEXT (t2); break;
-      case 'x': t2 = BLOCK_SUPERCONTEXT (t2); break;  /* assume block */
+      case tcc_declaration:
+       t2 = DECL_CONTEXT (t2); break;
+      case tcc_type:
+       t2 = TYPE_CONTEXT (t2); break;
+      case tcc_exceptional:
+       t2 = BLOCK_SUPERCONTEXT (t2); break;  /* assume block */
       default: gcc_unreachable ();
       }
 
       default: gcc_unreachable ();
       }
 
@@ -897,7 +973,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
                    break;
                  }
            tagged_tu_seen_base = tts.next;
                    break;
                  }
            tagged_tu_seen_base = tts.next;
-           if (! ok)
+           if (!ok)
              return 0;
          }
        return needs_warning ? 2 : 1;
              return 0;
          }
        return needs_warning ? 2 : 1;
@@ -1021,62 +1097,80 @@ type_lists_compatible_p (tree args1, tree args2)
 
   while (1)
     {
 
   while (1)
     {
+      tree a1, mv1, a2, mv2;
       if (args1 == 0 && args2 == 0)
        return val;
       /* If one list is shorter than the other,
         they fail to match.  */
       if (args1 == 0 || args2 == 0)
        return 0;
       if (args1 == 0 && args2 == 0)
        return val;
       /* If one list is shorter than the other,
         they fail to match.  */
       if (args1 == 0 || args2 == 0)
        return 0;
+      mv1 = a1 = TREE_VALUE (args1);
+      mv2 = a2 = TREE_VALUE (args2);
+      if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
+       mv1 = TYPE_MAIN_VARIANT (mv1);
+      if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
+       mv2 = TYPE_MAIN_VARIANT (mv2);
       /* A null pointer instead of a type
         means there is supposed to be an argument
         but nothing is specified about what type it has.
         So match anything that self-promotes.  */
       /* A null pointer instead of a type
         means there is supposed to be an argument
         but nothing is specified about what type it has.
         So match anything that self-promotes.  */
-      if (TREE_VALUE (args1) == 0)
+      if (a1 == 0)
        {
        {
-         if (c_type_promotes_to (TREE_VALUE (args2)) != TREE_VALUE (args2))
+         if (c_type_promotes_to (a2) != a2)
            return 0;
        }
            return 0;
        }
-      else if (TREE_VALUE (args2) == 0)
+      else if (a2 == 0)
        {
        {
-         if (c_type_promotes_to (TREE_VALUE (args1)) != TREE_VALUE (args1))
+         if (c_type_promotes_to (a1) != a1)
            return 0;
        }
       /* If one of the lists has an error marker, ignore this arg.  */
            return 0;
        }
       /* If one of the lists has an error marker, ignore this arg.  */
-      else if (TREE_CODE (TREE_VALUE (args1)) == ERROR_MARK
-              || TREE_CODE (TREE_VALUE (args2)) == ERROR_MARK)
+      else if (TREE_CODE (a1) == ERROR_MARK
+              || TREE_CODE (a2) == ERROR_MARK)
        ;
        ;
-      else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
-                                     TYPE_MAIN_VARIANT (TREE_VALUE (args2)))))
+      else if (!(newval = comptypes (mv1, mv2)))
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
-         if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE
-             && (TYPE_NAME (TREE_VALUE (args1)) == 0
-                 || TYPE_TRANSPARENT_UNION (TREE_VALUE (args1)))
-             && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST
-             && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)),
-                                    TYPE_SIZE (TREE_VALUE (args2))))
+         if (TREE_CODE (a1) == UNION_TYPE
+             && (TYPE_NAME (a1) == 0
+                 || TYPE_TRANSPARENT_UNION (a1))
+             && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
+             && tree_int_cst_equal (TYPE_SIZE (a1),
+                                    TYPE_SIZE (a2)))
            {
              tree memb;
            {
              tree memb;
-             for (memb = TYPE_FIELDS (TREE_VALUE (args1));
+             for (memb = TYPE_FIELDS (a1);
                   memb; memb = TREE_CHAIN (memb))
                   memb; memb = TREE_CHAIN (memb))
-               if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2)))
-                 break;
+               {
+                 tree mv3 = TREE_TYPE (memb);
+                 if (mv3 && mv3 != error_mark_node
+                     && TREE_CODE (mv3) != ARRAY_TYPE)
+                   mv3 = TYPE_MAIN_VARIANT (mv3);
+                 if (comptypes (mv3, mv2))
+                   break;
+               }
              if (memb == 0)
                return 0;
            }
              if (memb == 0)
                return 0;
            }
-         else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE
-                  && (TYPE_NAME (TREE_VALUE (args2)) == 0
-                      || TYPE_TRANSPARENT_UNION (TREE_VALUE (args2)))
-                  && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST
-                  && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)),
-                                         TYPE_SIZE (TREE_VALUE (args1))))
+         else if (TREE_CODE (a2) == UNION_TYPE
+                  && (TYPE_NAME (a2) == 0
+                      || TYPE_TRANSPARENT_UNION (a2))
+                  && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
+                  && tree_int_cst_equal (TYPE_SIZE (a2),
+                                         TYPE_SIZE (a1)))
            {
              tree memb;
            {
              tree memb;
-             for (memb = TYPE_FIELDS (TREE_VALUE (args2));
+             for (memb = TYPE_FIELDS (a2);
                   memb; memb = TREE_CHAIN (memb))
                   memb; memb = TREE_CHAIN (memb))
-               if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1)))
-                 break;
+               {
+                 tree mv3 = TREE_TYPE (memb);
+                 if (mv3 && mv3 != error_mark_node
+                     && TREE_CODE (mv3) != ARRAY_TYPE)
+                   mv3 = TYPE_MAIN_VARIANT (mv3);
+                 if (comptypes (mv3, mv1))
+                   break;
+               }
              if (memb == 0)
                return 0;
            }
              if (memb == 0)
                return 0;
            }
@@ -1095,7 +1189,7 @@ type_lists_compatible_p (tree args1, tree args2)
 \f
 /* Compute the size to increment a pointer by.  */
 
 \f
 /* Compute the size to increment a pointer by.  */
 
-tree
+static tree
 c_size_in_bytes (tree type)
 {
   enum tree_code code = TREE_CODE (type);
 c_size_in_bytes (tree type)
 {
   enum tree_code code = TREE_CODE (type);
@@ -1125,7 +1219,7 @@ decl_constant_value (tree decl)
         isn't valid for a PARM_DECL.  */
       current_function_decl != 0
       && TREE_CODE (decl) != PARM_DECL
         isn't valid for a PARM_DECL.  */
       current_function_decl != 0
       && TREE_CODE (decl) != PARM_DECL
-      && ! TREE_THIS_VOLATILE (decl)
+      && !TREE_THIS_VOLATILE (decl)
       && TREE_READONLY (decl)
       && DECL_INITIAL (decl) != 0
       && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
       && TREE_READONLY (decl)
       && DECL_INITIAL (decl) != 0
       && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
@@ -1200,7 +1294,7 @@ default_function_array_conversion (tree exp)
       int volatilep = 0;
       int lvalue_array_p;
 
       int volatilep = 0;
       int lvalue_array_p;
 
-      if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
+      if (REFERENCE_CLASS_P (exp) || DECL_P (exp))
        {
          constp = TREE_READONLY (exp);
          volatilep = TREE_THIS_VOLATILE (exp);
        {
          constp = TREE_READONLY (exp);
          volatilep = TREE_THIS_VOLATILE (exp);
@@ -1357,7 +1451,7 @@ lookup_field (tree decl, tree component)
      find the element.  Otherwise, do a linear search.  TYPE_LANG_SPECIFIC
      will always be set for structures which have many elements.  */
 
      find the element.  Otherwise, do a linear search.  TYPE_LANG_SPECIFIC
      will always be set for structures which have many elements.  */
 
-  if (TYPE_LANG_SPECIFIC (type))
+  if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s)
     {
       int bot, top, half;
       tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
     {
       int bot, top, half;
       tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
@@ -1446,26 +1540,6 @@ build_component_ref (tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
-  /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
-     Ensure that the arguments are not lvalues; otherwise,
-     if the component is an array, it would wrongly decay to a pointer in
-     C89 mode.
-     We cannot do this with a COND_EXPR, because in a conditional expression
-     the default promotions are applied to both sides, and this would yield
-     the wrong type of the result; for example, if the components have
-     type "char".  */
-  switch (TREE_CODE (datum))
-    {
-    case COMPOUND_EXPR:
-      {
-       tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
-       return build2 (COMPOUND_EXPR, TREE_TYPE (value),
-                      TREE_OPERAND (datum, 0), non_lvalue (value));
-      }
-    default:
-      break;
-    }
-
   /* See if there is a field or component with name COMPONENT.  */
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
   /* See if there is a field or component with name COMPONENT.  */
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
@@ -1480,9 +1554,7 @@ build_component_ref (tree datum, tree component)
 
       if (!field)
        {
 
       if (!field)
        {
-         error ("%s has no member named %qs",
-                code == RECORD_TYPE ? "structure" : "union",
-                IDENTIFIER_POINTER (component));
+         error ("%qT has no member named %qE", type, component);
          return error_mark_node;
        }
 
          return error_mark_node;
        }
 
@@ -1517,8 +1589,8 @@ build_component_ref (tree datum, tree component)
       return ref;
     }
   else if (code != ERROR_MARK)
       return ref;
     }
   else if (code != ERROR_MARK)
-    error ("request for member %qs in something not a structure or union",
-           IDENTIFIER_POINTER (component));
+    error ("request for member %qE in something not a structure or union",
+          component);
 
   return error_mark_node;
 }
 
   return error_mark_node;
 }
@@ -1542,7 +1614,12 @@ build_indirect_ref (tree ptr, const char *errorstring)
       else
        {
          tree t = TREE_TYPE (type);
       else
        {
          tree t = TREE_TYPE (type);
-         tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer);
+         tree mvt = t;
+         tree ref;
+
+         if (TREE_CODE (mvt) != ARRAY_TYPE)
+           mvt = TYPE_MAIN_VARIANT (mvt);
+         ref = build1 (INDIRECT_REF, mvt, pointer);
 
          if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
 
          if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
@@ -1583,39 +1660,58 @@ build_indirect_ref (tree ptr, const char *errorstring)
 tree
 build_array_ref (tree array, tree index)
 {
 tree
 build_array_ref (tree array, tree index)
 {
-  if (index == 0)
-    {
-      error ("subscript missing in array reference");
-      return error_mark_node;
-    }
-
+  bool swapped = false;
   if (TREE_TYPE (array) == error_mark_node
       || TREE_TYPE (index) == error_mark_node)
     return error_mark_node;
 
   if (TREE_TYPE (array) == error_mark_node
       || TREE_TYPE (index) == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+  if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
+      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
     {
     {
-      tree rval, type;
-
-      /* Subscripting with type char is likely to lose
-        on a machine where chars are signed.
-        So warn on any machine, but optionally.
-        Don't warn for unsigned char since that type is safe.
-        Don't warn for signed char because anyone who uses that
-        must have done so deliberately.  */
-      if (warn_char_subscripts
-         && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-       warning ("array subscript has type %<char%>");
-
-      /* Apply default promotions *after* noticing character types.  */
-      index = default_conversion (index);
-
-      /* Require integer *after* promotion, for sake of enums.  */
-      if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE)
+      tree temp;
+      if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
+         && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
        {
-         error ("array subscript is not an integer");
+         error ("subscripted value is neither array nor pointer");
          return error_mark_node;
        }
          return error_mark_node;
        }
+      temp = array;
+      array = index;
+      index = temp;
+      swapped = true;
+    }
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
+    {
+      error ("array subscript is not an integer");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
+    {
+      error ("subscripted value is pointer to function");
+      return error_mark_node;
+    }
+
+  /* Subscripting with type char is likely to lose on a machine where
+     chars are signed.  So warn on any machine, but optionally.  Don't
+     warn for unsigned char since that type is safe.  Don't warn for
+     signed char because anyone who uses that must have done so
+     deliberately.  ??? Existing practice has also been to warn only
+     when the char index is syntactically the index, not for
+     char[array].  */
+  if (warn_char_subscripts && !swapped
+      && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
+    warning ("array subscript has type %<char%>");
+
+  /* Apply default promotions *after* noticing character types.  */
+  index = default_conversion (index);
+
+  gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
+
+  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+    {
+      tree rval, type;
 
       /* An array that is indexed by a non-constant
         cannot be stored in a register; we must be able to do
 
       /* An array that is indexed by a non-constant
         cannot be stored in a register; we must be able to do
@@ -1634,7 +1730,7 @@ build_array_ref (tree array, tree index)
         to access a non-existent part of the register.  */
       if (TREE_CODE (index) == INTEGER_CST
          && TYPE_DOMAIN (TREE_TYPE (array))
         to access a non-existent part of the register.  */
       if (TREE_CODE (index) == INTEGER_CST
          && TYPE_DOMAIN (TREE_TYPE (array))
-         && ! int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array))))
+         && !int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array))))
        {
          if (!c_mark_addressable (array))
            return error_mark_node;
        {
          if (!c_mark_addressable (array))
            return error_mark_node;
@@ -1647,11 +1743,13 @@ build_array_ref (tree array, tree index)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
            pedwarn ("ISO C forbids subscripting %<register%> array");
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
            pedwarn ("ISO C forbids subscripting %<register%> array");
-         else if (! flag_isoc99 && ! lvalue_p (foo))
+         else if (!flag_isoc99 && !lvalue_p (foo))
            pedwarn ("ISO C90 forbids subscripting non-lvalue array");
        }
 
            pedwarn ("ISO C90 forbids subscripting non-lvalue array");
        }
 
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
+      type = TREE_TYPE (TREE_TYPE (array));
+      if (TREE_CODE (type) != ARRAY_TYPE)
+       type = TYPE_MAIN_VARIANT (type);
       rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
          or if the array is.  */
       rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
          or if the array is.  */
@@ -1670,72 +1768,36 @@ build_array_ref (tree array, tree index)
            | TREE_THIS_VOLATILE (array));
       return require_complete_type (fold (rval));
     }
            | TREE_THIS_VOLATILE (array));
       return require_complete_type (fold (rval));
     }
+  else
+    {
+      tree ar = default_conversion (array);
 
 
-  {
-    tree ar = default_conversion (array);
-    tree ind = default_conversion (index);
-
-    /* Do the same warning check as above, but only on the part that's
-       syntactically the index and only if it is also semantically
-       the index.  */
-    if (warn_char_subscripts
-       && TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE
-       && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-      warning ("subscript has type %<char%>");
-
-    /* Put the integer in IND to simplify error checking.  */
-    if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
-      {
-       tree temp = ar;
-       ar = ind;
-       ind = temp;
-      }
-
-    if (ar == error_mark_node)
-      return ar;
+      if (ar == error_mark_node)
+       return ar;
 
 
-    if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE
-       || TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE)
-      {
-       error ("subscripted value is neither array nor pointer");
-       return error_mark_node;
-      }
-    if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
-      {
-       error ("array subscript is not an integer");
-       return error_mark_node;
-      }
+      gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
+      gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
 
 
-    return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, ind, 0),
-                              "array indexing");
-  }
+      return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
+                                "array indexing");
+    }
 }
 \f
 /* Build an external reference to identifier ID.  FUN indicates
 }
 \f
 /* Build an external reference to identifier ID.  FUN indicates
-   whether this will be used for a function call.  */
+   whether this will be used for a function call.  LOC is the source
+   location of the identifier.  */
 tree
 tree
-build_external_ref (tree id, int fun)
+build_external_ref (tree id, int fun, location_t loc)
 {
   tree ref;
   tree decl = lookup_name (id);
 {
   tree ref;
   tree decl = lookup_name (id);
-  tree objc_ivar = objc_lookup_ivar (id);
+
+  /* In Objective-C, an instance variable (ivar) may be preferred to
+     whatever lookup_name() found.  */
+  decl = objc_lookup_ivar (decl, id);
 
   if (decl && decl != error_mark_node)
 
   if (decl && decl != error_mark_node)
-    {
-      /* Properly declared variable or function reference.  */
-      if (!objc_ivar)
-       ref = decl;
-      else if (decl != objc_ivar && !DECL_FILE_SCOPE_P (decl))
-       {
-         warning ("local declaration of %qs hides instance variable",
-                  IDENTIFIER_POINTER (id));
-         ref = decl;
-       }
-      else
-       ref = objc_ivar;
-    }
-  else if (objc_ivar)
-    ref = objc_ivar;
+    ref = decl;
   else if (fun)
     /* Implicit function declaration.  */
     ref = implicitly_declare (id);
   else if (fun)
     /* Implicit function declaration.  */
     ref = implicitly_declare (id);
@@ -1745,7 +1807,7 @@ build_external_ref (tree id, int fun)
     return error_mark_node;
   else
     {
     return error_mark_node;
   else
     {
-      undeclared_variable (id);
+      undeclared_variable (id, loc);
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
@@ -1808,7 +1870,7 @@ static struct maybe_used_decl *maybe_used_decls;
    a VLA type or the operand of typeof is a variably modified
    type.  */
 
    a VLA type or the operand of typeof is a variably modified
    type.  */
 
-void
+static void
 record_maybe_used_decl (tree decl)
 {
   struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
 record_maybe_used_decl (tree decl)
 {
   struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
@@ -1849,9 +1911,18 @@ struct c_expr
 c_expr_sizeof_expr (struct c_expr expr)
 {
   struct c_expr ret;
 c_expr_sizeof_expr (struct c_expr expr)
 {
   struct c_expr ret;
-  ret.value = c_sizeof (TREE_TYPE (expr.value));
-  ret.original_code = ERROR_MARK;
-  pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = c_sizeof (TREE_TYPE (expr.value));
+      ret.original_code = ERROR_MARK;
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
   return ret;
 }
 
   return ret;
 }
 
@@ -1911,7 +1982,7 @@ build_function_call (tree function, tree params)
   if (!(TREE_CODE (fntype) == POINTER_TYPE
        && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
     {
   if (!(TREE_CODE (fntype) == POINTER_TYPE
        && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
     {
-      error ("called object is not a function");
+      error ("called object %qE is not a function", function);
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
@@ -1930,11 +2001,11 @@ build_function_call (tree function, tree params)
      ??? This doesn't work for Objective-C because objc_comptypes
      refuses to compare function prototypes, yet the compiler appears
      to build calls that are flagged as invalid by C's comptypes.  */
      ??? This doesn't work for Objective-C because objc_comptypes
      refuses to compare function prototypes, yet the compiler appears
      to build calls that are flagged as invalid by C's comptypes.  */
-  if (! c_dialect_objc ()
+  if (!c_dialect_objc ()
       && TREE_CODE (function) == NOP_EXPR
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
       && TREE_CODE (function) == NOP_EXPR
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
-      && ! comptypes (fntype, TREE_TYPE (tem)))
+      && !comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
       tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP],
     {
       tree return_type = TREE_TYPE (fntype);
       tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP],
@@ -1970,7 +2041,10 @@ build_function_call (tree function, tree params)
      function prototype, or apply default promotions.  */
 
   coerced_params
      function prototype, or apply default promotions.  */
 
   coerced_params
-    = convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl);
+    = convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl);
+
+  if (coerced_params == error_mark_node)
+    return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
 
 
   /* Check that the arguments to the function are valid.  */
 
@@ -1999,7 +2073,8 @@ build_function_call (tree function, tree params)
 \f
 /* Convert the argument expressions in the list VALUES
    to the types in the list TYPELIST.  The result is a list of converted
 \f
 /* Convert the argument expressions in the list VALUES
    to the types in the list TYPELIST.  The result is a list of converted
-   argument expressions.
+   argument expressions, unless there are too few arguments in which
+   case it is error_mark_node.
 
    If TYPELIST is exhausted, or when an element has NULL as its type,
    perform the default conversions.
 
    If TYPELIST is exhausted, or when an element has NULL as its type,
    perform the default conversions.
@@ -2008,7 +2083,8 @@ build_function_call (tree function, tree params)
    It may be 0, if that info is not available.
    It is used only for generating error messages.
 
    It may be 0, if that info is not available.
    It is used only for generating error messages.
 
-   NAME is an IDENTIFIER_NODE or 0.  It is used only for error messages.
+   FUNCTION is a tree for the called function.  It is used only for
+   error messages, where it is formatted with %qE.
 
    This is also where warnings about wrong number of args are generated.
 
 
    This is also where warnings about wrong number of args are generated.
 
@@ -2016,11 +2092,21 @@ build_function_call (tree function, tree params)
    with the elements of the list in the TREE_VALUE slots of those nodes.  */
 
 static tree
    with the elements of the list in the TREE_VALUE slots of those nodes.  */
 
 static tree
-convert_arguments (tree typelist, tree values, tree name, tree fundecl)
+convert_arguments (tree typelist, tree values, tree function, tree fundecl)
 {
   tree typetail, valtail;
   tree result = NULL;
   int parmnum;
 {
   tree typetail, valtail;
   tree result = NULL;
   int parmnum;
+  tree selector;
+
+  /* Change pointer to function to the function itself for
+     diagnostics.  */
+  if (TREE_CODE (function) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+    function = TREE_OPERAND (function, 0);
+
+  /* Handle an ObjC selector specially for diagnostics.  */
+  selector = objc_message_selector ();
 
   /* Scan the given expressions and types, producing individual
      converted arguments and pushing them on RESULT in reverse order.  */
 
   /* Scan the given expressions and types, producing individual
      converted arguments and pushing them on RESULT in reverse order.  */
@@ -2031,17 +2117,22 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
     {
       tree type = typetail ? TREE_VALUE (typetail) : 0;
       tree val = TREE_VALUE (valtail);
     {
       tree type = typetail ? TREE_VALUE (typetail) : 0;
       tree val = TREE_VALUE (valtail);
+      tree rname = function;
+      int argnum = parmnum + 1;
+      const char *invalid_func_diag;
 
       if (type == void_type_node)
        {
 
       if (type == void_type_node)
        {
-         if (name)
-           error ("too many arguments to function %qs",
-                  IDENTIFIER_POINTER (name));
-         else
-           error ("too many arguments to function");
+         error ("too many arguments to function %qE", function);
          break;
        }
 
          break;
        }
 
+      if (selector && argnum > 2)
+       {
+         rname = selector;
+         argnum -= 2;
+       }
+
       /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
       /* Do not use STRIP_NOPS here!  We do not want an enumerator with value 0
         to convert automatically to a pointer.  */
       /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
       /* Do not use STRIP_NOPS here!  We do not want an enumerator with value 0
         to convert automatically to a pointer.  */
@@ -2057,7 +2148,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
          /* Formal parm type is specified by a function prototype.  */
          tree parmval;
 
          /* Formal parm type is specified by a function prototype.  */
          tree parmval;
 
-         if (!COMPLETE_TYPE_P (type))
+         if (type == error_mark_node || !COMPLETE_TYPE_P (type))
            {
              error ("type of formal parameter %d is incomplete", parmnum + 1);
              parmval = val;
            {
              error ("type of formal parameter %d is incomplete", parmnum + 1);
              parmval = val;
@@ -2072,22 +2163,34 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
 
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
 
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
-                   warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1);
+                   warning ("passing argument %d of %qE as integer "
+                            "rather than floating due to prototype",
+                            argnum, rname);
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
-                   warn_for_assignment ("%s as integer rather than complex due to prototype", (char *) 0, name, parmnum + 1);
+                   warning ("passing argument %d of %qE as integer "
+                            "rather than complex due to prototype",
+                            argnum, rname);
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
-                   warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1);
+                   warning ("passing argument %d of %qE as complex "
+                            "rather than floating due to prototype",
+                            argnum, rname);
                  else if (TREE_CODE (type) == REAL_TYPE
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                  else if (TREE_CODE (type) == REAL_TYPE
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
-                   warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1);
+                   warning ("passing argument %d of %qE as floating "
+                            "rather than integer due to prototype",
+                            argnum, rname);
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
-                   warn_for_assignment ("%s as complex rather than integer due to prototype", (char *) 0, name, parmnum + 1);
+                   warning ("passing argument %d of %qE as complex "
+                            "rather than integer due to prototype",
+                            argnum, rname);
                  else if (TREE_CODE (type) == REAL_TYPE
                           && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
                  else if (TREE_CODE (type) == REAL_TYPE
                           && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
-                   warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1);
+                   warning ("passing argument %d of %qE as floating "
+                            "rather than complex due to prototype",
+                            argnum, rname);
                  /* ??? At some point, messages should be written about
                     conversions between complex types, but that's too messy
                     to do now.  */
                  /* ??? At some point, messages should be written about
                     conversions between complex types, but that's too messy
                     to do now.  */
@@ -2097,9 +2200,9 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
                      if (formal_prec == TYPE_PRECISION (float_type_node))
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
                      if (formal_prec == TYPE_PRECISION (float_type_node))
-                       warn_for_assignment ("%s as %<float%> rather than "
-                                            "%<double%> due to prototype",
-                                            (char *) 0, name, parmnum + 1);
+                       warning ("passing argument %d of %qE as %<float%> "
+                                "rather than %<double%> due to prototype",
+                                argnum, rname);
                    }
                  /* Detect integer changing in width or signedness.
                     These warnings are only activated with
                    }
                  /* Detect integer changing in width or signedness.
                     These warnings are only activated with
@@ -2117,7 +2220,8 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
-                       warn_for_assignment ("%s with different width due to prototype", (char *) 0, name, parmnum + 1);
+                       warning ("passing argument %d of %qE with different "
+                                "width due to prototype", argnum, rname);
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
                        ;
                      /* Don't complain if the formal parameter type
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
                        ;
                      /* Don't complain if the formal parameter type
@@ -2143,15 +2247,17 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                               && TYPE_UNSIGNED (TREE_TYPE (val)))
                        ;
                      else if (TYPE_UNSIGNED (type))
                               && TYPE_UNSIGNED (TREE_TYPE (val)))
                        ;
                      else if (TYPE_UNSIGNED (type))
-                       warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1);
+                       warning ("passing argument %d of %qE as unsigned "
+                                "due to prototype", argnum, rname);
                      else
                      else
-                       warn_for_assignment ("%s as signed due to prototype", (char *) 0, name, parmnum + 1);
+                       warning ("passing argument %d of %qE as signed "
+                                "due to prototype", argnum, rname);
                    }
                }
 
                    }
                }
 
-             parmval = convert_for_assignment (type, val,
-                                               (char *) 0, /* arg passing  */
-                                               fundecl, name, parmnum + 1);
+             parmval = convert_for_assignment (type, val, ic_argpass,
+                                               fundecl, function,
+                                               parmnum + 1);
 
              if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
                  && INTEGRAL_TYPE_P (type)
 
              if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
                  && INTEGRAL_TYPE_P (type)
@@ -2165,6 +2271,12 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                   < TYPE_PRECISION (double_type_node)))
        /* Convert `float' to `double'.  */
        result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
                   < TYPE_PRECISION (double_type_node)))
        /* Convert `float' to `double'.  */
        result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
+      else if ((invalid_func_diag = 
+               targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
+       {
+         error (invalid_func_diag);
+         return error_mark_node; 
+       }
       else
        /* Convert `short' and `char' to full-size `int'.  */
        result = tree_cons (NULL_TREE, default_conversion (val), result);
       else
        /* Convert `short' and `char' to full-size `int'.  */
        result = tree_cons (NULL_TREE, default_conversion (val), result);
@@ -2175,11 +2287,8 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      if (name)
-       error ("too few arguments to function %qs",
-              IDENTIFIER_POINTER (name));
-      else
-       error ("too few arguments to function");
+      error ("too few arguments to function %qE", function);
+      return error_mark_node;
     }
 
   return nreverse (result);
     }
 
   return nreverse (result);
@@ -2232,7 +2341,8 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of |");
          /* Check cases like x|y==z */
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of |");
          /* Check cases like x|y==z */
-         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+         if (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison)
            warning ("suggest parentheses around comparison in operand of |");
        }
 
            warning ("suggest parentheses around comparison in operand of |");
        }
 
@@ -2244,7 +2354,8 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of ^");
          /* Check cases like x^y==z */
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of ^");
          /* Check cases like x^y==z */
-         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+         if (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison)
            warning ("suggest parentheses around comparison in operand of ^");
        }
 
            warning ("suggest parentheses around comparison in operand of ^");
        }
 
@@ -2254,13 +2365,14 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around + or - in operand of &");
          /* Check cases like x&y==z */
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around + or - in operand of &");
          /* Check cases like x&y==z */
-         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+         if (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison)
            warning ("suggest parentheses around comparison in operand of &");
        }
       /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
            warning ("suggest parentheses around comparison in operand of &");
        }
       /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
-      if (TREE_CODE_CLASS (code) == '<'
-         && (TREE_CODE_CLASS (code1) == '<'
-             || TREE_CODE_CLASS (code2) == '<'))
+      if (TREE_CODE_CLASS (code) == tcc_comparison
+         && (TREE_CODE_CLASS (code1) == tcc_comparison
+             || TREE_CODE_CLASS (code2) == tcc_comparison))
        warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");
 
     }
        warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");
 
     }
@@ -2548,8 +2660,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
-                                  ? "invalid lvalue in increment"
-                                  : "invalid lvalue in decrement")))
+                                  ? lv_increment
+                                  : lv_decrement)))
          return error_mark_node;
 
        /* Report a read-only lvalue.  */
          return error_mark_node;
 
        /* Report a read-only lvalue.  */
@@ -2557,7 +2669,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          readonly_error (arg,
                          ((code == PREINCREMENT_EXPR
                            || code == POSTINCREMENT_EXPR)
          readonly_error (arg,
                          ((code == PREINCREMENT_EXPR
                            || code == POSTINCREMENT_EXPR)
-                          ? "increment" : "decrement"));
+                          ? lv_increment : lv_decrement));
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
@@ -2594,7 +2706,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
-              && !lvalue_or_else (arg, "invalid lvalue in unary %<&%>"))
+              && !lvalue_or_else (arg, lv_addressof))
        return error_mark_node;
 
       /* Ordinary case; arg is a COMPONENT_REF or a decl.  */
        return error_mark_node;
 
       /* Ordinary case; arg is a COMPONENT_REF or a decl.  */
@@ -2604,7 +2716,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          to which the address will point.  Note that you can't get a
         restricted pointer by taking the address of something, so we
         only have to deal with `const' and `volatile' here.  */
          to which the address will point.  Note that you can't get a
         restricted pointer by taking the address of something, so we
         only have to deal with `const' and `volatile' here.  */
-      if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
+      if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
          && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
          argtype = c_build_type_variant (argtype,
                                          TREE_READONLY (arg),
          && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
          argtype = c_build_type_variant (argtype,
                                          TREE_READONLY (arg),
@@ -2613,13 +2725,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       if (!c_mark_addressable (arg))
        return error_mark_node;
 
       if (!c_mark_addressable (arg))
        return error_mark_node;
 
-      if (TREE_CODE (arg) == COMPONENT_REF
-         && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
-       {
-         error ("attempt to take address of bit-field structure member %qD",
-                TREE_OPERAND (arg, 1));
-         return error_mark_node;
-       }
+      gcc_assert (TREE_CODE (arg) != COMPONENT_REF
+                 || !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)));
 
       argtype = build_pointer_type (argtype);
 
 
       argtype = build_pointer_type (argtype);
 
@@ -2683,40 +2790,38 @@ lvalue_p (tree ref)
       return 0;
     }
 }
       return 0;
     }
 }
-
-/* Return nonzero if REF is an lvalue valid for this language;
-   otherwise, print an error message and return zero.  */
-
-static int
-lvalue_or_else (tree ref, const char *msgid)
-{
-  int win = lvalue_p (ref);
-
-  if (! win)
-    error ("%s", msgid);
-
-  return win;
-}
-
 \f
 \f
-/* Warn about storing in something that is `const'.  */
+/* Give an error for storing in something that is 'const'.  */
 
 
-void
-readonly_error (tree arg, const char *msgid)
+static void
+readonly_error (tree arg, enum lvalue_use use)
 {
 {
+  gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement);
+  /* Using this macro rather than (for example) arrays of messages
+     ensures that all the format strings are checked at compile
+     time.  */
+#define READONLY_MSG(A, I, D) (use == lv_assign                                \
+                              ? (A)                                    \
+                              : (use == lv_increment ? (I) : (D)))
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       readonly_error (TREE_OPERAND (arg, 0), msgid);
+       readonly_error (TREE_OPERAND (arg, 0), use);
       else
       else
-       error ("%s of read-only member %qs", _(msgid),
-              IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
+       error (READONLY_MSG (N_("assignment of read-only member %qD"),
+                            N_("increment of read-only member %qD"),
+                            N_("decrement of read-only member %qD")),
+              TREE_OPERAND (arg, 1));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    error ("%s of read-only variable %qs", _(msgid),
-          IDENTIFIER_POINTER (DECL_NAME (arg)));
+    error (READONLY_MSG (N_("assignment of read-only variable %qD"),
+                        N_("increment of read-only variable %qD"),
+                        N_("decrement of read-only variable %qD")),
+          arg);
   else
   else
-    error ("%s of read-only location", _(msgid));
+    error (READONLY_MSG (N_("assignment of read-only location"),
+                        N_("increment of read-only location"),
+                        N_("decrement of read-only location")));
 }
 \f
 /* Mark EXP saying that we need to be able to take the
 }
 \f
 /* Mark EXP saying that we need to be able to take the
@@ -2734,8 +2839,8 @@ c_mark_addressable (tree exp)
       case COMPONENT_REF:
        if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
          {
       case COMPONENT_REF:
        if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
          {
-           error ("cannot take address of bit-field %qs",
-                  IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
+           error
+             ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
            return false;
          }
 
            return false;
          }
 
@@ -2762,24 +2867,19 @@ c_mark_addressable (tree exp)
          {
            if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
              {
          {
            if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
              {
-               error ("global register variable %qs used in nested function",
-                      IDENTIFIER_POINTER (DECL_NAME (x)));
+               error
+                 ("global register variable %qD used in nested function", x);
                return false;
              }
                return false;
              }
-           pedwarn ("register variable %qs used in nested function",
-                    IDENTIFIER_POINTER (DECL_NAME (x)));
+           pedwarn ("register variable %qD used in nested function", x);
          }
        else if (C_DECL_REGISTER (x))
          {
            if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
          }
        else if (C_DECL_REGISTER (x))
          {
            if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
-             {
-               error ("address of global register variable %qs requested",
-                      IDENTIFIER_POINTER (DECL_NAME (x)));
-               return false;
-             }
-
-           pedwarn ("address of register variable %qs requested",
-                    IDENTIFIER_POINTER (DECL_NAME (x)));
+             error ("address of global register variable %qD requested", x);
+           else
+             error ("address of register variable %qD requested", x);
+           return false;
          }
 
        /* drops in */
          }
 
        /* drops in */
@@ -2844,7 +2944,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
            && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
                || code2 == COMPLEX_TYPE))
     {
            && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
                || code2 == COMPLEX_TYPE))
     {
-      result_type = common_type (type1, type2);
+      result_type = c_common_type (type1, type2);
 
       /* If -Wsign-compare, warn here if type1 and type2 have
         different signedness.  We'll promote the signed to unsigned
 
       /* If -Wsign-compare, warn here if type1 and type2 have
         different signedness.  We'll promote the signed to unsigned
@@ -2861,7 +2961,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
              /* Do not warn if the result type is signed, since the
                 signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
              /* Do not warn if the result type is signed, since the
                 signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
-             if (! TYPE_UNSIGNED (result_type))
+             if (!TYPE_UNSIGNED (result_type))
                /* OK */;
              /* Do not warn if the signed quantity is an unsuffixed
                 integer literal (or some static constant expression
                /* OK */;
              /* Do not warn if the signed quantity is an unsuffixed
                 integer literal (or some static constant expression
@@ -2914,7 +3014,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
     {
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
     {
-      if (! integer_zerop (op2))
+      if (!integer_zerop (op2))
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
@@ -2970,17 +3070,13 @@ build_compound_expr (tree expr1, tree expr2)
   /* Convert arrays and functions to pointers.  */
   expr2 = default_function_array_conversion (expr2);
 
   /* Convert arrays and functions to pointers.  */
   expr2 = default_function_array_conversion (expr2);
 
-  /* Don't let (0, 0) be null pointer constant.  */
-  if (integer_zerop (expr2))
-    expr2 = non_lvalue (expr2);
-
-  if (! TREE_SIDE_EFFECTS (expr1))
+  if (!TREE_SIDE_EFFECTS (expr1))
     {
       /* The left-hand operand of a comma expression is like an expression
          statement: with -Wextra or -Wunused, we should warn if it doesn't have
         any side-effects, unless it was explicitly cast to (void).  */
       if (warn_unused_value
     {
       /* The left-hand operand of a comma expression is like an expression
          statement: with -Wextra or -Wunused, we should warn if it doesn't have
         any side-effects, unless it was explicitly cast to (void).  */
       if (warn_unused_value
-           && ! (TREE_CODE (expr1) == CONVERT_EXPR
+           && !(TREE_CODE (expr1) == CONVERT_EXPR
                 && VOID_TYPE_P (TREE_TYPE (expr1))))
         warning ("left-hand operand of comma expression has no effect");
     }
                 && VOID_TYPE_P (TREE_TYPE (expr1))))
         warning ("left-hand operand of comma expression has no effect");
     }
@@ -3140,7 +3236,8 @@ build_c_cast (tree type, tree expr)
       if (warn_bad_function_cast
          && TREE_CODE (value) == CALL_EXPR
          && TREE_CODE (type) != TREE_CODE (otype))
       if (warn_bad_function_cast
          && TREE_CODE (value) == CALL_EXPR
          && TREE_CODE (type) != TREE_CODE (otype))
-       warning ("cast does not match function type");
+       warning ("cast from function call of type %qT to non-matching "
+                "type %qT", otype, type);
 
       if (TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == INTEGER_TYPE
 
       if (TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == INTEGER_TYPE
@@ -3193,9 +3290,6 @@ build_c_cast (tree type, tree expr)
        pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
 
       ovalue = value;
        pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
 
       ovalue = value;
-      /* Replace a nonvolatile const static variable with its value.  */
-      if (optimize && TREE_CODE (value) == VAR_DECL)
-       value = decl_constant_value (value);
       value = convert (type, value);
 
       /* Ignore any integer overflow caused by the cast.  */
       value = convert (type, value);
 
       /* Ignore any integer overflow caused by the cast.  */
@@ -3208,19 +3302,13 @@ build_c_cast (tree type, tree expr)
          else
            TREE_OVERFLOW (value) = 0;
          
          else
            TREE_OVERFLOW (value) = 0;
          
-         if (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c')
+         if (CONSTANT_CLASS_P (ovalue))
            /* Similarly, constant_overflow cannot have become
               cleared.  */
            TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
        }
     }
 
            /* Similarly, constant_overflow cannot have become
               cleared.  */
            TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
        }
     }
 
-  /* Don't let (void *) (FOO *) 0 be a null pointer constant.  */
-  if (TREE_CODE (value) == INTEGER_CST
-      && TREE_CODE (expr) == INTEGER_CST
-      && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
-    value = non_lvalue (value);
-
   /* Don't let a cast be an lvalue.  */
   if (value == expr)
     value = non_lvalue (value);
   /* Don't let a cast be an lvalue.  */
   if (value == expr)
     value = non_lvalue (value);
@@ -3283,16 +3371,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
-  if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
+  if (!lvalue_or_else (lhs, lv_assign))
     return error_mark_node;
 
     return error_mark_node;
 
-  /* Warn about storing in something that is `const'.  */
+  /* Give an error for storing in something that is 'const'.  */
 
   if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
 
   if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
-    readonly_error (lhs, "assignment");
+    readonly_error (lhs, lv_assign);
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
@@ -3317,12 +3405,12 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   /* Convert new value to destination type.  */
 
 
   /* Convert new value to destination type.  */
 
-  newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"),
+  newrhs = convert_for_assignment (lhstype, newrhs, ic_assign,
                                   NULL_TREE, NULL_TREE, 0);
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
 
                                   NULL_TREE, NULL_TREE, 0);
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
 
-  /* Scan operands */
+  /* Scan operands */
 
   result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
 
   result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
@@ -3334,7 +3422,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   if (olhstype == TREE_TYPE (result))
     return result;
 
   if (olhstype == TREE_TYPE (result))
     return result;
-  return convert_for_assignment (olhstype, result, _("assignment"),
+  return convert_for_assignment (olhstype, result, ic_assign,
                                 NULL_TREE, NULL_TREE, 0);
 }
 \f
                                 NULL_TREE, NULL_TREE, 0);
 }
 \f
@@ -3343,21 +3431,66 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
    The real work of conversion is done by `convert'.
    The purpose of this function is to generate error messages
    for assignments that are not allowed in C.
    The real work of conversion is done by `convert'.
    The purpose of this function is to generate error messages
    for assignments that are not allowed in C.
-   ERRTYPE is a string to use in error messages:
-   "assignment", "return", etc.  If it is null, this is parameter passing
-   for a function call (and different error messages are output).
+   ERRTYPE says whether it is argument passing, assignment,
+   initialization or return.
 
 
-   FUNNAME is the name of the function being called,
-   as an IDENTIFIER_NODE, or null.
+   FUNCTION is a tree for the function being called.
    PARMNUM is the number of the argument, for printing in error messages.  */
 
 static tree
    PARMNUM is the number of the argument, for printing in error messages.  */
 
 static tree
-convert_for_assignment (tree type, tree rhs, const char *errtype,
-                       tree fundecl, tree funname, int parmnum)
+convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
+                       tree fundecl, tree function, int parmnum)
 {
   enum tree_code codel = TREE_CODE (type);
   tree rhstype;
   enum tree_code coder;
 {
   enum tree_code codel = TREE_CODE (type);
   tree rhstype;
   enum tree_code coder;
+  tree rname = NULL_TREE;
+
+  if (errtype == ic_argpass || errtype == ic_argpass_nonproto)
+    {
+      tree selector;
+      /* Change pointer to function to the function itself for
+        diagnostics.  */
+      if (TREE_CODE (function) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+       function = TREE_OPERAND (function, 0);
+
+      /* Handle an ObjC selector specially for diagnostics.  */
+      selector = objc_message_selector ();
+      rname = function;
+      if (selector && parmnum > 2)
+       {
+         rname = selector;
+         parmnum -= 2;
+       }
+    }
+
+  /* This macro is used to emit diagnostics to ensure that all format
+     strings are complete sentences, visible to gettext and checked at
+     compile time.  */
+#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE)    \
+  do {                                         \
+    switch (errtype)                           \
+      {                                                \
+      case ic_argpass:                         \
+       pedwarn (AR, parmnum, rname);           \
+       break;                                  \
+      case ic_argpass_nonproto:                        \
+       warning (AR, parmnum, rname);           \
+       break;                                  \
+      case ic_assign:                          \
+       pedwarn (AS);                           \
+       break;                                  \
+      case ic_init:                            \
+       pedwarn (IN);                           \
+       break;                                  \
+      case ic_return:                          \
+       pedwarn (RE);                           \
+       break;                                  \
+      default:                                 \
+       gcc_unreachable ();                     \
+      }                                                \
+  } while (0)
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   /* Do not use STRIP_NOPS here.  We do not want an enumerator
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   /* Do not use STRIP_NOPS here.  We do not want an enumerator
@@ -3390,6 +3523,11 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
 
   if (coder == VOID_TYPE)
     {
 
   if (coder == VOID_TYPE)
     {
+      /* Except for passing an argument to an unprototyped function,
+        this is a constraint violation.  When passing an argument to
+        an unprototyped function, it is compile-time undefined;
+        making it a constraint in that case was rejected in
+        DR#252.  */
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
@@ -3434,7 +3572,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
 
   /* Conversion to a transparent union from its member types.
      This applies only to function arguments.  */
 
   /* Conversion to a transparent union from its member types.
      This applies only to function arguments.  */
-  else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && ! errtype)
+  else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
+          && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
     {
       tree memb_types;
       tree marginal_memb_type = 0;
     {
       tree memb_types;
       tree marginal_memb_type = 0;
@@ -3474,7 +3613,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                    break;
 
                  /* Keep looking for a better type, but remember this one.  */
                    break;
 
                  /* Keep looking for a better type, but remember this one.  */
-                 if (! marginal_memb_type)
+                 if (!marginal_memb_type)
                    marginal_memb_type = memb_type;
                }
            }
                    marginal_memb_type = memb_type;
                }
            }
@@ -3491,7 +3630,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
 
       if (memb_types || marginal_memb_type)
        {
 
       if (memb_types || marginal_memb_type)
        {
-         if (! memb_types)
+         if (!memb_types)
            {
              /* We have only a marginally acceptable member type;
                 it needs a warning.  */
            {
              /* We have only a marginally acceptable member type;
                 it needs a warning.  */
@@ -3509,16 +3648,30 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                     function where an ordinary one is wanted, but not
                     vice-versa.  */
                  if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
                     function where an ordinary one is wanted, but not
                     vice-versa.  */
                  if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-                   warn_for_assignment ("%s makes qualified function pointer from unqualified",
-                                        errtype, funname, parmnum);
+                   WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE "
+                                           "makes qualified function "
+                                           "pointer from unqualified"),
+                                        N_("assignment makes qualified "
+                                           "function pointer from "
+                                           "unqualified"),
+                                        N_("initialization makes qualified "
+                                           "function pointer from "
+                                           "unqualified"),
+                                        N_("return makes qualified function "
+                                           "pointer from unqualified"));
                }
              else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
                }
              else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               warn_for_assignment ("%s discards qualifiers from pointer target type",
-                                    errtype, funname,
-                                    parmnum);
+               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
+                                       "qualifiers from pointer target type"),
+                                    N_("assignment discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("initialization discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("return discards qualifiers from "
+                                       "pointer target type"));
            }
 
            }
 
-         if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
+         if (pedantic && !DECL_IN_SYSTEM_HEADER (fundecl))
            pedwarn ("ISO C prohibits argument conversion to union type");
 
          return build1 (NOP_EXPR, type, rhs);
            pedwarn ("ISO C prohibits argument conversion to union type");
 
          return build1 (NOP_EXPR, type, rhs);
@@ -3531,9 +3684,15 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
     {
       tree ttl = TREE_TYPE (type);
       tree ttr = TREE_TYPE (rhstype);
     {
       tree ttl = TREE_TYPE (type);
       tree ttr = TREE_TYPE (rhstype);
+      tree mvl = ttl;
+      tree mvr = ttr;
       bool is_opaque_pointer;
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
 
       bool is_opaque_pointer;
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
 
+      if (TREE_CODE (mvl) != ARRAY_TYPE)
+       mvl = TYPE_MAIN_VARIANT (mvl);
+      if (TREE_CODE (mvr) != ARRAY_TYPE)
+       mvr = TYPE_MAIN_VARIANT (mvr);
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = (targetm.vector_opaque_p (type)
                            || targetm.vector_opaque_p (rhstype))
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = (targetm.vector_opaque_p (type)
                            || targetm.vector_opaque_p (rhstype))
@@ -3546,8 +3705,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
       if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
          || (target_cmp = comp_target_types (type, rhstype, 0))
          || is_opaque_pointer
       if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
          || (target_cmp = comp_target_types (type, rhstype, 0))
          || is_opaque_pointer
-         || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl))
-             == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr))))
+         || (c_common_unsigned_type (mvl)
+             == c_common_unsigned_type (mvr)))
        {
          if (pedantic
              && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
        {
          if (pedantic
              && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -3557,26 +3716,44 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                      which are not ANSI null ptr constants.  */
                   && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
                      which are not ANSI null ptr constants.  */
                   && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           warn_for_assignment ("ISO C forbids %s between function "
-                                "pointer and %<void *%>",
-                                errtype, funname, parmnum);
+           WARN_FOR_ASSIGNMENT (N_("ISO C forbids passing argument %d of "
+                                   "%qE between function pointer "
+                                   "and %<void *%>"),
+                                N_("ISO C forbids assignment between "
+                                   "function pointer and %<void *%>"),
+                                N_("ISO C forbids initialization between "
+                                   "function pointer and %<void *%>"),
+                                N_("ISO C forbids return between function "
+                                   "pointer and %<void *%>"));
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
              if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
              if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               warn_for_assignment ("%s discards qualifiers from pointer target type",
-                                    errtype, funname, parmnum);
+               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
+                                       "qualifiers from pointer target type"),
+                                    N_("assignment discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("initialization discards qualifiers "
+                                       "from pointer target type"),
+                                    N_("return discards qualifiers from "
+                                       "pointer target type"));
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
              else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
                       || target_cmp)
                ;
              /* If there is a mismatch, do warn.  */
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
              else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
                       || target_cmp)
                ;
              /* If there is a mismatch, do warn.  */
-             else
-               warn_for_assignment ("pointer targets in %s differ in signedness",
-                                    errtype, funname, parmnum);
+             else if (warn_pointer_sign)
+               WARN_FOR_ASSIGNMENT (N_("pointer targets in passing argument "
+                                       "%d of %qE differ in signedness"),
+                                    N_("pointer targets in assignment "
+                                       "differ in signedness"),
+                                    N_("pointer targets in initialization "
+                                       "differ in signedness"),
+                                    N_("pointer targets in return differ "
+                                       "in signedness"));
            }
          else if (TREE_CODE (ttl) == FUNCTION_TYPE
                   && TREE_CODE (ttr) == FUNCTION_TYPE)
            }
          else if (TREE_CODE (ttl) == FUNCTION_TYPE
                   && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -3586,17 +3763,30 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-               warn_for_assignment ("%s makes qualified function pointer from unqualified",
-                                    errtype, funname, parmnum);
+               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+                                       "qualified function pointer "
+                                       "from unqualified"),
+                                    N_("assignment makes qualified function "
+                                       "pointer from unqualified"),
+                                    N_("initialization makes qualified "
+                                       "function pointer from unqualified"),
+                                    N_("return makes qualified function "
+                                       "pointer from unqualified"));
            }
        }
       else
            }
        }
       else
-       warn_for_assignment ("%s from incompatible pointer type",
-                            errtype, funname, parmnum);
+       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE from "
+                               "incompatible pointer type"),
+                            N_("assignment from incompatible pointer type"),
+                            N_("initialization from incompatible "
+                               "pointer type"),
+                            N_("return from incompatible pointer type"));
       return convert (type, rhs);
     }
   else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
     {
       return convert (type, rhs);
     }
   else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
     {
+      /* ??? This should not be an error when inlining calls to
+        unprototyped functions.  */
       error ("invalid use of non-lvalue array");
       return error_mark_node;
     }
       error ("invalid use of non-lvalue array");
       return error_mark_node;
     }
@@ -3605,45 +3795,58 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
       /* An explicit constant 0 can convert to a pointer,
         or one that results from arithmetic, even including
         a cast to integer type.  */
       /* An explicit constant 0 can convert to a pointer,
         or one that results from arithmetic, even including
         a cast to integer type.  */
-      if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs))
+      if (!(TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs))
          &&
          &&
-         ! (TREE_CODE (rhs) == NOP_EXPR
-            && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
-            && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
-            && integer_zerop (TREE_OPERAND (rhs, 0))))
-         warn_for_assignment ("%s makes pointer from integer without a cast",
-                              errtype, funname, parmnum);
+         !(TREE_CODE (rhs) == NOP_EXPR
+           && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
+           && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
+           && integer_zerop (TREE_OPERAND (rhs, 0))))
+       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+                               "pointer from integer without a cast"),
+                            N_("assignment makes pointer from integer "
+                               "without a cast"),
+                            N_("initialization makes pointer from "
+                               "integer without a cast"),
+                            N_("return makes pointer from integer "
+                               "without a cast"));
 
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
 
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      warn_for_assignment ("%s makes integer from pointer without a cast",
-                          errtype, funname, parmnum);
+      WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes integer "
+                             "from pointer without a cast"),
+                          N_("assignment makes integer from pointer "
+                             "without a cast"),
+                          N_("initialization makes integer from pointer "
+                             "without a cast"),
+                          N_("return makes integer from pointer "
+                             "without a cast"));
       return convert (type, rhs);
     }
   else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
     return convert (type, rhs);
 
       return convert (type, rhs);
     }
   else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
     return convert (type, rhs);
 
-  if (!errtype)
+  switch (errtype)
     {
     {
-      if (funname)
-       {
-         tree selector = objc_message_selector ();
-
-         if (selector && parmnum > 2)
-           error ("incompatible type for argument %d of %qs",
-                  parmnum - 2, IDENTIFIER_POINTER (selector));
-         else
-           error ("incompatible type for argument %d of %qs",
-                  parmnum, IDENTIFIER_POINTER (funname));
-       }
-      else
-       error ("incompatible type for argument %d of indirect function call",
-              parmnum);
+    case ic_argpass:
+    case ic_argpass_nonproto:
+      /* ??? This should not be an error when inlining calls to
+        unprototyped functions.  */
+      error ("incompatible type for argument %d of %qE", parmnum, rname);
+      break;
+    case ic_assign:
+      error ("incompatible types in assignment");
+      break;
+    case ic_init:
+      error ("incompatible types in initialization");
+      break;
+    case ic_return:
+      error ("incompatible types in return");
+      break;
+    default:
+      gcc_unreachable ();
     }
     }
-  else
-    error ("incompatible types in %s", errtype);
 
   return error_mark_node;
 }
 
   return error_mark_node;
 }
@@ -3659,80 +3862,19 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
 
   /* If FN was prototyped, the value has been converted already
      in convert_arguments.  */
 
   /* If FN was prototyped, the value has been converted already
      in convert_arguments.  */
-  if (! value || TYPE_ARG_TYPES (TREE_TYPE (fn)))
+  if (!value || TYPE_ARG_TYPES (TREE_TYPE (fn)))
     return value;
 
   type = TREE_TYPE (parm);
   ret = convert_for_assignment (type, value,
     return value;
 
   type = TREE_TYPE (parm);
   ret = convert_for_assignment (type, value,
-                               (char *) 0 /* arg passing  */, fn,
-                               DECL_NAME (fn), argnum);
+                               ic_argpass_nonproto, fn,
+                               fn, argnum);
   if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
       && INTEGRAL_TYPE_P (type)
       && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
     ret = default_conversion (ret);
   return ret;
 }
   if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
       && INTEGRAL_TYPE_P (type)
       && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
     ret = default_conversion (ret);
   return ret;
 }
-
-/* Print a warning using MSGID.
-   It gets OPNAME as its one parameter.
-   if OPNAME is null and ARGNUM is 0, it is replaced by "passing arg of `FUNCTION'".
-   Otherwise if OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'".
-   FUNCTION and ARGNUM are handled specially if we are building an
-   Objective-C selector.  */
-
-static void
-warn_for_assignment (const char *msgid, const char *opname, tree function,
-                    int argnum)
-{
-  if (opname == 0)
-    {
-      tree selector = objc_message_selector ();
-      char * new_opname;
-
-      if (selector && argnum > 2)
-       {
-         function = selector;
-         argnum -= 2;
-       }
-      if (argnum == 0)
-       {
-         if (function)
-           {
-             /* Function name is known; supply it.  */
-             const char *const argstring = _("passing arg of '%s'");
-             new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
-                                  + strlen (argstring) + 1 + 1);
-             sprintf (new_opname, argstring,
-                      IDENTIFIER_POINTER (function));
-           }
-         else
-           {
-             /* Function name unknown (call through ptr).  */
-             const char *const argnofun = _("passing arg of pointer to function");
-             new_opname = (char *) alloca (strlen (argnofun) + 1 + 1);
-             sprintf (new_opname, argnofun);
-           }
-       }
-      else if (function)
-       {
-         /* Function name is known; supply it.  */
-         const char *const argstring = _("passing arg %d of '%s'");
-         new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
-                              + strlen (argstring) + 1 + 25 /*%d*/ + 1);
-         sprintf (new_opname, argstring, argnum,
-                  IDENTIFIER_POINTER (function));
-       }
-      else
-       {
-         /* Function name unknown (call through ptr); just give arg number.  */
-         const char *const argnofun = _("passing arg %d of pointer to function");
-         new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
-         sprintf (new_opname, argnofun, argnum);
-       }
-      opname = new_opname;
-    }
-  pedwarn (msgid, opname);
-}
 \f
 /* If VALUE is a compound expr all of whose expressions are constant, then
    return its value.  Otherwise, return error_mark_node.
 \f
 /* If VALUE is a compound expr all of whose expressions are constant, then
    return its value.  Otherwise, return error_mark_node.
@@ -3780,7 +3922,7 @@ store_init_value (tree decl, tree init)
   /* Store the expression if valid; else report error.  */
 
   if (warn_traditional && !in_system_header
   /* Store the expression if valid; else report error.  */
 
   if (warn_traditional && !in_system_header
-      && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && ! TREE_STATIC (decl))
+      && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
     warning ("traditional C rejects automatic aggregate initialization");
 
   DECL_INITIAL (decl) = value;
     warning ("traditional C rejects automatic aggregate initialization");
 
   DECL_INITIAL (decl) = value;
@@ -4095,18 +4237,32 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
   /* Build a VECTOR_CST from a *constant* vector constructor.  If the
      vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
      below and handle as a constructor.  */
   /* Build a VECTOR_CST from a *constant* vector constructor.  If the
      vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
      below and handle as a constructor.  */
-    if (code == VECTOR_TYPE
-       && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
-        && vector_types_convertible_p (TREE_TYPE (inside_init), type)
-        && TREE_CONSTANT (inside_init))
-      {
-       if (TREE_CODE (inside_init) == VECTOR_CST
-            && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-                         TYPE_MAIN_VARIANT (type)))
-         return inside_init;
-       else
-         return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
-      }
+  if (code == VECTOR_TYPE
+      && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
+      && vector_types_convertible_p (TREE_TYPE (inside_init), type)
+      && TREE_CONSTANT (inside_init))
+    {
+      if (TREE_CODE (inside_init) == VECTOR_CST
+         && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+                       TYPE_MAIN_VARIANT (type)))
+       return inside_init;
+
+      if (TREE_CODE (inside_init) == CONSTRUCTOR)
+       {
+         tree link;
+
+         /* Iterate through elements and check if all constructor
+            elements are *_CSTs.  */
+         for (link = CONSTRUCTOR_ELTS (inside_init);
+              link;
+              link = TREE_CHAIN (link))
+           if (! CONSTANT_CLASS_P (TREE_VALUE (link)))
+             break;
+
+         if (link == NULL)
+           return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
+       }
+    }
 
   /* Any type can be initialized
      from an expression of the same type, optionally with braces.  */
 
   /* Any type can be initialized
      from an expression of the same type, optionally with braces.  */
@@ -4200,13 +4356,13 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
         for arrays and functions.  We must not call it in the
         case where inside_init is a null pointer constant.  */
       inside_init
         for arrays and functions.  We must not call it in the
         case where inside_init is a null pointer constant.  */
       inside_init
-       = convert_for_assignment (type, init, _("initialization"),
+       = convert_for_assignment (type, init, ic_init,
                                  NULL_TREE, NULL_TREE, 0);
 
       /* Check to see if we have already given an error message.  */
       if (inside_init == error_mark_node)
        ;
                                  NULL_TREE, NULL_TREE, 0);
 
       /* Check to see if we have already given an error message.  */
       if (inside_init == error_mark_node)
        ;
-      else if (require_constant && ! TREE_CONSTANT (inside_init))
+      else if (require_constant && !TREE_CONSTANT (inside_init))
        {
          error_init ("initializer element is not constant");
          inside_init = error_mark_node;
        {
          error_init ("initializer element is not constant");
          inside_init = error_mark_node;
@@ -4302,17 +4458,11 @@ static struct init_node *constructor_pending_elts;
 /* The SPELLING_DEPTH of this constructor.  */
 static int constructor_depth;
 
 /* The SPELLING_DEPTH of this constructor.  */
 static int constructor_depth;
 
-/* 0 if implicitly pushing constructor levels is allowed.  */
-int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages.  */
-
 /* DECL node for which an initializer is being read.
    0 means we are reading a constructor expression
    such as (struct foo) {...}.  */
 static tree constructor_decl;
 
 /* DECL node for which an initializer is being read.
    0 means we are reading a constructor expression
    such as (struct foo) {...}.  */
 static tree constructor_decl;
 
-/* start_init saves the ASMSPEC arg here for really_start_incremental_init.  */
-static const char *constructor_asmspec;
-
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
 
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
 
@@ -4359,7 +4509,7 @@ struct constructor_stack
   char designated;
 };
 
   char designated;
 };
 
-struct constructor_stack *constructor_stack;
+static struct constructor_stack *constructor_stack;
 
 /* This stack represents designators from some range designator up to
    the last designator in the list.  */
 
 /* This stack represents designators from some range designator up to
    the last designator in the list.  */
@@ -4374,7 +4524,7 @@ struct constructor_range_stack
   tree fields;
 };
 
   tree fields;
 };
 
-struct constructor_range_stack *constructor_range_stack;
+static struct constructor_range_stack *constructor_range_stack;
 
 /* This stack records separate initializers that are nested.
    Nested initializers can't happen in ANSI C, but GNU C allows them
 
 /* This stack records separate initializers that are nested.
    Nested initializers can't happen in ANSI C, but GNU C allows them
@@ -4384,7 +4534,6 @@ struct initializer_stack
 {
   struct initializer_stack *next;
   tree decl;
 {
   struct initializer_stack *next;
   tree decl;
-  const char *asmspec;
   struct constructor_stack *constructor_stack;
   struct constructor_range_stack *constructor_range_stack;
   tree elements;
   struct constructor_stack *constructor_stack;
   struct constructor_range_stack *constructor_range_stack;
   tree elements;
@@ -4396,22 +4545,17 @@ struct initializer_stack
   char require_constant_elements;
 };
 
   char require_constant_elements;
 };
 
-struct initializer_stack *initializer_stack;
+static struct initializer_stack *initializer_stack;
 \f
 /* Prepare to parse and output the initializer for variable DECL.  */
 
 void
 \f
 /* Prepare to parse and output the initializer for variable DECL.  */
 
 void
-start_init (tree decl, tree asmspec_tree, int top_level)
+start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
 {
   const char *locus;
 {
   const char *locus;
-  struct initializer_stack *p = XNEW (struct initializer_stack);
-  const char *asmspec = 0;
-
-  if (asmspec_tree)
-    asmspec = TREE_STRING_POINTER (asmspec_tree);
+  struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
 
   p->decl = constructor_decl;
 
   p->decl = constructor_decl;
-  p->asmspec = constructor_asmspec;
   p->require_constant_value = require_constant_value;
   p->require_constant_elements = require_constant_elements;
   p->constructor_stack = constructor_stack;
   p->require_constant_value = require_constant_value;
   p->require_constant_elements = require_constant_elements;
   p->constructor_stack = constructor_stack;
@@ -4425,11 +4569,10 @@ start_init (tree decl, tree asmspec_tree, int top_level)
   initializer_stack = p;
 
   constructor_decl = decl;
   initializer_stack = p;
 
   constructor_decl = decl;
-  constructor_asmspec = asmspec;
   constructor_designated = 0;
   constructor_top_level = top_level;
 
   constructor_designated = 0;
   constructor_top_level = top_level;
 
-  if (decl != 0)
+  if (decl != 0 && decl != error_mark_node)
     {
       require_constant_value = TREE_STATIC (decl);
       require_constant_elements
     {
       require_constant_value = TREE_STATIC (decl);
       require_constant_elements
@@ -4481,7 +4624,6 @@ finish_init (void)
   free (spelling_base);
 
   constructor_decl = p->decl;
   free (spelling_base);
 
   constructor_decl = p->decl;
-  constructor_asmspec = p->asmspec;
   require_constant_value = p->require_constant_value;
   require_constant_elements = p->require_constant_elements;
   constructor_stack = p->constructor_stack;
   require_constant_value = p->require_constant_value;
   require_constant_elements = p->require_constant_elements;
   constructor_stack = p->constructor_stack;
@@ -4583,7 +4725,10 @@ really_start_incremental_init (tree type)
                       TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
        }
       else
                       TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
        }
       else
-       constructor_index = bitsize_zero_node;
+       {
+         constructor_index = bitsize_zero_node;
+         constructor_max_index = NULL_TREE;
+       }
 
       constructor_unfilled_index = constructor_index;
     }
 
       constructor_unfilled_index = constructor_index;
     }
@@ -4787,7 +4932,8 @@ push_init_level (int implicit)
     }
   else
     {
     }
   else
     {
-      warning_init ("braces around scalar initializer");
+      if (constructor_type != error_mark_node)
+       warning_init ("braces around scalar initializer");
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
@@ -4833,7 +4979,7 @@ pop_init_level (int implicit)
   if (constructor_type && constructor_fields
       && TREE_CODE (constructor_type) == ARRAY_TYPE
       && TYPE_DOMAIN (constructor_type)
   if (constructor_type && constructor_fields
       && TREE_CODE (constructor_type) == ARRAY_TYPE
       && TYPE_DOMAIN (constructor_type)
-      && ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
+      && !TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
     {
       /* Silently discard empty initializations.  The parser will
         already have pedwarned for empty brackets.  */
     {
       /* Silently discard empty initializations.  The parser will
         already have pedwarned for empty brackets.  */
@@ -4864,7 +5010,7 @@ pop_init_level (int implicit)
     {
        /* Do not warn for flexible array members or zero-length arrays.  */
        while (constructor_unfilled_fields
     {
        /* Do not warn for flexible array members or zero-length arrays.  */
        while (constructor_unfilled_fields
-              && (! DECL_SIZE (constructor_unfilled_fields)
+              && (!DECL_SIZE (constructor_unfilled_fields)
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
          constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
 
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
          constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
 
@@ -4986,12 +5132,6 @@ set_designator (int array)
       return 0;
     }
 
       return 0;
     }
 
-  if (constructor_no_implicit)
-    {
-      error_init ("initialization designators may not nest");
-      return 1;
-    }
-
   switch (TREE_CODE (constructor_type))
     {
     case  RECORD_TYPE:
   switch (TREE_CODE (constructor_type))
     {
     case  RECORD_TYPE:
@@ -5150,8 +5290,7 @@ set_init_label (tree fieldname)
     }
 
   if (tail == 0)
     }
 
   if (tail == 0)
-    error ("unknown field %qs specified in initializer",
-          IDENTIFIER_POINTER (fieldname));
+    error ("unknown field %qE specified in initializer", fieldname);
   else
     {
       constructor_fields = tail;
   else
     {
       constructor_fields = tail;
@@ -5567,7 +5706,7 @@ static void
 output_init_element (tree value, bool strict_string, tree type, tree field,
                     int pending)
 {
 output_init_element (tree value, bool strict_string, tree type, tree field,
                     int pending)
 {
-  if (type == error_mark_node)
+  if (type == error_mark_node || value == error_mark_node)
     {
       constructor_erroneous = 1;
       return;
     {
       constructor_erroneous = 1;
       return;
@@ -5839,7 +5978,7 @@ output_pending_init_elements (int all)
 
   /* Ordinarily return, but not if we want to output all
      and there are elements left.  */
 
   /* Ordinarily return, but not if we want to output all
      and there are elements left.  */
-  if (! (all && next != 0))
+  if (!(all && next != 0))
     return;
 
   /* If it's not incremental, just skip over the gap, so that after
     return;
 
   /* If it's not incremental, just skip over the gap, so that after
@@ -5962,7 +6101,7 @@ process_init_element (struct c_expr value)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value.value != 0 && !constructor_no_implicit
+         else if (value.value != 0
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
@@ -6050,7 +6189,7 @@ process_init_element (struct c_expr value)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value.value != 0 && !constructor_no_implicit
+         else if (value.value != 0
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
@@ -6090,7 +6229,7 @@ process_init_element (struct c_expr value)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value.value != 0 && !constructor_no_implicit
+         else if (value.value != 0
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
@@ -6155,7 +6294,8 @@ process_init_element (struct c_expr value)
 
       /* Handle the sole element allowed in a braced initializer
         for a scalar variable.  */
 
       /* Handle the sole element allowed in a braced initializer
         for a scalar variable.  */
-      else if (constructor_fields == 0)
+      else if (constructor_type != error_mark_node
+              && constructor_fields == 0)
        {
          pedwarn_init ("excess elements in scalar initializer");
          break;
        {
          pedwarn_init ("excess elements in scalar initializer");
          break;
@@ -6247,47 +6387,80 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
   tree args;
   int i;
   const char *constraint;
   tree args;
   int i;
   const char *constraint;
+  const char **oconstraints;
   bool allows_mem, allows_reg, is_inout;
   bool allows_mem, allows_reg, is_inout;
-  int ninputs;
-  int noutputs;
+  int ninputs, noutputs;
 
   ninputs = list_length (inputs);
   noutputs = list_length (outputs);
 
   ninputs = list_length (inputs);
   noutputs = list_length (outputs);
+  oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
+
+  string = resolve_asm_operand_names (string, outputs, inputs);
 
   /* Remove output conversions that change the type but not the mode.  */
   for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
     {
       tree output = TREE_VALUE (tail);
 
   /* Remove output conversions that change the type but not the mode.  */
   for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
     {
       tree output = TREE_VALUE (tail);
+
+      /* ??? Really, this should not be here.  Users should be using a
+        proper lvalue, dammit.  But there's a long history of using casts
+        in the output operands.  In cases like longlong.h, this becomes a
+        primitive form of typechecking -- if the cast can be removed, then
+        the output operand had a type of the proper width; otherwise we'll
+        get an error.  Gross, but ...  */
       STRIP_NOPS (output);
       STRIP_NOPS (output);
-      TREE_VALUE (tail) = output;
-      lvalue_or_else (output, "invalid lvalue in asm statement");
+
+      if (!lvalue_or_else (output, lv_asm))
+       output = error_mark_node;
 
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
 
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+      oconstraints[i] = constraint;
 
 
-      if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
-                                    &allows_mem, &allows_reg, &is_inout))
-        {
-          /* By marking this operand as erroneous, we will not try
-          to process this operand again in expand_asm_operands.  */
-          TREE_VALUE (tail) = error_mark_node;
-          continue;
-        }
+      if (parse_output_constraint (&constraint, i, ninputs, noutputs,
+                                  &allows_mem, &allows_reg, &is_inout))
+       {
+         /* If the operand is going to end up in memory,
+            mark it addressable.  */
+         if (!allows_reg && !c_mark_addressable (output))
+           output = error_mark_node;
+       }
+      else
+        output = error_mark_node;
 
 
-      /* If the operand is a DECL that is going to end up in
-        memory, assume it is addressable.  This is a bit more
-        conservative than it would ideally be; the exact test is
-        buried deep in expand_asm_operands and depends on the
-        DECL_RTL for the OPERAND -- which we don't have at this
-        point.  */
-      if (!allows_reg && DECL_P (output))
-        c_mark_addressable (output);
+      TREE_VALUE (tail) = output;
     }
 
   /* Perform default conversions on array and function inputs.
      Don't do this for other types as it would screw up operands
      expected to be in memory.  */
     }
 
   /* Perform default conversions on array and function inputs.
      Don't do this for other types as it would screw up operands
      expected to be in memory.  */
-  for (tail = inputs; tail; tail = TREE_CHAIN (tail))
-    TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail));
+  for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
+    {
+      tree input;
+
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+      input = TREE_VALUE (tail);
+
+      input = default_function_array_conversion (input);
+
+      if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
+                                 oconstraints, &allows_mem, &allows_reg))
+       {
+         /* If the operand is going to end up in memory,
+            mark it addressable.  */
+         if (!allows_reg && allows_mem)
+           {
+             /* Strip the nops as we allow this case.  FIXME, this really
+                should be rejected or made deprecated.  */
+             STRIP_NOPS (input);
+             if (!c_mark_addressable (input))
+               input = error_mark_node;
+         }
+       }
+      else
+       input = error_mark_node;
+
+      TREE_VALUE (tail) = input;
+    }
 
   args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers);
 
 
   args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers);
 
@@ -6297,6 +6470,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
       ASM_VOLATILE_P (args) = 1;
       ASM_INPUT_P (args) = 1;
     }
       ASM_VOLATILE_P (args) = 1;
       ASM_INPUT_P (args) = 1;
     }
+
   return args;
 }
 \f
   return args;
 }
 \f
@@ -6351,7 +6525,7 @@ c_finish_return (tree retval)
     }
   else
     {
     }
   else
     {
-      tree t = convert_for_assignment (valtype, retval, _("return"),
+      tree t = convert_for_assignment (valtype, retval, ic_return,
                                       NULL_TREE, NULL_TREE, 0);
       tree res = DECL_RESULT (current_function_decl);
       tree inner;
                                       NULL_TREE, NULL_TREE, 0);
       tree res = DECL_RESULT (current_function_decl);
       tree inner;
@@ -6380,7 +6554,7 @@ c_finish_return (tree retval)
              {
                tree op1 = TREE_OPERAND (inner, 1);
 
              {
                tree op1 = TREE_OPERAND (inner, 1);
 
-               while (! POINTER_TYPE_P (TREE_TYPE (op1))
+               while (!POINTER_TYPE_P (TREE_TYPE (op1))
                       && (TREE_CODE (op1) == NOP_EXPR
                           || TREE_CODE (op1) == NON_LVALUE_EXPR
                           || TREE_CODE (op1) == CONVERT_EXPR))
                       && (TREE_CODE (op1) == NOP_EXPR
                           || TREE_CODE (op1) == NON_LVALUE_EXPR
                           || TREE_CODE (op1) == CONVERT_EXPR))
@@ -6396,13 +6570,13 @@ c_finish_return (tree retval)
            case ADDR_EXPR:
              inner = TREE_OPERAND (inner, 0);
 
            case ADDR_EXPR:
              inner = TREE_OPERAND (inner, 0);
 
-             while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r'
+             while (REFERENCE_CLASS_P (inner)
                     && TREE_CODE (inner) != INDIRECT_REF)
                inner = TREE_OPERAND (inner, 0);
 
              if (DECL_P (inner)
                     && TREE_CODE (inner) != INDIRECT_REF)
                inner = TREE_OPERAND (inner, 0);
 
              if (DECL_P (inner)
-                 && ! DECL_EXTERNAL (inner)
-                 && ! TREE_STATIC (inner)
+                 && !DECL_EXTERNAL (inner)
+                 && !TREE_STATIC (inner)
                  && DECL_CONTEXT (inner) == current_function_decl)
                warning ("function returns address of local variable");
              break;
                  && DECL_CONTEXT (inner) == current_function_decl)
                warning ("function returns address of local variable");
              break;
@@ -6462,11 +6636,12 @@ c_start_case (tree exp)
       code = TREE_CODE (TREE_TYPE (exp));
       orig_type = TREE_TYPE (exp);
 
       code = TREE_CODE (TREE_TYPE (exp));
       orig_type = TREE_TYPE (exp);
 
-      if (! INTEGRAL_TYPE_P (orig_type)
+      if (!INTEGRAL_TYPE_P (orig_type)
          && code != ERROR_MARK)
        {
          error ("switch quantity not an integer");
          exp = integer_zero_node;
          && code != ERROR_MARK)
        {
          error ("switch quantity not an integer");
          exp = integer_zero_node;
+         orig_type = error_mark_node;
        }
       else
        {
        }
       else
        {
@@ -6485,8 +6660,7 @@ c_start_case (tree exp)
 
   /* Add this new SWITCH_STMT to the stack.  */
   cs = XNEW (struct c_switch);
 
   /* Add this new SWITCH_STMT to the stack.  */
   cs = XNEW (struct c_switch);
-  cs->switch_stmt = build_stmt ((enum tree_code) SWITCH_STMT, exp, NULL_TREE,
-                               orig_type);
+  cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type);
   cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
   cs->next = c_switch_stack;
   cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
   cs->next = c_switch_stack;
@@ -6505,7 +6679,7 @@ do_case (tree low_value, tree high_value)
   if (c_switch_stack)
     {
       label = c_add_case_label (c_switch_stack->cases,
   if (c_switch_stack)
     {
       label = c_add_case_label (c_switch_stack->cases,
-                               SWITCH_COND (c_switch_stack->switch_stmt),
+                               SWITCH_STMT_COND (c_switch_stack->switch_stmt),
                                c_switch_stack->orig_type,
                                low_value, high_value);
       if (label == error_mark_node)
                                c_switch_stack->orig_type,
                                low_value, high_value);
       if (label == error_mark_node)
@@ -6526,7 +6700,7 @@ c_finish_case (tree body)
 {
   struct c_switch *cs = c_switch_stack;
 
 {
   struct c_switch *cs = c_switch_stack;
 
-  SWITCH_BODY (cs->switch_stmt) = body;
+  SWITCH_STMT_BODY (cs->switch_stmt) = body;
 
   /* Emit warnings as needed.  */
   c_do_switch_warnings (cs->cases, cs->switch_stmt);
 
   /* Emit warnings as needed.  */
   c_do_switch_warnings (cs->cases, cs->switch_stmt);
@@ -6619,10 +6793,17 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
 {
   tree entry = NULL, exit = NULL, t;
 
 {
   tree entry = NULL, exit = NULL, t;
 
-  /* Detect do { ... } while (0) and don't generate loop construct.  */
-  if (cond && !cond_is_first && integer_zerop (cond))
-    cond = NULL;
-  if (cond_is_first || cond)
+  /* If the condition is zero don't generate a loop construct.  */
+  if (cond && integer_zerop (cond))
+    {
+      if (cond_is_first)
+       {
+         t = build_and_jump (&blab);
+         SET_EXPR_LOCATION (t, start_locus);
+         add_stmt (t);
+       }
+    }
+  else
     {
       tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
  
     {
       tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
  
@@ -6631,7 +6812,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
          then we just build a jump back to the top.  */
       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
  
          then we just build a jump back to the top.  */
       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
  
-      if (cond)
+      if (cond && !integer_nonzerop (cond))
         {
           /* Canonicalize the loop condition to the end.  This means
              generating a branch to the loop condition.  Reuse the
         {
           /* Canonicalize the loop condition to the end.  This means
              generating a branch to the loop condition.  Reuse the
@@ -6678,10 +6859,23 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
 tree
 c_finish_bc_stmt (tree *label_p, bool is_break)
 {
 tree
 c_finish_bc_stmt (tree *label_p, bool is_break)
 {
+  bool skip;
   tree label = *label_p;
 
   tree label = *label_p;
 
+  /* In switch statements break is sometimes stylistically used after
+     a return statement.  This can lead to spurious warnings about
+     control reaching the end of a non-void function when it is
+     inlined.  Note that we are calling block_may_fallthru with
+     language specific tree nodes; this works because
+     block_may_fallthru returns true when given something it does not
+     understand.  */
+  skip = !block_may_fallthru (cur_stmt_list);
+
   if (!label)
   if (!label)
-    *label_p = label = create_artificial_label ();
+    {
+      if (!skip)
+       *label_p = label = create_artificial_label ();
+    }
   else if (TREE_CODE (label) != LABEL_DECL)
     {
       if (is_break)
   else if (TREE_CODE (label) != LABEL_DECL)
     {
       if (is_break)
@@ -6691,6 +6885,9 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
       return NULL_TREE;
     }
 
       return NULL_TREE;
     }
 
+  if (skip)
+    return NULL_TREE;
+
   return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
 }
 
   return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
 }
 
@@ -6744,7 +6941,7 @@ c_process_expr_stmt (tree expr)
 
   /* If the expression is not of a type to which we cannot assign a line
      number, wrap the thing in a no-op NOP_EXPR.  */
 
   /* If the expression is not of a type to which we cannot assign a line
      number, wrap the thing in a no-op NOP_EXPR.  */
-  if (DECL_P (expr) || TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
+  if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
     expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
 
   if (EXPR_P (expr))
     expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
 
   if (EXPR_P (expr))
@@ -7078,7 +7275,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
               dividing by something we know != -1.  */
            shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
                       || (TREE_CODE (op1) == INTEGER_CST
               dividing by something we know != -1.  */
            shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
                       || (TREE_CODE (op1) == INTEGER_CST
-                          && ! integer_all_onesp (op1)));
+                          && !integer_all_onesp (op1)));
          common = 1;
        }
       break;
          common = 1;
        }
       break;
@@ -7105,7 +7302,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             only if unsigned or if dividing by something we know != -1.  */
          shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
                     || (TREE_CODE (op1) == INTEGER_CST
             only if unsigned or if dividing by something we know != -1.  */
          shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
                     || (TREE_CODE (op1) == INTEGER_CST
-                        && ! integer_all_onesp (op1)));
+                        && !integer_all_onesp (op1)));
          common = 1;
        }
       break;
          common = 1;
        }
       break;
@@ -7143,7 +7340,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                warning ("right shift count is negative");
              else
                {
                warning ("right shift count is negative");
              else
                {
-                 if (! integer_zerop (op1))
+                 if (!integer_zerop (op1))
                    short_shift = 1;
 
                  if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                    short_shift = 1;
 
                  if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
@@ -7185,29 +7382,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        }
       break;
 
        }
       break;
 
-    case RROTATE_EXPR:
-    case LROTATE_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
-       {
-         if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
-           {
-             if (tree_int_cst_sgn (op1) < 0)
-               warning ("shift count is negative");
-             else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
-               warning ("shift count >= width of type");
-           }
-
-         /* Use the type of the value to be shifted.  */
-         result_type = type0;
-         /* Convert the shift-count to an integer, regardless of size
-            of value being shifted.  */
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-           op1 = convert (integer_type_node, op1);
-         /* Avoid converting op1 to result_type later.  */
-         converted = 1;
-       }
-      break;
-
     case EQ_EXPR:
     case NE_EXPR:
       if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE))
     case EQ_EXPR:
     case NE_EXPR:
       if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE))
@@ -7269,28 +7443,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        }
       break;
 
        }
       break;
 
-    case MAX_EXPR:
-    case MIN_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
-       shorten = 1;
-      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
-       {
-         if (comp_target_types (type0, type1, 1))
-           {
-             result_type = common_pointer_type (type0, type1);
-             if (pedantic
-                 && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-               pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
-           }
-         else
-           {
-             result_type = ptr_type_node;
-             pedwarn ("comparison of distinct pointer types lacks a cast");
-           }
-       }
-      break;
-
     case LE_EXPR:
     case GE_EXPR:
     case LT_EXPR:
     case LE_EXPR:
     case GE_EXPR:
     case LT_EXPR:
@@ -7343,25 +7495,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        }
       break;
 
        }
       break;
 
-    case UNORDERED_EXPR:
-    case ORDERED_EXPR:
-    case UNLT_EXPR:
-    case UNLE_EXPR:
-    case UNGT_EXPR:
-    case UNGE_EXPR:
-    case UNEQ_EXPR:
-    case LTGT_EXPR:
-      build_type = integer_type_node;
-      if (code0 != REAL_TYPE || code1 != REAL_TYPE)
-       {
-         error ("unordered comparison on non-floating point argument");
-         return error_mark_node;
-       }
-      common = 1;
-      break;
-
     default:
     default:
-      break;
+      gcc_unreachable ();
     }
 
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
     }
 
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
@@ -7376,7 +7511,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
       if (shorten || common || short_compare)
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
       if (shorten || common || short_compare)
-       result_type = common_type (type0, type1);
+       result_type = c_common_type (type0, type1);
 
       /* For certain operations (which identify themselves by shorten != 0)
         if both args were extended from the same smaller type,
 
       /* For certain operations (which identify themselves by shorten != 0)
         if both args were extended from the same smaller type,
@@ -7434,7 +7569,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
              && (unsigned0 || !uns))
            result_type
              = c_common_signed_or_unsigned_type
              && (unsigned0 || !uns))
            result_type
              = c_common_signed_or_unsigned_type
-             (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+             (unsigned0, c_common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
          else if (TREE_CODE (arg0) == INTEGER_CST
                   && (unsigned1 || !uns)
                   && (TYPE_PRECISION (TREE_TYPE (arg1))
          else if (TREE_CODE (arg0) == INTEGER_CST
                   && (unsigned1 || !uns)
                   && (TYPE_PRECISION (TREE_TYPE (arg1))
@@ -7508,8 +7643,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
          if (warn_sign_compare && skip_evaluation == 0)
            {
 
          if (warn_sign_compare && skip_evaluation == 0)
            {
-             int op0_signed = ! TYPE_UNSIGNED (TREE_TYPE (orig_op0));
-             int op1_signed = ! TYPE_UNSIGNED (TREE_TYPE (orig_op1));
+             int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
+             int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
              int unsignedp0, unsignedp1;
              tree primop0 = get_narrower (op0, &unsignedp0);
              tree primop1 = get_narrower (op1, &unsignedp1);
              int unsignedp0, unsignedp1;
              tree primop0 = get_narrower (op0, &unsignedp0);
              tree primop1 = get_narrower (op1, &unsignedp1);
@@ -7528,7 +7663,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 Do not warn if the comparison is being done in a signed type,
                 since the signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
                 Do not warn if the comparison is being done in a signed type,
                 since the signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
-             if (! TYPE_UNSIGNED (result_type))
+             if (!TYPE_UNSIGNED (result_type))
                /* OK */;
               /* Do not warn if both operands are the same signedness.  */
               else if (op0_signed == op1_signed)
                /* OK */;
               /* Do not warn if both operands are the same signedness.  */
               else if (op0_signed == op1_signed)
@@ -7563,7 +7698,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                  else if (TREE_CODE (uop) == INTEGER_CST
                           && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
                           && int_fits_type_p
                  else if (TREE_CODE (uop) == INTEGER_CST
                           && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
                           && int_fits_type_p
-                          (TYPE_MAX_VALUE (TREE_TYPE(uop)),
+                          (TYPE_MAX_VALUE (TREE_TYPE (uop)),
                            c_common_signed_type (result_type)))
                    /* OK */;
                  else
                            c_common_signed_type (result_type)))
                    /* OK */;
                  else
@@ -7611,7 +7746,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                      if (bits < TYPE_PRECISION (result_type)
                          && bits < HOST_BITS_PER_WIDE_INT && unsignedp)
                        {
                      if (bits < TYPE_PRECISION (result_type)
                          && bits < HOST_BITS_PER_WIDE_INT && unsignedp)
                        {
-                         mask = (~ (HOST_WIDE_INT) 0) << bits;
+                         mask = (~(HOST_WIDE_INT) 0) << bits;
                          if ((mask & constant) != mask)
                            warning ("comparison of promoted ~unsigned with constant");
                        }
                          if ((mask & constant) != mask)
                            warning ("comparison of promoted ~unsigned with constant");
                        }
@@ -7639,7 +7774,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
-  if (! converted)
+  if (!converted)
     {
       if (TREE_TYPE (op0) != result_type)
        op0 = convert (result_type, op0);
     {
       if (TREE_TYPE (op0) != result_type)
        op0 = convert (result_type, op0);