Patchwork [C++] PR 54501

login
register
mail settings
Submitter Paolo Carlini
Date Oct. 17, 2012, 4:05 p.m.
Message ID <507ED72D.7080403@oracle.com>
Download mbox | patch
Permalink /patch/192082/
State New
Headers show

Comments

Paolo Carlini - Oct. 17, 2012, 4:05 p.m.
... oh well, I just realized that zero-size VECTORs don't make much 
sense and are early rejected, thus I can improve my earlier patch.

Now I'm happier: essentially I'm only *moving* code around ;)

Thanks,
Paolo.

//////////////////////
/cp
2012-10-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54501
	* decl.c (reshape_init_array): Check for zero-size arrays.
	(reshape_init_array_1): Don't handle zero-size arrays here.

/testsuite
2012-10-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54501
	* g++.dg/init/array30.C: New.
	* g++.dg/init/array0.C: Adjust.
	* g++.dg/parse/pr43765.C: Likewise.
Jason Merrill - Oct. 18, 2012, 1:17 a.m.
Hmm, I thought I fixed a very similar bug recently.

I'm concerned that this change will cause problems with brace-elision 
situations.  But then again, can we have a zero-length array followed by 
anything else?

Jason
Paolo Carlini - Oct. 18, 2012, 8:15 a.m.
Hi,

On 10/18/2012 03:17 AM, Jason Merrill wrote:
> Hmm, I thought I fixed a very similar bug recently.
>
> I'm concerned that this change will cause problems with brace-elision 
> situations.  But then again, can we have a zero-length array followed 
> by anything else?
If I understand correctly your hesitations, I don't think there are 
exceptions to the general rule that if the size of the array is zero 
there can be no initializers. This morning I investigated in some detail 
this special case (from a testcase I recently added, pr43765.C):

struct SomeType
{
   const char *values[];
};

it's in fact related because we parse it as:

struct SomeType
{
   const char *values[0];
};

(per grokdeclarator around line 10246). Given the way we parse it (not 
completely uncontroversial, IMHO, but that would be a separate issue), 
we do the right thing, we accept:

SomeType s = { };

and we reject:

SomeType s = { 1 };

Only the wording of the error changes (from "too many initializers" to 
"initializers provided") (*)

In any case, I can't imagine a different, safer, way to handle the issue 
we are facing. Do you have anything specific to suggest?

Thanks,
Paolo.

(*) Moreover we likewise accept:

SomeType s = { {  } };

and likewise reject:

SomeType s = { { { } } };
Jason Merrill - Oct. 18, 2012, 4:02 p.m.
On 10/18/2012 01:15 AM, Paolo Carlini wrote:
> If I understand correctly your hesitations, I don't think there are
> exceptions to the general rule that if the size of the array is zero
> there can be no initializers.

I'm thinking of a testcase like this, which is currently accepted:

struct A
{
   int i[0];
   int j;
};

struct A a = { 1 };

Here, since i has no elements, we should skip over it and apply the one 
initializer to j.

Jason
Paolo Carlini - Oct. 18, 2012, 5:06 p.m.
On 10/18/2012 06:02 PM, Jason Merrill wrote:
> On 10/18/2012 01:15 AM, Paolo Carlini wrote:
>> If I understand correctly your hesitations, I don't think there are
>> exceptions to the general rule that if the size of the array is zero
>> there can be no initializers.
>
> I'm thinking of a testcase like this, which is currently accepted:
>
> struct A
> {
>   int i[0];
>   int j;
> };
>
> struct A a = { 1 };
>
> Here, since i has no elements, we should skip over it and apply the 
> one initializer to j.
Ah, Ok, I was missing the "skipping" thing ;)

Let me see how we can handle this... it seems tricky.

Paolo.

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 192527)
+++ cp/decl.c	(working copy)
@@ -5022,10 +5022,6 @@  reshape_init_array_1 (tree elt_type, tree max_inde
 
   if (sized_array_p)
     {
-      /* Minus 1 is used for zero sized arrays.  */
-      if (integer_all_onesp (max_index))
-	return new_init;
-
       if (host_integerp (max_index, 1))
 	max_index_cst = tree_low_cst (max_index, 1);
       /* sizetype is sign extended, not zero extended.  */
@@ -5068,6 +5064,14 @@  reshape_init_array (tree type, reshape_iter *d, ts
   if (TYPE_DOMAIN (type))
     max_index = array_type_nelts (type);
 
+  /* Minus 1 is used for zero sized arrays.  */
+  if (max_index && integer_all_onesp (max_index))
+    {
+      if (complain & tf_error)
+	error ("initializers provided for zero-size array of type %qT", type);
+      return error_mark_node;
+    }
+
   return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
 }
 
Index: testsuite/g++.dg/parse/pr43765.C
===================================================================
--- testsuite/g++.dg/parse/pr43765.C	(revision 192527)
+++ testsuite/g++.dg/parse/pr43765.C	(working copy)
@@ -11,4 +11,4 @@  SomeType vals[] =
     {
         { values : temp, },
         0
-    };          // { dg-error "invalid" }
+    };          // { dg-error "zero-size" }
Index: testsuite/g++.dg/init/array30.C
===================================================================
--- testsuite/g++.dg/init/array30.C	(revision 0)
+++ testsuite/g++.dg/init/array30.C	(working copy)
@@ -0,0 +1,7 @@ 
+// PR c++/54501
+// { dg-options "" }
+
+int main()
+{
+  int a[][0] = {0};  // { dg-error "zero-size" }
+}
Index: testsuite/g++.dg/init/array0.C
===================================================================
--- testsuite/g++.dg/init/array0.C	(revision 192527)
+++ testsuite/g++.dg/init/array0.C	(working copy)
@@ -8,5 +8,5 @@  void foo()
     unsigned char dir;
     int data[0];
   } yanito;
-  static const yanito horse = { 1,  { 2,  3 }  }; // { dg-error "too many" }
+  static const yanito horse = { 1,  { 2,  3 }  }; // { dg-error "zero-size" }
 }