mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-26 07:24:08 +08:00
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
This commit is contained in:
parent
d303ec8e17
commit
6132bdd72e
@ -1,3 +1,17 @@
|
||||
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>
|
||||
|
||||
PR c++/50258
|
||||
|
@ -4356,6 +4356,40 @@ type_has_user_provided_default_constructor (tree t)
|
||||
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
|
||||
would be constexpr. */
|
||||
|
||||
|
@ -4838,6 +4838,7 @@ extern tree in_class_defaulted_default_constructor (tree);
|
||||
extern bool user_provided_p (tree);
|
||||
extern bool type_has_user_provided_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 type_has_constexpr_default_constructor (tree);
|
||||
extern bool type_has_virtual_destructor (tree);
|
||||
|
@ -4899,15 +4899,16 @@ check_for_uninitialized_const_var (tree decl)
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& TREE_CODE (type) != REFERENCE_TYPE
|
||||
&& CP_TYPE_CONST_P (type)
|
||||
&& (!TYPE_NEEDS_CONSTRUCTING (type)
|
||||
|| !type_has_user_provided_default_constructor (type))
|
||||
&& !DECL_INITIAL (decl))
|
||||
{
|
||||
tree field = default_init_uninitialized_part (type);
|
||||
if (!field)
|
||||
return;
|
||||
|
||||
permerror (DECL_SOURCE_LOCATION (decl),
|
||||
"uninitialized const %qD", decl);
|
||||
|
||||
if (CLASS_TYPE_P (type)
|
||||
&& !type_has_user_provided_default_constructor (type))
|
||||
if (CLASS_TYPE_P (type))
|
||||
{
|
||||
tree defaulted_ctor;
|
||||
|
||||
@ -4918,6 +4919,8 @@ check_for_uninitialized_const_var (tree decl)
|
||||
inform (DECL_SOURCE_LOCATION (defaulted_ctor),
|
||||
"constructor is not user-provided because it is "
|
||||
"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)
|
||||
flags |= LOOKUP_DEFAULTED;
|
||||
if (CP_TYPE_CONST_P (type)
|
||||
&& 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
|
||||
vtable; still give this diagnostic. */
|
||||
permerror (DECL_SOURCE_LOCATION (current_function_decl),
|
||||
@ -2088,7 +2088,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
|
||||
}
|
||||
|
||||
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)
|
||||
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,
|
||||
{
|
||||
bool bad = true;
|
||||
if (CP_TYPE_CONST_P (mem_type)
|
||||
&& (!CLASS_TYPE_P (mem_type)
|
||||
|| !type_has_user_provided_default_constructor (mem_type)))
|
||||
&& default_init_uninitialized_part (mem_type))
|
||||
{
|
||||
if (msg)
|
||||
error ("uninitialized non-static const member %q#D",
|
||||
|
@ -1,3 +1,13 @@
|
||||
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>
|
||||
|
||||
* gcc.dg/ipa/inline-1.c: new testcase.
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
// p 1 constexpr specifier
|
||||
// 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 A1 a1 = A1();
|
||||
|
@ -17,7 +17,8 @@ void g() = delete; // { dg-error "redefinition" }
|
||||
|
||||
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" }
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
struct A // { dg-message "user-provided default constructor" }
|
||||
{
|
||||
int i;
|
||||
A() = default; // { dg-message "not user-provided" }
|
||||
};
|
||||
|
||||
@ -14,17 +15,20 @@ struct Base
|
||||
|
||||
struct Derived : Base // { dg-message "user-provided default constructor" }
|
||||
{
|
||||
int i;
|
||||
Derived() = default; // { dg-message "not user-provided" }
|
||||
};
|
||||
|
||||
struct Derived2 : Base // { dg-message "user-provided default constructor" }
|
||||
{
|
||||
int i;
|
||||
Derived2() = default; // { dg-message "not user-provided" }
|
||||
Derived2( Derived2 const& ) = default;
|
||||
};
|
||||
|
||||
struct Derived3 : Base // { dg-message "user-provided default constructor" }
|
||||
{
|
||||
int i;
|
||||
Derived3( Derived3 const& ) = default;
|
||||
Derived3() = default; // { dg-message "not user-provided" }
|
||||
};
|
||||
|
11
gcc/testsuite/g++.dg/init/const8.C
Normal file
11
gcc/testsuite/g++.dg/init/const8.C
Normal file
@ -0,0 +1,11 @@
|
||||
// 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
|
||||
struct X
|
||||
{
|
||||
M m;
|
||||
int i;
|
||||
};
|
||||
|
||||
int mymain()
|
||||
|
@ -6,19 +6,19 @@ struct 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 E {}; // { dg-message "user-provided default constructor" }
|
||||
struct E { int i; }; // { dg-message "user-provided default constructor" }
|
||||
|
||||
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>
|
||||
struct G {}; // { dg-message "user-provided default constructor" }
|
||||
struct G { T t; }; // { dg-message "user-provided default constructor" }
|
||||
|
||||
void f ()
|
||||
{
|
||||
@ -41,9 +41,9 @@ void f ()
|
||||
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>
|
||||
void g ()
|
||||
|
Loading…
Reference in New Issue
Block a user