OSDN Git Service

PR c/52880
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 14bc281..fc01a79 100644 (file)
@@ -1,6 +1,6 @@
 /* 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, 2006, 2007, 2008, 2009, 2010
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -35,12 +35,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-lang.h"
 #include "flags.h"
 #include "output.h"
-#include "toplev.h"
 #include "intl.h"
 #include "target.h"
 #include "tree-iterator.h"
 #include "bitmap.h"
 #include "gimple.h"
+#include "c-family/c-objc.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -51,12 +51,13 @@ enum impl_conv {
   ic_return
 };
 
-/* Whether we are building a boolean conversion inside
-   convert_for_assignment, or some other late binary operation.  If
-   build_binary_op is called (from code shared with C++) in this case,
-   then the operands have already been folded and the result will not
-   be folded again, so C_MAYBE_CONST_EXPR should not be generated.  */
-bool in_late_binary_op;
+/* Possibe cases of scalar_to_vector conversion.  */
+enum stv_conv {
+  stv_error,        /* Error occured.  */
+  stv_nothing,      /* Nothing happened.  */
+  stv_firstarg,     /* First argument must be expanded.  */
+  stv_secondarg     /* Second argument must be expanded.  */
+};
 
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
@@ -104,9 +105,8 @@ static void add_pending_init (tree, tree, tree, bool, struct obstack *);
 static void set_nonincremental_init (struct obstack *);
 static void set_nonincremental_init_from_string (tree, struct obstack *);
 static tree find_init_member (tree, struct obstack *);
-static void readonly_error (tree, enum lvalue_use);
 static void readonly_warning (tree, enum lvalue_use);
-static int lvalue_or_else (const_tree, enum lvalue_use);
+static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (const_tree, const_tree, bool *, bool *);
 \f
@@ -394,7 +394,7 @@ composite_type (tree t1, tree t2)
        tree pointed_to_1 = TREE_TYPE (t1);
        tree pointed_to_2 = TREE_TYPE (t2);
        tree target = composite_type (pointed_to_1, pointed_to_2);
-       t1 = build_pointer_type (target);
+        t1 = build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
        t1 = build_type_attribute_variant (t1, attributes);
        return qualify_type (t1, t2);
       }
@@ -515,9 +515,6 @@ composite_type (tree t1, tree t2)
 
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
-       /* Tell global_bindings_p to return false so that variable_size
-          doesn't die on VLAs in parameter types.  */
-       c_override_global_bindings_to_false = true;
 
        len = list_length (p1);
        newargs = 0;
@@ -600,7 +597,6 @@ composite_type (tree t1, tree t2)
          parm_done: ;
          }
 
-       c_override_global_bindings_to_false = false;
        t1 = build_function_type (valtype, newargs);
        t1 = qualify_type (t1, t2);
        /* ... falls through ...  */
@@ -1018,7 +1014,7 @@ comptypes_check_different_types (tree type1, tree type2,
    compatible integer type, then this sets *ENUM_AND_INT_P to true;
    *ENUM_AND_INT_P is never set to false.  If DIFFERENT_TYPES_P is not
    NULL, and the types are compatible but different enough not to be
-   permitted in C1X typedef redeclarations, then this sets
+   permitted in C11 typedef redeclarations, then this sets
    *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
    false, but may or may not be set if the types are incompatible.
    This differs from comptypes, in that we don't free the seen
@@ -1087,7 +1083,7 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
     return 1;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  if (!(attrval = targetm.comp_type_attributes (t1, t2)))
+  if (!(attrval = comp_type_attributes (t1, t2)))
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -2130,6 +2126,11 @@ build_component_ref (location_t loc, tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
+  /* Detect Objective-C property syntax object.property.  */
+  if (c_dialect_objc ()
+      && (ref = objc_maybe_build_component_ref (datum, component)))
+    return ref;
+
   /* See if there is a field or component with name COMPONENT.  */
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
@@ -2269,26 +2270,8 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    switch (errstring)
-      {
-         case RO_ARRAY_INDEXING:
-           error_at (loc,
-                     "invalid type argument of array indexing (have %qT)",
-                     type);
-           break;
-         case RO_UNARY_STAR:
-           error_at (loc,
-                     "invalid type argument of unary %<*%> (have %qT)",
-                     type);
-           break;
-         case RO_ARROW:
-           error_at (loc,
-                     "invalid type argument of %<->%> (have %qT)",
-                     type);
-           break;
-         default:
-           gcc_unreachable ();
-      }
+    invalid_indirection_error (loc, type, errstring);
+
   return error_mark_node;
 }
 
@@ -2301,6 +2284,9 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
    arrays that are not lvalues (for example, members of structures returned
    by functions).
 
+   For vector types, allow vector[i] but not i[vector], and create
+   *(((type*)&vectortype) + i) for the expression.
+
    LOC is the location to use for the returned expression.  */
 
 tree
@@ -2313,13 +2299,17 @@ build_array_ref (location_t loc, tree array, tree index)
     return error_mark_node;
 
   if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
-      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
+      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
+      /* Allow vector[index] but not index[vector].  */
+      && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE)
     {
       tree temp;
       if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
-         error_at (loc, "subscripted value is neither array nor pointer");
+          error_at (loc,
+            "subscripted value is neither array nor pointer nor vector");
+
          return error_mark_node;
        }
       temp = array;
