OSDN Git Service

91th Cygnus<->FSF quick merge
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index 4c876f6..4aee8a6 100644 (file)
@@ -44,18 +44,17 @@ int mark_addressable PROTO((tree));
 static tree convert_for_assignment PROTO((tree, tree, char*, tree, int));
 /* static */ tree convert_for_initialization PROTO((tree, tree, tree, int, char*, tree, int));
 extern tree shorten_compare ();
-extern void binary_op_error ();
 static tree pointer_int_sum PROTO((enum tree_code, register tree, register tree));
 static tree pointer_diff PROTO((register tree, register tree));
+static int comp_target_parms PROTO((tree, tree, int));
+static int comp_ptr_ttypes_const PROTO((tree, tree));
+static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
 #if 0
 static tree convert_sequence ();
 #endif
 /* static */ tree unary_complex_lvalue PROTO((enum tree_code, tree));
 static tree get_delta_difference PROTO((tree, tree, int));
 
-extern rtx original_result_rtx;
-extern int warn_synth;
-
 /* Return the target type of TYPE, which meas return T for:
    T*, T&, T[], T (...), and otherwise, just T.  */
 
@@ -942,7 +941,7 @@ comp_target_types (ttl, ttr, nptrs)
    If there is not a unique most-derived base type, this function
    returns ERROR_MARK_NODE.  */
 
-tree
+static tree
 common_base_type (tt1, tt2)
      tree tt1, tt2;
 {
@@ -1049,7 +1048,7 @@ compparms (parms1, parms2, strict)
 /* This really wants return whether or not parameter type lists
    would make their owning functions assignment compatible or not.  */
 
-int
+static int
 comp_target_parms (parms1, parms2, strict)
      tree parms1, parms2;
      int strict;
@@ -1508,7 +1507,7 @@ decay_conversion (exp)
              inner = build1 (CONVERT_EXPR,
                              build_pointer_type (TREE_TYPE (TREE_TYPE (inner))),
                              inner);
-             TREE_REFERENCE_EXPR (inner) = 1;
+             TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0));
            }
          return convert (build_pointer_type (TREE_TYPE (type)), inner);
        }
@@ -1805,10 +1804,13 @@ build_component_ref (datum, component, basetype_path, protect)
     }
   else
     {
+      tree name = component;
+      if (TREE_CODE (component) == VAR_DECL)
+       name = DECL_NAME (component);
       if (basetype_path == NULL_TREE)
        basetype_path = TYPE_BINFO (basetype);
-      field = lookup_field (basetype_path, component,
-                           protect && ! VFIELD_NAME_P (component), 0);
+      field = lookup_field (basetype_path, name,
+                           protect && !VFIELD_NAME_P (name), 0);
       if (field == error_mark_node)
        return error_mark_node;
 
@@ -1817,7 +1819,7 @@ build_component_ref (datum, component, basetype_path, protect)
          /* Not found as a data field, look for it as a method.  If found,
             then if this is the only possible one, return it, else
             report ambiguity error.  */
-         tree fndecls = lookup_fnfields (basetype_path, component, 1);
+         tree fndecls = lookup_fnfields (basetype_path, name, 1);
          if (fndecls == error_mark_node)
            return error_mark_node;
          if (fndecls)
@@ -1837,10 +1839,13 @@ build_component_ref (datum, component, basetype_path, protect)
                          && ! resolves_to_fixed_type_p (datum, 0))
                        {
                          tree addr = build_unary_op (ADDR_EXPR, datum, 0);
+                         tree fntype = TREE_TYPE (fndecl);
+
                          addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr);
                          datum = build_indirect_ref (addr, NULL_PTR);
                          my_friendly_assert (datum != error_mark_node, 310);
                          fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
+                         TREE_TYPE (fndecl) = build_pointer_type (fntype);
                        }
                      mark_used (fndecl);
                      return build (OFFSET_REF, TREE_TYPE (fndecl), datum, fndecl);
