OSDN Git Service

2008-03-21 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / cp / cvt.c
index 52b5be4..64a8716 100644 (file)
@@ -1,13 +1,14 @@
 /* Language-level data type conversion for GNU C++.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* This file contains the functions for converting C++ expressions
@@ -38,7 +38,7 @@ Boston, MA 02110-1301, USA.  */
 #include "decl.h"
 #include "target.h"
 
-static tree cp_convert_to_pointer (tree, tree, bool);
+static tree cp_convert_to_pointer (tree, tree);
 static tree convert_to_pointer_force (tree, tree);
 static tree build_type_conversion (tree, tree);
 static tree build_up_reference (tree, tree, int, tree);
@@ -71,12 +71,10 @@ static void warn_ref_binding (tree, tree, tree);
      else if dealing with method pointers, delegate
      else convert blindly
    else if converting class, pass off to build_type_conversion
-   else try C-style pointer conversion.  If FORCE is true then allow
-   conversions via virtual bases (these are permitted by reinterpret_cast,
-   but not static_cast).  */
+   else try C-style pointer conversion.  */
 
 static tree
-cp_convert_to_pointer (tree type, tree expr, bool force)
+cp_convert_to_pointer (tree type, tree expr)
 {
   tree intype = TREE_TYPE (expr);
   enum tree_code form;
@@ -84,7 +82,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
   if (intype == error_mark_node)
     return error_mark_node;
 
-  if (IS_AGGR_TYPE (intype))
+  if (MAYBE_CLASS_TYPE_P (intype))
     {
       intype = complete_type (intype);
       if (!COMPLETE_TYPE_P (intype))
@@ -129,8 +127,8 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
       if (TYPE_MAIN_VARIANT (type) != intype
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
-         && IS_AGGR_TYPE (TREE_TYPE (type))
-         && IS_AGGR_TYPE (TREE_TYPE (intype))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
          && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
        {
          enum tree_code code = PLUS_EXPR;
@@ -174,61 +172,17 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
 
       return build_nop (type, expr);
     }
-  else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
-    {
-      tree b1;
-      tree b2;
-      tree binfo;
-      enum tree_code code = PLUS_EXPR;
-      base_kind bk;
-
-      b1 = TYPE_PTRMEM_CLASS_TYPE (type);
-      b2 = TYPE_PTRMEM_CLASS_TYPE (intype);
-      binfo = lookup_base (b1, b2, ba_check, &bk);
-      if (!binfo)
-       {
-         binfo = lookup_base (b2, b1, ba_check, &bk);
-         code = MINUS_EXPR;
-       }
-      if (binfo == error_mark_node)
-       return error_mark_node;
-
-      if (bk == bk_via_virtual)
-       {
-         if (force)
-           warning (0, "pointer to member cast from %qT to %qT is via"
-                    " virtual base", intype, type);
-         else
-           {
-             error ("pointer to member cast from %qT to %qT is"
-                    " via virtual base", intype, type);
-             return error_mark_node;
-           }
-         /* This is a reinterpret cast, whose result is unspecified.
-            We choose to do nothing.  */
-         return build1 (NOP_EXPR, type, expr);
-       }
-
-      if (TREE_CODE (expr) == PTRMEM_CST)
-       expr = cplus_expand_constant (expr);
-
-      if (binfo && !integer_zerop (BINFO_OFFSET (binfo)))
-       expr = size_binop (code,
-                          build_nop (sizetype, expr),
-                          BINFO_OFFSET (binfo));
-      return build_nop (type, expr);
-    }
-  else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
-    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
-                            /*c_cast_p=*/false);
+  else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+          || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+    return convert_ptrmem (type, expr, /*allow_inverse_p=*/false,
+                          /*c_cast_p=*/false);
   else if (TYPE_PTRMEMFUNC_P (intype))
     {
       if (!warn_pmf2ptr)
        {
          if (TREE_CODE (expr) == PTRMEM_CST)
            return cp_convert_to_pointer (type,
-                                         PTRMEM_CST_MEMBER (expr),
-                                         force);
+                                         PTRMEM_CST_MEMBER (expr));
          else if (TREE_CODE (expr) == OFFSET_REF)
            {
              tree object = TREE_OPERAND (expr, 0);
@@ -251,9 +205,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
        {
          /* A NULL pointer-to-member is represented by -1, not by
             zero.  */
-         expr = build_int_cst (type, -1);
-         /* Fix up the representation of -1 if appropriate.  */
-         expr = force_fit_type (expr, 0, false, false);
+         expr = build_int_cst_type (type, -1);
        }
       else
        expr = build_int_cst (type, 0);
@@ -304,8 +256,8 @@ convert_to_pointer_force (tree type, tree expr)
 
       if (TYPE_MAIN_VARIANT (type) != intype
          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
-         && IS_AGGR_TYPE (TREE_TYPE (type))
-         && IS_AGGR_TYPE (TREE_TYPE (intype))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
          && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
        {
          enum tree_code code = PLUS_EXPR;
@@ -335,7 +287,7 @@ convert_to_pointer_force (tree type, tree expr)
        }
     }
 
-  return cp_convert_to_pointer (type, expr, true);
+  return cp_convert_to_pointer (type, expr);
 }
 
 /* We are passing something to a function which requires a reference.
@@ -380,8 +332,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
 
   if ((flags & LOOKUP_PROTECT)
       && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
-      && IS_AGGR_TYPE (argtype)
-      && IS_AGGR_TYPE (target_type))
+      && MAYBE_CLASS_TYPE_P (argtype)
+      && MAYBE_CLASS_TYPE_P (target_type))
     {
       /* We go through lookup_base for the access control.  */
       tree binfo = lookup_base (argtype, target_type, ba_check, NULL);
@@ -427,7 +379,7 @@ warn_ref_binding (tree reftype, tree intype, tree decl)
          msg = "conversion to non-const reference type %q#T from"
            " rvalue of type %qT";
 
-      pedwarn (msg, reftype, intype);
+      permerror (msg, reftype, intype);
     }
 }
 
@@ -466,7 +418,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
   can_convert_intype_to_type = can_convert (type, intype);
   if (!can_convert_intype_to_type
-      && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
+      && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype)
       && ! (flags & LOOKUP_NO_CONVERSION))
     {
       /* Look for a user-defined conversion to lvalue that we can use.  */
@@ -497,8 +449,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
          if (! (convtype & CONV_CONST)
                   && !at_least_as_qualified_p (ttl, ttr))
-           pedwarn ("conversion from %qT to %qT discards qualifiers",
-                    ttr, reftype);
+           permerror ("conversion from %qT to %qT discards qualifiers",
+                      ttr, reftype);
        }
 
       return build_up_reference (reftype, expr, flags, decl);
