From 21bd02a96f8322e5a61ad27630d09e46b6f0936d Mon Sep 17 00:00:00 2001
From: lmillward <lmillward@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Sat, 26 Aug 2006 17:41:18 +0000
Subject: [PATCH]         PR c++/28736         PR c++/28737         PR
 c++/28738         * pt.c (process_template_parm): Store invalid template     
    parameters as a TREE_LIST with a TREE_VALUE of error_mark_node.        
 (push_inline_template_parms_recursive): Check for template         parameters
 having a TREE_VALUE of error_mark_node rather than         check the
 parameter itself.         (mangle_class_name_for_template): Likewise.        
 (comp_template_parms): When comparing the individual template        
 parameters, return 1 if either is error_mark_node.        
 (current_template_args): Robustify.         (redeclare_class_template):
 Likewise.

        * g++.dg/template/void10.C: New test.
        * g++.dg/template/void8.C: New test.
        * g++.dg/template/void9.C: New test.

        * g++.dg/template/void3.C: Adjust error markers.
        * g++.dg/template/void4.C: Likewise.
        * g++.dg/template/crash55.C: Likewise.
        * g++.dg/template/void7.C: Likewise.



git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116473 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog                        | 16 +++++++
 gcc/cp/pt.c                             | 63 +++++++++++++++----------
 gcc/testsuite/ChangeLog                 | 16 +++++++
 gcc/testsuite/g++.dg/template/crash55.C |  2 +-
 gcc/testsuite/g++.dg/template/void10.C  | 10 ++++
 gcc/testsuite/g++.dg/template/void3.C   |  2 +-
 gcc/testsuite/g++.dg/template/void4.C   |  2 +-
 gcc/testsuite/g++.dg/template/void7.C   |  2 +-
 gcc/testsuite/g++.dg/template/void8.C   |  7 +++
 gcc/testsuite/g++.dg/template/void9.C   |  4 ++
 10 files changed, 94 insertions(+), 30 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/void10.C
 create mode 100644 gcc/testsuite/g++.dg/template/void8.C
 create mode 100644 gcc/testsuite/g++.dg/template/void9.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d7c952dd8804..e219547c545c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+2006-08-26  Lee Millward  <lee.millward@codesourcery.com>