@@ -1864,7 +1869,7 @@ build_component_ref (datum, component, basetype_path, protect)
                }
            }
 
-         cp_error ("`%#T' has no member named `%D'", basetype, component);
+         cp_error ("`%#T' has no member named `%D'", basetype, name);
          return error_mark_node;
        }
       else if (TREE_TYPE (field) == error_mark_node)
@@ -2065,16 +2070,6 @@ build_indirect_ref (ptr, errorstring)
    will inherit the type of the array, which will be some pointer type.  */
 
 tree
-build_x_array_ref (array, idx)
-     tree array, idx;
-{
-  tree rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, idx, NULL_TREE);
-  if (rval)
-    return rval;
-  return build_array_ref (array, idx);
-}
-
-tree
 build_array_ref (array, idx)
      tree array, idx;
 {
@@ -2436,7 +2431,7 @@ build_x_function_call (function, params, decl)
          decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl);
        }
       else
-       decl = build_c_cast (ctypeptr, decl, 0);
+       decl = build_c_cast (ctypeptr, decl);
       params = tree_cons (NULL_TREE, decl, params);
     }
 
@@ -2716,6 +2711,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
   if (! flag_elide_constructors)
     return_loc = 0;
 
+  /* Argument passing is always copy-initialization.  */
+  flags |= LOOKUP_ONLYCONVERTING;
+
   if (fndecl)
     {
       if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
@@ -2822,9 +2820,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
            }
          else
            {
-             parmval = convert_for_initialization (return_loc, type, val,
-                                                   flags|INDIRECT_BIND,
-                                                   "argument passing", fndecl, i);
+             parmval = convert_for_initialization
+               (return_loc, type, val, flags,
+                "argument passing", fndecl, i);
 #ifdef PROMOTE_PROTOTYPES
              if ((TREE_CODE (type) == INTEGER_TYPE
                   || TREE_CODE (type) == ENUMERAL_TYPE)
@@ -4263,8 +4261,10 @@ build_unary_op (code, xarg, noconvert)
       argtype = TREE_TYPE (arg);
       if (TREE_CODE (argtype) == REFERENCE_TYPE)
        {
-         arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
-         TREE_REFERENCE_EXPR (arg) = 1;
+         arg = build1
+           (CONVERT_EXPR,
+            build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
+         TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
          return arg;
        }
       else if (pedantic
@@ -4285,16 +4285,12 @@ build_unary_op (code, xarg, noconvert)
          if (arg == current_class_ref)
            return current_class_ptr;
 
-         /* Keep `default_conversion' from converting if
-            ARG is of REFERENCE_TYPE.  */
          arg = TREE_OPERAND (arg, 0);
          if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
            {
-             if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg)
-                 && !TREE_SIDE_EFFECTS (DECL_INITIAL (arg)))
-               arg = DECL_INITIAL (arg);
-             arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
-             TREE_REFERENCE_EXPR (arg) = 1;
+             arg = build1
+               (CONVERT_EXPR,
+                build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
              TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
            }
          else if (lvalue_p (arg))
@@ -4490,7 +4486,9 @@ unary_complex_lvalue (code, arg)
       || TREE_CODE (arg) == INIT_EXPR)
     {
       tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
-      return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
+      arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
+      TREE_NO_UNUSED_WARNING (arg) = 1;
+      return arg;
     }
 
   if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
@@ -4616,7 +4614,8 @@ mark_addressable (exp)
       case PARM_DECL:
        if (x == current_class_ptr)
          {
-           error ("address of `this' not available");
+           if (! flag_this_is_variable)
+             error ("address of `this' not available");
            TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
            put_var_into_stack (x);
            return 1;
@@ -4649,8 +4648,10 @@ mark_addressable (exp)
 
       case CONST_DECL:
       case RESULT_DECL:
-       /* For C++, we don't warn about taking the address of a register
-          variable for CONST_DECLs; ARM p97 explicitly says it's okay.  */
+       if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
+           && !DECL_ARTIFICIAL (x) && extra_warnings)
+         cp_warning ("address requested for `%D', which is declared `register'",
+                     x);
        put_var_into_stack (x);
        TREE_ADDRESSABLE (x) = 1;
        return 1;
@@ -4678,6 +4679,11 @@ mark_addressable (exp)
        TREE_ADDRESSABLE (x) = 1;
        return 1;
 
+      case TARGET_EXPR:
+       TREE_ADDRESSABLE (x) = 1;
+       mark_addressable (TREE_OPERAND (x, 0));
+       return 1;
+
       default:
        return 1;
     }
@@ -4715,7 +4721,6 @@ build_conditional_expr (ifexp, op1, op2)
   register enum tree_code code1;
   register enum tree_code code2;
   register tree result_type = NULL_TREE;
-  tree orig_op1 = op1, orig_op2 = op2;
 
   /* If second operand is omitted, it is the same as the first one;
      make sure it is calculated only once.  */
@@ -5180,7 +5185,7 @@ build_static_cast (type, expr)
     ok = 1;
 
   if (ok)
-    return build_c_cast (type, expr, 0);
+    return build_c_cast (type, expr);
 
   cp_error ("static_cast from `%T' to `%T'", intype, type);
   return error_mark_node;
@@ -5346,10 +5351,8 @@ build_const_cast (type, expr)
    when doing the cast.  */
 
 tree
-build_c_cast (type, expr, allow_nonconverting)
-     register tree type;
-     tree expr;
-     int allow_nonconverting;
+build_c_cast (type, expr)
+     tree type, expr;
 {
   register tree value = expr;
 
@@ -5419,7 +5422,6 @@ build_c_cast (type, expr, allow_nonconverting)
   else
     {
       tree otype;
-      int flag;
 
       /* Convert functions and arrays to pointers and
         convert references to their expanded types,
@@ -5477,11 +5479,9 @@ build_c_cast (type, expr, allow_nonconverting)
        warning ("cast to pointer from integer of different size");
 #endif
 
-      flag = allow_nonconverting ? CONV_NONCONVERTING : 0;
-
       if (TREE_CODE (type) == REFERENCE_TYPE)
        value = (convert_from_reference
-                (convert_to_reference (type, value, CONV_OLD_CONVERT|flag,
+                (convert_to_reference (type, value, CONV_C_CAST,
                                        LOOKUP_COMPLAIN, NULL_TREE)));
       else
        {
@@ -5491,7 +5491,7 @@ build_c_cast (type, expr, allow_nonconverting)
            value = decl_constant_value (value);
 
          ovalue = value;
-         value = convert_force (type, value, flag);
+         value = convert_force (type, value, CONV_C_CAST);
 
          /* Ignore any integer overflow caused by the cast.  */
          if (TREE_CODE (value) == INTEGER_CST)
@@ -5565,7 +5565,7 @@ build_modify_expr (lhs, modifycode, rhs)
   tree olhs = lhs;
 
   /* Avoid duplicate error messages from operands that had errors.  */
-  if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
+  if (lhs == error_mark_node || rhs == error_mark_node)
     return error_mark_node;
 
   /* Types that aren't fully specified cannot be used in assignments.  */
@@ -5601,14 +5601,14 @@ build_modify_expr (lhs, modifycode, rhs)
     case COMPOUND_EXPR:
       newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
                                  modifycode, rhs);
-      if (TREE_CODE (newrhs) == ERROR_MARK)
+      if (newrhs == error_mark_node)
        return error_mark_node;
       return build (COMPOUND_EXPR, lhstype,
                    TREE_OPERAND (lhs, 0), newrhs);
 
     case MODIFY_EXPR:
       newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs);
-      if (TREE_CODE (newrhs) == ERROR_MARK)
+      if (newrhs == error_mark_node)
        return error_mark_node;
       return build (COMPOUND_EXPR, lhstype, lhs, newrhs);
 
@@ -5625,7 +5625,7 @@ build_modify_expr (lhs, modifycode, rhs)
                                                       modifycode, rhs),
                                    build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
                                                       modifycode, rhs));
