OSDN Git Service

* c-common.c (shadow_warning): Delete.
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 423d6bd..95a2c34 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 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -35,6 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "langhooks.h"
 #include "c-tree.h"
 #include "tm_p.h"
 #include "flags.h"
@@ -50,6 +51,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 static int missing_braces_mentioned;
 
 static tree qualify_type (tree, tree);
+static int same_translation_unit_p (tree, tree);
 static int tagged_types_tu_compatible_p (tree, tree, int);
 static int comp_target_types (tree, tree, int);
 static int function_types_compatible_p (tree, tree, int);
@@ -59,8 +61,6 @@ static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
-static tree unary_complex_lvalue (enum tree_code, tree, int);
-static void pedantic_lvalue_warning (enum tree_code);
 static tree internal_build_compound_expr (tree, int);
 static tree convert_for_assignment (tree, tree, const char *, tree, tree,
                                    int);
@@ -473,12 +473,13 @@ comptypes (tree type1, tree type2, int flags)
       && TYPE_DOMAIN (t2) != 0)
     t2 = TYPE_DOMAIN (t2);
 
-  /* Treat an enum type as the integer type of the same width and
-     signedness.  */
+  /* Enumerated types are compatible with integer types, but this is
+     not transitive: two enumerated types in the same translation unit
+     are compatible with each other only if they are the same type.  */
 
-  if (TREE_CODE (t1) == ENUMERAL_TYPE)
+  if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
     t1 = c_common_type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
-  if (TREE_CODE (t2) == ENUMERAL_TYPE)
+  else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
     t2 = c_common_type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
 
   if (t1 == t2)
@@ -510,8 +511,12 @@ comptypes (tree type1, tree type2, int flags)
   switch (TREE_CODE (t1))
     {
     case POINTER_TYPE:
+      /* We must give ObjC the first crack at comparing pointers, since
+          protocol qualifiers may be involved.  */
+      if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0)
+       break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-             ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags));
+            ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags));
       break;
 
     case FUNCTION_TYPE:
@@ -559,12 +564,14 @@ comptypes (tree type1, tree type2, int flags)
       }
 
     case RECORD_TYPE:
+      /* We are dealing with two distinct structs.  In assorted Objective-C
+        corner cases, however, these can still be deemed equivalent.  */
       if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1)
        val = 1;
 
     case ENUMERAL_TYPE:
     case UNION_TYPE:
-      if (val != 1 && (flags & COMPARE_DIFFERENT_TU))
+      if (val != 1 && !same_translation_unit_p (t1, t2))
        val = tagged_types_tu_compatible_p (t1, t2, flags);
       break;
 
@@ -606,6 +613,34 @@ comp_target_types (tree ttl, tree ttr, int reflexive)
 \f
 /* Subroutines of `comptypes'.  */
 
+/* Determine whether two types derive from the same translation unit.
+   If the CONTEXT chain ends in a null, that type's context is still
+   being parsed, so if two types have context chains ending in null,
+   they're in the same translation unit.  */
+static int
+same_translation_unit_p (tree t1, tree t2)
+{
+  while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
+    switch (TREE_CODE_CLASS (TREE_CODE (t1)))
+      {
+      case 'd': t1 = DECL_CONTEXT (t1); break;
+      case 't': t1 = TYPE_CONTEXT (t1); break;
+      case 'b': t1 = BLOCK_SUPERCONTEXT (t1); break;
+      default: abort ();
+      }
+
+  while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
+    switch (TREE_CODE_CLASS (TREE_CODE (t2)))
+      {
+      case 'd': t2 = DECL_CONTEXT (t1); break;
+      case 't': t2 = TYPE_CONTEXT (t2); break;
+      case 'b': t2 = BLOCK_SUPERCONTEXT (t2); break;
+      default: abort ();
+      }
+
+  return t1 == t2;
+}
+
 /* The C standard says that two structures in different translation
    units are compatible with each other only if the types of their
    fields are compatible (among other things).  So, consider two copies
@@ -1267,7 +1302,7 @@ build_component_ref (tree datum, tree component)
   tree ref;
 
   /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
-     If pedantic ensure that the arguments are not lvalues; otherwise,
+     Ensure that the arguments are not lvalues; otherwise,
      if the component is an array, it would wrongly decay to a pointer in
      C89 mode.
      We cannot do this with a COND_EXPR, because in a conditional expression
@@ -1280,7 +1315,7 @@ build_component_ref (tree datum, tree component)
       {
        tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
        return build (COMPOUND_EXPR, TREE_TYPE (value),
-                     TREE_OPERAND (datum, 0), pedantic_non_lvalue (value));
+                     TREE_OPERAND (datum, 0), non_lvalue (value));
       }
     default:
       break;
@@ -1545,7 +1580,7 @@ build_external_ref (tree id, int fun)
       /* Properly declared variable or function reference.  */
       if (!objc_ivar)
        ref = decl;
