OSDN Git Service

Add Go frontend, libgo library, and Go testsuite.
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 2296cbe..77a3864 100644 (file)
@@ -29,22 +29,17 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "rtl.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
 #include "c-lang.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
 #include "c-lang.h"
-#include "tm_p.h"
 #include "flags.h"
 #include "output.h"
 #include "flags.h"
 #include "output.h"
-#include "expr.h"
-#include "toplev.h"
 #include "intl.h"
 #include "intl.h"
-#include "ggc.h"
 #include "target.h"
 #include "tree-iterator.h"
 #include "target.h"
 #include "tree-iterator.h"
+#include "bitmap.h"
 #include "gimple.h"
 #include "gimple.h"
-#include "tree-flow.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -55,13 +50,6 @@ enum impl_conv {
   ic_return
 };
 
   ic_return
 };
 
-/* Whether we are building a boolean conversion inside
-   convert_for_assignment, or some other late binary operation.  If
-   build_binary_op is called (from code shared with C++) in this case,
-   then the operands have already been folded and the result will not
-   be folded again, so C_MAYBE_CONST_EXPR should not be generated.  */
-bool in_late_binary_op;
-
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
 
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
 
@@ -80,10 +68,12 @@ static int require_constant_elements;
 
 static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
 
 static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *);
+static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
+                                        bool *);
 static int comp_target_types (location_t, tree, tree);
 static int comp_target_types (location_t, tree, tree);
-static int function_types_compatible_p (const_tree, const_tree, bool *);
-static int type_lists_compatible_p (const_tree, const_tree, bool *);
+static int function_types_compatible_p (const_tree, const_tree, bool *,
+                                       bool *);
+static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
@@ -97,19 +87,20 @@ static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (int, const char *);
 static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
 static char *print_spelling (char *);
 static void warning_init (int, const char *);
 static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
-static void output_init_element (tree, tree, bool, tree, tree, int, bool);
-static void output_pending_init_elements (int);
-static int set_designator (int);
-static void push_range_stack (tree);
-static void add_pending_init (tree, tree, tree, bool);
-static void set_nonincremental_init (void);
-static void set_nonincremental_init_from_string (tree);
-static tree find_init_member (tree);
+static void output_init_element (tree, tree, bool, tree, tree, int, bool,
+                                struct obstack *);
+static void output_pending_init_elements (int, struct obstack *);
+static int set_designator (int, struct obstack *);
+static void push_range_stack (tree, struct obstack *);
+static void add_pending_init (tree, tree, tree, bool, struct obstack *);
+static void set_nonincremental_init (struct obstack *);
+static void set_nonincremental_init_from_string (tree, struct obstack *);
+static tree find_init_member (tree, struct obstack *);
 static void readonly_error (tree, enum lvalue_use);
 static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
 static void readonly_error (tree, enum lvalue_use);
 static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree, bool *);
+static int comptypes_internal (const_tree, const_tree, bool *, bool *);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -556,7 +547,7 @@ composite_type (tree t1, tree t2)
                    && TREE_CODE (mv2) != ARRAY_TYPE)
                  mv2 = TYPE_MAIN_VARIANT (mv2);
                for (memb = TYPE_FIELDS (TREE_VALUE (p1));
                    && TREE_CODE (mv2) != ARRAY_TYPE)
                  mv2 = TYPE_MAIN_VARIANT (mv2);
                for (memb = TYPE_FIELDS (TREE_VALUE (p1));
-                    memb; memb = TREE_CHAIN (memb))
+                    memb; memb = DECL_CHAIN (memb))
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
@@ -581,7 +572,7 @@ composite_type (tree t1, tree t2)
                    && TREE_CODE (mv1) != ARRAY_TYPE)
                  mv1 = TYPE_MAIN_VARIANT (mv1);
                for (memb = TYPE_FIELDS (TREE_VALUE (p2));
                    && TREE_CODE (mv1) != ARRAY_TYPE)
                  mv1 = TYPE_MAIN_VARIANT (mv1);
                for (memb = TYPE_FIELDS (TREE_VALUE (p2));
-                    memb; memb = TREE_CHAIN (memb))
+                    memb; memb = DECL_CHAIN (memb))
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
@@ -975,7 +966,7 @@ comptypes (tree type1, tree type2)
   const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
   int val;
 
   const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
   int val;
 
-  val = comptypes_internal (type1, type2, NULL);
+  val = comptypes_internal (type1, type2, NULL, NULL);
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
@@ -990,7 +981,23 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
   const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
   int val;
 
   const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
   int val;
 
-  val = comptypes_internal (type1, type2, enum_and_int_p);
+  val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+  return val;
+}
+
+/* Like comptypes, but if it returns nonzero for different types, it
+   sets *DIFFERENT_TYPES_P to true.  */
+
+int
+comptypes_check_different_types (tree type1, tree type2,
+                                bool *different_types_p)
+{
+  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+  int val;
+
+  val = comptypes_internal (type1, type2, NULL, different_types_p);
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
@@ -1001,11 +1008,17 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
    but a warning may be needed if you use them together.  If
    ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
    compatible integer type, then this sets *ENUM_AND_INT_P to true;
    but a warning may be needed if you use them together.  If
    ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
    compatible integer type, then this sets *ENUM_AND_INT_P to true;
-   *ENUM_AND_INT_P is never set to false.  This differs from
-   comptypes, in that we don't free the seen types.  */
+   *ENUM_AND_INT_P is never set to false.  If DIFFERENT_TYPES_P is not
+   NULL, and the types are compatible but different enough not to be
+   permitted in C1X typedef redeclarations, then this sets
+   *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
+   false, but may or may not be set if the types are incompatible.
+   This differs from comptypes, in that we don't free the seen
+   types.  */
 
 static int
 
 static int
-comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
+comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
+                   bool *different_types_p)
 {
   const_tree t1 = type1;
   const_tree t2 = type2;
 {
   const_tree t1 = type1;
   const_tree t2 = type2;
@@ -1017,17 +1030,6 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
       || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
     return 1;
 
       || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
     return 1;
 
-  /* If either type is the internal version of sizetype, return the
-     language version.  */
-  if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
-      && TYPE_ORIG_SIZE_TYPE (t1))
-    t1 = TYPE_ORIG_SIZE_TYPE (t1);
-
-  if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
-      && TYPE_ORIG_SIZE_TYPE (t2))
-    t2 = TYPE_ORIG_SIZE_TYPE (t2);
-
-
   /* Enumerated types are compatible with integer types, but this is
      not transitive: two enumerated types in the same translation unit
      are compatible with each other only if they are the same type.  */
   /* Enumerated types are compatible with integer types, but this is
      not transitive: two enumerated types in the same translation unit
      are compatible with each other only if they are the same type.  */
@@ -1035,14 +1037,24 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
   if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
     {
       t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
   if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
     {
       t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
-      if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE)
-       *enum_and_int_p = true;
+      if (TREE_CODE (t2) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_p = true;
+       }
     }
   else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
     {
       t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
     }
   else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
     {
       t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
-      if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE)
-       *enum_and_int_p = true;
+      if (TREE_CODE (t1) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_p = true;
+       }
     }
 
   if (t1 == t2)
     }
 
   if (t1 == t2)
@@ -1082,11 +1094,12 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
             ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
             ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                      enum_and_int_p));
+                                      enum_and_int_p, different_types_p));
       break;
 
     case FUNCTION_TYPE:
       break;
 
     case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2, enum_and_int_p);
+      val = function_types_compatible_p (t1, t2, enum_and_int_p,
+                                        different_types_p);
       break;
 
     case ARRAY_TYPE:
       break;
 
     case ARRAY_TYPE:
@@ -1100,9 +1113,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
            && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
            && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                              enum_and_int_p)))
+                                              enum_and_int_p,
+                                              different_types_p)))
          return 0;
 
          return 0;
 
+       if (different_types_p != NULL
+           && (d1 == 0) != (d2 == 0))
+         *different_types_p = true;
        /* Sizes must match unless one is missing or variable.  */
        if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
        /* Sizes must match unless one is missing or variable.  */
        if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
@@ -1119,6 +1136,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
        d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
        d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
 
        d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
        d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
 
+       if (different_types_p != NULL
+           && d1_variable != d2_variable)
+         *different_types_p = true;
        if (d1_variable || d2_variable)
          break;
        if (d1_zero && d2_zero)
        if (d1_variable || d2_variable)
          break;
        if (d1_zero && d2_zero)
@@ -1144,15 +1164,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
            break;
 
          if (attrval != 2)
            break;
 
          if (attrval != 2)
-           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
-         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
+           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                                different_types_p);
+         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                             different_types_p);
        }
       break;
 
     case VECTOR_TYPE:
       val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
             && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
        }
       break;
 
     case VECTOR_TYPE:
       val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
             && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                   enum_and_int_p));
+                                   enum_and_int_p, different_types_p));
       break;
 
     default:
       break;
 
     default:
@@ -1284,11 +1306,12 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
    compatible.  If the two types are not the same (which has been
    checked earlier), this can only happen when multiple translation
    units are being compiled.  See C99 6.2.7 paragraph 1 for the exact
    compatible.  If the two types are not the same (which has been
    checked earlier), this can only happen when multiple translation
    units are being compiled.  See C99 6.2.7 paragraph 1 for the exact
-   rules.  ENUM_AND_INT_P is as in comptypes_internal.  */
+   rules.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
 
 static int
 tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
 
 static int
 tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
-                             bool *enum_and_int_p)
+                             bool *enum_and_int_p, bool *different_types_p)
 {
   tree s1, s2;
   bool needs_warning = false;
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1392,14 +1415,14 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
 
        /*  Speed up the common case where the fields are in the same order. */
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
 
        /*  Speed up the common case where the fields are in the same order. */
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
-            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
          {
            int result;
 
            if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
          {
            int result;
 
            if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p);
+                                        enum_and_int_p, different_types_p);
 
            if (result != 1 && !DECL_NAME (s1))
              break;
 
            if (result != 1 && !DECL_NAME (s1))
              break;
@@ -1425,17 +1448,18 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
            return tu->val;
          }
 
            return tu->val;
          }
 