-       if (TREE_CODE (cond) == ERROR_MARK)
+       if (cond == error_mark_node)
          return cond;
        /* Make sure the code to compute the rhs comes out
           before the split.  */
@@ -5772,13 +5772,16 @@ build_modify_expr (lhs, modifycode, rhs)
       {
        tree inner_lhs = TREE_OPERAND (lhs, 0);
        tree result;
-       if (! lvalue_p (lhs) && pedantic)
-         pedwarn ("cast to non-reference type used as lvalue");
+
+       /* WP 5.4.1:  The result is an lvalue if T is a reference type,
+          otherwise the result is an rvalue.   */
+       if (! lvalue_p (lhs))
+         pedwarn ("ANSI C++ forbids cast to non-reference type used as lvalue");
 
        result = build_modify_expr (inner_lhs, NOP_EXPR,
                                    convert (TREE_TYPE (inner_lhs),
                                             convert (lhstype, newrhs)));
-       if (TREE_CODE (result) == ERROR_MARK)
+       if (result == error_mark_node)
          return result;
        return convert (TREE_TYPE (lhs), result);
       }
@@ -5965,7 +5968,7 @@ build_modify_expr (lhs, modifycode, rhs)
                        TREE_OPERAND (newrhs, 0));
     }
 
-  if (TREE_CODE (newrhs) == ERROR_MARK)
+  if (newrhs == error_mark_node)
     return error_mark_node;
 
   if (TREE_CODE (newrhs) == COND_EXPR)
