OSDN Git Service

PR c++/43951
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index e639744..e45d2b8 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -54,6 +54,7 @@ static tree dfs_initialize_vtbl_ptrs (tree, void *);
 static tree build_dtor_call (tree, special_function_kind, int);
 static tree build_field_list (tree, tree, int *);
 static tree build_vtbl_address (tree);
+static int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool);
 
 /* We are about to generate some complex initialization code.
    Conceptually, it is all a single expression.  However, we may want
@@ -505,6 +506,7 @@ perform_member_init (tree member, tree init)
     {
       if (init == NULL_TREE)
        {
+         tree core_type;
          /* member traversal: note it leaves init NULL */
          if (TREE_CODE (type) == REFERENCE_TYPE)
            permerror (DECL_SOURCE_LOCATION (current_function_decl),
@@ -514,6 +516,14 @@ perform_member_init (tree member, tree init)
            permerror (DECL_SOURCE_LOCATION (current_function_decl),
                       "uninitialized member %qD with %<const%> type %qT",
                       member, type);
+
+         core_type = strip_array_types (type);
+         if (CLASS_TYPE_P (core_type)
+             && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+                 || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
+           diagnose_uninitialized_cst_or_ref_member (core_type,
+                                                     /*using_new=*/false,
+                                                     /*complain=*/true);
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
@@ -834,7 +844,7 @@ emit_mem_initializers (tree mem_inits)
          base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
                                       subobject, 1);
          expand_aggr_init_1 (subobject, NULL_TREE,
-                             cp_build_indirect_ref (base_addr, NULL,
+                             cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
                              arguments,
                              LOOKUP_NORMAL,
@@ -918,7 +928,7 @@ expand_virtual_init (tree binfo, tree decl)
                      TREE_TYPE (vtt_parm),
                      vtt_parm,
                      vtt_index);
-      vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error);
+      vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error);
       vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
 
       /* The actual initializer is the VTT value only in the subobject
@@ -933,7 +943,7 @@ expand_virtual_init (tree binfo, tree decl)
     }
 
   /* Compute the location of the vtpr.  */
-  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, 
+  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL, 
                                                       tf_warning_or_error),
                               TREE_TYPE (binfo));
   gcc_assert (vtbl_ptr != error_mark_node);
@@ -1657,7 +1667,14 @@ constant_value_1 (tree decl, bool integral_p)
          init = DECL_INITIAL (decl);
        }
       if (init == error_mark_node)
-       return decl;
+       {
+         if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+           /* Treat the error as a constant to avoid cascading errors on
+              excessively recursive template instantiation (c++/9335).  */
+           return init;
+         else
+           return decl;
+       }
       /* Initializers in templates are generally expanded during
         instantiation, so before that for const int i(2)
         INIT is a TREE_LIST with the actual initializer as
@@ -1753,6 +1770,74 @@ build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts,
   return new_expr;
 }
 
+/* Diagnose uninitialized const members or reference members of type
+   TYPE. USING_NEW is used to disambiguate the diagnostic between a
+   new expression without a new-initializer and a declaration. Returns
+   the error count. */
+
+static int
+diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
+                                           bool using_new, bool complain)
+{
+  tree field;
+  int error_count = 0;
+
+  if (type_has_user_provided_constructor (type))
+    return 0;
+
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    {
+      tree field_type;
+
+      if (TREE_CODE (field) != FIELD_DECL)
+       continue;
+
+      field_type = strip_array_types (TREE_TYPE (field));
+
+      if (TREE_CODE (field_type) == REFERENCE_TYPE)
+       {
+         ++ error_count;
+         if (complain)
+           {
+             if (using_new)
+               error ("uninitialized reference member in %q#T "
+                      "using %<new%> without new-initializer", origin);
+             else
+               error ("uninitialized reference member in %q#T", origin);
+             inform (DECL_SOURCE_LOCATION (field),
+                     "%qD should be initialized", field);
+           }
+       }
+
+      if (CP_TYPE_CONST_P (field_type))
+       {
+         ++ error_count;
+         if (complain)
+           {
+             if (using_new)
+               error ("uninitialized const member in %q#T "
+                      "using %<new%> without new-initializer", origin);
+             else
+               error ("uninitialized const member in %q#T", origin);
+             inform (DECL_SOURCE_LOCATION (field),
+                     "%qD should be initialized", field);
+           }
+       }
+
+      if (CLASS_TYPE_P (field_type))
+       error_count
+         += diagnose_uninitialized_cst_or_ref_member_1 (field_type, origin,
+                                                        using_new, complain);
+    }
+  return error_count;
+}
+
+int
+diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool complain)
+{
+  return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain);
+}
+
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
@@ -1839,6 +1924,36 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 
   is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
 
