OSDN Git Service

* typeck.c (composite_pointer_type_r, cxx_sizeof_expr,
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck2.c
index a3654c0..05e88b9 100644 (file)
@@ -1,7 +1,7 @@
 /* Report error messages, build initializers, and perform
    some front-end optimizations for C++ compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2004, 2005, 2006
+   1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
@@ -9,7 +9,7 @@ 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,
@@ -18,9 +18,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 is part of the C++ front end.
@@ -68,20 +67,12 @@ binfo_or_else (tree base, tree type)
 }
 
 /* According to ARM $7.1.6, "A `const' object may be initialized, but its
-   value may not be changed thereafter.  Thus, we emit hard errors for these,
-   rather than just pedwarns.  If `SOFT' is 1, then we just pedwarn.  (For
-   example, conversions to references.)  */
+   value may not be changed thereafter.  */
 
 void
-readonly_error (tree arg, const char* string, int soft)
+readonly_error (tree arg, const char* string)
 {
   const char *fmt;
-  void (*fn) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
-
-  if (soft)
-    fn = pedwarn;
-  else
-    fn = error;
 
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
@@ -89,7 +80,7 @@ readonly_error (tree arg, const char* string, int soft)
        fmt = "%s of data-member %qD in read-only structure";
       else
        fmt = "%s of read-only data-member %qD";
-      (*fn) (fmt, string, TREE_OPERAND (arg, 1));
+      error (fmt, string, TREE_OPERAND (arg, 1));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
     {
@@ -99,21 +90,21 @@ readonly_error (tree arg, const char* string, int soft)
        fmt = "%s of constant field %qD";
       else
        fmt = "%s of read-only variable %qD";
-      (*fn) (fmt, string, arg);
+      error (fmt, string, arg);
     }
   else if (TREE_CODE (arg) == PARM_DECL)
-    (*fn) ("%s of read-only parameter %qD", string, arg);
+    error ("%s of read-only parameter %qD", string, arg);
   else if (TREE_CODE (arg) == INDIRECT_REF
           && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
           && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
               || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
-    (*fn) ("%s of read-only reference %qD", string, TREE_OPERAND (arg, 0));
+    error ("%s of read-only reference %qD", string, TREE_OPERAND (arg, 0));
   else if (TREE_CODE (arg) == RESULT_DECL)
-    (*fn) ("%s of read-only named return value %qD", string, arg);
+    error ("%s of read-only named return value %qD", string, arg);
   else if (TREE_CODE (arg) == FUNCTION_DECL)
-    (*fn) ("%s of function %qD", string, arg);
+    error ("%s of function %qD", string, arg);
   else
-    (*fn) ("%s of read-only location", string);
+    error ("%s of read-only location %qE", string, arg);
 }
 
 \f
@@ -157,9 +148,9 @@ pat_calc_hash (const void* val)
 static int
 pat_compare (const void* val1, const void* val2)
 {
-  const struct pending_abstract_type *pat1 =
+  const struct pending_abstract_type *const pat1 =
      (const struct pending_abstract_type *) val1;
-  tree type2 = (tree)val2;
+  const_tree const type2 = (const_tree)val2;
 
   return (pat1->type == type2);
 }
@@ -345,7 +336,7 @@ abstract_virtuals_error (tree decl, tree type)
    pedwarn.  */
 
 void
-cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type)
+cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type)
 {
   int decl = 0;
   void (*p_msg) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
@@ -436,7 +427,7 @@ cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type)
    required by ../tree.c.  */
 #undef cxx_incomplete_type_error
 void
-cxx_incomplete_type_error (tree value, tree type)
+cxx_incomplete_type_error (const_tree value, const_tree type)
 {
   cxx_incomplete_type_diagnostic (value, type, 0);
 }
@@ -592,7 +583,7 @@ store_init_value (tree decl, tree init)
   if (TREE_CODE (type) == ERROR_MARK)
     return NULL_TREE;
 
-  if (IS_AGGR_TYPE (type))
+  if (MAYBE_CLASS_TYPE_P (type))
     {
       gcc_assert (TYPE_HAS_TRIVIAL_INIT_REF (type)
                  || TREE_CODE (init) == CONSTRUCTOR);
@@ -703,16 +694,33 @@ digest_init (tree type, tree init)
                 counted in the length of the constant, but in C++ this would
                 be invalid.  */
              if (size < TREE_STRING_LENGTH (init))
-               pedwarn ("initializer-string for array of chars is too long");
+               permerror ("initializer-string for array of chars is too long");
            }
          return init;
        }
     }
 
   /* Handle scalar types (including conversions) and references.  */
-  if (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE)
-    return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
-                                      "initialization", NULL_TREE, 0);
+  if (TREE_CODE (type) != COMPLEX_TYPE
+      && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
+    {
+      tree *exp;
+
+      init = convert_for_initialization (0, type, init, LOOKUP_NORMAL,
+                                        "initialization", NULL_TREE, 0,
+                                         tf_warning_or_error);
+      exp = &init;
+
+      /* Skip any conversions since we'll be outputting the underlying
+        constant.  */
+      while (CONVERT_EXPR_P (*exp)
+            || TREE_CODE (*exp) == NON_LVALUE_EXPR)
+       exp = &TREE_OPERAND (*exp, 0);
+
+      *exp = cplus_expand_constant (*exp);
+
+      return init;
+    }
 
   /* Come here only for aggregates: records, arrays, unions, complex numbers
      and vectors.  */
@@ -744,7 +752,8 @@ digest_init (tree type, tree init)
 
       return convert_for_initialization (NULL_TREE, type, init,
                                         LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
-                                        "initialization", NULL_TREE, 0);
+                                        "initialization", NULL_TREE, 0,
+                                         tf_warning_or_error);
     }
 }
 
@@ -771,8 +780,8 @@ picflag_from_initializer (tree init)
 }
 
 /* Subroutine of process_init_constructor, which will process an initializer
-   INIT for a array or vector of type TYPE. Returns the flags (PICFLAG_*) which
-   describe the initializers.  */
+   INIT for an array or vector of type TYPE. Returns the flags (PICFLAG_*)
+   which describe the initializers.  */
 
 static int
 process_init_constructor_array (tree type, tree init)
@@ -838,11 +847,12 @@ process_init_constructor_array (tree type, tree init)
        if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
          {
            /* If this type needs constructors run for default-initialization,
-             we can't rely on the backend to do it for us, so build up
+             we can't rely on the back end to do it for us, so build up
              TARGET_EXPRs.  If the type in question is a class, just build
              one up; if it's an array, recurse.  */
-           if (IS_AGGR_TYPE (TREE_TYPE (type)))
-               next = build_functional_cast (TREE_TYPE (type), NULL_TREE);
+           if (MAYBE_CLASS_TYPE_P (TREE_TYPE (type)))
+              next = build_functional_cast (TREE_TYPE (type), NULL_TREE,
+                                            tf_warning_or_error);
            else
                next = build_constructor (NULL_TREE, NULL);
            next = digest_init (TREE_TYPE (type), next);
@@ -925,11 +935,12 @@ process_init_constructor_record (tree type, tree init)
       else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
        {
          /* If this type needs constructors run for
-            default-initialization, we can't rely on the backend to do it
+            default-initialization, we can't rely on the back end to do it
             for us, so build up TARGET_EXPRs.  If the type in question is
             a class, just build one up; if it's an array, recurse.  */
-         if (IS_AGGR_TYPE (TREE_TYPE (field)))
-           next = build_functional_cast (TREE_TYPE (field), NULL_TREE);
+         if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field)))
+           next = build_functional_cast (TREE_TYPE (field), NULL_TREE,
+                                          tf_warning_or_error);
          else
            next = build_constructor (NULL_TREE, NULL);
 
@@ -1070,7 +1081,6 @@ process_init_constructor (tree type, tree init)
   if (!(flags & PICFLAG_NOT_ALL_CONSTANT))
     {
       TREE_CONSTANT (init) = 1;
-      TREE_INVARIANT (init) = 1;
       if (!(flags & PICFLAG_NOT_ALL_SIMPLE))
        TREE_STATIC (init) = 1;
     }
@@ -1154,11 +1164,12 @@ build_x_arrow (tree expr)
       expr = build_non_dependent_expr (expr);
     }
 
-  if (IS_AGGR_TYPE (type))
+  if (MAYBE_CLASS_TYPE_P (type))
     {
       while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
                                   NULL_TREE, NULL_TREE,
-                                  /*overloaded_p=*/NULL)))
+                                  /*overloaded_p=*/NULL, 
+                                  tf_warning_or_error)))
        {
          if (expr == error_mark_node)
            return error_mark_node;
@@ -1198,7 +1209,7 @@ build_x_arrow (tree expr)
          return expr;
        }
 
