OSDN Git Service

PR c++/25811
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 1bd80ff..c1f1cbf 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 void diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool);
 
 /* We are about to generate some complex initialization code.
    Conceptually, it is all a single expression.  However, we may want
@@ -1753,6 +1754,59 @@ 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 */
+
+static void
+diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
+                                           bool using_new)
+{
+  tree field;
+
+  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)
+       {
+         if (using_new)
+           error ("uninitialized reference member in %q#T using %<new%>",
+                  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))
+       {
+         if (using_new)
+           error ("uninitialized const member in %q#T using %<new%>",
+                  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))
+       diagnose_uninitialized_cst_or_ref_member_1 (field_type,
+                                                   origin, using_new);
+    }
+}
+
+void
+diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new)
+{
+  diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new);
+}
+
 /* 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 +1893,38 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 
   is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
 
+  if (*init == NULL && !type_has_user_provided_constructor (elt_type))
+    {
+      bool 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))
+       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))
+       uninitialized_error = true;
+
+      if (uninitialized_error)
+       {
+         if (complain & tf_error)
+           diagnose_uninitialized_cst_or_ref_member (elt_type,
+                                                     /*using_new*/true);
+         return error_mark_node;
+       }
+    }
+
   if (CP_TYPE_CONST_P (elt_type) && *init == NULL
       && !type_has_user_provided_default_constructor (elt_type))
     {