OSDN Git Service

gcc/fortran:
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 80259cc..2151f97 100644 (file)
@@ -1,6 +1,7 @@
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -74,6 +75,7 @@ static int missing_braces_mentioned;
 static int require_constant_value;
 static int require_constant_elements;
 
 static int require_constant_value;
 static int require_constant_elements;
 
+static bool null_pointer_constant_p (tree);
 static tree qualify_type (tree, tree);
 static int tagged_types_tu_compatible_p (tree, tree);
 static int comp_target_types (tree, tree);
 static tree qualify_type (tree, tree);
 static int tagged_types_tu_compatible_p (tree, tree);
 static int comp_target_types (tree, tree);
@@ -81,14 +83,13 @@ static int function_types_compatible_p (tree, tree);
 static int type_lists_compatible_p (tree, tree);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree lookup_field (tree, tree);
 static int type_lists_compatible_p (tree, tree);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree lookup_field (tree, tree);
-static tree convert_arguments (tree, tree, tree, tree);
+static int convert_arguments (int, tree *, tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
 static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
                                    int);
 static tree valid_compound_expr_initializer (tree, tree);
 static void push_string (const char *);
 static void push_member_name (tree);
 static tree pointer_diff (tree, tree);
 static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
                                    int);
 static tree valid_compound_expr_initializer (tree, tree);
 static void push_string (const char *);
 static void push_member_name (tree);
-static void push_array_bounds (int);
 static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (const char *);
 static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (const char *);
@@ -106,6 +107,23 @@ static int lvalue_or_else (tree, enum lvalue_use);
 static int lvalue_p (tree);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (tree, tree);
 static int lvalue_p (tree);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (tree, tree);
+\f
+/* Return true if EXP is a null pointer constant, false otherwise.  */
+
+static bool
+null_pointer_constant_p (tree expr)
+{
+  /* This should really operate on c_expr structures, but they aren't
+     yet available everywhere required.  */
+  tree type = TREE_TYPE (expr);
+  return (TREE_CODE (expr) == INTEGER_CST
+         && !TREE_OVERFLOW (expr)
+         && integer_zerop (expr)
+         && (INTEGRAL_TYPE_P (type)
+             || (TREE_CODE (type) == POINTER_TYPE
+                 && VOID_TYPE_P (TREE_TYPE (type))
+                 && TYPE_QUALS (TREE_TYPE (type)) == TYPE_UNQUALIFIED)));
+}
 \f/* This is a cache to hold if two types are compatible or not.  */
 
 struct tagged_tu_seen_cache {
 \f/* This is a cache to hold if two types are compatible or not.  */
 
 struct tagged_tu_seen_cache {
@@ -218,8 +236,8 @@ c_type_promotes_to (tree type)
     {
       /* Preserve unsignedness if not really getting any wider.  */
       if (TYPE_UNSIGNED (type)
     {
       /* Preserve unsignedness if not really getting any wider.  */
       if (TYPE_UNSIGNED (type)
-          && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
-        return unsigned_type_node;
+         && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+       return unsigned_type_node;
       return integer_type_node;
     }
 
       return integer_type_node;
     }
 
@@ -235,6 +253,17 @@ qualify_type (tree type, tree like)
   return c_build_qualified_type (type,
                                 TYPE_QUALS (type) | TYPE_QUALS (like));
 }
   return c_build_qualified_type (type,
                                 TYPE_QUALS (type) | TYPE_QUALS (like));
 }
+
+/* Return true iff the given tree T is a variable length array.  */
+
+bool
+c_vla_type_p (tree t)
+{
+  if (TREE_CODE (t) == ARRAY_TYPE
+      && C_TYPE_VARIABLE_SIZE (t))
+    return true;
+  return false;
+}
 \f
 /* Return the composite type of two compatible types.
 
 \f
 /* Return the composite type of two compatible types.
 
@@ -302,7 +331,7 @@ composite_type (tree t1, tree t2)
 
        /* We should not have any type quals on arrays at all.  */
        gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
 
        /* We should not have any type quals on arrays at all.  */
        gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
-       
+
        d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1);
        d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2);
 
        d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1);
        d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2);
 
@@ -312,6 +341,8 @@ composite_type (tree t1, tree t2)
        d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
        d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
+       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
 
        /* Save space: see if the result is identical to one of the args.  */
        if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
 
        /* Save space: see if the result is identical to one of the args.  */
        if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
@@ -320,12 +351,12 @@ composite_type (tree t1, tree t2)
        if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
            && (d1_variable || d1_zero || !d2_variable))
          return build_type_attribute_variant (t2, attributes);
        if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
            && (d1_variable || d1_zero || !d2_variable))
          return build_type_attribute_variant (t2, attributes);
-       
+
        if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t1, attributes);
        if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t2, attributes);
        if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t1, attributes);
        if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t2, attributes);
-       
+
        /* Merge the element types, and have a size if either arg has
           one.  We may have qualifiers on the element types.  To set
           up TYPE_MAIN_VARIANT correctly, we need to form the
        /* Merge the element types, and have a size if either arg has
           one.  We may have qualifiers on the element types.  To set
           up TYPE_MAIN_VARIANT correctly, we need to form the
@@ -344,6 +375,19 @@ composite_type (tree t1, tree t2)
        return build_type_attribute_variant (t1, attributes);
       }
 
        return build_type_attribute_variant (t1, attributes);
       }
 
+    case ENUMERAL_TYPE:
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (attributes != NULL)
+       {
+         /* Try harder not to create a new aggregate type.  */
+         if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
+           return t1;
+         if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
+           return t2;
+       }
+      return build_type_attribute_variant (t1, attributes);
+
     case FUNCTION_TYPE:
       /* Function types: prefer the one that specified arg types.
         If both do, merge the arg types.  Also merge the return types.  */
     case FUNCTION_TYPE:
       /* Function types: prefer the one that specified arg types.
         If both do, merge the arg types.  Also merge the return types.  */
@@ -499,7 +543,7 @@ common_pointer_type (tree t1, tree t2)
     return t1;
 
   gcc_assert (TREE_CODE (t1) == POINTER_TYPE
     return t1;
 
   gcc_assert (TREE_CODE (t1) == POINTER_TYPE
-             && TREE_CODE (t2) == POINTER_TYPE);
+             && TREE_CODE (t2) == POINTER_TYPE);
 
   /* Merge the attributes.  */
   attributes = targetm.merge_type_attributes (t1, t2);
 
   /* Merge the attributes.  */
   attributes = targetm.merge_type_attributes (t1, t2);
@@ -565,6 +609,29 @@ c_common_type (tree t1, tree t2)
   gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
              || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
 
   gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
              || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
 
+  /* When one operand is a decimal float type, the other operand cannot be
+     a generic float type or a complex type.  We also disallow vector types
+     here.  */
+  if ((DECIMAL_FLOAT_TYPE_P (t1) || DECIMAL_FLOAT_TYPE_P (t2))
+      && !(DECIMAL_FLOAT_TYPE_P (t1) && DECIMAL_FLOAT_TYPE_P (t2)))
+    {
+      if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and vector types");
+         return error_mark_node;
+       }
+      if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and complex types");
+         return error_mark_node;
+       }
+      if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and other float types");
+         return error_mark_node;
+       }
+    }
+
   /* If one type is a vector type, return that type.  (How the usual
      arithmetic conversions apply to the vector types extension is not
      precisely specified.)  */
   /* If one type is a vector type, return that type.  (How the usual
      arithmetic conversions apply to the vector types extension is not
      precisely specified.)  */
@@ -599,6 +666,22 @@ c_common_type (tree t1, tree t2)
   if (code2 == REAL_TYPE && code1 != REAL_TYPE)
     return t2;
 
   if (code2 == REAL_TYPE && code1 != REAL_TYPE)
     return t2;
 
+  /* If both are real and either are decimal floating point types, use
+     the decimal floating point type with the greater precision. */
+
+  if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+    {
+      if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node
+         || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node)
+       return dfloat128_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node)
+       return dfloat64_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node)
+       return dfloat32_type_node;
+    }
+
   /* Both real or both integers; use the one with greater precision.  */
 
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
   /* Both real or both integers; use the one with greater precision.  */
 
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
@@ -620,7 +703,7 @@ c_common_type (tree t1, tree t2)
       if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
        return long_long_unsigned_type_node;
       else
       if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
        return long_long_unsigned_type_node;
       else
-        return long_long_integer_type_node;
+       return long_long_integer_type_node;
     }
 
   if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
     }
 
   if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
@@ -690,9 +773,10 @@ comptypes (tree type1, tree type2)
 
   val = comptypes_internal (type1, type2);
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   val = comptypes_internal (type1, type2);
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
-  
+
   return val;
   return val;
-}\f
+}
+\f
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  This
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  This
@@ -800,6 +884,8 @@ comptypes_internal (tree type1, tree type2)
        d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
        d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
+       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
 
        if (d1_variable || d2_variable)
          break;
 
        if (d1_variable || d2_variable)
          break;
@@ -810,14 +896,21 @@ comptypes_internal (tree type1, tree type2)
            || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
          val = 0;
 
            || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
          val = 0;
 