@@ -2350,6 +2340,27 @@ build_array_ref (location_t loc, tree array, tree index)
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
 
+  /* For vector[index], convert the vector to a
+     pointer of the underlying type.  */
+  if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE)
+    {
+      tree type = TREE_TYPE (array);
+      tree type1;
+
+      if (TREE_CODE (index) == INTEGER_CST)
+        if (!host_integerp (index, 1)
+            || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
+               >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array))))
+          warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
+
+      c_common_mark_addressable_vec (array);
+      type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
+      type = build_pointer_type (type);
+      type1 = build_pointer_type (TREE_TYPE (array));
+      array = build1 (ADDR_EXPR, type1, array);
+      array = convert (type, array);
+    }
+
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
       tree rval, type;
@@ -2705,7 +2716,14 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
        return tem;
 
       name = DECL_NAME (function);
+
+      if (flag_tm)
+       tm_malloc_replacement (function);
       fundecl = function;
+      /* Atomic functions have type checking/casting already done.  They are 
+        often rewritten and don't match the original parameter list.  */
+      if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
+        origtypes = NULL;
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
     function = function_to_pointer_conversion (loc, function);
@@ -2755,7 +2773,8 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
       && !comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
-      tree trap = build_function_call (loc, built_in_decls[BUILT_IN_TRAP],
+      tree trap = build_function_call (loc,
+                                      builtin_decl_explicit (BUILT_IN_TRAP),
                                       NULL_TREE);
       int i;
 
@@ -2788,7 +2807,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
                                          build_constructor (return_type, 0),
                                          false);
          else
-           rhs = fold_convert_loc (loc, return_type, integer_zero_node);
+           rhs = build_zero_cst (return_type);
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
@@ -2805,8 +2824,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
     return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
-                           TYPE_ARG_TYPES (fntype));
+  check_function_arguments (fntype, nargs, argarray);
 
   if (name != NULL_TREE
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
@@ -2835,6 +2853,98 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
     }
   return require_complete_type (result);
 }
