This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 };
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]