@@ -578,7 +530,7 @@ convert_from_reference (tree val)
 tree
 force_rvalue (tree expr)
 {
-  if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
+  if (MAYBE_CLASS_TYPE_P (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
     expr = ocp_convert (TREE_TYPE (expr), expr,
                        CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
   else
@@ -595,6 +547,29 @@ cp_convert (tree type, tree expr)
   return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);
 }
 
+/* C++ equivalent of convert_and_check but using cp_convert as the
+   conversion function.
+
+   Convert EXPR to TYPE, warning about conversion problems with constants.
+   Invoke this function on every expression that is converted implicitly,
+   i.e. because of language rules and not because of an explicit cast.  */
+
+tree
+cp_convert_and_check (tree type, tree expr)
+{
+  tree result;
+
+  if (TREE_TYPE (expr) == type)
+    return expr;
+  
+  result = cp_convert (type, expr);
+
+  if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node)
+    warnings_for_convert_and_check (type, expr, result);
+
+  return result;
+}
+
 /* Conversion...
 
    FLAGS indicates how we should behave.  */
@@ -621,13 +596,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
 
   e = integral_constant_value (e);
 
-  if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
-      /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
-        don't go through finish_struct, so they don't have the synthesized
-        constructors.  So don't force a temporary.  */
-      && TYPE_HAS_CONSTRUCTOR (type))
+  if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP))
     /* We need a new temporary; don't take this shortcut.  */;
