OSDN Git Service

2008-06-12 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 4fb7092..23880d1 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
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -74,12 +74,12 @@ static int missing_braces_mentioned;
 static int require_constant_value;
 static int require_constant_elements;
 
-static bool null_pointer_constant_p (tree);
+static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (tree, tree);
+static int tagged_types_tu_compatible_p (const_tree, const_tree);
 static int comp_target_types (tree, tree);
-static int function_types_compatible_p (tree, tree);
-static int type_lists_compatible_p (tree, tree);
+static int function_types_compatible_p (const_tree, const_tree);
+static int type_lists_compatible_p (const_tree, const_tree);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree lookup_field (tree, tree);
 static int convert_arguments (int, tree *, tree, tree, tree, tree);
@@ -91,7 +91,7 @@ static void push_string (const char *);
 static void push_member_name (tree);
 static int spelling_length (void);
 static char *print_spelling (char *);
-static void warning_init (const char *);
+static void warning_init (int, const char *);
 static tree digest_init (tree, tree, bool, int);
 static void output_init_element (tree, bool, tree, tree, int);
 static void output_pending_init_elements (int);
@@ -102,15 +102,15 @@ static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
 static void readonly_error (tree, enum lvalue_use);
-static int lvalue_or_else (tree, enum lvalue_use);
-static int lvalue_p (tree);
+static int lvalue_or_else (const_tree, enum lvalue_use);
+static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (tree, tree);
+static int comptypes_internal (const_tree, const_tree);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
 static bool
-null_pointer_constant_p (tree expr)
+null_pointer_constant_p (const_tree expr)
 {
   /* This should really operate on c_expr structures, but they aren't
      yet available everywhere required.  */
@@ -127,8 +127,8 @@ null_pointer_constant_p (tree expr)
 
 struct tagged_tu_seen_cache {
   const struct tagged_tu_seen_cache * next;
-  tree t1;
-  tree t2;
+  const_tree t1;
+  const_tree t2;
   /* The return value of tagged_types_tu_compatible_p if we had seen
      these two types already.  */
   int val;
@@ -161,7 +161,7 @@ require_complete_type (tree value)
    and TYPE is the type that was invalid.  */
 
 void
-c_incomplete_type_error (tree value, tree type)
+c_incomplete_type_error (const_tree value, const_tree type)
 {
   const char *type_code_string;
 
@@ -256,7 +256,7 @@ qualify_type (tree type, tree like)
 /* Return true iff the given tree T is a variable length array.  */
 
 bool
-c_vla_type_p (tree t)
+c_vla_type_p (const_tree t)
 {
   if (TREE_CODE (t) == ARRAY_TYPE
       && C_TYPE_VARIABLE_SIZE (t))
@@ -530,6 +530,7 @@ common_pointer_type (tree t1, tree t2)
   tree pointed_to_1, mv1;
   tree pointed_to_2, mv2;
   tree target;
+  unsigned target_quals;
 
   /* Save time if the two types are the same.  */
 
@@ -557,10 +558,15 @@ common_pointer_type (tree t1, tree t2)
   if (TREE_CODE (mv2) != ARRAY_TYPE)
     mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
   target = composite_type (mv1, mv2);
-  t1 = build_pointer_type (c_build_qualified_type
-                          (target,
-                           TYPE_QUALS (pointed_to_1) |
-                           TYPE_QUALS (pointed_to_2)));
+
+  /* For function types do not merge const qualifiers, but drop them
+     if used inconsistently.  The middle-end uses these to mark const
+     and noreturn functions.  */
+  if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
+    target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
+  else
+    target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
+  t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
   return build_type_attribute_variant (t1, attributes);
 }
 
@@ -604,9 +610,11 @@ c_common_type (tree t1, tree t2)
   code2 = TREE_CODE (t2);
 
   gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
-             || code1 == REAL_TYPE || code1 == INTEGER_TYPE);
+             || code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
+             || code1 == INTEGER_TYPE);
   gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
-             || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
+             || code2 == FIXED_POINT_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
@@ -681,6 +689,91 @@ c_common_type (tree t1, tree t2)
        return dfloat32_type_node;
     }
 