-       for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
+       for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1))
          {
            bool ok = false;
 
          {
            bool ok = false;
 
-           for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
+           for (s2 = TYPE_FIELDS (t2); s2; s2 = DECL_CHAIN (s2))
              if (DECL_NAME (s1) == DECL_NAME (s2))
                {
                  int result;
 
                  result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
              if (DECL_NAME (s1) == DECL_NAME (s2))
                {
                  int result;
 
                  result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                              enum_and_int_p);
+                                              enum_and_int_p,
+                                              different_types_p);
 
                  if (result != 1 && !DECL_NAME (s1))
                    continue;
 
                  if (result != 1 && !DECL_NAME (s1))
                    continue;
@@ -1471,14 +1495,14 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
-            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
          {
            int result;
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
          {
            int result;
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p);
+                                        enum_and_int_p, different_types_p);
            if (result == 0)
              break;
            if (result == 2)
            if (result == 0)
              break;
            if (result == 2)
@@ -1507,11 +1531,11 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
    Otherwise, if one type specifies only the number of arguments,
    the other must specify that number of self-promoting arg types.
    Otherwise, the argument types must match.
    Otherwise, if one type specifies only the number of arguments,
    the other must specify that number of self-promoting arg types.
    Otherwise, the argument types must match.
-   ENUM_AND_INT_P is as in comptypes_internal.  */
+   ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal.  */
 
 static int
 function_types_compatible_p (const_tree f1, const_tree f2,
 
 static int
 function_types_compatible_p (const_tree f1, const_tree f2,
-                            bool *enum_and_int_p)
+                            bool *enum_and_int_p, bool *different_types_p)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1532,13 +1556,17 @@ function_types_compatible_p (const_tree f1, const_tree f2,
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes_internal (ret1, ret2, enum_and_int_p);
+  val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
   if (val == 0)
     return 0;
 
   args1 = TYPE_ARG_TYPES (f1);
   args2 = TYPE_ARG_TYPES (f2);
 
   if (val == 0)
     return 0;
 
   args1 = TYPE_ARG_TYPES (f1);
   args2 = TYPE_ARG_TYPES (f2);
 
+  if (different_types_p != NULL
+      && (args1 == 0) != (args2 == 0))
+    *different_types_p = true;
+
   /* An unspecified parmlist matches any specified parmlist
      whose argument types don't need default promotions.  */
 
   /* An unspecified parmlist matches any specified parmlist
      whose argument types don't need default promotions.  */
 
@@ -1551,7 +1579,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
         If they don't match, ask for a warning (but no error).  */
       if (TYPE_ACTUAL_ARG_TYPES (f1)
          && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
         If they don't match, ask for a warning (but no error).  */
       if (TYPE_ACTUAL_ARG_TYPES (f1)
          && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
-                                          enum_and_int_p))
+                                          enum_and_int_p, different_types_p))
        val = 2;
       return val;
     }
        val = 2;
       return val;
     }
@@ -1561,23 +1589,25 @@ function_types_compatible_p (const_tree f1, const_tree f2,
        return 0;
       if (TYPE_ACTUAL_ARG_TYPES (f2)
          && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
        return 0;
       if (TYPE_ACTUAL_ARG_TYPES (f2)
          && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
-                                          enum_and_int_p))
+                                          enum_and_int_p, different_types_p))
        val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
        val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p);
+  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
+                                 different_types_p);
   return val1 != 1 ? val1 : val;
 }
 
 /* Check two lists of types for compatibility, returning 0 for
    incompatible, 1 for compatible, or 2 for compatible with
   return val1 != 1 ? val1 : val;
 }
 
 /* Check two lists of types for compatibility, returning 0 for
    incompatible, 1 for compatible, or 2 for compatible with
-   warning.  ENUM_AND_INT_P is as in comptypes_internal.  */
+   warning.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
 
 static int
 type_lists_compatible_p (const_tree args1, const_tree args2,
 
 static int
 type_lists_compatible_p (const_tree args1, const_tree args2,
-                        bool *enum_and_int_p)
+                        bool *enum_and_int_p, bool *different_types_p)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1602,6 +1632,9 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
         means there is supposed to be an argument
         but nothing is specified about what type it has.
         So match anything that self-promotes.  */
         means there is supposed to be an argument
         but nothing is specified about what type it has.
         So match anything that self-promotes.  */
+      if (different_types_p != NULL
+         && (a1 == 0) != (a2 == 0))
+       *different_types_p = true;
       if (a1 == 0)
        {
          if (c_type_promotes_to (a2) != a2)
       if (a1 == 0)
        {
          if (c_type_promotes_to (a2) != a2)
@@ -1616,8 +1649,11 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
       else if (TREE_CODE (a1) == ERROR_MARK
               || TREE_CODE (a2) == ERROR_MARK)
        ;
       else if (TREE_CODE (a1) == ERROR_MARK
               || TREE_CODE (a2) == ERROR_MARK)
        ;
-      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p)))
+      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
+                                             different_types_p)))
        {
        {
+         if (different_types_p != NULL)
+           *different_types_p = true;
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
          if (TREE_CODE (a1) == UNION_TYPE
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
          if (TREE_CODE (a1) == UNION_TYPE
@@ -1629,13 +1665,14 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
            {
              tree memb;
              for (memb = TYPE_FIELDS (a1);
            {
              tree memb;
              for (memb = TYPE_FIELDS (a1);
-                  memb; memb = TREE_CHAIN (memb))
+                  memb; memb = DECL_CHAIN (memb))
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv2, enum_and_int_p))
+                 if (comptypes_internal (mv3, mv2, enum_and_int_p,
+                                         different_types_p))
                    break;
                }
              if (memb == 0)
                    break;
                }
              if (memb == 0)
@@ -1650,13 +1687,14 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
            {
              tree memb;
              for (memb = TYPE_FIELDS (a2);
            {
              tree memb;
              for (memb = TYPE_FIELDS (a2);
-                  memb; memb = TREE_CHAIN (memb))
+                  memb; memb = DECL_CHAIN (memb))
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv1, enum_and_int_p))
+                 if (comptypes_internal (mv3, mv1, enum_and_int_p,
+                                         different_types_p))
                    break;
                }
              if (memb == 0)
                    break;
                }
              if (memb == 0)
@@ -1785,6 +1823,7 @@ mark_exp_read (tree exp)
       mark_exp_read (TREE_OPERAND (exp, 0));
       break;
     case COMPOUND_EXPR:
       mark_exp_read (TREE_OPERAND (exp, 0));
       break;
     case COMPOUND_EXPR:
+    case C_MAYBE_CONST_EXPR:
       mark_exp_read (TREE_OPERAND (exp, 1));
       break;
     default:
       mark_exp_read (TREE_OPERAND (exp, 1));
       break;
     default:
@@ -1952,7 +1991,7 @@ default_conversion (tree exp)
   return exp;
 }
 \f
   return exp;
 }
 \f
-/* Look up COMPONENT in a structure or union DECL.
+/* Look up COMPONENT in a structure or union TYPE.
 
    If the component name is not found, returns NULL_TREE.  Otherwise,
    the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
 
    If the component name is not found, returns NULL_TREE.  Otherwise,
    the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
@@ -1962,9 +2001,8 @@ default_conversion (tree exp)
    unions, the list steps down the chain to the component.  */
 
 static tree
    unions, the list steps down the chain to the component.  */
 
 static tree
-lookup_field (tree decl, tree component)
+lookup_field (tree type, tree component)
 {
 {
-  tree type = TREE_TYPE (decl);
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@@ -1994,10 +2032,21 @@ lookup_field (tree decl, tree component)
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
                    {
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
                    {
-                     tree anon = lookup_field (field, component);
+                     tree anon = lookup_field (TREE_TYPE (field), component);
 
                      if (anon)
                        return tree_cons (NULL_TREE, field, anon);
 
                      if (anon)
                        return tree_cons (NULL_TREE, field, anon);
+
+                     /* The Plan 9 compiler permits referring
+                        directly to an anonymous struct/union field
+                        using a typedef name.  */
+                     if (flag_plan9_extensions
+                         && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                         && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
+                             == TYPE_DECL)
+                         && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                             == component))
+                       break;
                    }
                }
 
                    }
                }
 