-  else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
+  else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
     {
       if (same_type_p (type, TREE_TYPE (e)))
        /* The call to fold will not always remove the NOP_EXPR as
@@ -644,10 +615,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       else if (TREE_CODE (e) == TARGET_EXPR)
        {
          /* Don't build a NOP_EXPR of class type.  Instead, change the
-            type of the temporary.  Only allow this for cv-qual changes,
-            though.  */
-         gcc_assert (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
-                                  TYPE_MAIN_VARIANT (type)));
+            type of the temporary.  */
          TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
          return e;
        }
@@ -678,12 +646,12 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
              || TREE_CODE (intype) == POINTER_TYPE))
        {
          if (flags & LOOKUP_COMPLAIN)
-           pedwarn ("conversion from %q#T to %q#T", intype, type);
+           permerror ("conversion from %q#T to %q#T", intype, type);
 
-         if (flag_pedantic_errors)
+         if (!flag_permissive)
            return error_mark_node;
        }
-      if (IS_AGGR_TYPE (intype))
+      if (MAYBE_CLASS_TYPE_P (intype))
        {
          tree rval;
          rval = build_type_conversion (type, e);
@@ -699,11 +667,11 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       return fold_if_not_in_template (convert_to_integer (type, e));
     }
   if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
-    return fold_if_not_in_template (cp_convert_to_pointer (type, e, false));
+    return fold_if_not_in_template (cp_convert_to_pointer (type, e));
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
-      if (IS_AGGR_TYPE (in_vtype))
+      if (MAYBE_CLASS_TYPE_P (in_vtype))
        {
          tree ret_val;
          ret_val = build_type_conversion (type, e);
@@ -717,7 +685,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
     }
   if (code == REAL_TYPE || code == COMPLEX_TYPE)
     {
-      if (IS_AGGR_TYPE (TREE_TYPE (e)))
+      if (MAYBE_CLASS_TYPE_P (TREE_TYPE (e)))
        {
          tree rval;
          rval = build_type_conversion (type, e);
@@ -737,7 +705,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
   /* New C++ semantics:  since assignment is now based on
      memberwise copying,  if the rhs type is derived from the
      lhs type, then we may still do a conversion.  */
-  if (IS_AGGR_TYPE_CODE (code))
+  if (RECORD_OR_UNION_CODE_P (code))
     {
       tree dtype = TREE_TYPE (e);
       tree ctor = NULL_TREE;
@@ -757,7 +725,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
        return error_mark_node;
 
       if ((flags & LOOKUP_ONLYCONVERTING)
-         && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
+         && ! (MAYBE_CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype)))
        /* For copy-initialization, first we create a temp of the proper type
           with a user-defined conversion sequence, then we direct-initialize
           the target with the temp (see [dcl.init]).  */
@@ -897,16 +865,18 @@ convert_to_void (tree expr, const char *implicit)
         we don't use it and don't need to destroy it.  We'll still
         allocate space for it in expand_call or declare_return_variable,
         but we don't need to track it through all the tree phases.  */
-      if (0 && TARGET_EXPR_IMPLICIT_P (expr)
+      if (TARGET_EXPR_IMPLICIT_P (expr)
          && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (expr)))
        {
          tree init = TARGET_EXPR_INITIAL (expr);
          if (TREE_CODE (init) == AGGR_INIT_EXPR
              && !AGGR_INIT_VIA_CTOR_P (init))
            {
-             tree fn = TREE_OPERAND (init, 0);
-             expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
-                            fn, TREE_OPERAND (init, 1), NULL_TREE);
+             tree fn = AGGR_INIT_EXPR_FN (init);
+             expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
+                                      fn,
+                                      aggr_init_expr_nargs (init),
+                                      AGGR_INIT_EXPR_ARGP (init));
            }
        }
       break;