+  /* Deal with fixed-point types.  */
+  if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE)
+    {
+      unsigned int unsignedp = 0, satp = 0;
+      enum machine_mode m1, m2;
+      unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit;
+
+      m1 = TYPE_MODE (t1);
+      m2 = TYPE_MODE (t2);
+
+      /* If one input type is saturating, the result type is saturating.  */
+      if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2))
+       satp = 1;
+
+      /* If both fixed-point types are unsigned, the result type is unsigned.
+        When mixing fixed-point and integer types, follow the sign of the
+        fixed-point type.
+        Otherwise, the result type is signed.  */
+      if ((TYPE_UNSIGNED (t1) && TYPE_UNSIGNED (t2)
+          && code1 == FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE)
+         || (code1 == FIXED_POINT_TYPE && code2 != FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t1))
+         || (code1 != FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t2)))
+       unsignedp = 1;
+
+      /* The result type is signed.  */
+      if (unsignedp == 0)
+       {
+         /* If the input type is unsigned, we need to convert to the
+            signed type.  */
+         if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
+           {
+             unsigned char mclass = 0;
+             if (GET_MODE_CLASS (m1) == MODE_UFRACT)
+               mclass = MODE_FRACT;
+             else if (GET_MODE_CLASS (m1) == MODE_UACCUM)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0);
+           }
+         if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
+           {
+             unsigned char mclass = 0;
+             if (GET_MODE_CLASS (m2) == MODE_UFRACT)
+               mclass = MODE_FRACT;
+             else if (GET_MODE_CLASS (m2) == MODE_UACCUM)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0);
+           }
+       }
+
+      if (code1 == FIXED_POINT_TYPE)
+       {
+         fbit1 = GET_MODE_FBIT (m1);
+         ibit1 = GET_MODE_IBIT (m1);
+       }
+      else
+       {
+         fbit1 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit1 = TYPE_PRECISION (t1) - (!TYPE_UNSIGNED (t1));
+       }
+
+      if (code2 == FIXED_POINT_TYPE)
+       {
+         fbit2 = GET_MODE_FBIT (m2);
+         ibit2 = GET_MODE_IBIT (m2);
+       }
+      else
+       {
+         fbit2 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit2 = TYPE_PRECISION (t2) - (!TYPE_UNSIGNED (t2));
+       }
+
+      max_ibit = ibit1 >= ibit2 ?  ibit1 : ibit2;
+      max_fbit = fbit1 >= fbit2 ?  fbit1 : fbit2;
+      return c_common_fixed_point_type_for_size (max_ibit, max_fbit, unsignedp,
+                                                satp);
+    }
+
   /* Both real or both integers; use the one with greater precision.  */
 
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
@@ -782,10 +875,10 @@ comptypes (tree type1, tree type2)
    differs from comptypes, in that we don't free the seen types.  */
 
 static int
-comptypes_internal (tree type1, tree type2)
+comptypes_internal (const_tree type1, const_tree type2)
 {
-  tree t1 = type1;
-  tree t2 = type2;
+  const_tree t1 = type1;
+  const_tree t2 = type2;
   int attrval, val;
 
   /* Suppress errors caused by previously reported errors.  */
@@ -958,7 +1051,7 @@ comp_target_types (tree ttl, tree ttr)
    being parsed, so if two trees have context chains ending in null,
    they're in the same translation unit.  */
 int
-same_translation_unit_p (tree t1, tree t2)
+same_translation_unit_p (const_tree t1, const_tree t2)
 {
   while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t1)))
@@ -990,7 +1083,7 @@ same_translation_unit_p (tree t1, tree t2)
 /* Allocate the seen two types, assuming that they are compatible. */
 
 static struct tagged_tu_seen_cache *