@@ -6082,7 +6085,7 @@ get_delta_difference (from, to, force)
   binfo = get_binfo (from, to, 1);
   if (binfo == error_mark_node)
     {
-      error ("   in pointer to member function conversion");
+      error ("   in pointer to member function conversiona");
       return delta;
     }
   if (binfo == 0)
@@ -6096,12 +6099,14 @@ get_delta_difference (from, to, force)
       binfo = get_binfo (to, from, 1);
       if (binfo == error_mark_node)
        {
-         error ("   in pointer to member conversion");
+         if (!force)
+           error ("   in pointer to member conversion");
          return delta;
        }
       if (binfo == 0)
        {
-         cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
+         if (!force)
+           cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
          return delta;
        }
       if (TREE_VIA_VIRTUAL (binfo))
@@ -6218,12 +6223,11 @@ build_ptrmemfunc (type, pfn, force)
   tree delta2 = integer_zero_node;
   tree vfield_offset;
   tree npfn = NULL_TREE;
-  tree u;
 
   /* Handle multiple conversions of pointer to member functions.  */
   if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
     {
-      tree ndelta, ndelta2, nindex;
+      tree ndelta, ndelta2;
       tree e1, e2, e3, n;
 
       /* Is is already the right type? */
@@ -6257,7 +6261,7 @@ build_ptrmemfunc (type, pfn, force)
   /* Handle null pointer to member function conversions.  */
   if (integer_zerop (pfn))
     {
-      pfn = build_c_cast (type, integer_zero_node, 0);
+      pfn = build_c_cast (type, integer_zero_node);
       return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type),
                                integer_zero_node, integer_zero_node,
                                pfn, NULL_TREE);
@@ -6751,6 +6755,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
     }
   else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
     return convert (type, rhs);