-        break;
+       break;
       }
 
     case ENUMERAL_TYPE:
     case RECORD_TYPE:
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
       }
 
     case ENUMERAL_TYPE:
     case RECORD_TYPE:
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
-        {
+       {
+         tree a1 = TYPE_ATTRIBUTES (t1);
+         tree a2 = TYPE_ATTRIBUTES (t2);
+
+         if (! attribute_list_contained (a1, a2)
+             && ! attribute_list_contained (a2, a1))
+           break;
+
          if (attrval != 2)
            return tagged_types_tu_compatible_p (t1, t2);
          val = tagged_types_tu_compatible_p (t1, t2);
          if (attrval != 2)
            return tagged_types_tu_compatible_p (t1, t2);
          val = tagged_types_tu_compatible_p (t1, t2);
@@ -900,13 +993,13 @@ same_translation_unit_p (tree t1, tree t2)
 static struct tagged_tu_seen_cache *
 alloc_tagged_tu_seen_cache (tree t1, tree t2)
 {
 static struct tagged_tu_seen_cache *
 alloc_tagged_tu_seen_cache (tree t1, tree t2)
 {
-  struct tagged_tu_seen_cache *tu = xmalloc (sizeof (struct tagged_tu_seen_cache));
+  struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
   tu->next = tagged_tu_seen_base;
   tu->t1 = t1;
   tu->t2 = t2;
   tu->next = tagged_tu_seen_base;
   tu->t1 = t1;
   tu->t2 = t2;
-  
+
   tagged_tu_seen_base = tu;
   tagged_tu_seen_base = tu;
-  
+
   /* The C standard says that two structures in different translation
      units are compatible with each other only if the types of their
      fields are compatible (among other things).  We assume that they
   /* The C standard says that two structures in different translation
      units are compatible with each other only if the types of their
      fields are compatible (among other things).  We assume that they
@@ -989,31 +1082,31 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
     case ENUMERAL_TYPE:
       {
        struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
     case ENUMERAL_TYPE:
       {
        struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
-        /* Speed up the case where the type values are in the same order.  */
-        tree tv1 = TYPE_VALUES (t1);
-        tree tv2 = TYPE_VALUES (t2);
+       /* Speed up the case where the type values are in the same order.  */
+       tree tv1 = TYPE_VALUES (t1);
+       tree tv2 = TYPE_VALUES (t2);
 
 
-        if (tv1 == tv2)
+       if (tv1 == tv2)
          {
            return 1;
          }
 
          {
            return 1;
          }
 
-        for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
-          {
-            if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
-              break;
-            if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
+       for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
+         {
+           if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
+             break;
+           if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
              {
              {
-               tu->val = 0;
+               tu->val = 0;
                return 0;
              }
                return 0;
              }
-          }
+         }
 
 
-        if (tv1 == NULL_TREE && tv2 == NULL_TREE)
+       if (tv1 == NULL_TREE && tv2 == NULL_TREE)
          {
            return 1;
          }
          {
            return 1;
          }
-        if (tv1 == NULL_TREE || tv2 == NULL_TREE)
+       if (tv1 == NULL_TREE || tv2 == NULL_TREE)
          {
            tu->val = 0;
            return 0;
          {
            tu->val = 0;
            return 0;
@@ -1046,16 +1139,16 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
            tu->val = 0;
            return 0;
          }
            tu->val = 0;
            return 0;
          }
-       
+
        /*  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))
          {
            int result;
        /*  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))
          {
            int result;
-           
-           
+
+
            if (DECL_NAME (s1) == NULL
            if (DECL_NAME (s1) == NULL
-               || DECL_NAME (s1) != DECL_NAME (s2))
+               || DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
            if (result == 0)
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
            if (result == 0)
@@ -1118,7 +1211,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
 
     case RECORD_TYPE:
       {
 
     case RECORD_TYPE:
       {
-        struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
+       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
@@ -1467,7 +1560,8 @@ default_function_array_conversion (struct c_expr exp)
        bool lvalue_array_p;
 
        while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
        bool lvalue_array_p;
 
        while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
-               || TREE_CODE (exp.value) == NOP_EXPR)
+               || TREE_CODE (exp.value) == NOP_EXPR
+               || TREE_CODE (exp.value) == CONVERT_EXPR)
               && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
          {
            if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
               && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
          {
            if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
@@ -1735,11 +1829,17 @@ build_component_ref (tree datum, tree component)
       do
        {
          tree subdatum = TREE_VALUE (field);
       do
        {
          tree subdatum = TREE_VALUE (field);
+         int quals;
+         tree subtype;
 
          if (TREE_TYPE (subdatum) == error_mark_node)
            return error_mark_node;
 
 
          if (TREE_TYPE (subdatum) == error_mark_node)
            return error_mark_node;
 
-         ref = build3 (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum,
+         quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum)));
+         quals |= TYPE_QUALS (TREE_TYPE (datum));
+         subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals);
+
+         ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
                        NULL_TREE);
          if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
                        NULL_TREE);
          if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
@@ -1776,6 +1876,19 @@ build_indirect_ref (tree ptr, const char *errorstring)
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
+      if (TREE_CODE (pointer) == CONVERT_EXPR
+          || TREE_CODE (pointer) == NOP_EXPR
+          || TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
+       {
+         /* If a warning is issued, mark it to avoid duplicates from
+            the backend.  This only needs to be done at
+            warn_strict_aliasing > 2.  */
+         if (warn_strict_aliasing > 2)
+           if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)),
+                                        type, TREE_OPERAND (pointer, 0)))
+             TREE_NO_WARNING (pointer) = 1;
+       }
+
       if (TREE_CODE (pointer) == ADDR_EXPR
          && (TREE_TYPE (TREE_OPERAND (pointer, 0))
              == TREE_TYPE (type)))
       if (TREE_CODE (pointer) == ADDR_EXPR
          && (TREE_TYPE (TREE_OPERAND (pointer, 0))
              == TREE_TYPE (type)))
@@ -1810,7 +1923,7 @@ build_indirect_ref (tree ptr, const char *errorstring)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    error ("invalid type argument of %qs", errorstring);
+    error ("invalid type argument of %qs (have %qT)", errorstring, type);
   return error_mark_node;
 }
 
   return error_mark_node;
 }
 
@@ -1859,16 +1972,10 @@ build_array_ref (tree array, tree index)
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
-  /* Subscripting with type char is likely to lose on a machine where
-     chars are signed.  So warn on any machine, but optionally.  Don't
-     warn for unsigned char since that type is safe.  Don't warn for
-     signed char because anyone who uses that must have done so
-     deliberately.  ??? Existing practice has also been to warn only
-     when the char index is syntactically the index, not for
-     char[array].  */
-  if (!swapped
-      && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-    warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
+  /* ??? Existing practice has been to warn only when the char
+     index is syntactically the index, not for char[array].  */
+  if (!swapped)
+     warn_array_subscript_with_type_char (index);
 
   /* Apply default promotions *after* noticing character types.  */
   index = default_conversion (index);
 
   /* Apply default promotions *after* noticing character types.  */
   index = default_conversion (index);
@@ -1918,7 +2025,7 @@ build_array_ref (tree array, tree index)
        type = TYPE_MAIN_VARIANT (type);
       rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
        type = TYPE_MAIN_VARIANT (type);
       rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
-         or if the array is.  */
+        or if the array is.  */
       TREE_READONLY (rval)
        |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
            | TREE_READONLY (array));
       TREE_READONLY (rval)
        |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
            | TREE_READONLY (array));
@@ -1983,9 +2090,13 @@ build_external_ref (tree id, int fun, location_t loc)
   if (TREE_DEPRECATED (ref))
     warn_deprecated_use (ref);
 
   if (TREE_DEPRECATED (ref))
     warn_deprecated_use (ref);
 
-  if (!skip_evaluation)
-    assemble_external (ref);
-  TREE_USED (ref) = 1;
+  /* Recursive call does not count as usage.  */
+  if (ref != current_function_decl) 
+    {
+      if (!skip_evaluation)
+       assemble_external (ref);
+      TREE_USED (ref) = 1;
+    }
 
   if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
     {
 
   if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
     {
@@ -1999,6 +2110,7 @@ build_external_ref (tree id, int fun, location_t loc)
 
   if (TREE_CODE (ref) == CONST_DECL)
     {
 
   if (TREE_CODE (ref) == CONST_DECL)
     {
+      used_types_insert (TREE_TYPE (ref));
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
       TREE_INVARIANT (ref) = 1;
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
       TREE_INVARIANT (ref) = 1;
@@ -2014,6 +2126,17 @@ build_external_ref (tree id, int fun, location_t loc)
       if (context != 0 && context != current_function_decl)
        DECL_NONLOCAL (ref) = 1;
     }
       if (context != 0 && context != current_function_decl)
        DECL_NONLOCAL (ref) = 1;
     }
+  /* C99 6.7.4p3: An inline definition of a function with external
+     linkage ... shall not contain a reference to an identifier with
+     internal linkage.  */
+  else if (current_function_decl != 0
+          && DECL_DECLARED_INLINE_P (current_function_decl)
+          && DECL_EXTERNAL (current_function_decl)
+          && VAR_OR_FUNCTION_DECL_P (ref)
+          && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
+          && ! TREE_PUBLIC (ref))
+    pedwarn ("%H%qD is static but used in inline function %qD "
+            "which is not static", &loc, ref, current_function_decl);
 
   return ref;
 }
 
   return ref;
 }
@@ -2087,6 +2210,11 @@ c_expr_sizeof_expr (struct c_expr expr)
     {
       ret.value = c_sizeof (TREE_TYPE (expr.value));
       ret.original_code = ERROR_MARK;
     {
       ret.value = c_sizeof (TREE_TYPE (expr.value));
       ret.original_code = ERROR_MARK;
+      if (c_vla_type_p (TREE_TYPE (expr.value)))
+       {
+         /* sizeof is evaluated when given a vla (C99 6.5.3.4p2).  */
+         ret.value = build2 (COMPOUND_EXPR, TREE_TYPE (ret.value), expr.value, ret.value);
+       }
       pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
     }
   return ret;
       pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
     }
   return ret;
@@ -2103,7 +2231,8 @@ c_expr_sizeof_type (struct c_type_name *t)
   type = groktypename (t);
   ret.value = c_sizeof (type);
   ret.original_code = ERROR_MARK;
   type = groktypename (t);
   ret.value = c_sizeof (type);
   ret.original_code = ERROR_MARK;
-  pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+  pop_maybe_used (type != error_mark_node
+                 ? C_TYPE_VARIABLE_SIZE (type) : false);
   return ret;
 }
 
   return ret;
 }
 
@@ -2116,9 +2245,11 @@ tree
 build_function_call (tree function, tree params)
 {
   tree fntype, fundecl = 0;
 build_function_call (tree function, tree params)
 {
   tree fntype, fundecl = 0;
-  tree coerced_params;
   tree name = NULL_TREE, result;
   tree tem;
   tree name = NULL_TREE, result;
   tree tem;
+  int nargs;
+  tree *argarray;
+  
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -2167,7 +2298,8 @@ build_function_call (tree function, tree params)
      expression if necessary.  This has the nice side-effect to prevent
      the tree-inliner from generating invalid assignment trees which may
      blow up in the RTL expander later.  */
      expression if necessary.  This has the nice side-effect to prevent
      the tree-inliner from generating invalid assignment trees which may
      blow up in the RTL expander later.  */
-  if (TREE_CODE (function) == NOP_EXPR
+  if ((TREE_CODE (function) == NOP_EXPR
+       || TREE_CODE (function) == CONVERT_EXPR)
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
       && !comptypes (fntype, TREE_TYPE (tem)))
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
       && !comptypes (fntype, TREE_TYPE (tem)))
@@ -2195,7 +2327,7 @@ build_function_call (tree function, tree params)
            rhs = build_compound_literal (return_type,
                                          build_constructor (return_type, 0));
          else
            rhs = build_compound_literal (return_type,
                                          build_constructor (return_type, 0));
          else
-           rhs = fold_build1 (NOP_EXPR, return_type, integer_zero_node);
+           rhs = fold_convert (return_type, integer_zero_node);
 
          return build2 (COMPOUND_EXPR, return_type, trap, rhs);
        }
 
          return build2 (COMPOUND_EXPR, return_type, trap, rhs);
        }