-alloc_tagged_tu_seen_cache (tree t1, tree t2)
+alloc_tagged_tu_seen_cache (const_tree t1, const_tree t2)
 {
   struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
   tu->next = tagged_tu_seen_base;
@@ -1026,7 +1119,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
       const struct tagged_tu_seen_cache *const tu1
        = (const struct tagged_tu_seen_cache *) tu;
       tu = tu1->next;
-      free (CONST_CAST (tu1));
+      free (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
     }
   tagged_tu_seen_base = tu_til;
 }
@@ -1038,7 +1131,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
    rules.  */
 
 static int
-tagged_types_tu_compatible_p (tree t1, tree t2)
+tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1146,11 +1239,12 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
          {
            int result;
 
-
-           if (DECL_NAME (s1) == NULL
-               || DECL_NAME (s1) != DECL_NAME (s2))
+           if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+
+           if (result != 1 && !DECL_NAME (s1))
+             break;
            if (result == 0)
              {
                tu->val = 0;
@@ -1177,28 +1271,31 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
          {
            bool ok = false;
 
-           if (DECL_NAME (s1) != NULL)
-             for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
-               if (DECL_NAME (s1) == DECL_NAME (s2))
-                 {
-                   int result;
-                   result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
-                   if (result == 0)
-                     {
-                       tu->val = 0;
-                       return 0;
-                     }
-                   if (result == 2)
-                     needs_warning = true;
+           for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
+             if (DECL_NAME (s1) == DECL_NAME (s2))
+               {
+                 int result;
 
-                   if (TREE_CODE (s1) == FIELD_DECL
-                       && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
-                                            DECL_FIELD_BIT_OFFSET (s2)) != 1)
-                     break;
+                 result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
 
-                   ok = true;
+                 if (result != 1 && !DECL_NAME (s1))
+                   continue;
+                 if (result == 0)
+                   {
+                     tu->val = 0;
+                     return 0;
+                   }
+                 if (result == 2)
+                   needs_warning = true;
+
+                 if (TREE_CODE (s1) == FIELD_DECL
+                     && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+                                          DECL_FIELD_BIT_OFFSET (s2)) != 1)
                    break;
-                 }
+
+                 ok = true;
+                 break;
+               }
            if (!ok)
              {
                tu->val = 0;
@@ -1252,7 +1349,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
    Otherwise, the argument types must match.  */
 
 static int
-function_types_compatible_p (tree f1, tree f2)
+function_types_compatible_p (const_tree f1, const_tree f2)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1315,7 +1412,7 @@ function_types_compatible_p (tree f1, tree f2)
    or 2 for compatible with warning.  */
 
 static int
-type_lists_compatible_p (tree args1, tree args2)
+type_lists_compatible_p (const_tree args1, const_tree args2)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1416,7 +1513,7 @@ type_lists_compatible_p (tree args1, tree args2)
 /* Compute the size to increment a pointer by.  */
 
 static tree
-c_size_in_bytes (tree type)
+c_size_in_bytes (const_tree type)
 {
   enum tree_code code = TREE_CODE (type);
 
@@ -1560,8 +1657,7 @@ default_function_array_conversion (struct c_expr exp)
        bool lvalue_array_p;
 
        while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
-               || TREE_CODE (exp.value) == NOP_EXPR
-               || TREE_CODE (exp.value) == CONVERT_EXPR)
+               || CONVERT_EXPR_P (exp.value))
               && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
          {
            if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
@@ -1683,14 +1779,19 @@ default_conversion (tree exp)
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
-  if (INTEGRAL_TYPE_P (type))
-    return perform_integral_promotions (exp);
-
   if (code == VOID_TYPE)
     {
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+
+  exp = require_complete_type (exp);
+  if (exp == error_mark_node)
+    return error_mark_node;
+
+  if (INTEGRAL_TYPE_P (type))
+    return perform_integral_promotions (exp);
+
   return exp;
 }
 \f
@@ -1876,8 +1977,7 @@ build_indirect_ref (tree ptr, const char *errorstring)
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
-      if (TREE_CODE (pointer) == CONVERT_EXPR
-          || TREE_CODE (pointer) == NOP_EXPR
+      if (CONVERT_EXPR_P (pointer)
           || TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
        {
          /* If a warning is issued, mark it to avoid duplicates from
@@ -2021,8 +2121,6 @@ build_array_ref (tree array, tree index)
        }
 
       type = TREE_TYPE (TREE_TYPE (array));
-      if (TREE_CODE (type) != ARRAY_TYPE)
-       type = TYPE_MAIN_VARIANT (type);
       rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
         or if the array is.  */
@@ -2113,7 +2211,6 @@ build_external_ref (tree id, int fun, location_t loc)
       used_types_insert (TREE_TYPE (ref));
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
-      TREE_INVARIANT (ref) = 1;
     }
   else if (current_function_decl != 0
           && !DECL_FILE_SCOPE_P (current_function_decl)
@@ -2134,7 +2231,8 @@ build_external_ref (tree id, int fun, location_t loc)
           && DECL_EXTERNAL (current_function_decl)
           && VAR_OR_FUNCTION_DECL_P (ref)
           && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
-          && ! TREE_PUBLIC (ref))
+          && ! TREE_PUBLIC (ref)
+          && DECL_CONTEXT (ref) != current_function_decl)
     pedwarn ("%H%qD is static but used in inline function %qD "
             "which is not static", &loc, ref, current_function_decl);
 
@@ -2298,8 +2396,7 @@ 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.  */
-  if ((TREE_CODE (function) == NOP_EXPR
-       || TREE_CODE (function) == CONVERT_EXPR)
+  if (CONVERT_EXPR_P (function)
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
       && !comptypes (fntype, TREE_TYPE (tem)))
@@ -2343,8 +2440,14 @@ build_function_call (tree function, tree params)
   if (nargs < 0)
     return error_mark_node;
 
-  /* Check that the arguments to the function are valid.  */
+  /* Check that arguments to builtin functions match the expectations.  */
+  if (fundecl
+      && DECL_BUILT_IN (fundecl)
+      && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
+      && !check_builtin_function_arguments (fundecl, nargs, argarray))
+    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));
 
@@ -2715,13 +2818,13 @@ 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.  */
-  if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR)
+  if (CONVERT_EXPR_P (op0)
       && (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)
+  if (CONVERT_EXPR_P (op1)
       && (TYPE_PRECISION (TREE_TYPE (op1))
          == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
     con1 = TREE_OPERAND (op1, 0);
@@ -2784,11 +2887,15 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
   /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
   tree arg = xarg;
   tree argtype = 0;
-  enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
+  enum tree_code typecode;
   tree val;
   int noconvert = flag;
   const char *invalid_op_diag;
 
+  if (code != ADDR_EXPR)
+    arg = require_complete_type (arg);
+
+  typecode = TREE_CODE (TREE_TYPE (arg));
   if (typecode == ERROR_MARK)
     return error_mark_node;
   if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
@@ -2808,7 +2915,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
         is enough to prevent anybody from looking inside for
         associativity, but won't generate any code.  */
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE
+           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
            || typecode == VECTOR_TYPE))
        {
          error ("wrong type argument to unary plus");
@@ -2821,7 +2928,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
     case NEGATE_EXPR:
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE
+           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
            || typecode == VECTOR_TYPE))
        {
          error ("wrong type argument to unary minus");
@@ -2878,7 +2985,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       break;
 
     case TRUTH_NOT_EXPR:
-      if (typecode != INTEGER_TYPE
+      if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
          && typecode != REAL_TYPE && typecode != POINTER_TYPE
          && typecode != COMPLEX_TYPE)
        {
@@ -2931,7 +3038,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
       /* Report invalid types.  */
 
-      if (typecode != POINTER_TYPE
+      if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
          if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
@@ -2975,6 +3082,25 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
            inc = c_size_in_bytes (TREE_TYPE (result_type));
            inc = fold_convert (sizetype, inc);
          }
+       else if (FRACT_MODE_P (TYPE_MODE (result_type)))
+         {
+           /* For signed fract types, we invert ++ to -- or
+              -- to ++, and change inc from 1 to -1, because
+              it is not possible to represent 1 in signed fract constants.
+              For unsigned fract types, the result always overflows and
+              we get an undefined (original) or the maximum value.  */
+           if (code == PREINCREMENT_EXPR)
+             code = PREDECREMENT_EXPR;
+           else if (code == PREDECREMENT_EXPR)
+             code = PREINCREMENT_EXPR;
+           else if (code == POSTINCREMENT_EXPR)
+             code = POSTDECREMENT_EXPR;
+           else /* code == POSTDECREMENT_EXPR  */
+             code = POSTINCREMENT_EXPR;
+
+           inc = integer_minus_one_node;
+           inc = convert (argtype, inc);
+         }
        else
          {
            inc = integer_one_node;
@@ -3092,9 +3218,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
    Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
 
 static int
-lvalue_p (tree ref)
+lvalue_p (const_tree ref)
 {
-  enum tree_code code = TREE_CODE (ref);
+  const enum tree_code code = TREE_CODE (ref);
 
   switch (code)
     {
@@ -3168,7 +3294,7 @@ readonly_error (tree arg, enum lvalue_use use)
    how the lvalue is being used and so selects the error message.  */
 
 static int
-lvalue_or_else (tree ref, enum lvalue_use use)
+lvalue_or_else (const_tree ref, enum lvalue_use use)
 {
   int win = lvalue_p (ref);
 
@@ -3326,7 +3452,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
                           && tree_expr_nonnegative_warnv_p (op2, &ovf)))
                /* OK */;
              else
-               warning (0, "signed and unsigned type in conditional expression");
+               warning (OPT_Wsign_compare, "signed and unsigned type in conditional expression");
            }
        }
     }
@@ -3421,18 +3547,16 @@ build_compound_expr (tree expr1, tree expr2)
   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 -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))