+
+/* Build a VEC_PERM_EXPR if V0, V1 and MASK are not error_mark_nodes
+   and have vector types, V0 has the same type as V1, and the number of
+   elements of V0, V1, MASK is the same.
+
+   In case V1 is a NULL_TREE it is assumed that __builtin_shuffle was
+   called with two arguments.  In this case implementation passes the
+   first argument twice in order to share the same tree code.  This fact
+   could enable the mask-values being twice the vector length.  This is
+   an implementation accident and this semantics is not guaranteed to
+   the user.  */
+tree
+c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
+{
+  tree ret;
+  bool wrap = true;
+  bool maybe_const = false;
+  bool two_arguments = false;
+
+  if (v1 == NULL_TREE)
+    {
+      two_arguments = true;
+      v1 = v0;
+    }
+
+  if (v0 == error_mark_node || v1 == error_mark_node
+      || mask == error_mark_node)
+    return error_mark_node;
+
+  if (TREE_CODE (TREE_TYPE (mask)) != VECTOR_TYPE
+      || TREE_CODE (TREE_TYPE (TREE_TYPE (mask))) != INTEGER_TYPE)
+    {
+      error_at (loc, "__builtin_shuffle last argument must "
+                    "be an integer vector");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (TREE_TYPE (v0)) != VECTOR_TYPE
+      || TREE_CODE (TREE_TYPE (v1)) != VECTOR_TYPE)
+    {
+      error_at (loc, "__builtin_shuffle arguments must be vectors");
+      return error_mark_node;
+    }
+
+  if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1)))
+    {
+      error_at (loc, "__builtin_shuffle argument vectors must be of "
+                    "the same type");
+      return error_mark_node;
+    }
+
+  if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0))
+      != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))
+      && TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1))
+        != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))
+    {
+      error_at (loc, "__builtin_shuffle number of elements of the "
+                    "argument vector(s) and the mask vector should "
+                    "be the same");
+      return error_mark_node;
+    }
+
+  if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
+      != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
+    {
+      error_at (loc, "__builtin_shuffle argument vector(s) inner type "
+                    "must have the same size as inner type of the mask");
+      return error_mark_node;
+    }
+
+  /* Avoid C_MAYBE_CONST_EXPRs inside VEC_PERM_EXPR.  */
+  v0 = c_fully_fold (v0, false, &maybe_const);
+  wrap &= maybe_const;
+
+  if (two_arguments)
+    v1 = v0 = save_expr (v0);
+  else
+    {
+      v1 = c_fully_fold (v1, false, &maybe_const);
+      wrap &= maybe_const;
+    }
+
+  mask = c_fully_fold (mask, false, &maybe_const);
+  wrap &= maybe_const;
+
+  ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask);
+
+  if (!wrap)
+    ret = c_wrap_maybe_const (ret, true);
+
+  return ret;
+}
 \f
 /* Convert the argument expressions in the vector VALUES
    to the types in the list TYPELIST.
@@ -3157,7 +3267,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      error_at (input_location, 
+      error_at (input_location,
                "too few arguments to function %qE", function);
       if (fundecl && !DECL_BUILT_IN (fundecl))
        inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
@@ -3528,26 +3638,10 @@ build_unary_op (location_t location,
       goto return_build_unary_op;
 
     case REALPART_EXPR:
-      if (TREE_CODE (arg) == COMPLEX_CST)
-       ret = TREE_REALPART (arg);
-      else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1_loc (location,
-                              REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
-      else
-       ret = arg;
-      if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
-       eptype = TREE_TYPE (eptype);
-      goto return_build_unary_op;
-
     case IMAGPART_EXPR:
-      if (TREE_CODE (arg) == COMPLEX_CST)
-       ret = TREE_IMAGPART (arg);
-      else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1_loc (location,
-                              IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
-      else
-       ret = omit_one_operand_loc (location, TREE_TYPE (arg),
-                               integer_zero_node, arg);
+      ret = build_real_imag_expr (location, code, arg);
+      if (ret == error_mark_node)
+       return error_mark_node;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
@@ -3570,11 +3664,14 @@ build_unary_op (location_t location,
          goto return_build_unary_op;
        }
 
-      /* Complain about anything that is not a true lvalue.  */
-      if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
-                                 || code == POSTINCREMENT_EXPR)
-                                ? lv_increment
-                                : lv_decrement)))
+      /* Complain about anything that is not a true lvalue.  In
+        Objective-C, skip this check for property_refs.  */
+      if (!objc_is_property_ref (arg)
+         && !lvalue_or_else (location,
+                             arg, ((code == PREINCREMENT_EXPR
+                                    || code == POSTINCREMENT_EXPR)
+                                   ? lv_increment
+                                   : lv_decrement)))
        return error_mark_node;
 
       if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
@@ -3655,7 +3752,7 @@ build_unary_op (location_t location,
              }
 
            inc = c_size_in_bytes (TREE_TYPE (argtype));
-           inc = fold_convert_loc (location, sizetype, inc);
+           inc = convert_to_ptrofftype_loc (location, inc);
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
@@ -3682,6 +3779,13 @@ build_unary_op (location_t location,
            inc = convert (argtype, inc);
          }
 