@@ -2024,16 +2073,26 @@ lookup_field (tree decl, tree component)
     }
   else
     {
     }
   else
     {
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        {
          if (DECL_NAME (field) == NULL_TREE
              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
            {
        {
          if (DECL_NAME (field) == NULL_TREE
              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
            {
-             tree anon = lookup_field (field, component);
+             tree anon = lookup_field (TREE_TYPE (field), component);
 
              if (anon)
                return tree_cons (NULL_TREE, field, anon);
 
              if (anon)
                return tree_cons (NULL_TREE, field, anon);
+
+             /* The Plan 9 compiler permits referring directly to an
+                anonymous struct/union field using a typedef
+                name.  */
+             if (flag_plan9_extensions
+                 && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                 && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
+                 && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                     == component))
+               break;
            }
 
          if (DECL_NAME (field) == component)
            }
 
          if (DECL_NAME (field) == component)
@@ -2063,6 +2122,11 @@ build_component_ref (location_t loc, tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
+  /* Detect Objective-C property syntax object.property.  */
+  if (c_dialect_objc ()
+      && (ref = objc_maybe_build_component_ref (datum, component)))
+    return ref;
+
   /* 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)
@@ -2073,7 +2137,7 @@ build_component_ref (location_t loc, tree datum, tree component)
          return error_mark_node;
        }
 
          return error_mark_node;
        }
 
-      field = lookup_field (datum, component);
+      field = lookup_field (type, component);
 
       if (!field)
        {
 
       if (!field)
        {
@@ -2234,6 +2298,9 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
    arrays that are not lvalues (for example, members of structures returned
    by functions).
 
    arrays that are not lvalues (for example, members of structures returned
    by functions).
 
+   For vector types, allow vector[i] but not i[vector], and create
+   *(((type*)&vectortype) + i) for the expression.
+
    LOC is the location to use for the returned expression.  */
 
 tree
    LOC is the location to use for the returned expression.  */
 
 tree
@@ -2246,13 +2313,17 @@ build_array_ref (location_t loc, tree array, tree index)
     return error_mark_node;
 
   if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
     return error_mark_node;
 
   if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
-      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
+      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
+      /* Allow vector[index] but not index[vector].  */
+      && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE)
     {
       tree temp;
       if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
     {
       tree temp;
       if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
-         error_at (loc, "subscripted value is neither array nor pointer");
+          error_at (loc, 
+            "subscripted value is neither array nor pointer nor vector");
+
          return error_mark_node;
        }
       temp = array;
          return error_mark_node;
        }
       temp = array;
@@ -2282,6 +2353,27 @@ build_array_ref (location_t loc, tree array, tree index)
   index = default_conversion (index);
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
   index = default_conversion (index);
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
+  
+  /* For vector[index], convert the vector to a 
+     pointer of the underlying type.  */
+  if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE)
+    {
+      tree type = TREE_TYPE (array);
+      tree type1;
+
+      if (TREE_CODE (index) == INTEGER_CST)
+        if (!host_integerp (index, 1) 
+            || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1) 
+               >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array))))
+          warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
+     
+      c_common_mark_addressable_vec (array);
+      type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
+      type = build_pointer_type (type);
+      type1 = build_pointer_type (TREE_TYPE (array));
+      array = build1 (ADDR_EXPR, type1, array);
+      array = convert (type, array);
+    }
 
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
 
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
@@ -2721,7 +2813,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
                                          build_constructor (return_type, 0),
                                          false);
          else
                                          build_constructor (return_type, 0),
                                          false);
          else
-           rhs = fold_convert_loc (loc, return_type, integer_zero_node);
+           rhs = build_zero_cst (return_type);
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
@@ -2851,8 +2943,13 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
       if (type == void_type_node)
        {
 
       if (type == void_type_node)
        {
-         error_at (input_location,
-                   "too many arguments to function %qE", function);
+         if (selector)
+           error_at (input_location,
+                     "too many arguments to method %qE", selector);
+         else
+           error_at (input_location,
+                     "too many arguments to function %qE", function);
+
          if (fundecl && !DECL_BUILT_IN (fundecl))
            inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
          return parmnum;
          if (fundecl && !DECL_BUILT_IN (fundecl))
            inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
          return parmnum;
@@ -3049,8 +3146,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
          if (type_generic)
            parmval = val;
          else
          if (type_generic)
            parmval = val;
          else
-           /* Convert `float' to `double'.  */
-           parmval = convert (double_type_node, val);
+           {
+             /* Convert `float' to `double'.  */
+             if (warn_double_promotion && !c_inhibit_evaluation_warnings)
+               warning (OPT_Wdouble_promotion,
+                        "implicit conversion from %qT to %qT when passing "
+                        "argument to function",
+                        valtype, double_type_node);
+             parmval = convert (double_type_node, val);
+           }
        }
       else if (excess_precision && !type_generic)
        /* A "double" argument with excess precision being passed
        }
       else if (excess_precision && !type_generic)
        /* A "double" argument with excess precision being passed
@@ -3449,26 +3553,10 @@ build_unary_op (location_t location,
       goto return_build_unary_op;
 
     case REALPART_EXPR:
       goto return_build_unary_op;
 
     case REALPART_EXPR:
-      if (TREE_CODE (arg) == COMPLEX_CST)
-       ret = TREE_REALPART (arg);
-      else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1_loc (location,
-                              REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
-      else
-       ret = arg;
-      if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
-       eptype = TREE_TYPE (eptype);
-      goto return_build_unary_op;
-
     case IMAGPART_EXPR:
     case IMAGPART_EXPR:
-      if (TREE_CODE (arg) == COMPLEX_CST)
-       ret = TREE_IMAGPART (arg);
-      else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1_loc (location,
-                              IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
-      else
-       ret = omit_one_operand_loc (location, TREE_TYPE (arg),
-                               integer_zero_node, arg);
+      ret = build_real_imag_expr (location, code, arg);
+      if (ret == error_mark_node)
+       return error_mark_node;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
@@ -3491,11 +3579,13 @@ build_unary_op (location_t location,
          goto return_build_unary_op;
        }
 
          goto return_build_unary_op;
        }
 
-      /* Complain about anything that is not a true lvalue.  */
-      if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
-                                 || code == POSTINCREMENT_EXPR)
-                                ? lv_increment
-                                : lv_decrement)))
+      /* Complain about anything that is not a true lvalue.  In
+        Objective-C, skip this check for property_refs.  */
+      if (!objc_is_property_ref (arg) 
+         && !lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
+                                    || code == POSTINCREMENT_EXPR)
+                                   ? lv_increment
+                                   : lv_decrement)))
        return error_mark_node;
 
       if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
        return error_mark_node;
 
       if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
@@ -3603,6 +3693,13 @@ build_unary_op (location_t location,
            inc = convert (argtype, inc);
          }
 
            inc = convert (argtype, inc);
          }
 
+       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+          need to ask Objective-C to build the increment or decrement
+          expression for it.  */
+       if (objc_is_property_ref (arg))
+         return objc_build_incr_expr_for_property_ref (location, code, 
+                                                       arg, inc);
+
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
@@ -3689,14 +3786,24 @@ build_unary_op (location_t location,
       argtype = TREE_TYPE (arg);
 
       /* If the lvalue is const or volatile, merge that into the type
       argtype = TREE_TYPE (arg);
 
       /* If the lvalue is const or volatile, merge that into the type
-        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.  This should only be needed
+        for function types.  */
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
          && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
          && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
-         argtype = c_build_type_variant (argtype,
-                                         TREE_READONLY (arg),
-                                         TREE_THIS_VOLATILE (arg));
+       {
+         int orig_quals = TYPE_QUALS (strip_array_types (argtype));
+         int quals = orig_quals;
+
+         if (TREE_READONLY (arg))
+           quals |= TYPE_QUAL_CONST;
+         if (TREE_THIS_VOLATILE (arg))
+           quals |= TYPE_QUAL_VOLATILE;
+
+         gcc_assert (quals == orig_quals
+                     || TREE_CODE (argtype) == FUNCTION_TYPE);
+
+         argtype = c_build_qualified_type (argtype, quals);
+       }
 
       if (!c_mark_addressable (arg))
        return error_mark_node;
 
       if (!c_mark_addressable (arg))
        return error_mark_node;
@@ -3983,7 +4090,6 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
   bool int_const, op1_int_operands, op2_int_operands, int_operands;
   bool ifexp_int_operands;
   tree ret;
   bool int_const, op1_int_operands, op2_int_operands, int_operands;
   bool ifexp_int_operands;
   tree ret;
-  bool objc_ok;
 
   op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
   if (op1_int_operands)
 
   op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
   if (op1_int_operands)
@@ -4020,8 +4126,6 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
-  objc_ok = objc_compare_types (type1, type2, -3, NULL_TREE);
-
   if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
        || TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
       && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
   if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
        || TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
       && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -4073,6 +4177,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
               || code2 == COMPLEX_TYPE))
     {
       result_type = c_common_type (type1, type2);
               || code2 == COMPLEX_TYPE))
     {
       result_type = c_common_type (type1, type2);
+      do_warn_double_promotion (result_type, type1, type2,
+                               "implicit conversion from %qT to %qT to "
+                               "match other result of conditional",
+                               colon_loc);
 
       /* 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
@@ -4183,13 +4291,15 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
                                                          TREE_TYPE (type1)));
        }
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
                                                          TREE_TYPE (type1)));
        }
+      /* Objective-C pointer comparisons are a bit more lenient.  */
+      else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
+       result_type = objc_common_type (type1, type2);
       else
        {
          int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
 
       else
        {
          int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
 
-         if (!objc_ok)
-           pedwarn (colon_loc, 0,
-                    "pointer type mismatch in conditional expression");
+         pedwarn (colon_loc, 0,
+                  "pointer type mismatch in conditional expression");
          result_type = build_pointer_type
                          (build_qualified_type (void_type_node, qual));
        }
          result_type = build_pointer_type
                          (build_qualified_type (void_type_node, qual));
        }
@@ -4347,12 +4457,13 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
 
 /* Issue -Wcast-qual warnings when appropriate.  TYPE is the type to
    which we are casting.  OTYPE is the type of the expression being
 
 /* Issue -Wcast-qual warnings when appropriate.  TYPE is the type to
    which we are casting.  OTYPE is the type of the expression being
-   cast.  Both TYPE and OTYPE are pointer types.  -Wcast-qual appeared
-   on the command line.  Named address space qualifiers are not handled
-   here, because they result in different warnings.  */
+   cast.  Both TYPE and OTYPE are pointer types.  LOC is the location
+   of the cast.  -Wcast-qual appeared on the command line.  Named
+   address space qualifiers are not handled here, because they result
+   in different warnings.  */
 
 static void
 
 static void
-handle_warn_cast_qual (tree type, tree otype)
+handle_warn_cast_qual (location_t loc, tree type, tree otype)
 {
   tree in_type = type;
   tree in_otype = otype;
 {
   tree in_type = type;
   tree in_otype = otype;
@@ -4385,13 +4496,15 @@ handle_warn_cast_qual (tree type, tree otype)
         && TREE_CODE (in_otype) == POINTER_TYPE);
 
   if (added)
         && TREE_CODE (in_otype) == POINTER_TYPE);
 
   if (added)
-    warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+    warning_at (loc, OPT_Wcast_qual,
+               "cast adds %q#v qualifier to function type", added);
 
   if (discarded)
     /* There are qualifiers present in IN_OTYPE that are not present
        in IN_TYPE.  */
 
   if (discarded)
     /* There are qualifiers present in IN_OTYPE that are not present
        in IN_TYPE.  */
-    warning (OPT_Wcast_qual,
-            "cast discards qualifiers from pointer target type");
+    warning_at (loc, OPT_Wcast_qual,
+               "cast discards %q#v qualifier from pointer target type",
+               discarded);
 
   if (added || discarded)
     return;
 
   if (added || discarded)
     return;
@@ -4424,9 +4537,10 @@ handle_warn_cast_qual (tree type, tree otype)
       if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
          && !is_const)
        {
       if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
          && !is_const)
        {
-         warning (OPT_Wcast_qual,
-                  ("new qualifiers in middle of multi-level non-const cast "
-                   "are unsafe"));
+         warning_at (loc, OPT_Wcast_qual,
+                     "to be safe all intermediate pointers in cast from "
+                      "%qT to %qT must be %<const%> qualified",
+                     otype, type);
          break;
        }
       if (is_const)
          break;
        }
       if (is_const)