-      else if (decl != objc_ivar && !C_DECL_FILE_SCOPE (decl))
+      else if (decl != objc_ivar && !DECL_FILE_SCOPE_P (decl))
        {
          warning ("local declaration of `%s' hides instance variable",
                   IDENTIFIER_POINTER (id));
@@ -1585,7 +1620,7 @@ build_external_ref (tree id, int fun)
       TREE_CONSTANT (ref) = 1;
     }
   else if (current_function_decl != 0
-          && !C_DECL_FILE_SCOPE (current_function_decl)
+          && !DECL_FILE_SCOPE_P (current_function_decl)
           && (TREE_CODE (ref) == VAR_DECL
               || TREE_CODE (ref) == PARM_DECL
               || TREE_CODE (ref) == FUNCTION_DECL))
@@ -1610,6 +1645,7 @@ build_function_call (tree function, tree params)
   tree fntype, fundecl = 0;
   tree coerced_params;
   tree name = NULL_TREE, result;
+  tree tem;
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -1649,6 +1685,47 @@ build_function_call (tree function, tree params)
   /* fntype now gets the type of function pointed to.  */
   fntype = TREE_TYPE (fntype);
 
+  /* Check that the function is called through a compatible prototype.
+     If it is not, replace the call by a trap, wrapped up in a compound
+     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.
+
+     ??? This doesn't work for Objective-C because objc_comptypes
+     refuses to compare function prototypes, yet the compiler appears
+     to build calls that are flagged as invalid by C's comptypes.  */
+  if (! c_dialect_objc ()
+      && TREE_CODE (function) == NOP_EXPR
+      && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
+      && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
+      && ! comptypes (fntype, TREE_TYPE (tem), COMPARE_STRICT))
+    {
+      tree return_type = TREE_TYPE (fntype);
+      tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP],
+                                      NULL_TREE);
+
+      /* This situation leads to run-time undefined behavior.  We can't,
+        therefore, simply error unless we can prove that all possible
+        executions of the program must execute the code.  */
+      warning ("function called through a non-compatible type");
+
+      if (VOID_TYPE_P (return_type))
+       return trap;
+      else
+       {
+         tree rhs;
+
+         if (AGGREGATE_TYPE_P (return_type))
+           rhs = build_compound_literal (return_type,
+                                         build_constructor (return_type,
+                                                            NULL_TREE));
+         else
+           rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node));
+
+         return build (COMPOUND_EXPR, return_type, trap, rhs);
+       }
+    }
+
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
@@ -1837,7 +1914,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                                                (char *) 0, /* arg passing  */
                                                fundecl, name, parmnum + 1);
 
-             if (PROMOTE_PROTOTYPES
+             if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
                  && INTEGRAL_TYPE_P (type)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
@@ -2183,7 +2260,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          error ("wrong type argument to unary exclamation mark");
          return error_mark_node;
        }
-      arg = c_common_truthvalue_conversion (arg);
+      arg = (*lang_hooks.truthvalue_conversion) (arg);
       return invert_truthvalue (arg);
 
     case NOP_EXPR:
@@ -2209,12 +2286,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      /* Handle complex lvalues (when permitted)
-        by reduction to simpler cases.  */
-
-      val = unary_complex_lvalue (code, arg, 0);
-      if (val != 0)
-       return val;
 
       /* Increment or decrement the real part of the value,
         and don't change the imaginary part.  */
@@ -2282,57 +2353,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
        inc = convert (argtype, inc);
 
