]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/31439 (ICE with variadic template and broken specialization)
authorDouglas Gregor <doug.gregor@gmail.com>
Tue, 6 Nov 2007 14:37:56 +0000 (14:37 +0000)
committerDoug Gregor <dgregor@gcc.gnu.org>
Tue, 6 Nov 2007 14:37:56 +0000 (14:37 +0000)
2007-11-06  Douglas Gregor  <doug.gregor@gmail.com>

PR c++/31439
PR c++/32114
PR c++/32115
PR c++/32125
PR c++/32126
PR c++/32127
PR c++/32128
PR c++/32253
PR c++/32566
* typeck.c (check_return_expr): Pass address of retval to
check_for_bare_parameter_packs.
* class.c (build_base_field): Tolerate bases that have no layout
due to errors.
(end_of_base): Ditto.
* tree.c (canonical_type_variant): Be careful with
ERROR_MARK_NODE.
* cp-tree.h (check_for_bare_parameter_packs): Now accepts a
tree*.
* pt.c (find_parameter_pack_data): Add set_packs_to_error field,
which states whether parameter packs should be replaced with
ERROR_MARK_NODE.
(find_parameter_packs_r): Pass addresses to cp_walk_tree wherever
possible. If set_packs_to_error is set true, replace the parameter
pack with ERROR_MARK_NODE. Manage our own pointer sets.
(uses_parameter_packs): Don't set parameter packs to
ERROR_MARK_NODE.
(check_for_bare_parameter_packs): Now takes a pointer to a tree,
which may be modified (if it is a parameter pack). Instructs
find_parameter_packs_r to replace parameter packs with
ERROR_MARK_NODE (so that they won't cause errors later on).
(process_template_parm): Pass pointer to
check_for_bare_parameter_packs.
(process_partial_specialization): Replace pack expansions before
the end of the template argument list with ERROR_MARK_NODE.
(push_template_decl_real): Pass pointer to
check_for_bare_parameter_packs. Replace parameter packs not at the
end of the template parameter list with ERROR_MARK_NODE.
(convert_template_argument): Be more careful about using DECL_NAME
on only declarations.
(unify): Can't unify against ERROR_MARK_NODE.
* semantics.c (finish_cond): Pass pointer to
check_for_bare_parameter_packs.
(finish_expr_stmt): Ditto.
(finish_for_expr): Ditto.
(finish_switch_cond): Pass pointer to
check_for_bare_parameter_packs, and call it before we put the
condition into the statement.
(finish_mem_initializers): Pass pointer to
check_for_bare_parameter_packs.
(finish_member_declaration): Ditto.
* parser.c (cp_parser_base_clause): Ditto.

2007-11-06  Douglas Gregor  <doug.gregor@gmail.com>

* testsuite/g++.dg/parser/crash36.C: Tweak expected errors.
* testsuite/g++.dg/cpp0x/pr31439.C: New.
* testsuite/g++.dg/cpp0x/pr32114.C: New.
* testsuite/g++.dg/cpp0x/pr32115.C: New.
* testsuite/g++.dg/cpp0x/pr32125.C: New.
* testsuite/g++.dg/cpp0x/pr32126.C: New.
* testsuite/g++.dg/cpp0x/pr32127.C: New.
* testsuite/g++.dg/cpp0x/pr32128.C: New.
* testsuite/g++.dg/cpp0x/pr32253.C: New.
* testsuite/g++.dg/cpp0x/pr32566.C: New.
* testsuite/g++.dg/cpp0x/pr31445.C: Tweak expected errors.
* testsuite/g++.dg/cpp0x/pr31438.C: Ditto.
* testsuite/g++.dg/cpp0x/variadic81.C: Ditto.
* testsuite/g++.dg/cpp0x/pr31432.C: Ditto.
* testsuite/g++.dg/cpp0x/pr31442.C: Ditto.

From-SVN: r129928

24 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr31432.C
gcc/testsuite/g++.dg/cpp0x/pr31438.C
gcc/testsuite/g++.dg/cpp0x/pr31439.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr31442.C
gcc/testsuite/g++.dg/cpp0x/pr31445.C
gcc/testsuite/g++.dg/cpp0x/pr32114.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32115.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32125.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32126.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32127.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32128.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32253.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32566.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic81.C
gcc/testsuite/g++.dg/parse/crash36.C

index 2f0d55274b62143fcd46e4c2e1895ddf5ffcf938..9fff78d0fbf59ba98cce48bde670be83f5a7cb94 100644 (file)
@@ -1,3 +1,57 @@
+2007-11-06  Douglas Gregor  <doug.gregor@gmail.com>
+
+       PR c++/31439
+       PR c++/32114
+       PR c++/32115
+       PR c++/32125
+       PR c++/32126
+       PR c++/32127
+       PR c++/32128
+       PR c++/32253
+       PR c++/32566
+       * typeck.c (check_return_expr): Pass address of retval to
+       check_for_bare_parameter_packs.
+       * class.c (build_base_field): Tolerate bases that have no layout
+       due to errors.
+       (end_of_base): Ditto.
+       * tree.c (canonical_type_variant): Be careful with
+       ERROR_MARK_NODE.
+       * cp-tree.h (check_for_bare_parameter_packs): Now accepts a
+       tree*.
+       * pt.c (find_parameter_pack_data): Add set_packs_to_error field,
+       which states whether parameter packs should be replaced with
+       ERROR_MARK_NODE.
+       (find_parameter_packs_r): Pass addresses to cp_walk_tree wherever
+       possible. If set_packs_to_error is set true, replace the parameter
+       pack with ERROR_MARK_NODE. Manage our own pointer sets.
+       (uses_parameter_packs): Don't set parameter packs to
+       ERROR_MARK_NODE.
+       (check_for_bare_parameter_packs): Now takes a pointer to a tree,
+       which may be modified (if it is a parameter pack). Instructs
+       find_parameter_packs_r to replace parameter packs with
+       ERROR_MARK_NODE (so that they won't cause errors later on).
+       (process_template_parm): Pass pointer to
+       check_for_bare_parameter_packs.
+       (process_partial_specialization): Replace pack expansions before
+       the end of the template argument list with ERROR_MARK_NODE.
+       (push_template_decl_real): Pass pointer to
+       check_for_bare_parameter_packs. Replace parameter packs not at the
+       end of the template parameter list with ERROR_MARK_NODE.
+       (convert_template_argument): Be more careful about using DECL_NAME
+       on only declarations.
+       (unify): Can't unify against ERROR_MARK_NODE.
+       * semantics.c (finish_cond): Pass pointer to
+       check_for_bare_parameter_packs.
+       (finish_expr_stmt): Ditto.
+       (finish_for_expr): Ditto.
+       (finish_switch_cond): Pass pointer to
+       check_for_bare_parameter_packs, and call it before we put the
+       condition into the statement.
+       (finish_mem_initializers): Pass pointer to
+       check_for_bare_parameter_packs.
+       (finish_member_declaration): Ditto.
+       * parser.c (cp_parser_base_clause): Ditto.
+       
 2007-11-06  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/33168
index 4453b346a69a7467ebfaa11ec13a85014d5c2832..e468db30442c90c663a5b7d904318bea1ad10a9e 100644 (file)
@@ -3613,21 +3613,24 @@ build_base_field (record_layout_info rli, tree binfo,
       DECL_ARTIFICIAL (decl) = 1;
       DECL_IGNORED_P (decl) = 1;
       DECL_FIELD_CONTEXT (decl) = t;
-      DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
-      DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
-      DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
-      DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
-      DECL_MODE (decl) = TYPE_MODE (basetype);
-      DECL_FIELD_IS_BASE (decl) = 1;
-
-      /* Try to place the field.  It may take more than one try if we
-        have a hard time placing the field without putting two
-        objects of the same type at the same address.  */
-      layout_nonempty_base_or_field (rli, decl, binfo, offsets);
-      /* Add the new FIELD_DECL to the list of fields for T.  */
-      TREE_CHAIN (decl) = *next_field;
-      *next_field = decl;
-      next_field = &TREE_CHAIN (decl);
+      if (CLASSTYPE_AS_BASE (basetype))
+       {
+         DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+         DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
+         DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+         DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
+         DECL_MODE (decl) = TYPE_MODE (basetype);
+         DECL_FIELD_IS_BASE (decl) = 1;
+
+         /* Try to place the field.  It may take more than one try if we
+            have a hard time placing the field without putting two
+            objects of the same type at the same address.  */
+         layout_nonempty_base_or_field (rli, decl, binfo, offsets);
+         /* Add the new FIELD_DECL to the list of fields for T.  */
+         TREE_CHAIN (decl) = *next_field;
+         *next_field = decl;
+         next_field = &TREE_CHAIN (decl);
+       }
     }
   else
     {
@@ -4423,7 +4426,9 @@ end_of_base (tree binfo)
 {
   tree size;
 
-  if (is_empty_class (BINFO_TYPE (binfo)))
+  if (!CLASSTYPE_AS_BASE (BINFO_TYPE (binfo)))
+    size = TYPE_SIZE_UNIT (char_type_node);
+  else if (is_empty_class (BINFO_TYPE (binfo)))
     /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
        allocate some space for it. It cannot have virtual bases, so
        TYPE_SIZE_UNIT is fine.  */
index 5f43c13d3d8ddfbfbe97dda330062414563c5e62..f954da5d850985f4fd9b3bfe0ad5794982d55da1 100644 (file)
@@ -4435,7 +4435,7 @@ extern int comp_template_parms                    (const_tree, const_tree);
 extern bool uses_parameter_packs                (tree);
 extern bool template_parameter_pack_p           (const_tree);
 extern tree make_pack_expansion                 (tree);
-extern bool check_for_bare_parameter_packs      (tree);
+extern bool check_for_bare_parameter_packs      (tree*);
 extern tree get_template_info                  (tree);
 extern int template_class_depth                        (tree);
 extern int is_specialization_of                        (tree, tree);
index 4729d1ed5dd1cbc904a676a20edb1c6a13a77dd0..23994b0808ad1bf22baf7a0ba6421d1cee5ddc2e 100644 (file)
@@ -15248,7 +15248,7 @@ cp_parser_base_clause (cp_parser* parser)
             /* Make this a pack expansion type. */
             TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
           else
-            check_for_bare_parameter_packs (TREE_VALUE (base));
+            check_for_bare_parameter_packs (&TREE_VALUE (base));
 
          TREE_CHAIN (base) = bases;
          bases = base;
index 53edd31cd337c2f29875035406411a9ee71533e8..0ac7314c72b38f89e751e0eb4a1b4441bf3d7bb9 100644 (file)
@@ -2419,11 +2419,19 @@ make_ith_pack_parameter_name (tree name, int i)
   return get_identifier (newname);
 }
 
-/* Structure used to track the progress of find_parameter_pack_r.  */
+/* Structure used to track the progress of find_parameter_packs_r.  */
 struct find_parameter_pack_data 
 {
+  /* TREE_LIST that will contain all of the parameter packs found by
+     the traversal.  */
   tree* parameter_packs;
+
+  /* Set of AST nodes that have been visited by the traversal.  */
   struct pointer_set_t *visited;
+
+  /* Whether we should replace parameter packs with
+     ERROR_MARK_NODE. Used by check_for_bare_parameter_packs.  */
+  bool set_packs_to_error;
 };
 
 /* Identifies all of the argument packs that occur in a template
@@ -2436,49 +2444,89 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
   tree t = *tp;
   struct find_parameter_pack_data* ppd = 
     (struct find_parameter_pack_data*)data;
+  bool parameter_pack_p = false;
 
-  if (TYPE_P (t))
+  /* Don't visit nodes twice, except when we're clearing out parameter
+     packs.  */
+  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))
+    {
+    case TEMPLATE_PARM_INDEX:
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+        parameter_pack_p = true;
+      break;
+
+    case TEMPLATE_TYPE_PARM:
+    case TEMPLATE_TEMPLATE_PARM:
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+        parameter_pack_p = true;
+      break;
+
+    case PARM_DECL:
+      if (FUNCTION_PARAMETER_PACK_P (t))
+        {
+          /* We don't want to walk into the type of a PARM_DECL,
+             because we don't want to see the type parameter pack.  */
+          *walk_subtrees = 0;
+         parameter_pack_p = true;
+        }
+      break;
+
+    default:
+      /* Not a parameter pack.  */
+      break;
+    }
+
+  if (parameter_pack_p)
     {
-      tree context = TYPE_CONTEXT (t);
-      cp_walk_tree (&context, &find_parameter_packs_r, ppd, ppd->visited);
+      /* Add this parameter pack to the list.  */
+      *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
+
+      if (ppd->set_packs_to_error)
+       /* The caller requested that we set the parameter packs to
+          ERROR_MARK_NODE so that they will not trip up the compiler
+          later.  The caller is responsible for emitting an error.  */
+       *tp = error_mark_node;
+      else
+       /* Make sure we do not visit this node again.  */
+       pointer_set_insert (ppd->visited, *tp);
     }
+  else
+    /* 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);
 
   /* This switch statement will return immediately if we don't find a
      parameter pack.  */
   switch (TREE_CODE (t)) 
     {
     case TEMPLATE_PARM_INDEX:
-      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-        break;
       return NULL_TREE;
 
     case BOUND_TEMPLATE_TEMPLATE_PARM:
+      /* Check the template itself.  */
+      cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)), 
+                   &find_parameter_packs_r, ppd, NULL);
       /* Check the template arguments.  */
       cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd, 