@@ -4489,7 +4603,7 @@ build_c_cast (location_t loc, tree type, tree expr)
     {
       tree field;
 
     {
       tree field;
 
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        if (TREE_TYPE (field) != error_mark_node
            && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
                          TYPE_MAIN_VARIANT (TREE_TYPE (value))))
        if (TREE_TYPE (field) != error_mark_node
            && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
                          TYPE_MAIN_VARIANT (TREE_TYPE (value))))
@@ -4530,7 +4644,7 @@ build_c_cast (location_t loc, tree type, tree expr)
       if (warn_cast_qual
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE)
       if (warn_cast_qual
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE)
-       handle_warn_cast_qual (type, otype);
+       handle_warn_cast_qual (loc, type, otype);
 
       /* Warn about conversions between pointers to disjoint
         address spaces.  */
 
       /* Warn about conversions between pointers to disjoint
         address spaces.  */
@@ -4702,8 +4816,9 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
   if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
     SET_EXPR_LOCATION (ret, loc);
 
   if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
     SET_EXPR_LOCATION (ret, loc);
 
-  /* C++ does not permits types to be defined in a cast.  */
-  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+  /* C++ does not permits types to be defined in a cast, but it
+     allows references to incomplete types.  */
+  if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef)
     warning_at (loc, OPT_Wc___compat,
                "defining a type in a cast is invalid in C++");
 
     warning_at (loc, OPT_Wc___compat,
                "defining a type in a cast is invalid in C++");
 
@@ -4741,7 +4856,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
     return error_mark_node;
 
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
     return error_mark_node;
 
-  if (!lvalue_or_else (lhs, lv_assign))
+  /* For ObjC properties, defer this check.  */
+  if (!objc_is_property_ref (lhs) && !lvalue_or_else (lhs, lv_assign))
     return error_mark_node;
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
     return error_mark_node;
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
@@ -4782,6 +4898,19 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       rhs_origtype = NULL_TREE;
     }
 
       rhs_origtype = NULL_TREE;
     }
 
+  if (c_dialect_objc ())
+    {
+      /* Check if we are modifying an Objective-C property reference;
+        if so, we need to generate setter calls.  */
+      result = objc_maybe_build_modify_expr (lhs, newrhs);
+      if (result)
+       return result;
+
+      /* Else, do the check that we postponed for Objective-C.  */
+      if (!lvalue_or_else (lhs, lv_assign))
+       return error_mark_node;
+    }
+
   /* Give an error for storing in something that is 'const'.  */
 
   if (TYPE_READONLY (lhstype)
   /* Give an error for storing in something that is 'const'.  */
 
   if (TYPE_READONLY (lhstype)
@@ -4877,6 +5006,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   return result;
 }
 \f
   return result;
 }
 \f
+/* Return whether STRUCT_TYPE has an anonymous field with type TYPE.
+   This is used to implement -fplan9-extensions.  */
+
+static bool
+find_anonymous_field_with_type (tree struct_type, tree type)
+{
+  tree field;
+  bool found;
+
+  gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE
+             || TREE_CODE (struct_type) == UNION_TYPE);
+  found = false;
+  for (field = TYPE_FIELDS (struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) == NULL
+         && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+      else if (DECL_NAME (field) == NULL
+              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+              && find_anonymous_field_with_type (TREE_TYPE (field), type))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+    }
+  return found;
+}
+
+/* RHS is an expression whose type is pointer to struct.  If there is
+   an anonymous field in RHS with type TYPE, then return a pointer to
+   that field in RHS.  This is used with -fplan9-extensions.  This
+   returns NULL if no conversion could be found.  */
+
+static tree
+convert_to_anonymous_field (location_t location, tree type, tree rhs)
+{
+  tree rhs_struct_type, lhs_main_type;
+  tree field, found_field;
+  bool found_sub_field;
+  tree ret;
+
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs)));
+  rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs));
+  gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE
+             || TREE_CODE (rhs_struct_type) == UNION_TYPE);
+
+  gcc_assert (POINTER_TYPE_P (type));
+  lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+
+  found_field = NULL_TREE;
+  found_sub_field = false;
+  for (field = TYPE_FIELDS (rhs_struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) != NULL_TREE
+         || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
+             && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
+       continue;
+      if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+       }
+      else if (find_anonymous_field_with_type (TREE_TYPE (field),
+                                              lhs_main_type))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+         found_sub_field = true;
+       }
+    }
+
+  if (found_field == NULL_TREE)
+    return NULL_TREE;
+
+  ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field),
+                        build_fold_indirect_ref (rhs), found_field,
+                        NULL_TREE);
+  ret = build_fold_addr_expr_loc (location, ret);
+
+  if (found_sub_field)
+    {
+      ret = convert_to_anonymous_field (location, type, ret);
+      gcc_assert (ret != NULL_TREE);
+    }
+
+  return ret;
+}
+
 /* Convert value RHS to type TYPE as preparation for an assignment to
    an lvalue of type TYPE.  If ORIGTYPE is not NULL_TREE, it is the
    original type of RHS; this differs from TREE_TYPE (RHS) for enum
 /* Convert value RHS to type TYPE as preparation for an assignment to
    an lvalue of type TYPE.  If ORIGTYPE is not NULL_TREE, it is the
    original type of RHS; this differs from TREE_TYPE (RHS) for enum
@@ -4942,7 +5171,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         pedwarn (LOCATION, OPT, AS);                                     \
         break;                                                           \
       case ic_init:                                                      \
         pedwarn (LOCATION, OPT, AS);                                     \
         break;                                                           \
       case ic_init:                                                      \
-        pedwarn (LOCATION, OPT, IN);                                     \
+        pedwarn_init (LOCATION, OPT, IN);                                \
         break;                                                           \
       case ic_return:                                                    \
         pedwarn (LOCATION, OPT, RE);                                    \
         break;                                                           \
       case ic_return:                                                    \
         pedwarn (LOCATION, OPT, RE);                                    \
@@ -4952,6 +5181,36 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       }                                                                  \
   } while (0)
 
       }                                                                  \
   } while (0)
 
+  /* This macro is used to emit diagnostics to ensure that all format
+     strings are complete sentences, visible to gettext and checked at
+     compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
+     extra parameter to enumerate qualifiers.  */
+
+#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS)        \
+  do {                                                                   \
+    switch (errtype)                                                     \
+      {                                                                  \
+      case ic_argpass:                                                   \
+        if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS))          \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
+                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+                  "expected %qT but argument is of type %qT",            \
+                  type, rhstype);                                        \
+        break;                                                           \
+      case ic_assign:                                                    \
+        pedwarn (LOCATION, OPT, AS, QUALS);                          \
+        break;                                                           \
+      case ic_init:                                                      \
+        pedwarn (LOCATION, OPT, IN, QUALS);                          \
+        break;                                                           \
+      case ic_return:                                                    \
+        pedwarn (LOCATION, OPT, RE, QUALS);                             \
+        break;                                                           \
+      default:                                                           \
+        gcc_unreachable ();                                              \
+      }                                                                  \
+  } while (0)
+
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
 
