re PR c++/43951 (Revision 158918 miscompiled 483.xalancbmk in SPEC CPU 2006)
authorFabien Chêne <fabien.chene@gmail.com>
Fri, 7 May 2010 15:52:06 +0000 (15:52 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 7 May 2010 15:52:06 +0000 (11:52 -0400)
PR c++/43951
* init.c (diagnose_uninitialized_cst_or_ref_member_1): Returns the
error count. Emit errors only if compain is true.
(build_new_1): Do not return error_mark_node if
diagnose_uninitialized_cst_or_ref_member_1 does not diagnose any
errors. Delay the check for user-provided constructor.
(perform_member_init): Adjust.
* cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Change the
prototype.

From-SVN: r159158

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

index 860f4e7..d41a95f 100644 (file)
@@ -1,3 +1,15 @@
+2010-05-07  Fabien Chêne  <fabien.chene@gmail.com>
+
+       PR c++/43951
+       * init.c (diagnose_uninitialized_cst_or_ref_member_1): Returns the
+       error count. Emit errors only if compain is true.
+       (build_new_1): Do not return error_mark_node if
+       diagnose_uninitialized_cst_or_ref_member_1 does not diagnose any
+       errors. Delay the check for user-provided constructor.
+       (perform_member_init): Adjust.
+       * cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Change the
+       prototype.
+
 2010-05-06  Magnus Fromreide  <magfr@lysator.liu.se>
            Jason Merrill  <jason@redhat.com>
 
index 22a7487..0528289 100644 (file)
@@ -4857,7 +4857,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);
+extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool);
 
 /* in lex.c */
 extern void cxx_dup_lang_specific_decl         (tree);
index a2d9837..e45d2b8 100644 (file)
@@ -54,7 +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);
+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
@@ -522,7 +522,8 @@ perform_member_init (tree member, tree init)
              && (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);
+                                                     /*using_new=*/false,
+                                                     /*complain=*/true);
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
@@ -1771,16 +1772,18 @@ build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts,
 
 /* 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 */
+   new expression without a new-initializer and a declaration. Returns
+   the error count. */
 
-static void
+static int
 diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
-                                           bool using_new)
+                                           bool using_new, bool complain)
 {
   tree field;
+  int error_count = 0;
 
   if (type_has_user_provided_constructor (type))
-    return;
+    return 0;
 
   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     {
@@ -1793,36 +1796,46 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
 
       if (TREE_CODE (field_type) == REFERENCE_TYPE)
        {
-         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);
+         ++ 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))
        {
-         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);
+         ++ 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))
-       diagnose_uninitialized_cst_or_ref_member_1 (field_type,
-                                                   origin, using_new);
+       error_count
+         += diagnose_uninitialized_cst_or_ref_member_1 (field_type, origin,
+                                                        using_new, complain);
     }
+  return error_count;
 }
 
-void
-diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new)
+int
+diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool complain)
 {
-  diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new);
+  return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain);
 }
 
 /* Generate code for a new-expression, including calling the "operator
@@ -1911,13 +1924,13 @@ 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))
+  if (*init == NULL)
     {
-      bool uninitialized_error = false;
+      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))
-       uninitialized_error = true;
+       maybe_uninitialized_error = true;
 
       /* A new-expression that creates an object of type T initializes
         that object as follows:
@@ -1932,15 +1945,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
           const-qualified type, the program is ill-formed; */
 
       if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type))
-       uninitialized_error = true;
+       maybe_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 (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
index 297ae76..08da4e6 100644 (file)
@@ -1,3 +1,8 @@
+2010-05-07  Fabien Chêne  <fabien.chene@gmail.com>
+
+       PR c++/43951
+       * g++.dg/init/new29.C: New.
+
 2010-05-07  Daniel Franke  <franke.daniel@gmail.com>
 
         PR fortran/40728
diff --git a/gcc/testsuite/g++.dg/init/new29.C b/gcc/testsuite/g++.dg/init/new29.C
new file mode 100644 (file)
index 0000000..1ca8ca0
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/43951
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort ();
+
+class Foo
+{
+public:
+  Foo () : xxx (1) {};
+  const int xxx;
+};
+
+struct Foo2
+{
+  Foo foo;
+};
+
+Foo2 *
+bar ()
+{
+  return new Foo2;
+}
+
+int
+main ()
+{
+  Foo2 *p = bar ();
+
+  if (p->foo.xxx != 1)
+    abort ();
+  return 0;
+}