+  /* Handle anachronistic conversions from (::*)() to cv void* or (*)().  */
+  else if (TREE_CODE (type) == POINTER_TYPE
+          && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+              || TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
+          && TREE_TYPE (rhs)
+          && TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
+    return convert (type, rhs);
 
   cp_error ("%s to `%T' from `%T'", errtype, type, rhstype);
   return error_mark_node;
@@ -6869,6 +6880,9 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
   if (IS_AGGR_TYPE (type)
       && (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
     {
+      if (flag_ansi_overloading)
+       return cp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+
       if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
        {
          /* This is sufficient to perform initialization.  No need,
@@ -7090,10 +7104,17 @@ c_expand_return (retval)
       retval = current_class_ptr;
     }
 
+  /* Effective C++ rule 15.  See also start_function.  */
+  if (warn_ecpp
+      && DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR]
+      && retval != current_class_ref)
+    cp_warning ("`operator=' should return a reference to `*this'");
+
   if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
     {
       current_function_returns_null = 1;
-      if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+      if ((pedantic && ! DECL_ARTIFICIAL (current_function_decl))
+         || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
        pedwarn ("`return' with a value, in function returning void");
       expand_return (retval);
       return;
@@ -7113,9 +7134,9 @@ c_expand_return (retval)
 
       /* convert to reference now, so we can give error if we
         return an reference to a non-lvalue.  */
-      retval = convert_for_initialization (tmp_result, valtype, retval,
-                                          LOOKUP_NORMAL, "return",
-                                          NULL_TREE, 0);
+      retval = convert_for_initialization
+       (tmp_result, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
+        "return", NULL_TREE, 0);
 
       /* Sort through common things to see what it is
         we are returning.  */
@@ -7126,6 +7147,8 @@ c_expand_return (retval)
          if (TREE_CODE (whats_returned) == ADDR_EXPR)
            whats_returned = TREE_OPERAND (whats_returned, 0);
        }
+      if (TREE_CODE (whats_returned) == CONVERT_EXPR)
+       whats_returned = TREE_OPERAND (whats_returned, 0);
       if (TREE_CODE (whats_returned) == ADDR_EXPR)
        {
          whats_returned = TREE_OPERAND (whats_returned, 0);
@@ -7180,7 +7203,7 @@ c_expand_return (retval)
   if (retval == result
       || DECL_CONSTRUCTOR_P (current_function_decl))
     /* It's already done for us.  */;
-  else if (TYPE_MODE (TREE_TYPE (retval)) == VOIDmode)
+  else if (TREE_TYPE (retval) == void_type_node)
     {
       pedwarn ("return of void value in function returning non-void");
       expand_expr_stmt (retval);
@@ -7190,14 +7213,14 @@ c_expand_return (retval)
     {
       /* We already did this above for refs, don't do it again.  */
       if (TREE_CODE (valtype) != REFERENCE_TYPE)
-       retval = convert_for_initialization (NULL_TREE, valtype, retval,
-                                            LOOKUP_NORMAL,
-                                            "return", NULL_TREE, 0);
+       retval = convert_for_initialization
+         (NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
+          "return", NULL_TREE, 0);
 
       /* We can't initialize a register from a NEW_EXPR.  */
       if (! current_function_returns_struct
          && TREE_CODE (retval) == TARGET_EXPR
-         && TREE_CODE (TREE_OPERAND (retval, 0)) == NEW_EXPR)
+         && TREE_CODE (TREE_OPERAND (retval, 1)) == NEW_EXPR)
        retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
                        TREE_OPERAND (retval, 0));
 
@@ -7286,7 +7309,7 @@ c_expand_start_case (exp)
 /* CONSTP remembers whether or not all the intervening pointers in the `to'
    type have been const.  */
 
-int
+static int
 comp_ptr_ttypes_real (to, from, constp)
      tree to, from;
      int constp;
@@ -7357,7 +7380,7 @@ ptr_reasonably_similar (to, from)
 
 /* Like comp_ptr_ttypes, for const_cast.  */
 
-int
+static int
 comp_ptr_ttypes_const (to, from)
      tree to, from;
 {
@@ -7378,7 +7401,7 @@ comp_ptr_ttypes_const (to, from)
 
 /* Like comp_ptr_ttypes, for reinterpret_cast.  */
 
-int
+static int
 comp_ptr_ttypes_reinterpret (to, from)
      tree to, from;
 {