This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/19989 (4.0/4.1 regression)
- From: Josh Conner <jconner at apple dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 02 Nov 2005 17:10:50 -0800
- Subject: [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;
}