-                   ppd->visited);
-
-      /* Dig out the underlying TEMPLATE_TEMPLATE_PARM.  */
-      t = TYPE_TI_TEMPLATE (t);
-      if (DECL_P (t) && TREE_TYPE (t))
-        t = TREE_TYPE (t);
+                   NULL);
       *walk_subtrees = 0;
-      
-      /* Fall through.  */
+      return NULL_TREE;
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-        break;
       return NULL_TREE;
 
     case PARM_DECL:
-      if (FUNCTION_PARAMETER_PACK_P (t))
-        {
-          /* We don't want to walk into the type of a PARM_DECL,
-             because we don't want to see the type parameter pack.*/
-          *walk_subtrees = 0;
-          break;
-        }
       return NULL_TREE;
 
     case RECORD_TYPE:
@@ -2489,25 +2537,20 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
     case UNION_TYPE:
     case ENUMERAL_TYPE:
       if (TYPE_TEMPLATE_INFO (t))
-        {
-          tree args = TREE_VALUE (TYPE_TEMPLATE_INFO (t));
-          cp_walk_tree (&args, &find_parameter_packs_r, ppd, ppd->visited);
-        }
+       cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)), 
+                     &find_parameter_packs_r, ppd, NULL);
 
       *walk_subtrees = 0;
       return NULL_TREE;
 
     case TEMPLATE_DECL:
-      if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
-         && TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
-       break;
-      
-      *walk_subtrees = 0;
+      cp_walk_tree (&TREE_TYPE (t),
+                   &find_parameter_packs_r, ppd, NULL);
       return NULL_TREE;
  
     case TYPENAME_TYPE:
       cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
-                   ppd, ppd->visited);
+                   ppd, NULL);
       *walk_subtrees = 0;
       return NULL_TREE;
 
@@ -2519,16 +2562,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, ppd->visited);
+                   ppd, NULL);
       *walk_subtrees = 0;
       return NULL_TREE;
 
     default:
       return NULL_TREE;
     }
-  
-  /* Add this parameter pack to the list.  */
-  *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
 
   return NULL_TREE;
 }
@@ -2541,7 +2581,8 @@ 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, ppd.visited);
+  ppd.set_packs_to_error = false;
+  cp_walk_tree (&t, &find_parameter_packs_r, &ppd, NULL);
   pointer_set_destroy (ppd.visited);
   return parameter_packs != NULL_TREE;
 }
@@ -2559,6 +2600,8 @@ make_pack_expansion (tree arg)
   bool for_types = false;
   struct find_parameter_pack_data ppd;
 
+  ppd.set_packs_to_error = false;
+
   if (!arg || arg == error_mark_node)
     return arg;
 