-      return build_indirect_ref (last_rval, NULL);
+      return cp_build_indirect_ref (last_rval, NULL, tf_warning_or_error);
     }
 
   if (types_memoized)
@@ -1233,7 +1244,7 @@ build_m_component_ref (tree datum, tree component)
     }
 
   objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
-  if (! IS_AGGR_TYPE (objtype))
+  if (! MAYBE_CLASS_TYPE_P (objtype))
     {
       error ("cannot apply member pointer %qE to %qE, which is of "
             "non-class type %qT",
@@ -1268,6 +1279,8 @@ build_m_component_ref (tree datum, tree component)
 
   if (TYPE_PTRMEM_P (ptrmem_type))
     {
+      tree ptype;
+
       /* Compute the type of the field, as described in [expr.ref].
         There's no such thing as a mutable pointer-to-member, so
         things are not as complex as they are for references to
@@ -1284,9 +1297,11 @@ build_m_component_ref (tree datum, tree component)
 
       /* Build an expression for "object + offset" where offset is the
         value stored in the pointer-to-data-member.  */
-      datum = build2 (PLUS_EXPR, build_pointer_type (type),
-                     datum, build_nop (ptrdiff_type_node, component));
-      return build_indirect_ref (datum, 0);
+      ptype = build_pointer_type (type);
+      datum = build2 (POINTER_PLUS_EXPR, ptype,
+                     fold_convert (ptype, datum),
+                     build_nop (sizetype, component));
+      return cp_build_indirect_ref (datum, 0, tf_warning_or_error);
     }
   else
     return build2 (OFFSET_REF, type, datum, component);
@@ -1295,10 +1310,12 @@ build_m_component_ref (tree datum, tree component)
 /* Return a tree node for the expression TYPENAME '(' PARMS ')'.  */
 
 tree
-build_functional_cast (tree exp, tree parms)
+build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
 {
   /* This is either a call to a constructor,
      or a C cast in C++'s `functional' notation.  */
+
+  /* The type to which we are casting.  */
   tree type;
 
   if (exp == error_mark_node || parms == error_mark_node)
@@ -1317,14 +1334,14 @@ build_functional_cast (tree exp, tree parms)
       return t;
     }
 
-  if (! IS_AGGR_TYPE (type))
+  if (! MAYBE_CLASS_TYPE_P (type))
     {
       if (parms == NULL_TREE)
        return cp_convert (type, integer_zero_node);
 
       /* This must build a C cast.  */
       parms = build_x_compound_expr_from_list (parms, "functional cast");
-      return build_c_cast (type, parms);
+      return cp_build_c_cast (type, parms, complain);
     }
 
   /* Prepare to evaluate as a call to a constructor.  If this expression
@@ -1339,20 +1356,33 @@ build_functional_cast (tree exp, tree parms)
   if (abstract_virtuals_error (NULL_TREE, type))
     return error_mark_node;
 
+  /* [expr.type.conv]
+
+     If the expression list is a single-expression, the type
+     conversion is equivalent (in definedness, and if defined in
+     meaning) to the corresponding cast expression.  */
   if (parms && TREE_CHAIN (parms) == NULL_TREE)
-    return build_c_cast (type, TREE_VALUE (parms));
+    return cp_build_c_cast (type, TREE_VALUE (parms), complain);
+
+  /* [expr.type.conv]
+
+     The expression T(), where T is a simple-type-specifier for a
+     non-array complete object type or the (possibly cv-qualified)
+     void type, creates an rvalue of the specified type, which is
+     value-initialized.  */
 
-  /* We need to zero-initialize POD types.  */
-  if (parms == NULL_TREE 
-      && !CLASSTYPE_NON_POD_P (type)
-      && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+  if (parms == NULL_TREE
+      /* If there's a user-defined constructor, value-initialization is
+        just calling the constructor, so fall through.  */
+      && !TYPE_HAS_USER_CONSTRUCTOR (type))
     {
-      exp = build_constructor (type, NULL);
+      exp = build_value_init (type);
       return get_target_expr (exp);
     }
 
+  /* Call the constructor.  */
   exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
-                                  type, LOOKUP_NORMAL);
+                                  type, LOOKUP_NORMAL, complain);
 
   if (exp == error_mark_node)
     return error_mark_node;