@@ -5091,7 +5350,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     {
       tree memb, marginal_memb = NULL_TREE;
 
     {
       tree memb, marginal_memb = NULL_TREE;
 
-      for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb))
+      for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb))
        {
          tree memb_type = TREE_TYPE (memb);
 
        {
          tree memb_type = TREE_TYPE (memb);
 
@@ -5159,30 +5418,32 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                     vice-versa.  */
                  if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
                     vice-versa.  */
                  if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-                   WARN_FOR_ASSIGNMENT (location, 0,
+                   WARN_FOR_QUALIFIERS (location, 0,
                                         G_("passing argument %d of %qE "
                                         G_("passing argument %d of %qE "
-                                           "makes qualified function "
+                                           "makes %q#v qualified function "
                                            "pointer from unqualified"),
                                            "pointer from unqualified"),
-                                        G_("assignment makes qualified "
+                                        G_("assignment makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
                                            "function pointer from "
                                            "unqualified"),
-                                        G_("initialization makes qualified "
+                                        G_("initialization makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
                                            "function pointer from "
                                            "unqualified"),
-                                        G_("return makes qualified function "
-                                           "pointer from unqualified"));
+                                        G_("return makes %q#v qualified function "
+                                           "pointer from unqualified"),
+                                        TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
                }
              else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
                       & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
                }
              else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
                       & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
-               WARN_FOR_ASSIGNMENT (location, 0,
+               WARN_FOR_QUALIFIERS (location, 0,
                                     G_("passing argument %d of %qE discards "
                                     G_("passing argument %d of %qE discards "
-                                       "qualifiers from pointer target type"),
-                                    G_("assignment discards qualifiers "
+                                       "%qv qualifier from pointer target type"),
+                                    G_("assignment discards %qv qualifier "
                                        "from pointer target type"),
                                        "from pointer target type"),
-                                    G_("initialization discards qualifiers "
+                                    G_("initialization discards %qv qualifier "
                                        "from pointer target type"),
                                        "from pointer target type"),
-                                    G_("return discards qualifiers from "
-                                       "pointer target type"));
+                                    G_("return discards %qv qualifier from "
+                                       "pointer target type"),
+                                    TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
 
              memb = marginal_memb;
            }
 
              memb = marginal_memb;
            }
@@ -5216,6 +5477,25 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
 
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
 
+      /* The Plan 9 compiler permits a pointer to a struct to be
+        automatically converted into a pointer to an anonymous field
+        within the struct.  */
+      if (flag_plan9_extensions
+         && (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE)
+         && (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE)
+         && mvl != mvr)
+       {
+         tree new_rhs = convert_to_anonymous_field (location, type, rhs);
+         if (new_rhs != NULL_TREE)
+           {
+             rhs = new_rhs;
+             rhstype = TREE_TYPE (rhs);
+             coder = TREE_CODE (rhstype);
+             ttr = TREE_TYPE (rhstype);
+             mvr = TYPE_MAIN_VARIANT (ttr);
+           }
+       }
+
       /* C++ does not allow the implicit conversion void* -> T*.  However,
         for the purpose of reducing the number of false positives, we
         tolerate the special case of
       /* C++ does not allow the implicit conversion void* -> T*.  However,
         for the purpose of reducing the number of false positives, we
         tolerate the special case of
@@ -5324,19 +5604,16 @@ convert_for_assignment (location_t location, tree type, tree rhs,
              if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
                  & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
                {
              if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
                  & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
                {
-                 /* Types differing only by the presence of the 'volatile'
-                    qualifier are acceptable if the 'volatile' has been added
-                    in by the Objective-C EH machinery.  */
-                 if (!objc_type_quals_match (ttl, ttr))
-                   WARN_FOR_ASSIGNMENT (location, 0,
-                                        G_("passing argument %d of %qE discards "
-                                           "qualifiers from pointer target type"),
-                                        G_("assignment discards qualifiers "
-                                           "from pointer target type"),
-                                        G_("initialization discards qualifiers "
-                                           "from pointer target type"),
-                                        G_("return discards qualifiers from "
-                                           "pointer target type"));
+                 WARN_FOR_QUALIFIERS (location, 0,
+                                      G_("passing argument %d of %qE discards "
+                                         "%qv qualifier from pointer target type"),
+                                      G_("assignment discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("initialization discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("return discards %qv qualifier from "
+                                         "pointer target type"),
+                                      TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
                }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
                }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
@@ -5364,16 +5641,17 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                  & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                  & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-               WARN_FOR_ASSIGNMENT (location, 0,
+               WARN_FOR_QUALIFIERS (location, 0,
                                     G_("passing argument %d of %qE makes "
                                     G_("passing argument %d of %qE makes "
-                                       "qualified function pointer "
+                                       "%q#v qualified function pointer "
                                        "from unqualified"),
                                        "from unqualified"),
-                                    G_("assignment makes qualified function "
+                                    G_("assignment makes %q#v qualified function "
                                        "pointer from unqualified"),
                                        "pointer from unqualified"),
-                                    G_("initialization makes qualified "
+                                    G_("initialization makes %q#v qualified "
                                        "function pointer from unqualified"),
                                        "function pointer from unqualified"),
-                                    G_("return makes qualified function "
-                                       "pointer from unqualified"));
+                                    G_("return makes %q#v qualified function "
+                                       "pointer from unqualified"),
+                                    TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
            }
        }
       else
            }
        }
       else
@@ -5682,15 +5960,16 @@ print_spelling (char *buffer)
 }
 
 /* Issue an error message for a bad initializer component.
 }
 
 /* Issue an error message for a bad initializer component.
-   MSGID identifies the message.
+   GMSGID identifies the message.
    The component name is taken from the spelling stack.  */
 
 void
    The component name is taken from the spelling stack.  */
 
 void
-error_init (const char *msgid)
+error_init (const char *gmsgid)
 {
   char *ofwhat;
 
 {
   char *ofwhat;
 
-  error ("%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  error (gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     error ("(near initialization for %qs)", ofwhat);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     error ("(near initialization for %qs)", ofwhat);
@@ -5698,15 +5977,16 @@ error_init (const char *msgid)
 
 /* Issue a pedantic warning for a bad initializer component.  OPT is
    the option OPT_* (from options.h) controlling this warning or 0 if
 
 /* Issue a pedantic warning for a bad initializer component.  OPT is
    the option OPT_* (from options.h) controlling this warning or 0 if
-   it is unconditionally given.  MSGID identifies the message.  The
+   it is unconditionally given.  GMSGID identifies the message.  The
    component name is taken from the spelling stack.  */
 
 void
    component name is taken from the spelling stack.  */
 
 void
-pedwarn_init (location_t location, int opt, const char *msgid)
+pedwarn_init (location_t location, int opt, const char *gmsgid)
 {
   char *ofwhat;
 {
   char *ofwhat;
-
-  pedwarn (location, opt, "%s", _(msgid));
+  
+  /* The gmsgid may be a format string with %< and %>. */
+  pedwarn (location, opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
@@ -5715,15 +5995,16 @@ pedwarn_init (location_t location, int opt, const char *msgid)
 /* Issue a warning for a bad initializer component.
 
    OPT is the OPT_W* value corresponding to the warning option that
 /* Issue a warning for a bad initializer component.
 
    OPT is the OPT_W* value corresponding to the warning option that
-   controls this warning.  MSGID identifies the message.  The
+   controls this warning.  GMSGID identifies the message.  The
    component name is taken from the spelling stack.  */
 
 static void
    component name is taken from the spelling stack.  */
 
 static void
-warning_init (int opt, const char *msgid)
+warning_init (int opt, const char *gmsgid)
 {
   char *ofwhat;
 
 {
   char *ofwhat;
 
-  warning (opt, "%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  warning (opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     warning (opt, "(near initialization for %qs)", ofwhat);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     warning (opt, "(near initialization for %qs)", ofwhat);
@@ -6375,7 +6656,7 @@ really_start_incremental_init (tree type)
       /* Skip any nameless bit fields at the beginning.  */
       while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
       /* Skip any nameless bit fields at the beginning.  */
       while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
-       constructor_fields = TREE_CHAIN (constructor_fields);
+       constructor_fields = DECL_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6390,14 +6671,14 @@ really_start_incremental_init (tree type)
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          constructor_index
            = convert (bitsizetype,
 
          constructor_index
            = convert (bitsizetype,
@@ -6433,7 +6714,7 @@ really_start_incremental_init (tree type)
    IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
    IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
-push_init_level (int implicit)
+push_init_level (int implicit, struct obstack * braced_init_obstack)
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
@@ -6451,12 +6732,14 @@ push_init_level (int implicit)
          if ((TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
              && constructor_fields == 0)
          if ((TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
              && constructor_fields == 0)
-           process_init_element (pop_init_level (1), true);
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
          else if (TREE_CODE (constructor_type) == ARRAY_TYPE
                   && constructor_max_index
                   && tree_int_cst_lt (constructor_max_index,
                                       constructor_index))
          else if (TREE_CODE (constructor_type) == ARRAY_TYPE
                   && constructor_max_index
                   && tree_int_cst_lt (constructor_max_index,
                                       constructor_index))
-           process_init_element (pop_init_level (1), true);
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
          else
            break;
        }
          else
            break;
        }
@@ -6469,9 +6752,9 @@ push_init_level (int implicit)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields)
-       value = find_init_member (constructor_fields);
+       value = find_init_member (constructor_fields, braced_init_obstack);
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       value = find_init_member (constructor_index);
+       value = find_init_member (constructor_index, braced_init_obstack);
     }
 
   p = XNEW (struct constructor_stack);
     }
 
   p = XNEW (struct constructor_stack);
@@ -6557,7 +6840,7 @@ push_init_level (int implicit)
       if (!VEC_empty (constructor_elt, constructor_elements)
          && (TREE_CODE (constructor_type) == RECORD_TYPE
              || TREE_CODE (constructor_type) == ARRAY_TYPE))
       if (!VEC_empty (constructor_elt, constructor_elements)
          && (TREE_CODE (constructor_type) == RECORD_TYPE
              || TREE_CODE (constructor_type) == ARRAY_TYPE))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
     }
 
   if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
     }
 
   if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
@@ -6573,7 +6856,7 @@ push_init_level (int implicit)
       /* Skip any nameless bit fields at the beginning.  */
       while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
       /* Skip any nameless bit fields at the beginning.  */
       while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
-       constructor_fields = TREE_CHAIN (constructor_fields);
+       constructor_fields = DECL_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6596,14 +6879,14 @@ push_init_level (int implicit)
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          constructor_index
            = convert (bitsizetype,
 
          constructor_index
            = convert (bitsizetype,
@@ -6618,7 +6901,7 @@ push_init_level (int implicit)
          /* We need to split the char/wchar array into individual
             characters, so that we don't have to special case it
             everywhere.  */
          /* We need to split the char/wchar array into individual
             characters, so that we don't have to special case it
             everywhere.  */
-         set_nonincremental_init_from_string (value);
+         set_nonincremental_init_from_string (value, braced_init_obstack);
        }
     }
   else
        }
     }
   else
@@ -6642,7 +6925,7 @@ push_init_level (int implicit)
    Otherwise, return a CONSTRUCTOR expression as the value.  */
 
 struct c_expr
    Otherwise, return a CONSTRUCTOR expression as the value.  */
 
 struct c_expr
-pop_init_level (int implicit)
+pop_init_level (int implicit, struct obstack * braced_init_obstack)
 {
   struct constructor_stack *p;
   struct c_expr ret;
 {
   struct constructor_stack *p;
   struct c_expr ret;
@@ -6655,14 +6938,16 @@ pop_init_level (int implicit)
       /* When we come to an explicit close brace,
         pop any inner levels that didn't have explicit braces.  */
       while (constructor_stack->implicit)
       /* When we come to an explicit close brace,
         pop any inner levels that didn't have explicit braces.  */
       while (constructor_stack->implicit)
-       process_init_element (pop_init_level (1), true);
-
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
       gcc_assert (!constructor_range_stack);
     }
 
   /* Now output all pending elements.  */
   constructor_incremental = 1;
       gcc_assert (!constructor_range_stack);
     }
 
   /* Now output all pending elements.  */
   constructor_incremental = 1;
-  output_pending_init_elements (1);
+  output_pending_init_elements (1, braced_init_obstack);
 
   p = constructor_stack;
 
 
   p = constructor_stack;
 
@@ -6690,7 +6975,7 @@ pop_init_level (int implicit)
          /* We have already issued an error message for the existence
             of a flexible array member not at the end of the structure.
             Discard the initializer so that we do not die later.  */
          /* We have already issued an error message for the existence
             of a flexible array member not at the end of the structure.
             Discard the initializer so that we do not die later.  */
-         if (TREE_CHAIN (constructor_fields) != NULL_TREE)
+         if (DECL_CHAIN (constructor_fields) != NULL_TREE)
            constructor_type = NULL_TREE;
        }
     }
            constructor_type = NULL_TREE;
        }
     }
