diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cd1af6f8a9153b05ad0d11e3b005261ca2e794ec..60d2fb29868acf3b54a8cf4bc5b8292f27b91093 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 d278b00448ee07d8d97bcefeaef89bf947f10945..715b9461aba4bf8d4e79e032522cfe833639938d 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 c15dda40f9c2914dd385f576fe7325bf45b57106..6e7bd99eee7740b554cce97862c6b49c322674d2 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 0000000000000000000000000000000000000000..329cc7dde00c745a0aecdd0d8eb926076315dfb8 --- /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 0000000000000000000000000000000000000000..c51441041b45e81c4b23cf9d4f86b7ad0f2d7603 --- /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;