OSDN Git Service

2012-02-01 Tristan Gingold <gingold@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 09e9ca7..2de1e5c 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,6 +51,14 @@ enum impl_conv {
   ic_return
 };
 
+/* 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;
 
@@ -97,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
@@ -387,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);
       }
@@ -508,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;
@@ -593,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 ...  */
@@ -1011,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
@@ -1080,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.  */
@@ -2267,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;
 }
 
@@ -2322,7 +2307,7 @@ build_array_ref (location_t loc, tree array, tree index)
       if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
-          error_at (loc, 
+          error_at (loc,
             "subscripted value is neither array nor pointer nor vector");
 
          return error_mark_node;
@@ -2354,8 +2339,8 @@ build_array_ref (location_t loc, tree array, tree index)
   index = default_conversion (index);
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
-  
-  /* For vector[index], convert the vector to a 
+
+  /* For vector[index], convert the vector to a
      pointer of the underlying type.  */
   if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE)
     {
@@ -2363,11 +2348,11 @@ build_array_ref (location_t loc, tree array, tree index)
       tree type1;
 
       if (TREE_CODE (index) == INTEGER_CST)
-        if (!host_integerp (index, 1) 
-            || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1) 
+        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);
@@ -2731,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);
@@ -2781,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;
 
@@ -2831,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))
@@ -2861,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.
@@ -3183,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");
@@ -3582,8 +3666,9 @@ build_unary_op (location_t location,
 
       /* Complain about anything that is not a true lvalue.  In
         Objective-C, skip this check for property_refs.  */
-      if (!objc_is_property_ref (arg) 
-         && !lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
+      if (!objc_is_property_ref (arg)
+         && !lvalue_or_else (location,
+                             arg, ((code == PREINCREMENT_EXPR
                                     || code == POSTINCREMENT_EXPR)
                                    ? lv_increment
                                    : lv_decrement)))
@@ -3667,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)))
          {
@@ -3698,7 +3783,7 @@ build_unary_op (location_t location,
           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, 
+         return objc_build_incr_expr_for_property_ref (location, code,
                                                        arg, inc);
 
        /* Report a read-only lvalue.  */
@@ -3755,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
@@ -3787,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;
@@ -3800,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);
        }
 
@@ -3820,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;
        }
 
@@ -3898,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.  */
 
@@ -3962,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;
 }
@@ -4858,7 +4894,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
     return error_mark_node;
 
   /* For ObjC properties, defer this check.  */
-  if (!objc_is_property_ref (lhs) && !lvalue_or_else (lhs, lv_assign))
+  if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
     return error_mark_node;
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
@@ -4908,7 +4944,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
        return result;
 
       /* Else, do the check that we postponed for Objective-C.  */
-      if (!lvalue_or_else (lhs, lv_assign))
+      if (!lvalue_or_else (location, lhs, lv_assign))
        return error_mark_node;
     }
 
@@ -5329,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;
     }
@@ -5605,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.  */
@@ -5832,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));
            }
        }
     }
@@ -5989,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));
@@ -6701,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;
     }
@@ -6870,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)
@@ -6991,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,
@@ -8540,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
@@ -8561,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;
@@ -8587,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;
@@ -9152,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
@@ -9343,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)
     {
@@ -9374,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.
@@ -9485,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);
@@ -9557,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)
+               op0 = 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:
@@ -9819,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,
@@ -9858,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));
@@ -9931,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)
@@ -10090,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:
@@ -10110,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:
@@ -10235,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);
@@ -10329,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;
     }
@@ -10341,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)
@@ -10496,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 = "&";
@@ -10612,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;
 
@@ -10641,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:
@@ -10669,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.  */