@@ -6705,7 +6990,7 @@ pop_init_level (int implicit)
        while (constructor_unfilled_fields
               && (!DECL_SIZE (constructor_unfilled_fields)
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
        while (constructor_unfilled_fields
               && (!DECL_SIZE (constructor_unfilled_fields)
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
-         constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
+         constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
 
        /* Do not warn if this level of the initializer uses member
           designators; it is likely to be deliberate.  */
 
        /* Do not warn if this level of the initializer uses member
           designators; it is likely to be deliberate.  */
@@ -6803,7 +7088,7 @@ pop_init_level (int implicit)
    ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
 
 static int
    ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
 
 static int
-set_designator (int array)
+set_designator (int array, struct obstack * braced_init_obstack)
 {
   tree subtype;
   enum tree_code subcode;
 {
   tree subtype;
   enum tree_code subcode;
@@ -6825,7 +7110,10 @@ set_designator (int array)
       /* Designator list starts at the level of closest explicit
         braces.  */
       while (constructor_stack->implicit)
       /* Designator list starts at the level of closest explicit
         braces.  */
       while (constructor_stack->implicit)
-       process_init_element (pop_init_level (1), true);
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
       constructor_designated = 1;
       return 0;
     }
       constructor_designated = 1;
       return 0;
     }
@@ -6858,7 +7146,7 @@ set_designator (int array)
     }
 
   constructor_designated = 1;
     }
 
   constructor_designated = 1;
-  push_init_level (2);
+  push_init_level (2, braced_init_obstack);
   return 0;
 }
 
   return 0;
 }
 
@@ -6867,11 +7155,13 @@ set_designator (int array)
    NULL_TREE if there is no range designator at this level.  */
 
 static void
    NULL_TREE if there is no range designator at this level.  */
 
 static void
-push_range_stack (tree range_end)
+push_range_stack (tree range_end, struct obstack * braced_init_obstack)
 {
   struct constructor_range_stack *p;
 
 {
   struct constructor_range_stack *p;
 
-  p = GGC_NEW (struct constructor_range_stack);
+  p = (struct constructor_range_stack *)
+    obstack_alloc (braced_init_obstack,
+                  sizeof (struct constructor_range_stack));
   p->prev = constructor_range_stack;
   p->next = 0;
   p->fields = constructor_fields;
   p->prev = constructor_range_stack;
   p->next = 0;
   p->fields = constructor_fields;
@@ -6889,9 +7179,10 @@ push_range_stack (tree range_end)
    of indices, running from FIRST through LAST.  */
 
 void
    of indices, running from FIRST through LAST.  */
 
 void
-set_init_index (tree first, tree last)
+set_init_index (tree first, tree last,
+               struct obstack * braced_init_obstack)
 {
 {
-  if (set_designator (1))
+  if (set_designator (1, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
     return;
 
   designator_erroneous = 1;
@@ -6963,18 +7254,18 @@ set_init_index (tree first, tree last)
       designator_depth++;
       designator_erroneous = 0;
       if (constructor_range_stack || last)
       designator_depth++;
       designator_erroneous = 0;
       if (constructor_range_stack || last)
-       push_range_stack (last);
+       push_range_stack (last, braced_init_obstack);
     }
 }
 
 /* Within a struct initializer, specify the next field to be initialized.  */
 
 void
     }
 }
 
 /* Within a struct initializer, specify the next field to be initialized.  */
 
 void
-set_init_label (tree fieldname)
+set_init_label (tree fieldname, struct obstack * braced_init_obstack)
 {
 {
-  tree tail;
+  tree field;
 
 
-  if (set_designator (0))
+  if (set_designator (0, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
     return;
 
   designator_erroneous = 1;
@@ -6986,23 +7277,26 @@ set_init_label (tree fieldname)
       return;
     }
 
       return;
     }
 
-  for (tail = TYPE_FIELDS (constructor_type); tail;
-       tail = TREE_CHAIN (tail))
-    {
-      if (DECL_NAME (tail) == fieldname)
-       break;
-    }
+  field = lookup_field (constructor_type, fieldname);
 
 
-  if (tail == 0)
+  if (field == 0)
     error ("unknown field %qE specified in initializer", fieldname);
   else
     error ("unknown field %qE specified in initializer", fieldname);
   else
-    {
-      constructor_fields = tail;
-      designator_depth++;
-      designator_erroneous = 0;
-      if (constructor_range_stack)
-       push_range_stack (NULL_TREE);
-    }
+    do
+      {
+       constructor_fields = TREE_VALUE (field);
+       designator_depth++;
+       designator_erroneous = 0;
+       if (constructor_range_stack)
+         push_range_stack (NULL_TREE, braced_init_obstack);
+       field = TREE_CHAIN (field);
+       if (field)
+         {
+           if (set_designator (0, braced_init_obstack))
+             return;
+         }
+      }
+    while (field != NULL_TREE);
 }
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
 }
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
@@ -7016,7 +7310,8 @@ set_init_label (tree fieldname)
    existing initializer.  */
 
 static void
    existing initializer.  */
 
 static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
+add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
+                 struct obstack * braced_init_obstack)
 {
   struct init_node *p, **q, *r;
 
 {
   struct init_node *p, **q, *r;
 
@@ -7075,7 +7370,8 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
        }
     }
 
        }
     }
 
-  r = GGC_NEW (struct init_node);
+  r = (struct init_node *) obstack_alloc (braced_init_obstack,
+                                         sizeof (struct init_node));
   r->purpose = purpose;
   r->value = value;
   r->origtype = origtype;
   r->purpose = purpose;
   r->value = value;
   r->origtype = origtype;
@@ -7244,7 +7540,7 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
 /* Build AVL tree from a sorted chain.  */
 
 static void
 /* Build AVL tree from a sorted chain.  */
 
 static void
-set_nonincremental_init (void)
+set_nonincremental_init (struct obstack * braced_init_obstack)
 {
   unsigned HOST_WIDE_INT ix;
   tree index, value;
 {
   unsigned HOST_WIDE_INT ix;
   tree index, value;
@@ -7254,7 +7550,10 @@ set_nonincremental_init (void)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    add_pending_init (index, value, NULL_TREE, false);
+    {
+      add_pending_init (index, value, NULL_TREE, false,
+                       braced_init_obstack);
+    }
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -7281,7 +7580,8 @@ set_nonincremental_init (void)
 /* Build AVL tree from a string constant.  */
 
 static void
 /* Build AVL tree from a string constant.  */
 
 static void
-set_nonincremental_init_from_string (tree str)
+set_nonincremental_init_from_string (tree str,
+                                    struct obstack * braced_init_obstack)
 {
   tree value, purpose, type;
   HOST_WIDE_INT val[2];
 {
   tree value, purpose, type;
   HOST_WIDE_INT val[2];
@@ -7344,7 +7644,8 @@ set_nonincremental_init_from_string (tree str)
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value, NULL_TREE, false);
+      add_pending_init (purpose, value, NULL_TREE, false,
+                        braced_init_obstack);
     }
 
   constructor_incremental = 0;
     }
 
   constructor_incremental = 0;
@@ -7354,7 +7655,7 @@ set_nonincremental_init_from_string (tree str)
    not initialized yet.  */
 
 static tree
    not initialized yet.  */
 
 static tree
-find_init_member (tree field)
+find_init_member (tree field, struct obstack * braced_init_obstack)
 {
   struct init_node *p;
 
 {
   struct init_node *p;
 
@@ -7362,7 +7663,7 @@ find_init_member (tree field)
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
       p = constructor_pending_elts;
       while (p)
 
       p = constructor_pending_elts;
       while (p)
@@ -7383,7 +7684,7 @@ find_init_member (tree field)
          && (!constructor_unfilled_fields
              || tree_int_cst_lt (bitpos,
                                  bit_position (constructor_unfilled_fields))))
          && (!constructor_unfilled_fields
              || tree_int_cst_lt (bitpos,
                                  bit_position (constructor_unfilled_fields))))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
       p = constructor_pending_elts;
       while (p)
 
       p = constructor_pending_elts;
       while (p)
@@ -7427,7 +7728,8 @@ find_init_member (tree field)
 
 static void
 output_init_element (tree value, tree origtype, bool strict_string, tree type,
 
 static void
 output_init_element (tree value, tree origtype, bool strict_string, tree type,
-                    tree field, int pending, bool implicit)
+                    tree field, int pending, bool implicit,
+                    struct obstack * braced_init_obstack)
 {
   tree semantic_type = NULL_TREE;
   constructor_elt *celt;
 {
   tree semantic_type = NULL_TREE;
   constructor_elt *celt;
@@ -7521,7 +7823,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
          || (COMPLETE_TYPE_P (TREE_TYPE (field))
              && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
              && (TREE_CODE (constructor_type) == ARRAY_TYPE
          || (COMPLETE_TYPE_P (TREE_TYPE (field))
              && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
              && (TREE_CODE (constructor_type) == ARRAY_TYPE
-                 || TREE_CHAIN (field)))))
+                 || DECL_CHAIN (field)))))
     return;
 
   if (semantic_type)
     return;
 
   if (semantic_type)