+       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+          need to ask Objective-C to build the increment or decrement
+          expression for it.  */
+       if (objc_is_property_ref (arg))
+         return objc_build_incr_expr_for_property_ref (location, code,
+                                                       arg, inc);
+
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
@@ -3736,18 +3840,12 @@ build_unary_op (location_t location,
          tree op0 = TREE_OPERAND (arg, 0);
          if (!c_mark_addressable (op0))
            return error_mark_node;
-         return build_binary_op (location, PLUS_EXPR,
-                                 (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
-                                  ? array_to_pointer_conversion (location,
-                                                                 op0)
-                                  : op0),
-                                 TREE_OPERAND (arg, 1), 1);
        }
 
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
-              && !lvalue_or_else (arg, lv_addressof))
+              && !lvalue_or_else (location, arg, lv_addressof))
        return error_mark_node;
 
       /* Move address operations inside C_MAYBE_CONST_EXPR to simplify
@@ -3768,10 +3866,11 @@ build_unary_op (location_t location,
       argtype = TREE_TYPE (arg);
 
       /* If the lvalue is const or volatile, merge that into the type
-        to which the address will point.  This should only be needed
+        to which the address will point.  This is only needed
         for function types.  */
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
-         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
+         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
+         && TREE_CODE (argtype) == FUNCTION_TYPE)
        {
          int orig_quals = TYPE_QUALS (strip_array_types (argtype));
          int quals = orig_quals;
@@ -3781,9 +3880,6 @@ build_unary_op (location_t location,
          if (TREE_THIS_VOLATILE (arg))
            quals |= TYPE_QUAL_VOLATILE;
 
-         gcc_assert (quals == orig_quals
-                     || TREE_CODE (argtype) == FUNCTION_TYPE);
-
          argtype = c_build_qualified_type (argtype, quals);
        }
 
@@ -3801,11 +3897,7 @@ build_unary_op (location_t location,
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
-         tree op0 = fold_convert_loc (location, sizetype,
-                                      fold_offsetof (arg, val)), op1;
-
-         op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0));
-         ret = fold_build2_loc (location, POINTER_PLUS_EXPR, argtype, op1, op0);
+         ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
          goto return_build_unary_op;
        }
 
@@ -3879,44 +3971,6 @@ lvalue_p (const_tree ref)
     }
 }
 \f
-/* Give an error for storing in something that is 'const'.  */
-
-static void
-readonly_error (tree arg, enum lvalue_use use)
-{
-  gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
-             || use == lv_asm);
-  /* Using this macro rather than (for example) arrays of messages
-     ensures that all the format strings are checked at compile
-     time.  */
-#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A)              \
-                                  : (use == lv_increment ? (I)         \
-                                  : (use == lv_decrement ? (D) : (AS))))
-  if (TREE_CODE (arg) == COMPONENT_REF)
-    {
-      if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       readonly_error (TREE_OPERAND (arg, 0), use);
-      else
-       error (READONLY_MSG (G_("assignment of read-only member %qD"),
-                            G_("increment of read-only member %qD"),
-                            G_("decrement of read-only member %qD"),
-                            G_("read-only member %qD used as %<asm%> output")),
-              TREE_OPERAND (arg, 1));
-    }
-  else if (TREE_CODE (arg) == VAR_DECL)
-    error (READONLY_MSG (G_("assignment of read-only variable %qD"),
-                        G_("increment of read-only variable %qD"),
-                        G_("decrement of read-only variable %qD"),
-                        G_("read-only variable %qD used as %<asm%> output")),
-          arg);
-  else
-    error (READONLY_MSG (G_("assignment of read-only location %qE"),
-                        G_("increment of read-only location %qE"),
-                        G_("decrement of read-only location %qE"),
-                        G_("read-only location %qE used as %<asm%> output")),
-          arg);
-}
-
 /* Give a warning for storing in something that is read-only in GCC
    terms but not const in ISO C terms.  */
 
@@ -3943,15 +3997,16 @@ readonly_warning (tree arg, enum lvalue_use use)
 
 /* Return nonzero if REF is an lvalue valid for this language;
    otherwise, print an error message and return zero.  USE says
-   how the lvalue is being used and so selects the error message.  */
+   how the lvalue is being used and so selects the error message.
+   LOCATION is the location at which any error should be reported.  */
 
 static int
-lvalue_or_else (const_tree ref, enum lvalue_use use)
+lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use)
 {
   int win = lvalue_p (ref);
 
   if (!win)
-    lvalue_error (use);
+    lvalue_error (loc, use);
 
   return win;
 }
@@ -4798,8 +4853,9 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
   if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
     SET_EXPR_LOCATION (ret, loc);
 
-  /* C++ does not permits types to be defined in a cast.  */
-  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+  /* C++ does not permits types to be defined in a cast, but it
+     allows references to incomplete types.  */
+  if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef)
     warning_at (loc, OPT_Wc___compat,
                "defining a type in a cast is invalid in C++");
 
@@ -4837,7 +4893,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
     return error_mark_node;
 
-  if (!lvalue_or_else (lhs, lv_assign))
+  /* For ObjC properties, defer this check.  */
+  if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
     return error_mark_node;
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
@@ -4878,6 +4935,19 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       rhs_origtype = NULL_TREE;
     }
 