-             && (TREE_CODE (expr1) == NOP_EXPR
-                 || TREE_CODE (expr1) == CONVERT_EXPR))
+             && CONVERT_EXPR_P (expr1))
            ; /* (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)) == NOP_EXPR))
+                  && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
            ; /* (void) a, (void) b, c */
          else
            warning (OPT_Wunused_value, 
@@ -3483,6 +3607,13 @@ build_c_cast (tree type, tree expr)
       return error_mark_node;
     }
 
+  if (!VOID_TYPE_P (type))
+    {
+      value = require_complete_type (value);
+      if (value == error_mark_node)
+       return error_mark_node;
+    }
+
   if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
     {
       if (pedantic)
@@ -3497,8 +3628,9 @@ build_c_cast (tree type, tree expr)
       tree field;
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-       if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
-                      TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+       if (TREE_TYPE (field) != error_mark_node
+           && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
+                         TYPE_MAIN_VARIANT (TREE_TYPE (value))))
          break;
 
       if (field)
@@ -3511,7 +3643,6 @@ build_c_cast (tree type, tree expr)
                           build_constructor_single (type, field, value),
                           true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
-         TREE_INVARIANT (t) = TREE_INVARIANT (value);
          return t;
        }
       error ("cast to union type from type not present in union");