-       /* Handle incrementing a cast-expression.  */
-
-       while (1)
-         switch (TREE_CODE (arg))
-           {
-           case NOP_EXPR:
-           case CONVERT_EXPR:
-           case FLOAT_EXPR:
-           case FIX_TRUNC_EXPR:
-           case FIX_FLOOR_EXPR:
-           case FIX_ROUND_EXPR:
-           case FIX_CEIL_EXPR:
-             pedantic_lvalue_warning (CONVERT_EXPR);
-             /* If the real type has the same machine representation
-                as the type it is cast to, we can make better output
-                by adding directly to the inside of the cast.  */
-             if ((TREE_CODE (TREE_TYPE (arg))
-                  == TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))))
-                 && (TYPE_MODE (TREE_TYPE (arg))
-                     == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0)))))
-               arg = TREE_OPERAND (arg, 0);
-             else
-               {
-                 tree incremented, modify, value;
-                 if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
-                   value = boolean_increment (code, arg);
-                 else
-                   {
-                     arg = stabilize_reference (arg);
-                     if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
-                       value = arg;
-                     else
-                       value = save_expr (arg);
-                     incremented = build (((code == PREINCREMENT_EXPR
-                                            || code == POSTINCREMENT_EXPR)
-                                           ? PLUS_EXPR : MINUS_EXPR),
-                                          argtype, value, inc);
-                     TREE_SIDE_EFFECTS (incremented) = 1;
-                     modify = build_modify_expr (arg, NOP_EXPR, incremented);
-                     value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
-                   }
-                 TREE_USED (value) = 1;
-                 return value;
-               }
-             break;
-
-           default:
-             goto give_up;
-           }
-      give_up:
-
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
@@ -2379,12 +2399,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
                                  TREE_OPERAND (arg, 1), 1);
        }
 
-      /* Handle complex lvalues (when permitted)
-        by reduction to simpler cases.  */
-      val = unary_complex_lvalue (code, arg, flag);
-      if (val != 0)
-       return val;
-
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
@@ -2436,7 +2450,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
           file-scope function counts as a constant.  */
        if (staticp (arg)
            && ! (TREE_CODE (arg) == FUNCTION_DECL
-                 && !C_DECL_FILE_SCOPE (arg)))
+                 && !DECL_FILE_SCOPE_P (arg)))
          TREE_CONSTANT (addr) = 1;
        return addr;
       }
@@ -2502,68 +2516,6 @@ lvalue_or_else (tree ref, const char *msgid)
   return win;
 }
 
-/* Apply unary lvalue-demanding operator CODE to the expression ARG
-   for certain kinds of expressions which are not really lvalues
-   but which we can accept as lvalues.  If FLAG is nonzero, then
-   non-lvalues are OK since we may be converting a non-lvalue array to
-   a pointer in C99.
-
-   If ARG is not a kind of expression we can handle, return zero.  */
-
-static tree
-unary_complex_lvalue (enum tree_code code, tree arg, int flag)
-{
-  /* Handle (a, b) used as an "lvalue".  */
-  if (TREE_CODE (arg) == COMPOUND_EXPR)
-    {
-      tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
-
-      /* If this returns a function type, it isn't really being used as
-        an lvalue, so don't issue a warning about it.  */
-      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
-       pedantic_lvalue_warning (COMPOUND_EXPR);
-
-      return build (COMPOUND_EXPR, TREE_TYPE (real_result),
-                   TREE_OPERAND (arg, 0), real_result);
-    }
-
-  /* Handle (a ? b : c) used as an "lvalue".  */
-  if (TREE_CODE (arg) == COND_EXPR)
-    {
-      if (!flag)
-       pedantic_lvalue_warning (COND_EXPR);
-      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
-       pedantic_lvalue_warning (COMPOUND_EXPR);
-
-      return (build_conditional_expr
-             (TREE_OPERAND (arg, 0),
-              build_unary_op (code, TREE_OPERAND (arg, 1), flag),
-              build_unary_op (code, TREE_OPERAND (arg, 2), flag)));
-    }
-
-  return 0;
-}
-
-/* If pedantic, warn about improper lvalue.   CODE is either COND_EXPR
-   COMPOUND_EXPR, or CONVERT_EXPR (for casts).  */
-
-static void
-pedantic_lvalue_warning (enum tree_code code)
-{
-  if (pedantic)
-    switch (code)
-      {
-      case COND_EXPR:
-       pedwarn ("ISO C forbids use of conditional expressions as lvalues");
-       break;
-      case COMPOUND_EXPR:
-       pedwarn ("ISO C forbids use of compound expressions as lvalues");
-       break;
-      default:
-       pedwarn ("ISO C forbids use of cast expressions as lvalues");
-       break;
-      }
-}
 \f
 /* Warn about storing in something that is `const'.  */
 
