aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-09-07 01:04:07 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-09-07 01:04:07 +0000
commit6ee3ffe85ea599b1d977615ee31b8421563312c0 (patch)
treead868713c74b728318412e4f976f6e9e9eced7ed /gcc
parentd0304854de398cc3979df4976047c2dcd5de0723 (diff)
downloadgcc-6ee3ffe85ea599b1d977615ee31b8421563312c0.zip
gcc-6ee3ffe85ea599b1d977615ee31b8421563312c0.tar.gz
gcc-6ee3ffe85ea599b1d977615ee31b8421563312c0.tar.bz2
re PR c++/28903 (Rejects VLA in template class's member with using)
PR c++/28903 * pt.c (tsubst): Use fold_non_dependent_expr to fold array dimensions. PR c++/28886 * pt.c (unify): Avoid unnecessary calls to fold_build2 for array dimensions. From-SVN: r116736
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/pt.c59
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/ext/vla3.C24
-rw-r--r--gcc/testsuite/g++.dg/template/array16.C9
5 files changed, 98 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index cd1af6f..60d2fb2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2006-09-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/28903
+ * pt.c (tsubst): Use fold_non_dependent_expr to fold array
+ dimensions.
+
+ PR c++/28886
+ * pt.c (unify): Avoid unnecessary calls to fold_build2 for array
+ dimensions.
+
2006-09-06 Jason Merrill <jason@redhat.com>
PR c++/26696
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d278b00..715b946 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7216,9 +7216,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
- /* The array dimension behaves like a non-type template arg,
- in that we want to fold it as much as possible. */
- max = tsubst_template_arg (omax, args, complain, in_decl);
+ max = tsubst_expr (omax, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ max = fold_non_dependent_expr (max);
max = fold_decl_constant_value (max);
if (TREE_CODE (max) != INTEGER_CST
@@ -10618,21 +10618,56 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
tree parm_max;
tree arg_max;
-
- parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
- arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+ bool parm_cst;
+ bool arg_cst;
/* Our representation of array types uses "N - 1" as the
TYPE_MAX_VALUE for an array with "N" elements, if "N" is
- not an integer constant. */
- if (TREE_CODE (parm_max) == MINUS_EXPR)
+ not an integer constant. We cannot unify arbitrarily
+ complex expressions, so we eliminate the MINUS_EXPRs
+ here. */
+ parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
+ parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
+ if (!parm_cst)
{
- arg_max = fold_build2 (PLUS_EXPR,
- integer_type_node,
- arg_max,
- TREE_OPERAND (parm_max, 1));
+ gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
parm_max = TREE_OPERAND (parm_max, 0);
}
+ arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
+ arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
+ if (!arg_cst)
+ {
+ /* The ARG_MAX may not be a simple MINUS_EXPR, if we are
+ trying to unify the type of a variable with the type
+ of a template parameter. For example:
+
+ template <unsigned int N>
+ void f (char (&) [N]);
+ int g();
+ void h(int i) {
+ char a[g(i)];
+ f(a);
+ }
+
+ Here, the type of the ARG will be "int [g(i)]", and
+ may be a SAVE_EXPR, etc. */
+ if (TREE_CODE (arg_max) != MINUS_EXPR)
+ return 1;
+ arg_max = TREE_OPERAND (arg_max, 0);
+ }
+
+ /* If only one of the bounds used a MINUS_EXPR, compensate
+ by adding one to the other bound. */
+ if (parm_cst && !arg_cst)
+ parm_max = fold_build2 (PLUS_EXPR,
+ integer_type_node,
+ parm_max,
+ integer_one_node);
+ else if (arg_cst && !parm_cst)
+ arg_max = fold_build2 (PLUS_EXPR,
+ integer_type_node,
+ arg_max,
+ integer_one_node);
if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
return 1;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c15dda4..6e7bd99 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2006-09-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/28903
+ * g++.dg/ext/vla3.C: New test.
+
+ PR c++/28886
+ * g++.dg/template/array16.C: New test.
+
2006-09-06 Richard Guenther <rguenther@suse.de>
* gcc.dg/pr27226.c: Remove testcase again.
diff --git a/gcc/testsuite/g++.dg/ext/vla3.C b/gcc/testsuite/g++.dg/ext/vla3.C
new file mode 100644
index 0000000..329cc7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vla3.C
@@ -0,0 +1,24 @@
+// PR c++/28903
+// { dg-options "" }
+
+template <class>
+struct View
+{
+ int n;
+};
+template <class ViewA>
+struct ViewDom : View<ViewA>
+{
+ using View<ViewA>::n;
+ ViewDom();
+};
+template <class ViewA>
+ViewDom<ViewA>::ViewDom()
+{
+ char a[n];
+}
+void element( )
+{
+ ViewDom<int> a;
+}
+
diff --git a/gcc/testsuite/g++.dg/template/array16.C b/gcc/testsuite/g++.dg/template/array16.C
new file mode 100644
index 0000000..c514410
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/array16.C
@@ -0,0 +1,9 @@
+// PR c++/28886
+
+template<typename> struct A;
+
+template<typename T, int N> struct A<T[N]> {};
+
+template<typename T, int N> struct A<const T[N]> {};
+
+A<const int[1]> a;