@@ -2592,7 +2635,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, ppd.visited);
+                    &ppd, NULL);
 
       if (parameter_packs == NULL_TREE)
         {
@@ -2610,7 +2653,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, ppd.visited);
+                            &ppd, NULL);
             }
         }
 
@@ -2648,7 +2691,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, ppd.visited);
+  cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, NULL);
   pointer_set_destroy (ppd.visited);
 
   /* Make sure we found some parameter packs.  */
@@ -2680,20 +2723,21 @@ make_pack_expansion (tree arg)
    Returns TRUE if there were no bare parameter packs, returns FALSE
    (and emits an error) if there were bare parameter packs.*/
 bool 
-check_for_bare_parameter_packs (tree t)
+check_for_bare_parameter_packs (tree* t)
 {
   tree parameter_packs = NULL_TREE;
   struct find_parameter_pack_data ppd;
 
-  if (!processing_template_decl || !t || t == error_mark_node)
+  if (!processing_template_decl || !t || !*t || *t == error_mark_node)
     return true;
 
-  if (TREE_CODE (t) == TYPE_DECL)
-    t = TREE_TYPE (t);
+  if (TREE_CODE (*t) == TYPE_DECL)
+    t = &TREE_TYPE (*t);
 
   ppd.parameter_packs = &parameter_packs;
   ppd.visited = pointer_set_create ();
-  cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
+  ppd.set_packs_to_error = false;
+  cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL);
   pointer_set_destroy (ppd.visited);
 
   if (parameter_packs) 
@@ -2711,11 +2755,23 @@ check_for_bare_parameter_packs (tree t)
             name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
           else
             name = DECL_NAME (pack);
-          inform ("        %qD", name);
+
+         if (name)
+           inform ("        %qD", name);
+         else
+           inform ("        <anonymous>");
 
           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 ();
+      ppd.set_packs_to_error = true;
+      cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL);
+      pointer_set_destroy (ppd.visited);
+
       return false;
     }
 
@@ -2978,7 +3034,7 @@ process_template_parm (tree list, tree parm, bool is_non_type,
          {
            /* This template parameter is not a parameter pack, but it
               should be. Complain about "bare" parameter packs.  */
-           check_for_bare_parameter_packs (TREE_TYPE (parm));
+           check_for_bare_parameter_packs (&TREE_TYPE (parm));
            
            /* Recover by calling this a parameter pack.  */
            is_parameter_pack = true;
@@ -3382,7 +3438,10 @@ process_partial_specialization (tree decl)
                   if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
                     error ("parameter pack argument %qE must be at the end of the template argument list", arg);
                   else
-                    error ("parameter pack argument %qT must be at the end of the template argument list", arg);                   
+                    error ("parameter pack argument %qT must be at the end of the template argument list", arg);
+
+                 if (packed_args)
+                   TREE_VEC_ELT (packed_args, j) = error_mark_node;
                 }
             }
 
@@ -3789,7 +3848,7 @@ push_template_decl_real (tree decl, bool is_friend)
       while (arg && argtype)
         {
           if (!FUNCTION_PARAMETER_PACK_P (arg)
-              && !check_for_bare_parameter_packs (TREE_TYPE (arg)))
+              && !check_for_bare_parameter_packs (&TREE_TYPE (arg)))
             {
             /* This is a PARM_DECL that contains unexpanded parameter
                packs. We have already complained about this in the
@@ -3805,11 +3864,11 @@ push_template_decl_real (tree decl, bool is_friend)
 
       /* Check for bare parameter packs in the return type and the
          exception specifiers.  */
-      check_for_bare_parameter_packs (TREE_TYPE (type));
-      check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type));
+      check_for_bare_parameter_packs (&TREE_TYPE (type));
+      check_for_bare_parameter_packs (&TYPE_RAISES_EXCEPTIONS (type));
     }
   else
-    check_for_bare_parameter_packs (TREE_TYPE (decl));
+    check_for_bare_parameter_packs (&TREE_TYPE (decl));
 
   if (is_partial)
     return process_partial_specialization (decl);
@@ -3833,6 +3892,8 @@ push_template_decl_real (tree decl, bool is_friend)
              else
                error ("parameter pack %qT must be at the end of the"
                       " template parameter list", TREE_TYPE (parm));
+
+             TREE_VALUE (TREE_VEC_ELT (inner_parms, i)) = error_mark_node;
            }
         }
     }
@@ -4755,7 +4816,7 @@ convert_template_argument (tree parm,
              if (is_type)
                error ("  expected a constant of type %qT, got %qT",
                       TREE_TYPE (parm),
-                      (is_tmpl_type ? DECL_NAME (arg) : orig_arg));
+                      (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
              else if (requires_tmpl_type)
                error ("  expected a class template, got %qE", orig_arg);
              else
@@ -13101,6 +13162,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          nodes.  */
       return 0;
 
+    case ERROR_MARK:
+      /* Unification fails if we hit an error node.  */
+      return 1;
+
     default:
       gcc_assert (EXPR_P (parm));
 
index 3f45f712e0e7d8f36fef7889bb137b92cbe2a46c..50118a25f126fad573419be2b2153572253f9080 100644 (file)
@@ -508,7 +508,7 @@ finish_cond (tree *cond_p, tree expr)
       if (TREE_CODE (cond) == DECL_EXPR)
        expr = cond;
 
-      check_for_bare_parameter_packs (expr);
+      check_for_bare_parameter_packs (&expr);
     }
   *cond_p = expr;
 }
@@ -618,7 +618,7 @@ finish_expr_stmt (tree expr)
       else if (!type_dependent_expression_p (expr))
        convert_to_void (build_non_dependent_expr (expr), "statement");
 
-      check_for_bare_parameter_packs (expr);
+      check_for_bare_parameter_packs (&expr);
 
       /* Simplification of inner statement expressions, compound exprs,
         etc can result in us already having an EXPR_STMT.  */
@@ -875,7 +875,7 @@ finish_for_expr (tree expr, tree for_stmt)
   else if (!type_dependent_expression_p (expr))
     convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
   expr = maybe_cleanup_point_expr_void (expr);
-  check_for_bare_parameter_packs (expr);
+  check_for_bare_parameter_packs (&expr);
   FOR_EXPR (for_stmt) = expr;
 }
 
@@ -971,12 +971,12 @@ finish_switch_cond (tree cond, tree switch_stmt)
            cond = index;
        }
     }
+  check_for_bare_parameter_packs (&cond);
   finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
   SWITCH_STMT_TYPE (switch_stmt) = orig_type;
   add_stmt (switch_stmt);
   push_switch (switch_stmt);
   SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
-  check_for_bare_parameter_packs (cond);
 }
 
 /* Finish the body of a switch-statement, which may be given by
@@ -1389,7 +1389,7 @@ finish_mem_initializers (tree mem_inits)
              bound as part of the TREE_PURPOSE.  See
              make_pack_expansion for more information.  */
           if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
-            check_for_bare_parameter_packs (TREE_VALUE (mem));
+            check_for_bare_parameter_packs (&TREE_VALUE (mem));
         }
 
       add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
@@ -2306,9 +2306,8 @@ finish_member_declaration (tree decl)
   DECL_CONTEXT (decl) = current_class_type;
 
   /* Check for bare parameter packs in the member variable declaration.  */
-  if (TREE_CODE (decl) == FIELD_DECL
-      && !check_for_bare_parameter_packs (TREE_TYPE (decl)))
-    TREE_TYPE (decl) = error_mark_node;
+  if (TREE_CODE (decl) == FIELD_DECL)
+    check_for_bare_parameter_packs (&TREE_TYPE (decl));
 
   /* [dcl.link]
 
index 64efda50d65d9a75e3550aaca9e2ef61627bd0f9..fba7c2281f0dc2755e0ffeb8f375cf6899269f42 100644 (file)
@@ -846,6 +846,9 @@ cp_build_qualified_type_real (tree type,
 tree
 canonical_type_variant (tree t)
 {
+  if (t == error_mark_node)
+    return error_mark_node;
+
   return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
 }
 \f
index 862787a10c88327f7479f1831430f1e64e2bc2e0..d167de20c0617c95e7f991074c8bcac055d99d38 100644 (file)
@@ -6613,7 +6613,7 @@ check_return_expr (tree retval, bool *no_warning)
   if (processing_template_decl)
     {
       current_function_returns_value = 1;
-      check_for_bare_parameter_packs (retval);
+      check_for_bare_parameter_packs (&retval);
       return retval;
     }
 
index 1d9a9c6fe9a62ae46120373b66d67fbad5c0303a..6689530ba54681fde2b1498899572aac68ba59d7 100644 (file)
@@ -1,3 +1,21 @@
+2007-11-06  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * testsuite/g++.dg/parser/crash36.C: Tweak expected errors.
+       * testsuite/g++.dg/cpp0x/pr31439.C: New.
+       * testsuite/g++.dg/cpp0x/pr32114.C: New.
+       * testsuite/g++.dg/cpp0x/pr32115.C: New.
+       * testsuite/g++.dg/cpp0x/pr32125.C: New.
+       * testsuite/g++.dg/cpp0x/pr32126.C: New.
+       * testsuite/g++.dg/cpp0x/pr32127.C: New.
+       * testsuite/g++.dg/cpp0x/pr32128.C: New.
+       * testsuite/g++.dg/cpp0x/pr32253.C: New.
+       * testsuite/g++.dg/cpp0x/pr32566.C: New.
+       * testsuite/g++.dg/cpp0x/pr31445.C: Tweak expected errors.
+       * testsuite/g++.dg/cpp0x/pr31438.C: Ditto.
+       * testsuite/g++.dg/cpp0x/variadic81.C: Ditto.
+       * testsuite/g++.dg/cpp0x/pr31432.C: Ditto.
+       * testsuite/g++.dg/cpp0x/pr31442.C: Ditto.
+
 2007-11-06  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/33168
index cb8826e5957208cb799979ec04b3f392054471c6..8016ee69d75b402a8e6e7c6860443645f85009b7 100644 (file)
@@ -4,5 +4,5 @@ template<typename..., typename> struct A // { dg-error "parameter pack" }
  static int i;
 };
 
-A<int, int> a; // { dg-error "invalid type" }
-A<char,int> b; // { dg-error "invalid type" }
+A<int, int> a; // { dg-error "mismatch|expected|invalid type" }
+A<char,int> b; // { dg-error "mismatch|expected|invalid type" }
index 3a125634ffb08112bb2ceb9999a6f57197be6c94..0e27971494b73e49e0b207c74095599d4a388eea 100644 (file)
@@ -1,9 +1,9 @@
 // { dg-options "-std=gnu++0x" }
 
-template<typename> struct A; // { dg-error "candidates" }
-template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U" }
-{ // { dg-error "parameter packs|U" }
- template<typename X> A(X); // { dg-error "parameter packs|U" }
+template<typename> struct A;
+template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U|not used|U" }
+{
+ template<typename X> A(X);
 };
 
-A<void(int)> a(0); // { dg-error "no matching" }
+A<void(int)> a(0); // { dg-error "incomplete type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31439.C b/gcc/testsuite/g++.dg/cpp0x/pr31439.C
new file mode 100644 (file)
index 0000000..420dc08
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+template<typename...> struct A;
+
+template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous" }
+
+template<typename T, typename... U> struct A<T, U...> : A<U...> {};
+
+A<int> a;
index 050e2999566aae59eaebfc3b132b4bd941b7c181..f4e411c4505922d94f56409bc280f68dac9b3b57 100644 (file)
@@ -1,9 +1,9 @@
 // { dg-options "-std=gnu++0x" }
-template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end" }
+template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end|parameter packs|anonymous" }
 
 struct B
 {
   template <template <typename...> class C> B(C<int>);
 };
 
-B b = A<int>();
+B b = A<int>(); // { dg-error "mismatch|expected" }
index 025cb9606c3bb808ab304ba443f5727f945ddd6a..b3f2b5b09dafbaaf4d328d14a736fd76118c7d0a 100644 (file)
@@ -1,8 +1,8 @@
 // { dg-options "-std=gnu++0x" }
 template <typename... T> struct A
 {
-  void foo(T...); // { dg-error "candidates" }
-  A(T... t) { foo(t); } // { dg-error "parameter packs|t|no matching" }
+  void foo(T...);
+  A(T... t) { foo(t); } // { dg-error "parameter packs|t" }
 };
 
 A<int> a(0);
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32114.C b/gcc/testsuite/g++.dg/cpp0x/pr32114.C
new file mode 100644 (file)
index 0000000..e78dfdf
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options "-std=c++0x" }
+template<typename ...T> struct A
+{
+  typedef typename T::X Y; // { dg-error "not expanded|T" }
+};
+
+A<int> a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32115.C b/gcc/testsuite/g++.dg/cpp0x/pr32115.C
new file mode 100644 (file)
index 0000000..a721eed
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-options "-std=c++0x" }
+template<typename ...T, int = 0> struct A {}; // { dg-error "end of" }
+
+A<int> a; // { dg-error "mismatch|expected|invalid" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32125.C b/gcc/testsuite/g++.dg/cpp0x/pr32125.C
new file mode 100644 (file)
index 0000000..154cd85
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+template<typename...> struct A;
+
+template<typename...T> struct A<T*> // { dg-error "not expanded|T|not used|T" }
+{
+  A();
+  A(T); // { dg-error "not expanded|T" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32126.C b/gcc/testsuite/g++.dg/cpp0x/pr32126.C
new file mode 100644 (file)
index 0000000..e7c61bd
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<typename...> struct A;
+
+template<typename...T> struct A<T> // { dg-error "not expanded|T|not used|T" }
+{
+ static int i;
+};
+
+A<char> a; // { dg-error "incomplete" }
+A<int> b; // { dg-error "incomplete" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32127.C b/gcc/testsuite/g++.dg/cpp0x/pr32127.C
new file mode 100644 (file)
index 0000000..8e4bc00
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options "-std=c++0x" }
+template<typename...T> struct A
+{
+  static T i; // { dg-error "parameter packs|T" }
+};
+
+int j = A<int>::i; // { dg-error "not a member" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32128.C b/gcc/testsuite/g++.dg/cpp0x/pr32128.C
new file mode 100644 (file)
index 0000000..5876dbe
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options "-std=c++0x" }
+template<typename...> struct A;
+
+template<typename...T, typename...U> 
+  struct A<T..., U...> {}; // { dg-error "must be at the end" }
+
+A<int> a; // { dg-error "incomplete" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32253.C b/gcc/testsuite/g++.dg/cpp0x/pr32253.C
new file mode 100644 (file)
index 0000000..d8f7b03
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+template<void (*... fp)()> struct A
+{
+  A() { fp(); } // { dg-error "not expanded|fp" }
+};
+
+void foo();
+
+A<foo> a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32566.C b/gcc/testsuite/g++.dg/cpp0x/pr32566.C
new file mode 100644 (file)
index 0000000..f6e7a5b
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-options "-std=c++0x" }
+template<int...> struct A;
+
+template<template<int> class... T> struct A<T...> {}; // { dg-error "mismatch|expected" }
index d710128df49a3bad2e1707169215dfe0cea722b7..322f249de9ade526a643e8d51120ac7dfd538d50 100644 (file)
@@ -3,9 +3,9 @@
 
 template<typename> struct A;
 
-template<typename... T> struct A<T*>  // { dg-error "not expanded|note" }
-{                                     // { dg-error "not expanded|note" }
+template<typename... T> struct A<T*>  // { dg-error "not expanded|T|not used|T" }
+{                                     
   struct B;
 };
 
-A<void*> a;
+A<void*> a; // { dg-error "incomplete" }
index 1e5ab8f25625e34da2824c34bd2fb113849e1d6d..e73e928350d4f6177eabe3437391886f9304b9ca 100644 (file)
@@ -5,7 +5,7 @@
 template <typename... T> struct A      // { dg-error "does not include variadic templates" }
 {
   static T &t;                         // { dg-error "not expanded with|T" }
-  static const int i = sizeof (++t);   // { dg-error "invalid use of template type parameter" }
+  static const int i = sizeof (++t);
 };
 
 int x[A <int>::i];     // { dg-error "is not an integral constant-expression" }