@@ -2681,7 +2633,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   tree result_type = NULL;
   tree orig_op1 = op1, orig_op2 = op2;
 
-  ifexp = c_common_truthvalue_conversion (default_conversion (ifexp));
+  ifexp = (*lang_hooks.truthvalue_conversion) (default_conversion (ifexp));
 
   /* Promote both alternatives.  */
 
@@ -2700,6 +2652,14 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   type2 = TREE_TYPE (op2);
   code2 = TREE_CODE (type2);
 
+  /* C90 does not permit non-lvalue arrays in conditional expressions.
+     In C99 they will be pointers by now.  */
+  if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
+    {
+      error ("non-lvalue array in conditional expression");
+      return error_mark_node;
+    }
+
   /* Quickly detect the usual case where op1 and op2 have the same type
      after promotion.  */
   if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
@@ -2824,7 +2784,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     op2 = convert_and_check (result_type, op2);
 
   if (TREE_CODE (ifexp) == INTEGER_CST)
-    return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
+    return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
 
   return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
 }
@@ -2868,11 +2828,6 @@ internal_build_compound_expr (tree list, int first_p)
            && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
                 && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list)))))
         warning ("left-hand operand of comma expression has no effect");
-
-      /* When pedantic, a compound expression can be neither an lvalue
-         nor an integer constant expression.  */
-      if (! pedantic)
-        return rest;
     }
 
   /* With -Wunused, we should also warn if the left-hand operand does have
@@ -2898,7 +2853,7 @@ build_c_cast (tree type, tree expr)
   /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
      only in <protocol> qualifications.  But when constructing cast expressions,
      the protocols do matter and must be kept around.  */
-  if (!c_dialect_objc () || !objc_is_id (type))
+  if (!c_dialect_objc () || !objc_is_object_ptr (type))
     type = TYPE_MAIN_VARIANT (type);
 
   if (TREE_CODE (type) == ARRAY_TYPE)
@@ -3053,6 +3008,25 @@ build_c_cast (tree type, tree expr)
            warning ("dereferencing type-punned pointer will break strict-aliasing rules");
        }
 
+      /* If pedantic, warn for conversions between function and object
+        pointer types, except for converting a null pointer constant
+        to function pointer type.  */
+      if (pedantic
+         && TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
+         && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
+       pedwarn ("ISO C forbids conversion of function pointer to object pointer type");
+
+      if (pedantic
+         && TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+         && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+         && !(integer_zerop (value) && TREE_TYPE (otype) == void_type_node
+              && TREE_CODE (expr) != NOP_EXPR))
+       pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
+
       ovalue = value;
       /* Replace a nonvolatile const static variable with its value.  */
       if (optimize && TREE_CODE (value) == VAR_DECL)
@@ -3067,14 +3041,14 @@ build_c_cast (tree type, tree expr)
        }
     }
 
