Commit 40bb78ad by Fabien Chêne Committed by Jason Merrill

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
parent 48cf395b
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> 2010-05-06 Magnus Fromreide <magfr@lysator.liu.se>
Jason Merrill <jason@redhat.com> Jason Merrill <jason@redhat.com>
......
...@@ -4857,7 +4857,7 @@ extern tree create_temporary_var (tree); ...@@ -4857,7 +4857,7 @@ extern tree create_temporary_var (tree);
extern void initialize_vtbl_ptrs (tree); extern void initialize_vtbl_ptrs (tree);
extern tree build_java_class_ref (tree); extern tree build_java_class_ref (tree);
extern tree integral_constant_value (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 */ /* in lex.c */
extern void cxx_dup_lang_specific_decl (tree); extern void cxx_dup_lang_specific_decl (tree);
......
...@@ -54,7 +54,7 @@ static tree dfs_initialize_vtbl_ptrs (tree, void *); ...@@ -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_dtor_call (tree, special_function_kind, int);
static tree build_field_list (tree, tree, int *); static tree build_field_list (tree, tree, int *);
static tree build_vtbl_address (tree); 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. /* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want Conceptually, it is all a single expression. However, we may want
...@@ -522,7 +522,8 @@ perform_member_init (tree member, tree init) ...@@ -522,7 +522,8 @@ perform_member_init (tree member, tree init)
&& (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type) && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
|| CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))) || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
diagnose_uninitialized_cst_or_ref_member (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) else if (TREE_CODE (init) == TREE_LIST)
/* There was an explicit member initialization. Do some work /* 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, ...@@ -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 /* Diagnose uninitialized const members or reference members of type
TYPE. USING_NEW is used to disambiguate the diagnostic between a 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, diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
bool using_new) bool using_new, bool complain)
{ {
tree field; tree field;
int error_count = 0;
if (type_has_user_provided_constructor (type)) if (type_has_user_provided_constructor (type))
return; return 0;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) 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, ...@@ -1793,36 +1796,46 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
if (TREE_CODE (field_type) == REFERENCE_TYPE) if (TREE_CODE (field_type) == REFERENCE_TYPE)
{ {
if (using_new) ++ error_count;
error ("uninitialized reference member in %q#T " if (complain)
"using %<new%> without new-initializer", origin); {
else if (using_new)
error ("uninitialized reference member in %q#T", origin); error ("uninitialized reference member in %q#T "
inform (DECL_SOURCE_LOCATION (field), "using %<new%> without new-initializer", origin);
"%qD should be initialized", field); 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 (CP_TYPE_CONST_P (field_type))
{ {
if (using_new) ++ error_count;
error ("uninitialized const member in %q#T " if (complain)
"using %<new%> without new-initializer", origin); {
else if (using_new)
error ("uninitialized const member in %q#T", origin); error ("uninitialized const member in %q#T "
inform (DECL_SOURCE_LOCATION (field), "using %<new%> without new-initializer", origin);
"%qD should be initialized", field); 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)) if (CLASS_TYPE_P (field_type))
diagnose_uninitialized_cst_or_ref_member_1 (field_type, error_count
origin, using_new); += diagnose_uninitialized_cst_or_ref_member_1 (field_type, origin,
using_new, complain);
} }
return error_count;
} }
void int
diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new) 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 /* 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, ...@@ -1911,13 +1924,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL); 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 /* A program that calls for default-initialization [...] of an
entity of reference type is ill-formed. */ entity of reference type is ill-formed. */
if (CLASSTYPE_REF_FIELDS_NEED_INIT (elt_type)) 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 /* A new-expression that creates an object of type T initializes
that object as follows: that object as follows:
...@@ -1932,15 +1945,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, ...@@ -1932,15 +1945,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
const-qualified type, the program is ill-formed; */ const-qualified type, the program is ill-formed; */
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type)) if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type))
uninitialized_error = true; maybe_uninitialized_error = true;
if (uninitialized_error) if (maybe_uninitialized_error
{ && diagnose_uninitialized_cst_or_ref_member (elt_type,
if (complain & tf_error) /*using_new=*/true,
diagnose_uninitialized_cst_or_ref_member (elt_type, complain & tf_error))
/*using_new*/true); return error_mark_node;
return error_mark_node;
}
} }
if (CP_TYPE_CONST_P (elt_type) && *init == NULL if (CP_TYPE_CONST_P (elt_type) && *init == NULL
......
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> 2010-05-07 Daniel Franke <franke.daniel@gmail.com>
PR fortran/40728 PR fortran/40728
......
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment