From 92fab505d29cc38f12ad0369648ef7d0a54a3aef Mon Sep 17 00:00:00 2001
From: Douglas Gregor <doug.gregor@gmail.com>
Date: Fri, 15 Feb 2008 17:33:02 +0000
Subject: [PATCH] re PR c++/35023 (ICE with parameter pack in variable
 declaration)

2008-02-15  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/35023
	PR c++/35024
	PR c++/35026
	* pt.c (finish_member_template_decl): If the type in a TYPE_DECL
	is error_mark_node, return an error early.
	(find_parameter_packs_r): Pass the pointer set along to recursive
	calls of cp_walk_subtrees; don't try to manage the pointer set
	ourselves.
	(uses_parameter_packs): Pass the pointer set to cp_walk_tree.
	(make_pack_expansion): Ditto.
	(check_for_bare_parameter_packs): Ditto. Also, don't bother taking
	a second pass through the tree with find_parameter_packs_r; that
	second pass no longer does anything.
	(push_template_decl_real): If we have an erroneous declaration,
	set its type to error_mark_node before returning an error.

2008-02-15  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/35023
	PR c++/35024
	PR c++/35026
	* g++.dg/cpp0x/vt-35026.C: New.
	* g++.dg/cpp0x/vt-35023.C: New.
	* g++.dg/cpp0x/vt-34055.C: Tweak expected error messages.
	* g++.dg/cpp0x/vt-35024.C: New.

From-SVN: r132348
---
 gcc/cp/ChangeLog                      | 18 ++++++++++
 gcc/cp/pt.c                           | 51 +++++++++++----------------
 gcc/testsuite/ChangeLog               | 10 ++++++
 gcc/testsuite/g++.dg/cpp0x/vt-34055.C |  6 ++--
 gcc/testsuite/g++.dg/cpp0x/vt-35023.C | 11 ++++++
 gcc/testsuite/g++.dg/cpp0x/vt-35024.C | 11 ++++++
 gcc/testsuite/g++.dg/cpp0x/vt-35026.C |  7 ++++
 7 files changed, 80 insertions(+), 34 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-35023.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-35024.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-35026.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 385398346b06..6789236c031f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,21 @@
+2008-02-15  Douglas Gregor  <doug.gregor@gmail.com>
+
+	PR c++/35023
+	PR c++/35024
+	PR c++/35026
+	* pt.c (finish_member_template_decl): If the type in a TYPE_DECL
+	is error_mark_node, return an error early.
+	(find_parameter_packs_r): Pass the pointer set along to recursive
+	calls of cp_walk_subtrees; don't try to manage the pointer set
+	ourselves.
+	(uses_parameter_packs): Pass the pointer set to cp_walk_tree.
+	(make_pack_expansion): Ditto.
+	(check_for_bare_parameter_packs): Ditto. Also, don't bother taking
+	a second pass through the tree with find_parameter_packs_r; that
+	second pass no longer does anything.
+	(push_template_decl_real): If we have an erroneous declaration,
+	set its type to error_mark_node before returning an error.
+
 2008-02-14  Douglas Gregor  <doug.gregor@gmail.com>
 
 	PR c++/34050
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d11a959fba8c..5931126e860b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -236,6 +236,8 @@ finish_member_template_decl (tree decl)
       tree type;
 
       type = TREE_TYPE (decl);
+      if (type == error_mark_node)
+	return error_mark_node;
       if (IS_AGGR_TYPE (type)
 	  && CLASSTYPE_TEMPLATE_INFO (type)
 	  && !CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
@@ -2445,13 +2447,6 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
     (struct find_parameter_pack_data*)data;
   bool parameter_pack_p = false;
 
-  /* Don't visit nodes twice.  */
-  if (pointer_set_contains (ppd->visited, *tp))
-    {
-      *walk_subtrees = 0;
-      return NULL_TREE;
-    }
-
   /* Identify whether this is a parameter pack or not.  */
   switch (TREE_CODE (t))
     {
@@ -2487,12 +2482,9 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
       *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
     }
 
-  /* Make sure we do not visit this node again.  */
-  pointer_set_insert (ppd->visited, *tp);
-
   if (TYPE_P (t))
     cp_walk_tree (&TYPE_CONTEXT (t), 
-		  &find_parameter_packs_r, ppd, NULL);
+		  &find_parameter_packs_r, ppd, ppd->visited);
 
   /* This switch statement will return immediately if we don't find a
      parameter pack.  */