-  /* Pedantically, don't let (void *) (FOO *) 0 be a null pointer constant.  */
-  if (pedantic && TREE_CODE (value) == INTEGER_CST
+  /* Don't let (void *) (FOO *) 0 be a null pointer constant.  */
+  if (TREE_CODE (value) == INTEGER_CST
       && TREE_CODE (expr) == INTEGER_CST
       && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
     value = non_lvalue (value);
 
-  /* If pedantic, don't let a cast be an lvalue.  */
-  if (value == expr && pedantic)
+  /* Don't let a cast be an lvalue.  */
+  if (value == expr)
     value = non_lvalue (value);
 
   return value;
@@ -3125,45 +3099,6 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   newrhs = rhs;
 
-  /* Handle control structure constructs used as "lvalues".  */
-
-  switch (TREE_CODE (lhs))
-    {
-      /* Handle (a, b) used as an "lvalue".  */
-    case COMPOUND_EXPR:
-      pedantic_lvalue_warning (COMPOUND_EXPR);
-      newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs);
-      if (TREE_CODE (newrhs) == ERROR_MARK)
-       return error_mark_node;
-      return build (COMPOUND_EXPR, lhstype,
-                   TREE_OPERAND (lhs, 0), newrhs);
-
-      /* Handle (a ? b : c) used as an "lvalue".  */
-    case COND_EXPR:
-      pedantic_lvalue_warning (COND_EXPR);
-      rhs = save_expr (rhs);
-      {
-       /* Produce (a ? (b = rhs) : (c = rhs))
-          except that the RHS goes through a save-expr
-          so the code to compute it is only emitted once.  */
-       tree cond
-         = build_conditional_expr (TREE_OPERAND (lhs, 0),
-                                   build_modify_expr (TREE_OPERAND (lhs, 1),
-                                                      modifycode, rhs),
-                                   build_modify_expr (TREE_OPERAND (lhs, 2),
-                                                      modifycode, rhs));
-       if (TREE_CODE (cond) == ERROR_MARK)
-         return cond;
-       /* Make sure the code to compute the rhs comes out
-          before the split.  */
-       return build (COMPOUND_EXPR, TREE_TYPE (lhs),
-                     /* But cast it to void to avoid an "unused" error.  */
-                     convert (void_type_node, rhs), cond);
-      }
-    default:
-      break;
-    }
-
   /* If a binary op has been requested, combine the old LHS value with the RHS
      producing the value we should actually store into the LHS.  */
 
@@ -3173,42 +3108,6 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
-  /* Handle a cast used as an "lvalue".
-     We have already performed any binary operator using the value as cast.
-     Now convert the result to the cast type of the lhs,
-     and then true type of the lhs and store it there;
-     then convert result back to the cast type to be the value
-     of the assignment.  */
-
-  switch (TREE_CODE (lhs))
-    {
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case FLOAT_EXPR:
-    case FIX_TRUNC_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
-    case FIX_CEIL_EXPR:
-      newrhs = default_function_array_conversion (newrhs);
-      {
-       tree inner_lhs = TREE_OPERAND (lhs, 0);
-       tree result;
-       result = build_modify_expr (inner_lhs, NOP_EXPR,
-                                   convert (TREE_TYPE (inner_lhs),
-                                            convert (lhstype, newrhs)));
-       if (TREE_CODE (result) == ERROR_MARK)
-         return result;
-       pedantic_lvalue_warning (CONVERT_EXPR);
-       return convert (TREE_TYPE (lhs), result);
-      }
-
-    default:
-      break;
-    }
-
-  /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
-     Reject anything strange now.  */
-
   if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
     return error_mark_node;
 
@@ -3459,6 +3358,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
       tree ttl = TREE_TYPE (type);
       tree ttr = TREE_TYPE (rhstype);
       bool is_opaque_pointer;
+      int target_cmp = 0;   /* Cache comp_target_types () result.  */
 
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = ((*targetm.vector_opaque_p) (type)
@@ -3470,7 +3370,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
         and vice versa; otherwise, targets must be the same.
         Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
       if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-         || comp_target_types (type, rhstype, 0)
+         || (target_cmp = comp_target_types (type, rhstype, 0))
          || is_opaque_pointer
          || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl))
              == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr))))
@@ -3496,7 +3396,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
              else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-                      || comp_target_types (type, rhstype, 0))
+                      || target_cmp)
                ;
              /* If there is a mismatch, do warn.  */
              else if (pedantic)
@@ -3520,6 +3420,11 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                             errtype, funname, parmnum);
       return convert (type, rhs);
     }