@@ -3892,6 +4023,9 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+  rhs = require_complete_type (rhs);
+  if (rhs == error_mark_node)
+    return error_mark_node;
   /* A type converts to a reference to it.
      This code doesn't fully support references, it's just for the
      special case of va_start and va_copy.  */
@@ -3924,9 +4058,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
+           || codel == FIXED_POINT_TYPE
            || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
            || codel == BOOLEAN_TYPE)
           && (coder == INTEGER_TYPE || coder == REAL_TYPE
+              || coder == FIXED_POINT_TYPE
               || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
               || coder == BOOLEAN_TYPE))
     return convert_and_check (type, rhs);
@@ -4039,6 +4175,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
          if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)))
            pedwarn ("ISO C prohibits argument conversion to union type");
 
+         rhs = fold_convert (TREE_TYPE (memb), rhs);
          return build_constructor_single (type, memb, rhs);
        }
     }
@@ -4499,19 +4636,21 @@ pedwarn_init (const char *msgid)
     pedwarn ("(near initialization for %qs)", ofwhat);
 }
 
-/* Issue a warning for a bad initializer component.
-   MSGID identifies the message.
-   The component name is taken from the spelling stack.  */
+/* Issue a warning for a bad initializer component.  
+
+   OPT is the OPT_W* value corresponding to the warning option that
+   controls this warning.  MSGID identifies the message.  The
+   component name is taken from the spelling stack.  */
 
 static void