@@ -2204,30 +2336,30 @@ build_function_call (tree function, tree params)
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
-  coerced_params
-    = convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl);
-
-  if (coerced_params == error_mark_node)
+  nargs = list_length (params);
+  argarray = (tree *) alloca (nargs * sizeof (tree));
+  nargs = convert_arguments (nargs, argarray, TYPE_ARG_TYPES (fntype), 
+                            params, function, fundecl);
+  if (nargs < 0)
     return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
 
     return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
 
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
                            TYPE_ARG_TYPES (fntype));
 
   if (require_constant_value)
     {
                            TYPE_ARG_TYPES (fntype));
 
   if (require_constant_value)
     {
-      result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype),
-                                       function, coerced_params, NULL_TREE);
-
+      result = fold_build_call_array_initializer (TREE_TYPE (fntype),
+                                                 function, nargs, argarray);
       if (TREE_CONSTANT (result)
          && (name == NULL_TREE
              || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
        pedwarn_init ("initializer element is not constant");
     }
   else
       if (TREE_CONSTANT (result)
          && (name == NULL_TREE
              || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
        pedwarn_init ("initializer element is not constant");
     }
   else
-    result = fold_build3 (CALL_EXPR, TREE_TYPE (fntype),
-                         function, coerced_params, NULL_TREE);
+    result = fold_build_call_array (TREE_TYPE (fntype),
+                                   function, nargs, argarray);
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     return result;
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     return result;
@@ -2235,9 +2367,8 @@ build_function_call (tree function, tree params)
 }
 \f
 /* Convert the argument expressions in the list VALUES
 }
 \f
 /* Convert the argument expressions in the list VALUES
-   to the types in the list TYPELIST.  The result is a list of converted
-   argument expressions, unless there are too few arguments in which
-   case it is error_mark_node.
+   to the types in the list TYPELIST.  The resulting arguments are
+   stored in the array ARGARRAY which has size NARGS.
 
    If TYPELIST is exhausted, or when an element has NULL as its type,
    perform the default conversions.
 
    If TYPELIST is exhausted, or when an element has NULL as its type,
    perform the default conversions.
@@ -2251,15 +2382,20 @@ build_function_call (tree function, tree params)
 
    This is also where warnings about wrong number of args are generated.
 
 
    This is also where warnings about wrong number of args are generated.
 
-   Both VALUES and the returned value are chains of TREE_LIST nodes
-   with the elements of the list in the TREE_VALUE slots of those nodes.  */
+   VALUES is a chain of TREE_LIST nodes with the elements of the list
+   in the TREE_VALUE slots of those nodes.
 
 
-static tree
-convert_arguments (tree typelist, tree values, tree function, tree fundecl)
+   Returns the actual number of arguments processed (which may be less
+   than NARGS in some error situations), or -1 on failure.  */
+
+static int
+convert_arguments (int nargs, tree *argarray,
+                  tree typelist, tree values, tree function, tree fundecl)
 {
   tree typetail, valtail;
 {
   tree typetail, valtail;
-  tree result = NULL;
   int parmnum;
   int parmnum;
+  const bool type_generic = fundecl
+    && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   tree selector;
 
   /* Change pointer to function to the function itself for
   tree selector;
 
   /* Change pointer to function to the function itself for
@@ -2272,7 +2408,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
   selector = objc_message_selector ();
 
   /* Scan the given expressions and types, producing individual
   selector = objc_message_selector ();
 
   /* Scan the given expressions and types, producing individual
-     converted arguments and pushing them on RESULT in reverse order.  */
+     converted arguments and storing them in ARGARRAY.  */
 
   for (valtail = values, typetail = typelist, parmnum = 0;
        valtail;
 
   for (valtail = values, typetail = typelist, parmnum = 0;
        valtail;
@@ -2287,7 +2423,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
       if (type == void_type_node)
        {
          error ("too many arguments to function %qE", function);
       if (type == void_type_node)
        {
          error ("too many arguments to function %qE", function);
-         break;
+         return parmnum;
        }
 
       if (selector && argnum > 2)
        }
 
       if (selector && argnum > 2)
@@ -2314,7 +2450,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
            {
              /* Optionally warn about conversions that
                 differ from the default conversions.  */
            {
              /* Optionally warn about conversions that
                 differ from the default conversions.  */
-             if (warn_conversion || warn_traditional)
+             if (warn_traditional_conversion || warn_traditional)
                {
                  unsigned int formal_prec = TYPE_PRECISION (type);
 
                {
                  unsigned int formal_prec = TYPE_PRECISION (type);
 
@@ -2356,15 +2492,42 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                    {
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
                    {
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
-                     if (formal_prec == TYPE_PRECISION (float_type_node))
+                     if (formal_prec == TYPE_PRECISION (float_type_node)
+                         && type != dfloat32_type_node)
                        warning (0, "passing argument %d of %qE as %<float%> "
                                 "rather than %<double%> due to prototype",
                                 argnum, rname);
                        warning (0, "passing argument %d of %qE as %<float%> "
                                 "rather than %<double%> due to prototype",
                                 argnum, rname);
+
+                     /* Warn if mismatch between argument and prototype
+                        for decimal float types.  Warn of conversions with
+                        binary float types and of precision narrowing due to
+                        prototype. */
+                     else if (type != TREE_TYPE (val)
+                              && (type == dfloat32_type_node
+                                  || type == dfloat64_type_node
+                                  || type == dfloat128_type_node
+                                  || TREE_TYPE (val) == dfloat32_type_node
+                                  || TREE_TYPE (val) == dfloat64_type_node
+                                  || TREE_TYPE (val) == dfloat128_type_node)
+                              && (formal_prec
+                                  <= TYPE_PRECISION (TREE_TYPE (val))
+                                  || (type == dfloat128_type_node
+                                      && (TREE_TYPE (val)
+                                          != dfloat64_type_node
+                                          && (TREE_TYPE (val)
+                                              != dfloat32_type_node)))
+                                  || (type == dfloat64_type_node
+                                      && (TREE_TYPE (val)
+                                          != dfloat32_type_node))))
+                       warning (0, "passing argument %d of %qE as %qT "
+                                "rather than %qT due to prototype",
+                                argnum, rname, type, TREE_TYPE (val));
+
                    }
                  /* Detect integer changing in width or signedness.
                     These warnings are only activated with
                    }
                  /* Detect integer changing in width or signedness.
                     These warnings are only activated with
-                    -Wconversion, not with -Wtraditional.  */
-                 else if (warn_conversion && INTEGRAL_TYPE_P (type)
+                    -Wtraditional-conversion, not with -Wtraditional.  */
+                 else if (warn_traditional_conversion && INTEGRAL_TYPE_P (type)
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                    {
                      tree would_have_been = default_conversion (val);
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                    {
                      tree would_have_been = default_conversion (val);
@@ -2377,7 +2540,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
-                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                       warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
                                 "with different width due to prototype",
                                 argnum, rname);
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
                                 "with different width due to prototype",
                                 argnum, rname);
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
@@ -2400,11 +2563,11 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                               && TYPE_UNSIGNED (TREE_TYPE (val)))
                        ;
                      else if (TYPE_UNSIGNED (type))
                               && TYPE_UNSIGNED (TREE_TYPE (val)))
                        ;
                      else if (TYPE_UNSIGNED (type))
-                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                       warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
                                 "as unsigned due to prototype",
                                 argnum, rname);
                      else
                                 "as unsigned due to prototype",
                                 argnum, rname);
                      else
-                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                       warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
                                 "as signed due to prototype", argnum, rname);
                    }
                }
                                 "as signed due to prototype", argnum, rname);
                    }
                }
@@ -2418,34 +2581,42 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
-         result = tree_cons (NULL_TREE, parmval, result);
+         argarray[parmnum] = parmval;
        }
       else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
        }
       else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
-               && (TYPE_PRECISION (TREE_TYPE (val))
-                  < TYPE_PRECISION (double_type_node)))
-       /* Convert `float' to `double'.  */
-       result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
-      else if ((invalid_func_diag = 
-               targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
+              && (TYPE_PRECISION (TREE_TYPE (val))
+                  < TYPE_PRECISION (double_type_node))
+              && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
+        {
+         if (type_generic)
+           argarray[parmnum] = val;
+         else
+           /* Convert `float' to `double'.  */
+           argarray[parmnum] = convert (double_type_node, val);
+       }
+      else if ((invalid_func_diag =
+               targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
        {
          error (invalid_func_diag);
        {
          error (invalid_func_diag);
-         return error_mark_node; 
+         return -1;
        }
       else
        /* Convert `short' and `char' to full-size `int'.  */
        }
       else
        /* Convert `short' and `char' to full-size `int'.  */
-       result = tree_cons (NULL_TREE, default_conversion (val), result);
+       argarray[parmnum] = default_conversion (val);
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
     }
 
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
     }
 
+  gcc_assert (parmnum == nargs);
+
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
       error ("too few arguments to function %qE", function);
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
       error ("too few arguments to function %qE", function);
-      return error_mark_node;
+      return -1;
     }
 
     }
 
-  return nreverse (result);
+  return parmnum;
 }
 \f
 /* This is the entry point used by the parser to build unary operators
 }
 \f
 /* This is the entry point used by the parser to build unary operators
@@ -2460,7 +2631,10 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg)
 
   result.original_code = ERROR_MARK;
   result.value = build_unary_op (code, arg.value, 0);
 
   result.original_code = ERROR_MARK;
   result.value = build_unary_op (code, arg.value, 0);
-  overflow_warning (result.value);
+  
+  if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
+    overflow_warning (result.value);
+
   return result;
 }
 
   return result;
 }
 
@@ -2488,77 +2662,27 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
   /* Check for cases such as x+y<<z which users are likely
      to misinterpret.  */
   if (warn_parentheses)
   /* Check for cases such as x+y<<z which users are likely
      to misinterpret.  */
   if (warn_parentheses)
-    {
-      if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
-       {
-         if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
-             || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around + or - inside shift");
-       }
-
-      if (code == TRUTH_ORIF_EXPR)
-       {
-         if (code1 == TRUTH_ANDIF_EXPR
-             || code2 == TRUTH_ANDIF_EXPR)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around && within ||");
-       }
-
-      if (code == BIT_IOR_EXPR)
-       {
-         if (code1 == BIT_AND_EXPR || code1 == BIT_XOR_EXPR
-             || code1 == PLUS_EXPR || code1 == MINUS_EXPR
-             || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
-             || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around arithmetic in operand of |");
-         /* Check cases like x|y==z */
-         if (TREE_CODE_CLASS (code1) == tcc_comparison
-             || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around comparison in operand of |");
-       }
-
-      if (code == BIT_XOR_EXPR)
-       {
-         if (code1 == BIT_AND_EXPR
-             || code1 == PLUS_EXPR || code1 == MINUS_EXPR
-             || code2 == BIT_AND_EXPR
-             || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around arithmetic in operand of ^");
-         /* Check cases like x^y==z */
-         if (TREE_CODE_CLASS (code1) == tcc_comparison
-             || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around comparison in operand of ^");
-       }
+    warn_about_parentheses (code, code1, code2);
 
 
-      if (code == BIT_AND_EXPR)
-       {
-         if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
-             || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around + or - in operand of &");
-         /* Check cases like x&y==z */
-         if (TREE_CODE_CLASS (code1) == tcc_comparison
-             || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning (OPT_Wparentheses,
-                    "suggest parentheses around comparison in operand of &");
-       }
-      /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
-      if (TREE_CODE_CLASS (code) == tcc_comparison
-         && (TREE_CODE_CLASS (code1) == tcc_comparison
-             || TREE_CODE_CLASS (code2) == tcc_comparison))
-       warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
-                "have their mathematical meaning");
+  if (code1 != tcc_comparison)
+    warn_logical_operator (code, arg1.value, arg2.value);
 
 
+  /* Warn about comparisons against string literals, with the exception
+     of testing for equality or inequality of a string literal with NULL.  */
+  if (code == EQ_EXPR || code == NE_EXPR)
+    {
+      if ((code1 == STRING_CST && !integer_zerop (arg2.value))
+         || (code2 == STRING_CST && !integer_zerop (arg1.value)))
+       warning (OPT_Waddress, "comparison with string literal results in unspecified behavior");
     }
     }
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
+          && (code1 == STRING_CST || code2 == STRING_CST))
+    warning (OPT_Waddress, "comparison with string literal results in unspecified behavior");
 
 
-  unsigned_conversion_warning (result.value, arg1.value);
-  unsigned_conversion_warning (result.value, arg2.value);
-  overflow_warning (result.value);
+  if (TREE_OVERFLOW_P (result.value) 
+      && !TREE_OVERFLOW_P (arg1.value) 
+      && !TREE_OVERFLOW_P (arg2.value))
+    overflow_warning (result.value);
 
   return result;
 }
 
   return result;
 }
@@ -2591,8 +2715,18 @@ pointer_diff (tree op0, tree op1)
      different mode in place.)
      So first try to find a common term here 'by hand'; we want to cover
      at least the cases that occur in legal static initializers.  */
      different mode in place.)
      So first try to find a common term here 'by hand'; we want to cover
      at least the cases that occur in legal static initializers.  */