+  else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
+    {
+      error ("invalid use of non-lvalue array");
+      return error_mark_node;
+    }
   else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
     {
       /* An explicit constant 0 can convert to a pointer,
@@ -3531,12 +3436,10 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
             && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
             && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
             && integer_zerop (TREE_OPERAND (rhs, 0))))
-       {
          warn_for_assignment ("%s makes pointer from integer without a cast",
                               errtype, funname, parmnum);
-         return convert (type, rhs);
-       }
-      return null_pointer_node;
+
+      return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
@@ -3570,10 +3473,12 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
   return error_mark_node;
 }
 
-/* Convert VALUE for assignment into inlined parameter PARM.  */
+/* Convert VALUE for assignment into inlined parameter PARM.  ARGNUM
+   is used for error and waring reporting and indicates which argument
+   is being processed.  */
 
 tree
-c_convert_parm_for_inlining (tree parm, tree value, tree fn)
+c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
 {
   tree ret, type;
 
@@ -3585,8 +3490,8 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn)
   type = TREE_TYPE (parm);
   ret = convert_for_assignment (type, value,
                                (char *) 0 /* arg passing  */, fn,
-                               DECL_NAME (fn), 0);
-  if (PROMOTE_PROTOTYPES
+                               DECL_NAME (fn), argnum);
+  if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
       && INTEGRAL_TYPE_P (type)
       && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
     ret = default_conversion (ret);
@@ -4010,14 +3915,25 @@ digest_init (tree type, tree init, int require_constant)
          || (code == VECTOR_TYPE
              && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
          || (code == POINTER_TYPE
-             && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
-                 || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)
+             && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
              && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
+                           TREE_TYPE (type), COMPARE_STRICT))
+         || (code == POINTER_TYPE
+             && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE
+             && comptypes (TREE_TYPE (inside_init),
                            TREE_TYPE (type), COMPARE_STRICT))))
     {
       if (code == POINTER_TYPE)
-       inside_init = default_function_array_conversion (inside_init);
-      
+       {
+         inside_init = default_function_array_conversion (inside_init);
+
+         if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
+           {
+             error_init ("invalid use of non-lvalue array");
+             return error_mark_node;
+           }
+        }
+
       if (code == VECTOR_TYPE)
        /* Although the types are compatible, we may require a
           conversion.  */
@@ -4365,6 +4281,8 @@ finish_init (void)
     abort ();
 
   /* Pop back to the data of the outer initializer (if any).  */
+  free (spelling_base);
+  
   constructor_decl = p->decl;
   constructor_asmspec = p->asmspec;
   require_constant_value = p->require_constant_value;
@@ -5597,7 +5515,7 @@ output_pending_init_elements (int all)
 
  retry:
 
-  /* Look thru the whole pending tree.
+  /* Look through the whole pending tree.
      If we find an element that should be output now,
      output it.  Otherwise, set NEXT to the element
      that comes first among those still pending.  */
@@ -6180,8 +6098,7 @@ build_asm_stmt (tree cv_qualifier, tree string, tree outputs, tree inputs,
 
 void
 c_expand_asm_operands (tree string, tree outputs, tree inputs,
-                      tree clobbers, int vol, const char *filename,
-                      int line)
+                      tree clobbers, int vol, location_t locus)
 {
   int noutputs = list_length (outputs);
   int i;
@@ -6199,7 +6116,7 @@ c_expand_asm_operands (tree string, tree outputs, tree inputs,
 
   /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
      OUTPUTS some trees for where the values were actually stored.  */
-  expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
+  expand_asm_operands (string, outputs, inputs, clobbers, vol, locus);
 
   /* Copy all the intermediate outputs into the specified outputs.  */
   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
@@ -6594,7 +6511,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       break;
 
     case BIT_AND_EXPR:
-    case BIT_ANDTC_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
@@ -6635,8 +6551,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             but that does not mean the operands should be
             converted to ints!  */
          result_type = integer_type_node;
-         op0 = c_common_truthvalue_conversion (op0);
-         op1 = c_common_truthvalue_conversion (op1);
+         op0 = (*lang_hooks.truthvalue_conversion) (op0);
+         op1 = (*lang_hooks.truthvalue_conversion) (op1);
          converted = 1;
        }
       break;
@@ -6874,6 +6790,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       break;
     }
 
+  if (code0 == ERROR_MARK || code1 == ERROR_MARK)
+    return error_mark_node;
+
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
        || code0 == VECTOR_TYPE)
       &&