Commit 6132bdd7 by Jason Merrill Committed by Jason Merrill

Core 234 - allow const objects with no initializer or user-provided default...

	Core 234 - allow const objects with no initializer or
	user-provided default constructor if the defaulted constructor
	initializes all the subobjects.
	PR c++/20039
	PR c++/42844
	* class.c (default_init_uninitialized_part): New.
	* cp-tree.h: Declare it.
	* decl.c (check_for_uninitialized_const_var): Use it.
	* init.c (perform_member_init): Likewise.
	(build_new_1): Likewise.
	* method.c (walk_field_subobs): Likewise.

From-SVN: r179130
parent d303ec8e
2011-09-23 Jason Merrill <jason@redhat.com>
Core 234 - allow const objects with no initializer or
user-provided default constructor if the defaulted constructor
initializes all the subobjects.
PR c++/20039
PR c++/42844
* class.c (default_init_uninitialized_part): New.
* cp-tree.h: Declare it.
* decl.c (check_for_uninitialized_const_var): Use it.
* init.c (perform_member_init): Likewise.
(build_new_1): Likewise.
* method.c (walk_field_subobs): Likewise.
2011-09-23 Paolo Carlini <paolo.carlini@oracle.com> 2011-09-23 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50258 PR c++/50258
......
...@@ -4356,6 +4356,40 @@ type_has_user_provided_default_constructor (tree t) ...@@ -4356,6 +4356,40 @@ type_has_user_provided_default_constructor (tree t)
return false; return false;
} }
/* If default-initialization leaves part of TYPE uninitialized, returns
a DECL for the field or TYPE itself (DR 253). */
tree
default_init_uninitialized_part (tree type)
{
tree t, r, binfo;
int i;
type = strip_array_types (type);
if (!CLASS_TYPE_P (type))
return type;
if (type_has_user_provided_default_constructor (type))
return NULL_TREE;
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, t); ++i)
{
r = default_init_uninitialized_part (BINFO_TYPE (t));
if (r)
return r;
}
for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL
&& !DECL_ARTIFICIAL (t)
&& !DECL_INITIAL (t))
{
r = default_init_uninitialized_part (TREE_TYPE (t));
if (r)
return DECL_P (r) ? r : t;
}
return NULL_TREE;
}
/* Returns true iff for class T, a trivial synthesized default constructor /* Returns true iff for class T, a trivial synthesized default constructor
would be constexpr. */ would be constexpr. */
......
...@@ -4838,6 +4838,7 @@ extern tree in_class_defaulted_default_constructor (tree); ...@@ -4838,6 +4838,7 @@ extern tree in_class_defaulted_default_constructor (tree);
extern bool user_provided_p (tree); extern bool user_provided_p (tree);
extern bool type_has_user_provided_constructor (tree); extern bool type_has_user_provided_constructor (tree);
extern bool type_has_user_provided_default_constructor (tree); extern bool type_has_user_provided_default_constructor (tree);
extern tree default_init_uninitialized_part (tree);
extern bool trivial_default_constructor_is_constexpr (tree); extern bool trivial_default_constructor_is_constexpr (tree);
extern bool type_has_constexpr_default_constructor (tree); extern bool type_has_constexpr_default_constructor (tree);
extern bool type_has_virtual_destructor (tree); extern bool type_has_virtual_destructor (tree);
......
...@@ -4899,15 +4899,16 @@ check_for_uninitialized_const_var (tree decl) ...@@ -4899,15 +4899,16 @@ check_for_uninitialized_const_var (tree decl)
if (TREE_CODE (decl) == VAR_DECL if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE && TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type) && CP_TYPE_CONST_P (type)
&& (!TYPE_NEEDS_CONSTRUCTING (type)
|| !type_has_user_provided_default_constructor (type))
&& !DECL_INITIAL (decl)) && !DECL_INITIAL (decl))
{ {
tree field = default_init_uninitialized_part (type);
if (!field)
return;
permerror (DECL_SOURCE_LOCATION (decl), permerror (DECL_SOURCE_LOCATION (decl),
"uninitialized const %qD", decl); "uninitialized const %qD", decl);
if (CLASS_TYPE_P (type) if (CLASS_TYPE_P (type))
&& !type_has_user_provided_default_constructor (type))
{ {
tree defaulted_ctor; tree defaulted_ctor;
...@@ -4918,6 +4919,8 @@ check_for_uninitialized_const_var (tree decl) ...@@ -4918,6 +4919,8 @@ check_for_uninitialized_const_var (tree decl)
inform (DECL_SOURCE_LOCATION (defaulted_ctor), inform (DECL_SOURCE_LOCATION (defaulted_ctor),
"constructor is not user-provided because it is " "constructor is not user-provided because it is "
"explicitly defaulted in the class body"); "explicitly defaulted in the class body");
inform (0, "and the implicitly-defined constructor does not "
"initialize %q+#D", field);
} }
} }
} }
......
...@@ -579,7 +579,7 @@ perform_member_init (tree member, tree init) ...@@ -579,7 +579,7 @@ perform_member_init (tree member, tree init)
flags |= LOOKUP_DEFAULTED; flags |= LOOKUP_DEFAULTED;
if (CP_TYPE_CONST_P (type) if (CP_TYPE_CONST_P (type)
&& init == NULL_TREE && init == NULL_TREE
&& !type_has_user_provided_default_constructor (type)) && default_init_uninitialized_part (type))
/* TYPE_NEEDS_CONSTRUCTING can be set just because we have a /* TYPE_NEEDS_CONSTRUCTING can be set just because we have a
vtable; still give this diagnostic. */ vtable; still give this diagnostic. */
permerror (DECL_SOURCE_LOCATION (current_function_decl), permerror (DECL_SOURCE_LOCATION (current_function_decl),
...@@ -2088,7 +2088,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, ...@@ -2088,7 +2088,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
} }
if (CP_TYPE_CONST_P (elt_type) && *init == NULL if (CP_TYPE_CONST_P (elt_type) && *init == NULL
&& !type_has_user_provided_default_constructor (elt_type)) && default_init_uninitialized_part (elt_type))
{ {
if (complain & tf_error) if (complain & tf_error)
error ("uninitialized const in %<new%> of %q#T", elt_type); error ("uninitialized const in %<new%> of %q#T", elt_type);
......
...@@ -1015,8 +1015,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, ...@@ -1015,8 +1015,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
{ {
bool bad = true; bool bad = true;
if (CP_TYPE_CONST_P (mem_type) if (CP_TYPE_CONST_P (mem_type)
&& (!CLASS_TYPE_P (mem_type) && default_init_uninitialized_part (mem_type))
|| !type_has_user_provided_default_constructor (mem_type)))
{ {
if (msg) if (msg)
error ("uninitialized non-static const member %q#D", error ("uninitialized non-static const member %q#D",
......
2011-09-23 Jason Merrill <jason@redhat.com>
Core 234
* g++.dg/init/const8.C: New.
* g++.dg/cpp0x/constexpr-object1.C: Add a data member.
* g++.dg/cpp0x/defaulted2.C: Likewise.
* g++.dg/cpp0x/pr42844-2.C: Likewise.
* g++.dg/init/pr20039.C: Likewise.
* g++.dg/init/pr42844.C: Likewise.
2011-09-23 Jan Hubicka <jh@suse.cz> 2011-09-23 Jan Hubicka <jh@suse.cz>
* gcc.dg/ipa/inline-1.c: new testcase. * gcc.dg/ipa/inline-1.c: new testcase.
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
// p 1 constexpr specifier // p 1 constexpr specifier
// objects, static const data // objects, static const data
struct A1 { }; // { dg-message "no user-provided default constructor" } struct A1 { int i; }; // { dg-message "no user-provided default constructor" }
constexpr int i1 = 1024; constexpr int i1 = 1024;
constexpr A1 a1 = A1(); constexpr A1 a1 = A1();
......
...@@ -17,7 +17,8 @@ void g() = delete; // { dg-error "redefinition" } ...@@ -17,7 +17,8 @@ void g() = delete; // { dg-error "redefinition" }
struct B // { dg-message "user-provided default constructor" } struct B // { dg-message "user-provided default constructor" }
{ {
B() = default; // { dg-message "not user-provided" } int i;
B() = default; // { dg-message "not user-provided" }
}; };
const B b; // { dg-error "uninitialized const" } const B b; // { dg-error "uninitialized const" }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
struct A // { dg-message "user-provided default constructor" } struct A // { dg-message "user-provided default constructor" }
{ {
int i;
A() = default; // { dg-message "not user-provided" } A() = default; // { dg-message "not user-provided" }
}; };
...@@ -14,17 +15,20 @@ struct Base ...@@ -14,17 +15,20 @@ struct Base
struct Derived : Base // { dg-message "user-provided default constructor" } struct Derived : Base // { dg-message "user-provided default constructor" }
{ {
int i;
Derived() = default; // { dg-message "not user-provided" } Derived() = default; // { dg-message "not user-provided" }
}; };
struct Derived2 : Base // { dg-message "user-provided default constructor" } struct Derived2 : Base // { dg-message "user-provided default constructor" }
{ {
int i;
Derived2() = default; // { dg-message "not user-provided" } Derived2() = default; // { dg-message "not user-provided" }
Derived2( Derived2 const& ) = default; Derived2( Derived2 const& ) = default;
}; };
struct Derived3 : Base // { dg-message "user-provided default constructor" } struct Derived3 : Base // { dg-message "user-provided default constructor" }
{ {
int i;
Derived3( Derived3 const& ) = default; Derived3( Derived3 const& ) = default;
Derived3() = default; // { dg-message "not user-provided" } Derived3() = default; // { dg-message "not user-provided" }
}; };
......
// DR 234 - it should be OK to leave off the initializer of a const
// variable if the default constructor fully initializes the object.
struct A { };
const A a;
struct B { A a; };
const B b;
struct C { virtual void f(); };
const C c;
...@@ -10,6 +10,7 @@ struct M ...@@ -10,6 +10,7 @@ struct M
struct X struct X
{ {
M m; M m;
int i;
}; };
int mymain() int mymain()
......
...@@ -6,19 +6,19 @@ struct A ...@@ -6,19 +6,19 @@ struct A
A(){} A(){}
}; };
struct B : A {}; // { dg-message "user-provided default constructor" } struct B : A { int i; }; // { dg-message "user-provided default constructor" }
struct C : A {}; // { dg-message "user-provided default constructor" } struct C : A { int i; }; // { dg-message "user-provided default constructor" }
struct D : B { D() {} }; struct D : B { D() {} };
struct E {}; // { dg-message "user-provided default constructor" } struct E { int i; }; // { dg-message "user-provided default constructor" }
template <class T> template <class T>
struct F : A {}; // { dg-message "user-provided default constructor" } struct F : A { T t; }; // { dg-message "user-provided default constructor" }
template <class T> template <class T>
struct G {}; // { dg-message "user-provided default constructor" } struct G { T t; }; // { dg-message "user-provided default constructor" }
void f () void f ()
{ {
...@@ -41,9 +41,9 @@ void f () ...@@ -41,9 +41,9 @@ void f ()
extern G<int> const gext; extern G<int> const gext;
} }
struct H {}; // { dg-message "user-provided default constructor" } struct H { int i; }; // { dg-message "user-provided default constructor" }
struct I : A {}; // { dg-message "user-provided default constructor" } struct I : A { int i; }; // { dg-message "user-provided default constructor" }
template <class T> template <class T>
void g () void g ()
......
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