-warning_init (const char *msgid)
+warning_init (int opt, const char *msgid)
 {
   char *ofwhat;
 
-  warning (0, "%s", _(msgid));
+  warning (opt, "%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    warning (0, "(near initialization for %qs)", ofwhat);
+    warning (opt, "(near initialization for %qs)", ofwhat);
 }
 \f
 /* If TYPE is an array type and EXPR is a parenthesized string
@@ -4745,9 +4884,9 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
   /* Handle scalar types, including conversions.  */
 
-  if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
-      || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
-      || code == VECTOR_TYPE)
+  if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE
+      || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
+      || code == COMPLEX_TYPE || code == VECTOR_TYPE)
     {
       if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
          && (TREE_CODE (init) == STRING_CST
@@ -5278,7 +5417,7 @@ push_init_level (int implicit)
   if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
     {
       missing_braces_mentioned = 1;
-      warning_init ("missing braces around initializer");
+      warning_init (OPT_Wmissing_braces, "missing braces around initializer");
     }
 
   if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -5339,7 +5478,7 @@ push_init_level (int implicit)
   else
     {
       if (constructor_type != error_mark_node)
-       warning_init ("braces around scalar initializer");
+       warning_init (0, "braces around scalar initializer");
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
@@ -5425,7 +5564,8 @@ pop_init_level (int implicit)
        if (constructor_unfilled_fields && !constructor_designated)
          {
            push_member_name (constructor_unfilled_fields);
-           warning_init ("missing initializer");
+           warning_init (OPT_Wmissing_field_initializers,
+                          "missing initializer");
            RESTORE_SPELLING_DEPTH (constructor_depth);
          }
     }
@@ -5467,7 +5607,7 @@ pop_init_level (int implicit)
          ret.value = build_constructor (constructor_type,
                                         constructor_elements);
          if (constructor_constant)
-           TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
+           TREE_CONSTANT (ret.value) = 1;
          if (constructor_constant && constructor_simple)
            TREE_STATIC (ret.value) = 1;
        }
@@ -5709,9 +5849,9 @@ add_pending_init (tree purpose, tree value)
          else
            {
              if (TREE_SIDE_EFFECTS (p->value))
-               warning_init ("initialized field with side-effects overwritten");
+               warning_init (0, "initialized field with side-effects overwritten");
              else if (warn_override_init)
-               warning_init ("initialized field overwritten");
+               warning_init (OPT_Woverride_init, "initialized field overwritten");
              p->value = value;
              return;
            }
@@ -5732,9 +5872,9 @@ add_pending_init (tree purpose, tree value)
          else
            {
              if (TREE_SIDE_EFFECTS (p->value))
-               warning_init ("initialized field with side-effects overwritten");
+               warning_init (0, "initialized field with side-effects overwritten");
              else if (warn_override_init)
-               warning_init ("initialized field overwritten");
+               warning_init (OPT_Woverride_init, "initialized field overwritten");
              p->value = value;
              return;
            }
@@ -6206,9 +6346,9 @@ 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");
+       warning_init (0, "initialized field with side-effects overwritten");
       else if (warn_override_init)
-       warning_init ("initialized field overwritten");
+       warning_init (OPT_Woverride_init, "initialized field overwritten");
 
       /* We can have just one union field set.  */
       constructor_elements = 0;
@@ -6980,7 +7120,7 @@ c_finish_return (tree retval)
        {
          switch (TREE_CODE (inner))
            {
-           case NOP_EXPR:   case NON_LVALUE_EXPR:  case CONVERT_EXPR:
+           CASE_CONVERT:   case NON_LVALUE_EXPR:
            case PLUS_EXPR:
              inner = TREE_OPERAND (inner, 0);
              continue;
@@ -6993,9 +7133,8 @@ c_finish_return (tree retval)
                tree op1 = TREE_OPERAND (inner, 1);
 
                while (!POINTER_TYPE_P (TREE_TYPE (op1))
-                      && (TREE_CODE (op1) == NOP_EXPR
-                          || TREE_CODE (op1) == NON_LVALUE_EXPR
-                          || TREE_CODE (op1) == CONVERT_EXPR))
+                      && (CONVERT_EXPR_P (op1)
+                          || TREE_CODE (op1) == NON_LVALUE_EXPR))
                  op1 = TREE_OPERAND (op1, 0);
 
                if (POINTER_TYPE_P (TREE_TYPE (op1)))
@@ -7363,6 +7502,9 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
   if (skip)
     return NULL_TREE;
 
+  if (!is_break)
+    add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
+
   return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
 }
 
@@ -7861,8 +8003,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       warn_for_div_by_zero (op1);
 
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE
           || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE
              || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
        {
          enum tree_code tcode0 = code0, tcode1 = code1;
@@ -7872,7 +8016,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
            tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
 
-         if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
+         if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)
+             || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
            resultcode = RDIV_EXPR;
          else
            /* Although it would be tempting to shorten always here, that
@@ -7892,7 +8037,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case BIT_XOR_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        shorten = -1;
-      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+      /* Allow vector types which are not floating point types.   */
+      else if (code0 == VECTOR_TYPE
+              && code1 == VECTOR_TYPE
+              && !VECTOR_FLOAT_TYPE_P (type0)
+              && !VECTOR_FLOAT_TYPE_P (type1))
        common = 1;
       break;
 
@@ -7919,9 +8068,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
       if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
-          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+          || code0 == FIXED_POINT_TYPE)
          && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