+  if (*init == NULL)
+    {
+      bool maybe_uninitialized_error = false;
+      /* A program that calls for default-initialization [...] of an
+        entity of reference type is ill-formed. */
+      if (CLASSTYPE_REF_FIELDS_NEED_INIT (elt_type))
+       maybe_uninitialized_error = true;
+
+      /* A new-expression that creates an object of type T initializes
+        that object as follows:
+      - If the new-initializer is omitted:
+        -- If T is a (possibly cv-qualified) non-POD class type
+          (or array thereof), the object is default-initialized (8.5).
+          [...]
+        -- Otherwise, the object created has indeterminate
+          value. If T is a const-qualified type, or a (possibly
+          cv-qualified) POD class type (or array thereof)
+          containing (directly or indirectly) a member of
+          const-qualified type, the program is ill-formed; */
+
+      if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type))
+       maybe_uninitialized_error = true;
+
+      if (maybe_uninitialized_error
+         && diagnose_uninitialized_cst_or_ref_member (elt_type,
+                                                      /*using_new=*/true,
+                                                      complain & tf_error))
+       return error_mark_node;
+    }
+
   if (CP_TYPE_CONST_P (elt_type) && *init == NULL
       && !type_has_user_provided_default_constructor (elt_type))
     {
@@ -2055,7 +2170,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
                                alloc_node, cookie_ptr);
       size_ptr_type = build_pointer_type (sizetype);
       cookie_ptr = fold_convert (size_ptr_type, cookie_ptr);
-      cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+      cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
 
       cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
 
@@ -2067,7 +2182,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
                                            NEGATE_EXPR, sizetype,
                                            size_in_bytes (sizetype)));
 
-         cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+         cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
          cookie = build2 (MODIFY_EXPR, sizetype, cookie,
                           size_in_bytes (elt_type));
          cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
@@ -2154,7 +2269,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
        }
       else
        {
-         init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
+         init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
 
          if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
            {
@@ -2361,6 +2476,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
           else
             return error_mark_node;
         }
+      nelts = mark_rvalue_use (nelts);
       nelts = cp_save_expr (cp_convert (sizetype, nelts));
     }
 
@@ -2949,7 +3065,7 @@ build_vec_init (tree base, tree maxindex, tree init,
     {
       atype = build_pointer_type (atype);
       stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
-      stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain);
+      stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain);
       TREE_NO_WARNING (stmt_expr) = 1;
     }
 
@@ -3016,6 +3132,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
 
   type = TYPE_MAIN_VARIANT (type);
 
+  addr = mark_rvalue_use (addr);
+
   if (TREE_CODE (type) == POINTER_TYPE)
     {
       bool complete_p = true;
@@ -3144,7 +3262,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                                /*alloc_fn=*/NULL_TREE);
        }
 
-      expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, 
+      expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, 
                                                      tf_warning_or_error),
                              auto_delete, flags);
       if (do_delete)
@@ -3298,7 +3416,7 @@ build_vec_delete (tree base, tree maxindex,
                            size_ptr_type,
                            fold_convert (size_ptr_type, base),
                            cookie_addr);
-      maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error);
+      maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {