This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 28903, 28886


This patch fixes two problems with arrays and templates introduced by
one of my recent patches.

For 28903, we were using tsubst_template_arg to fold things that were not
template arguments; as is so often the case with such things, we were
punished.  In this case, our punishment was that we got a spurious
error about a VLA in a template function; template arguments can't
have VLA types, but local varibales may.  By using
fold_non_dependent_expr instead, we avoid this problem.

In 28886, we were getting confused when trying to unify array bounds.
We can take advantage of the fact that the bounds are either (a)
constants, (b) X - 1, for some expression X, or (c) computable only at
runtime.  If both bounds have form (a), life is easy.  If both bounds
have form (b), then we can just ignore the -1.  Nothing unifies with
(c).  If one is (a) and the other is (b), we can just add one to the
constant, and drop the -1.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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.

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 116682)
+++ gcc/cp/pt.c	(working copy)
@@ -7212,9 +7212,9 @@ tsubst (tree t, tree args, tsubst_flags_
       {
 	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 
@@ -10614,21 +10614,56 @@ unify (tree tparms, tree targs, tree par
 	{
 	  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: gcc/testsuite/g++.dg/ext/vla3.C
===================================================================
--- gcc/testsuite/g++.dg/ext/vla3.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/vla3.C	(revision 0)
@@ -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;
+}
+
Index: gcc/testsuite/g++.dg/template/array16.C
===================================================================
--- gcc/testsuite/g++.dg/template/array16.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/array16.C	(revision 0)
@@ -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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]