+
+        PR c++/28736
+        PR c++/28737
+        PR c++/28738
+        * pt.c (process_template_parm): Store invalid template
+        parameters as a TREE_LIST with a TREE_VALUE of error_mark_node.
+        (push_inline_template_parms_recursive): Check for template
+        parameters having a TREE_VALUE of error_mark_node rather than
+        check the parameter itself.
+        (mangle_class_name_for_template): Likewise.
+        (comp_template_parms): When comparing the individual template
+        parameters, return 1 if either is error_mark_node.
+        (current_template_args): Robustify.
+        (redeclare_class_template): Likewise.
+	
 2006-08-26  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/28588
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e078149fa770..5e0c9541b9a7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -336,12 +336,11 @@ push_inline_template_parms_recursive (tree parmlist, int levels)
 	       NULL);
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
     {
-      tree parm;
+      tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
 
-      if (TREE_VEC_ELT (parms, i) == error_mark_node)
-        continue;
+      if (parm == error_mark_node)
+	continue;
 
-      parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
       gcc_assert (DECL_P (parm));
 
       switch (TREE_CODE (parm))
@@ -2212,15 +2211,13 @@ comp_template_parms (tree parms1, tree parms2)
 
       for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
 	{
-          tree parm1;
-          tree parm2;
+          tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
+          tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
 
-          if (TREE_VEC_ELT (t1, i) == error_mark_node
-              || TREE_VEC_ELT (t2, i) == error_mark_node)
-            continue;
-
-	  parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
-          parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
+          /* If either of the template parameters are invalid, assume
+             they match for the sake of error recovery. */
+          if (parm1 == error_mark_node || parm2 == error_mark_node)
+            return 1;
 
 	  if (TREE_CODE (parm1) != TREE_CODE (parm2))
 	    return 0;
@@ -2352,6 +2349,7 @@ process_template_parm (tree list, tree parm, bool is_non_type)
 {
   tree decl = 0;
   tree defval;
+  tree err_parm_list;
   int idx = 0;
 
   gcc_assert (TREE_CODE (parm) == TREE_LIST);
@@ -2361,7 +2359,7 @@ process_template_parm (tree list, tree parm, bool is_non_type)
     {
       tree p = tree_last (list);
 
-      if (p && p != error_mark_node)
+      if (p && TREE_VALUE (p) != error_mark_node)
         {
           p = TREE_VALUE (p);
           if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
@@ -2382,7 +2380,11 @@ process_template_parm (tree list, tree parm, bool is_non_type)
       SET_DECL_TEMPLATE_PARM_P (parm);
 
       if (TREE_TYPE (parm) == error_mark_node)
-	return chainon(list, error_mark_node);
+        {
+          err_parm_list = build_tree_list (defval, parm);
+          TREE_VALUE (err_parm_list) = error_mark_node;
+	   return chainon (list, err_parm_list);
+        }
       else
       {
 	/* [temp.param]
@@ -2391,7 +2393,11 @@ process_template_parm (tree list, tree parm, bool is_non_type)
 	   ignored when determining its type.  */
 	TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
 	if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
-	  return chainon(list, error_mark_node);
+          {
+            err_parm_list = build_tree_list (defval, parm);
+            TREE_VALUE (err_parm_list) = error_mark_node;
+	     return chainon (list, err_parm_list);
+          }
       }
 
       /* A template parameter is not modifiable.  */
@@ -2522,11 +2528,15 @@ current_template_args (void)
 	    {
 	      t = TREE_VALUE (t);
 
-	      if (TREE_CODE (t) == TYPE_DECL
-		  || TREE_CODE (t) == TEMPLATE_DECL)
-		t = TREE_TYPE (t);
-	      else
-		t = DECL_INITIAL (t);
+	      if (t != error_mark_node)
+		{
+		  if (TREE_CODE (t) == TYPE_DECL
+		      || TREE_CODE (t) == TEMPLATE_DECL)
+		    t = TREE_TYPE (t);
+		  else
+		    t = DECL_INITIAL (t);
+		}
+
 	      TREE_VEC_ELT (a, i) = t;
 	    }
 	}
@@ -3350,9 +3360,10 @@ redeclare_class_template (tree type, tree parms)
 
       /* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or
 	 TEMPLATE_DECL.  */
-      if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
-	  || (TREE_CODE (tmpl_parm) != TYPE_DECL
-	      && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm))))
+      if (tmpl_parm != error_mark_node
+	   && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+	   || (TREE_CODE (tmpl_parm) != TYPE_DECL
+	       && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))))
 	{
 	  error ("template parameter %q+#D", tmpl_parm);
 	  error ("redeclared here as %q#D", parm);
@@ -4207,12 +4218,12 @@ mangle_class_name_for_template (const char* name, tree parms, tree arglist)
       tree parm;
       tree arg;
 
-      if (TREE_VEC_ELT (parms, i) == error_mark_node)
-        continue;
-
       parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
       arg = TREE_VEC_ELT (arglist, i);
 
+      if (parm == error_mark_node)
+	continue;
+
       if (i)
 	ccat (',');
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 017de891864a..1df799676b4b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2006-08-26  Lee Millward  <lee.millward@codesourcery.com>
+
+        PR c++/28736
+        * g++.dg/template/void10.C: New test.
+
+        PR c++/28737
+        * g++.dg/template/void8.C: New test.
+
+        PR c+_+/28738
+        * g++.dg/template/void9.C: New test.
+
+        * g++.dg/template/void3.C: Adjust error markers.
+        * g++.dg/template/void4.C: Likewise.
+        * g++.dg/template/crash55.C: Likewise.
+        * g++.dg/template/void7.C: Likewise
+	
 2006-08-26  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/28588
diff --git a/gcc/testsuite/g++.dg/template/crash55.C b/gcc/testsuite/g++.dg/template/crash55.C
index 7e15b66ee75b..0e3fe4c3a593 100644
--- a/gcc/testsuite/g++.dg/template/crash55.C
+++ b/gcc/testsuite/g++.dg/template/crash55.C
@@ -3,4 +3,4 @@
 template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|valid type" }
 struct A {};                        // { dg-error "definition"
 
-template<int> void foo(A<int>);     // { dg-error "mismatch|constant" }
+template<int> void foo(A<int>);     // { dg-error "mismatch|constant|template argument" }
diff --git a/gcc/testsuite/g++.dg/template/void10.C b/gcc/testsuite/g++.dg/template/void10.C
new file mode 100644
index 000000000000..56e0b6d2e5b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/void10.C
@@ -0,0 +1,10 @@
+//PR c++/28736
+
+template<void> struct A                 // { dg-error "not a valid type" }
+{
+    template<typename> friend struct B;
+};
+
+template<typename> struct B {};
+
+B<int> b;                              // { dg-error "template argument|invalid type" }
diff --git a/gcc/testsuite/g++.dg/template/void3.C b/gcc/testsuite/g++.dg/template/void3.C
index 6526a2a47be1..bb59934ffe4f 100644
--- a/gcc/testsuite/g++.dg/template/void3.C
+++ b/gcc/testsuite/g++.dg/template/void3.C
@@ -1,5 +1,5 @@
 //PR c++/28637
 
 template<void> struct A {};  // { dg-error "not a valid type" }
-A<0> a;
+A<0> a;                      // { dg-error "type" }
 
diff --git a/gcc/testsuite/g++.dg/template/void4.C b/gcc/testsuite/g++.dg/template/void4.C
index 7d264fbf10bc..fe30b2e3736b 100644
--- a/gcc/testsuite/g++.dg/template/void4.C
+++ b/gcc/testsuite/g++.dg/template/void4.C
@@ -4,4 +4,4 @@ template<void> struct A;  // { dg-error "not a valid type" }
 
 template<template<int> class> struct B {};
 
-B<A> b;
+B<A> b;                  // { dg-error "template|invalid type" }
diff --git a/gcc/testsuite/g++.dg/template/void7.C b/gcc/testsuite/g++.dg/template/void7.C
index 2c464b3a055c..95d87a207322 100644
--- a/gcc/testsuite/g++.dg/template/void7.C
+++ b/gcc/testsuite/g++.dg/template/void7.C
@@ -5,4 +5,4 @@ template<void> struct A         // { dg-error "not a valid type" }
   static int i;
 };
 
-A<0> a;
+A<0> a;                        // { dg-error "invalid type|not a valid type" }
diff --git a/gcc/testsuite/g++.dg/template/void8.C b/gcc/testsuite/g++.dg/template/void8.C
new file mode 100644
index 000000000000..e45c91c044c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/void8.C
@@ -0,0 +1,7 @@
+//PR c++/28737
+
+template<void> struct A;                // { dg-error "not a valid type" }
+
+template<typename> struct B;
+
+template<void N> struct B<A<N> > {};   // { dg-error "not a valid type|declared|invalid" }
diff --git a/gcc/testsuite/g++.dg/template/void9.C b/gcc/testsuite/g++.dg/template/void9.C
new file mode 100644
index 000000000000..bb2ed66ff381
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/void9.C
@@ -0,0 +1,4 @@
+//PR c++/28738
+
+template<int,void> struct A {};    // { dg-error "not a valid type" }
+template<int N> struct A<N,0> {};  // { dg-error "not a valid type" }
-- 
GitLab