From 6ee3ffe85ea599b1d977615ee31b8421563312c0 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Thu, 7 Sep 2006 01:04:07 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 10 +++++ gcc/cp/pt.c | 59 ++++++++++++++++++++----- gcc/testsuite/ChangeLog | 8 ++++ gcc/testsuite/g++.dg/ext/vla3.C | 24 ++++++++++ gcc/testsuite/g++.dg/template/array16.C | 9 ++++ 5 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/vla3.C create mode 100644 gcc/testsuite/g++.dg/template/array16.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cd1af6f8a91..60d2fb29868 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2006-09-06 Mark Mitchell + + 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 PR c++/26696 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d278b00448e..715b9461aba 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 + 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 c15dda40f9c..6e7bd99eee7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2006-09-06 Mark Mitchell + + 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 * 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 00000000000..329cc7dde00 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vla3.C @@ -0,0 +1,24 @@ +// PR c++/28903 +// { dg-options "" } + +template +struct View +{ + int n; +}; +template +struct ViewDom : View +{ + using View::n; + ViewDom(); +}; +template +ViewDom::ViewDom() +{ + char a[n]; +} +void element( ) +{ + ViewDom a; +} + diff --git a/gcc/testsuite/g++.dg/template/array16.C b/gcc/testsuite/g++.dg/template/array16.C new file mode 100644 index 00000000000..c51441041b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/array16.C @@ -0,0 +1,9 @@ +// PR c++/28886 + +template struct A; + +template struct A {}; + +template struct A {}; + +A a; -- 2.30.2