@@ -7544,9 +7846,10 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
 
-      add_pending_init (field, value, origtype, implicit);
+      add_pending_init (field, value, origtype, implicit,
+                       braced_init_obstack);
       return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
       return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -7559,7 +7862,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
       if (constructor_incremental)
        {
          if (!constructor_unfilled_fields)
       if (constructor_incremental)
        {
          if (!constructor_unfilled_fields)
-           set_nonincremental_init ();
+           set_nonincremental_init (braced_init_obstack);
          else
            {
              tree bitpos, unfillpos;
          else
            {
              tree bitpos, unfillpos;
@@ -7568,11 +7871,12 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
              unfillpos = bit_position (constructor_unfilled_fields);
 
              if (tree_int_cst_lt (bitpos, unfillpos))
              unfillpos = bit_position (constructor_unfilled_fields);
 
              if (tree_int_cst_lt (bitpos, unfillpos))
-               set_nonincremental_init ();
+               set_nonincremental_init (braced_init_obstack);
            }
        }
 
            }
        }
 
-      add_pending_init (field, value, origtype, implicit);
+      add_pending_init (field, value, origtype, implicit,
+                       braced_init_obstack);
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
@@ -7607,21 +7911,21 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
   else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
       constructor_unfilled_fields
   else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
       constructor_unfilled_fields
-       = TREE_CHAIN (constructor_unfilled_fields);
+       = DECL_CHAIN (constructor_unfilled_fields);
 
       /* Skip any nameless bit fields.  */
       while (constructor_unfilled_fields != 0
             && DECL_C_BIT_FIELD (constructor_unfilled_fields)
             && DECL_NAME (constructor_unfilled_fields) == 0)
        constructor_unfilled_fields =
 
       /* Skip any nameless bit fields.  */
       while (constructor_unfilled_fields != 0
             && DECL_C_BIT_FIELD (constructor_unfilled_fields)
             && DECL_NAME (constructor_unfilled_fields) == 0)
        constructor_unfilled_fields =
-         TREE_CHAIN (constructor_unfilled_fields);
+         DECL_CHAIN (constructor_unfilled_fields);
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE)
     constructor_unfilled_fields = 0;
 
   /* Now output any pending elements which have become next.  */
   if (pending)
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE)
     constructor_unfilled_fields = 0;
 
   /* Now output any pending elements which have become next.  */
   if (pending)
-    output_pending_init_elements (0);
+    output_pending_init_elements (0, braced_init_obstack);
 }
 
 /* Output any pending elements which have become next.
 }
 
 /* Output any pending elements which have become next.
@@ -7634,9 +7938,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
 
    If ALL is 1, we output space as necessary so that
    we can output all the pending elements.  */
 
    If ALL is 1, we output space as necessary so that
    we can output all the pending elements.  */
-
 static void
 static void
-output_pending_init_elements (int all)
+output_pending_init_elements (int all, struct obstack * braced_init_obstack)
 {
   struct init_node *elt = constructor_pending_elts;
   tree next;
 {
   struct init_node *elt = constructor_pending_elts;
   tree next;
@@ -7657,7 +7960,8 @@ output_pending_init_elements (int all)
                                  constructor_unfilled_index))
            output_init_element (elt->value, elt->origtype, true,
                                 TREE_TYPE (constructor_type),
                                  constructor_unfilled_index))
            output_init_element (elt->value, elt->origtype, true,
                                 TREE_TYPE (constructor_type),
-                                constructor_unfilled_index, 0, false);
+                                constructor_unfilled_index, 0, false,
+                                braced_init_obstack);
          else if (tree_int_cst_lt (constructor_unfilled_index,
                                    elt->purpose))
            {
          else if (tree_int_cst_lt (constructor_unfilled_index,
                                    elt->purpose))
            {
@@ -7711,7 +8015,8 @@ output_pending_init_elements (int all)
              constructor_unfilled_fields = elt->purpose;
              output_init_element (elt->value, elt->origtype, true,
                                   TREE_TYPE (elt->purpose),
              constructor_unfilled_fields = elt->purpose;
              output_init_element (elt->value, elt->origtype, true,
                                   TREE_TYPE (elt->purpose),
-                                  elt->purpose, 0, false);
+                                  elt->purpose, 0, false,
+                                  braced_init_obstack);
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
            {
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
            {
@@ -7782,7 +8087,8 @@ output_pending_init_elements (int all)
    existing initializer.  */
 
 void
    existing initializer.  */
 
 void
-process_init_element (struct c_expr value, bool implicit)
+process_init_element (struct c_expr value, bool implicit,
+                     struct obstack * braced_init_obstack)
 {
   tree orig_value = value.value;
   int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
 {
   tree orig_value = value.value;
   int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
@@ -7823,13 +8129,15 @@ process_init_element (struct c_expr value, bool implicit)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields == 0)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields == 0)
-       process_init_element (pop_init_level (1), true);
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
       else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
                || TREE_CODE (constructor_type) == VECTOR_TYPE)
               && (constructor_max_index == 0
                   || tree_int_cst_lt (constructor_max_index,
                                       constructor_index)))
       else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
                || TREE_CODE (constructor_type) == VECTOR_TYPE)
               && (constructor_max_index == 0
                   || tree_int_cst_lt (constructor_max_index,
                                       constructor_index)))
-       process_init_element (pop_init_level (1), true);
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
       else
        break;
     }
       else
        break;
     }
@@ -7879,7 +8187,7 @@ process_init_element (struct c_expr value, bool implicit)
          if (fieldcode == ARRAY_TYPE
              && !require_constant_value
              && TYPE_SIZE (fieldtype) == NULL_TREE
          if (fieldcode == ARRAY_TYPE
              && !require_constant_value
              && TYPE_SIZE (fieldtype) == NULL_TREE
-             && TREE_CHAIN (constructor_fields) == NULL_TREE)
+             && DECL_CHAIN (constructor_fields) == NULL_TREE)
            {
              error_init ("non-static initialization of a flexible array member");
              break;
            {
              error_init ("non-static initialization of a flexible array member");
              break;
@@ -7899,7 +8207,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
              continue;
            }
 
@@ -7908,7 +8216,8 @@ process_init_element (struct c_expr value, bool implicit)
              push_member_name (constructor_fields);
              output_init_element (value.value, value.original_type,
                                   strict_string, fieldtype,
              push_member_name (constructor_fields);
              output_init_element (value.value, value.original_type,
                                   strict_string, fieldtype,
-                                  constructor_fields, 1, implicit);
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7926,22 +8235,22 @@ process_init_element (struct c_expr value, bool implicit)
                 it isn't now, so update.  */
              if (constructor_unfilled_fields == constructor_fields)
                {
                 it isn't now, so update.  */
              if (constructor_unfilled_fields == constructor_fields)
                {
-                 constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+                 constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
                  /* Skip any nameless bit fields.  */
                  while (constructor_unfilled_fields != 0
                         && DECL_C_BIT_FIELD (constructor_unfilled_fields)
                         && DECL_NAME (constructor_unfilled_fields) == 0)
                    constructor_unfilled_fields =
                  /* Skip any nameless bit fields.  */
                  while (constructor_unfilled_fields != 0
                         && DECL_C_BIT_FIELD (constructor_unfilled_fields)
                         && DECL_NAME (constructor_unfilled_fields) == 0)
                    constructor_unfilled_fields =
-                     TREE_CHAIN (constructor_unfilled_fields);
+                     DECL_CHAIN (constructor_unfilled_fields);
                }
            }
 
                }
            }
 
-         constructor_fields = TREE_CHAIN (constructor_fields);
+         constructor_fields = DECL_CHAIN (constructor_fields);
          /* Skip any nameless bit fields at the beginning.  */
          while (constructor_fields != 0
                 && DECL_C_BIT_FIELD (constructor_fields)
                 && DECL_NAME (constructor_fields) == 0)
          /* Skip any nameless bit fields at the beginning.  */
          while (constructor_fields != 0
                 && DECL_C_BIT_FIELD (constructor_fields)
                 && DECL_NAME (constructor_fields) == 0)
-           constructor_fields = TREE_CHAIN (constructor_fields);
+           constructor_fields = DECL_CHAIN (constructor_fields);
        }
       else if (TREE_CODE (constructor_type) == UNION_TYPE)
        {
        }
       else if (TREE_CODE (constructor_type) == UNION_TYPE)
        {
@@ -7990,7 +8299,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
              continue;
            }
 
@@ -7999,7 +8308,8 @@ process_init_element (struct c_expr value, bool implicit)
              push_member_name (constructor_fields);
              output_init_element (value.value, value.original_type,
                                   strict_string, fieldtype,
              push_member_name (constructor_fields);
              output_init_element (value.value, value.original_type,
                                   strict_string, fieldtype,
-                                  constructor_fields, 1, implicit);
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -8007,7 +8317,7 @@ process_init_element (struct c_expr value, bool implicit)
               directly output as a constructor.  */
            {
              constructor_bit_index = DECL_SIZE (constructor_fields);
               directly output as a constructor.  */
            {
              constructor_bit_index = DECL_SIZE (constructor_fields);
-             constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+             constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
            }
 
          constructor_fields = 0;
            }
 
          constructor_fields = 0;
@@ -8031,7 +8341,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
              continue;
            }
 
