re PR c++/28903 (Rejects VLA in template class's member with using)
authorMark Mitchell <mark@codesourcery.com>
Thu, 7 Sep 2006 01:04:07 +0000 (01:04 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 7 Sep 2006 01:04:07 +0000 (01:04 +0000)
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
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/vla3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/array16.C [new file with mode: 0644]

index cd1af6f8a9153b05ad0d11e3b005261ca2e794ec..60d2fb29868acf3b54a8cf4bc5b8292f27b91093 100644 (file)
@@ -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
index d278b00448ee07d8d97bcefeaef89bf947f10945..715b9461aba4bf8d4e79e032522cfe833639938d 100644 (file)
@@ -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;
index c15dda40f9c2914dd385f576fe7325bf45b57106..6e7bd99eee7740b554cce97862c6b49c322674d2 100644 (file)
@@ -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 (file)
index 0000000..329cc7d
--- /dev/null
@@ -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 (file)
index 0000000..c514410
--- /dev/null
@@ -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;