@@ -2504,10 +2496,10 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
     case BOUND_TEMPLATE_TEMPLATE_PARM:
       /* Check the template itself.  */
       cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)), 
-		    &find_parameter_packs_r, ppd, NULL);
+		    &find_parameter_packs_r, ppd, ppd->visited);
       /* Check the template arguments.  */
       cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd, 
-		    NULL);
+		    ppd->visited);
       *walk_subtrees = 0;
       return NULL_TREE;
 
@@ -2527,19 +2519,19 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
     case ENUMERAL_TYPE:
       if (TYPE_TEMPLATE_INFO (t))
 	cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)), 
-		      &find_parameter_packs_r, ppd, NULL);
+		      &find_parameter_packs_r, ppd, ppd->visited);
 
       *walk_subtrees = 0;
       return NULL_TREE;
 
     case TEMPLATE_DECL:
       cp_walk_tree (&TREE_TYPE (t),
-		    &find_parameter_packs_r, ppd, NULL);
+		    &find_parameter_packs_r, ppd, ppd->visited);
       return NULL_TREE;
  
     case TYPENAME_TYPE:
       cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
-                   ppd, NULL);
+                   ppd, ppd->visited);
       *walk_subtrees = 0;
       return NULL_TREE;
       
@@ -2550,12 +2542,13 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
 
     case INTEGER_TYPE:
       cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r, 
-		    ppd, NULL);
+		    ppd, ppd->visited);
       *walk_subtrees = 0;
       return NULL_TREE;
 
     case IDENTIFIER_NODE:
-      cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd, NULL);
+      cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd, 
+		    ppd->visited);
       *walk_subtrees = 0;
       return NULL_TREE;
 
@@ -2574,7 +2567,7 @@ uses_parameter_packs (tree t)
   struct find_parameter_pack_data ppd;
   ppd.parameter_packs = &parameter_packs;
   ppd.visited = pointer_set_create ();
-  cp_walk_tree (&t, &find_parameter_packs_r, &ppd, NULL);
+  cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
   pointer_set_destroy (ppd.visited);
   return parameter_packs != NULL_TREE;
 }
@@ -2625,7 +2618,7 @@ make_pack_expansion (tree arg)
       ppd.visited = pointer_set_create ();
       ppd.parameter_packs = &parameter_packs;
       cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r, 
-                    &ppd, NULL);
+                    &ppd, ppd.visited);
 
       if (parameter_packs == NULL_TREE)
         {
@@ -2643,7 +2636,7 @@ make_pack_expansion (tree arg)
               /* Determine which parameter packs will be expanded in this
                  argument.  */
               cp_walk_tree (&TREE_VALUE (value), &find_parameter_packs_r, 
-                            &ppd, NULL);
+                            &ppd, ppd.visited);
             }
         }
 
@@ -2681,7 +2674,7 @@ make_pack_expansion (tree arg)
   /* Determine which parameter packs will be expanded.  */
   ppd.parameter_packs = &parameter_packs;
   ppd.visited = pointer_set_create ();
-  cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, NULL);
+  cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
   pointer_set_destroy (ppd.visited);
 
   /* Make sure we found some parameter packs.  */
@@ -2726,7 +2719,7 @@ check_for_bare_parameter_packs (tree t)
 
   ppd.parameter_packs = &parameter_packs;
   ppd.visited = pointer_set_create ();
-  cp_walk_tree (&t, &find_parameter_packs_r, &ppd, NULL);
+  cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
   pointer_set_destroy (ppd.visited);
 
   if (parameter_packs) 
