This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/30759: Initializer-list accepted for object of non-POD type
- From: Simon Martin <simartin at users dot sourceforge dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 26 May 2007 20:44:53 +0200
- Subject: [PATCH] Fix PR c++/30759: Initializer-list accepted for object of non-POD type
Hi all.
The following invalid snippet is accepted since version 3.4:
=== cut here ===
struct A {
A(int) { }
};
int main()
{
A a = { 6 };
}
=== cut here ===
It is invalid because A is not an aggregate (due to its constructor),
and its instances cannot therefore be initialized via an initializer list.
The problem is that the only check that we do in 'check_initializer'
when dealing with an initializer list for a non-aggregate is that there
is only one element in that list.
If I read the standard correctly, this constraint is for scalars, not
any non-aggregate (the error message that is issued if it is broken
suggests this as well: "scalar object %qD requires one element in
initializer").
The attached patch modifies 'check_initializer' so that when dealing
with an initializer list:
- For a scalar, we ensure that the initializer list only contains one
element
- For a non-aggregate type that is not a scalar (e.g. 'A' in the
snippet above), we issue the following error: "braces around initializer
for non-aggregate type %qT".
I have regtested it on i386-apple-darwin8.9.1 with no new unexpected
failures. Is it OK for mainline?
Best regards,
Simon
:ADDPATCH c++:
2007-05-26 Simon Martin <simartin@users.sourceforge.net>
PR c++/30759
* decl.c (check_initializer): Report an error when a brace enclosed
initializer is used for a non-aggregate type.
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c (revision 125087)
+++ gcc/cp/decl.c (working copy)
@@ -4777,14 +4777,25 @@ check_initializer (tree decl, tree init,
else
/* There is no way to make a variable-sized class type in GNU C++. */
gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
-
- if (!CP_AGGREGATE_TYPE_P (type)
- && init && BRACE_ENCLOSED_INITIALIZER_P (init)
- && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) != 1)
- {
- error ("scalar object %qD requires one element in initializer", decl);
- TREE_TYPE (decl) = error_mark_node;
- return NULL_TREE;
+
+ if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
+ {
+ int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
+ if (SCALAR_TYPE_P (type))
+ {
+ if (init_len != 1)
+ {
+ error ("scalar object %qD requires one element in initializer", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ return NULL_TREE;
+ }
+ }
+ else if (!CP_AGGREGATE_TYPE_P (type))
+ {
+ error ("braces around initializer for non-aggregate type %qT", type);
+ TREE_TYPE (decl) = error_mark_node;
+ return NULL_TREE;
+ }
}
if (TREE_CODE (decl) == CONST_DECL)
2007-05-26 Simon Martin <simartin@users.sourceforge.net>
PR c++/30759
* g++.dg/init/brace6.C: New test.
/* PR c++/30759 */
/* { dg-do "compile" } */
struct A {
A(int) { }
};
struct B {
B(const B&);
int b;
};
struct C {};
struct D { int c; };
int main()
{
int i = { 1 };
int j = { 1, 2 }; /* { dg-error "requires one element" } */
A a = { 6 }; /* { dg-error "initializer for non" } */
B b = { 6 }; /* { dg-error "initializer for non" } */
C c = { 6 }; /* { dg-error "too many initializers" } */
D d = { 6 };
}