@@ -922,14 +892,18 @@ convert_to_void (tree expr, const char *implicit)
       {
        /* [over.over] enumerates the places where we can take the address
           of an overloaded function, and this is not one of them.  */
-       pedwarn ("%s cannot resolve address of overloaded function",
-                   implicit ? implicit : "void cast");
+       error ("%s cannot resolve address of overloaded function",
+              implicit ? implicit : "void cast");
        expr = void_zero_node;
       }
     else if (implicit && probe == expr && is_overloaded_fn (probe))
-      /* Only warn when there is no &.  */
-      warning (0, "%s is a reference, not call, to function %qE",
-                 implicit, expr);
+      {
+       /* Only warn when there is no &.  */
+       warning (OPT_Waddress, "%s is a reference, not call, to function %qE",
+                implicit, expr);
+       if (TREE_CODE (expr) == COMPONENT_REF)
+         expr = TREE_OPERAND (expr, 0);
+      }
   }
 
   if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
@@ -992,7 +966,7 @@ convert_to_void (tree expr, const char *implicit)
 
    Most of this routine is from build_reinterpret_cast.
 
-   The backend cannot call cp_convert (what was convert) because
+   The back end cannot call cp_convert (what was convert) because
    conversions to/from basetypes may involve memory references
    (vbases) and adding or subtracting small values (multiple
    inheritance), but it calls convert from the constant folding code
@@ -1091,7 +1065,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
   if (basetype == error_mark_node)
     return error_mark_node;
 
-  if (! IS_AGGR_TYPE (basetype))
+  if (! MAYBE_CLASS_TYPE_P (basetype))
     switch (TREE_CODE (basetype))
       {
       case INTEGER_TYPE:
@@ -1099,7 +1073,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
          return expr;
        /* else fall through...  */
 
-      case VECTOR_TYPE:
       case BOOLEAN_TYPE:
        return (desires & WANT_INT) ? expr : NULL_TREE;
       case ENUMERAL_TYPE:
@@ -1113,6 +1086,23 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
       case ARRAY_TYPE:
        return (desires & WANT_POINTER) ? decay_conversion (expr)
                                        : NULL_TREE;
+
+      case VECTOR_TYPE:
+       if ((desires & WANT_VECTOR) == 0)
+         return NULL_TREE;
+       switch (TREE_CODE (TREE_TYPE (basetype)))
+         {
+         case INTEGER_TYPE:
+         case BOOLEAN_TYPE:
+           return (desires & WANT_INT) ? expr : NULL_TREE;
+         case ENUMERAL_TYPE:
+           return (desires & WANT_ENUM) ? expr : NULL_TREE;
+         case REAL_TYPE:
+           return (desires & WANT_FLOAT) ? expr : NULL_TREE;
+         default:
+           return NULL_TREE;
+         }
+
       default:
        return NULL_TREE;
       }
@@ -1147,6 +1137,23 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
        case POINTER_TYPE:
          win = (desires & WANT_POINTER); break;
 
+       case VECTOR_TYPE:
+         if ((desires & WANT_VECTOR) == 0)
+           break;
+         switch (TREE_CODE (TREE_TYPE (candidate)))
+           {
+           case BOOLEAN_TYPE:
+           case INTEGER_TYPE:
+             win = (desires & WANT_INT); break;
+           case ENUMERAL_TYPE:
+             win = (desires & WANT_ENUM); break;
+           case REAL_TYPE:
+             win = (desires & WANT_FLOAT); break;
+           default:
+             break;
+           }
+         break;
+
        default:
          break;
        }