@@ -2753,13 +2746,6 @@ check_for_bare_parameter_packs (tree t)
           parameter_packs = TREE_CHAIN (parameter_packs);
         }
 
-      /* Clean up any references to these parameter packs within the
-	 tree.  */
-      ppd.parameter_packs = &parameter_packs;
-      ppd.visited = pointer_set_create ();
-      cp_walk_tree (&t, &find_parameter_packs_r, &ppd, NULL);
-      pointer_set_destroy (ppd.visited);
-
       return true;
     }
 
@@ -3887,7 +3873,10 @@ push_template_decl_real (tree decl, bool is_friend)
 	TYPE_RAISES_EXCEPTIONS (type) = NULL_TREE;
     }
   else if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
-    return error_mark_node;
+    {
+      TREE_TYPE (decl) = error_mark_node;
+      return error_mark_node;
+    }
 
   if (is_partial)
     return process_partial_specialization (decl);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0b888ea8d714..6665d266314a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2008-02-15  Douglas Gregor  <doug.gregor@gmail.com>
+
+	PR c++/35023
+	PR c++/35024
+	PR c++/35026
+	* g++.dg/cpp0x/vt-35026.C: New.
+	* g++.dg/cpp0x/vt-35023.C: New.
+	* g++.dg/cpp0x/vt-34055.C: Tweak expected error messages.
+	* g++.dg/cpp0x/vt-35024.C: New.
+
 2008-02-15  Uros Bizjak  <ubizjak@gmail.com>
 
 	* gcc.c-torture/execute/va-arg-25.x: Remove.
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34055.C b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C
index 8ad9c2d52661..29066b50bd72 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34055.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C
@@ -7,7 +7,7 @@ template<typename...T> struct A<T*> // { dg-error "parameter packs|T" }
   void foo();  // { dg-error "parameter packs|T|candidate" }
 };
 
-template<typename...T> void A<T*>::foo() {} // { dg-error "does not match" }
+template<typename...T> void A<T*>::foo() {} // { dg-error "invalid declarator" }
 
 
 
@@ -18,7 +18,7 @@ template<typename...T> struct B<T&> // { dg-error "parameter packs|T" }
   void foo(); // { dg-error "parameter packs|T" }
 };
 
-template<typename...T> void B<T&>::foo() {} // { dg-error "does not match" }
+template<typename...T> void B<T&>::foo() {} // { dg-error "invalid declarator" }
 
 
 template<typename...> struct C;
@@ -28,4 +28,4 @@ template<typename...T> struct C<T()> // { dg-error "parameter packs|T" }
   void foo(); // { dg-error "parameter packs|T" }
 };
 
-template<typename...T> void C<T()>::foo() {} // { dg-error "does not match" }
+template<typename...T> void C<T()>::foo() {} // { dg-error "invalid declarator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35023.C b/gcc/testsuite/g++.dg/cpp0x/vt-35023.C
new file mode 100644
index 000000000000..9db20503e7ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35023.C
@@ -0,0 +1,11 @@
+// { dg-options "-std=c++0x" }
+template<typename... T> int foo()
+{
+  T t; // { dg-error "parameter packs|T" }
+  return t;
+}
+
+void bar()
+{
+  foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35024.C b/gcc/testsuite/g++.dg/cpp0x/vt-35024.C
new file mode 100644
index 000000000000..77f0b66bdc02
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35024.C
@@ -0,0 +1,11 @@
+// { dg-options "-std=c++0x" }
+template<typename... T> int foo()
+{
+  typename T::X x; // { dg-error "parameter packs|T" }
+  return x;
+}
+
+void bar()
+{
+  foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35026.C b/gcc/testsuite/g++.dg/cpp0x/vt-35026.C
new file mode 100644
index 000000000000..643a416c5787
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35026.C
@@ -0,0 +1,7 @@
+// { dg-options "-std=c++0x" }
+template<typename... T> struct A
+{
+  T* x[1]; // { dg-error "parameter packs|T" }
+};
+
+A<int> a;
-- 
GitLab