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++/19989 (4.0/4.1 regression)


The attached patches fix PR c++/19989 on the 4.0 and 4.1 branches.
Without this fix, code of this form is rejected:

  template<int> struct A
  {
    static const int i = 0;
  };

  template<int N> struct B
  {
    int x[A<N>::i];
  };

  B<0> b;

It was rejected because template instantiation was being conservative in
not allowing zero-sized arrays, to avoid (correctly) something like this
from also being accepted:

  template<int M> void foobar (int (*) [M] = 0 );

  void fn (void)
  {
    foobar<0>();
  }

Fortunately, we can distinguish between these instances in this code by
looking at the complain variable -- when we're committed to applying a
template (as in the first case), tf_error will be set.

Other points worth mentioning:

* The error message for array size <= 0: "creating array with size zero"
was incorrect for negative values -- I split this into an always-invalid
case of less than zero (with an appropriate error message) and the
sometimes-invalid case of zero.

* The code for handling an explicit array of size zero:
       if (integer_zerop (omax)) {...}
was redundant -- if this error would have triggered (which I couldn't
manufacture), a pedwarn would have been generated by the immediately
following call to compute_array_index_type.

Tested on i686-pc-linux-gnu for both trunk and 4.0 with all default
languages and no regressions.

Also tested on arm-none-elf for both trunk and 4.0 with c, c++ and no
regressions.

OK for 4.0 and trunk?

Thanks -

Josh
Index: gcc/testsuite/g++.dg/ext/array2.C
===================================================================
--- gcc/testsuite/g++.dg/ext/array2.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/array2.C	(revision 0)
@@ -0,0 +1,18 @@
+// { dg-do compile }
+
+// Avoid -pedantic-error default
+// { dg-options "" }
+ 
+// PR 19989 - dependent array of size 0 fails to compile.
+
+template<int I> struct A
+{
+  static const int zero = 0;
+};
+
+template<int N> struct B
+{
+  int x[A<N>::zero];
+};
+
+B<0> b;
Index: gcc/testsuite/g++.dg/template/dependent-name3.C
===================================================================
--- gcc/testsuite/g++.dg/template/dependent-name3.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/dependent-name3.C	(revision 0)
@@ -0,0 +1,17 @@
+// { dg-do compile }
+
+// Dependent arrays of invalid size generate appropriate error messages
+
+template<int I> struct A
+{
+  static const int zero = 0;
+  static const int minus_one = -1;
+};
+
+template<int N> struct B
+{
+  int x[A<N>::zero];       // { dg-error "zero" }
+  int y[A<N>::minus_one];  // { dg-error "negative" }
+};
+
+B<0> b;
Index: gcc/testsuite/g++.dg/template/dependent-name4.C
===================================================================
--- gcc/testsuite/g++.dg/template/dependent-name4.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/dependent-name4.C	(revision 0)
@@ -0,0 +1,15 @@
+// { dg-do compile }
+
+// Dependent arrays of invalid size cause template instantiation failure.
+
+// We'll get an error message (duplicate matching templates) if the first
+//  pattern is incorrectly allowed to match.
+
+template<int M> void foobar (int (*) [M] = 0 );
+template<int M> void foobar ( );
+
+void fn (void)
+{
+  foobar<0>();
+  foobar<-1>();
+}
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 106378)
+++ gcc/cp/pt.c	(working copy)
@@ -7065,25 +7065,25 @@ tsubst (tree t, tree args, tsubst_flags_
 	max = tsubst_template_arg (omax, args, complain, in_decl);
 	max = fold_decl_constant_value (max);
 
-	if (integer_zerop (omax))
-	  {
-	    /* Still allow an explicit array of size zero.  */
-	    if (pedantic)
-	      pedwarn ("creating array with size zero");
-	  }
-	else if (integer_zerop (max)
-		 || (TREE_CODE (max) == INTEGER_CST
-		     && INT_CST_LT (max, integer_zero_node)))
-	  {
-	    /* [temp.deduct]
+	/* [temp.deduct]
 
-	       Type deduction may fail for any of the following
-	       reasons:
+	   Type deduction may fail for any of the following
+	   reasons:
 
-		 Attempting to create an array with a size that is
-		 zero or negative.  */
+	     Attempting to create an array with a size that is
+	     zero or negative.  */
+	if (integer_zerop (max) && !(complain & tf_error))
+	  {
+	    /* We must fail if performing argument deduction (as
+	       indicated by the state of complain), so that
+	       another substitution can be found.  */
+	    return error_mark_node;
+	  }
+	else if (TREE_CODE (max) == INTEGER_CST
+		 && INT_CST_LT (max, integer_zero_node))
+	  {
 	    if (complain & tf_error)
-	      error ("creating array with size zero (%qE)", max);
+	      error ("creating array with negative size (%qE)", max);
 
 	    return error_mark_node;
 	  }
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 106378)
+++ gcc/cp/pt.c	(working copy)
@@ -6986,25 +6986,25 @@ tsubst (tree t, tree args, tsubst_flags_
 	max = tsubst_template_arg (omax, args, complain, in_decl);
 	max = fold_decl_constant_value (max);
 
-	if (integer_zerop (omax))
+	/* [temp.deduct]
+
+	   Type deduction may fail for any of the following
+	   reasons:
+
+	     Attempting to create an array with a size that is
+	     zero or negative.  */
+	if (integer_zerop (max) && !(complain & tf_error))
 	  {
-	    /* Still allow an explicit array of size zero.  */
-	    if (pedantic)
-	      pedwarn ("creating array with size zero");
+	    /* We must fail if performing argument deduction (as
+	       indicated by the state of complain), so that
+	       another substitution can be found.  */
+	    return error_mark_node;
 	  }
-	else if (integer_zerop (max) 
-		 || (TREE_CODE (max) == INTEGER_CST 
-		     && INT_CST_LT (max, integer_zero_node)))
+	else if (TREE_CODE (max) == INTEGER_CST
+		 && INT_CST_LT (max, integer_zero_node))
 	  {
-	    /* [temp.deduct]
-
-	       Type deduction may fail for any of the following
-	       reasons:  
-
-		 Attempting to create an array with a size that is
-		 zero or negative.  */
 	    if (complain & tf_error)
-	      error ("creating array with size zero (%qE)", max);
+	      error ("creating array with negative size (%qE)", max);
 
 	    return error_mark_node;
 	  }

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