-  con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0;
-  con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1;
+  if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR)
+      && (TYPE_PRECISION (TREE_TYPE (op0))
+         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
+    con0 = TREE_OPERAND (op0, 0);
+  else
+    con0 = op0;
+  if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR)
+      && (TYPE_PRECISION (TREE_TYPE (op1))
+         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
+    con1 = TREE_OPERAND (op1, 0);
+  else
+    con1 = op1;
 
   if (TREE_CODE (con0) == PLUS_EXPR)
     {
 
   if (TREE_CODE (con0) == PLUS_EXPR)
     {
@@ -2751,9 +2885,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       arg = c_objc_common_truthvalue_conversion (arg);
       return invert_truthvalue (arg);
 
       arg = c_objc_common_truthvalue_conversion (arg);
       return invert_truthvalue (arg);
 
-    case NOP_EXPR:
-      break;
-
     case REALPART_EXPR:
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_REALPART (arg);
     case REALPART_EXPR:
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_REALPART (arg);
@@ -2788,8 +2919,11 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          arg = stabilize_reference (arg);
          real = build_unary_op (REALPART_EXPR, arg, 1);
          imag = build_unary_op (IMAGPART_EXPR, arg, 1);
          arg = stabilize_reference (arg);
          real = build_unary_op (REALPART_EXPR, arg, 1);
          imag = build_unary_op (IMAGPART_EXPR, arg, 1);
+         real = build_unary_op (code, real, 1);
+         if (real == error_mark_node || imag == error_mark_node)
+           return error_mark_node;
          return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
          return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
-                        build_unary_op (code, real, 1), imag);
+                        real, imag);
        }
 
       /* Report invalid types.  */
        }
 
       /* Report invalid types.  */
@@ -2798,9 +2932,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
          if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
          if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-            error ("wrong type argument to increment");
-          else
-            error ("wrong type argument to decrement");
+           error ("wrong type argument to increment");
+         else
+           error ("wrong type argument to decrement");
 
          return error_mark_node;
        }
 
          return error_mark_node;
        }
@@ -2828,7 +2962,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
            else if ((pedantic || warn_pointer_arith)
                     && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
                         || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
            else if ((pedantic || warn_pointer_arith)
                     && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
                         || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
-              {
+             {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
                  pedwarn ("wrong type argument to increment");
                else
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
                  pedwarn ("wrong type argument to increment");
                else
@@ -2836,11 +2970,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
              }
 
            inc = c_size_in_bytes (TREE_TYPE (result_type));
              }
 
            inc = c_size_in_bytes (TREE_TYPE (result_type));
+           inc = fold_convert (sizetype, inc);
          }
        else
          }
        else
-         inc = integer_one_node;
-
-       inc = convert (argtype, inc);
+         {
+           inc = integer_one_node;
+           inc = convert (argtype, inc);
+         }
 
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
 
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
@@ -2851,10 +2987,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
        /* Report a read-only lvalue.  */
        if (TREE_READONLY (arg))
 
        /* Report a read-only lvalue.  */
        if (TREE_READONLY (arg))
-         readonly_error (arg,
-                         ((code == PREINCREMENT_EXPR
-                           || code == POSTINCREMENT_EXPR)
-                          ? lv_increment : lv_decrement));
+         {
+           readonly_error (arg,
+                           ((code == PREINCREMENT_EXPR
+                             || code == POSTINCREMENT_EXPR)
+                            ? lv_increment : lv_decrement));
+           return error_mark_node;
+         }
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
@@ -2902,7 +3041,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       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
+        to which the address will point.  Note that you can't get a
         restricted pointer by taking the address of something, so we
         only have to deal with `const' and `volatile' here.  */
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
         restricted pointer by taking the address of something, so we
         only have to deal with `const' and `volatile' here.  */
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
@@ -2923,21 +3062,26 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
         when we have proper support for integer constant expressions.  */
       val = get_base_address (arg);
       if (val && TREE_CODE (val) == INDIRECT_REF
         when we have proper support for integer constant expressions.  */
       val = get_base_address (arg);
       if (val && TREE_CODE (val) == INDIRECT_REF
-         && integer_zerop (TREE_OPERAND (val, 0)))
-       return fold_convert (argtype, fold_offsetof (arg));
+          && TREE_CONSTANT (TREE_OPERAND (val, 0)))
+       {
+         tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
+
+         op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
+         return fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+       }
 
       val = build1 (ADDR_EXPR, argtype, arg);
 
       return val;
 
     default:
 
       val = build1 (ADDR_EXPR, argtype, arg);
 
       return val;
 
     default:
-      break;
+      gcc_unreachable ();
     }
 
   if (argtype == 0)
     argtype = TREE_TYPE (arg);
   return require_constant_value ? fold_build1_initializer (code, argtype, arg)
     }
 
   if (argtype == 0)
     argtype = TREE_TYPE (arg);
   return require_constant_value ? fold_build1_initializer (code, argtype, arg)
-                               : fold_build1 (code, argtype, arg);
+                               : fold_build1 (code, argtype, arg);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language.
 }
 
 /* Return nonzero if REF is an lvalue valid for this language.
@@ -2988,7 +3132,7 @@ readonly_error (tree arg, enum lvalue_use use)
      ensures that all the format strings are checked at compile
      time.  */
 #define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A)              \
      ensures that all the format strings are checked at compile
      time.  */
 #define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A)              \
-                                  : (use == lv_increment ? (I)         \
+                                  : (use == lv_increment ? (I)         \
                                   : (use == lv_decrement ? (D) : (AS))))
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
                                   : (use == lv_decrement ? (D) : (AS))))
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
@@ -3144,9 +3288,9 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
        result_type = TYPE_MAIN_VARIANT (type1);
     }
   else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
        result_type = TYPE_MAIN_VARIANT (type1);
     }
   else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
-            || code1 == COMPLEX_TYPE)
-           && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
-               || code2 == COMPLEX_TYPE))
+           || code1 == COMPLEX_TYPE)
+          && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
+              || code2 == COMPLEX_TYPE))
     {
       result_type = c_common_type (type1, type2);
 
     {
       result_type = c_common_type (type1, type2);
 
@@ -3162,6 +3306,8 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
 
          if (unsigned_op1 ^ unsigned_op2)
            {
 
          if (unsigned_op1 ^ unsigned_op2)
            {
+             bool ovf;
+
              /* Do not warn if the result type is signed, since the
                 signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
              /* Do not warn if the result type is signed, since the
                 signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
@@ -3170,8 +3316,10 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
              /* Do not warn if the signed quantity is an unsuffixed
                 integer literal (or some static constant expression
                 involving such literals) and it is non-negative.  */
              /* Do not warn if the signed quantity is an unsuffixed
                 integer literal (or some static constant expression
                 involving such literals) and it is non-negative.  */
-             else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
-                      || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
+             else if ((unsigned_op2
+                       && tree_expr_nonnegative_warnv_p (op1, &ovf))
+                      || (unsigned_op1
+                          && tree_expr_nonnegative_warnv_p (op2, &ovf)))
                /* OK */;
              else
                warning (0, "signed and unsigned type in conditional expression");
                /* OK */;
              else
                warning (0, "signed and unsigned type in conditional expression");
@@ -3188,11 +3336,9 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     {
       if (comp_target_types (type1, type2))
        result_type = common_pointer_type (type1, type2);
     {
       if (comp_target_types (type1, type2))
        result_type = common_pointer_type (type1, type2);
-      else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
-              && TREE_CODE (orig_op1) != NOP_EXPR)
+      else if (null_pointer_constant_p (orig_op1))
        result_type = qualify_type (type2, type1);
        result_type = qualify_type (type2, type1);
-      else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
-              && TREE_CODE (orig_op2) != NOP_EXPR)
+      else if (null_pointer_constant_p (orig_op2))
        result_type = qualify_type (type1, type2);
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
        result_type = qualify_type (type1, type2);
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
@@ -3218,7 +3364,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
     {
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
     {
-      if (!integer_zerop (op2))
+      if (!null_pointer_constant_p (orig_op2))
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
@@ -3228,7 +3374,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     }
   else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
     {
     }
   else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
     {
-      if (!integer_zerop (op1))
+      if (!null_pointer_constant_p (orig_op1))
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
@@ -3271,19 +3417,22 @@ build_compound_expr (tree expr1, tree expr2)
   if (!TREE_SIDE_EFFECTS (expr1))
     {
       /* The left-hand operand of a comma expression is like an expression
   if (!TREE_SIDE_EFFECTS (expr1))
     {
       /* The left-hand operand of a comma expression is like an expression
-         statement: with -Wextra or -Wunused, we should warn if it doesn't have
+        statement: with -Wextra or -Wunused, we should warn if it doesn't have
         any side-effects, unless it was explicitly cast to (void).  */
       if (warn_unused_value)
        {
          if (VOID_TYPE_P (TREE_TYPE (expr1))
         any side-effects, unless it was explicitly cast to (void).  */
       if (warn_unused_value)
        {
          if (VOID_TYPE_P (TREE_TYPE (expr1))
-             && TREE_CODE (expr1) == CONVERT_EXPR)
+             && (TREE_CODE (expr1) == NOP_EXPR
+                 || TREE_CODE (expr1) == CONVERT_EXPR))
            ; /* (void) a, b */
          else if (VOID_TYPE_P (TREE_TYPE (expr1))
                   && TREE_CODE (expr1) == COMPOUND_EXPR
            ; /* (void) a, b */
          else if (VOID_TYPE_P (TREE_TYPE (expr1))
                   && TREE_CODE (expr1) == COMPOUND_EXPR
-                  && TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR)
+                  && (TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR
+                      || TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR))
            ; /* (void) a, (void) b, c */
          else
            ; /* (void) a, (void) b, c */
          else
-           warning (0, "left-hand operand of comma expression has no effect");
+           warning (OPT_Wunused_value, 
+                    "left-hand operand of comma expression has no effect");
        }
     }
 
        }
     }
 
@@ -3294,6 +3443,9 @@ build_compound_expr (tree expr1, tree expr2)
   else if (warn_unused_value)
     warn_if_unused_value (expr1, input_location);
 
   else if (warn_unused_value)
     warn_if_unused_value (expr1, input_location);
 
+  if (expr2 == error_mark_node)
+    return error_mark_node;
+
   return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
 }
 
   return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
 }
 
@@ -3429,8 +3581,12 @@ build_c_cast (tree type, tree expr)
 
       if (TREE_CODE (type) == INTEGER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
 
       if (TREE_CODE (type) == INTEGER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
-         && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
-         && !TREE_CONSTANT (value))
+         && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
+      /* Unlike conversion of integers to pointers, where the
+         warning is disabled for converting constants because
+         of cases such as SIG_*, warn about converting constant
+         pointers to integers. In some cases it may cause unwanted
+         sign extension, and a warning is appropriate.  */
        warning (OPT_Wpointer_to_int_cast,
                 "cast from pointer to integer of different size");
 
        warning (OPT_Wpointer_to_int_cast,
                 "cast from pointer to integer of different size");
 
@@ -3447,33 +3603,8 @@ build_c_cast (tree type, tree expr)
        warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
                 "of different size");
 
        warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
                 "of different size");
 
-      if (flag_strict_aliasing && warn_strict_aliasing
-         && TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE
-         && TREE_CODE (expr) == ADDR_EXPR
-         && (DECL_P (TREE_OPERAND (expr, 0))
-             || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF)
-         && !VOID_TYPE_P (TREE_TYPE (type)))
-       {
-         /* Casting the address of an object to non void pointer. Warn
-            if the cast breaks type based aliasing.  */
-         if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
-           warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
-                    "might break strict-aliasing rules");
-         else
-           {
-             HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
-             HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
-
-             if (!alias_sets_conflict_p (set1, set2))
-               warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
-                        "pointer will break strict-aliasing rules");
-             else if (warn_strict_aliasing > 1
-                      && !alias_sets_might_conflict_p (set1, set2))
-               warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
-                        "pointer might break strict-aliasing rules");
-           }
-       }
+      if (warn_strict_aliasing <= 2)
+        strict_aliasing_warning (otype, type, expr);
 
       /* If pedantic, warn for conversions between function and object
         pointer types, except for converting a null pointer constant
 
       /* If pedantic, warn for conversions between function and object
         pointer types, except for converting a null pointer constant
@@ -3490,8 +3621,7 @@ build_c_cast (tree type, tree expr)
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
-         && !(integer_zerop (value) && TREE_TYPE (otype) == void_type_node
-              && TREE_CODE (expr) != NOP_EXPR))
+         && !null_pointer_constant_p (value))
        pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
 
       ovalue = value;
        pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
 
       ovalue = value;
@@ -3500,15 +3630,16 @@ build_c_cast (tree type, tree expr)
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST)
        {
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST)
        {
-         if (CONSTANT_CLASS_P (ovalue)
-             && (TREE_OVERFLOW (ovalue) || TREE_CONSTANT_OVERFLOW (ovalue)))
+         if (CONSTANT_CLASS_P (ovalue) && TREE_OVERFLOW (ovalue))
            {
            {
-             /* Avoid clobbering a shared constant.  */
-             value = copy_node (value);
-             TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
-             TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+             if (!TREE_OVERFLOW (value))
+               {
+                 /* Avoid clobbering a shared constant.  */
+                 value = copy_node (value);
+                 TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+               }
            }
            }
-         else if (TREE_OVERFLOW (value) || TREE_CONSTANT_OVERFLOW (value))
+         else if (TREE_OVERFLOW (value))
            /* Reset VALUE's overflow flags, ensuring constant sharing.  */
            value = build_int_cst_wide (TREE_TYPE (value),
                                        TREE_INT_CST_LOW (value),
            /* Reset VALUE's overflow flags, ensuring constant sharing.  */
            value = build_int_cst_wide (TREE_TYPE (value),
                                        TREE_INT_CST_LOW (value),
@@ -3539,7 +3670,6 @@ c_cast_expr (struct c_type_name *type_name, tree expr)
 
   return build_c_cast (type, expr);
 }
 
   return build_c_cast (type, expr);
 }
-
 \f
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
 \f
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
@@ -3561,6 +3691,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   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))
+    return error_mark_node;
+
   STRIP_TYPE_NOPS (rhs);
 
   newrhs = rhs;
   STRIP_TYPE_NOPS (rhs);
 
   newrhs = rhs;
@@ -3574,16 +3707,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
-  if (!lvalue_or_else (lhs, lv_assign))
-    return error_mark_node;
-
   /* Give an error for storing in something that is 'const'.  */
 
   if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
   /* Give an error for storing in something that is 'const'.  */
 
   if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
-    readonly_error (lhs, lv_assign);
+    {
+      readonly_error (lhs, lv_assign);
+      return error_mark_node;
+    }
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
@@ -3743,10 +3876,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     }
 
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
     }
 
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
-    {
-      overflow_warning (rhs);
-      return rhs;
-    }
+    return rhs;
 
   if (coder == VOID_TYPE)
     {
 
   if (coder == VOID_TYPE)
     {
@@ -3786,7 +3916,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     }
   /* Some types can interconvert without explicit casts.  */
   else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
     }
   /* Some types can interconvert without explicit casts.  */
   else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
-           && vector_types_convertible_p (type, TREE_TYPE (rhs)))
+          && vector_types_convertible_p (type, TREE_TYPE (rhs), true))
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
@@ -3797,10 +3927,16 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
               || coder == BOOLEAN_TYPE))
     return convert_and_check (type, rhs);
 
               || coder == BOOLEAN_TYPE))
     return convert_and_check (type, rhs);
 
+  /* Aggregates in different TUs might need conversion.  */
+  if ((codel == RECORD_TYPE || codel == UNION_TYPE)
+      && codel == coder
+      && comptypes (type, rhstype))
+    return convert_and_check (type, rhs);
+
   /* Conversion to a transparent union from its member types.
      This applies only to function arguments.  */
   /* Conversion to a transparent union from its member types.
      This applies only to function arguments.  */
-  else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
-          && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
+  if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
+      && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
     {
       tree memb, marginal_memb = NULL_TREE;
 
     {
       tree memb, marginal_memb = NULL_TREE;
 
@@ -3844,9 +3980,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
            }
 
          /* Can convert integer zero to any pointer type.  */
            }
 
          /* Can convert integer zero to any pointer type.  */
-         if (integer_zerop (rhs)
-             || (TREE_CODE (rhs) == NOP_EXPR
-                 && integer_zerop (TREE_OPERAND (rhs, 0))))
+         if (null_pointer_constant_p (rhs))
            {
              rhs = null_pointer_node;
              break;
            {
              rhs = null_pointer_node;
              break;
@@ -3922,26 +4056,26 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
        mvr = TYPE_MAIN_VARIANT (mvr);
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = (targetm.vector_opaque_p (type)
        mvr = TYPE_MAIN_VARIANT (mvr);
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = (targetm.vector_opaque_p (type)
-                           || targetm.vector_opaque_p (rhstype))
-        && TREE_CODE (ttl) == VECTOR_TYPE
-        && TREE_CODE (ttr) == VECTOR_TYPE;
-      
+                          || targetm.vector_opaque_p (rhstype))
+       && TREE_CODE (ttl) == VECTOR_TYPE
+       && TREE_CODE (ttr) == VECTOR_TYPE;
+
       /* C++ does not allow the implicit conversion void* -> T*.  However,
       /* 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
+        for the purpose of reducing the number of false positives, we
+        tolerate the special case of
 
 
-                int *p = NULL;
+               int *p = NULL;
 
 
-         where NULL is typically defined in C to be '(void *) 0'.  */
+        where NULL is typically defined in C to be '(void *) 0'.  */
       if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
       if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
-        warning (OPT_Wc___compat, "request for implicit conversion from "
-                 "%qT to %qT not permitted in C++", rhstype, type);
+       warning (OPT_Wc___compat, "request for implicit conversion from "
+                "%qT to %qT not permitted in C++", rhstype, type);
 
       /* Check if the right-hand side has a format attribute but the
         left-hand side doesn't.  */
       if (warn_missing_format_attribute
          && check_missing_format_attribute (type, rhstype))
 
       /* Check if the right-hand side has a format attribute but the
         left-hand side doesn't.  */
       if (warn_missing_format_attribute
          && check_missing_format_attribute (type, rhstype))
-        {
+       {
          switch (errtype)
          {
          case ic_argpass:
          switch (errtype)
          {
          case ic_argpass:
@@ -3970,7 +4104,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
            gcc_unreachable ();
          }
        }
            gcc_unreachable ();
          }
        }
-      
+
       /* Any non-function converts to a [const][volatile] void *
         and vice versa; otherwise, targets must be the same.
         Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
       /* Any non-function converts to a [const][volatile] void *
         and vice versa; otherwise, targets must be the same.
         Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
@@ -3984,9 +4118,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
              && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
                  ||
                  (VOID_TYPE_P (ttr)
              && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
                  ||
                  (VOID_TYPE_P (ttr)
-                  /* Check TREE_CODE to catch cases like (void *) (char *) 0
-                     which are not ANSI null ptr constants.  */
-                  && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
+                  && !null_pointer_constant_p (rhs)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
            WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of "
                                    "%qE between function pointer "
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
            WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of "
                                    "%qE between function pointer "
@@ -4076,12 +4208,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       /* An explicit constant 0 can convert to a pointer,
         or one that results from arithmetic, even including
         a cast to integer type.  */
       /* An explicit constant 0 can convert to a pointer,
         or one that results from arithmetic, even including
         a cast to integer type.  */
-      if (!(TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs))
-         &&
-         !(TREE_CODE (rhs) == NOP_EXPR
-           && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
-           && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
-           && integer_zerop (TREE_OPERAND (rhs, 0))))
+      if (!null_pointer_constant_p (rhs))
        WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
                                "pointer from integer without a cast"),
                             G_("assignment makes pointer from integer "
        WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
                                "pointer from integer without a cast"),
                             G_("assignment makes pointer from integer "
@@ -4131,31 +4258,6 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
 
   return error_mark_node;
 }
 
   return error_mark_node;
 }
-
-/* Convert VALUE for assignment into inlined parameter PARM.  ARGNUM
-   is used for error and waring reporting and indicates which argument
-   is being processed.  */
-
-tree
-c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
-{
-  tree ret, type;
-
-  /* If FN was prototyped, the value has been converted already
-     in convert_arguments.  */
-  if (!value || TYPE_ARG_TYPES (TREE_TYPE (fn)))
-    return value;
-
-  type = TREE_TYPE (parm);
-  ret = convert_for_assignment (type, value,
-                               ic_argpass_nonproto, fn,
-                               fn, argnum);
-  if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
-      && INTEGRAL_TYPE_P (type)
-      && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
-    ret = default_conversion (ret);
-  return ret;
-}
 \f
 /* If VALUE is a compound expr all of whose expressions are constant, then
    return its value.  Otherwise, return error_mark_node.
 \f
 /* If VALUE is a compound expr all of whose expressions are constant, then
    return its value.  Otherwise, return error_mark_node.
@@ -4211,7 +4313,8 @@ store_init_value (tree decl, tree init)
 
   /* ANSI wants warnings about out-of-range constant initializers.  */
   STRIP_TYPE_NOPS (value);
 
   /* ANSI wants warnings about out-of-range constant initializers.  */
   STRIP_TYPE_NOPS (value);
-  constant_expression_warning (value);
+  if (TREE_STATIC (decl)) 
+    constant_expression_warning (value);
 
   /* Check if we need to set array size from compound literal size.  */
   if (TREE_CODE (type) == ARRAY_TYPE
 
   /* Check if we need to set array size from compound literal size.  */
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -4225,16 +4328,18 @@ store_init_value (tree decl, tree init)
 
       if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
        {
 
       if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
        {
-         tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
+         tree cldecl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
 
 
-         if (TYPE_DOMAIN (TREE_TYPE (decl)))
+         if (TYPE_DOMAIN (TREE_TYPE (cldecl)))
            {
              /* For int foo[] = (int [3]){1}; we need to set array size
                 now since later on array initializer will be just the
                 brace enclosed list of the compound literal.  */
            {
              /* For int foo[] = (int [3]){1}; we need to set array size
                 now since later on array initializer will be just the
                 brace enclosed list of the compound literal.  */
-             TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (decl));
+             type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+             TREE_TYPE (decl) = type;
+             TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
              layout_type (type);
              layout_type (type);
-             layout_decl (decl, 0);
+             layout_decl (cldecl, 0);
            }
        }
     }
            }
        }
     }
@@ -4250,7 +4355,7 @@ struct spelling
   int kind;
   union
     {
   int kind;
   union
     {
-      int i;
+      unsigned HOST_WIDE_INT i;
       const char *s;
     } u;
 };
       const char *s;
     } u;
 };
@@ -4310,7 +4415,7 @@ push_member_name (tree decl)
 /* Push an array bounds on the stack.  Printed as [BOUNDS].  */
 
 static void
 /* Push an array bounds on the stack.  Printed as [BOUNDS].  */
 
 static void
-push_array_bounds (int bounds)
+push_array_bounds (unsigned HOST_WIDE_INT bounds)
 {
   PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
 }
 {
   PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
 }
@@ -4345,7 +4450,7 @@ print_spelling (char *buffer)
   for (p = spelling_base; p < spelling; p++)
     if (p->kind == SPELLING_BOUNDS)
       {
   for (p = spelling_base; p < spelling; p++)
     if (p->kind == SPELLING_BOUNDS)
       {
-       sprintf (d, "[%d]", p->u.i);
+       sprintf (d, "[" HOST_WIDE_INT_PRINT_UNSIGNED "]", p->u.i);
        d += strlen (d);
       }
     else
        d += strlen (d);
       }
     else
@@ -4436,6 +4541,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
   tree inside_init = init;
 
   if (type == error_mark_node
   tree inside_init = init;
 
   if (type == error_mark_node
+      || !init
       || init == error_mark_node
       || TREE_TYPE (init) == error_mark_node)
     return error_mark_node;
       || init == error_mark_node
       || TREE_TYPE (init) == error_mark_node)
     return error_mark_node;
@@ -4516,7 +4622,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
      below and handle as a constructor.  */
   if (code == VECTOR_TYPE
       && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
      below and handle as a constructor.  */
   if (code == VECTOR_TYPE
       && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
-      && vector_types_convertible_p (TREE_TYPE (inside_init), type)
+      && vector_types_convertible_p (TREE_TYPE (inside_init), type, true)
       && TREE_CONSTANT (inside_init))
     {
       if (TREE_CODE (inside_init) == VECTOR_CST
       && TREE_CONSTANT (inside_init))
     {
       if (TREE_CODE (inside_init) == VECTOR_CST
@@ -4580,12 +4686,14 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
           conversion.  */
        inside_init = convert (type, inside_init);
 
           conversion.  */
        inside_init = convert (type, inside_init);
 
-      if (require_constant && !flag_isoc99
+      if (require_constant
+         && (code == VECTOR_TYPE || !flag_isoc99)
          && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
        {
          /* As an extension, allow initializing objects with static storage
             duration with compound literals (which are then treated just as
          && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
        {
          /* As an extension, allow initializing objects with static storage
             duration with compound literals (which are then treated just as
-            the brace enclosed list they contain).  */
+            the brace enclosed list they contain).  Also allow this for
+            vectors, as we can only assign them with compound literals.  */
          tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
          inside_init = DECL_INITIAL (decl);
        }
          tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
          inside_init = DECL_INITIAL (decl);
        }
@@ -4839,7 +4947,7 @@ void
 start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
 {
   const char *locus;
 start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
 {
   const char *locus;
-  struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
+  struct initializer_stack *p = XNEW (struct initializer_stack);
 
   p->decl = constructor_decl;
   p->require_constant_value = require_constant_value;
 
   p->decl = constructor_decl;
   p->require_constant_value = require_constant_value;
@@ -5023,7 +5131,7 @@ really_start_incremental_init (tree type)
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
        build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
        build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
-      constructor_index = convert (bitsizetype, bitsize_zero_node);
+      constructor_index = bitsize_zero_node;
       constructor_unfilled_index = constructor_index;
     }
   else
       constructor_unfilled_index = constructor_index;
     }
   else
@@ -5140,7 +5248,7 @@ push_init_level (int implicit)
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
       constructor_type = TREE_TYPE (constructor_type);
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
       constructor_type = TREE_TYPE (constructor_type);
-      push_array_bounds (tree_low_cst (constructor_index, 0));
+      push_array_bounds (tree_low_cst (constructor_index, 1));
       constructor_depth++;
     }
 
       constructor_depth++;
     }
 
@@ -5282,7 +5390,7 @@ pop_init_level (int implicit)
       else
        {
          gcc_assert (!TYPE_SIZE (constructor_type));
       else
        {
          gcc_assert (!TYPE_SIZE (constructor_type));
-         
+
          if (constructor_depth > 2)
            error_init ("initialization of flexible array member in a nested context");
          else if (pedantic)
          if (constructor_depth > 2)
            error_init ("initialization of flexible array member in a nested context");
          else if (pedantic)
@@ -5383,15 +5491,8 @@ pop_init_level (int implicit)
   constructor_stack = p->next;
   free (p);
 
   constructor_stack = p->next;
   free (p);
 
-  if (ret.value == 0)
-    {
-      if (constructor_stack == 0)
-       {
-         ret.value = error_mark_node;
-         return ret;
-       }
-      return ret;
-    }
+  if (ret.value == 0 && constructor_stack == 0)
+    ret.value = error_mark_node;
   return ret;
 }
 
   return ret;
 }
 
@@ -5605,6 +5706,8 @@ add_pending_init (tree purpose, tree value)
            {
              if (TREE_SIDE_EFFECTS (p->value))
                warning_init ("initialized field with side-effects overwritten");
            {
              if (TREE_SIDE_EFFECTS (p->value))
                warning_init ("initialized field with side-effects overwritten");
+             else if (warn_override_init)
+               warning_init ("initialized field overwritten");
              p->value = value;
              return;
            }
              p->value = value;
              return;
            }
@@ -5626,6 +5729,8 @@ add_pending_init (tree purpose, tree value)
            {
              if (TREE_SIDE_EFFECTS (p->value))
                warning_init ("initialized field with side-effects overwritten");
            {
              if (TREE_SIDE_EFFECTS (p->value))
                warning_init ("initialized field with side-effects overwritten");
+             else if (warn_override_init)
+               warning_init ("initialized field overwritten");
              p->value = value;
              return;
            }
              p->value = value;
              return;
            }
@@ -5899,7 +6004,7 @@ set_nonincremental_init_from_string (tree str)
          else if (bitpos == HOST_BITS_PER_WIDE_INT)
            {
              if (val[1] < 0)
          else if (bitpos == HOST_BITS_PER_WIDE_INT)
            {
              if (val[1] < 0)
-               val[0] = -1;
+               val[0] = -1;
            }
          else if (val[0] & (((HOST_WIDE_INT) 1)
                             << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
            }
          else if (val[0] & (((HOST_WIDE_INT) 1)
                             << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
@@ -6098,6 +6203,8 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
       if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
                                       constructor_elements)->value))
        warning_init ("initialized field with side-effects overwritten");
       if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
                                       constructor_elements)->value))
        warning_init ("initialized field with side-effects overwritten");
+      else if (warn_override_init)
+       warning_init ("initialized field overwritten");
 
       /* We can have just one union field set.  */
       constructor_elements = 0;
 
       /* We can have just one union field set.  */
       constructor_elements = 0;
@@ -6305,7 +6412,7 @@ process_init_element (struct c_expr value)
       && integer_zerop (constructor_unfilled_index))
     {
       if (constructor_stack->replacement_value.value)
       && integer_zerop (constructor_unfilled_index))
     {
       if (constructor_stack->replacement_value.value)
-        error_init ("excess elements in char array initializer");
+       error_init ("excess elements in char array initializer");
       constructor_stack->replacement_value = value;
       return;
     }
       constructor_stack->replacement_value = value;
       return;
     }
@@ -6408,10 +6515,10 @@ process_init_element (struct c_expr value)
            {
              /* For a record, keep track of end position of last field.  */
              if (DECL_SIZE (constructor_fields))
            {
              /* For a record, keep track of end position of last field.  */
              if (DECL_SIZE (constructor_fields))
-               constructor_bit_index
+               constructor_bit_index
                  = size_binop (PLUS_EXPR,
                  = size_binop (PLUS_EXPR,
-                               bit_position (constructor_fields),
-                               DECL_SIZE (constructor_fields));
+                               bit_position (constructor_fields),
+                               DECL_SIZE (constructor_fields));
 
              /* If the current field was the first one not yet written out,
                 it isn't now, so update.  */
 
              /* If the current field was the first one not yet written out,
                 it isn't now, so update.  */
@@ -6535,7 +6642,7 @@ process_init_element (struct c_expr value)
          /* Now output the actual element.  */
          if (value.value)
            {
          /* Now output the actual element.  */
          if (value.value)
            {
-             push_array_bounds (tree_low_cst (constructor_index, 0));
+             push_array_bounds (tree_low_cst (constructor_index, 1));
              output_init_element (value.value, strict_string,
                                   elttype, constructor_index, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
              output_init_element (value.value, strict_string,
                                   elttype, constructor_index, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
@@ -6554,8 +6661,8 @@ process_init_element (struct c_expr value)
        {
          tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
 
        {
          tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
 
-         /* Do a basic check of initializer size.  Note that vectors
-            always have a fixed size derived from their type.  */
+        /* Do a basic check of initializer size.  Note that vectors
+           always have a fixed size derived from their type.  */
          if (tree_int_cst_lt (constructor_max_index, constructor_index))
            {
              pedwarn_init ("excess elements in vector initializer");
          if (tree_int_cst_lt (constructor_max_index, constructor_index))
            {
              pedwarn_init ("excess elements in vector initializer");
@@ -6718,7 +6825,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
            output = error_mark_node;
        }
       else
            output = error_mark_node;
        }
       else
-        output = error_mark_node;
+       output = error_mark_node;
 
       TREE_VALUE (tail) = output;
     }
 
       TREE_VALUE (tail) = output;
     }
@@ -6845,8 +6952,10 @@ c_finish_return (tree retval)
   else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
     {
       current_function_returns_null = 1;
   else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
     {
       current_function_returns_null = 1;
-      if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
        pedwarn ("%<return%> with a value, in function returning void");
        pedwarn ("%<return%> with a value, in function returning void");
+      else if (pedantic)
+       pedwarn ("ISO C forbids %<return%> with expression, in function returning void");
     }
   else
     {
     }
   else
     {
@@ -6896,7 +7005,7 @@ c_finish_return (tree retval)
              inner = TREE_OPERAND (inner, 0);
 
              while (REFERENCE_CLASS_P (inner)
              inner = TREE_OPERAND (inner, 0);
 
              while (REFERENCE_CLASS_P (inner)
-                    && TREE_CODE (inner) != INDIRECT_REF)
+                    && TREE_CODE (inner) != INDIRECT_REF)
                inner = TREE_OPERAND (inner, 0);
 
              if (DECL_P (inner)
                inner = TREE_OPERAND (inner, 0);
 
              if (DECL_P (inner)
@@ -6964,25 +7073,25 @@ struct c_switch *c_switch_stack;
 tree
 c_start_case (tree exp)
 {
 tree
 c_start_case (tree exp)
 {
-  enum tree_code code;
-  tree type, orig_type = error_mark_node;
+  tree orig_type = error_mark_node;
   struct c_switch *cs;
 
   if (exp != error_mark_node)
     {
   struct c_switch *cs;
 
   if (exp != error_mark_node)
     {
-      code = TREE_CODE (TREE_TYPE (exp));
       orig_type = TREE_TYPE (exp);
 
       orig_type = TREE_TYPE (exp);
 
-      if (!INTEGRAL_TYPE_P (orig_type)
-         && code != ERROR_MARK)
+      if (!INTEGRAL_TYPE_P (orig_type))
        {
        {
-         error ("switch quantity not an integer");
+         if (orig_type != error_mark_node)
+           {
+             error ("switch quantity not an integer");
+             orig_type = error_mark_node;
+           }
          exp = integer_zero_node;
          exp = integer_zero_node;
-         orig_type = error_mark_node;
        }
       else
        {
        }
       else
        {
-         type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+         tree type = TYPE_MAIN_VARIANT (orig_type);
 
          if (!in_system_header
              && (type == long_integer_type_node
 
          if (!in_system_header
              && (type == long_integer_type_node
@@ -6991,7 +7100,6 @@ c_start_case (tree exp)
                     "converted to %<int%> in ISO C");
 
          exp = default_conversion (exp);
                     "converted to %<int%> in ISO C");
 
          exp = default_conversion (exp);
-         type = TREE_TYPE (exp);
        }
     }
 
        }
     }
 
@@ -7127,36 +7235,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
                  &if_locus);
     }
 
                  &if_locus);
     }
 
-  /* Diagnose ";" via the special empty statement node that we create.  */
-  if (extra_warnings)
-    {
-      tree *inner_then = &then_block, *inner_else = &else_block;
-
-      if (TREE_CODE (*inner_then) == STATEMENT_LIST
-         && STATEMENT_LIST_TAIL (*inner_then))
-       inner_then = &STATEMENT_LIST_TAIL (*inner_then)->stmt;
-      if (*inner_else && TREE_CODE (*inner_else) == STATEMENT_LIST
-         && STATEMENT_LIST_TAIL (*inner_else))
-       inner_else = &STATEMENT_LIST_TAIL (*inner_else)->stmt;
-
-      if (TREE_CODE (*inner_then) == NOP_EXPR && !TREE_TYPE (*inner_then))
-       {
-         if (!*inner_else)
-           warning (0, "%Hempty body in an if-statement",
-                    EXPR_LOCUS (*inner_then));
-
-         *inner_then = alloc_stmt_list ();
-       }
-      if (*inner_else
-         && TREE_CODE (*inner_else) == NOP_EXPR
-         && !TREE_TYPE (*inner_else))
-       {
-         warning (0, "%Hempty body in an else-statement",
-                  EXPR_LOCUS (*inner_else));
-
-         *inner_else = alloc_stmt_list ();
-       }
-    }
+  empty_if_body_warning (then_block, else_block);
 
   stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
   SET_EXPR_LOCATION (stmt, if_locus);
 
   stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
   SET_EXPR_LOCATION (stmt, if_locus);
@@ -7188,41 +7267,41 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
   else
     {
       tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
   else
     {
       tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+
       /* If we have an exit condition, then we build an IF with gotos either
       /* If we have an exit condition, then we build an IF with gotos either
-         out of the loop, or to the top of it.  If there's no exit condition,
-         then we just build a jump back to the top.  */
+        out of the loop, or to the top of it.  If there's no exit condition,
+        then we just build a jump back to the top.  */
       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
+
       if (cond && !integer_nonzerop (cond))
       if (cond && !integer_nonzerop (cond))
-        {
-          /* Canonicalize the loop condition to the end.  This means
-             generating a branch to the loop condition.  Reuse the
-             continue label, if possible.  */
-          if (cond_is_first)
-            {
-              if (incr || !clab)
-                {
-                  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-                  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
-                }
-              else
-                t = build1 (GOTO_EXPR, void_type_node, clab);
+       {
+         /* Canonicalize the loop condition to the end.  This means
+            generating a branch to the loop condition.  Reuse the
+            continue label, if possible.  */
+         if (cond_is_first)
+           {
+             if (incr || !clab)
+               {
+                 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+                 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
+               }
+             else
+               t = build1 (GOTO_EXPR, void_type_node, clab);
              SET_EXPR_LOCATION (t, start_locus);
              SET_EXPR_LOCATION (t, start_locus);
-              add_stmt (t);
-            }
+             add_stmt (t);
+           }
+
          t = build_and_jump (&blab);
          t = build_and_jump (&blab);
-          exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
+         exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
          if (cond_is_first)
          if (cond_is_first)
-            SET_EXPR_LOCATION (exit, start_locus);
+           SET_EXPR_LOCATION (exit, start_locus);
          else
          else
-            SET_EXPR_LOCATION (exit, input_location);
-        }
+           SET_EXPR_LOCATION (exit, input_location);
+       }
+
       add_stmt (top);
     }
       add_stmt (top);
     }
+
   if (body)
     add_stmt (body);
   if (clab)
   if (body)
     add_stmt (body);
   if (clab)
@@ -7257,13 +7336,24 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
       if (!skip)
        *label_p = label = create_artificial_label ();
     }
       if (!skip)
        *label_p = label = create_artificial_label ();
     }
-  else if (TREE_CODE (label) != LABEL_DECL)
+  else if (TREE_CODE (label) == LABEL_DECL)
+    ;
+  else switch (TREE_INT_CST_LOW (label))
     {
     {
+    case 0:
       if (is_break)
        error ("break statement not within loop or switch");
       else
       if (is_break)
        error ("break statement not within loop or switch");
       else
-        error ("continue statement not within a loop");
+       error ("continue statement not within a loop");
+      return NULL_TREE;
+
+    case 1:
+      gcc_assert (is_break);
+      error ("break statement used with OpenMP for loop");
       return NULL_TREE;
       return NULL_TREE;
+
+    default:
+      gcc_unreachable ();
     }
 
   if (skip)
     }
 
   if (skip)
@@ -7282,10 +7372,10 @@ emit_side_effect_warnings (tree expr)
   else if (!TREE_SIDE_EFFECTS (expr))
     {
       if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
   else if (!TREE_SIDE_EFFECTS (expr))
     {
       if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
-       warning (0, "%Hstatement with no effect",
+       warning (OPT_Wunused_value, "%Hstatement with no effect",
                 EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location);
     }
                 EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location);
     }
-  else if (warn_unused_value)
+  else
     warn_if_unused_value (expr, input_location);
 }
 
     warn_if_unused_value (expr, input_location);
 }
 
@@ -7310,7 +7400,7 @@ c_process_expr_stmt (tree expr)
      Warnings for statement expressions will be emitted later, once we figure
      out which is the result.  */
   if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
      Warnings for statement expressions will be emitted later, once we figure
      out which is the result.  */
   if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
-      && (extra_warnings || warn_unused_value))
+      && warn_unused_value)
     emit_side_effect_warnings (expr);
 
   /* If the expression is not of a type to which we cannot assign a line
     emit_side_effect_warnings (expr);
 
   /* If the expression is not of a type to which we cannot assign a line
@@ -7318,7 +7408,7 @@ c_process_expr_stmt (tree expr)
   if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
     expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
 
   if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
     expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
 
-  if (EXPR_P (expr))
+  if (CAN_HAVE_LOCATION_P (expr))
     SET_EXPR_LOCATION (expr, input_location);
 
   return expr;
     SET_EXPR_LOCATION (expr, input_location);
 
   return expr;
@@ -7426,7 +7516,7 @@ c_finish_stmt_expr (tree body)
 
       /* If we're supposed to generate side effects warnings, process
         all of the statements except the last.  */
 
       /* If we're supposed to generate side effects warnings, process
         all of the statements except the last.  */
-      if (extra_warnings || warn_unused_value)
+      if (warn_unused_value)
        {
          for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
            emit_side_effect_warnings (tsi_stmt (i));
        {
          for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
            emit_side_effect_warnings (tsi_stmt (i));
@@ -7455,7 +7545,7 @@ c_finish_stmt_expr (tree body)
     {
       /* Do not warn if the return value of a statement expression is
         unused.  */
     {
       /* Do not warn if the return value of a statement expression is
         unused.  */
-      if (EXPR_P (last))
+      if (CAN_HAVE_LOCATION_P (last))
        TREE_NO_WARNING (last) = 1;
       return last;
     }
        TREE_NO_WARNING (last) = 1;
       return last;
     }
@@ -7497,6 +7587,11 @@ c_begin_vm_scope (unsigned int scope)
   struct c_label_list *glist;
 
   gcc_assert (scope > 0);
   struct c_label_list *glist;
 
   gcc_assert (scope > 0);
+
+  /* At file_scope, we don't have to do any processing.  */
+  if (label_context_stack_vm == NULL)
+    return;
+
   if (c_switch_stack && !c_switch_stack->blocked_vm)
     c_switch_stack->blocked_vm = scope;
   for (glist = label_context_stack_vm->labels_used;
   if (c_switch_stack && !c_switch_stack->blocked_vm)
     c_switch_stack->blocked_vm = scope;
   for (glist = label_context_stack_vm->labels_used;
@@ -7759,10 +7854,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
-      /* Floating point division by zero is a legitimate way to obtain
-        infinities and NaNs.  */
-      if (skip_evaluation == 0 && integer_zerop (op1))
-       warning (OPT_Wdiv_by_zero, "division by zero");
+      warn_for_div_by_zero (op1);
 
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
 
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
@@ -7802,8 +7894,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
-      if (skip_evaluation == 0 && integer_zerop (op1))
-       warning (OPT_Wdiv_by_zero, "division by zero");
+      warn_for_div_by_zero (op1);
 
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
 
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -7919,14 +8010,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
            {
              /* op0 != orig_op0 detects the case of something
                 whose value is 0 but which isn't a valid null ptr const.  */
            {
              /* op0 != orig_op0 detects the case of something
                 whose value is 0 but which isn't a valid null ptr const.  */
-             if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
+             if (pedantic && !null_pointer_constant_p (orig_op0)
                  && TREE_CODE (tt1) == FUNCTION_TYPE)
                pedwarn ("ISO C forbids comparison of %<void *%>"
                         " with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
                  && TREE_CODE (tt1) == FUNCTION_TYPE)
                pedwarn ("ISO C forbids comparison of %<void *%>"
                         " with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
-             if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
+             if (pedantic && !null_pointer_constant_p (orig_op1)
                  && TREE_CODE (tt0) == FUNCTION_TYPE)
                pedwarn ("ISO C forbids comparison of %<void *%>"
                         " with function pointer");
                  && TREE_CODE (tt0) == FUNCTION_TYPE)
                pedwarn ("ISO C forbids comparison of %<void *%>"
                         " with function pointer");
@@ -7939,12 +8030,22 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          if (result_type == NULL_TREE)
            result_type = ptr_type_node;
        }
          if (result_type == NULL_TREE)
            result_type = ptr_type_node;
        }
-      else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
-              && integer_zerop (op1))
-       result_type = type0;
-      else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
-              && integer_zerop (op0))
-       result_type = type1;
+      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 (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 (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;
@@ -7983,15 +8084,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
              pedwarn ("comparison of distinct pointer types lacks a cast");
            }
        }
              pedwarn ("comparison of distinct pointer types lacks a cast");
            }
        }
-      else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
-              && integer_zerop (op1))
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
        {
          result_type = type0;
          if (pedantic || extra_warnings)
            pedwarn ("ordered comparison of pointer with integer zero");
        }
        {
          result_type = type0;
          if (pedantic || extra_warnings)
            pedwarn ("ordered comparison of pointer with integer zero");
        }
-      else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
-              && integer_zerop (op0))
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
          if (pedantic)
        {
          result_type = type1;
          if (pedantic)
@@ -8021,7 +8120,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
                                                    TREE_TYPE (type1))))
     {
          || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
                                                    TREE_TYPE (type1))))
     {
-      binary_op_error (code);
+      binary_op_error (code, type0, type1);
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
@@ -8034,7 +8133,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
       if (shorten || common || short_compare)
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
       if (shorten || common || short_compare)
-       result_type = c_common_type (type0, type1);
+       {
+         result_type = c_common_type (type0, type1);
+         if (result_type == error_mark_node)
+           return error_mark_node;
+       }
 
       /* For certain operations (which identify themselves by shorten != 0)
         if both args were extended from the same smaller type,
 
       /* For certain operations (which identify themselves by shorten != 0)
         if both args were extended from the same smaller type,
@@ -8050,12 +8153,35 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       if (shorten && none_complex)
        {
          int unsigned0, unsigned1;
       if (shorten && none_complex)
        {
          int unsigned0, unsigned1;
-         tree arg0 = get_narrower (op0, &unsigned0);
-         tree arg1 = get_narrower (op1, &unsigned1);
-         /* UNS is 1 if the operation to be done is an unsigned one.  */
-         int uns = TYPE_UNSIGNED (result_type);
+         tree arg0, arg1;
+         int uns;
          tree type;
 
          tree type;
 
+         /* Cast OP0 and OP1 to RESULT_TYPE.  Doing so prevents
+            excessive narrowing when we call get_narrower below.  For
+            example, suppose that OP0 is of unsigned int extended
+            from signed char and that RESULT_TYPE is long long int.
+            If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
+            like
+
+              (long long int) (unsigned int) signed_char
+
+            which get_narrower would narrow down to
+
+              (unsigned int) signed char
+
+            If we do not cast OP0 first, get_narrower would return
+            signed_char, which is inconsistent with the case of the
+            explicit cast.  */
+         op0 = convert (result_type, op0);
+         op1 = convert (result_type, op1);
+
+         arg0 = get_narrower (op0, &unsigned0);
+         arg1 = get_narrower (op1, &unsigned1);
+
+         /* UNS is 1 if the operation to be done is an unsigned one.  */
+         uns = TYPE_UNSIGNED (result_type);
+
          final_type = result_type;
 
          /* Handle the case that OP0 (or OP1) does not *contain* a conversion
          final_type = result_type;
 
          /* Handle the case that OP0 (or OP1) does not *contain* a conversion
@@ -8188,12 +8314,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 all the values of the unsigned type.  */
              if (!TYPE_UNSIGNED (result_type))
                /* OK */;
                 all the values of the unsigned type.  */
              if (!TYPE_UNSIGNED (result_type))
                /* OK */;
-              /* Do not warn if both operands are the same signedness.  */
-              else if (op0_signed == op1_signed)
-                /* OK */;
+             /* Do not warn if both operands are the same signedness.  */
+             else if (op0_signed == op1_signed)
+               /* OK */;
              else
                {
                  tree sop, uop;
              else
                {
                  tree sop, uop;
+                 bool ovf;
 
                  if (op0_signed)
                    sop = xop0, uop = xop1;
 
                  if (op0_signed)
                    sop = xop0, uop = xop1;
@@ -8205,7 +8332,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                     constant expression involving such literals or a
                     conditional expression involving such literals)
                     and it is non-negative.  */
                     constant expression involving such literals or a
                     conditional expression involving such literals)
                     and it is non-negative.  */
-                 if (tree_expr_nonnegative_p (sop))
+                 if (tree_expr_nonnegative_warnv_p (sop, &ovf))
                    /* OK */;
                  /* Do not warn if the comparison is an equality operation,
                     the unsigned quantity is an integral constant, and it
                    /* OK */;
                  /* Do not warn if the comparison is an equality operation,
                     the unsigned quantity is an integral constant, and it
@@ -8293,16 +8420,16 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
   if (!result_type)
     {
 
   if (!result_type)
     {
-      binary_op_error (code);
+      binary_op_error (code, TREE_TYPE (op0), TREE_TYPE (op1));
       return error_mark_node;
     }
 
   if (!converted)
     {
       if (TREE_TYPE (op0) != result_type)
       return error_mark_node;
     }
 
   if (!converted)
     {
       if (TREE_TYPE (op0) != result_type)
-       op0 = convert (result_type, op0);
+       op0 = convert_and_check (result_type, op0);
       if (TREE_TYPE (op1) != result_type)
       if (TREE_TYPE (op1) != result_type)
-       op1 = convert (result_type, op1);
+       op1 = convert_and_check (result_type, op1);
 
       /* This can happen if one operand has a vector type, and the other
         has a different type.  */
 
       /* This can happen if one operand has a vector type, and the other
         has a different type.  */
@@ -8380,3 +8507,247 @@ c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
   else
     return expr;
 }
   else
     return expr;
 }
+\f
+/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
+
+tree
+c_begin_omp_parallel (void)
+{
+  tree block;
+
+  keep_next_level ();
+  block = c_begin_compound_stmt (true);
+
+  return block;
+}
+
+tree
+c_finish_omp_parallel (tree clauses, tree block)
+{
+  tree stmt;
+
+  block = c_end_compound_stmt (block, true);
+
+  stmt = make_node (OMP_PARALLEL);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_PARALLEL_CLAUSES (stmt) = clauses;
+  OMP_PARALLEL_BODY (stmt) = block;
+
+  return add_stmt (stmt);
+}
+
+/* For all elements of CLAUSES, validate them vs OpenMP constraints.
+   Remove any elements from the list that are invalid.  */
+
+tree
+c_finish_omp_clauses (tree clauses)
+{
+  bitmap_head generic_head, firstprivate_head, lastprivate_head;
+  tree c, t, *pc = &clauses;
+  const char *name;
+
+  bitmap_obstack_initialize (NULL);
+  bitmap_initialize (&generic_head, &bitmap_default_obstack);
+  bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
+  bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
+
+  for (pc = &clauses, c = clauses; c ; c = *pc)
+    {
+      bool remove = false;
+      bool need_complete = false;
+      bool need_implicitly_determined = false;
+
+      switch (OMP_CLAUSE_CODE (c))
+       {
+       case OMP_CLAUSE_SHARED:
+         name = "shared";
+         need_implicitly_determined = true;
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_PRIVATE:
+         name = "private";
+         need_complete = true;
+         need_implicitly_determined = true;
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_REDUCTION:
+         name = "reduction";
+         need_implicitly_determined = true;
+         t = OMP_CLAUSE_DECL (c);
+         if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+             || POINTER_TYPE_P (TREE_TYPE (t)))
+           {
+             error ("%qE has invalid type for %<reduction%>", t);
+             remove = true;
+           }
+         else if (FLOAT_TYPE_P (TREE_TYPE (t)))
+           {
+             enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
+             const char *r_name = NULL;
+
+             switch (r_code)
+               {
+               case PLUS_EXPR:
+               case MULT_EXPR:
+               case MINUS_EXPR:
+                 break;
+               case BIT_AND_EXPR:
+                 r_name = "&";
+                 break;
+               case BIT_XOR_EXPR:
+                 r_name = "^";
+                 break;
+               case BIT_IOR_EXPR:
+                 r_name = "|";
+                 break;
+               case TRUTH_ANDIF_EXPR:
+                 r_name = "&&";
+                 break;
+               case TRUTH_ORIF_EXPR:
+                 r_name = "||";
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             if (r_name)
+               {
+                 error ("%qE has invalid type for %<reduction(%s)%>",
+                        t, r_name);
+                 remove = true;
+               }
+           }
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_COPYPRIVATE:
+         name = "copyprivate";
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_COPYIN:
+         name = "copyin";
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
+           {
+             error ("%qE must be %<threadprivate%> for %<copyin%>", t);
+             remove = true;
+           }
+         goto check_dup_generic;
+
+       check_dup_generic:
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error ("%qE is not a variable in clause %qs", t, name);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&generic_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_FIRSTPRIVATE:
+         name = "firstprivate";
+         t = OMP_CLAUSE_DECL (c);
+         need_complete = true;
+         need_implicitly_determined = true;
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error ("%qE is not a variable in clause %<firstprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&firstprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_LASTPRIVATE:
+         name = "lastprivate";
+         t = OMP_CLAUSE_DECL (c);
+         need_complete = true;
+         need_implicitly_determined = true;
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error ("%qE is not a variable in clause %<lastprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&lastprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_IF:
+       case OMP_CLAUSE_NUM_THREADS:
+       case OMP_CLAUSE_SCHEDULE:
+       case OMP_CLAUSE_NOWAIT:
+       case OMP_CLAUSE_ORDERED:
+       case OMP_CLAUSE_DEFAULT:
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
+
+       default:
+         gcc_unreachable ();
+       }
+
+      if (!remove)
+       {
+         t = OMP_CLAUSE_DECL (c);
+
+         if (need_complete)
+           {
+             t = require_complete_type (t);
+             if (t == error_mark_node)
+               remove = true;
+           }
+
+         if (need_implicitly_determined)
+           {
+             const char *share_name = NULL;
+
+             if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+               share_name = "threadprivate";
+             else switch (c_omp_predetermined_sharing (t))
+               {
+               case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
+                 break;
+               case OMP_CLAUSE_DEFAULT_SHARED:
+                 share_name = "shared";
+                 break;
+               case OMP_CLAUSE_DEFAULT_PRIVATE:
+                 share_name = "private";
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             if (share_name)
+               {
+                 error ("%qE is predetermined %qs for %qs",
+                        t, share_name, name);
+                 remove = true;
+               }
+           }
+       }
+
+      if (remove)
+       *pc = OMP_CLAUSE_CHAIN (c);
+      else
+       pc = &OMP_CLAUSE_CHAIN (c);
+    }
+
+  bitmap_obstack_release (NULL);
+  return clauses;
+}