aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorFabien Chêne <fabien.chene@gmail.com>2010-05-07 15:52:06 +0000
committerJason Merrill <jason@gcc.gnu.org>2010-05-07 11:52:06 -0400
commit40bb78ad246919ee068382c3a2cdf6f299e412c9 (patch)
tree509ac9f873d8887b78813e37442448aa6d8215b2 /gcc
parent48cf395bdb30be10a283c3ac4d6217c322f39070 (diff)
downloadgcc-40bb78ad246919ee068382c3a2cdf6f299e412c9.zip
gcc-40bb78ad246919ee068382c3a2cdf6f299e412c9.tar.gz
gcc-40bb78ad246919ee068382c3a2cdf6f299e412c9.tar.bz2
re PR c++/43951 (Revision 158918 miscompiled 483.xalancbmk in SPEC CPU 2006)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/init.c83
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/init/new29.C33
5 files changed, 98 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 860f4e7..d41a95f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 22a7487..0528289 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index a2d9837..e45d2b8 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 297ae76..08da4e6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..1ca8ca0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new29.C
@@ -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;
+}