-             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+             || code1 == FIXED_POINT_TYPE))
        {
          /* Result of these operations is always an int,
             but that does not mean the operands should be
@@ -7938,7 +8089,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
@@ -7966,7 +8118,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       break;
 
     case LSHIFT_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
@@ -7990,16 +8143,16 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case EQ_EXPR:
     case NE_EXPR:
-      if (code0 == REAL_TYPE || code1 == REAL_TYPE)
+      if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
        warning (OPT_Wfloat_equal,
                 "comparing floating point with == or != is unsafe");
       /* Result of comparison is always int,
         but don't convert the args to int!  */
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == COMPLEX_TYPE)
+          || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == COMPLEX_TYPE))
+             || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
@@ -8067,8 +8220,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case LT_EXPR:
     case GT_EXPR:
       build_type = integer_type_node;
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE)
+         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
@@ -8129,10 +8284,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     }
 
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
-       || code0 == VECTOR_TYPE)
+       || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE)
       &&
       (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
-       || code1 == VECTOR_TYPE))
+       || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
     {
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
@@ -8358,7 +8513,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                            c_common_signed_type (result_type)))
                    /* OK */;
                  else
-                   warning (0, "comparison between signed and unsigned");
+                   warning (OPT_Wsign_compare, "comparison between signed and unsigned");
                }
 
              /* Warn if two unsigned values are being compared in a size
@@ -8404,7 +8559,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                        {
                          mask = (~(HOST_WIDE_INT) 0) << bits;
                          if ((mask & constant) != mask)
-                           warning (0, "comparison of promoted ~unsigned with constant");
+                           warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with constant");
                        }
                    }
                  else if (unsignedp0 && unsignedp1
@@ -8412,7 +8567,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                               < TYPE_PRECISION (result_type))
                           && (TYPE_PRECISION (TREE_TYPE (primop1))
                               < TYPE_PRECISION (result_type)))
-                   warning (0, "comparison of promoted ~unsigned with unsigned");
+                   warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with unsigned");
                }
            }
        }
@@ -8498,8 +8653,7 @@ c_objc_common_truthvalue_conversion (tree expr)
    required.  */
 
 tree
-c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
-               bool *ti ATTRIBUTE_UNUSED, bool *se)
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
 {
   if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
     {
@@ -8527,6 +8681,8 @@ c_begin_omp_parallel (void)
   return block;
 }
 
+/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound statement.  */
+
 tree
 c_finish_omp_parallel (tree clauses, tree block)
 {
@@ -8542,6 +8698,36 @@ c_finish_omp_parallel (tree clauses, tree block)
   return add_stmt (stmt);
 }
 
+/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
+
+tree
+c_begin_omp_task (void)
+{
+  tree block;
+
+  keep_next_level ();
+  block = c_begin_compound_stmt (true);
+
+  return block;
+}
+
+/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound statement.  */
+
+tree
+c_finish_omp_task (tree clauses, tree block)
+{
+  tree stmt;
+
+  block = c_end_compound_stmt (block, true);
+
+  stmt = make_node (OMP_TASK);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_TASK_CLAUSES (stmt) = clauses;
+  OMP_TASK_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.  */
 
@@ -8702,6 +8888,8 @@ c_finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_DEFAULT:
+       case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_COLLAPSE:
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
@@ -8757,3 +8945,68 @@ c_finish_omp_clauses (tree clauses)
   bitmap_obstack_release (NULL);
   return clauses;
 }
+
+/* Make a variant type in the proper way for C/C++, propagating qualifiers
+   down to the element type of an array.  */
+
+tree
+c_build_qualified_type (tree type, int type_quals)
+{
+  if (type == error_mark_node)
+    return type;
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree t;
+      tree element_type = c_build_qualified_type (TREE_TYPE (type),
+                                                 type_quals);
+
+      /* See if we already have an identically qualified type.  */
+      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         if (TYPE_QUALS (strip_array_types (t)) == type_quals
+             && TYPE_NAME (t) == TYPE_NAME (type)
+             && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+             && attribute_list_equal (TYPE_ATTRIBUTES (t),
+                                      TYPE_ATTRIBUTES (type)))
+           break;
+       }
+      if (!t)
+       {
+          tree domain = TYPE_DOMAIN (type);
+
+         t = build_variant_type_copy (type);
+         TREE_TYPE (t) = element_type;
+
+          if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
+              || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
+            SET_TYPE_STRUCTURAL_EQUALITY (t);
+          else if (TYPE_CANONICAL (element_type) != element_type
+                   || (domain && TYPE_CANONICAL (domain) != domain))
+            {
+              tree unqualified_canon 
+                = build_array_type (TYPE_CANONICAL (element_type),
+                                    domain? TYPE_CANONICAL (domain) 
+                                          : NULL_TREE);
+              TYPE_CANONICAL (t) 
+                = c_build_qualified_type (unqualified_canon, type_quals);
+            }
+          else
+            TYPE_CANONICAL (t) = t;
+       }
+      return t;
+    }
+
+  /* A restrict-qualified pointer type must be a pointer to object or
+     incomplete type.  Note that the use of POINTER_TYPE_P also allows
+     REFERENCE_TYPEs, which is appropriate for C++.  */
+  if ((type_quals & TYPE_QUAL_RESTRICT)
+      && (!POINTER_TYPE_P (type)
+         || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+    {
+      error ("invalid use of %<restrict%>");
+      type_quals &= ~TYPE_QUAL_RESTRICT;
+    }
+
+  return build_qualified_type (type, type_quals);
+}