@@ -8050,7 +8360,8 @@ process_init_element (struct c_expr value, bool implicit)
              push_array_bounds (tree_low_cst (constructor_index, 1));
              output_init_element (value.value, value.original_type,
                                   strict_string, elttype,
              push_array_bounds (tree_low_cst (constructor_index, 1));
              output_init_element (value.value, value.original_type,
                                   strict_string, elttype,
-                                  constructor_index, 1, implicit);
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
@@ -8084,7 +8395,8 @@ process_init_element (struct c_expr value, bool implicit)
                elttype = TYPE_MAIN_VARIANT (constructor_type);
              output_init_element (value.value, value.original_type,
                                   strict_string, elttype,
                elttype = TYPE_MAIN_VARIANT (constructor_type);
              output_init_element (value.value, value.original_type,
                                   strict_string, elttype,
-                                  constructor_index, 1, implicit);
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
            }
 
          constructor_index
            }
 
          constructor_index
@@ -8112,7 +8424,8 @@ process_init_element (struct c_expr value, bool implicit)
          if (value.value)
            output_init_element (value.value, value.original_type,
                                 strict_string, constructor_type,
          if (value.value)
            output_init_element (value.value, value.original_type,
                                 strict_string, constructor_type,
-                                NULL_TREE, 1, implicit);
+                                NULL_TREE, 1, implicit,
+                                braced_init_obstack);
          constructor_fields = 0;
        }
 
          constructor_fields = 0;
        }
 
@@ -8128,14 +8441,17 @@ process_init_element (struct c_expr value, bool implicit)
          while (constructor_stack != range_stack->stack)
            {
              gcc_assert (constructor_stack->implicit);
          while (constructor_stack != range_stack->stack)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1), true);
+             process_init_element (pop_init_level (1,
+                                                   braced_init_obstack),
+                                   true, braced_init_obstack);
            }
          for (p = range_stack;
               !p->range_end || tree_int_cst_equal (p->index, p->range_end);
               p = p->prev)
            {
              gcc_assert (constructor_stack->implicit);
            }
          for (p = range_stack;
               !p->range_end || tree_int_cst_equal (p->index, p->range_end);
               p = p->prev)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1), true);
+             process_init_element (pop_init_level (1, braced_init_obstack),
+                                   true, braced_init_obstack);
            }
 
          p->index = size_binop_loc (input_location,
            }
 
          p->index = size_binop_loc (input_location,
@@ -8155,7 +8471,7 @@ process_init_element (struct c_expr value, bool implicit)
              p = p->next;
              if (!p)
                break;
              p = p->next;
              if (!p)
                break;
-             push_init_level (2);
+             push_init_level (2, braced_init_obstack);
              p->stack = constructor_stack;
              if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
                p->index = p->range_start;
              p->stack = constructor_stack;
              if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
                p->index = p->range_start;
@@ -8806,6 +9122,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
 tree
 c_process_expr_stmt (location_t loc, tree expr)
 {
 tree
 c_process_expr_stmt (location_t loc, tree expr)
 {
+  tree exprv;
+
   if (!expr)
     return NULL_TREE;
 
   if (!expr)
     return NULL_TREE;
 
@@ -8826,11 +9144,16 @@ c_process_expr_stmt (location_t loc, tree expr)
       && warn_unused_value)
     emit_side_effect_warnings (loc, expr);
 
       && warn_unused_value)
     emit_side_effect_warnings (loc, expr);
 
+  exprv = expr;
+  while (TREE_CODE (exprv) == COMPOUND_EXPR)
+    exprv = TREE_OPERAND (exprv, 1);
+  if (DECL_P (exprv) || handled_component_p (exprv))
+    mark_exp_read (exprv);
+
   /* 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) || CONSTANT_CLASS_P (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) || CONSTANT_CLASS_P (expr))
     {
-      mark_exp_read (expr);
       expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
       SET_EXPR_LOCATION (expr, loc);
     }
       expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
       SET_EXPR_LOCATION (expr, loc);
     }
@@ -9129,6 +9452,10 @@ build_binary_op (location_t location, enum tree_code code,
      precision.  */
   bool may_need_excess_precision;
 
      precision.  */
   bool may_need_excess_precision;
 
+  /* True means this is a boolean operation that converts both its
+     operands to truth-values.  */
+  bool boolean_op = false;
+
   if (location == UNKNOWN_LOCATION)
     location = input_location;
 
   if (location == UNKNOWN_LOCATION)
     location = input_location;
 
@@ -9356,6 +9683,7 @@ build_binary_op (location_t location, enum tree_code code,
          op0 = c_common_truthvalue_conversion (location, op0);
          op1 = c_common_truthvalue_conversion (location, op1);
          converted = 1;
          op0 = c_common_truthvalue_conversion (location, op0);
          op1 = c_common_truthvalue_conversion (location, op1);
          converted = 1;
+         boolean_op = true;
        }
       if (code == TRUTH_ANDIF_EXPR)
        {
        }
       if (code == TRUTH_ANDIF_EXPR)
        {
@@ -9386,7 +9714,21 @@ build_binary_op (location_t location, enum tree_code code,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9413,9 +9755,10 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
 
          /* 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)
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9423,7 +9766,21 @@ build_binary_op (location_t location, enum tree_code code,
       break;
 
     case LSHIFT_EXPR:
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9445,9 +9802,10 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
 
          /* 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)
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9468,6 +9826,46 @@ build_binary_op (location_t location, enum tree_code code,
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
        short_compare = 1;
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
        short_compare = 1;
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+       {
+         if (TREE_CODE (op0) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+           }
+         result_type = type0;
+       }
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+       {
+         if (TREE_CODE (op1) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress, 
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+           }
+         result_type = type1;
+       }
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
          tree tt0 = TREE_TYPE (type0);
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
          tree tt0 = TREE_TYPE (type0);
@@ -9481,10 +9879,6 @@ build_binary_op (location_t location, enum tree_code code,
             and both must be object or both incomplete.  */
          if (comp_target_types (location, type0, type1))
            result_type = common_pointer_type (type0, type1);
             and both must be object or both incomplete.  */
          if (comp_target_types (location, type0, type1))
            result_type = common_pointer_type (type0, type1);
-         else if (null_pointer_constant_p (orig_op0))
-           result_type = type1;
-         else if (null_pointer_constant_p (orig_op1))
-           result_type = type0;
          else if (!addr_space_superset (as0, as1, &as_common))
            {
              error_at (location, "comparison of pointers to "
          else if (!addr_space_superset (as0, as1, &as_common))
            {
              error_at (location, "comparison of pointers to "
@@ -9516,24 +9910,6 @@ build_binary_op (location_t location, enum tree_code code,
                              (build_qualified_type (void_type_node, qual));
            }
        }
                              (build_qualified_type (void_type_node, qual));
            }
        }
-      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
-       {
-         if (TREE_CODE (op0) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
-           warning_at (location,
-                       OPT_Waddress, "the address of %qD will never be NULL",
-                       TREE_OPERAND (op0, 0));
-         result_type = type0;
-       }
-      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
-       {
-         if (TREE_CODE (op1) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
-           warning_at (location,
-                       OPT_Waddress, "the address of %qD will never be NULL",
-                       TREE_OPERAND (op1, 0));
-         result_type = type1;
-       }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          result_type = type0;
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          result_type = type0;
@@ -9572,6 +9948,11 @@ build_binary_op (location_t location, enum tree_code code,
              else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "ordered comparisons of pointers to functions");
              else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "ordered comparisons of pointers to functions");
+             else if (null_pointer_constant_p (orig_op0)
+                      || null_pointer_constant_p (orig_op1))
+               warning_at (location, OPT_Wextra,
+                           "ordered comparison of pointer with null pointer");
+
            }
          else if (!addr_space_superset (as0, as1, &as_common))
            {
            }
          else if (!addr_space_superset (as0, as1, &as_common))
            {
@@ -9596,13 +9977,17 @@ build_binary_op (location_t location, enum tree_code code,
                     "ordered comparison of pointer with integer zero");
          else if (extra_warnings)
            warning_at (location, OPT_Wextra,
                     "ordered comparison of pointer with integer zero");
          else if (extra_warnings)
            warning_at (location, OPT_Wextra,
-                    "ordered comparison of pointer with integer zero");
+                       "ordered comparison of pointer with integer zero");
        }
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
        }
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
-         pedwarn (location, OPT_pedantic,
-                  "ordered comparison of pointer with integer zero");
+         if (pedantic)
+           pedwarn (location, OPT_pedantic,
+                    "ordered comparison of pointer with integer zero");
+         else if (extra_warnings)
+           warning_at (location, OPT_Wextra,
+                       "ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -9645,6 +10030,11 @@ build_binary_op (location_t location, enum tree_code code,
       if (shorten || common || short_compare)
        {
          result_type = c_common_type (type0, type1);
       if (shorten || common || short_compare)
        {
          result_type = c_common_type (type0, type1);
+         do_warn_double_promotion (result_type, type0, type1,
+                                   "implicit conversion from %qT to %qT "
+                                   "to match other operand of binary "
+                                   "expression",
+                                   location);
          if (result_type == error_mark_node)
            return error_mark_node;
        }
          if (result_type == error_mark_node)
            return error_mark_node;
        }
@@ -9866,7 +10256,8 @@ build_binary_op (location_t location, enum tree_code code,
   if (build_type == NULL_TREE)
     {
       build_type = result_type;
   if (build_type == NULL_TREE)
     {
       build_type = result_type;
-      if (type0 != orig_type0 || type1 != orig_type1)
+      if ((type0 != orig_type0 || type1 != orig_type1)
+         && !boolean_op)
        {
          gcc_assert (may_need_excess_precision && common);
          semantic_result_type = c_common_type (orig_type0, orig_type1);
        {
          gcc_assert (may_need_excess_precision && common);
          semantic_result_type = c_common_type (orig_type0, orig_type1);