OSDN Git Service

PR c++/25811
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Apr 2010 19:58:27 +0000 (19:58 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Apr 2010 19:58:27 +0000 (19:58 +0000)
* cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Declare.
* init.c (build_new_1): Check for uninitialized const members and
uninitialized reference members, when using new without
new-initializer. Call diagnose_uninitialized_cst_or_ref_member.
(diagnose_uninitialized_cst_or_ref_member): Define, call
diagnose_uninitialized_cst_or_ref_member_1.
(diagnose_uninitialized_cst_or_ref_member_1): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158239 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/pr25811.C [new file with mode: 0644]

index e56c77c..c32e19f 100644 (file)
@@ -1,3 +1,14 @@
+2010-04-12  Fabien Chene  <fabien.chene@gmail.com>
+
+       PR c++/25811
+       * cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Declare.
+       * init.c (build_new_1): Check for uninitialized const members and
+       uninitialized reference members, when using new without
+       new-initializer. Call diagnose_uninitialized_cst_or_ref_member.
+       (diagnose_uninitialized_cst_or_ref_member): Define, call
+       diagnose_uninitialized_cst_or_ref_member_1.
+       (diagnose_uninitialized_cst_or_ref_member_1): New function.
+
 2010-04-12  Richard Guenther  <rguenther@suse.de>
 
        PR c++/43611
index 941c49a..91f2a9e 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions for C++ parsing and type checking.
    Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -4852,6 +4852,7 @@ extern tree create_temporary_var          (tree);
 extern void initialize_vtbl_ptrs               (tree);
 extern tree build_java_class_ref               (tree);
 extern tree integral_constant_value            (tree);
+extern void diagnose_uninitialized_cst_or_ref_member (tree, bool);
 
 /* in lex.c */
 extern void cxx_dup_lang_specific_decl         (tree);
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))
     {
index f6fb943..4b79ce0 100644 (file)
@@ -1,3 +1,8 @@
+2010-04-12  Fabien Chene  <fabien.chene@gmail.com>
+
+       PR c++/25811
+       * g++.dg/init/pr25811.C: New test.
+
 2010-04-12  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * g++.dg/warn/miss-format-1.C: Removed *-*-solaris2.7 from
diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C
new file mode 100644 (file)
index 0000000..c906a9b
--- /dev/null
@@ -0,0 +1,195 @@
+// PR c++/25811
+// { dg-do compile }
+
+struct A1
+{
+  int const j; // { dg-message "should be initialized" }
+};
+
+struct A2
+{
+  int const volatile i; // { dg-message "should be initialized" }
+};
+
+struct A3
+{
+  int& ref; // { dg-message "should be initialized" }
+};
+
+struct A4
+{
+  int const& ref; // { dg-message "should be initialized" }
+};
+
+struct A5
+{
+  int& ref; // { dg-message "should be initialized" }
+  int const i; // { dg-message "should be initialized" }
+};
+
+template <class T> struct S1
+{
+  T const i; // { dg-message "should be initialized" }
+};
+
+template <class T> struct S2
+{
+  T const volatile i; // { dg-message "should be initialized" }
+};
+
+template <class T> struct S3
+{
+  T& ref; // { dg-message "should be initialized" }
+};
+
+template <class T> struct S4
+{
+  T const i; // { dg-message "should be initialized" }
+  T& ref; // { dg-message "should be initialized" }
+};
+
+struct X
+{
+  X () : c (0), r (c) {}
+  int const c;
+  int const& r;
+};
+
+struct Y11
+{
+  int const i; // { dg-message "should be initialized" }
+};
+
+struct Y1
+{
+  Y11 a[1];
+};
+
+struct Y22
+{
+  int& ref; // { dg-message "should be initialized" }
+};
+
+struct Y2
+{
+  Y22 a[1];
+};
+
+struct Z1
+{
+  int const i; // { dg-message "should be initialized" }
+};
+
+struct Z2
+{
+  int& ref; // { dg-message "should be initialized" }
+};
+
+struct Z3
+{
+  int const i; // { dg-message "should be initialized" }
+};
+
+struct Z4
+{
+  int& ref; // { dg-message "should be initialized" }
+};
+
+struct Z5
+{
+  int i;
+};
+
+struct Z
+{
+  Z1 z1;
+  Z2 z2;
+  Z3 z3;
+  Z4 z4;
+  Z5 z5;
+};
+
+union U
+{
+  int const i; // { dg-message "should be initialized" }
+};
+
+void f1 ()
+{
+  new A1; // { dg-error "uninitialized const member" }
+}
+
+void f2 ()
+{
+  new A2; // { dg-error "uninitialized const member" }
+}
+
+void f3 ()
+{
+  new A3; // { dg-error "uninitialized reference member" }
+}
+
+void f4 ()
+{
+  new A4; // { dg-error "uninitialized reference member" }
+}
+
+void f5 ()
+{
+  new A5; // { dg-error "uninitialized reference member|uninitialized const member" }
+}
+
+void f6 ()
+{
+  new S1<int>; // { dg-error "uninitialized const member" }
+}
+
+void f7 ()
+{
+  new S2<int>; // { dg-error "uninitialized const member" }
+}
+
+void f8 ()
+{
+  new S3<int>; // { dg-error "uninitialized reference member" }
+}
+
+void f9 ()
+{
+  new S4<int>; // { dg-error "uninitialized reference member|uninitialized const member" }
+}
+
+void f10 ()
+{
+  new X;
+}
+
+void f11 ()
+{
+  new A1[1]; // { dg-error "uninitialized const member" }
+}
+
+void f12 ()
+{
+  new A3[1]; // { dg-error "uninitialized reference member" }
+}
+
+void f13 ()
+{
+  new Y1; // { dg-error "uninitialized const member" }
+}
+
+void f14 ()
+{
+  new Y2; // { dg-error "uninitialized reference member" }
+}
+
+void f15 ()
+{
+  new Z; // { dg-error "uninitialized reference member|uninitialized const member" }
+}
+
+void f16 ()
+{
+  new U; // { dg-error "uninitialized const member" }
+}