+  if (c_dialect_objc ())
+    {
+      /* Check if we are modifying an Objective-C property reference;
+        if so, we need to generate setter calls.  */
+      result = objc_maybe_build_modify_expr (lhs, newrhs);
+      if (result)
+       return result;
+
+      /* Else, do the check that we postponed for Objective-C.  */
+      if (!lvalue_or_else (location, lhs, lv_assign))
+       return error_mark_node;
+    }
+
   /* Give an error for storing in something that is 'const'.  */
 
   if (TYPE_READONLY (lhstype)
@@ -5295,10 +5365,10 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     {
       tree ret;
       bool save = in_late_binary_op;
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = true;
       ret = convert_and_check (type, orig_rhs);
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = save;
       return ret;
     }
@@ -5571,20 +5641,16 @@ convert_for_assignment (location_t location, tree type, tree rhs,
              if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
                  & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
                {
-                 /* Types differing only by the presence of the 'volatile'
-                    qualifier are acceptable if the 'volatile' has been added
-                    in by the Objective-C EH machinery.  */
-                 if (!objc_type_quals_match (ttl, ttr))
-                   WARN_FOR_QUALIFIERS (location, 0,
-                                        G_("passing argument %d of %qE discards "
-                                           "%qv qualifier from pointer target type"),
-                                        G_("assignment discards %qv qualifier "
-                                           "from pointer target type"),
-                                        G_("initialization discards %qv qualifier "
-                                           "from pointer target type"),
-                                        G_("return discards %qv qualifier from "
-                                           "pointer target type"),
-                                        TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+                 WARN_FOR_QUALIFIERS (location, 0,
+                                      G_("passing argument %d of %qE discards "
+                                         "%qv qualifier from pointer target type"),
+                                      G_("assignment discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("initialization discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("return discards %qv qualifier from "
+                                         "pointer target type"),
+                                      TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
                }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
@@ -5798,11 +5864,13 @@ store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
              /* 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.  */
+             tree etype = strip_array_types (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_decl (cldecl, 0);
+             TREE_TYPE (decl)
+               = c_build_qualified_type (type, TYPE_QUALS (etype));
            }
        }
     }
@@ -5955,7 +6023,7 @@ void
 pedwarn_init (location_t location, int opt, const char *gmsgid)
 {
   char *ofwhat;
-  
+
   /* The gmsgid may be a format string with %< and %>. */
   pedwarn (location, opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
@@ -6667,7 +6735,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);
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       constructor_index = bitsize_zero_node;
       constructor_unfilled_index = constructor_index;
     }
@@ -6836,8 +6904,8 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
     {
       /* 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, integer_zero_node);
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
+      constructor_index = bitsize_int (0);
       constructor_unfilled_index = constructor_index;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -6957,15 +7025,23 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
     {
+       bool constructor_zeroinit =
+        (VEC_length (constructor_elt, constructor_elements) == 1
+         && integer_zerop
+             (VEC_index (constructor_elt, constructor_elements, 0)->value));
+
        /* Do not warn for flexible array members or zero-length arrays.  */
        while (constructor_unfilled_fields
               && (!DECL_SIZE (constructor_unfilled_fields)
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
          constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
 
-       /* Do not warn if this level of the initializer uses member
-          designators; it is likely to be deliberate.  */
-       if (constructor_unfilled_fields && !constructor_designated)
+       if (constructor_unfilled_fields
+           /* Do not warn if this level of the initializer uses member
+              designators; it is likely to be deliberate.  */
+           && !constructor_designated
+           /* Do not warn about initializing with ` = {0}'.  */
+           && !constructor_zeroinit)
          {
            push_member_name (constructor_unfilled_fields);
            warning_init (OPT_Wmissing_field_initializers,
@@ -7522,7 +7598,7 @@ set_nonincremental_init (struct obstack * braced_init_obstack)
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
     {
-      add_pending_init (index, value, NULL_TREE, false,
+      add_pending_init (index, value, NULL_TREE, true,
                        braced_init_obstack);
     }
   constructor_elements = 0;
@@ -7615,7 +7691,7 @@ set_nonincremental_init_from_string (tree str,
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value, NULL_TREE, false,
+      add_pending_init (purpose, value, NULL_TREE, true,
                         braced_init_obstack);
     }
 
@@ -8506,7 +8582,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
         get an error.  Gross, but ...  */
       STRIP_NOPS (output);
 
-      if (!lvalue_or_else (output, lv_asm))
+      if (!lvalue_or_else (loc, output, lv_asm))
        output = error_mark_node;
 
       if (output != error_mark_node
@@ -8527,6 +8603,13 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
             mark it addressable.  */
          if (!allows_reg && !c_mark_addressable (output))
            output = error_mark_node;
+         if (!(!allows_reg && allows_mem)
+             && output != error_mark_node
+             && VOID_TYPE_P (TREE_TYPE (output)))
+           {
+             error_at (loc, "invalid use of void expression");
+             output = error_mark_node;
+           }
        }
       else
        output = error_mark_node;
@@ -8553,7 +8636,12 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
              STRIP_NOPS (input);
              if (!c_mark_addressable (input))
                input = error_mark_node;
-         }
+           }
+         else if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
+           {
+             error_at (loc, "invalid use of void expression");
+             input = error_mark_node;
+           }
        }
       else
        input = error_mark_node;
@@ -9118,7 +9206,11 @@ c_process_expr_stmt (location_t loc, tree expr)
   exprv = expr;
   while (TREE_CODE (exprv) == COMPOUND_EXPR)
     exprv = TREE_OPERAND (exprv, 1);
-  if (DECL_P (exprv) || handled_component_p (exprv))
+  while (CONVERT_EXPR_P (exprv))
+    exprv = TREE_OPERAND (exprv, 0);
+  if (DECL_P (exprv)
+      || handled_component_p (exprv)
+      || TREE_CODE (exprv) == ADDR_EXPR)
     mark_exp_read (exprv);
 
   /* If the expression is not of a type to which we cannot assign a line
@@ -9309,7 +9401,7 @@ c_end_compound_stmt (location_t loc, tree stmt, bool do_scope)
      do the wrong thing for ({ { 1; } }) or ({ 1; { } }).  In particular,
      STATEMENT_LISTs merge, and thus we can lose track of what statement
      was really last.  */
-  if (cur_stmt_list
+  if (building_stmt_list_p ()
       && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
       && TREE_CODE (stmt) != BIND_EXPR)
     {
@@ -9340,6 +9432,88 @@ push_cleanup (tree decl, tree cleanup, bool eh_only)
   TREE_OPERAND (stmt, 0) = list;
   STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
 }
+
+/* Convert scalar to vector for the range of operations.  */
+static enum stv_conv
+scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
+{
+  tree type0 = TREE_TYPE (op0);
+  tree type1 = TREE_TYPE (op1);
+  bool integer_only_op = false;
+  enum stv_conv ret = stv_firstarg;
+
+  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
+             || TREE_CODE (type1) == VECTOR_TYPE);
+  switch (code)
+    {
+      case RSHIFT_EXPR:
+      case LSHIFT_EXPR:
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           else
+             return stv_firstarg;
+         }
+       break;
+
+      case BIT_IOR_EXPR:
+      case BIT_XOR_EXPR:
+      case BIT_AND_EXPR:
+       integer_only_op = true;
+       /* ... fall through ...  */
+
+      case PLUS_EXPR:
+      case MINUS_EXPR:
+      case MULT_EXPR:
+      case TRUNC_DIV_EXPR:
+      case TRUNC_MOD_EXPR:
+      case RDIV_EXPR:
+       if (TREE_CODE (type0) == VECTOR_TYPE)
+         {
+           tree tmp;
+           ret = stv_secondarg;
+           /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
+           tmp = type0; type0 = type1; type1 = tmp;
+           tmp = op0; op0 = op1; op1 = tmp;
+         }
+
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           return ret;
+         }
+       else if (!integer_only_op
+                   /* Allow integer --> real conversion if safe.  */
+                && (TREE_CODE (type0) == REAL_TYPE
+                    || TREE_CODE (type0) == INTEGER_TYPE)
+                && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           return ret;
+         }
+      default:
+       break;
+    }
+
+  return stv_nothing;
+}
 \f
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
@@ -9423,6 +9597,10 @@ build_binary_op (location_t location, enum tree_code code,
      precision.  */
   bool may_need_excess_precision;
 
+  /* True means this is a boolean operation that converts both its
+     operands to truth-values.  */
+  bool boolean_op = false;
+
   if (location == UNKNOWN_LOCATION)
     location = input_location;
 
@@ -9447,7 +9625,10 @@ build_binary_op (location_t location, enum tree_code code,
   else
     int_const = int_const_or_overflow = false;
 
-  if (convert_p)
+  /* Do not apply default conversion in mixed vector/scalar expression.  */
+  if (convert_p
+      && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE)
+          != (TREE_CODE (TREE_TYPE (op1)) == VECTOR_TYPE)))
     {
       op0 = default_conversion (op0);
       op1 = default_conversion (op1);
@@ -9519,6 +9700,51 @@ build_binary_op (location_t location, enum tree_code code,
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* In case when one of the operands of the binary operation is
+     a vector and another is a scalar -- convert scalar to vector.  */
+  if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
+    {
+      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
+
+      switch (convert_flag)
+       {
+         case stv_error:
+           return error_mark_node;
+         case stv_firstarg:
+           {
+              bool maybe_const = true;
+              tree sc;
+              sc = c_fully_fold (op0, false, &maybe_const);
+              sc = save_expr (sc);
+              sc = convert (TREE_TYPE (type1), sc);
+              op0 = build_vector_from_val (type1, sc);
+              if (!maybe_const)
+                op0 = c_wrap_maybe_const (op0, true);
+              orig_type0 = type0 = TREE_TYPE (op0);
+              code0 = TREE_CODE (type0);
+              converted = 1;
+              break;
+           }
+         case stv_secondarg:
+           {
+             bool maybe_const = true;
+             tree sc;
+             sc = c_fully_fold (op1, false, &maybe_const);
+             sc = save_expr (sc);
+             sc = convert (TREE_TYPE (type0), sc);
+             op1 = build_vector_from_val (type0, sc);
+             if (!maybe_const)
+               op1 = c_wrap_maybe_const (op1, true);
+             orig_type1 = type1 = TREE_TYPE (op1);
+             code1 = TREE_CODE (type1);
+             converted = 1;
+             break;
+           }
+         default:
+           break;
+       }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9650,6 +9876,7 @@ build_binary_op (location_t location, enum tree_code code,
          op0 = c_common_truthvalue_conversion (location, op0);
          op1 = c_common_truthvalue_conversion (location, op1);
          converted = 1;
+         boolean_op = true;
        }
       if (code == TRUTH_ANDIF_EXPR)
        {
@@ -9680,7 +9907,21 @@ build_binary_op (location_t location, enum tree_code code,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9707,9 +9948,10 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
-         /* Convert the shift-count to an integer, regardless of size
-            of value being shifted.  */
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9717,7 +9959,21 @@ build_binary_op (location_t location, enum tree_code code,
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9739,9 +9995,10 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
-         /* Convert the shift-count to an integer, regardless of size
-            of value being shifted.  */
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9750,6 +10007,31 @@ build_binary_op (location_t location, enum tree_code code,
 
     case EQ_EXPR:
     case NE_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
        warning_at (location,
                    OPT_Wfloat_equal,
@@ -9789,7 +10071,7 @@ build_binary_op (location_t location, enum tree_code code,
            {
              if (code == EQ_EXPR)
                warning_at (location,
-                           OPT_Waddress, 
+                           OPT_Waddress,
                            "the comparison will always evaluate as %<false%> "
                            "for the address of %qD will never be NULL",
                            TREE_OPERAND (op1, 0));
@@ -9862,6 +10144,31 @@ build_binary_op (location_t location, enum tree_code code,
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == FIXED_POINT_TYPE)
@@ -10021,6 +10328,7 @@ build_binary_op (location_t location, enum tree_code code,
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
+                 op1 = c_save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -10041,6 +10349,7 @@ build_binary_op (location_t location, enum tree_code code,
              switch (code)
                {
                case MULT_EXPR:
+                 op0 = c_save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -10166,7 +10475,7 @@ build_binary_op (location_t location, enum tree_code code,
                warn_for_sign_compare (location, orig_op0_folded,
                                       orig_op1_folded, op0, op1,
                                       result_type, resultcode);
-             if (!in_late_binary_op)
+             if (!in_late_binary_op && !int_operands)
                {
                  if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
                    op0 = c_wrap_maybe_const (op0, !op0_maybe_const);
@@ -10192,7 +10501,8 @@ build_binary_op (location_t location, enum tree_code code,
   if (build_type == NULL_TREE)
     {
       build_type = result_type;
-      if (type0 != orig_type0 || type1 != orig_type1)
+      if ((type0 != orig_type0 || type1 != orig_type1)
+         && !boolean_op)
        {
          gcc_assert (may_need_excess_precision && common);
          semantic_result_type = c_common_type (orig_type0, orig_type1);
@@ -10259,9 +10569,17 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr)
       error_at (location, "used union type value where scalar is required");
       return error_mark_node;
 
+    case VOID_TYPE:
+      error_at (location, "void value not ignored as it ought to be");
+      return error_mark_node;
+
     case FUNCTION_TYPE:
       gcc_unreachable ();
 
+    case VECTOR_TYPE:
+      error_at (location, "used vector type where scalar is required");
+      return error_mark_node;
+
     default:
       break;
     }
@@ -10271,8 +10589,8 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr)
   if (int_operands)
     expr = remove_c_maybe_const_expr (expr);
 
-  /* ??? Should we also give an error for void and vectors rather than
-     leaving those to give errors later?  */
+  /* ??? Should we also give an error for vectors rather than leaving
+     those to give errors later?  */
   expr = c_common_truthvalue_conversion (location, expr);
 
   if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)
@@ -10426,6 +10744,8 @@ c_finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
@@ -10542,6 +10862,8 @@ c_finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
@@ -10571,6 +10893,10 @@ c_finish_omp_clauses (tree clauses)
                case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
                  break;
                case OMP_CLAUSE_DEFAULT_SHARED:
+                 /* const vars may be specified in firstprivate clause.  */
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                     && TREE_READONLY (t))
+                   break;
                  share_name = "shared";
                  break;
                case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -10599,6 +10925,19 @@ c_finish_omp_clauses (tree clauses)
   return clauses;
 }
 
+/* Create a transaction node.  */
+
+tree
+c_finish_transaction (location_t loc, tree block, int flags)
+{
+  tree stmt = build_stmt (loc, TRANSACTION_EXPR, block);
+  if (flags & TM_STMT_ATTR_OUTER)
+    TRANSACTION_EXPR_OUTER (stmt) = 1;
+  if (flags & TM_STMT_ATTR_RELAXED)
+    TRANSACTION_EXPR_RELAXED (stmt) = 1;
+  return add_stmt (stmt);
+}
+
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */